Embedded Linux System Development¶
Vu Tang - 10/2026 (bản gốc 2/2019)
Cập nhật 10/2026
Bài được viết lại vào 10/2026. Bản gốc năm 2019 được giữ nguyên ở cuối trang tại mục Bản gốc 2019, một số nhận định trong đó đã không còn đầy đủ.
Embedded System Engineer làm gì?¶
Nhiệm vụ chính của một "Embedded System Engineer" gồm năm mảng:
- Bring-up hệ thống: đưa toàn bộ các chip trên một bo mạch khởi động và phối hợp được với nhau, trong đó có Linux trên chip chính
- Tích hợp hoặc phát triển các User-space application cho một hệ nhúng
- Phát triển Linux Device Driver cho các ngoại vi
- Linux Real-time & High-performance Optimization: tối ưu hệ thống Linux để đạt hiệu năng cao và đáp ứng yêu cầu real-time
- Bảo mật hệ thống và quản lý lỗ hổng: thiết kế hệ thống an toàn từ đầu và xử lý lỗ hổng bảo mật trong suốt vòng đời sản phẩm
Bring-up hệ thống¶
Trong bài viết năm 2019 (xem lại mục Porting Linux trong bản gốc), tôi định nghĩa porting Linux là quá trình làm cho một bo mạch mới khởi động với hệ điều hành Linux. Định nghĩa đó ngầm giả định trên bo mạch chỉ có một chip chạy Linux là trung tâm. Thực tế, các hệ nhúng ngày nay phức tạp hơn nhiều: một bo mạch có thể dùng nhiều chipset khác nhau, với tới hàng chục chip có bộ xử lý và firmware riêng.
Vì vậy, quá trình khởi động không còn là chuyện của một chip, mà là sự phối hợp của nhiều chip trên cùng một bo mạch. Gọi nhiệm vụ này là bring-up hệ thống sẽ chính xác hơn: ngoài việc đưa Linux lên chip chính, kỹ sư cần đảm bảo toàn bộ các chip trên bo mạch khởi động đúng và phối hợp được với nhau. Một số khía cạnh cần quan tâm:
- Power và reset sequencing: thứ tự cấp nguồn và nhả reset cho từng chip.
- Thứ tự và phụ thuộc khi khởi động: chip nào khởi động trước, chip nào nạp firmware hoặc cấu hình cho chip nào (ví dụ nạp bitstream cho FPGA, khởi động các lõi phụ).
- Clock và đồng bộ: các chip cần lock clock hoặc đồng bộ với nhau trước khi hệ thống hoạt động.
- Xử lý lỗi khi khởi động: khi một chip khởi động lỗi, hệ thống cần retry, reset riêng chip đó hay reset toàn bộ bo mạch.
- Debug: lỗi thường nằm ở ranh giới giữa các chip, mỗi chip lại có log và công cụ debug riêng.
Embedded application development¶
Nhiệm vụ tích hợp và phát triển ứng dụng cho hệ nhúng về cơ bản không có nhiều thay đổi so với góc nhìn năm 2019 (xem lại mục Embedded application development trong bản gốc). Điều cần nhấn mạnh thêm là độ ổn định và bền vững của hệ thống ứng dụng: một hệ nhúng thường phải chạy liên tục nhiều năm, ở nơi khó tiếp cận, nên ứng dụng phải được thiết kế để tự duy trì hoạt động, chứ không chỉ chạy đúng chức năng. Một số khía cạnh cần quan tâm:
- Giám sát và tự phục hồi: watchdog, và cơ chế giám sát tiến trình để tự khởi động lại khi ứng dụng lỗi (ví dụ qua systemd).
- Quản lý tài nguyên lâu dài: rò rỉ bộ nhớ, file descriptor và các tài nguyên khác thường chỉ lộ ra sau nhiều ngày hoặc nhiều tuần chạy.
- Cô lập lỗi: tách chức năng thành các tiến trình riêng để lỗi ở một thành phần không kéo sập cả hệ thống.
- Chịu được sự cố môi trường: mất điện đột ngột, lỗi hệ thống file, thiết bị ngoại vi hoặc kết nối mạng chập chờn.
Linux Device Driver¶
Nhiệm vụ phát triển Linux Device Driver cho các ngoại vi về cơ bản không thay đổi so với góc nhìn năm 2019 (xem lại mục Linux Device Driver trong bản gốc). Điểm bổ sung là phạm vi của driver ngày nay rộng hơn:
- Về độ phức tạp: từ các thiết bị đơn giản như I2C, SPI, đến các driver phức tạp hơn như DMA, network device.
- Về khuôn khổ: khái niệm driver không còn nằm trong khuôn khổ Linux kernel, mà mở rộng ra các dạng khác, ví dụ DPDK poll mode driver.
Linux Real-time & High-performance Optimization¶
Hệ nhúng không còn chỉ là hệ thống hiệu năng thấp, tài nguyên hạn chế. Một phần không nhỏ các hệ nhúng ngày nay là hệ multi-core hiệu năng cao, chạy Linux kernel real-time (kernel được bật tùy chọn PREEMPT_RT). Với các hệ thống này, ngoài việc làm cho hệ thống chạy được, kỹ sư còn phải tối ưu để hệ thống đạt hiệu năng cao và đáp ứng yêu cầu real-time.
Để làm được điều đó, kỹ sư cần có bộ kỹ năng phân tích khi hệ thống có sự cố hoặc chưa đạt yêu cầu:
- Phân tích crash dump: thu thập và đọc dump khi kernel panic hoặc ứng dụng bị crash (kdump/vmcore với công cụ
crash, core dump vớigdb), từ đó xác định nguyên nhân gốc thay vì chỉ khởi động lại hệ thống. - Phân tích hiệu năng hệ thống: đo đạc để tìm nút thắt thay vì đoán, bằng các công cụ như perf, ftrace, eBPF. Với hệ real-time, trọng tâm là độ trễ và jitter: đo bằng
cyclictest, và dùng các latency tracer của ftrace để truy ra nguồn gây trễ (ngắt, tắt preempt, tranh chấp tài nguyên...).
Ví dụ, đo độ trễ lập lịch của hệ thống bằng cyclictest:
# -m: khóa bộ nhớ, -S: mỗi core một thread, -p 95: ưu tiên real-time,
# -i 200: chu kỳ 200 µs, -D 10m: chạy 10 phút, -q: chỉ in tổng kết
cyclictest -m -S -p 95 -i 200 -D 10m -q
Kết quả mẫu (số liệu minh họa, đơn vị µs):
T: 0 ( 2301) P:95 I:200 C:3000000 Min: 3 Act: 5 Avg: 5 Max: 31
T: 1 ( 2302) P:95 I:200 C:3000000 Min: 3 Act: 4 Avg: 5 Max: 27
T: 2 ( 2303) P:95 I:200 C:3000000 Min: 3 Act: 5 Avg: 5 Max: 34
T: 3 ( 2304) P:95 I:200 C:3000000 Min: 3 Act: 4 Avg: 5 Max: 29
Chỉ số cần quan tâm nhất là Max: độ trễ xấu nhất, vì hệ real-time bị đánh giá bởi trường hợp xấu nhất chứ không phải giá trị trung bình.
Bảo mật hệ thống và quản lý lỗ hổng¶
Bảo mật là một nhiệm vụ mà bài viết năm 2019 chưa đề cập. Ngày nay, kỹ sư nhúng cần quan tâm đến bảo mật ở cả hai giai đoạn: thiết kế và vận hành.
- Thiết kế hệ thống an toàn từ đầu: secure boot và chain of trust, cập nhật firmware an toàn (OTA), giảm bề mặt tấn công (tắt các dịch vụ và cổng không cần thiết).
- Quản lý lỗ hổng trong suốt vòng đời sản phẩm: theo dõi CVE cho kernel, bootloader và các gói trong rootfs, đánh giá mức độ ảnh hưởng đến sản phẩm, vá lỗi và phát hành bản cập nhật. Xem thêm mục Embedded Security.
Bản gốc 2019¶
Nội dung bài viết gốc 2/2019 (nhấn để mở)
Phần này được giữ nguyên nội dung từ bài viết 2/2019 (chỉ sửa lỗi chính tả) để tham khảo.
Embedded Linux System Development - What I have to do?¶
Khái niệm phát triển một hệ nhúng Linux rất rộng. Nhiệm vụ chính của một "Embedded System Engineer" sẽ là:
- Porting Linux OS cho một custom board
- Tích hợp hoặc phát triển các User-space application cho một hệ nhúng
- Phát triển Linux Device Driver cho các ngoại vi
Porting Linux¶
Porting Linux, ở một khía cạnh khái quát, là quá trình làm cho một bo mạch mới khởi động với hệ điều hành Linux. Để hoàn thành được nhiệm vụ này cần tổ hợp rất nhiều kiến thức khác nhau. Trong đó có một số mục cần lưu ý sau:
- Kiến trúc máy tính (Computer system architecture). Kiến trúc chung của một hệ máy tính, các thành phần cấu thành. Quá trình hoạt động của một CPU.
- Trình biên dịch và quá trình biên dịch một chương trình. Quá trình hoạt động của compiler, các khái niệm liên quan đến make system (Makefile). Ngoài ra trong mục này cũng có thể mở rộng đến các công cụ sử dụng cho porting linux như: Xilinx Petalinux, Yocto Bitbake...
- Linux booting sequence. Các khái niệm liên quan đến bootloader cũng như quá trình khởi động của Linux kernel. Quá trình mounting root file system.
Embedded application development¶
Một cách minh họa, máy tính cá nhân sau khi cài đặt xong hệ điều hành, người dùng tiến hành cài đặt các ứng dụng (ví dụ như Office...) để thực hiện các nhiệm vụ (ví dụ như soạn thảo văn bản...). Một hệ nhúng cũng tương tự vậy. Quá trình porting Linux giúp board khởi động thành công với hệ điều hành, kỹ sư cần phát triển thêm các ứng dụng nhúng tùy theo yêu cầu của từng hệ thống. Tích hợp và phát triển ứng dụng có thể chia làm hai loại:
-
Các ứng dụng mã nguồn mở (open source) được phát triển bởi cộng đồng. Nhiệm vụ của kỹ sư trong trường hợp này là tích hợp được ứng dụng này vào hệ thống của mình. Trong một số trường hợp, kỹ sư có thể kết hợp tích hợp và tùy biến lại mã nguồn để phù hợp với từng hệ thống. Một số khái niệm quan trọng cần lưu ý trong mục này là:
- Cross compiling
- Các hệ thống build như cmake, autoconf, make ...
-
Các ứng dụng đặc biệt chỉ có tại hệ thống. Các hệ nhúng thực hiện các nhiệm vụ đặc thù, do đó kỹ sư trong rất nhiều trường hợp cần phát triển các ứng dụng cho hệ nhúng (các ứng dụng này không được phát triển bởi cộng đồng).
Quy trình phát triển một ứng dụng trên hệ nhúng Linux không quá khác biệt so với phát triển một ứng dụng trên Linux Desktop.
Linux Device Driver¶
Quá trình porting giúp board có thể khởi động với hệ điều hành (Linux) nhưng không đảm bảo được tất cả các tài nguyên phần cứng trên board đã có các driver (*) tương ứng. Nhiệm vụ của kỹ sư trong trường hợp này sẽ là:
-
Porting các driver cho các phần cứng. Một số phần cứng cung cấp bởi các vendor sẽ đi kèm mã nguồn cho driver, nhiệm vụ của kỹ sư là tích hợp driver này vào hệ thống để có thể tương thích được với phần cứng.
-
Phát triển các driver cho các phần cứng chuyên dụng trên board.
(*) Khái niệm driver sẽ được thảo luận thêm ở các tài liệu chuyên sâu khác.
References¶
[1] - Embedded Linux system development - bootlin.com


