Đồ án Lập trình nhúng ARM trên Linux - Nguyễn Huy Dũng

pdf 78 trang huongle 190
Bạn đang xem 20 trang mẫu của tài liệu "Đồ án Lập trình nhúng ARM trên Linux - Nguyễn Huy Dũng", để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên

Tài liệu đính kèm:

  • pdfdo_an_lap_trinh_nhung_arm_tren_linux_nguyen_huy_dung.pdf

Nội dung text: Đồ án Lập trình nhúng ARM trên Linux - Nguyễn Huy Dũng

  1. BỘ GIÁO DỤC VÀ ĐÀO TẠO TRƢỜNG ĐẠI HỌC DÂN LẬP HẢI PHÕNG ISO 9001:2008 ĐỒ ÁN TỐT NGHIỆP NGÀNH: ĐIỆN TỬ VIỄN THƠNG Ngƣời hƣớng dẫn : CN. Nguyễn Huy Dũng Sinh viên : Lê Quốc Thiên HẢI PHÕNG – 2013
  2. BỘ GIÁO DỤC VÀ ĐÀO TẠO TRƢỜNG ĐẠI HỌC DÂN LẬP HẢI PHÕNG LẬP TRÌNH NHƯNG ARM TRÊN LINUX ĐỒ ÁN TỐT NGHIỆP ĐẠI HỌC HỆ CHÍNH QUY NGÀNH: ĐIỆN TỬ VIỄN THƠNG Ngƣời hƣớng dẫn : CN. Nguyễn Huy Dũng Sinh viên : Lê Quốc Thiên HẢI PHÕNG – 2013
  3. BỘ GIÁO DỤC VÀ ĐÀO TẠO TRƢỜNG ĐẠI HỌC DÂN LẬP HẢI PHÕNG NHIỆM VỤ ĐỀ TÀI TỐT NGHIỆP Sinh viên : Lê Quốc Thiên. Mã SV: 1351030018. Lớp : ĐT 1301 Ngành: Điện tử viễn thơng. Tên đề tài : Lập trình nhúng ARM trên Linux
  4. NHIỆM VỤ ĐỀ TÀI 1. Nội dung và các yêu cầu cần giải quyết trong nhiệm vụ đề tài tốt nghiệp ( về lý luận, thực tiễn, các số liệu cần tính tốn và các bản vẽ). 2. Các số liệu cần thiết để thiết kế, tính tốn. 3. Địa điểm thực tập tốt nghiệp.
  5. CÁN BỘ HƢỚNG DẪN ĐỀ TÀI TỐT NGHIỆP Ngƣời hƣớng dẫn thứ nhất: Họ và tên: Nguyễn Huy Dũng. Học hàm, học vị: Cử nhân. Cơ quan cơng tác: Trƣờng Đại học Dân lập Hải Phịng. Nội dung hƣớng dẫn: Ngƣời hƣớng dẫn thứ hai: Họ và tên: Học hàm, học vị: Cơ quan cơng tác: Nội dung hƣớng dẫn: Đề tài tốt nghiệp đƣợc giao ngày .tháng .năm 2013 Yêu cầu phải hồn thành xong trƣớc ngày .tháng .năm 2013 Đã nhận nhiệm vụ ĐTTN Đã giao nhiệm vụ ĐTTN Sinh viên Người hướng dẫn Hải Phịng, ngày tháng năm 2013 Hiệu trƣởng GS.TS.NGƢT Trần Hữu Nghị
  6. PHẦN NHẬN XÉT CỦA CÁN BỘ HƢỚNG DẪN 1. Tinh thần thái độ của sinh viên trong quá trình làm đề tài tốt nghiệp: 2. Đánh giá chất lƣợng của khĩa luận (so với nội dung yêu cầu đã đề ra trong nhiệm vụ Đ.T. T.N trên các mặt lý luận, thực tiễn, tính tốn số liệu ): 3. Cho điểm của cán bộ hƣớng dẫn (ghi bằng cả số và chữ): Hải Phịng, ngày tháng năm 2013 Cán bộ hƣớng dẫn
  7. PHẦN NHẬN XÉT TĨM TẮT CỦA NGƢỜI CHẤM PHẢN BIỆN 1. Đánh giá chất lƣợng đề tài tốt nghiệp về các mặt thu thập và phân tích số liệu ban đầu, cơ sở lý luận chọn phƣơng án tối ƣu, cách tính tốn chất lƣợng thuyết minh và bản vẽ, giá trị lý luận và thực tiễn đề tài. 2. Cho điểm của cán bộ phản biện (Điểm ghi cả số và chữ). Hải Phịng, ngày tháng năm 2013 Ngƣời chấm phản biện
  8. MỤC LỤC ẢM ƠN LỜI MỞ ĐẦU 1 CHƢƠNG 1: TỔNG QUAN VỀ HỆ THỐNG NHÚNG 3 1.1. Khái niệm về hệ thống nhúng 3 1.2. Bộ xử lý hệ thống nhúng 5 1.2.1. Kiến trúc CPU 5 1.2.2. Thiết bị ngoại vi 5 1.2.3. Cơng cụ phát triển 6 1.2.4. Độ tin cậy 6 1.2.5. Các kiến trúc phần mềm hệ thống nhúng 8 1.2.6. Hệ thống thời gian thực 8 1.2.7. Hệ điều hành thời gian thực (RTOS) và kernel thời gian thực 9 1.2.8. Chƣơng trình, tác vụ và luồng 9 1.2.9. Kiến trúc của hệ thống thời gian thực 10 1.3. Phát triển ứng dụng nhúng 10 CHƢƠNG 2: VI XỬ LÝ ARM 14 2.1. Tổng quan 14 2.2. Cơ chế Pipeline 15 2.3. Các thanh ghi 15 2.4. Thanh ghi trạng thái chƣơng trình hiện hành 16 2.5. Các mode ngoại lệ 17 2.6. Tập lệnh ARM7 19 2.6.1. Các lệnh rẽ nhánh 20 2.6.2. Các lệnh xử lý dữ liệu 21 2.6.3. Các lệnh truyền dữ liệu 22 2.6.4. Lệnh SWAP 23 2.7. Ngắt mềm (SWI – Software Interput instruction) 23 2.8. Đơn vị MAC (Multíply Accumulate Unit (MAC) 23 2.9. Tập lệnh THUMB 24 2.10. Cổng JTAG 26 2.11. Memory Acelerator Module (MAM) 27 2.12. PLL- Phase Locked Loop 29 2.13. Bộ chia bus (VLSI Peripheral Bus Divider) 31
  9. CHƢƠNG 3: HỆ ĐIỀU HÀNH NHÚNG EMBEDĐE LINUX 33 3.1. Giới thiệu hệ điều hành nhúng 33 3.1.1. Hệ điều hành 33 3.1.2. Hệ điều hành nhúng 34 3.2. Các hệ điều hành nhúng điển hình 34 3.2.1. Embedded Linux 34 3.2.2. Windows CE 36 3.2.3. Andriod 37 3.3. Lập trình C/C++ trên Linux 39 3.3.1. Linux và các lệnh cơ bản 39 3.3.2. Chƣơng trình trên Linux 43 3.3.3. Xử lý tiến trình trong linux 48 CHƢƠNG 4:LẬP TRÌNH NHÚNG ARM TRÊN LINUX 59 4.1. Giới thiệu KIT nhúng FriendlyArm Micro2440 59 4.2. Mơi trƣờng phát triển ứng dụng 61 4.3. Lập trình điều khiển LED 61 4.4. Lập trình đọc trạng thái nút bấm 63 KẾT LUẬN 67 TÀI LIỆU THAM KHẢO 68
  10. ẢM ƠN Trƣớc hết, em xin gửi lời cảm ơn chân thành tới thầy giáo Nguyễn Huy Dũng đã tận tình chỉ bảo, hƣớng dẫn và giúp cho em cĩ những kiến thức cũng nhƣ kinh nghiệm quý báu. Em xin tỏ lịng biết ơn sâu sắc tới các thầy cơ giáo trƣờng Đại Học Dân Lập Hải Phịng và đặc biệt là các thầy cơ giáo trong tổ bộ mơn điện tử viễn thơng đã luơn nhiệt tình giảng dạy và chỉ bảo chúng em trong suốt bốn năm học vừa qua. Cuối cùng, xin cảm ơn gia đình, ngƣời thân và các bạn của tơi, những ngƣời đã luơn bên cạnh động viên, khích lệ và giúp đỡ tơi trong thời gian qua. Mặc dù cĩ nhiều cố gắng, song thời gian thực hiện đồ án cĩ hạn, vốn kiến thức nắm đƣợc chƣa nhiều nên đồ án cịn nhiều hạn chế. Em rất mong nhận đƣợc nhiều sự gĩp ý, chỉ bảo của các thầy, cơ để hồn thiện hơn bài viết của mình. Em xin chân thành cảm ơn! Hải Phịng, tháng 6 năm 2013 Sinh viên thực hiện Lê Quốc Thiên
  11. LỜI MỞ ĐẦU Thế giới ngày nay với khoa học kĩ thuật phát triển mạnh mẽ cuộc sống con ngƣời ngày càng đƣợc phát triển tốt hơn. Khoa học kỹ thuật đem lại nhiều tiện ích thiết thực hơn cho cuộc sống con ngƣời. Gĩp phần to lớn trong quá trình phát triển của khoa học kỹ thuật là sự phát triển mạnh mẽ của vi xử lý. Từ bộ vi xử lý đầu tiên Intel 4004 đƣợc sản xuất bởi cơng ty Intel vào năm 1971, đến nay ngành cơng nghiệp vi xử lý đã phát triển vƣợt bậc và đa dạng với nhiều loại nhƣ: 8951, PIC, AVR, ARM, Pentium,Core i7, . Cùng với sự phát triển đa dạng về chủng loại thì tài nguyên của vi xử lý cũng đƣợc nâng cao. Các vi xử lý ngày nay cung cấp cho ngƣời dùng một nguồn tài nguyên rộng lớn và phong phú. Cĩ thể đáp ứng đƣợc nhiều yêu cầu khác nhau trong thƣc tế. Để giúp cho ngƣời dùng sử dụng hiệu quả và triệt để các tài nguyên này thì hệ thống nhúng ra đời.Hệ thống nhúng (Embedded system) là một thuật ngữ để chỉ một hệ thống cĩ khả năng tự trị đƣợc nhúng vào trong một mơi trƣờng hay một hệ thống mẹ. Đĩ là các hệ thống tích hợp cả phần cứng và phần phềm phục vụ các bài tốn chuyên dụng trong nhiều lĩnh vực cơng nghiệp, tự động hố điều khiển, quan trắc và truyền tin. Với sự ra đời của hệ thống nhúng thì vi xử lý ngày càng đƣợc ứng dụng rộng rãi trong đời sống cũng nhƣ trong cơng nghiệp vì khả năng xử lý nhanh, đa dạng, tiết kiệm năng lƣợng và độ ổn định của hệ thống nhúng. Tuy hệ thống nhúng rất phổ biến trên tồn thế giới và là hƣớng phát triển của ngành Điện tử sau này nhƣng hiện nay ở Việt Nam độ ngũ kỹ sƣ hiểu biết về hệ thống nhúng cịn rất hạn chế khơng đáp ứng đƣợc nhu cầu nhân lực trong lĩnh vực này. Vì vậy việc biên soạn giáo trình về hệ thống nhúng là một yêu cầu cần thiết trong thời điểm hiện tại cũng nhƣ trong tƣơng lai. Nhận thấy đƣợc nhu cầu cấp thiết đĩ nên sinh viên thực hiện đã chọn đề tài: “LẬP TRÌNH NHƯNG ARM TRÊN LINUX” để làm đồ án tốt nghiệp cho mình. Với mục tiêu xác định nhƣ trên, đồ án đƣợc chia ra làm 3 phần với nội dung cơ bản nhƣ sau: 1
  12. Chƣơng 1: Tổng quan về hệ thống nhúng. Chƣơng 2: Vi xử lý ARM. Chƣơng 3: Hê điều hành nhúng Embedded Linux. Chƣơng 4: Lập trình nhúng ARM trên Linux. Do thời gian thực hiện ngắn cộng với vốn kiến thức cịn rất hạn chế nên đồ án chắc chắn cịn nhiều thiếu sĩt, em rất mong nhận đƣợc sự chỉ bảo của các thầy cơ để hồn thiện hơn bài viết của mình. 2
  13. CHƢƠNG 1: TỔNG QUAN VỀ HỆ THỐNG NHÚNG 1.1. Khái niệm về hệ thống nhúng Hệ thống nhúng (Embedded system) là một thuật ngữ để chỉ một hệ thống cĩ khả năng tự trị đƣợc nhúng vào trong một mơi trƣờng hay một hệ thống mẹ. Đĩ là các hệ thống tích hợp cả phần cứng và phần mềm phục vụ các bài tốn chuyên dụng trong nhiều lĩnh vực cơng nghiệp, tự động hố điều khiển, quan trắc và truyền tin. Đặc điểm của các hệ thống nhúng là hoạt động ổn định và cĩ tính năng tự động hố cao. Hệ thống nhúng thƣờng đƣợc thiết kế để thực hiện một chức năng chuyên biệt nào đĩ. Khác với các máy tính đa chức năng, chẳng hạn nhƣ máy tính cá nhân, một hệ thống nhúng chỉ thực hiện một hoặc một vài chức năng nhất định, thƣờng đi kèm với những yêu cầu cụ thể và bao gồm một số thiết bị máy mĩc và phần cứng chuyên dụng mà ta khơng tìm thấy trong một máy tính đa năng nĩi chung. Vì hệ thống chỉ đƣợc xây dựng cho một số nhiệm vụ nhất định nên các nhà thiết kế cĩ thể tối ƣu hĩa nĩ nhằm giảm thiểu kích thƣớc và chi phí sản xuất. Các hệ thống nhúng thƣờng đƣợc sản xuất hàng loạt với số lƣợng lớn. Hệ thống nhúng rất đa dạng, phong phú về chủng loại. Đĩ cĩ thể là những thiết bị cầm tay nhỏ gọn nhƣ đồng hồ kĩ thuật số và máy chơi nhạc MP3, hoặc những sản phẩm lớn nhƣ đèn giao thơng, bộ kiểm sốt trong nhà máy hoặc hệ thống kiểm sốt các máy năng lƣợng hạt nhân. Xét về độ phức tạp, hệ thống nhúng cĩ thể rất đơn giản với một vi điều khiển hoặc rất phức tạp với nhiều đơn vị, các thiết bị ngoại vi và mạng lƣới đƣợc nằm gọn trong một lớp vỏ máy lớn. Nhƣ vậy khơng phải tất cả các sản phẩm đo lƣờng và điều khiển đều là các hệ nhúng. Hiện nay chúng ta cịn gặp nhiều hệ thống điều khiển tự động hoạt động theo nguyên tắc cơ khí, thuỷ lực, khí nén, rơ le, hoặc diện tử tƣơng tự Ngƣợc lại phần lớn các sản phẩm cơ điện tử hiện nay đều cĩ nhúng trong nĩ các chip vi xử lý hoặc một mạng nhúng. Ta biết rằng cơ điện tử là sự cộng năng của các cơng nghệ cơ khí, điện tử, điều khiển và cơng nghệ thơng tin. Sự phối hợp đa ngành này tạo nên sự vƣợt trội của các sản phẩm cơ điện tử. Sản phẩm cơ điện tử ngày càng tinh sảo và ngày càng thơng minh mà phần hồn của nĩ do các phần mềm nhúng trong nĩ tạo nên. Các sản phẩm cơ điện tử là các sản phẩm cĩ ít nhất một quá trình cơ khí (thƣờng là một quá trình chuyển động), là đối tƣợng để điều khiển do vậy các sản phẩm cơ điện tử ngày nay thƣờng cĩ các hệ nhúng trong nĩ nhƣng ngƣợc lại khơng phải hệ thống nhúng nào cũng là một hệ cơ điện tử. 3
  14. Điểm qua sự phát triển của máy tính ta thấy nĩ đã trải qua 3 giai đoạn. Giai đoạn năm 1960-1980 là giai đoạn phát triển của máy tính lớn và máy mini (main frame và mini computer) với khoảng 1000 chip/máy và mỗi máy cĩ khoảng 100 ngƣời dùng. Giai đoạn từ 1980-2000 là giai đoạn phát triển của máy PC với số chip vi xử lý khoảng 10 chip/máy và thơng thƣờng cho một ngƣời sử dụng. Thời đại hậu PC (Post-PC Era) là giai đoạn mà mọi đồ dùng đều cĩ chip, trung bình 1 chip/một máy và số máy dùng cho một ngƣời lên đến >100 máy. Giai đoạn hậu PC đƣợc dự báo từ 2001-2010 khi các thiết bị xung quanh ta đều đƣợc thơng minh hố và kết nối với nhau thành mạng tạo thành mơi trƣờng thơng minh phục vụ cho con ngƣời. Điểm qua về chức năng xử lý tin ở PC và ở các thiết bị nhúng cĩ những nét khác biệt. Đối với PC và mạng Internet chức năng xử lý đang đƣợc phát triển mạnh ở các lĩnh vực nhƣ thƣơng mại điện tử, ngân hàng điện tử, chính phủ điện tử, thƣ viện điện tử, đào tạo từ xa, báo điện tử .Các ứng dụng này thƣờng sử dụng máy PC để bàn, mạng WAN, LAN hoạt động trong thế giới ảo. Cịn đối với các hệ nhúng thì chức năng xử lý tính tốn đƣợc ứng dụng cụ thể cho các thiết bị vật lý (thế giới thật) nhƣ mobile phone, quần áo thơng minh, các đồ điện tử cần tay, thiết bị y tế, xe ơ tơ, tàu tốc hành, phƣơng tiện vận tải thơng minh, máy đo, đầu đo cơ cấu chấp hành thơng minh, các hệ thống điều khiển, nhà thơng minh, thiết bị gia dụng thơng minh Hệ thống nhúngcĩ vai trị đảm nhận một phần cơng việc cụ thể của hệ thống mẹ. hệ thống nhúngcĩ thể là một hệ thống phần cứng và cũng cĩ thể là một hệ thống phần mềm. Đặc điểm của hệ thống nhúnglà hoạt động ổn định và cĩ tính năng tự động hố cao. hệ thống nhúngđƣợc thiết kế để thực hiện một chứa năng chuyên biệt nào đĩ. Khác với các máy tính đa năng, chẳng hạn nhƣ PC, một hệ thống nhúng chỉ thực hiện một hay một vài chức năng nhất định, thƣờng đi kèm với những yêu cầu cụ thể và bao gồm một số thiết bị máy mĩc và phần cứng chuyên dụng mà ta khơng tìm thấy trong một máy tính đa năng nĩi chung. Vì hệ thống chỉ đƣợc xây dựng cho một số nhiệm vụ nhất định nên các nhà thiết kế cĩ thể tối ƣu hĩa nĩ nhằm giảm thiểu kích thƣớc và chi phí sản xuất. Các hệ thống nhúngthƣờng đƣợc sản xuất hàng loạt với số lƣợng lớn. Hệ thống nhúngrất đa dạng, phong phú về chủng loại. Đĩ cĩ thể là những thiết bị cầm tay nhỏ gọn nhƣ đồng hồ kĩ thuật số và máy chơi nhạc MP3, các thiết bị điện tử dân dụng (máy giặt, tủ lạnh, TV ), các thiết bị điện tử “thơng minh” (điện thoại di động), thiết bị truyền thơng, thiết bị y tế, xe hơi, thậm chí cả trong một máy tính cá nhân (card mở rộng), hoặc những sản phẩm lớn nhƣ đèn giao thơng, bộ kiểm sốt trong nhà máy hoặc hệ thống kiểm sốt các máy năng lƣợng hạt nhân. Xét về độ phức tạp, hệ thống nhúng cĩ thể rất đơn giản với một vi điều khiển hoặc rất phức tạp với nhiều đơn vị, các thiết bị ngoại vi và mạng lƣới đƣợc nằm gọn trong một lớp vỏ máy lớn. 4
  15. Các thiết bị PDA hoặc máy tính cầm tay cũng cĩ một số đặc điểm tƣơng tự với hệ thống nhúng nhƣ các hệ điều hành hoặc vi xử lý điều khiển chúng nhƣng các thiết bị này khơng phải là hệ thống nhúng thật sự bởi chúng là các thiết bị đa năng, cho phép sử dụng nhiều ứng dụng và kết nối đến nhiều thiết bị ngoại vi. Cĩ rất nhiều hãng sản xuất bộ vi xử lý, phần cứng và phần mềm trong thị trƣờng hệ thống nhúng và ứng với mỗi nhà sản xuất lại cĩ nhiều dịng sản phẩm, phong phú về chủng loại và giá thành: • Những bộ vi xử lý và phần cứng khác nhau: Texas Instrument, Freescale, ARM, Intel, Motorola, Atmel, AVR, Renesas • Những hệ điều hành khác nhau: QNX, uITRON, VxWorks, Windows CE/XP Embedded, Embedded Linux, Osek, Symbian • Những ngơn ngữ lập trình khác nhau: C/C++, B#, Ada, Assembly, PMC, LabView, PLC 1.2. Bộ xử lý trong hệ nhúng 1.2.1 Kiến trúc CPU: Các bộ xử lý trong hệ thống nhúng cĩ thể đƣợc chia thành hai loại: vi xử lý và vi điều khiển. Các vi điều khiển thƣờng cĩ các thiết bị ngoại vi đƣợc tích hợp trên chip nhằm giảm kích thƣớc của hệ thống. Cĩ rất nhiều loại kiến trúc CPU đƣợc sử dụng trong thiết kế hệ nhúng nhƣ ARM, MIPS, Coldfire/68k, PowerPC, x86, PIC, 8051, Atmel AVR, Renesas H8, SH, V850, FR-V, M32R, Z80, Z8 Điều này trái ngƣợc với các loại máy tính để bàn, thƣờng bị hạn chế với một vài kiến trúc máy tính nhất định. Các hệ thống nhúng cĩ kích thƣớc nhỏ và đƣợc thiết kế để hoạt động trong mơi trƣờng cơng nghiệp thƣờng lựa chọn PC/104 và PC/104++ làm nền tảng. Những hệ thống này thƣờng sử dụng DOS, Linux, NetBSD hoặc các hệ điều hành nhúng thời gian thực nhƣ QNX hay VxWorks. Cịn các hệ thống nhúng cĩ kích thƣớc rất lớn thƣờng sử dụng một cấu hình thơng dụng là hệ thống on chip (System on a chip – SoC), một bảng mạch tích hợp cho một ứng dụng cụ thể (an application-specific integrated circuit – ASIC). Sau đĩ nhân CPU đƣợc mua và thêm vào nhƣ một phần của thiết kế chip. Một chiến lƣợc tƣơng tự là sử dụng FPGA (field-programmable gate array) và lập trình cho nĩ với những thành phần nguyên lý thiết kế bao gồm cả CPU. 1.2.2 Thiết bị ngoại vi: HỆ THỐNG NHÚNG giao tiếp với bên ngồi thơng qua các thiết bị ngoại vi • Serial Communication Interfaces (SCI): RS-232, RS-422, RS-485 • Synchronous Serial Communication Interface: I2C, JTAG, SPI, SSC và ESSI • Universal Serial Bus (USB) • Networks: Controller Area Network, LonWorks 5
  16. • Bộ định thời: PLL(s), Capture/Compare và Time Processing Units • Discrete IO: General Purpose Input/Output (GPIO) 1.2.3 Cơng cụ phát triển: Tƣơng tự nhƣ các sản phẩm phần mềm khác, phần mềm HỆ THỐNG NHÚNG cũng đƣợc phát triển nhờ việc sử dụng các trình biên dịch (compilers), chƣơng trình dịch hợp ngữ (assembler) hoặc các cơng cụ gỡ rối (debuggers). Tuy nhiên, các nhà thiết kế hệ thống nhúngcĩ thể sử dụng một số cơng cụ chuyên dụng nhƣ: • Bộ gỡ rối mạch hoặc các chƣơng trình mơ phỏng (emulator) • Tiện ích để thêm các giá trị checksum hoặc CRC vào chƣơng trình, giúp hệ thống nhúng cĩ thể kiểm tra tính hợp lệ của chƣơng trình đĩ. • Đối với các hệ thống xử lý tín hiệu số, ngƣời phát triển hệ thống cĩ thể sử dụng phần mềm workbench nhƣ MathCad hoặc Mathematica để mơ phỏng các phép tốn. • Các trình biên dịch và trình liên kết (linker) chuyên dụng đƣợc sử dụng để tối ƣu hĩa một thiết bị phần cứng. • Một hệ thống nhúng cĩ thể cĩ ngơn ngữ lập trình và cơng cụ thiết kế riêng của nĩ hoặc sử dụng và cải tiến từ một ngơn ngữ đã cĩ sẵn. - Các cơng cụ phần mềm cĩ thể đƣợc tạo ra bởi các cơng ty phần mềm chuyên dụng về hệ thống nhúng hoặc chuyển đổi từ các cơng cụ phát triển phần mềm GNU. Đơi khi, các cơng cụ phát triển dành cho PC cũng đƣợc sử dụng nếu bộ xử lý của hệ thống nhúngđĩ gần giống với bộ xử lý của một máy PC thơng dụng. 1.2.4 Độ tin cậy: Các hệ thống nhúngthƣờng nằm trong các cỗ máy đƣợc kỳ vọng là sẽ chạy hàng năm trời liên tục mà khơng bị lỗi hoặc cĩ thể khơi phục hệ thống khi gặp lỗi. Vì thế, các phần mềm hệ thống nhúngđƣợc phát triển và kiểm thử một cách cẩn thận hơn là phần mềm cho PC. Ngồi ra, các thiết bị rời khơng đáng tin cậy nhƣ ổ đĩa, cơng tắc hoặc nút bấm thƣờng bị hạn chế sử dụng. Việc khơi phục hệ thống khi gặp lỗi cĩ thể đƣợc thực hiện bằng cách sử dụng các kỹ thuật nhƣ watchdog timer – nếu phần mềm khơng đều đặn nhận đƣợc các tín hiệu watchdog định kì thì hệ thống sẽ bị khởi động lại. - Một số vấn đề cụ thể về độ tin cậy nhƣ: • Hệ thống khơng thể ngừng để sửa chữa một cách an tồn, VD nhƣ ở các hệ thống khơng gian, hệ thống dây cáp dƣới đáy biển, các đèn hiệu dẫn đƣờng Giải pháp đƣa ra là chuyển sang sử dụng các hệ thống con dự trữ hoặc các phần mềm cung cấp một phần chức năng. • Hệ thống phải đƣợc chạy liên tục vì tính an tồn, VD nhƣ các thiết bị dẫn đƣờng máy bay, thiết bị kiểm sốt độ an tồn trong các nhà máy hĩa chất, Giải pháp đƣa ra là lựa chọn backup hệ thống. 6
  17. • Nếu hệ thống ngừng hoạt động sẽ gây tổn thất rất nhiều tiền của, VD nhƣ các dịch vụ buơn bán tự động, hệ thống chuyển tiền, hệ thống kiểm sốt trong các nhà máy 1.2.5 Các kiến trúc phần mềm HỆ THỐNG NHÚNG: Một số loại kiến trúc phần mềm thơng dụng trong các hệ thống nhúngnhƣ sau: -Vịng lặp kiểm sốt đơn giản: Theo thiết kế này, phần mềm đƣợc tổ chức thành một vịng lặp đơn giản. Vịng lặp gọi đến các chƣơng trình con, mỗi chƣơng trình con quản lý một phần của hệ thống phần cứng hoặc phần mềm. - Hệ thống ngắt điều khiển: •Các hệ thống nhúngthƣờng đƣợc điểu khiển bằng các ngắt. Cĩ nghĩa là các tác vụ của hệ thống nhúngđƣợc kích hoạt bởi các loại sự kiện khác nhau. VD: một ngắt cĩ thể đƣợc sinh ra bởi một bộ định thời sau một chu kỳ đƣợc định nghĩa trƣớc, hoặc bởi sự kiện khi cổng nối tiếp nhận đƣợc một byte nào đĩ. •Loại kiến trúc này thƣờng đƣợc sử dụng trong các hệ thống cĩ bộ quản lý sự kiện đơn giản, ngắn gọn và cần độ trễ thấp. Hệ thống này thƣờng thực hiện một tác vụ đơn giản trong một vịng lặp chính. Đơi khi, các tác vụ phức tạp hơn sẽ đƣợc thêm vào một cấu trúc hàng đợi trong bộ quản lý ngắt để đƣợc vịng lặp xử lý sau đĩ. Lúc này, hệ thống gần giống với kiểu nhân đa nhiệm với các tiến trình rời rạc. - Đa nhiệm tƣơng tác: •Một hệ thống đa nhiệm khơng ƣu tiên cũng gần giống với kỹ thuật vịng lặp kiểm sốt đơn giản ngoại trừ việc vịng lặp này đƣợc ẩn giấu thơng qua một giao diện lập trình API. Các nhà lập trình định nghĩa một loạt các nhiệm vụ, mỗi nhiệm vụ chạy trong một mơi trƣờng riêng của nĩ. Khi khơng cần thực hiện nhiệm vụ đĩ thì nĩ gọi đến các tiến trình con tạm nghỉ (bằng cách gọi “pause”, “wait”, “yeild” ).Ƣu điểm và nhƣợc điểm của loại kiến trúc này cũng giống với kiểm vịng lặp kiểm sốt đơn giản. Tuy nhiên, việc thêm một phần mềm mới đƣợc thực hiện dễ dàng hơn bằng cách lập trình một tác vụ mới hoặc thêm vào hàng đợi thơng dịch (queue-interpreter). - Đa nhiệm ƣu tiên: •Ở loại kiến trúc này, hệ thống thƣờng cĩ một đoạn mã ở mức thấp thực hiện việc chuyển đổi giữa các tác vụ khác nhau thơng qua một bộ định thời. Đoạn mã này thƣờng nằm ở mức mà hệ thống đƣợc coi là cĩ một hệ điều hành và vì thế cũng gặp phải tất cả những phức tạp trong việc quản lý đa nhiệm. •Bất kỳ tác vụ nào cĩ thể phá hủy dữ liệu của một tác vụ khác đều cần phải đƣợc tách biệt một cách chính xác. Việc truy cập tới các dữ liệu chia sẻ cĩ thể đƣợc quản lý bằng một số kỹ thuật đồng bộ hĩa nhƣ hàng đợi thơng điệp (message queues), semaphores Vì những phức tạp nĩi trên nên một giải pháp thƣờng đƣợc đƣa ra đĩ là sử dụng một hệ điều hành thời gian thực. Lúc đĩ, các nhà lập trình cĩ thể tập trung vào 7
  18. việc phát triển các chức năng của thiết bị chứ khơng cần quan tâm đến các dịch vụ của hệ điều hành nữa. - Vi nhân (Microkernel) và nhân ngoại (Exokernel): •Khái niệm vi nhân (microkernel) là một bƣớc tiếp cận gần hơn tới khái niệm hệ điều hành thời gian thực. Lúc này, nhân hệ điều hành thực hiện việc cấp phát bộ nhớ và chuyển CPU cho các luồng thực thi. Cịn các tiến trình ngƣời dùng sử dụng các chức năng chính nhƣ hệ thống file, giao diện mạng lƣới, Nĩi chung, kiến trúc này thƣờng đƣợc áp dụng trong các hệ thống mà việc chuyển đổi và giao tiếp giữa các tác vụ là nhanh. •Cịn nhân ngoại (exokernel) tiến hành giao tiếp hiệu quả bằng cách sử dụng các lời gọi chƣơng trình con thơng thƣờng. Phần cứng và tồn bộ phần mềm trong hệ thống luơn đáp ứng và cĩ thể đƣợc mở rộng bởi các ứng dụng. - Nhân khối (monolithic kernels): •Trong kiến trúc này, một nhân đầy đủ với các khả năng phức tạp đƣợc chuyển đổi để phù hợp với mơi trƣờng nhúng. Điều này giúp các nhà lập trình cĩ đƣợc một mơi trƣờng giống với hệ điều hành trong các máy để bàn nhƣ Linux hay Microsoft Windows và vì thế rất thuận lợi cho việc phát triển. Tuy nhiên, nĩ lại địi hỏi đáng kể các tài nguyên phần cứng làm tăng chi phí của hệ thống. Một số loại nhân khối thơng dụng là Embedded Linux và Windows CE. Mặc dù chi phí phần cứng tăng lên nhƣng loại hệ thống nhúng này đang tăng trƣởng rất mạnh, đặc biệt là trong các thiết bị nhúng mạnh nhƣ Wireless router hoặc hệ thống định vị GPS. Lý do của điều này là: . Hệ thống này cĩ cổng để kết nối đến các chip nhúng thơng dụng . Hệ thống cho phép sử dụng lại các đoạn mã sẵn cĩ phổ biến nhƣ các trình điều khiển thiết bị, Web Servers, Firewalls, . Việc phát triển hệ thống cĩ thể đƣợc tiến hành với một tập nhiều loại đặc tính, chức năng cịn sau đĩ lúc phân phối sản phẩm, hệ thống cĩ thể đƣợc cấu hình để loại bỏ một số chức năng khơng cần thiết. Điều này giúp tiết kiệm đƣợc những vùng nhớ mà các chức năng đĩ chiếm giữ. . Hệ thống cĩ chế độ ngƣời dùng để dễ dàng chạy các ứng dụng và gỡ rối. Nhờ đĩ, qui trình phát triển đƣợc thực hiện dễ dàng hơn và việc lập trình cĩ tính linh động hơn. . Cĩ nhiều hệ thống nhúng thiếu các yêu cầu chặt chẽ về tính thời gian thực của hệ thống quản lý. Cịn một hệ thống nhƣ Embedded Linux cĩ tốc độ đủ nhanh để trả lời cho nhiều ứng dụng. Các chức năng cần đến sự phản ứng nhanh cũng cĩ thể đƣợc đặt vào phần cứng. 1.2.6 Hệ thống thời gian thực: Nhƣ đã đề cập ở trên, một hệ thống cĩ khả năng thực hiện thời gian thực nghĩa là hệ thống đĩ phải thực hiện các chức năng của mình trong một khoảng thời gian xác định và nhỏ nhất cĩ thể chấp nhận đƣợc. Khi đáp ứng đƣợc yêu cầu này, hệ thống đĩ cĩ thể gọi là hệ thống thời gian thực. 8
  19. Các hệ thống này phải cĩ khả năng đáp ứng các tín hiệu ngõ vào hoặc các sự kiện trong giới hạn một khoảng thời gian bắt buộc. Cho nên các hệ thống này khơng chỉ phải trả về một kết quả đúng mà cịn phải nhanh nhất đáp ứng đƣợc yêu cầu về tốc độ của hệ thống. Trong các hệ thống thời gian thực, tốc độ cũng quan trọng khơng kém gì độ chính xác của nĩ. Cĩ 2 loại thời gian thực: thời gian thực cứng và thời gian thực mềm. Đối với hệ thống thời gian thực cứng, tất cả các chức năng của nĩ phải đƣợc thực thi chính xác trong một khoảng thời gian xác định, nếu khơng cả hệ thống sẽ bị lỗi nghiêm trọng. VD: hệ thống điều khiển khơng lƣu, hệ thống dẫn đƣờng tên lửa, thiết bị y tế Đối với hệ thống thời gian thực mềm, các chức năng phải đƣợc thực hiện trong một khoảng thời gian xác định nhỏ nhất nhƣng khơng bắt buộc. 1.2.7 Hệ điều hành thời gian thực (RTOS) và kernel thời gian thực: Một số các ứng dụng nhúng cĩ thể thực hiện hiệu quả mà chỉ cần một chƣơng trình đơn giản chạy độc lập điều khiển cả hệ thống. Tuy nhiên, đối với đa số các ứng dụng mang tính thƣơng mại, một hệ thống nhúngcần phải cĩ hệ điều hành thời gian thực hoặc kernel thời gian thực. Một kernel thời gian thực thƣờng nhỏ hơn rất nhiều so với một RTOS hồn chỉnh. Trong lý thuyết về hệ điều hành, kernel chính là một phần của hệ điều hành, nĩ sẽ đƣợc nạp lên bộ nhớ đầu tiên và vẫn tồn tại trong lúc chƣơng trình hoạt động. Một kernel thời gian thực sẽ cung cấp hầu hết các dịch vụ cần thiết cho các ứng dụng nhúng.Do đĩ chỉ là một phần của hệ điều hành và đƣợc nạp thẳng lên bộ nhớ, nên một kernel thời gian thực thƣờng cĩ kích thƣớc rất nhỏ, rất phù hợp cho các bộ nhớ cĩ dung lƣợng thấp trong các hệ thống nhúng. Hình dƣới mơ tả một kernel trong một RTOS hồn chỉnh. Hoạt động của hệ thống nhúngđƣơc thực hiện theo chƣơng trình, gồm các tác vụ (task) hoặc luồng (thread) trong việc đáp ứng các tín hiệu ngõ vào hay trong quá trình xử lý bình thƣờng theo yêu cầu của hệ thống. Các quá trình xử lý phải trả về kết quả đúng trong một khoảng thời gian xác định. 1.2.8 Chƣơng trình, tác vụ và luồng: Một chƣơng trình trên một hệ thống nhúngchính là một phần mềm cĩ khả năng thực thi độc lập và cĩ vùng nhớ riêng của mình. Nĩ bao gồm mơi trƣờng thực thi một chức năng cụ thể và khả năng tƣơng tác với hệ điều hành. Một chƣơng trình cĩ thể đƣợc bắt đầu chạy một cách độc lập hoặc cĩ thể từ các chƣơng trình khác. Một hệ điều hành cĩ khả năng thực thi nhiều chƣơng trình cùng một lúc song song nhau. Tuy nhiên, khi một chƣơng trình cĩ khả năng tự chia ra một vài phần cĩ khả năng thực thi song song nhau, mỗi phần đĩ đƣợc gọi là một luồng. Một luồng chính là một phần trong chƣơng trình và phụ thuộc về mặt chức năng so với các luồng khác nhƣng lại cĩ khả năng hoạt động độc lập nhau. Các luồng sẽ chia sẻ chung một bộ nhớ trong một chƣơng trình. Khái niệm về tác vụ và luồng cĩ thể thay thế cho nhau. Hình dƣới mơ tả sự khác nhau giữa chƣơng trình và luồng. 9
  20. 1.2.9 Kiến trúc của hệ thống thời gian thực: Kiến trúc của một hệ thống thời gian thực sẽ quyết định các luồng đƣợc thực thi khi nào và bằng cách nào. Cĩ 2 kiến trúc phổ biến là kiến trúc điều khiển vịng lặp với polling và mơ hình sắp xếp ƣu tiên. Trong kiến trúc điều khiển vịng lặp với polling, kernel sẽ thực thi một vịng lặp vơ hạn, vịng lặp này sẽ chọn ra luồng trong một mẫu đƣợc định trƣớc. Nếu một luồng cần dịch vụ, nĩ sẽ đƣợc xử lý. Cĩ một vài biến thể của phƣơng pháp này, tuy nhiên vẫn phải đảm bảo mỗi luồng đều cĩ khả năng truy cập đến vi xử lý. Hình dƣới mơ tả cách xử lý của phƣơng pháp này. Mặc dù phƣơng pháp điều khiển vịng lặp với polling rất dễ thực hiện, tuy nhiên nĩ vẫn cĩ những hạn chế nghiêm trọng. Thứ nhất đĩ chính là nĩ sẽ mất rất nhiều thời gian, khi mà một luồng cần truy cập đến vi xử lý sẽ phải chờ đến lƣợt của mình và một chƣơng trình cĩ quá nhiều luồng sẽ bị chậm đi rất nhiều. Thứ hai, phƣơng pháp này khơng cĩ sự phân biệt giữa các luồng, luồng nào quan trọng và luồng nào ít quan trọng, từ đĩ xác định mức độ ƣu tiên giữa các luồng. Một phƣơng pháp khác mà các kernel thời gian thực hay sử dụng đĩ chính là mơ hình sắp xếp mức độ ƣu tiên. Trong mơ hình này, mỗi luồng sẽ đi kèm với mức độ ƣu tiên của nĩ. Lúc này, vi xử lý sẽ thiết lập đƣờng truy cập tới luồng nào cĩ mức độ ƣu tiên cao nhất khi nĩ địi hỏi đƣợc phục vụ. Cũng cĩ một vài biến thể của phƣơng pháp này, tuy nhiên vẫn phải đảm bảo các luồng cĩ mức độ ƣu tiên thấp nhất vẫn phải cĩ thể truy cập tới vi xử lý một vài lần. Hình dƣới mơ tả phƣơng pháp cách xử lý của phƣơng pháp này. Một ƣu điểm cực kỳ quan trọng của phƣơng pháp này đĩ chính là nĩ cĩ khả năng tạm hỗn thực thi một luồng khi cĩ một luồng khác với mức độ ƣu tiên cao hơn cần phục vụ. Quá trình lƣu trữ lại các thơng tin hiện thời của luồng bị tạm hỗn thực thi khi cĩ một luồng khác với mức độ ƣu tiên cao hơn cần phục vụ gọi là “context switching”. Quá trình này phải đƣợc thực hiện nhanh và đơn giản để luồng bị tạm hỗn cĩ thể thực hiện tiếp nhiệm vụ của mình một cách chính xác khi nĩ lấy lại đƣơc quyền điều khiển. Một hệ thống nhúng thời gian thực phải cĩ khả năng đáp ứng lại các tín hiệu ngõ vào hay các sự kiện một cách nhanh nhất và chính xác nhất, đây chính là các ngắt của hệ thống. Ngắt của hệ thống sẽ phải làm cho vi xử lý ngƣng nhiệm vụ đang thực thi để xử lý ngắt. Một ngắt sẽ đƣợc xử lý bởi ISR (interrupt service routine), nĩ cĩ khả năng kích hoạt một luồng cĩ mức độ ƣu tiên cao hơn luồng đang đƣợc thực thi. Lúc này, nĩ sẽ tạm hỗn lại luồng hiện tại để dành quyền cho luồng mới cĩ mức độ ƣu tiên cao hơn. Ngắt cĩ thể đƣợc tạo ra bởi phần mềm (ngắt mềm) hay bởi các thiết bị phần cứng (ngắt cứng). 1.3. Phát triển ứng dụng nhúng Các ứng dụng nhúng ngày nay rất rộng rãi và sẽ đƣợc phát triển ngày càng cao ở cả phần cứng lẫn phần mềm. Các ứng dụng nhúng đều cần phải cĩ thời gian thực, đây 10
  21. là một sự khác biệt rất lớn giữa một hệ thống nhúng và một hệ thống máy tính truyền thống. Ngày nay để tăng tốc độ của một hệ thống nhúng, nĩ phải cĩ khả năng thực hiện xử lý song song giữa các luồng với nhau. Do vậy, cách viết các chƣơng trình phần mềm truyền thống sẽ khơng cịn phù hợp khi lập trình cho các hệ thống nhúngđa luồng nữa. Hơn nữa, một vi xử lý trong hệ thống nhúng địi hỏi tốc độ cao sẽ khơng cịn làm nhiệm vụ xử lý, mà chỉ cịn làm nhiệm vụ điều khiển và giám sát hoạt động của hệ thống. Chức năng xử lý luồng dữ liệu sẽ đƣợc các module phần cứng trong hệ thống đảm nhận và đƣợc thực hiện song song nhau. Kiến trúc một hệ thống nhúngthời gian thực đã cĩ sự khác biệt rất nhiều và những cải tiến đáng kể so với kiến trúc hệ thống máy tính truyền thống trƣớc kia. Điều này nhằm đảm bảo về sự chính xác và cải thiện tốc độ của hệ thống. Hầu hết các hệ thống nhúng ngày nay dùng ngơn ngữ C để lập trình, tuy nhiên một số rất ít vẫn dùng hợp ngữ. - Xu hƣớng phát triển của các hệ thống nhúng hiện nay là: • Phần mềm ngày càng chiếm tỷ trọng cao và đã trở thành một thành phần cấu tạo nên thiết bị bình đẳng nhƣ các phần cơ khí, linh kiện điện tử, linh kiện quang học • Các hệ nhúng ngày càng phức tạp hơn đáp ứng các yêu cầu khắt khe về thời gian thực, tiêu ít năng lƣợng và hoạt động tin cậy ổn định hơn. • Các hệ nhúng ngày càng cĩ độ mềm dẻo cao đáp ứng các yêu cầu nhanh chĩng đƣa sản phẩm ra thƣơng trƣờng, cĩ khả năng bảo trì từ xa, cĩ tính cá nhân cao. • Các hệ nhúng ngày càng cĩ khả năng hội thoại cao, cĩ khả năng kết nối mạng và hội thoại đƣợc với các đầu đo cơ cấu chấp hành và với ngƣời sử dụng,. • Các hệ nhúng ngày càng cĩ tính thích nghi, tự tổ chức cao cĩ khả năng tái cấu hình nhƣ một thực thể, một tác nhân. • Các hệ nhúng ngày càng cĩ khả năng tiếp nhận năng lƣợng từ nhiều nguồn khác nhau (ánh sáng, rung động, điện từ trƣờng, sinh học .) để tạo nên các hệ thống tự tiếp nhận năng lƣợng trong quá trình hoạt động. - Trong các hệ nhúng, hệ thống điều khiển nhúng đĩng một vai trị hết sức quan trọng. - Nhu cầu hệ thống nhúng trên thế giới: Trong thế giới cơng nghệ thơng tin, các “ơng lớn” nhƣ IBM, Microsoft, Intel đã chuyển hƣớng một số bộ phận nghiên cứu phát triển của mình sang làm hệ thống nhúng từ rất sớm. Điển hình là Microsoft với các máy chơi game Xbox, hệ điều hành nhúng Windows CE, Intel với các dịng chip xử lý nhúng nhƣ Intel 8008, 8080, 8085, 3000, các thẻ nhớ Nand Flash, các vi điều khiển MCS 51/251, MCS 96/296 Bên cạnh đĩ là sự xuất hiện của hàng loạt các nhà sản xuất vi xử lý cho hệ thống nhúngnhƣ ARM, Atmel, Renesas Thị trƣờng hệ thống nhúng cĩ tiềm năng phát triển vơ cùng 11
  22. lớn. Theo các nhà thơng kê trên thế giới thì số chip xử lý trong các máy PC và các server, các mạng LAN, WAN, Internet chỉ chiếm khơng đầy 1% tổng số chip vi xử lý cĩ trên thế giới. Hơn 99% số vi xử lý cịn lại nằm trong các hệ hệ thống nhúng. Số liệu đánh giá chi tiết của nhĩm nghiên cứu BCC (BCC Research Group) về thị trƣờng HỆ THỐNG NHÚNG tồn cầu đến năm 2009 :“Thị trƣờng hệ thống nhúngtồn cầu đạt doanh thu 45,9 tỷ USD trong năm 2004 và dự báo sẽ tăng 14% trong vịng năm năm tới, đạt 88 tỷ USD.Trong đĩ thì thị trƣờng phần mềm nhúng sẽ tăng trƣởng từ 1,6 tỷ USD năm 2004 lên 3,5 tỷ USD năm 2009, với mức tăng trung bình hằng năm là 16%. Tốc độ tăng trƣởng phần cứng nhúng sẽ là 14,2% một năm, đạt 78,7 tỷ USD năm 2009, trong khi lợi nhuận các board mạch nhúng sẽ tăng 10% một năm. Tại Châu Á, Nhật Bản đang dẫn đầu về thị trƣờng nhúng và là một trong những thị trƣờng phần mềm nhúng hàng đầu thế giới. Theo thống kê của JISA (Hiệp hội Dịch vụ Cơng nghệ Thơng tin Nhật Bản), phần mềm nhúng hiện nay chiếm tới 40% thị phần phần mềm Nhật Bản, với các sản phẩm rất đa dạng : lị vi ba, máy photocopy, máy in laser, máy FAX, các bảng quảng cáo sử dụng hệ thống đèn LED, màn hình tinh thể lỏng Năm 2004, thị trƣờng phần mềm nhúng của Nhật Bản đạt khoảng 20 tỷ USD với 150.000 nhân viên. Đây đƣợc coi là thị trƣờng đầy hứa hẹn với các đối tác chuyên sản xuất phần mềm nhúng nhƣ Trung Quốc, Indonesia, Nga, Ireland, Israel và cả Việt Nam. - Nhu cầu hệ thống nhúng ở Việt Nam: Với tốc độ tăng trƣởng nhanh nhƣ vậy, cơ hội cho các doanh nghiệp Việt Nam đối với loại hình phần mềm mới mẻ này đang mở rộng. Chủ tịch Hiệp hội doanh nghiệp phần mềm Việt Nam (VINASA) Trƣơng Gia Bình cho rằng, các doanh nghiệp Việt Nam đang cĩ một số lợi thế. Đĩ là nguồn nhân lực cơng nghệ thơng tin rẻ và tiếp thu nhanh, cĩ kinh nghiệm làm gia cơng phần mềm cho nƣớc ngồi, đƣợc Chính phủ quan tâm và hỗ trợ phát triển Tuy nhiên, Việt Nam mới chỉ là “lính mới” trong sân chơi sơi động này.Ở Việt Nam, hệ thống nhúngmới đƣợc quan tâm trong thời gian gần đây. Các doanh nghiệp làm phần mềm nhúng cũng chƣa nhiều, mới cĩ một số trung tâm thuộc các trƣờng Đại học Quốc gia, Đại học Bách khoa, các đơn vị nhƣ Học viện Kỹ thuật quân sự, Viện nghiên cứu Điện tử - Tin học và Tự động hĩa, Tổng cơng ty Điện tử - Tin học, Cơng ty thiết bị Điện tử y tế, Cơng ty VTC – Truyền hình số mặt đất và một số cơng ty phần mềm khác Các sản phẩm phần mềm nhúng “made in Việt Nam” cĩ lẽ mới chỉ là con số khá khiêm tốn, cịn lại là làm gia cơng cho nƣớc ngồi. Cĩ thể điểm ra một vài sản phẩm tiêu biểu do ngƣời Việt làm ra nhƣ phần mềm nhúng cho đầu thu kỹ thuật số của Cơng ty Điện tử HANEL (giải Sao Khuê 2005), Nhúng cá thể hĩa thẻ thơng minh của Cơng ty Liên doanh thẻ thơng minh MK (giải Sao Khuê 2005) Con đƣờng để đến với thành cơng trong sản xuất và xuất khẩu phần mềm nhúng của các doanh nghiệp Việt Nam cịn rất nhiều chơng gai. Theo ơng Phan Văn Hịa, Giám đốc Trung tâm cơng nghệ của FPT Software, thách thức lớn nhất Việt Nam phải vƣợt qua hiện nay là chƣa cĩ nhiều kinh nghiệm trong lĩnh vực mới mẻ này, mới 12
  23. chỉ loanh quanh làm gia cơng phần mềm, làm thuê theo đơn đặt hàng của nƣớc ngồi, chƣa cĩ nhiều trung tâm đào tạo chuyên sâu về hệ thống nhúng. Tại hội thảo về CNTT tổ chức tại Hải Phịng tháng 9-2005, Hiệp hội doanh nghiệp phần mềm Việt Nam VINASA cho rằng, xây dựng và phát triển phần mềm nhúng là một trong 3 mũi nhọn cĩ thể coi là đột phá cho hƣớng đi của cơng nghệ phần mềm Việt Nam, bên cạnh việc phát triển game và các giải pháp ERP. Trong chiến lƣợc phát triển cơng nghệ thơng tin đến năm 2010, phần mềm nhúng đƣợc coi là một trong những sản phẩm trọng điểm. - Những thách thức và các vấn đề tồn tại của hệ nhúng: • Độ phức tạp của sự liên kết đa ngành phối hợp cứng - mềm.Độ phức tạp của hệ thống tăng cao do nĩ kết hợp nhiều lĩnh vực đa ngành, kết hợp phần cứng - mềm, trong khi các phƣơng pháp thiết kế và kiểm tra chƣa chin muồi. Khoảng cách giữa lý thuyết và thực hành lớn và cịn thiếu các phƣơng pháp và lý thuyết hồn chỉnh cho khảo sát phân tích tồn cục các hệ nhúng. • Thiếu phƣơng pháp tích hợp tối ƣu giữa các thành phần tạo nên hệ nhúng bao gồm lý thuyết điều khiển tự động, thiết kế máy, cơng nghệ phần mềm, điện tử, vi xử lý, các cơng nghệ hỗ trợ khác. • Thách thức đối với độ tin cậy và tính mở của hệ thống: Do hệ thống nhúng thƣờng phải hội thoại với mơi trƣờng xung quanh nên nhiều khi gặp những tình huống khơng đƣợc thiết kế trƣớc dễ dẫn đến hệ thống bị loạn. Trong quá trình hoạt động một số phần mềm thƣờng phải chỉnh lại và thay đổi nên hệ thống phần mềm cĩ thể khơng kiểm sốt đƣợc. Đối với hệ thống mở, các hãng thứ 3 đƣa các module mới, thành phần mới vào cũng cĩ thể gây nên sự hoạt động thiếu tin cậy. 13
  24. CHƢƠNG 2: VI XỬ LÝ ARM 2.1. Tổng quan Vi điều khiển ARM đƣợc phát triển theo kiến trúc RISC (Reduced Instruction Set Computer): - Chỉ cĩ các lệnh nạp hoặc lƣu trữ là cĩ thể tham chiếu tới bộ nhớ, - Tồn tại ít lệnh và kiểu định địa chỉ, khuơn dạng lệnh cố định, - Cĩ nhiều tập thanh ghi, - Các lệnh thực hiện trong một chu kỳ máy, - Lệnh đƣợc thực hiện trực tiếp trên phần cứng(CISC cĩ 1 chƣơng trình thơng dịch nhỏ), - Chƣơng trình biên dịch mã nguồn phức tạp(CISC-chƣơng trình thơng dịch phức tạp), - Hỗ trợ cơ chế pipeline, - Kích thƣớc chƣơng trình lớn. Cấu trúc các chân: Thí dụ các chân của LPC2101: Hình 2.1. Cấu trúc các chân của LPC2101 14
  25. 2.2. Cơ chế Pipeline Cơ chế pipeline của ARM7, thực thi lệnh theo ba bƣớc: đọc lệnh, giải mã lệnh và thực hiện lệnh. Hình 2.2. Ba bước thực hiện của pipepline - Pipeline cĩ phần cứng độc lập để thực hiện các bƣớc, trong khi lệnh thứ nhất đang thực thi, lệnh thứ 2 đƣợc giải mã và lệnh thứ 3 đƣợc đọc lên pipeline. - Hầu hết các lệnh của ARM 7 đƣợc thực thi trong 1 chu kỳ máy. - Pipeline làm việc rất tốt trong trƣờng hợp chƣơng trình khơng rẽ nhánh. ARM chỉ cho phép thực hiện các bƣớc nhảy ngán trong đoạn chƣơng trình. - Pipeline là một thành phần của CPU, thanh ghi PC chạy ở 8 bytes đầu của lệnh hiện hành sẽ đƣợc thực thi. Thí dụ: 0x4000 LDR PC,[PC,#4]-> PC=0x400C 2.3. Các thanh ghi ARM7 cĩ kiến trúc kiểu load and store, bởi vậy, để thực hiện các lệnh xử lý dữ liệu thì tất cả các dữ liệu phải đƣợc tải từ bộ nhớ vào một tập các thanh ghi trung tâm, lệnh xử lý dữ liệu đƣợc thực hiện và lƣu trữ dữ liệu trở lại bộ nhớ. Hình 2.3. Kiến trúc load and store của ARM 7 15
  26. ARM7 cĩ 17 thanh ghi 32 bít: - Các thanh ghi RO đến R12 là các thanh ghi chung, - Thanh ghi R13 là thanh ghi con trỏ ngăn xếp, - R14 là thanh ghi liên kết, - R15 là thanh ghi bộ đếm chƣơng trinh (PC) và - Thanh ghi trạng thái chƣơng trình CPSR. Thanh ghi R14 dùng trong chƣơng trƣờng hợp gọi đến chƣơng trình con “gần” thì nĩ sẽ cất giữ địa chỉ trả về của chƣơng trình chính, nếu trong chƣơng trình con này gọi đến một chƣơng trình con khác thì địa chỉ của chƣơng trình chính phải đƣợc cất giữa vào ngăn xếp. Hình 2.4. Các thanh ghi của ARM7 2.4. Thanh ghi trạng thái chƣơng trình hiện hành Hình 2.5. Thanh ghi trạng thái chương trình CPSR 16
  27. CPU ARM7 thực thi 2 loại lệnh: Tập lệnh ARM 32 bít và tập lệnh đƣợc nén 16 bít. Bít T sẽ quyết định loại lệnh nào sẽ đƣợc thực thi, ngƣời lập trình khơng nên set hay xĩa giá trị của bít này. ARM7 cĩ 7 chế độ hoạt động khác nhau, ngƣời lập trình thƣờng chạy trong chế độ ngƣời dùng để truy cập đến các bank thanh ghi từ R0-R15 và thanh ghi trạng thái chƣơng trình(CPSR). Tuy nhiên khi gặp các ngoại lệ nhƣ ngắt, lỗi bộ nhớ, ngắt mềm CPU sẽ chuyển sang chế độ khác. Mỗi chế độ các thanh ghi R13 và R14 cĩ giá trị riêng. Ở chế độ ngắt nhanh FIQ các thanh ghi R7-R12 cĩ giá trị giống nhau (khơng cần dùng stack để lƣu chữ). Hình 2.6. Các chế độ hoạt động của APU ARM7 2.5. Các mode ngoại lệ Khi cĩ một ngoại lệ xảy ra, CPU sẽ chuyển chế độ và thanh ghi PC sẽ đƣợc nhảy về địa chỉ của vecto ngoại lệ. Bảng vecto bắt đầu từ địa chỉ 0 trùng địa chỉ vecto ngắt. Mỗi vecto ngoại lệ là 4 bytes. 17
  28. Bảng 2.1. Bảng các vecto ngắt Bảng 2.2. Thứ tự ưu tiên của các ngắt Hình 2.7. Thí dụ về trật tự xử lý khi cĩ một ngoại lệ ngắt xảy ra 18
  29. Hình 2.8. CPU trở lại trạng thái ban đầu khi kết thúc phụ vụ ngoại lệ 2.6. Tập lệnh ARM 7 ARM7 cĩ 2 tập lệnh: Tập lệnh mở rộng 32 bít và tập lệnh nén (THUMB) 16 bít. CPU ARM7 đƣợc thiết kế để hỗ trợ xử lý theo kiểu big endian hay little endian: Hình 2.9. Hai kiểu xử lý của CPU ARM7 Một đặc điểm của ARM7 là tất cả các lệnh đều cĩ thể là các lệnh cĩ điều kiện, bằng cách so sánh 4 bít từ bit 28 đến bít 31 của kết quả thực hiện lệnh với các bít điều kiện trong thanh ghi CPSR, nếu điều khiện khơng thỏa mãn thì lệnh sẽ khơng đƣợc thực thi. 19
  30. Các lệnh xử lý dữ liệu sẽ bị ảnh hƣởng bởi các bít điều kiện trong thanh ghi CPSR. Hai lệnh cơ bản MOV và ADD cĩ thể đặt các tiến tố đằng trƣớc với 16 điều kiện nhƣ sau: Bảng 2.3. 16 điều kiện khi dung hai lệnh cơ bản MOV và ADD Thí dụ: EQMOY RI ,#0x00800000; - Giá trị 0x00800000 chỉ đƣa vào RI khi kết quả cuối cùng của lệnh cĩ các bít tƣơng ứng với 4 bít trong thanh ghi CPSR và bít cờ z đƣợc set =1. - Các lệnh của ARM7 cĩ thể chia thành 6 nhỏm: Các lệnh rẽ nhánh, các lệnh xử lý dữ liệu, truyền dữ liệu, truyền khối dữ liệu, lệnh số học và ngắt mềm. 2.6.1. Các lệnh rẽ nhánh Cho phép nhảy tiến hoặc lùi trong phạm vi 32MB, địa chỉ của lệnh tiếp theo sẽ đƣợc lƣu vào thanh ghi liên kết R14. Lệnh rễ nhánh cĩ 2 biến thể: Rễ nhánh trao đổi (branch exchange) và rẽ nhánh liên kết trao đổi (branch link exchange). Hai lệnh này cơ giống nhau nhƣng lệnh rẽ nhánh liên kết địa chỉ của lệnh tiếp theo đƣợc cộng thêm 4 bytes rồi đƣa vào R14. 20
  31. 2.6.2. Các lệnh xử lý dữ liệu Cú pháp tổng quát: Hình 2.10. Cú pháp tổng quát của một lệnh xử lý dữ liệu cĩ điều kiện Mỗi lệnh đều cĩ 2 tốn hạng, trong đĩ tốn hạng thứ nhất phải là thanh ghi, tốn hạng cịn lại cĩ thể thanh ghi hoặc giá trị cụ thể. Bít „S‟ đƣợc sử dụng để điều khiển điều kiện của lệnh: • S=1 thì điều kiện của lệnh phụ thuộc vào kết quả của lệnh, • S = 0thì khơng cĩ điều gì xảy ra Nếu S=1 và PC là thanh ghi chứa kết quả thì SPSR của chế độ hiện hành đƣợc copy vào CPSR. Bảng 2.4. Bảng các lệnh xử lý dữ liệu 21
  32. 2.6.3. Cáclệnh truyền dữ liệu: Bảng 2.5. Các lệnh truyền dữ liệu Hình 2.11. Các lệnh truyền một khối dữ liệu 22
  33. 2.6.4. Lệnh SWAP ARM7 hỗ trợ các tín hiệu thời gian thực YỚi một lệnh swap cho phép trao đổi chỗ nội dung của hai thanh ghi. Lệnh này đƣợc hỗ trợ trong thƣ viện ARM chứ khơng trực tiếp từ ngơn ngữ C. Hình 2.12. Mơ tả lệnh swap trong ARM7 2.7. Ngắt mềm (SWI – Software Interput instruction) Các ngắt mềm sinh ra một ngoại lệ khi thực thi, đƣa vi xử lý vào chế độ hoạt động giám sát và PC nhảy tới địa chỉ 0x00000008. Cũng nhƣ các lệnh ARM khác, lệnh ngắt mềm chứa một mã điều kiện thực thi trong 4 bít thấp của tốn hạng, các bít cịn lại là trống rỗng. Hình 2.13. Điều kiện của ngắt mềm để CPU vào chế độ giám sát Cĩ thể giả lặp chƣơng trình con phục vụ ngắt của ngắt mềm nhƣ sau: switch( *(R14-4) & 0x00FFFFFF) // Kiểm tra giá trịđƣợc lƣu trữ trong thanh ghi liên kết case (SWI-1): •••} 2.8. Đơn vị MAC (Multíply Accumulate Unit (MAC) MAC hỗ trợ phép nhận số nguyên kiểu integer và long integer, khi nhân kiểu integer 2 thanh ghi 32 bít với nhau thì kết quả là 32 bít đƣợc đặt vào thanh ghi thứ 3. Khi nhân 32 bít kiểu long integer thì kết quả là 64 bít và đƣợc đặt vào 2 thanh ghi. 23
  34. Các lệnh nhân dạng ASM: Bảng 2.6. Các lệnh nhân trong vi điêu khiên ARM 2.9. Tập lệnh THUMB Tập lệnh ARM là tập lệnh 32 bít, ARM cĩ tập lệnh 16 bít gọi là tập lệnh THUMB. Tập lệnh THUMB thực chất là tập lệnh nén lại từ tập lệnh ARM. Hình 2.14. Tập lệnh THUMB được nén lại từ tập lệnh ARM Tập lệnh THUMB tiết kiệm đƣợc khơng gian nhớ 30% và chạy nhanh hơn 40% so với tập lệnh ARM. Tập lệnh THUMB khơng cĩ điều kiện thực thi trừ các lệnh rẽ nhánh. Các lệnh xử lý dữ liệu thì cần cĩ một thanh ghi nguồn và một thanh ghi đích. Thí dụ: Vĩi lệnh cộng thanh ghi RO và RI: Dùng lệnh ARM: ADD RO, RO,RI //RO = R0+R1 Dùng lệnh THUMB: ADD RO,RI // RO = R0+R1 24
  35. Tập lệnh THUMB chỉ cĩ thể truy cập đến các thanh ghi thấp từ R0-R7, các thanh ghi cao từ R8-R12 bị giới hạn truy cập: Hình 2.15. Mơ hình lập trình tập lệnh THUMB Ngƣời lập trình khơng thể truy cập trực tiếp vào thanh ghi CPSR và SPSR. Ngƣời lập trình cĩ thể sử dụng 2 lệnh BLX và BX để chuyển chế độ hoạt động với các lệnh. Khi reset vi điều khiển làm việc với tập lệnh THUMB, khi cĩ 1 ngoại lệ xảy ra thì sẽ chuyển sang làm việc với tập lệnh ARM, khi kết thúc ngoại lệ thì quay trở về làm việc với lệnh ARM. 25
  36. Hình 2.16. Trao đổi giữa lệnh ARM và lệnh THUMB 2.10. Cổng JTAG Họ LPC2000 của hãng Philips cĩ nhiều cổng cho phép kết nối vi điều khiển với máy tính, thƣờng đƣợc sử dụng nhất là cổng JTAG. Khi kết nối trực tiếp với máy tính cho phép ngƣời lập trình debug trực tiếp trên mạch phần cứng: Hình 2.17. Kết nối LPC2000 với máy tính qua cổng JTAG - Đồng thời kèm theo module ETM cho phép debug chƣơng trình: nhƣ theo dõi thời gian thực, theo dõi sự kiện và phân tích quá trình thực thi. 26
  37. 2.11. Memory Acelerator Module (MAM) Là bộ nhớ nằm giữa bộ nhớ Flash và CPU ARM, cĩ tốc độ thực thi cao. Hình 2.18. Mơ hình bộ nhớ MAM - CPU ARM cĩ thể chạy ở tốc độ 80MHz, mỗi lần chíp Flash truy cập hết 50ns. - Flash chạy ở tốc độ 20MHz - MAM đƣợc tạo ra nhƣ là một cache đầy đủ cho phép CPU dễ dàng truy cập trực tiếp vào FLASH. Hĩnh 2.19. Truy cập bộ nhớ FLASH qua MAM - Khỉ đọc các lệnh từ bank thứ nhất thì bank thứ hai đƣợc chốt. - MAM là trong suốt với ngƣời dùng và đƣợc cấu hình bởi 2 thanh ghi: điều khiển (MAMCR) và định thời (MAMTIM). Thanh ghi định thời đƣợc sử dụng để điều 27
  38. khiển mối quan hệ giữa CPU và FLASH bằng cách thiết lập 3 bít đầu tiên của nĩ để chỉ định chu kỳ xung nhịp của CPU đƣợc yêu cầu bởi MAM để truy cập vào FLASH. - Khi FLASH cĩ tốc độ 20MHz và CPU cĩ cĩ thể cĩ tốc độ cực đại là 60MHz, số chu kỳ yêu cầu truy cập FLASH là 3. Thí dụ: cấu hình MAM #include "LPC21xx.h" void ChangeGPIOPinState(unsigned int State); int main(void){ unsigned int delay,val; unsigned int FLASHer = 0x00010000; // Khai báo cục bộ IODIRO = 0x00FF0000; //Thiết lập các chân ra VPBDIV = 0x02; ADCR = 0x00270601; // Thiết lập A/D: 10-bit AIN0 @ 3MHz ADCR 1= 0x01000000; // Khởi tạo bộ chuyển đổi A/D while(l) { do{ val = ADDR; // Đọc thanh ghi dữ liệu bộ chuyển đổi A/D }while ((val &0x80000000) == 0); val = ((val» 6) & 0x03FF); if (val <0x80) { MAMCR = 0; MAMTIM = 0x03; MAMCR = 0x02; }else { MAMCR = 0x0; } for(delay = 0;delay<0xl00000;delay++) //tạo vịng lặp {;} ChangeGPIOPinState(FLASHer); //Đổi trạng thái các chân ra ở cổng FLASHer = FLASHer «1; //Dịch đến đèn led tiếp if(FLASHer&0x01000000) { FLASHer = 0x00010000; //Lặp lại đèn đầu tiên // overflow }}} void ChangeGPIOPinState(unsigned int State) 28
  39. { IOSETO = State; //set output pins IOCLRO = ~state; //clear output pins 2.12. PLL- Phase Locked Loop Tạo ra một tần số dao động ngồi từ 10-25MHz từ mạch dao động cơ bản và cĩ thể tăng lên 60 MHz để cung cấp cho CPU ARM và thiết bị ngoại vi. Tần số đầu ra của PLL cĩ thể thay đổi tự động, cho phép thiết bị điều chỉnh theo tốc độ thực thi để duy trì nguồn năng lƣợng khi ở trạng thái rảnh rỗi. Hình 2.20. Phase Locked Loop Hai hằng M và p phải đƣợc lập trình để quyết định xung clock (Cclk) cho CPU và AHB. Hằng thứ nhất đƣợc nhân một cách tuyến tính với tần số dao động bên ngồi đƣa vào. Tần số ra của PLL là: Cclk=M X Osc Ngƣợc lại PLL lại đƣợc điều khiển bởi một dao động hoạt động hiện hành (CCO) ở dải tần 156MHz-320MHz. Hằng số thứ 2 phải đƣợc lập trình đề đảm bảo sao cho cco đƣợc giữ một giá trị cụ thể: Fcco = Cclk X 2 X p Trên board phát triển thì dao động thạch anh là 12MHz, bởi vậy để CPU đạt đƣợc tốc độ tối đa 60MHz thì: M = Cclk/Osc = 60/12 =5 và 156< Fcco <320 = 60 X 2 X p Thực nghiệm thì p=2. 29
  40. Giao diện lập trình PLL: Hình 2.21. Giao diện lập trình PLL Giá trị trong các thanh ghi PLLCON, PLLCFG và PLLSTAT sẽ đƣợc ghi sau khi giá trị trong PLL FEED đƣợc ghi. Khi cập nhật giá trị thanh ghi PLLCON và PLLCFG thì phải ghi liên tiếp hai giá trị OxOOOOOOAA và 0x00000055 cho thanh ghi PLLFEED, các giá trị này phải ghi trong các chu kỳ liên tiếp. Nếu lập trình cho phép các ngắt thì ngắt sẽ sinh ran gây sau khỉ từ đầu tiên đƣợc ghi và các thiết lập mới cho PLL sẽ khơng cĩ ảnh hƣờng. Đê cài đặt PLL phải ghi các giá trị cho p và M tới thanh ghi PLLCFG, sau đĩ set DO của thanh ghi PLLCON để cho phép PLL khởi động. Giá trị của M chiếm 5 bít thấp (D4-D0), p chiếm 2 bít D6D5: Bảng 2.7. Giá trị của p và M trong thanh ghi PLLCFG 30
  41. PLL mất một khoảng thời gian xác định đủ để sử dụng nguồn xung clock. Sự khởi động PLL cĩ thể đƣợc kiểm tra bằng cách đọc bít LOCK (D10) trong thanh ghi trạng thái PLLSTAT. Khi LOCK bít =1, PLL cĩ thể đƣợc sử dụng nhƣ nguồn xung clock chính. Một ngắt cĩ thể đƣợc sinh ra khi PLL khĩa, bởi vậy ngƣời lập trình cĩ thể thực hiện các nhiệm vụ khác khi PLL khởi động. Khi PLL bị khĩa thì cĩ thể thay thế nguồn xung cho Cclk bằng cách đỉều khiển bít PLLC ƣong thanh ghi PLLCON. Hình 2.22. Trình tự khởi động PLL 2.13. Bộ chia bus (VLSI Peripheral Bus Divider) Mạch dao động ngồi hoặc đầu ra của PLL đƣợc sử dụng để tạo ra nguồn xung Cclk cho CPU ARM hoặc hệ thống bus cĩ tần số cao. Các thiết bị ngoại vi cĩ thể sử dụng bus VPB riêng biệt Hình 2.23. Tạo xung Pclk từ Cclk Bộ chia cĩ thể chia tốc độ Cclk xuống 2 đến 24 lần. Thanh ghi trong bộ chia VPBDIV cĩ thể lập trình đƣợc và chứa số ỉần giảm tắc độ. Tại thời điểm khỏi động, giá trị cực đại đƣợc nạp và bằng VA giá trị Cclk lúc khởi động. 31
  42. Hiện nay tất cả các thiết bị ngoạỉ vi của họ vi điều khiển LPC cĩ thể chạy ở tần số 60MHz. Vì vậy, bộ chia tần VPB thƣờng đƣợc sử dụng để tiết kiệm nguồn bàng cách tạo xung clock chấp nhận đƣợc cho các ứng dụng. Thỉ du: cấu hình PLL và VPB: Cấu hình PLL để tạo ra tần sổ Cclk là 60MHz và Pclk là 30MHz với xung đầu vào là 12MHz: void init_PLL(void) { PLLCFG = 0x00000024; // Thiết lập hệ số nhân và bộ chia cho PLL //give 60.00 MHz PLLCON = 0x00000001; // Kích hoạt PLL PLLFEED = OxOOOOOOAA; // Cập nhật thanh ghi PLLFEED PLLFEED = 0x00000055; while (!(PLLSTAT & 0x00000400)); // kiểm tra bít Lock PLLCON = 0x00000003; // Kết nối tĩi PLL PLLFEED = OxOOOOOOAA; //Cập nhật các thanh ghi PLL PLLFEED = 0x00000055; VPBDIV = 0x00000002; //Thiết lập bus VLSI với tần số 30.000MHz } 2.13. Các cổng vào ra Các cổng vào ra của ARM là 32 bít, vi điều khiển cĩ thể chỉ cĩ 1 cổng hoặc cĩ nhiều hơn, nhƣng các chân dùng cho cổng vào/ra cũng là các chân dùng chung cho các mục đích khác nhƣ biến đổi AD, ngắt, giao diện SPI, I2C, Các chân đƣợc sử dụng vào mục đích nào tùy vào việc cấu hình chúng cho mục đích đĩ. 32
  43. CHƢƠNG 3: HÊ ĐIỀU HÀNH NHÚNG EMBEDDED LINUX 3.1. Giới thiệu hệ điều hành nhúng 3.1.1 Hệ điều hành Hệ điều hành là một chƣơng trình quản lý phần cứng máy tính. Nĩ cung cấp nền tảng cho các chƣơng trình ứng dụng và đĩng vai trị trung gian giao tiếp giữa ngƣời dùng máy tính và phần cứng của máy tính đĩ. Hệ điều hành thiết lập cho các tác vụ này rất đa dạng. Một vài hệ điều hành thiết kế tiện dụng trong khi một số khác thiết kế hiệu quả hoặc kết hợp cả hai. Một hệ điều hành là một thành phần quan trọng của mọi hệ thống máy tính. Một hệ thống máy tính cĩ thể đƣợc chia thành bốn thành phần: phần cứng, hệ điều hành, các chƣơng trình ứng dụng và ngƣời dùng. - Phần cứng (Hardware): bao gồm bộ xử lý trung tâm (CPU), bộ nhớ, thiết bị xuất/nhập, cung cấp tài nguyên cơ bản cho hệ thống. - Các chƣơng trình ứng dụng (application programs): trình biên dịch (compiler), trình soạn thảo văn bản (text editor), hệ cơ sở dữ liệu (database system), trình duyệt Web, định nghĩa cách mà trong đĩ các tài nguyên đƣợc sử dụng để giải quyết yêu cầu của ngƣời dùng. - Ngƣời dùng (user): cĩ nhiều loại ngƣời dùng khác nhau, thực hiện những yêu cầu khác nhau, do đĩ sẽ cĩ nhiều ứng dụng khác nhau. - Hệ điều hành (operating system): hay cịn gọi là chƣơng trình hệ thống, điều khiển và hợp tác việc sử dụng phần cứng giữa những chƣơng trình ứng dụng khác nhau cho những ngƣời dùng khác nhau. Hệ điều hành cĩ thể đƣợc khám phá từ hai phía: ngƣời dùng và hệ thống. Hình 3.1 Mơ tả các thành phần của một hệ thống máy tính 33
  44. 3.1.2. Hệ điều hành nhúng Hệ điều hành nhúng mang đặc trƣng cơ bản của hệ điều hành - Quản lý tài nguyên phần cứng và phần mềm của hệ thống. - Trung gian giữa phần cứng và phần mềm, giúp phần cứng làm việc trong suốt với phần mềm ứng dụng. - Cung cấp giao diện hàm chuẩn cho phần mềm ứng dụng. 3.2. Các hệ điều hành nhúng điển hình 3.2.1. Embedded Linux Trong những năm gần đây, Linux đã trở nên phổ biến trên các thiết bị nhúng, đặc biệt là trên các sản phẩm điện tử tiêu dùng, thiết bị định tuyến, chuyển mạch, các ứng dụng trên internet và trên ơtơ. Bởi vì bản chất của Linux là module Linux, do đĩ dễ dàng làm nhỏ lại cho vừa mơi trƣờng hoạt động bằng cách bớt các chƣơng trình tiện ích, cơng cụ, và hệ thống dịch vụ khơng cần thiết đƣợc nhúng vào trong một mơi trƣờng hoạt động. Một trong những lợi thế lớn của Linux đĩ là nĩ là một hệ điều hành đầy đủ các chức năng, với hỗ trợ cho các mạng đang trở thành một yêu cầu rất quan trọng trong bất kì hệ nhúng nào. Do cĩ thể thêm hoặc bớt từ các mơ đun nhân tại chế độ runtime, nên điều này làm cho Linux rất linh hoạt. Vì Linux là mã nguồn mở nên Linux khơng địi hỏi ngƣời dùng phải trả tiền bản quyền. Yếu tố này đặc biệt quan trong đối với các nhà sản xuất và phát triển các sản phẩm điện tử tiêu dùng vì nĩ sẽ làm giảm giá thành và nâng cao tính cạnh tranh cho các sản phẩm Cấu trúc Embedded Linux Trƣớc hết, để chạy một hệ Linux, phần cứng phải đáp ứng đƣợc đƣợc các yêu cầu sau: thứ nhất, Linux yêu cầu CPU tối thiểu phải là 32 bit, cĩ chứa một đơn vị quản lý bộ nhớ (MMU). Thứ hai, phải đủ bộ nhớ RAM cung cấp cho hệ thống. Thứ ba, vào/ra (I/O) tối thiểu phải đủ cho việc debug. Cuối cùng, nhân phải cĩ khả năng tải hoặc truy cập vào một hệ thống tập tin gốc (root filesystem) thơng qua các thiết bị lƣu trữ cố định hoặc kết nối thêm. Hình 3.2 Cấu trúc Embedded Linux 34
  45. Trong sơ đồ cấu trúc trên, ngay phía trên phần cứng là nhân. Nhân là thành phần lõi của hệ điều hành. Chức năng của nhân là để quản lý phần cứng một cách hiệu quả đồng thời cung cấp giao diện lập trình, qua đĩ các phần mềm sử dụng đƣợc phần cứng thơng qua nhân. Cũng giống nhƣ nhân UNIX, nhân Linux điều khiển thiết bị, quản lý truy cập I/O, kiểm sốt quá trình lập lịch (scheduling), thi hành việc chia sẻ bộ nhớ, xử lý phân phối các tín hiệu, và phục vụ các nhiệm vụ khác. Nĩ cũng cho phép ứng dụng sử dụng các API đƣợc cung cấp bởi một nhân cĩ thể di chuyển đƣợc giữa các cấu trúc khác nhau đƣợc hỗ trợ bởi nhân đĩ với sự thay đổi nhỏ hoặc khơng thay đổi. Điều này thƣờng xuyên đƣợc sử dụng đối với Linux, cĩ thể nhận thấy khối thống nhất của các ứng dụng sẵn cĩ trên tất cả các cấu trúc đƣợc hỗ trợ bởi Linux. Trong nhân, cĩ hai lớp dịch vụ chính cung cấp các chức năng theo yêu cầu của ứng dụng. Tƣơng tác mức thấp (Low-level interfaces) là đặc trƣng riêng cho các cấu hình phần cứng mà trên đĩ nhân chạy và qui định để kiểm sốt trực tiếp tài nguyên phần cứng bằng cách sử dụng một phần cứng độc lập với API. Phía trên dịch vụ mức thấp đƣợc cung cấp bởi nhân, các thành phần mức cao cung cấp các abstractions phổ biến cho tất cả các hệ thống UNIX, bao gồm cả các tiến trình, tập tin, các socket, và tín hiệu. Giữa hai mức độ của abstraction, nhân đơi khi cần phải gọi đến các thành phần phiên dịch (interpretation component) để hiểu và tƣơng tác đƣợc với cấu trúc dữ liệu đi và đến một số thiết bị. chẳng hạn nhƣ hệ thống tập tin và giao thức mạng là những cấu trúc dữ liệu mà nhân cần phải hiểu và tƣơng tác đƣợc để cấp quyền truy cập vào dữ liệu đi và đến. Trong lúc hoạt động bình thƣờng, nhân yêu cầu phải cĩ ít nhất một cấu trúc filesystem đĩ là root filesystem. Từ filesystem này nhân tải các ứng dụng đầu tiên chạy trên hệ thống. Nhân cũng dựa vào filesystem này cho các họat động sau đĩ, chẳng hạn nhƣ tải mơ đun và cung cấp mỗi tiến trình với một thƣ mục làm việc. hệ thống tập tin gốc lƣu trữ và họat động từ thiết bị lƣu trữ thực hoặc tải vào bộ nhớ RAM trong khi khởi động hệ thống và vận hành trên đĩ. Thƣ viện đƣợc sử dụng bởi hầu hết các ứng dụng Linux là thƣ viện GNU C glibc, thƣ viện đƣợc liên kết động với các ứng dụng. Điều này cho phép nhiều ứng dụng cĩ thể sử dụng chung một thƣ viện. Thƣ viện C đƣợc tìm thấy trên filesystem của hệ thống, chẳng hạn cĩ thể tải thƣ viện một lần lên bộ nhớ RAM, các ứng dụng sẽ cùng chia sẻ thƣ viện này. Tuy nhiên trên một số hệ thống nhúng, khi mà chỉ cĩ một phần của thƣ viện đƣợc sử dụng bởi một vài ứng dụng thì việc liên kết tĩnh giữa thƣ viện và ứng dụng sẽ tiết kiệm đƣợc bộ nhớ và đảm bảo đƣợc tính gọn nhẹ của hệ thống. Cơng cụ phát triển Embedded Linux Cũng nhƣ phát triển các phần mềm khác, để phát triển Embedded Linux cũng cần phải cĩ compiler, linker, IDE, interpreter, và các cơng cụ khác. Các cơng cụ để phát triển Embedded Linux cĩ thể tìm thấy dƣới dạng mã nguồn mở, đƣợc cung cấp miễn phí hoặc sử dụng các cơng cụ đƣợc biên soạn bởi các cơng ty, cá nhân. 35
  46. Cross-compiler Một trong những cơng cụ quan trọng đƣợc sử dụng để xây dựng Embedded Linux đĩ là cross-compiler. Cross-compiler là trình biên dịch cho phép biên dịch mã nguồn thành các tập tin thực thi chạy đƣợc ở các mơi trƣờng khác nhau, chứ khơng chỉ mơi trƣờng mà trình biên dịch đang chạy trên đĩ. Nhƣ hình trên mơ tả cross-compiler, cĩ thể thấy rõ để biên dịch từ nền tảng x86 sang ARM thì cần phải cĩ cross-compiler. Trong dự án GNU, cĩ xây dựng bộ cơng cụ GNU Toolchain. Bộ cơng cụ này sử dụng để phát triển các ứng dụng, các phần mềm cho hệ thống nhúng, hệ điều hành chẳng hạn nhƣ Embedded Linux. GNU Toolchain gồm cĩ: GNU make, GNU Compiler (GCC), GNU Binutils, GNU Bison, GNU mp4, GNU Debugger (GDB) và GNU build system (autotools). 3.2.2. Windows CE Windows CE hay Windows Embedded CE là tên một hệ điều hành của Microsoft. Đây là một hệ điều hành nhúng mở, đƣợc sử dụng cho các hệ thống nhúng. Windows CE mở ra khả năng phát triển rất lớn đối với các nhà phát triển ứng dụng bởi nĩ cung cấp rất nhiều bộ cơng cụ lập trình để tạo ra các mã quản lí và các ứng dụng mã máy cho các phần cứng cơ sở của Windows CE. Windows CE cung cấp cho các nhà phát triển ứng dụng một mơi trƣờng API 32 bit của Microsoft cùng với sự dễ dàng sử dụng và sự linh hoạt của ngơn ngữ kịch bản. Đồng thời nĩ cũng hỗ trợ cho các ứng dụng đa phƣơng tiện, Internet, mạng nội bộ (LAN), truyền thơng và các dịch vụ bảo mật Vì vậy nên Windows CE đƣợc ứng dụng rất rộng rãi trên các thiệt bị điện tử cầm tay nhƣ điện thoại, máy chơi trị chơi, máy nghe nhạc và các sản phẩm trong cơng nghiệp nhƣ HMI, PLC. Cấu trúc Windows CE Windows CE là một hệ điều hành thời gian thực, hỗ trợ và chạy trên nhiều bộ xử lý khác nhau bao gồm ARM, MIPS, x86 và SH4. Windows CE cho phép 32000 tiến trình chạy đồng thời. Tuy nhiên, trên thực tế số líợng tiến trình cịn phụ thuộc vào khả năng xử lý của hệ thống Sơ đồ dƣới đây mơ tả cấu trúc của hệ điều hành Windows CE. Trong đĩ: User Processes: Bao gồm các tiến trình riêng biệt tạo nên các ứng dụng ngƣời dùng, chẳng hạn nhƣ ứng dụng đƣợc gọi là user-mode server. Những ứng dụng này gồm cĩ Udevice.exe, Servicesd.exe(là tiến trình tải các dịch vụ chẳng hạn HTTP, FTP,UPnP ). Hệ thống API sẵn cĩ cho các ứng dụng thơng qua thƣ viện coredll.dll, chúng liên kết với tất cả các mơ đun thực thi của hệ điều hành. Bên cạnh đĩ, hệ điều hành cung cấp các ứng dụng API tƣơng tự nhƣ Win32 API trên máy tính để bàn. Ngƣời phát triển cĩ thể sử dụng tính năng truy cập thơng qua thƣ viện ứng dụng, chẳng hạn nhƣ Wininet.dll, Winsock.dll, Msxml.dll, và Winhttp.dll. 36
  47. Nhân( Nhân) : đƣợc mơ tả bởi mơ đun NK.exe là lõi của hệ điều hành Windows CE. Nĩ cung cấp các chức năng cơ bản cho hệ điều hành. Các chức năng này bao gồm việc xử lý cơ sở dữ liệu và quản lý bộ nhớ. nhân cũng cung cấp một số chức năng quản lý tập tin, các dịch vụ cho phép các ứng dụng cĩ thể sử dụng các chức năng của nhân. Cấu trúc Windows CE Phần cứng (Hardware): Nhân của Windows CE tƣơng tác với phần cứng thơng qua các trình điều khiển (driver). Sự kết hợp của lớp tƣơng thích thiết bị gốc(OAL), driver, và các tập tin cấu hình cho một nền tảng phần cứng cụ thể cĩ tên là gĩi hỗ trợ mạch(BSP) Cơng cụ phát triển Windows CE Windows CE bao gồm một bộ cơng cụ hỗ cho việc thiết kế và cấu hình OS images, phát triển các driver, dịch vụ và ứng dụng. Platform builder cho Windows CE 6.0 đƣợc plug-in trên Microsoft Visual Studio 2005(VS2005). Để phát triển Windows CE cần cĩ VS2005 và Platform Builder. Việc sử dụng nền tảng VS2005 làm cơng cụ giúp cho việc phát triển Windows CE đƣợc dễ dàng hơn. Platform Builder đƣợc plug- in trên VS2005 cho phép xây dựng các BSP, tạo ra các driver, xây dựng runtime image và xuất ra các SDK để hỗ trợ phát triển các ứng dụng. 3.2.3. Android Android lần đầu tiên ra mắt vào năm 2007, đƣợc phát triển bởi nhĩm Open Handset Alliance. Android là một hệ điều hành dựa trên nhân Linux (nhân 2.6), các ứng dụng chạy trên máy ảo Java - phiên bản đƣợc thiết kế cho các dịng máy di động cĩ tên Dalvik. Các tính năng mà Android hỗ trợ rất rộng, bao gồm đồ họa 2D, 3D (dựa trên OPENGLES), định vị GPS, Bluetooth, EDGE, 3G, WiFi, hỗ trợ thoại GSM, dữ liệu đƣợc lƣu trữ trong cơ sở dữ liệu SQLite Cấu trúc Android Trong hình dƣới đây cĩ thể thấy rõ bên trong hệ điều hành Android cĩ chứa Nhân Linux. Các thƣ viện là lớp nằm trên Nhân, tiếp đĩ là các framework và lớp trên cùng chính là những ứng dụng. Lớp thƣ viện chính là ngơi nhà để thực hiện các đoạn mã cho các thực thể nhƣ bộ xử lý đa phƣơng tiện dùng để xem/ghi lại âm thanh và hình ảnh, Nhân của trình duyệt Web, tiến trình biên dịch kiểu chữ, và bộ máy cơ sở dữ liệu SQLite. Phần runtime của Android cũng trú ngụ tại lớp thƣ viện. Nằm trên thƣ viện chính là các framework, đĩ là tập hợp các dịch vụ cĩ thể dùng lại đƣợc và những thành phần chung phục vụ cho các ứng dụng. Ví dụ, một loại framework là thành phần cung cấp nội dung cho bất kỳ dịch vụ nào cĩ liên quan đến việc líu trữ và truy xuất dữ liệu. Giao diện ứng dụng trong SQLite chính là một thí dụ cụ thể về phần cung cấp nội dung này. 37
  48. Cấu trúc Android Các ứng dụng chạy ở lớp trên cùng của hệ điều hành với một bộ các nhân ứng dụng bao gồm thƣ điện tử, lịch làm việc, trình duyệt web Khi nhà phát triển viết một ứng dụng dành cho Android, đầu tiên thực hiện các đoạn mã trong mơi trƣờng Java. Sau đĩ, nĩ sẽ đƣợc biên dịch sang các bytecode của Java, tuy nhiên để thực thi đƣợc ứng dụng này trên Android thì nhà phát triển phải thực thi một cơng cụ cĩ tên là dx. Đây là cơng cụ dùng để chuyển đổi bytecode sang một dạng gọi là dex bytecode. "Dex" là từ viết tắt của "Dalvik executable" đĩng vai trị nhƣ cơ chế ảo thực thi các ứng dụng Android. Máy ảo Dalvik cũng giống nhƣ máy ảo Java (Java Virtual Machine) Cơng cụ phát triển Android Phiên bản Europa của Eclipse là nền tảng phát triển các ứng dụng. Ngồi ra, cần cài đặt ít nhất một bộ JDK 5 hoặc JDK 6 để cĩ thể sử dụng các cơng cụ của Android. Tuy nhiên, cũng khơng bắt buộc phải dùng Eclipse để phát triển Android. Bên cạnh đĩ, Android SDK cung cấp các cơng cụ cho phép sử dụng các IDE khác. Ví dụ IDE IntelliJ đƣợc đề cập chi tiết trong tài liệu mơ tả của Android. Những nhà phát triển nhân cứng sẽ cảm thấy thoải mái khi làm việc với bộ cơng cụ command-line đi kèm SDK. Chẳng hạn, cơng cụ activityCreator (đƣợc cung cấp nhƣ là một tập tin batch file dành cho Windows và đĩng vai trị nhƣ một script Python cho ngƣời dùng Mac và Linux) sẽ xây dựng framework cho các ứng dụng của Android. Việc thực thi activityCreator sẽ dựng lên các tập tin Java nịng cốt, từ đĩ sẽ tạo ra những thƣ mục con và các tập tin XML cần thiết. Cơng cụ này cũng hình thành một tập tin Ant dùng cho việc biên dịch mã nguồn và tạo các ứng dụng. Những cơng cụ command-line khác trong SDK bao gồm logCat dùng để xuất các thơng điệp ghi nhận tình trạng hệ thống. logCat rất hữu dụng trong việc ghi nhận thời điểm xảy ra lỗi. Nếu cần phân tích các lỗi một cách sâu hơn cĩ thể dẫn nhập một class debug đặc biệt vào ứng dụng. Class này sẽ cung cấp các cách thức để bắt đầu và dừng việc tìm kiếm dấu vết. Khi ở trạng thái hoạt động, debug sẽ ghi nhận các sự kiện thành một tập tin, mà sau đĩ cĩ thể đƣợc kiểm tra bằng ứng dụng TraceView. Android Emulator Cuối cùng là bộ mơ phỏng Android, khi đƣợc khởi động nĩ sẽ hiển thị tồn bộ giao diện bao gồm cả các nút bấm và bàn phím QWERTY. Nĩ cĩ thể hoạt động tốt tƣơng tự nhƣ thiết bị thật dù cho các một vài giới hạn (ví dụ nhƣ khơng nhận đƣợc cuộc gọi đến). Bộ mơ phỏng Android chạy một phiên bản đã đƣợc sửa đổi của mơi trƣờng giả lập mã nguồn mở thuộc Fabrice Bellard, cĩ tên là QEMU. Phiên bản này giả lập bộ xử lý ARM và thực thi hệ điều hành Linux. 38
  49. 3.3. Lập trình C/C++ trên Linux 3.3.1 Linux và các lệnh cơ bản Các khái niệm cơ bản - Users (Người dùng): Để cĩ thể sử dụng đƣợc Linux, bạn phải đƣợc cấp tài khoản (account) đăng nhập vào máy Linux. Thơng tin về tài khoản bao gồm tên đăng nhập (username), mật khẩu đăng nhập (password), và các quyền truy xuất tập tin và thƣ mục mà bạn cĩ đƣợc dựa vào tài khoản mà bạn đăng nhập và máy. - Group (Nhĩm): Các ngƣời dùng làm việc trên cùng một bộ phận hoặc đang làm việc chung trên cùng một dự án (project) cĩ thể đƣợc đƣa vào cùng một nhĩm. Đây là một cách đơn giản của việc tổ chức để quản lí ngƣời dùng. - File (Tập tin): Tất cả các thơng tin trên Linux đƣợc lƣu giữ trong các tập tin. Các tập tin đƣợc tạo ra bởi ngƣời dùng và ngƣời chủ tập tin cĩ quyền truy xuất, tạo, sửa đổi, thiết lập kích thƣớc của tập tin và phân phối quyền để cho phép ngƣời dùng khác cĩ thể truy xuất tập tin. - Directory (Thư mục): Thƣ mục giống nhƣ Folder trong Windows. Nĩ đƣợc dùng để chứa các tập tin và thƣ mục khác, và tạo ra cấu trúc cho hệ thống tập tin. Dƣới Linux, chỉ cĩ một cây thƣ mục và gốc của nĩ là /. Giống nhƣ tập tin, mỗi thƣ mục cĩ thơng tin kết hợp với nĩ, kích thƣớc tối đa và những ngƣời dùng đƣợc quyền truy xuất thƣ mục này, - Path (Đường dẫn): Đƣờng dẫn là 1 chuỗi các thƣ mục và cĩ thể kết thúc bằng tên của một tập tin. Các thƣ mục và tên tập tin đƣợc phân cách bởi kƣ tự /. Ví dụ : /dir1/dir2/file là một đƣờng dẫn tuyệt đối tới file đƣợc chứa trong dir2, với dir2 đƣợc chứa trong dir1, và dir1 nằm trong thƣ mục gốc. Ví dụ khác: ~/homework là một đƣờng dẫn tƣơng đối, tính từ thƣ mục đăng nhập của ngƣời dùng, vào thƣ mục homework. - Permissions (Quyền): Quyền là một đặc tính quan trọng của Linux. Chúng tạo ra sự bảo mật bằng cách giới hạn các hành động mà ngƣời dùng cĩ thể thực hiện đối với tập tin và thƣ mục. Các quyền đọc (read), ghi (write) và thực thi (execute) điều khiển việc truy xuất tới việc truy xuất tập tin của ngƣời tạo ra nĩ, nhĩm và các ngƣời dùng khác. Một ngƣời dùng sẽ khơng thể truy xuất tới tập tin của ngƣời dùng khác nếu khơng cĩ đủ quyền truy xuất. - Process (Tiến trình): Khi ngƣời dùng thực thi một lệnh, Linux tạo ra một tiến trình chứa các chỉ thị lệnh. Một tiến trình cịn chứa các thơng tin điều khiển nhƣ thơng tin ngƣời dùng thực thi lệnh, định danh duy nhất của tiến trình (PID – process id). Việc quản lí của tiến trình dựa trên PID này. - Shell: Trong chế độ console, ngƣời dùng giao tiếp với máy thơng qua shell (hệ vỏ). Một shell là một chƣơng trình thƣờng đƣợc dùng để bắt đầu một chƣơng trình khác từ dấu nhắc của shell. Một shell đƣợc cấu hình bằng việc thiết lập các biến mơi trƣờng cho nĩ. Khi đăng nhập vào Linux, một shell sẽ đƣợc tự động tạo ra, và các biến 39
  50. mơi trƣờng mặc nhiên (default) sẽ đƣợc thiết lập. Ở đây, ta sẽ sử dụng shell BASH (Bourne Again SHell), là shell thơng dụng của hầu hết các hệ thống Linux. Thực thi Lệnh - Nhập lệnh: Để nhập lệnh, đơn giản bạn chỉ đánh vào tên của lệnh sau dấu nhắc của shell rồi nhấn Enter. Dấu nhắc của shell thƣờng cĩ dạng [user@host directory]$, nĩ cĩ thể đƣợc thiết lập lại, và cĩ thể khác nhau đối với các máy khác nhau. Hầu hết các lệnh thƣờng chấp nhận nhiều đối số (argument) hoặc lựa chọn (option) (thƣờng đƣợc gọi là flag – cờ). Thơng thƣờng các đối số đƣợc đƣa vào bằng cách sử dụng 1 hoặc 2 dấu -. Nếu một lệnh yêu cầu đối số và chúng ta khơng đƣa vào, lệnh sẽ tự động hiển thị một mơ tả ngắn về cách sử dụng các đối số kết hợp với nĩ. Một lệnh và các đối số thƣờng cĩ dạng nhƣ sau: command –a1 –a2 command long_argument_name - Biến mơi trường PATH: Đây là biến mơi trƣờng của shell mà cho phép các thƣ mục mà Linux cĩ thể nhìn thấy đƣợc khi thực thi lệnh nếu đƣờng dẫn đầy đủ của lệnh khơng đƣợc chỉ định rõ ràng. Biến mơi trƣờng PATH bao gồm 1 chuỗi tên các đƣờng dẫn thƣ mục, phân cách bởi dấu „:‟. Hầu hết các lệnh mà chúng ta sẽ thực hành đều nằm trong các thƣ mục mà đã đƣợc đƣa vào biến mơi trƣờng PATH và cĩ thể thực hiện đơn giản bằng cách nhập tên của nĩ tại dấu nhắc lệnh. Vìlí do bảo mật, thƣ mục hiện hành sẽ khơng đƣợc đƣa vào biến mơi trƣờng PATH, do đĩ, để chạy một chƣơng trình nằm trong thƣ mục hiện hành, chúng ta phải thêm „./‟ vào trƣớc tên chƣơng trình: ./command Một số lệnh cơ bản - Gọi sự trợ giúp: Hầu hết các console Linux đều chứa một chƣơng trình tiện ích nhỏ để in ra màn hình thơng tin về cách sử dụng lệnh khi một cờ „-h‟ hoặc „ help‟ đƣợc truyền vào cho chúng. Ngồi ra, chúng ta cĩ thể sử dụng lệnh man (manual) để tìm hiểu về một lệnh. command –h Hiển thị thơng tin trợ giúp ngắn gọn về lệnh. command -–help Hiển thị thơng tin trợ giúp ngắn gọn về lệnh. man command Hiển thị trang trợ giúp đầy đủ của lệnh. - Các lệnh liệt kê tập tin (file): Một trong những tác vụ cơ bản mà chúng ta cĩ thể thực hiện là liệt kê các tập tin nằm trong một thƣ mục với lệnh „ls‟ Lệnh này cho phép kiểm tra nội dung của thƣ mục và tìm kiếm tập tin mà chúng ta muốn làm việc. Nếu các tập tin liệt kê tràn quá một màn hình, chúng ta cĩ thể kết hợp với đƣờng ống (pipe) để xuất kết quả của lệnh „ls‟ đến một chƣơng trình hiển thị văn bản nhƣ „less‟ chẳng hạn. ls Liệt kê nội dung của thƣ mục hiện hành. ls –a Liệt kê tất cả tập tin, kể cả các tập tin cĩ thuộc tính ẩn. 40
  51. ls –l Hiển thị đầy đủ các thơng tin (quyền truy cập, chủ, kích thƣớc, ) ls | less - Thay đổi thư mục: Khi bạn đăng nhập vào Linux, chúng ta đƣợc tự động đặt vào thƣ mục tiếp nhận (home directory) của chúng ta. Để chuyển tới thƣ mục khác, dùng lệnh „cd‟. Lệnh „cd‟ nhận đối số là một đƣờng dẫn tƣơng đối hoặc tuyệt đốicủa thƣ mục hiện hành, hoặc một số các đối số đặc biệt nhƣ dƣới đây: cd path Chuyển đến thƣ mục đƣợc chỉ định bởi path. cd ~ Chuyển về thƣ mục nhà. cd - Chuyển về thƣ mục trƣớc của bạn. cd Chuyển về thƣ mục cha của thƣ mục hiện hành. - Quản lí tập tin và thư mục: cp Cho phép tạo ra một bản sao (copy) của một tập tin hoặc thƣ mục: cp source_path destination_path mkdir Cho phép tạo ra một thƣ mục mới (make directory), rỗng, tại vị trí đƣợc chỉ định: mkdir directoryname mv Cho phép di chuyển (move) một tập tin từ thƣ mục này tới thƣ mục khác, cĩ thể thực hiện việc đổi tên tập tin: mv source_path destination_path rm Cho phép xĩa (remove) các tập tin, dùng lệnh „rm – R‟ để xĩa một thƣ mục và tất cả những gì nằm trong nĩ: rm filename rmdir Dùng để xĩa thƣ mục: rmdir directoryname touch Tạo tập tin trống: touch filename - Xác định vị trí của tập tin: Khi các tập tin của chúng ta nằm trên nhiều thƣ mục, hoặc chúng ta cần tìm kiếm một tập tin nào đĩ, chúng ta cĩ thể sử dụng lệnh „find‟ và „locate‟. Lệnh „find‟ bắt đầu từ thƣ mục đƣợc chỉ định và sẽ tìm trong tất cả các thƣ mục con trong đĩ. Lệnh „locate‟ thì tạo ra và duy trì một cơ sở dữ liệu về các tập tin trong hệ thống, và nĩ đơn giản chỉ tìm trong cơ sở dữ liệu này xem cĩ tập tin cần tìm. Lệnh „locate‟ thực hiện nhanh hơn lệnh „find‟, nhƣng cơ sở dữ liệu của nĩ chỉ cập nhật một lần trong ngày nên những tập tin mới đƣợc tạo ra cĩ thể khơng đƣợc tìm thấy. find Tìm tập tin filename bắt đầu từ thƣ mục path: find path –name filename locate Tìm tập tin trong cơ sở dữ liệu của nĩ cĩ tên là filename: locate filename - Làm việc với tập tin văn bản: cat Để xem nội dung của một tập tin văn bản ngắn, chúng ta dùng lệnh „cat‟ để in nĩ ra màn hình: cat filename 41
  52. less Cho phép xem một tập tin dài bằng cách cuộn lên xuống bằng các phím mũi tên và các phím pageUp, pageDown. Dùng phím q để thốt chế độ xem: less filename grep Một cơng cụ mạnh để tìm một chuỗi trong một tập tin văn bản. Khi lệnh „grep‟ tìm thấy chuỗi, nĩ sẽ in ra cả dựng đĩ lên màn hình: grep string filename sort Sắp xếp các dựng trong tập tin theo thứ tự alphabet và in nội dung ra màn hình: sort filename - Giải nén: bunzip2 Giải nén một tập tin bzip2 (*.bz2). Thƣờng dùng cho các tập tin lớn: bunzip2 filename.bz2 gunzip Giải nén một tập tin gzipped (*.gz): gunzip filename.gz unzip Giải nén một tập tin PkZip hoặc WinZip (*.zip): unzip filename.zip tar Nén và giải nén các tập tin .tar, .tar.gz: Ví dụ: tar –xvf filename.tar và tar –xvzf filename.tar.gz - Xem thơng tin hệ thống: Các lệnh sau đây hiển thị các thơng tin khác trên hệ thống của chúng ta. date In ngày giờ hệ thống. df –h In thơng tin khơng gian đĩa đƣợc dùng. free In thơng tin bộ nhớ đƣợc dùng. history Hiển thị các lệnh đƣợc thực hiện bởi tài khoản hiện tại. hostname In tên của máy cục bộ (host). pwd In đƣờng dẫn đến thƣ mục làm việc hiện hành. rwho -a Liệt kê tất cả ngƣời dùng đã đăng nhập vào network. uptime In thời gian kể từ lần reboot gần nhất. who Liệt kê tất cả ngƣời dùng đã đăng nhập vào máy. whoami In tên ngƣời dùng hiện hành. - Các lệnh dùng theo dơi tiến trình: ps Liệt kê các tiến trình đang kích hoạt bởi ngƣời dùng và PID của các tiến trình đĩ. ps –aux Liệt kê các tiến trình đang kích hoạt cùng với tên của ngƣời dùng là chủ tiến trình. top Hiển thị danh sách các tiến trình đang kích hoạt, danh sách này đƣợc cập nhật liên tục. 42
  53. command & Chạy command trong nền. fg Đẩy một tiến trình nền hoặc bị dừng lên bề mặt trở lại. bg Chuyển một tiến trình vào nền. Cĩ thể thực hiện tƣơng tự với Ctrl-z. kill pid Thúc đẩy tiến trình kết thúc. Đầu tiên phải xác định pid của tiến trình cần hủy với lệnh ps. killall -9 name Hủy tiến trình với name chỉ định. nice program level Chạy program với cấp ƣu tiên ngƣợc level. Cấp nice càng cao, chƣơng trình càng cĩ mức ƣu tiên thấp 3.3.2 Chƣơng trình trên Linux Để cĩ thể viết chƣơng trình trên Linux, chúng ta cần phải nắm rõ 1 số vị trí tài nguyên để xây dựng chƣơng trình nhƣ trình biên dịch, tập tin thƣ viện, các tập tin tiêu đề (header), các tập tin chƣơng trình sau khi biên dịch, Trình biên dịch gcc thƣờng đƣợc đặt trong thƣ mục /usr/bin hoặc /usr/local/bin (kiểm tra bằng lệnh which gcc). Tuy nhiên, khi biên dịch, gcc cần đến rất nhiều tập tin hỗ trợ nằm trong những thƣ mục khác nhau nhƣ những tập tin tiêu đề (header) của C thƣờng nằm trong thƣ mục /usr/include hay /usr/local/include. Các tập tin thƣ viện liên kết thƣờng đƣợc gcc tìm trong thƣ mục /lib hoặc /usr/local/lib. Các thƣ viện chuẩn của gcc thƣờng đặt trong thƣ mục /usr/lib/gcc-lib. Chƣơng trình sau khi biên dịch ra tập tin thực thi (dạng nhị phân) cĩ thể đặt bất cứ vị trí nào trong hệ thống. Các tập tin tiêu đề (header) Các tập tin tiêu đề trong C thƣờng định nghĩa hàm và khai báo cần thiết cho quá trình biên dịch. Hầu hết các chƣơng trình trên Linux khi biên dịch sử dụng các tập tin tiêu đề trong thƣ mục /usr/include hoặc các thƣ mục con bên trong thƣ mục này, ví dụ: /usr/include/sys. Một số khác đƣợc trình biên dịch dị tìm mặc định nhƣ /usr/include/X11 đối với các khai báo hàm lập trình đồ họa X-Window, hoặc /usr/include/g++-2 đối với trình biên dịch GNU g++. Tuy nhiên, nếu chúng ta cĩ các tập tin tiêu đề của riêng mình trong một thƣ mục khác thƣ mục mặc định của hệ thống thì chúng ta cĩ thể chỉ rõ tƣờng minh đƣờng dẫn đến thƣ mục khi biên dịch bằng tùy chọn –I, ví dụ: $ gcc –I/usr/mypro/include test.c –otest Khi chúng ta sử dụng một hàm nào đĩ của thƣ viện hệ thống trong chƣơng trình C, ngồi việc phải biết khai báo nguyên mẫu của hàm, chúng ta cần phải biết hàm này đƣợc định nghĩa trong tập tin tiêu đề nào. Trình man sẽ cung cấp cho chúng ta các thơng tin này rất chi tiết. Ví dụ, khi dùng man để tham khảo thơng tin về hàm kill(), chúng ta sẽ thấy rằng cần phải khai báo 2 tập tin tiêu đề là types.h và signal.h. 43
  54. Các tập tin thƣ viện Các tập tin tiêu đề của C chỉ cần thiết để trình biên dịch bắt lỗi cú pháp, kiểm tra kiểu dữ liệu của chƣơng trình và tạo ra các tập tin đối tƣợng. Muốn tạo ra chƣơng trình thực thi, chúng ta cần phải cĩ các tập tin thƣ viện. Trong Linux, các tập tin thƣ viện tĩnh của C cĩ phần mở rộng là .a, .so, .sa và bắt đầu bằng tiếp đầu ngữ lib. Ví dụ libutil.a hay libc.so là tên các thƣ viện liên kết trong Linux. Linux cĩ hai loại liên kết là liên kết tĩnh (static) và liên kết động (dynamic). Thƣ viện liên kết động trên Linux thƣờng cĩ phần mở rộng là .so, chúng ta cĩ thể dùng lệnh ls /usr/lib hoặc ls /lib để xem các thƣ viện hệ thống đang sử dụng. Khi biên dịch, thơng thƣờng trình liên kết (ld) sẽ tìm thƣ viện trong 2 thƣ viện chuẩn /usr/lib và /lib. Để chỉ định tƣờng minh một thƣ viện nào đĩ, chúng ta làm nhƣ sau: $ gcc test.c –otest /usr/lib/libm.a Bởi vì thƣ viện bắt buộc phải cĩ tiếp đầu ngữ lib và cĩ phần mở rộng là .a hoặc .so, trình biên dịch cho phép chúng ta sử dụng tùy chọn –l ngắn gọn nhƣ sau: $ gcc test.c –otest -lm chúng ta sẽ thấy rằng gcc sẽ mở rộng –l thành tiếp đầu ngữ lib và tìm libm.a hoặc libm.so trong thƣ mục chuẩn để liên kết. Mặc dù vậy, khơng phải lúc nào thƣ viện của chúng ta cũng phải nằm trong thƣ viện của Linux. Nếu thƣ viện của chúng ta nằm ở một thƣ mục khác, chúng ta cĩ thể chỉ định gcc tìm kiếm trực tiếp với tùy chọn –L nhƣ sau: $ gcc test.c –otest -L/usr/myproj/lib -ltool Lệnh trên cho phép liên kết với thƣ viện libtool.a hoặc libtool.so trong thƣ mục /usr/myproj/lib. Thƣ viện liên kết trên Linux Hình thức đơn giản nhất của thƣ viện là tập hợp các tập tin .o do trình biên dịch tạo ra ở bƣớc biên dịch với tùy chọn –c. Ví dụ $gcc –c helloworld.c trình biên dịch chƣa tạo ra tập tin thực thi mà tạo ra tập tin đối tƣợng helloworld.o. Tập tin này chứa các mã máy của chƣơng trình đã đƣợc sắp xếp lại. Nếu muốn tạo ra tập tin thực thi, chúng ta gọi trình biên dịch thực hiện bƣớc liên kết: $gcc helloworld.o –o helloworld Trình biên dịch sẽ gọi tiếp trình liên kết ld tạo ra định dạng tập tin thực thi cuối cùng. Ở đây, nếu chúng ta khơng sử dụng tùy chọn –c, trình biên dịch sẽ thực hiện cả hai bƣớc đồng thời. 44
  55. Thư viện liên kết tĩnh Thƣ viện liên kết tĩnh là các thƣ viện khi liên kết trình biên dịch sẽ lấy tồn bộ mã thực thi của hàm trong thƣ viện đƣa vào chƣơng trình chính. Chƣơng trình sử dụng thƣ viện liên kết tĩnh chạy độc lập với thƣ viện sau khi biên dịch xong. Nhƣng khi nâng cấp và sửa đổi, muốn tận dụng những chức năng mới của thƣ viện thì chúng ta phải biên dịch lại chƣơng trình. Ví dụ sử dụng liên kết tĩnh: /* cong.c */ int cong( int a, int b ) { return a + b; } /* nhan.c */ long nhan( int a, int b ) { return a * b; } Thực hiện biên dịch để tạo ra hai tập tin thƣ viện đối tƣợng .o $ gcc –c cong.c nhan.c Để một chƣơng trình nào đĩ gọi đƣợc các hàm trong thƣ viện trên, chúng ta cần tạo một tập tin header .h khai báo các nguyên mẫu hàm để ngƣời sử dụng triệu gọi: /* lib.h */ int cong( int a, int b ); long nhan( int a, int b ); Cuối cùng, tạo ra chƣơng trình chính program.c triệu gọi hai hàm này. /* program.c */ #include #include "lib.h" int main () { int a, b; 45
  56. printf( "Nhap vào a : " ); scanf( "%d", &a ); printf("Nhap vào b : " ); scanf( "%d", &b ); printf( "Tổng %d + %d = %d\n", a, b, cong( a, b ) ); printf( "Tich %d * %d = %ld\n", a, b, nhan( a, b ) ); return ( 0 ); } - Chúng ta biên dịch và liên kết với chƣơng trình chính nhƣ sau: $ gcc –c program.c $ gcc program.o cong.o nhan.o -oprogram Sau đĩ thực thi chƣơng trình $ ./program Ở đây .o là các tập tin thƣ viện đối tƣợng. Các tập tin thƣ viện .a là chứa một tập hợp các tập tin .o. Tập tin thƣ viện .a thực ra là 1 dạng tập tin nén đƣợc tạo ra bởi chƣơng trình ar. Chúng ta hãy yêu cầu ar đĩng cong.o và nhan.o vào libfoo.a $ ar cvr libfoo.a cong.o nhan.o Sau khi đã cĩ đƣợc thƣ viện libfoo.a, chúng ta liên kết lại với chƣơng trình theo cách sau: $ gcc program.o –oprogram libfoo.a Chúng ta cĩ thể sử dụng tùy chọn –l để chỉ định thƣ viện khi biên dịch thay cho cách trên. Tuy nhiên libfoo.a khơng nằm trong thƣ mục thƣ viện chuẩn, cần phải kết hợp với tùy chọn –L để chỉ định đƣờng dẫn tìm kiếm thƣ viện trong thƣ mục hiện hành. Dƣới đây là cách biên dịch: $ gcc program.c –oprogram –L –lfoo Chúng ta cĩ thể sử dụng lệnh nm để xem các hàm đã biên dịch sử dụng trong tập tin chƣơng trình, tập tin đối tƣợng .o hoặc tập tin thƣ viện .a. Ví dụ: $ nm cong.o Thư viện liên kết động Khuyết điểm của thƣ viện liên kết tĩnh là nhúng mã nhị phân kèm theo chƣơng trình khi biên dịch, do đĩ tốn khơng gian đĩa và khĩ nâng cấp. Thƣ viện liên kết động đƣợc dùng để giải quyết vấn đề này. Các hàm trong thƣ viện liên kết động khơng trực tiếp đƣa vào chƣơng trình lúc biên dịch và liên kết, trình liên kết chỉ lƣu thơng tin tham chiếu đến các hàm trong thƣ viện liên kết động. Vào lúc chƣơng trình nhị phân thực thi, Hệ Điều Hành sẽ nạp các chƣơng trình liên kết cần tham chiếu vào bộ nhớ. 46
  57. Nhƣ vậy, nhiều chƣơng trình cĩ thể sử dụng chung các hàm trong một thƣ viện duy nhất. - Tạo thư viện liên kết động: Khi biên dịch tập tin đối tƣợng để đƣa vào thƣ viện liên kết động, chúng ta phải thêm tùy chọn –fpic (PIC- Position Independence Code – mã lệnh vị trí độc lập). Ví dụ: biên dịch lại 2 tập tin cong.c và nhan.c $ gcc –c –fpic cong.c nhan.c Để tạo ra thƣ viện liên kết động, chúng ta khơng sử dụng trình ar nhƣ với thƣ viện liên kết tĩnh mà dùng lại gcc với tùy chọn –shared. $ gcc –shared cong.o nhan.o -olibfoo.so Nếu tập tin libfoo.so đã cĩ sẵn trƣớc thì khơng cần dùng đến tùy chọn –o $ gcc –shared cong.o nhan.o libfoo.so Bây giờ chúng ta đã cĩ thƣ viện liên kết động libfoo.so. Biên dịch lại chƣơng trình nhƣ sau: $ gcc program.c –oprogram –L. –lfoo - Sử dụng thư viện liên kết động: Khi Hệ Điều Hành nạp chƣơng trình program, nĩ cần tìm thƣ viện libfoo.so ở đâu đĩ trong hệ thống. Ngồi các thƣ mục chuẩn, Linux cịn tìm thƣ viện liên kết động trong đƣờng dẫn của biến mơi trƣờng LD_LIBRARY_PATH. Do libfoo.so đặt trong thƣ mục hiện hành, khơng nằm trong các thƣ mục chuẩn nên ta cần đƣa thƣ mục hiện hành vào biến mơi trƣờng LD_LIBRARY_PATH: $ LD_LIBRARY_PATH=.: $ export LD_LIBRARY_PATH Kiểm tra xem Hệ Điều Hành cĩ thể tìm ra tất cả các thƣ viện liên kết động mà chƣơng trình sử dụng hay khơng: $ ldd program rồi chạy chƣơng trình sử dụng thƣ viện liên kết động này: $./program Một khuyết điểm của việc sử dụng thƣ viện liên kết động đĩ là thƣ viện phải tồn tại trong đƣờng dẫn để Hệ Điều Hành tìm ra khi chƣơng trình đƣợc triệu gọi. Nếu khơng tìm thấy thƣ viện, Hệ Điều Hành sẽ chấm dứt ngay chƣơng trình cho dù các hàm trong thƣ viện chƣa đƣợc sử dụng. Ta cĩ thể chủ động nạp và gọi các hàm trong thƣ viện liên kết động mà khơng cần nhờ vào Hệ Điều Hành bằng cách gọi hàm liên kết muộn. 47
  58. 3.3.3 Xử lý tiến trình trong linux Khái quát Một trong những đặc điểm nổi bật của Linux là khả năng chạy đồng thời nhiều chƣơng trình. Hệ Điều Hành xem mỗi đơn thể mã lệnh mà nĩ điều khiển là tiến trình (process). Một chƣơng trình cĩ thể bao gồm nhiều tiến trình kết hợp với nhau. Đối với Hệ Điều Hành, các tiến trình cùng hoạt động chia sẻ tốc độ xử lí của CPU, cùng dùng chung vùng nhớ và tài nguyên hệ thống khác. Các tiến trì . Một chƣơng trình của chúng ta nếu mở rộng dần ra, sẽ cĩ lúc cần phải tách ra thành nhiều tiến trình để xử lí những cơng việc độc lập với nhau. Các lệnh của Linux thực tế là những lệnh riêng lẻ cĩ khả năng kết hợp và truyền dữ liệu cho nhau thơng qua các cơ chế nhƣ : đƣờng ống pipe, chuyển hƣớng xuất nhập (redirect), phát sinh tín hiệu (signal), Chúng đƣợc gọi là cơ chế giao tiếp liên tiến trình (IPC – Inter Process Comunication). Đối với tiến trình, chúng ta sẽ tìm hiểu cách tạo, hủy, tạm dừng tiến trình, đồng bộ hĩa tiến trình và giao tiếp giữa các tiến trình với nhau. Xây dựng ứng dụng trong mơi trƣờng đa tiến trình nhƣ Linux là cơng việc khĩ khăn. Khơng nhƣ mơi trƣờng đơn nhiệm, trong mơi trƣờng đa nhiệm tiến trình cĩ tài nguyên rất hạn hẹp. Tiến trình của chúng ta khi hoạt động phải luơn ở trạng thái tơn trọng và sẵn sàng nhƣờng quyền xử lí CPU cho các tiến trình khác ở bất kỳ thời điểm nào, khi hệ thống cĩ yêu cầu. Nếu tiến trình của chúng ta đƣợc xây dựng khơng tốt, khi đổ vỡ và gây ra lỗi, nĩ cĩ thể làm treo các tiến trình khác trong hệ thống hay thậm chí phá vỡ (crash) Hệ Điều Hành. Định nghĩa của tiến trình: là một thực thể điều khiển đoạn mã lệnh cĩ riêng một khơng gian địa chỉ, cĩ ngăn xếp stack riêng rẽ, cĩ bảng chứa các thơng số mơ tả file đƣợc mở cùng tiến trình và đặc biệt cĩ một định danh PID (Process Identify) duy nhất trong tồn bộ hệ thống vào thời điểm tiến trình đang chạy. Nhƣ chúng ta đã thấy, tiến trình khơng phải là một chƣơng trình (tuy đơi lúc một chƣơng trình đơn giản chỉ cấn một tiến trình duy nhất để hồn thành tác vụ, trong trƣờng hợp này thì chúng ta cĩ thể xem tiến trình và chƣơng trình là một). Rất nhiều tiến trình cĩ thể thực thi trên cùng một máy với cùng một Hệ Điều Hành, cùng một ngƣời dùng hoặc nhiều ngƣời dùng đăng nhập khác nhau. Ví dụ shell bash là một tiến trình cĩ thể thực thi lệnh ls hay cp. Bản thân ls, cp lại là những tiến trình cĩ thể hoạt động tách biệt khác. Trong Linux, tiến trình đƣợc cấp khơng gian địa chỉ bộ nhớ phẳng là 4GB. Dữ liệu của tiến trình này khơng thể đọc và truy xuất đƣợc bởi các tiến trình khác. Hai tiến trình khác nhau khơng thể xâm phạm biến của nhau. Tuy nhiên, nếu chúng ta muốn chia sẻ dữ liệu giữa hai tiến trình, Linux cĩ thể cung cấp cho chúng ta một vùng khơng gian địa chỉ chung để làm điều này. 48
  59. Cách hoạt động của tiến trình Khi 1 chƣơng trình đang chạy từ dựng lệnh, chúng ta cĩ thể nhấn phím Ctrl+z để tạm dùng chƣơng trình và đƣa nĩ vào hoạt động phía hậu trƣờng (background). Tiến trình của Linux cĩ các trạng thái: - Đang chạy (running) : đây là lúc tiến trình chiếm quyền xử lí CPU dùng tính tốn hay thực các cơng việc của mình. -Chờ (waiting) : tiến trình bị Hệ Điều Hành tƣớc quyền xử lí CPU, và chờ đến lƣợt cấp phát khác. -Tạm dừng (suspend) : Hệ Điều Hành tạm dừng tiến trình. Tiến trình đƣợc đƣa vào trạng thái ngủ (sleep). Khi cần thiết và cĩ nhu cầu, Hệ Điều Hành sẽ đánh thức (wake up) hay nạp lại mã lệnh của tiến trình vào bộ nhớ. Cấp phát tài nguyên CPU để tiến trình tiếp tục hoạt động. Trên dựng lệnh, thay vì dùng lệnh Ctrl+z, chúng ta cĩ thể sử dụng lệnh bg để đƣa một tiến trình vào hoạt động phía hậu trƣờng. Chúng ta cũng cĩ thể yêu cầu 1 tiến trình chạy nền bằng cú pháp &. Ví dụ: $ls –R & Lệnh fg sẽ đem tiến trình trở về hoạt động ƣu tiên phía trƣớc. Thực tế khi chúng ta đăng nhập vào hệ thống và tƣơng tác trên dựng lệnh, cũng là lúc chúng ta đang ở trong tiến trình shell của bash. Khi gọi một lệnh cĩ nghĩa là chúng ta đã yêu cầu bash tạo thêm một tiến trình con thực thi khác. Về mặt lập trình, chúng ta cĩ thể dùng lệnh fork() để nhân bản tiến trình mới từ tiến trình cũ. Hoặc dùng lệnh system() để triệu gọi một tiến trình của Hệ Điều Hành. Hàm exec() cũng cĩ khả năng tạo ra tiến trình mới khác. Cấu trúc tiến trình Chúng ta hãy xem Hệ Điều Hành quản lí tiến trình nhƣ thế nào? Nếu cĩ hai ngƣời dùng: user1 và user2 cùng đăng nhập vào chạy chƣơng trình grep đồng thời, thực tế, Hệ Điều Hành sẽ quản lí và nạp mã của chƣơng trình grep vào hai vùng nhớ khác nhau và gọi mỗi phân vùng nhƣ vậy là tiến trình. Hình sau cho thấy cách phân chia chƣơng trình grep thành hai tiến trình cho hai ngƣời khác nhau sử dụng Trong hình này, user1 chạy chƣơng trình grep tìm chuỗi abc trong tập tin file1. $grep abc file1 user2 chạy chƣơng trình grep và tìm chuỗi cde trong tập tin file2. $grep cde file2 Chúng ta cần ta cần nhớ là hai ngƣời dùng user1 và user2 cĩ thể ở hai máy tính khác nhau đăng nhập vào máy chủ Linux và gọi grep chạy đồng thời. Hình trên là hiện trạng khơng gian bộ nhớ Hệ Điều Hành Linux khi chƣơng trình grep phục vụ ngƣời dùng. 49
  60. Nếu dùng lệnh ps, hệ thống sẽ liệt kê cho chúng ta thơng tin về các tiến trình mà Hệ Điều Hành đang kiểm sốt, Ví dụ: $ps –af Mỗi tiến trình đƣợc gán cho một định danh để nhận dạng gọi là PID (process identify). PID thƣờng là số nguyên dƣơng cĩ giá trị từ 2-32768. Khi một tiến trình mới yêu cầu khởi động, Hệ Điều Hành sẽ chọn lấy một số (chƣa bị tiến trình nào đang chạy chiếm giữ) trong khoảng số nguyên trên và cấp phát cho tiến trình mới. Khi tiến trình chấm dứt, hệ thống sẽ thu hồi số PID để cấp phát cho tiến trình khác trong lần sau. PID bắt đầu từ giá trị 2 bởi vì giá trị 1 đƣợc dành cho tiến trình đầu tiên gọi là init. Tiến trình init đƣợc và chạy ngay khi chúng ta khởi động Hệ Điều Hành. init là tiến trình quản lí và tạo ra mọi tiến trình con khác. Ở ví dụ trên, chúng ta thấy lệnh ps –af sẽ hiển thị 2 tiến trình grep chạy bởi user1 và user2 với số PID lần lƣợt là 101 và 102. Mã lệnh thực thi của lệnh grep chứa trong tập tin chƣơng trình nằm trên đĩa cứng đƣợc Hệ Điều Hành nạp vào vùng nhớ. Nhƣ chúng ta đã thấy ở lƣợc đồ trên, mỗi tiến trình đƣợc Hệ Điều hành phân chia rõ ràng: vùng chứa mã lệnh (code) và vùng chứa dữ liệu (data). Mã lệnh thƣờng là giống nhau và cĩ thể sử dụng chung. Linux quản lí cho phép tiến trình của cùng một chƣơng trình cĩ thể sử dụng chung mã lệnh của nhau. Thƣ viện cũng vậy. Trừ những thƣ viện đặc thù cịn thì các thƣ viện chuẩn sẽ đƣợc Hệ Điều Hành cho phép chia sẻ và dùng chung bởi mọi tiến trình trong hệ thống. Bằng cách chia sẻ thƣ viện, kích thƣớc chƣơng trình giảm đi đáng kể. Mã lệnh của chƣơng trình khi chạy trong hệ thống ở dạng tiến trình cũng sẽ đỡ tốn bộ nhớ hơn. Trừ mã lệnh và thƣ viện cĩ thể chia sẻ, cịn dữ liệu thì khơng thể chia sẻ bởi các tiến trình. Mỗi tiến trình sở hữu phân đoạn dữ liệu riêng. Ví dụ tiến trình grep do user1 nắm giữ lƣu giữ biến s cĩ giá trị là 'abc', trong khi grep do user2 nắm giữ lại cĩ biến s với giá trị là 'cde'. Mỗi tiến trình cũng đƣợc hệ thống dành riêng cho một bảng mơ tả file (file description table). Bảng này chứa các số mơ tả áp đặt cho các file đang đƣợc mở. Khi mỗi tiến trình khởi động, thƣờng Hệ Điều Hành sẽ mở sẳn cho chúng ta 3 file : stdin (số mơ tả 0), stdout (số mơ tả 1), và stderr (số mơ tả 2). Các file này tƣợng trƣng cho các thiết bị nhập, xuất, và thơng báo lỗi. Chúng ta cĩ thể mở thêm các file khác. Ví dụ user1 mở file file1, và user2 mở file file2. Hệ Điều Hành cấp phát số mơ tả file cho mỗi tiến trình và lƣu riêng chúng trong bảng mơ tả file của tiến trình đĩ. Ngồi ra, mỗi tiến trình cĩ riêng ngăn xếp stack để lƣu biến cục bộ và các giá trị trả về sau lời gọi hàm. Tiến trình cũng đƣợc dành cho khoảng khơng gian riêng để lƣu các biến mơi trƣờng. Chúng ta sẽ dùng lệnh putenv và getenv để đặt riêng biến mơi trƣờng cho tiến trình. Bảng thơng tin tiến trình Hệ Điều Hành lƣu giữ một cấu trúc danh sách bên trong hệ thống gọi là bảng tiến trình (process table). Bảng tiến trình quản lí tất cả PID của hệ thống cùng với thơng tin chi tiết về các tiến trình đang chạy. Ví dụng khi chúng ta gọi lệnh ps, Linux thƣờng 50
  61. đọc thơng tin trong bảng tiến trình này và hiển thị những lệnh hay tên tiến trình đƣợc gọi: thời gian chiếm giữ CPU của tiến trình, tên ngƣời sử dụng tiến trình, Xem thơng tin của tiến trình Lệnh ps của Hệ Điều Hành dùng để hiển thị thơng tin chi tiết về tiến trình. Tùy theo tham số, ps sẽ cho biết thơng tin về tiến trình ngƣời dùng, tiến trình của hệ thống hoặc tất cả các tiến trình đang chạy. Ví dụ ps sẽ đƣa ra chi tiết bằng tham số -af Trong các thơng tin do ps trả về, UID là tên của ngƣời dùng đã gọi tiến trình, PID là số định danh mà hệ thống cấp cho tiến trình, PPID là số định danh của tiến trình cha (parent PID). Ở đây chúng ta sẽ gặp một số tiến trình cĩ định danh PPID là 1, là định danh của tiến trình init, đƣợc gọi chạy khi hệ thống khởi động. Nếu chúng ta hủy tiến trình init thì Hệ Điều Hành sẽ chấm dứt phiên làm việc. STIME là thời điểm tiến trình đƣợc đƣa vào sử dụng. TIME là thời gian chiếm dụng CPU của tiến trình. CMD là tồn bộ dựng lệnh khi tiến trình đƣợc triệu gọi. TTY là màn hình terminal ảo nơi gọi thực thi tiến trình. Nhƣ chúng ta đã biết, ngƣời dùng cĩ thể đăng nhập vào hệ thống Linux từ rất nhiều terminal khác nhau để gọi tiến trình. Để liệt kê các tiến trình hệ thống, chúng ta sử dụng lệnh: $ps –ax Tạo lập tiến trình Gọi tiến trình mới bằng hàm system() Chúng ta cĩ thể gọi một tiến trình khác bên trong một chƣơng trình đang thực thi bằng hàm system(). Cĩ nghĩa là chúng ta cĩ thể tạo ra một tiến trình mới từ một tiến trình đang chạy. Hàm system() đƣợc khai báo nhƣ sau: #include int system( const char (cmdstr) ) Hàm này gọi chuỗi lệnh cmdstr thực thi và chờ lệnh chấm dứt mới quay về nơi gọi hàm. Nĩ tƣơng đƣơng với việc bạn gọi shell thực thi lệnh của hệ thống: $sh –c cmdstr system() sẽ trả về mã lỗi 127 nếu nhƣ khơng khởi động đƣợc shell để gọi lệnh cmdstr. Mã lỗi -1 nếu gặp các lỗi khác. Cịn lại, mã trả về của system() là mã lỗi do cmdstr sau khi lệnh đƣợc gọi trả về. Ví dụ sử dụng hàm system(), system.c #include #include int main() { printf( "Thuc thi lenh ps voi system\n" ); system( "ps –ax" ); 51
  62. printf( "Thuc hien xong. \n" ); exit( 0 ); } Hàm system() của chúng ta đƣợc sử dụng để gọi lệnh “ps –ax” của Hệ Điều Hành. Thay thế tiến trình hiện hành với các hàm exec Mỗi tiến trình đƣợc Hệ Điều Hành cấp cho 1 khơng gian nhớ tách biệt để tiến trình tự do hoạt động. Nếu tiến trình A của chúng ta triệu gọi một chƣơng trình ngồi B (bằng hàm system()chẳng hạn), Hệ Điều Hành thƣờng thực hiện các thao tác nhƣ: cấp phát khơng gian bộ nhớ cho tiến trình mới, điều chỉnh lại danh sách các tiến trình, nạp mã lệnh của chƣơng trình B trên đĩa cứng và khơng gian nhớ vừa cấp phát cho tiến trình. Đƣa tiến trình mới vào danh sách cần điều phối của Hệ Điều Hành. Những cơng việc này thƣờng mất thời gian đáng kể và chiếm giữ thêm tài nguyên của hệ thống. Nếu tiến trình A đang chạy và nếu chúng ta muốn tiến trình B khởi động chạy trong khơng gian bộ nhớ đã cĩ sẵn của tiến trình A thì cĩ thể sử dụng các hàm exec đƣợc cung cấp bới Linux. Các hàm exec sẽ thay thế tồn bộ ảnh của tiến trình A (bao gồm mã lệnh, dữ liệu, bảng mơ tả file) thành ảnh của một tiến trình B hồn tồn khác. Chỉ cĩ số định danh PID của tiến trình A là cịn giữ lại. Tập hàm exec bao gồm các hàm sau: #include extern char environ; int execl( const char *path, const char *arg, ); int execlp( const char *file, const char *arg, ); int execle( const char *path, const char *arg, , char *const envp[] ); int exect( const char *path, char *const argv[] ); int execv( const char *path, char *const argv[] ); int execvp( const char *file, char *const argv[] ); Đa số các hàm này đều yêu cầu chúng ta chỉ đối số path hoặc file là đƣờng dẫn đến tên chƣơng trình cần thực thi trên đĩa. arg là các đối số cần truyền cho chƣơng trình thực thi, những đối số này tƣơng tự cách chúng ta gọi chƣơng trình từ dựng lệnh. Ví dụ sử dụng hàm exec, pexec.c #include #include int main() { printf( "Thuc thi lenh ps voi execlp\n" ); 52
  63. execlp( "ps", "ps", "–ax", 0 ); printf( "Thuc hien xong. Nhung chung ta se khong thay duoc dong nay.\n" ); exit( 0 ); } Nhân bản tiến trình với hàm fork() Thay thế tiến trình đơi khi bất lợi với chúng ta. Đĩ là tiến trình mới chiếm giữ tồn bộ khơng gian của tiến trình cũ và chúng ta sẽ khơng cĩ khả năng kiểm sốt cũng nhƣ điều khiển tiếp tiến trình hiện hành của mình sau khi gọi hàm exec nữa. Cách đơn giản mà các chƣơng trình Linux thƣờng dùng đĩ là sử dụng hàm fork() để nhân bản hay tạo bản sao mới của tiến trình. fork() là một hàm khá đặc biệt, khi thực thi, nĩ sẽ trả về 2 giá trị khác nhau trong lần thực thi, so với hàm bình thƣờng chỉ trả về 1 giá trị trong lần thực thi. Khai báo của hàm fork() nhƣ sau: #include #include pid_t fork() Nếu thành cơng, fork() sẽ tách tiến trình hiện hành 2 tiến trình (dĩ nhiên Hệ Điều Hành phải cấp phát thêm khơng gian bộ nhớ để tiến trình mới hoạt động). Tiến trình ban đầu gọi là tiến trình cha (parent process) trong khi tiến trình mới gọi là tiến trình con (child process). Tiến trình con sẽ cĩ một số định danh PID riêng biệt. ngồi ra, tiến trình con cịn mang thêm một định danh PPID là số định danh PID của tiến trình cha. Sau khi tách tiến trình, mã lệnh thực thi ở cả hai tiến trình đƣợc sao chép là hồn tồn giống nhau. Chỉ cĩ một dấu hiệu để chúng ta cĩ thể nhận dạng tiến trình cha và tiến trình con, đĩ là trị trả về của hàm fork(). Bên trong tiến trình con, hàm fork() sẽ trả về trị 0. Trong khi bên trong tiến trình cha, hàm fork() sẽ trả về trị số nguyên chỉ là PID của tiến trình con vừa tạo. Trƣờng hợp khơng tách đƣợc tiến trình, fork() sẽ trả về trị -1. Kiểu pid_t đƣợc khai báo và định nghĩa trong uinstd.h là kiểu số nguyên (int). Đoạn mã điều khiển và sử dụng hàm fork() thƣờng cĩ dạng chuẩn sau: pid_t new_pid; new_pid = fork(); // tách tiến trình switch (new_pid) { case -1: printf( "Khong the tao tien trinh moi" ); break; case 0: printf( "Day la tien trinh con" ); // mã lệnh dành cho tiến trình con đặt ở đây break; 53
  64. default: printf( "Day la tien trinh cha" ); // mã lệnh dành cho tiến trình cha đặt ở đây break; } - Ví dụ sử dụng hàm fork(), fork_demo.c #include #include #include int main() { pid_t pid; char * message; int n; printf( "Bat dau.\n" ); pid = fork(); switch ( pid ) { case -1: printf( "Khong the tao tien trinh moi" ); exit(1); case 0: message = "Day la tien trinh con"; n = 0; for ( ; n < 5; n++ ) { printf( "%s", message ); sleep( 1 ); } break; default: message = "Day la tien trinh cha"; n = 0; for ( ; n < 3; n++ ) { printf( "%s", message ); sleep( 1 ); } break; } 54
  65. exit( 0 ); } Biên dịch và thực thi chƣơng trình này, chúng ta sẽ thấy rằng cả 2 tiến trình hoạt động đồng thời và in ra kết quả đan xen nhau. Nếu muốn xem sự liên quan về PID và PPID của cả 2 tiến trình cha và con khi lệnh fork() phát sinh, chúng ta cĩ thể thực hiện chƣơng trình nhƣ sau: $fork_demo & ps – af Kiểm sốt và đợi tiến trình con Khi fork() tách tiến trình chính thành hai tiến trình cha và con, trên thực tế cả hai tiến trình cha lẫn tiến trình con đều hoạt động độc lập. Đơi lúc tiến trình cha cần phải đợi tiến trình con thực hiện xong tác vụ thì mới tiếp tục thực thi. Ở ví dụ trên, khi thực thi, chúng ta sẽ thấy rằng tiến trình cha đã kết thúc mà tiến trình con vẫn in thơng báo và cả tiến trình cha và tiến trình con đều tranh nhau gởi kết quả ra màn hình. Chúng ta khơng muốn điều này, chúng ta muốn rằng khi tiến trình cha kết thúc thì tiến trình con cũng hồn tất thao tác của nĩ. Hơn nữa, chƣơng trình con cần thực hiện xong tác vụ của nĩ thì mới đến chƣơng trình cha. Để làm đƣợc việc này, chúng ta hãy sử dụng hàm wait() #include #include pid_t wait(int &stat_loc); Hàm wait khi đƣợc gọi sẽ yêu cầu tiến trình cha dừng lại chờ tiến trình con kết thúc trƣớc khi thực hiện tiếp các lệnh điều khiển trong tiến trình cha. wait() làm cho sự liên hệ giữa tiến trình cha và tiến trình con trở nên tuần tự. Khi tiến trình con kết thúc, hàm sẽ trả về số PID tƣơng ứng của tiến trình con. Nếu chúng ta truyền thêm đối số stat_loc khác NULL cho hàm thì wait() cũng sẽ trả về trạng thái mà tiến trình con kết thúc trong biến stat_loc. Chúng ta cĩ thể sử dụng các macro khai báo sẵn trong sys/wait.h nhƣ sau: WIFEXITED (stat_loc) Trả về trị khác 0 nếu tiến trình con kết thúc bình thƣờng. WEXITSTATUS (stat_loc) Nếu WIFEXITED trả về trị khác 0, macro này sẽ trả về mã lỗi của tiến trình con. WIFSIGNALED (stat_loc) Trả về trị khác 0 nếu tiến trình con kết thúc bởi một tín hiệu gửi đến. WTERMSIG(stat_loc) Nếu WIFSIGNALED khác 0, macro này sẽ cho biết số tín hiệu đã hủy tiến trình con. WIFSTOPPED(stat_loc) Trả về trị khác 0 nếu tiến trình con đã dừng. WSTOPSIG(stat_loc) Nếu WIFSTOPPED trả về trị khác 0, macro này trả về số hiệu của signal. 55