Làm thế nào để tránh những 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.

c-free

Ảnh minh họa

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 modun phân lớp được tách biệt càng nhiều càng tốt, mỗi modun 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 modun hoàn chỉnh.

Lý tưởng hơn là, các chức năng trong một modun chiếm dung lượng ít nhất khi sinh ra, từ đầu vào/đầu ra, và khi modun 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 modun kết nối TCP cùng với một bộ mô tả file mở. Bản thân modun và dữ liệu thành viên của nó được phân vùng trong bộ nhớ. Khi hủy modun, chúng ta gọi chức năng function yyy_close, modun đượ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 modun 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 modun 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.

CF Lin, Giám đốc phát triển phần mềm của Moxa - Địa chỉ email này đã được bảo vệ từ spam bots, bạn cần kích hoạt Javascript để xem nó.

Thông tin liên hệ

Trụ sở: Số 19, ngõ 84, P. Ngọc Khánh, P. Giảng Võ, Q. Ba Đình, TP. Hà Nội
Nhà máy sản xuất và VPGD: Số 1 đường Tứ Hiệp, Thôn Cổ Điển B, Xã Tứ Hiệp, H. Thanh Trì, TP. Hà Nội
HOTLINE: 0983369663
Tel: 024.37711488
Fax: 024.37711499

Mục tiêu - Định hướng

- Trở thành một công ty hàng đầu về cung cấp, thiết bị điện, và xây dựng các công trình cơ điện trên khắp mọi miền đất nước.
- Mang lại những giải pháp kỹ thuật hoàn hảo, là đối tác tin cậy với các bạn hàng.

Thông tin khác

CÔNG TY TNHH THƯƠNG MẠI & XÂY DỰNG NĂNG LƯỢNG
ECT CO., LTD
Tài khoản:0731100151008
Ngân hàng: TMCP Quân Đội - PGD Nguyễn Biểu - Hà Nội
Mã số thuế:0104227284
Hotline: 0983.369.663 - 0904.172.181