Tránh sự cố trong lập trình ứng dụng nhúng

Mặc dù việc viết phần mềm cho máy tính nhúng thoạt đầu nghe có vẻ đơn giản, đặc biệt là với các lập trình viên dày dạn kinh nghiệm, tuy nhiên có những trở ngại mà họ cần phải biết cách tránh: (1) Sử dụng quá nhiều bộ nhớ flash của máy tính nhúng, (2) Rò rỉ bộ nhớ do bộ nhớ động không sử dụng đến không được tháo ra

pdf11 trang | Chia sẻ: tranhoai21 | Lượt xem: 1181 | Lượt tải: 0download
Bạn đang xem nội dung tài liệu Tránh sự cố trong lập trình ứng dụng nhúng, để tải tài liệu về máy bạn click vào nút DOWNLOAD ở trên
Tránh sự cố trong lập trình ứng dụng nhúng Mặc dù việc viết phần mềm cho máy tính nhúng thoạt đầu nghe có vẻ đơn giản, đặc biệt là với các lập trình viên dày dạn kinh nghiệm, tuy nhiên có những trở ngại mà họ cần phải biết cách tránh: (1) Sử dụng quá nhiều bộ nhớ flash của máy tính nhúng, (2) Rò rỉ bộ nhớ do bộ nhớ động không sử dụng đến không được tháo ra (3) Tạo ra các ứng dụng không lường được các lỗi có thể xảy ra. Do các hệ thống nhúng thường phải hoạt động mà không có giám sát đồng thời trong một thời gian dài, máy tính nhúng thường được đặt ở xa nơi đi lại, một trong những mục đích chính của người lập trình hệ thống nhúng là bảo vệ độ ổn định của hệ thống. Embedded PC và PC-khác biệt ở bộ nhớ Vấn đề lớn nhất với việc viết code cho máy tính nhúng là hiểu sai vai trò của máy tính nhúng. Điều này đặc biệt đúng đối với người phát triển phần mềm lại là những người lập trình PC có kinh nghiệm. Trong khi đó, PC hiện đại cực nhanh và ứng dụng của PC có thể tận dụng được lượng bộ nhớ trên một PC điển hình, các hệ thống nhúng lại cung cấp nguồn bộ nhớ có hạn. Trên thực tế, người lập trình hệ thống nhúng thường gặp rắc rối khi ứng dụng của họ trở nên thiếu ổn định, không nhận ra rằng vấn đề có liên quan đến bộ nhớ. Sau đây là một ví dụ đơn giản. Khi viết phần mềm cho các ứng dụng PC, sẽ là bình thường khi viết 100 MB dữ liệu lên đĩa cứng 1 GB. So sánh điều này với việc viết 10 MB dữ liệu lên ổ flash 15 MB cho một ứng dụng nhúng. Mặc dù chỉ sử dụng 2/3 dung lượng có sẵn, vẫn cần thận trọng để tránh những sự cố xảy ra, viết dữ liệu nhiều lần cùng một lúc sẽ dẫn đến “khóa chết” trong ổ flash. Nguyên nhân là do các thiết bị bộ nhớ flash có vòng đời hoạt động ghi dữ liệu hạn chế, và do nhiều vùng của bộ nhớ flash sẽ thường không hỏng cùng lúc, thiết bị bộ nhớ flash sẽ vẫn hoạt động cho tới khi số lượng bộ nhớ còn dùng được bị xuống cấp dưới mức cần thiết để chạy ứng dụng. Khi điều đó xảy ra, ứng dụng của bạn sẽ trở nên thiếu ổn định và sau đó là hỏng. Cách tốt nhất để sử dụng ổ nhớ flash của một máy tính nhúng là lưu các file chương trình trên đĩa và lưu dữ liệu được tạo ra bởi chương trình trên CF card hay SD card mở rộng. Card mở rộng đem đến dung lượng lưu trữ lớn hơn và cùng lúc đó tránh được vấn đề vòng đời ổ cứng. Nếu vì một số lý do bạn phải sử dụng bộ nhớ flash để lưu trữ dữ liệu, chúng tôi muốn khuyên bạn rằng bạn nên sử dụng một nửa dung lượng flash. Rò rỉ bộ nhớ Một sự cố khác cần tránh là rò rỉ bộ nhớ. Máy tính nhúng thực sự nhạy với việc sử dụng bộ nhớ và việc rò rỉ bộ nhớ làm giảm công suất hệ thống do việc phân trang bộ nhớ tăng cao khi các chương trình khác nhau tìm cách chiếm bộ nhớ sẵn có. Vấn đề rò rỉ bộ nhớ cũng có thể xuất hiện khi bộ xử lí file không được sử dụng hay bộ mô tả không được đóng lại. Trong các ứng dụng truyền thông, mỗi kết nối TCP hay serial phải liên quan tới một bộ mô tả file chiếm một lượng bộ nhớ. Khi bộ mô tả file không được đóng đúng cách và kết nối được thiết lập đi thiết lập lại nhiều lần, việc tiêu tốn bộ nhớ thậm chí sẽ dẫn đến rò rỉ bộ nhớ. Để tránh rò rỉ bộ nhớ, người phát triển phần mềm phải chú ý chương trình của họ xử lí và sử dụng bộ nhớ như thế nào. Ngoài ra, các ứng dụng phải được xây dựng thật tốt. Việc lập trình đòi hỏi một thiết kế từ trên xuống và thực hiện từ dưới lên. Ứng dụng được phân ra thành các module phân lớp được tách biệt càng nhiều càng tốt, mỗi module lại được phân ra thêm thành nhiều chức năng. Trong giai đoạn thực hiện, bạn nên xây dựng các chức năng của mình trước khi kết hợp chúng để tạo ra một module hoàn chỉnh. Lý tưởng hơn là, các chức năng trong một module chiếm dung lượng ít nhất khi sinh ra, từ đầu vào/đầu ra, và khi module chết. Đoạn code sau đây phân tích một thí dụ như thế. typedef struct _YYYCONN { int fd; char *packet_data; int packet_size; } YYYCONN; /* the death of a module */ void yyy_close(YYYCONN *con) { if (con) { if (con->fd > 0) close(con->fd); /* close the file descriptor */ if (con->packet_data) free(con->packet_data); /* free the data buffer */ free(con); /* be sure to structure body */ } } /* the birth of a module */ YYYCONN* yyy_open(char *host, int port) { int fd; YYYCONN *con; con = (YYYCONN *) malloc(sizeof(YYYCONN)); /* memory allocation */ if (con==NULL) return NULL: con->fd = make_tcp_client(host, port); /* API call to connect to a TCP server */ If (con->fd < 0) { yyy_close(con) ; return NULL; } con->packet_data = (char*) malloc(1024); /* memory allocation */ if (con->packet_data==NULL) { yyy_close(con) ; return NULL; } con->packet_size=0; return con; } Chức năng yyy_open tạo ra module kết nối TCP cùng với một bộ mô tả file mở. Bản thân module và dữ liệu thành viên của nó được phân vùng trong bộ nhớ. Khi hủy module, chúng ta gọi chức năng function yyy_close, module được thiết kế để đóng bộ mô tả file và sau đó giải phóng bộ nhớ được phân bổ. Để quản lí nhiều module kết nối chúng ta cần thực hiện trên khu vực toàn cầu, đây có thể là một chuỗi hay là một danh sách được liên kết để theo dõi các module này. Một số chức năng quản lí sau đây cũng có thể được cần đến: y yyy_connection_add: thêm một kết nối vào danh sách toàn cầu. y yyy_connection_remove: xóa kết nối từ danh sách toàn cầu. y yyy_connection_lookup: tìm kiếm một kết nối cụ thể. Xử lí ngoại lệ Chủ đề cuối cùng của bài này là tính bền vững, điều mà đôi khi chúng ta nên cố gắng đạt được cho các ứng dụng của mình. Mọi ngoại lệ có thể xảy ra phải được xử lí một cách cẩn thận. Phân đoạn mã sau đây là một ví dụ: while(1) { if (select(fd+1, read_fds, NULL, NULL, NULL) > 0) { ; } } Thí dụ này giả định rằng kết nối sau bộ mô tả file, fd luôn luôn duy trì hoạt động. Tuy nhiên, kết nối có thể bị ngắt một cách cố tình bởi bên đồng đẳng, trong trường này chức năng “lựa chọn” sẽ ngay tức thì quay trở về -1. Chương trình sau đó sẽ tiêu thụ điện CPU và sẽ không quay lại trạng thái bình thường. Kết luận Người lập trình không biết cách tránh 3 sự cố như trên sẽ gặp vấn đề về tính ổn định, ngăn các ứng dụng hoạt động lâu dài. Những vấn đề này có thể khó giải quyết, đặc biệt khi một dự án đang chịu sức ép để sẵn sàng đưa ra thị trường sớm nhất có thể.” Vì lí do này, hầu hết những người phát triển đều sử dụng một bộ định thời giám sát để chạy đồng thời với các ứng dụng của mình. Nếu dung lượng bộ nhớ sẵn có xuống quá thấp, hay chương trình rơi vào tình trạng không như mong đợi, bộ định thời giám sát sẽ không được làm mới và phần còn lại của hệ thống sẽ được khởi động.
Tài liệu liên quan