通過編寫多進(jìn)程程序,使讀者熟練掌握fork()、exec()、wait()和waitpid()等函數(shù)的使用,進(jìn)一步理解在Linux中多進(jìn)程編程的步驟。
本章主要介紹進(jìn)程的控制開發(fā),首先給出了進(jìn)程的基本概念,Linux下進(jìn)程的基本結(jié)構(gòu)、模式與類型以及Linux進(jìn)程管理。進(jìn)程是Linux中程序運行和資源管理的最小單位,對進(jìn)程的處理也是嵌入式Linux應(yīng)用編程的基礎(chǔ),因此,讀者一定要牢牢掌握。
信號是UNIX中所使用的進(jìn)程通信的一種最古老的方法。它是在軟件層次上對中斷機制的一種模擬,是一種異步通信方式。信號可以直接進(jìn)行用戶空間進(jìn)程和內(nèi)核進(jìn)程之間的交互,內(nèi)核進(jìn)程也可以利用它來通知用戶空間進(jìn)程發(fā)生了哪些系統(tǒng)事件。它可以在任何時候發(fā)給某一進(jìn)程,而無需知道該進(jìn)程的狀態(tài)。
在多任務(wù)操作系統(tǒng)環(huán)境下,多個進(jìn)程會同時運行,并且一些進(jìn)程之間可能存在一定的關(guān)聯(lián)。多個進(jìn)程可能為了完成同一個任務(wù)會相互協(xié)作,這樣形成進(jìn)程之間的同步關(guān)系。而且在不同進(jìn)程之間,為了爭奪有限的系統(tǒng)資源(硬件或軟件資源)會進(jìn)入競爭狀態(tài),這就是進(jìn)程之間的互斥關(guān)系。
可以說,共享內(nèi)存是一種最為高效的進(jìn)程間通信方式。因為進(jìn)程可以直接讀寫內(nèi)存,不需要任何數(shù)據(jù)的復(fù)制。為了在多個進(jìn)程間交換信息,內(nèi)核專門留出了一塊內(nèi)存區(qū)。這段內(nèi)存區(qū)可以由需要訪問的進(jìn)程將其映射到自己的私有地址空間。因此,進(jìn)程就可以直接讀寫這一內(nèi)存區(qū)而不需要進(jìn)行數(shù)據(jù)的復(fù)制,從而大大提高了效率。
顧名思義,消息隊列就是一些消息的列表。用戶可以從消息隊列中添加消息和讀取消息等。從這點上看,消息隊列具有一定的FIFO特性,但是它可以實現(xiàn)消息的隨機查詢,比FIFO具有更大的優(yōu)勢。同時,這些消息又是存在于內(nèi)核中的,由“隊列ID”來標(biāo)識。
通過編寫有名管道多路通信實驗,讀者可進(jìn)一步掌握管道的創(chuàng)建、讀寫等操作,同時,也復(fù)習(xí)使用select()函數(shù)實現(xiàn)管道的通信。
本章詳細(xì)講解了Linux中進(jìn)程間通信的幾種機制,包括管道通信、信號通信、消息隊列、信號量以及共享內(nèi)存機制等,并且講解了進(jìn)程間通信的演進(jìn)。
前面已經(jīng)提到,進(jìn)程是系統(tǒng)中程序執(zhí)行和資源分配的基本單位。每個進(jìn)程都擁有自己的數(shù)據(jù)段、代碼段和堆棧段,這就造成了進(jìn)程在進(jìn)行切換等操作時都需要有比較復(fù)雜的上下文切換等動作。為了進(jìn)一步減少處理機的空轉(zhuǎn)時間,支持多處理器以及減少上下文切換開銷,進(jìn)程在演化中出現(xiàn)了另一個概念——線程。
“生產(chǎn)者消費者”問題是一個著名的同時性編程問題的集合。通過學(xué)習(xí)經(jīng)典的“生產(chǎn)者消費者”問題的實驗,讀者可以進(jìn)一步熟悉Linux中的多線程編程,并且掌握用信號量處理線程間的同步和互斥問題。
讀者一定都聽說過著名的OSI協(xié)議參考模型,它是基于國際標(biāo)準(zhǔn)化組織(ISO)的建議發(fā)展起來的,從上到下共分為7層:應(yīng)用層、表示層、會話層、傳輸層、網(wǎng)絡(luò)層、數(shù)據(jù)鏈路層及物理層。這個7層的協(xié)議模型雖然規(guī)定得非常細(xì)致和完善,但在實際中卻得不到廣泛的應(yīng)用,其重要的原因之一就在于它過于復(fù)雜。
本章首先介紹了線程的基本概念、線程的分類和特性以及線程的發(fā)展歷程。
在Linux中的網(wǎng)絡(luò)編程是通過socket接口來進(jìn)行的。人們常說的socket是一種特殊的I/O接口,它也是一種文件描述符。socket是一種常用的進(jìn)程之間通信機制,通過它不僅能實現(xiàn)本地機器上的進(jìn)程之間的通信,而且通過網(wǎng)絡(luò)能夠在不同機器上的進(jìn)程之間進(jìn)行通信。
在實際情況中,人們往往遇到多個客戶端連接服務(wù)器端的情況。由于之前介紹的如connet()、recv()和send()等都是阻塞性函數(shù),如果資源沒有準(zhǔn)備好,則調(diào)用該函數(shù)的進(jìn)程將進(jìn)入睡眠狀態(tài),這樣就無法處理I/O多路復(fù)用的情況了。本節(jié)給出了兩種解決I/O多路復(fù)用的解決方法,這兩個函數(shù)都是之前學(xué)過的fcntl()和select()。
通過實現(xiàn)NTP協(xié)議的練習(xí),進(jìn)一步掌握Linux網(wǎng)絡(luò)編程,并且提高協(xié)議的分析與實現(xiàn)能力,為參與完成綜合性項目打下良好的基礎(chǔ)。
本章首先概括地講解了OSI分層結(jié)構(gòu)以及TCP/IP協(xié)議各層的主要功能,介紹了常見的TCP/IP協(xié)議族,并且重點講解了網(wǎng)絡(luò)編程中需要用到的TCP和UDP協(xié)議,為嵌入式Linux的網(wǎng)絡(luò)編程打下良好的基礎(chǔ)。
操作系統(tǒng)是通過各種驅(qū)動程序來駕馭硬件設(shè)備的,它為用戶屏蔽了各種各樣的設(shè)備,驅(qū)動硬件是操作系統(tǒng)最基本的功能,并且提供統(tǒng)一的操作方式。設(shè)備驅(qū)動程序是內(nèi)核的一部分,硬件驅(qū)動程序是操作系統(tǒng)最基本的組成部分,在Linux內(nèi)核源程序中也占有60%以上。因此,熟悉驅(qū)動的編寫是很重要的。
設(shè)備驅(qū)動程序可以使用模塊的方式動態(tài)加載到內(nèi)核中去。加載模塊的方式與以往的應(yīng)用程序開發(fā)有很大的不同。以往在開發(fā)應(yīng)用程序時都有一個main()函數(shù)作為程序的入口點,而在驅(qū)動開發(fā)時卻沒有main()函數(shù),模塊在調(diào)用insmod命令時被加載,此時的入口點是init_module()函數(shù),通常在該函數(shù)中完成設(shè)備的注冊。
Qt/Embedded以原始Qt為基礎(chǔ),并做了許多出色的調(diào)整以適用于嵌入式環(huán)境。Qt/Embedded通過Qt API與Linux I/O設(shè)施直接交互,成為嵌入式Linux端口。同Qt/X11相比,Qt/Embedded很省內(nèi)存,因為它不需要一個X服務(wù)器或是Xlib庫,它在底層拋棄了X lib,采用framebuffer)作為底層圖形接口
FS2410開發(fā)板的S3C2410處理器具有117個多功能通用I/O(GPIO)端口管腳,包括GPIO 8個端口組,分別為GPA(23個輸出端口)、GPB(11個輸入/輸出端口)、GPC(16個輸入/輸出端口)、GPD(16個輸入/輸出端口)、GPE(16個輸入/輸出端口)、GPF(8個輸入/輸出端口)、GPH(11個輸入/輸出端口)。