1. Nội dung thiết kế tốt nghiệp:
3.2 Các đặc điểm của hệ điều hành uClinux
3.2.1 Ƣu điểm và nhƣợc điểm của hệ điều hành uClinux
Với đặc điểm mã nguồn mở, các nhà phát triển có thể tải và chỉnh sửa theo ý muốn. Tuy đã được phát triển từ lâu nhưng bên cạnh những ưu điểm, uClinux vẫn còn tồn tại một số nhược điểm.
Ưu điểm:
uClinux tích hợp sẵn nhiều IP của hệ điều hành Linux chuẩn, các file hệ thống, các phần mềm miễn phí mang tính ổn định cao.
Nhân Linux 2.6 có kích thước dưới 300KB.
Nhiều ứng dụng của hệ thống nhúng có thể thực hiện mà không cần MMU.
Ứng dụng người dùng có thể truy cập vào toàn bộ hệ thống, đến từng thanh ghi của thiết bị.
uClinux có thể sử dụng hầu hết các system calls của hệ điều hành Linux chuẩn.
uClinux hỗ trợ chạy đa nhiệm full multi-tasking với hạn chế tương đối nhỏ.
uClinux hỗ trợ nhiều bộ vi xử lý mà Linux chuẩn không hỗ trợ.
Nhược điểm:
uClinux phát triển chậm hơn so với Linux. Tài liệu và tài nguyên online ít hơn so với Linux. uClinux thường không có MMU.
Nhiều đường link cũng như source code trên trang chủ đã quá cũ.[8]
3.2.2 Đơn vị quản lý bộ nhớ MMU
MMU là đơn vị quản lý bộ nhớ trong hệ điều hành. MMU có vai trò dịch địa chỉ từ bộ nhớ ảo VM (Virtual Memory) sang bộ nhớ vật lý, mở rộng bộ nhớ khi bộ nhớ vật lý là có giới hạn, cho phép hệ điều hành có thể đổi chỗ hai bộ nhớ khi cần thiết. MMU còn có vai trò ngăn chặn tiến trình (process) truy cập vào những địa chỉ vật lý không được phép.
40
Hình 3.2 minh họa về mô hình bộ nhớ ảo và bộ nhớ vật lý trong hệ điều hành Linux chuẩn.
Hình 3.2 Bộ nhớ ảo và bộ nhớ vật lý trên hệ điều hành Linux [8]
Với bộ nhớ ảo VM, Linux có thể mở rộng một ngăn xếp (stack) của một process đang chạy khi cần thiết. Khi một ứng dụng thử ghi vào vượt quá đỉnh của stack, MMU sẽ mở rộng vùng bộ nhớ mới và tiếp tục ghép vào đó.
Trong các hệ điều hành có MMU, VM tạo ra một lớp trung gian giữa yêu cầu bộ nhớ cho các ứng dụng và MMU. Ưu điểm chính của hệ thống này là bộ nhớ cho các ứng dụng sẽ được phân tách trong bộ nhớ vật lý, nhờ đó mang lại mức độ bảo vệ bộ nhớ cao hơn. Yêu cầu của các ứng dụng về VM sẽ được phân bố với sự hợp tác giữa MMU và kernel. MMU cung cấp một sự bảo vệ bộ nhớ cho ứng dụng khi chạy trên nền tảng khác. Các hệ điều hành không có MMU nên bộ nhớ chương trình được ánh xạ trực tiếp từ bộ nhớ vật lý, kiến trúc này được gọi là mô hình bộ nhớ phẳng (flat memory model). Trong flat memory model, CPU truy cập tuần tự đến vị trí bộ nhớ sẵn có mà không cần phải phân trang hoặc phân đoạn.
Hệ điều hành uClinux thường không có MMU nên sẽ không có VM và không có sự bảo vệ bộ nhớ. Khi xảy ra lỗi về bộ nhớ của một chương trình sẽ gây ra lỗi cho các chương trình khác và cả kernel. uClinux không có sự phân trang theo yêu cầu, cần phải tải toàn bộ mã nguồn chương trình vào trong RAM, thay vì chỉ cần tải những trang mà chương trình thực sự truy cập đến. Trong hệ điều hành uClinux,
41
kích thước bộ nhớ cho các process được cố định nên không thể phân mảnh bộ nhớ, dẫn đến tốn bộ nhớ hơn.
3.2.3 Runtime linker and loader
Runtime loaders and linkers là một phần quan trọng của hệ điều hành có nhiệm vụ tải và chạy chương trình. Nó có tác dụng định vị mã của chương trình ứng dụng trong các bộ nhớ thứ cấp và cài đặt vào không gian bộ nhớ hệ thống. Mã chương trình ứng dụng có thể yêu cầu điều chỉnh phù hợp với vị trí nơi mà nó được cài đặt vào. [5]
Trong các hệ thống có MMU, ứng dụng có thể sử dụng lợi thế VM nên các lệnh và các dữ liệu chỉ đọc có thể được chia sẻ giữa các ứng dụng. Trong hệ thống không có MMU, kiến trúc flat memory model sẽ cố định từng ứng dụng vào các vùng bộ nhớ khác nhau trong quá trình thực thi. Linker/loader sẽ sắp xếp các ứng dụng và đưa nó vào không gian nhớ hệ thống. Các ứng dụng chỉ có thể làm việc trên phân vùng mà nó được quy định. Về cơ bản, Linker và loader thực thi ba nhiệm vụ chính:
Tải chương trình bằng cách copy chương trình vào bộ nhớ chính. Gán địa chỉ riêng cho mã nguồn và dữ liệu.
Phân tách các địa chỉ, gán con trỏ địa chỉ tới chương trình con.
Loader và linker trải qua ba bước như trên để tạo ra một thực thi. Gói thư viện dùng để biên dịch (toolchain) của uClinux sử dụng ELF (Execution and Linking Format) đã được sửa đổi chút ít cho phù hợp. Đây là một định dạng file chuẩn của các file thực thi, mã đối tượng, các thư viện được chia sẻ. ELF nguyên bản được phát triển bởi Unix System Laboratories và được sử dụng rộng rãi trong nhiều hệ điều hành. Năm 1999, nó được công nhận như một định dạng file nhị phân chuẩn trong Unix. Không giống như nhiều định dạng file thực thi độc quyền, ELF rất linh hoạt, có thể mở rộng và không phụ thuộc vào vi xử lý hoặc kiến trúc.
ELF định nghĩa liên kết và thực thi của một file. Một file ELF bao gồm bốn phần chính:
42 Program header: header của chương trình. Section header: nội dung của file.
Data: dữ liệu.
uClinux cung cấp bộ nhớ như một không gian địa chỉ duy nhất. Điều này có nghĩa là stack tiếp giáp vật lý với dữ liệu tĩnh. Các stack phải có một kích thước cố định và không được chồng lên dữ liệu tĩnh cũng như vùng mã nguồn. Do không có MMU nên uClinux sẽ không có bảo vệ bộ nhớ. Vì kích thước stack là cố định nên sẽ dẫn tới lãng phí một phần không gian bộ nhớ.
3.2.4 Ethernet
Giống như hệ điều hành Linux, uClinux hỗ trợ nhiều ứng dụng khác nhau, trong đó có ứng dụng mạng bao gồm TCP/IP stack và các giao thức khác liên quan đến mạng như TCP/UDP, IP, Ethernet. Khi một ứng dụng mạng được tạo ra và truyền nhận trong mạng, đầu tiên nó sẽ truyền đi gói tin thông qua lớp socket đến lớp transport (TCP hoặc UDP) sau đó chúng sẽ đi đến lớp IP, tại đây kernel sẽ phân giải địa chỉ mà gói tin cần truyền đến. Cấu trúc của ứng dụng mạng trong Linux được biểu diễn trên Hình 3.3.
Hình 3.3 Ethernet trong uClinux
Hai kiểu socket chính được cung cấp trong Linux là BSD (Berkeley Socket Distribution) và INET socket. BSD socket được thực thi dựa trên lớp INET socket và cung cấp giao diện cho người sử dụng.
43
3.2.5 Các thƣ viện đƣợc sử dụng để phát triển hệ điều hành uClinux
uClinux sử dụng một phần của thư viện C chuẩn, đó là thư viện cơ sở để phục vụ cho việc phát triển nhân uClinux. Thư viện này dựa trên thư viện C Linux – 8086 nhưng đã được thu nhỏ thành một thư viện súc tích phù hợp với vi điều khiển. Thư viện uClibc hỗ trợ cho các vi điều khiển không có MMU như Dragonball, ColdFire, ARM… uClinux cũng cung cấp hoàn toàn thư viện Linux chuẩn libC API.
Để phát triển uClinux, nhà phát triển có thể lựa chọn giữa hai thư viện libC là uC-libc và uClibc. Thư viện uClibC giống như thư viện glibc phát triển cho Linux, các hàm của glibc cũng được áp dụng cho uClibc. Ngoài ra gói mã nguồn của uClinux còn một số thư viện khác như:
libgmb: GNU library
libg: gồm có gtermcap, được thiết kế để hỗ trợ truyền đi các chuỗi điều khiển
đến terminal
libcap: cung cấp giao diện hệ thống độc lập ở mức user.
libatm: hỗ trợ cho việc truyền bất đồng bộ (ATM).
libjpeg: hỗ trợ hiển thị hình định dạng JPEG.
libm: hỗ trợ cho các phép tính toán học.
libnet: cung cấp thư viện API cho các giao thức mạng.
libpam: thư viện giao diện phân cấp.
libpng: thư viện giao diện đồ họa cho các ứng dụng mạng. [5] 3.2.6 Driver của các ngoại vi
Driver là các trình quản lý, điều khiển các ngoại vi, cung cấp các hàm cho phép người dùng có thể điều khiển tới các thành phần ngoại vi.
Các driver được chia làm ba lớp:
Character driver: Lớp này được sử dụng rộng rãi từ các ứng dụng đơn giản
44
Character driver đọc và ghi dữ liệu trực tiếp tới thiết bị mà không có bộ nhớ đệm.
Block driver : Lớp này giao tiếp tới hệ thống file và được sử dụng để kết nối
các phân vùng đĩa, các thiết bị vào file hệ thống. Khác với character driver, block driver thường đọc ghi dữ liệu với thiết bị thông qua bộ đệm.
Network driver: Loại này có nhiều cấu trúc khác nhau, hỗ trợ truyền thông,
sử dụng các Port và các Socket để định tuyến các gói dữ liệu.
Thông thường chương trình ứng dụng không được truy cập, đọc hoặc ghi trực tiếp tới các thiết bị ngoại vi. Khi cần giao tiếp với các ngoại vi, chương trình ứng dụng sẽ sử dụng các driver để giao tiếp. Các driver có thể là một module hoặc là được liên kết tĩnh vào nhân. Driver được đăng ký với nhân hệ điều hành trong khi module khởi tạo process. Driver sẽ đăng ký các thành phần:
Bảng Fops (đăng ký các hoạt động như open, close, read, write…) Chỉ số Major.
Device Class (Block hoặc Char). Name – tên driver.
3.2.7 Mã nguồn hệ điều hành uClinux
Người dùng có thể tải về các phiên bản khác nhau của hệ điều hành uClinux từ địa chỉ www.uclinux.org. Toàn bộ mã nguồn uClinux chứa trong một file nén. Khi được giải nén, gói mã nguồn tạo thành cấu trúc hình cây gồm các thư mục và chứa trong thư mục chính là uClinux-dist. Đó là toàn bộ mã nguồn của hệ điều hành uClinux. Công việc của người phát triển là biên dịch tạo ra một file ảnh để đưa vào hệ thống. File nén chứa mã nguồn uClinux được đặt tên theo một định dạng chuẩn như sau nios2-linux-YYYYMMDD.tar trong đó YYYY là năm, MM là tháng, DD là ngày.
Trong đồ án này chúng ta sử dụng mã nguồn hệ điều hành uClinux với phiên bản nhân linux-2.6. Sau khi giải nén, thư mục chính uClinux-dist gồm các thư mục sau:
45 bin: các tiện ích để tạo ra file flash.bin. Documention: tài liệu chi tiết của uClinux. tools: các công cụ để biên dịch.
user: ứng dụng của người dùng và mã nguồn các ứng dụng đó. freeswan: các chương trình bảo mật, mã hóa.
lib: thư mục chứa các thư viện cho ứng dụng. linux-2.6.x: mã nguồn nhân uClinux.
uClibc : thư viện C.
config: cấu hình hệ thống file uClinux.
romfs: cấu trúc hệ thống file của ROM (Read-Only Memory), bao gồm ứng dụng, các file thiết bị. Thư mục này được tạo ra khi biên dịch.
vendor: các loại vi xử lý mà mà hệ điều hành hỗ trợ.
images: Sau khi biên dịch, thư mục này chứa nhân dạng nhị phân của hệ điều hành. [5]
Cấu trúc thư mục của gói mã nguồn được giải nén ra được minh họa ở Hình 3.4.
46
Trong thư mục ROM chứa các thư mục con, đây chính là cấu trúc thư mục của hệ điều hành uClinux khi chạy trên hệ thống nhúng, tương tự như Linux chuẩn. Các thư mục đó là: bin, dev, etc, home, lib, mnt, proc, tmp, usr, var…
Cấu trúc thư mục trong ROM được minh họa ở Hình 3.5.
Hình 3.5 Cấu trúc thƣ mục trong ROM
3.3 Biên dịch mã nguồn hệ điều hành uClinux
Quá trình biên dịch nhân uClinux cũng giống như quá trình biên dịch nhân hệ điều hành Linux bình thường. Trong mã nguồn uClinux, các nhà phát triển đưa vào rất nhiều thư viện, chương trình ứng dụng, driver cho các thiết bị… nếu biên dịch hết toàn bộ mã nguồn thì kích thước file ảnh của hệ điều hành rất lớn. Để phù hợp cho từng hệ thống, uClinux hỗ trợ các lựa chọn cấu hình những mã nguồn cần biên dịch và các processor khác nhau. Khi tiến hành biên dịch, người sử dụng thiết lập các lựa chọn cần thiết cho hệ thống.
3.3.1 Toolchains
Chúng ta sử dụng gói toolchain chuẩn nios2gcc-20080203.tar.bz2 tải từ trang chủ của Altera wiki [9]. Gói toolchain bao gồm các thư viện gcc cần thiết cho quá trình biên dịch nhân như nios2-linux-uclibc-gcc…
47
Sau giải nén gói toolchain, ta cài đặt biến môi trường đến thư mục /opt /nios2/bin, nơi chứa các file thực thi của thư viện uClibc.
PATH=$PATH:~/opt/nios2/bin
3.3.2 Tạo file ảnh zImage
Trong quá trình biên dịch nhân uClinux, file ảnh zImage được tạo ra sau khi thực thi lệnh “make”. Lệnh “make” cũng tạo ra thư mục uClinux-dist/images - nơi chứa file ảnh zImage và thư mục uClinux-dist/romfs - là thư mục ROM khi chạy trên hệ thống nhúng và được đóng gói trong file zImage.
Makefile trong thư mục uClinux-dist sẽ được gọi khi mà lệnh “make” được thực thi. Khi thực hiện lệnh make config, uClinux sẽ hiện ra một màn hình để người dùng chọn lựa các cài đặt cơ bản như các driver cần thiết, thư viện C tích hợp vào nhân, các board hỗ trợ… Ban đầu, nhân sẽ được chọn sẵn một số driver cơ bản. Bằng cách thay đổi các tùy chọn, người dùng sẽ tạo ra được file config theo ý muốn. File config tạo ra sẽ được lưu tại thư mục vendor/Altera/nios2. Thư mục này bao gồm các files:
config.linux-2.6.x: bao gồm các cài đặt mặc định của kernel
config.vendor: bao gồm các cài đặt mặc định của ứng dụng người dùng được build cùng với file image
rc: file kịch bản khởi động hệ thống (script) sẽ được copy vào romfs config.arch: các cài đặt đặc trưng về cấu trúc khi biên dịch file image config.modules: các cài đặt về modules
config.uClibc: các cài đặt về thư viên Clibc
inittab: file script cho quá trình khởi tạo nhân được copy vào thư mục romfs/ etc/inittab
Makefile: file chứa hướng dẫn để build image và thư mục romfs. File này cũng định nghĩa cấu trúc các thư mục sẽ được build trong romfs và cài đặt các file cần thiết như rc & inittab
48
Cũng giống như Linux, uClinux cung cấp các lệnh để xóa các file không cần thiết và các file config nếu muốn cấu hình lại. Lệnh make clean sẽ xóa thư mục romfs và images. Lệnh make mrproper sẽ xóa tất cả các file config đã được tạo. Sau khi thực hiện lệnh này, hệ thống sẽ trở lại trạng thái nguyên bản và tất cả các config sẽ phải được thực hiện lại.
uClinux cung cấp một số lệnh “make” thường được sử dụng khi biên dịch nhân:
Make user_only: chỉ thực hiện make trong ứng dụng người dùng
Make romfs : chỉ thực hiện make ROM.
Make image: thực hiện lệnh make lại ROM và tạo file zImage
Make linux: biên dịch nhân Linux
Make lib_only: biên dịch thư viện
Make user_clean: xóa hết các thư mục trong thư mục user. [5]
3.3.3 Quá trình khởi động nhân Linux
Quá trình khởi động uClinux trên kit phát triển bắt đầu là phát hiện và khởi tạo phần cứng, sau đó thiết lập các ngắt và tải các driver cần thiết cho devices. Sau khi cài đặt phần cứng, kernel thực thi quá trình khởi tạo, nó sẽ đọc các file hệ thống inittab. Sau đó, quá trình khởi tạo sẽ thực thi các start script (các script chỉ chạy một lần, lúc khởi động). Để kết thúc quá trình boot, uClinux sẽ chạy các file rc script bao gồm các lệnh cần thiết để device bắt đầu làm việc. Các scrip này sẽ mount (gắn kết) các file hệ thống cần thiết và thiết lập địa chỉ mạng. Thư mục /etc bao gồm tất cả các scripts cần thiết cho quá trình khởi động hệ thống. Quá trình khởi động hệ thống được mô tả ở Hình 3.6
49
50
3.4 Xây dựng hệ thống uClinux