第5章_交叉開(kāi)發(fā)環(huán)境建立_第1頁(yè)
第5章_交叉開(kāi)發(fā)環(huán)境建立_第2頁(yè)
第5章_交叉開(kāi)發(fā)環(huán)境建立_第3頁(yè)
第5章_交叉開(kāi)發(fā)環(huán)境建立_第4頁(yè)
第5章_交叉開(kāi)發(fā)環(huán)境建立_第5頁(yè)
已閱讀5頁(yè),還剩40頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、第第2章章 嵌入式嵌入式Linux基礎(chǔ)基礎(chǔ)第二章第二章 嵌入式嵌入式LinuxLinux基基礎(chǔ)礎(chǔ)主要內(nèi)容主要內(nèi)容 第一節(jié) 構(gòu)建嵌入式Linux系統(tǒng)環(huán)境 第二節(jié) Linux C程序設(shè)計(jì) 第三節(jié) Linux多線程庫(kù)編程 第四節(jié) 進(jìn)程創(chuàng)建以及進(jìn)程間通信 學(xué)習(xí)方法與建議學(xué)習(xí)方法與建議本章將介紹和嵌入式Linux開(kāi)發(fā)有關(guān)的基礎(chǔ)知識(shí),主要包括三部分內(nèi)容:構(gòu)建嵌入式Linux操作系統(tǒng)開(kāi)發(fā)環(huán)境,即了解嵌入式系統(tǒng)開(kāi)發(fā)的相關(guān)細(xì)節(jié)和環(huán)境搭建;嵌入式系統(tǒng)開(kāi)發(fā)基礎(chǔ),C語(yǔ)言程序設(shè)計(jì);線程和進(jìn)程的程序?qū)崿F(xiàn)。本章的部分內(nèi)容在后續(xù)章節(jié)中會(huì)有進(jìn)一步的應(yīng)用。 內(nèi)容:內(nèi)容:一、交叉編譯一、交叉編譯 二、關(guān)于交叉編譯器二、關(guān)于交叉編譯

2、器 三、關(guān)于三、關(guān)于NFS第一節(jié)第一節(jié) 構(gòu)建嵌入式構(gòu)建嵌入式Linux系統(tǒng)環(huán)境系統(tǒng)環(huán)境 嵌入式系統(tǒng)一般是以應(yīng)用為中心、以計(jì)算機(jī)技術(shù)為基礎(chǔ)、軟件硬件可裁剪、適應(yīng)應(yīng)用系統(tǒng)對(duì)功能、可靠性、成本、體積、功耗嚴(yán)格要求的專用計(jì)算機(jī)系統(tǒng)。嵌入式開(kāi)發(fā)板的資源往往比較有限,沒(méi)有足夠的資源來(lái)運(yùn)行開(kāi)發(fā)調(diào)試工具。所以,通常嵌入式系統(tǒng)的軟件開(kāi)發(fā)需要采用交叉編譯的方式。 交叉編譯是構(gòu)建嵌入式Linux系統(tǒng)環(huán)境過(guò)程中的重要一步。交叉編譯的環(huán)境建立在宿主機(jī)(host)上,而對(duì)應(yīng)的開(kāi)發(fā)板稱為目標(biāo)機(jī)(target)。為了使宿主機(jī)上開(kāi)發(fā)的程序(應(yīng)用程序和驅(qū)動(dòng)程序)能夠方便地下載到目標(biāo)機(jī)上運(yùn)行,一般還要在宿主機(jī)上配置好網(wǎng)絡(luò),使其支持

3、NFS或tftp等網(wǎng)絡(luò)服務(wù),從而達(dá)到兩臺(tái)機(jī)器之間的文件共享。第一節(jié)第一節(jié) 構(gòu)建嵌入式構(gòu)建嵌入式Linux系統(tǒng)環(huán)境系統(tǒng)環(huán)境 一、交叉編譯一、交叉編譯交叉編譯交叉編譯利用運(yùn)行在某臺(tái)計(jì)算機(jī)(宿主機(jī))上的編譯器編譯某個(gè)源程序,生成在另一臺(tái)機(jī)器(目標(biāo)機(jī))上運(yùn)行的目標(biāo)代碼的過(guò)程。交叉編譯是不得不產(chǎn)生的技術(shù)。因?yàn)槟繕?biāo)機(jī)資源有限,無(wú)法運(yùn)行編譯和調(diào)試工具,因此需要宿主機(jī)為之代勞。另外,在構(gòu)建嵌入式系統(tǒng)的過(guò)程中也需要交叉編譯目標(biāo)機(jī)所需要的引導(dǎo)系統(tǒng)和操作系統(tǒng)內(nèi)核。因此,在嵌入式系統(tǒng)開(kāi)發(fā)時(shí),往往由宿主機(jī)開(kāi)發(fā)程序,而目標(biāo)機(jī)作為最后的執(zhí)行機(jī)。兩者在開(kāi)發(fā)時(shí)需要交替結(jié)合進(jìn)行。 在構(gòu)建交叉編譯環(huán)境的過(guò)程中,交叉編譯器(cros

4、s compilation tool chain)無(wú)疑是最重要的組成部分。在嵌入式系統(tǒng)開(kāi)發(fā)過(guò)程中,由于嵌入式開(kāi)發(fā)平臺(tái)的資源有限:例如常見(jiàn)的ARM開(kāi)發(fā)平臺(tái),其靜態(tài)存儲(chǔ)空間僅有32MB,CPU主頻也僅為203Mhz。這樣的資源不足以完成本機(jī)編譯(native compilation),因此交叉編譯器應(yīng)運(yùn)而生。可以使用-v參數(shù)查看編譯器的相關(guān)信息。由下圖可知,armv4l-unknown-linux-gcc的版本是2.95.2。 第一節(jié)第一節(jié) 構(gòu)建嵌入式構(gòu)建嵌入式Linux系統(tǒng)環(huán)境系統(tǒng)環(huán)境 二、關(guān)于交叉編譯器二、關(guān)于交叉編譯器 包括gcc在內(nèi)的語(yǔ)言編譯工具是能夠把某種以數(shù)字和符號(hào)為內(nèi)容的高級(jí)編程語(yǔ)言

5、轉(zhuǎn)換成機(jī)器語(yǔ)言指令的集合。因此在編譯過(guò)程中,編譯器還必需聯(lián)合其它一些輔助工具才能工作。這些輔助編譯工具包括:第一節(jié)第一節(jié) 構(gòu)建嵌入式構(gòu)建嵌入式Linux系統(tǒng)環(huán)境系統(tǒng)環(huán)境 二、關(guān)于交叉編譯器二、關(guān)于交叉編譯器 解釋程序解釋程序(Interpreter)其本身也是一種語(yǔ)言翻譯工具。它能夠直接執(zhí)行源程序,簡(jiǎn)單且方便移植,但是執(zhí)行速度比編譯器慢。匯編器(匯編器(Assembler)用于特定計(jì)算機(jī)上的匯編語(yǔ)言翻譯程序。連接器(連接器(Linker)能夠把在不同的目標(biāo)文件中編譯或匯編的代碼收集到一個(gè)可直接執(zhí)的文件中,同時(shí)也能夠連接目標(biāo)程序和相應(yīng)的標(biāo)準(zhǔn)庫(kù)函數(shù)代碼。裝載器(裝載器(Loader)裝載器可處理所

6、有與指定的基地址或起始地址相關(guān)的可復(fù)位的地址,這樣能夠使得編譯過(guò)程更加靈活。預(yù)處理器預(yù)處理器(Preprocessor)編譯開(kāi)始時(shí)被調(diào)用。專門負(fù)責(zé)刪除注釋和執(zhí)行宏替換等工作。調(diào)試器(調(diào)試器(Debugger) 用于調(diào)試目標(biāo)代碼,以排除代碼中存在的錯(cuò)誤。 在嵌入式系統(tǒng)開(kāi)發(fā)過(guò)程中,由于可執(zhí)行程序的編譯過(guò)程和執(zhí)行過(guò)程分別在宿主機(jī)和目標(biāo)機(jī)上完成,因此實(shí)現(xiàn)宿主機(jī)和目標(biāo)機(jī)之間的實(shí)時(shí)交互能夠大幅度提高嵌入式系統(tǒng)開(kāi)發(fā)的效率。由于目標(biāo)機(jī)也帶有操作系統(tǒng),因此可以通過(guò)實(shí)現(xiàn)不同機(jī)器之間的網(wǎng)絡(luò)共享來(lái)完成實(shí)時(shí)交互。 NFS(Network File System,網(wǎng)絡(luò)文件系統(tǒng)),網(wǎng)絡(luò)文件系統(tǒng)) 允許一個(gè)操作系統(tǒng)在網(wǎng)絡(luò)上與

7、他人共享目錄和文件。通過(guò)使用NFS,用戶可以像訪問(wèn)本地文件一樣訪問(wèn)遠(yuǎn)程系統(tǒng)上的文件,即使是不同的系統(tǒng)或者通信協(xié)議也能夠完成共享。 第一節(jié)第一節(jié) 構(gòu)建嵌入式構(gòu)建嵌入式Linux系統(tǒng)環(huán)境系統(tǒng)環(huán)境 三、關(guān)于三、關(guān)于NFS 相關(guān)操作 如下: 如果不知道宿主機(jī)的Linux系統(tǒng)是否已經(jīng)運(yùn)行NFS,可以使用如下命令查看:rootlocalhost root# netstat -l |grep nfsudp 0 0 *:nfs *:* 如果沒(méi)有啟動(dòng)NFS,可以使用如下命令啟動(dòng):rootlocalhost root# service nfs restart關(guān)閉 NFS mountd: 確定 關(guān)閉 NFS 守護(hù)進(jìn)

8、程: 確定 Shutting down NFS quotas: 確定 關(guān)閉 NFS 服務(wù): 確定 啟動(dòng) NFS 服務(wù): 確定 Starting NFS quotas: 確定 啟動(dòng) NFS 守護(hù)進(jìn)程: 確定 啟動(dòng) NFS mountd: 確定 第一節(jié)第一節(jié) 構(gòu)建嵌入式構(gòu)建嵌入式Linux系統(tǒng)環(huán)境系統(tǒng)環(huán)境 三、關(guān)于三、關(guān)于NFS 相關(guān)操作 如下: 對(duì)于需要export的nfs目錄,可以修改/etc/exports文件:rootlocalhost root# vi /etc/exports/arm2410s/ 192.168.0.*(rw,insecure,sync,no_root_squash)

9、保存退出之后,向內(nèi)核告知所要export的目錄:rootlocalhost root# exportfs -ravexporting 192.168.0.*:/arm2410s 全部完成后,可以測(cè)試一下NFS是否可用:rootlocalhost root# mkdir /testrootlocalhost root# mount -o nolock 21:/arm2410s/ /test/如果掛載成功,則進(jìn)入test目錄,所顯示內(nèi)容就是arm2410s目錄的內(nèi)容。第一節(jié)第一節(jié) 構(gòu)建嵌入式構(gòu)建嵌入式Linux系統(tǒng)環(huán)境系統(tǒng)環(huán)境 三、關(guān)于三、關(guān)于NFS 第二節(jié)第二節(jié) Linux

10、 C程序設(shè)計(jì)程序設(shè)計(jì)一、一、C程序設(shè)計(jì)概述程序設(shè)計(jì)概述 簡(jiǎn)單介紹Linux下的C程序設(shè)計(jì)二、二、Makefile介紹介紹 介紹Makefile的使用規(guī)則三、三、Makefile中的變量中的變量 陳述Makfeile中的多種變量 四、四、Makefile隱含規(guī)則隱含規(guī)則 介紹Makefile中的隱含規(guī)則 在Linux下,一般使用GNU C編譯器(GCC)進(jìn)行應(yīng)用程序的編譯。GNU C編譯器(GCC)是一款功能強(qiáng)大的ANSI C兼容編譯器 ,一般存放在/usr/bin目錄下;其頭文件一般存放在/usr/include及其下級(jí)子目錄里;而標(biāo)準(zhǔn)的庫(kù)文件則存放在/lib或/usr/lib子目錄里。gcc

11、 命令的基本用法如下所示:gcc options filenames make是一個(gè)命令工具,它讀入Makefile的指令并按照其制定的規(guī)則執(zhí)行。Makefile文件中描述整個(gè)工程所有文件的編譯順序、編譯規(guī)則,并且擁有自己的書寫格式、關(guān)鍵字和函數(shù);而且在Makefile中可以使用系統(tǒng)shell所提供的任何命令來(lái)完成想要的工作,因此能夠大大提高了編譯程序的效率。通過(guò)其“自動(dòng)化編譯”的規(guī)則,只需要一個(gè)make命令,整個(gè)工程就可以自動(dòng)完成全部編譯工作,因此在IDE開(kāi)發(fā)環(huán)境中得到廣泛應(yīng)用,已經(jīng)成為一種工程方面的編譯方法。 第二節(jié)第二節(jié) Linux C程序設(shè)計(jì)程序設(shè)計(jì) 一、一、C程序設(shè)計(jì)概述程序設(shè)計(jì)概述

12、 默認(rèn)情況下,GNU make工具在當(dāng)前工作目錄中按如下順序搜索makefile:GNUmakefile - makefile - Makefile 雖然Makefile作為規(guī)則的優(yōu)先等級(jí)較低,不過(guò)由于Makefile的首字母大寫,因此在當(dāng)前目錄下會(huì)優(yōu)先顯示,所以程序員往往會(huì)采用Makefile作為makefile文件。如果要使用其他文件作為 makefile,則可采用以下方式:$ make -f Makefile.debug第二節(jié)第二節(jié) Linux C程序設(shè)計(jì)程序設(shè)計(jì) 二、二、Makefile介紹介紹 makefile的基本結(jié)構(gòu)如下:target:dependency dependency(

13、tab)它包含target、dependency和command三個(gè)部分。具體如下所示: 一個(gè)目標(biāo)(一個(gè)目標(biāo)(target)最終需要?jiǎng)?chuàng)建的文件,包括可執(zhí)行文件或者目標(biāo)驅(qū)動(dòng)文件等。當(dāng)然目標(biāo)也可以是需要執(zhí)行的動(dòng)作,如“clean”等。 一個(gè)或多個(gè)依賴文件(一個(gè)或多個(gè)依賴文件(dependency)在創(chuàng)建target時(shí)需要用到的文件列表。一系列命令一系列命令(command) make執(zhí)行的動(dòng)作,即創(chuàng)建target文件所需要執(zhí)行的步驟。通常是把指定文件編譯成目標(biāo)文件的編譯命令,每個(gè)命令占一行,且每個(gè)命令行的起始字符必須為TAB字符。 第二節(jié)第二節(jié) Linux C程序設(shè)計(jì)程序設(shè)計(jì) 二、二、Makefi

14、le介紹介紹 編譯的具體過(guò)程是 make工具首先讀取makefile中的規(guī)則,然后檢查該規(guī)則中的依賴文件與目標(biāo)文件的時(shí)間戳哪個(gè)更新一些,并根據(jù)規(guī)則鏈由下至上依次執(zhí)行編譯過(guò)程,直到最終的可執(zhí)行文件被重新連接完成為止。 第二節(jié)第二節(jié) Linux C程序設(shè)計(jì)程序設(shè)計(jì) 二、二、Makefile介紹介紹 Makefile里的變量類似一個(gè)環(huán)境變量。這些變量對(duì)大小寫敏感,一般使用大寫字母。 下面給出一個(gè)具體的makefile:OBJS=prog.o code.o#定義變量定義變量OBJSCC=gcc #定義變量定義變量CCtest:$(OBJS)$(CC) o test $(OBJS) #gcc o tes

15、t prog.o code.oprog.o:prog.c prog.h code.h$(CC) c prog.c o prog.ocode.o:code.c code.h$(CC) c code.c o code.oclean:rm f *.o 顯然,在上述例子中,用戶自定義了CC和OBJS兩個(gè)變量,并且在之后的規(guī)則中使用$()符號(hào)對(duì)其內(nèi)容進(jìn)行引用。 第二節(jié)第二節(jié) Linux C程序設(shè)計(jì)程序設(shè)計(jì) 三、三、Makefile中的變量中的變量 除用戶自定義的變量外,make還允許使用如下類型的變量: 環(huán)境變量環(huán)境變量 在啟動(dòng)時(shí),make讀取系統(tǒng)當(dāng)前已定義的環(huán)境變量,并且創(chuàng)建與之同名同值的變量,因此用

16、戶可以像在Shell中一樣在Makefile中引用環(huán)境變量。需要注意的是,如果用戶在Makefile中定義了同名變量,那么用戶自定義變量將覆蓋同名的環(huán)境變量。第二節(jié)第二節(jié) Linux C程序設(shè)計(jì)程序設(shè)計(jì) 三、三、Makefile中的變量中的變量 預(yù)定義變量預(yù)定義變量$*不包含擴(kuò)展名的目標(biāo)文件名稱。$+所有的依賴文件,以空格分開(kāi),并以出現(xiàn)的先后為序,包含重復(fù)的依賴文件。$第一個(gè)依賴文件的名稱。$?所有依賴文件以空格分開(kāi),這些依賴文件修改日期比目標(biāo)創(chuàng)建日期晚 。$目標(biāo)的完整名稱。$所有的依賴文件,以空格分開(kāi),不包含重復(fù)的依賴文件。$%如果目標(biāo)是歸檔成員,則該變量表示目標(biāo)的歸檔成員名稱。AR歸檔維護(hù)

17、程序的名稱,默認(rèn)值為 ar。ARFLAGS歸檔維護(hù)程序的選項(xiàng)。AS匯編程序的名稱,默認(rèn)值為 as。ASFLAGS匯編程序的選項(xiàng)。CCC 編譯器的名稱,默認(rèn)值為 cc。CFLAGSC 編譯器的選項(xiàng)。CPPC 預(yù)編譯器的名稱,默認(rèn)值為 $(CC) -E。 CPPFLAGSC 預(yù)編譯的選項(xiàng)。 CXX C+ 編譯器的名稱,默認(rèn)值為 g+。 CXXFLAGSC+ 編譯器的選項(xiàng)。FCFORTRAN 編譯器的名稱,默認(rèn)值為 f77。FFLAGSFORTRAN 編譯器的選項(xiàng)。第二節(jié)第二節(jié) Linux C程序設(shè)計(jì)程序設(shè)計(jì) 三、三、Makefile中的變量中的變量 在上述例子中,幾個(gè)產(chǎn)生目標(biāo)文件的命令都是從C源文

18、件和相關(guān)文件通過(guò)編譯產(chǎn)生目標(biāo)文件。實(shí)際上,make完全可以更簡(jiǎn)潔一些:make有一些稱作隱含規(guī)則的內(nèi)置的規(guī)則,這些規(guī)則告訴make當(dāng)某些命令沒(méi)有被完整給出時(shí)應(yīng)該怎樣執(zhí)行。 例如,把生成prog.o和code.o的命令從規(guī)則中刪除,make將會(huì)查找隱含規(guī)則,并執(zhí)行一個(gè)適當(dāng)?shù)拿?。由于這些命令往往會(huì)使用一些變量,因此可以通過(guò)改變這些變量來(lái)定制make。像在前面的例子中所定義的那樣,make使用變量CC來(lái)定義編譯器,并且傳遞變量CFLAGS(編譯器參數(shù))、CPPFLAGS(C語(yǔ)言預(yù)處理器參數(shù))、TARGET_ARCH(目標(biāo)機(jī)器的結(jié)構(gòu)定義)給編譯器,然后加上編譯參數(shù)-c,變量$(第一個(gè)依賴文件名),改

19、名參數(shù)-o以及變量$(目標(biāo)文件名)。第二節(jié)第二節(jié) Linux C程序設(shè)計(jì)程序設(shè)計(jì) 四、四、Makefile隱含規(guī)則隱含規(guī)則 綜上所述,一個(gè)C編譯的具體命令將會(huì)是:$ CC $ CFLAGS $ CPPFLAGS $ TARGET_ARCH c $ -o $ 使用隱含規(guī)則的例子如下所示:OBJS=prog.o code.oCC=gcctest:$(OBJS)$(CC) o $ $prog.o:prog.c prog.h code.hcode.o:code.c code.hclean:rm f *.o第二節(jié)第二節(jié) Linux C程序設(shè)計(jì)程序設(shè)計(jì) 四、四、Makefile隱含規(guī)則隱含規(guī)則 第三節(jié)第三

20、節(jié) Linux多線程庫(kù)編程多線程庫(kù)編程 一、一、 多線程多線程 二二 、多線程介紹、多線程介紹 三三 、常用操作生產(chǎn)者、常用操作生產(chǎn)者-消費(fèi)者模型簡(jiǎn)述消費(fèi)者模型簡(jiǎn)述四、簡(jiǎn)述緩沖區(qū)的具體操作四、簡(jiǎn)述緩沖區(qū)的具體操作 五、幾個(gè)線程五、幾個(gè)線程API 第三節(jié)第三節(jié) Linux多線程庫(kù)編程多線程庫(kù)編程 一、多線程一、多線程 計(jì)算機(jī)在運(yùn)行時(shí)其執(zhí)行過(guò)程從大到小可以分為作業(yè)、進(jìn)程和線程三個(gè)等級(jí)。所謂線程,是系統(tǒng)能夠獨(dú)立調(diào)度和分派的最基本單位。線程自己并不擁有系統(tǒng)資源,只是在運(yùn)行的時(shí)候占用一點(diǎn)必不可少的資源。如果在一個(gè)程序中同時(shí)運(yùn)行多個(gè)線程來(lái)完成不同的工作,則稱之為多線程多線程。 顯然,多線程可以更方便的體現(xiàn)

21、“并行”特性,而且由于線程的輕量級(jí),因此能夠大大提高系統(tǒng)效率;而且在多CPU的硬件前提下更可以充分利用多核資源,因此被引入到操作系統(tǒng)之中。 Linux系統(tǒng)下的多線程遵循POSIX線程接口,稱之為pthread。多線程編程的源程序必須包含頭文件pthread.h,因?yàn)榫€程庫(kù)libpthread.a并不屬于Linux系統(tǒng)的默認(rèn)庫(kù),因此在編譯時(shí)需要加上l pthread參數(shù)。 /* exampthread.c*/#include #include void thread(void)int i;for(i=0;i3;i+)printf(This is a pthread.n);int main(voi

22、d)第三節(jié)第三節(jié) Linux多線程庫(kù)編程多線程庫(kù)編程 二、多線程介紹二、多線程介紹 pthread_t id;int i,ret;ret=pthread_create(&id,NULL,(void *) thread,NULL);if(ret)printf (Create pthread error!n);exit (1);for(i=0;i3;i+)printf(This is the main process.n);pthread_join(id,NULL);return (0);在宿主機(jī)上用如下命令編譯該程序,就可以生成可執(zhí)行文件。#armv4l-unknown-linux-gcc l

23、pthreado exampthread exampthread.c將生成的exampthread文件下載至開(kāi)發(fā)板。 或者可能出現(xiàn)如下結(jié)果:This is a pthread.This is the main process.This is a pthread.This is the main process. This is a pthread.This is the main process.運(yùn)行之后可能顯示如下結(jié)果:This is the main process.This is a pthread.This is the main process.This is the main pr

24、ocess.This is a pthread.This is a pthread.第三節(jié)第三節(jié) Linux多線程庫(kù)編程多線程庫(kù)編程 二、多線程介紹二、多線程介紹 在上例中首先聲明了一個(gè)pthread_t型變量。pthread_t類型類型在頭文件/usr/include/bits/pthreadtypes.h中定義:typedef unsigned long int pthread_t; 之后使用到的函數(shù)pthread_create用來(lái)創(chuàng)建一個(gè)線程,其原型為:extern int pthread_create _P (pthread_t *_thread, _const pthread_att

25、r_t *_attr, void *(*_start_routine) (void *), void *_arg); 第一個(gè)參數(shù)為指向線程標(biāo)識(shí)符的指針,第二個(gè)參數(shù)用來(lái)設(shè)置線程屬性,第三個(gè)參數(shù)是線程運(yùn)行函數(shù)的起始地址,最后一個(gè)參數(shù)為運(yùn)行函數(shù)的參數(shù)。 在該例中,函數(shù)thread不需要參數(shù),所以最后一個(gè)參數(shù)設(shè)為空指針;第二個(gè)參數(shù)也設(shè)為空指針,這樣將生成默認(rèn)屬性的線程。當(dāng)創(chuàng)建線程成功時(shí),函數(shù)返回0,若不返回0則說(shuō)明創(chuàng)建線程失敗。常見(jiàn)的錯(cuò)誤返回代碼為EAGAIN和EINVAL,前者表示系統(tǒng)限制創(chuàng)建新的線程(例如線程數(shù)目過(guò)多了);后者表示第二個(gè)參數(shù)代表的線程屬性值非法。創(chuàng)建線程成功后,新創(chuàng)建的線程則運(yùn)行第

26、3個(gè)參數(shù)和第4個(gè)參數(shù)確定的函數(shù),原來(lái)的線程則繼續(xù)運(yùn)行下一行代碼。 第三節(jié)第三節(jié) Linux多線程庫(kù)編程多線程庫(kù)編程 二、多線程介紹二、多線程介紹 使用的另外一個(gè)函數(shù)pthread_join用來(lái)等待一個(gè)線程的結(jié)束。該函數(shù)的原型為:extern int pthread_join _P (pthread_t _th, void *_thread_return); 其中,第一個(gè)參數(shù)為被等待的線程標(biāo)識(shí)符,第二個(gè)參數(shù)為一個(gè)用戶定義的指針,它可以用來(lái)存儲(chǔ)被等待線程的返回值。由于該函數(shù)是一個(gè)線程阻塞的函數(shù),調(diào)用它的函數(shù)將一直等待,直到被等待的線程結(jié)束為止。當(dāng)函數(shù)返回時(shí),被等待線程的資源被收回。 結(jié)束一個(gè)線程有

27、兩種方法,一種方法如上例所示,函數(shù)結(jié)束也就意味著調(diào)用它的線程結(jié)束;另一種方法是通過(guò)函數(shù)pthread_exit來(lái)實(shí)現(xiàn)。其函數(shù)原型為:extern void pthread_exit _P (void *_retval) _attribute_ (_noreturn_); 唯一的參數(shù)是函數(shù)的返回代碼,因此只要pthread_join中的第二個(gè)參數(shù)thread_return不是NULL,那么這個(gè)值將被傳遞給thread_return。這里要注意的是,一個(gè)線程不能被多個(gè)線程等待,否則第一個(gè)接收到信號(hào)的線程成功返回,其余調(diào)用pthread_join的線程則返回錯(cuò)誤代碼ESRCH。 第三節(jié)第三節(jié) Lin

28、ux多線程庫(kù)編程多線程庫(kù)編程 二、多線程介紹二、多線程介紹 在上例中,前后兩次的運(yùn)行結(jié)果不一樣,這是兩個(gè)線程競(jìng)爭(zhēng)CPU資源而導(dǎo)致的,說(shuō)明線程執(zhí)行具有無(wú)序性。也就是說(shuō),并發(fā)運(yùn)行線程的相對(duì)執(zhí)行順序是不確定的,在線程之間沒(méi)有數(shù)據(jù)共享的情況下,幾個(gè)線程執(zhí)行順序可以是隨機(jī)的。但是,當(dāng)兩個(gè)或者兩個(gè)以上的線程共享數(shù)據(jù)時(shí),線程隨機(jī)執(zhí)行就會(huì)產(chǎn)生錯(cuò)誤。這時(shí)就需要某種機(jī)制來(lái)進(jìn)行調(diào)整。當(dāng)某線程執(zhí)行訪問(wèn)共享數(shù)據(jù)區(qū)的某段程序時(shí),不允許其他線程并發(fā)執(zhí)行,這就是多線程的同步機(jī)制。 操作系統(tǒng)提出了多個(gè)機(jī)制對(duì)線程的執(zhí)行順序進(jìn)行限制,包括互斥鎖和條件變量等機(jī)制?;コ怄i用來(lái)保證共享數(shù)據(jù)操作的完整性。每個(gè)對(duì)象都有一個(gè)對(duì)應(yīng)的稱為“互斥鎖

29、”的標(biāo)記,而該標(biāo)記能夠保證在任一時(shí)刻只有一個(gè)線程訪問(wèn)該對(duì)象。條件變量能夠協(xié)助控制互斥鎖,滿足多線程控制機(jī)制。在這里將引入生產(chǎn)者-消費(fèi)者模型對(duì)多線程的管理機(jī)制進(jìn)行描述。第三節(jié)第三節(jié) Linux多線程庫(kù)編程多線程庫(kù)編程 三、常用操作生產(chǎn)者三、常用操作生產(chǎn)者-消費(fèi)者模型簡(jiǎn)述消費(fèi)者模型簡(jiǎn)述 在生產(chǎn)者-消費(fèi)者模型中,主程序分別啟動(dòng)了生產(chǎn)者線程和消費(fèi)者線程。其中生產(chǎn)者線程不停地寫入共享的循環(huán)緩沖區(qū),而消費(fèi)者線程則不停地從緩沖區(qū)中取出數(shù)據(jù)。 第三節(jié)第三節(jié) Linux多線程庫(kù)編程多線程庫(kù)編程 三、常用操作生產(chǎn)者三、常用操作生產(chǎn)者-消費(fèi)者模型簡(jiǎn)述消費(fèi)者模型簡(jiǎn)述 在生產(chǎn)者寫入緩沖區(qū)時(shí),首先要獲得互斥鎖,并且判斷緩

30、沖區(qū)是否為滿,也就是判斷寫指針+1后是否等于讀指針,如果相等則進(jìn)入等待狀態(tài),等候條件變量notfull發(fā)出信號(hào);如果判斷條件不等,則向緩沖區(qū)寫一個(gè)整數(shù),同時(shí)設(shè)置條件變量notempty。最后釋放互斥鎖。 當(dāng)消費(fèi)者從緩沖區(qū)讀數(shù)時(shí),首先要獲得互斥鎖,并且判斷緩沖區(qū)是否為空,也就是判斷寫指針是否等于讀指針,如果相等則進(jìn)入等待狀態(tài),等候條件變量notempty發(fā)出信號(hào);如果判斷結(jié)果為不等,則從緩沖區(qū)讀出一個(gè)整數(shù),同時(shí)設(shè)置條件變量notfull。最后釋放互斥鎖。 第三節(jié)第三節(jié) Linux多線程庫(kù)編程多線程庫(kù)編程 四、簡(jiǎn)述緩沖區(qū)的具體操作四、簡(jiǎn)述緩沖區(qū)的具體操作 條件變量初始化條件變量初始化int pth

31、read_cond_init (pthread_cond_t * cond, _const pthread_condattr_t * cond_attr) 第一個(gè)參數(shù)為指向結(jié)構(gòu)pthread_cond_t的指針,即條件變量名。第二個(gè)參數(shù)為指向結(jié)構(gòu)const pthread_condattr_t的指針,用來(lái)設(shè)置該條件變量是進(jìn)程內(nèi)可用還是進(jìn)程間可用。在該例中默認(rèn)值是PTHREAD_PROCESS_PRIVATE,即該條件變量可被同一個(gè)進(jìn)程內(nèi)的各個(gè)線程使用。 條件變量喚醒條件變量喚醒extern int pthread_cond_signal (pthread_cond_t *_cond) 它用來(lái)釋

32、放被阻塞在一個(gè)條件變量cond上的線程。如果條件變量cond阻塞的是多線程的話,喚醒哪一個(gè)線程則是由線程的調(diào)度策略來(lái)決定的。第三節(jié)第三節(jié) Linux多線程庫(kù)編程多線程庫(kù)編程 五、幾個(gè)線程五、幾個(gè)線程API 條件變量阻塞條件變量阻塞extern int pthread_cond_wait (pthread_cond_t *_restrict_cond,pthread_mutex_t *_restrict _mutex) 線程解開(kāi)mutex指向的鎖并被條件變量cond阻塞。該線程可以被pthread_cond_signal喚醒,但是條件變量只起阻塞和喚醒線程的作用。線程被喚醒后,它將重新檢查判斷條

33、件是否滿足,如果還不滿足,則線程應(yīng)該仍阻塞在這里,等待下一次喚醒。因此,這個(gè)過(guò)程一般用while語(yǔ)句實(shí)現(xiàn)。 互斥鎖初始化互斥鎖初始化pthread_mutex_init (pthread_mutex_t *mp,_const pthread_mutexattr_t *mattr) 當(dāng)輸入?yún)?shù)mattr為空指針時(shí),該函數(shù)以默認(rèn)值初始化由參數(shù)mp指定的互斥鎖。當(dāng)輸入?yún)?shù)mattr指向一個(gè)互斥鎖屬性對(duì)象時(shí),該函數(shù)用來(lái)創(chuàng)建一個(gè)指定屬性的互斥鎖,其屬性為參數(shù)mattr指向的互斥鎖屬性對(duì)象的屬性。初始化一個(gè)互斥鎖之后,該互斥鎖處在解鎖狀態(tài)。第三節(jié)第三節(jié) Linux多線程庫(kù)編程多線程庫(kù)編程 五、幾個(gè)線程五、

34、幾個(gè)線程API 互斥鎖鎖定互斥鎖鎖定int pthread_mutex_lock (pthread_mutex_t *_mutex) 鎖定mutex參數(shù)指向的互斥鎖對(duì)象。當(dāng)這個(gè)函數(shù)返回時(shí),相應(yīng)的互斥鎖被鎖定,調(diào)用pthread_mutex_lock函數(shù)的線程將成為這個(gè)互斥鎖的擁有者。如果此時(shí)這個(gè)互斥鎖被其他線程所擁有,那么這個(gè)線程將一直被阻塞,直到獲得這個(gè)互斥鎖。 互斥鎖解鎖互斥鎖解鎖int pthread_mutex_unlock (pthread_mutex_t *_mutex) 解開(kāi)已經(jīng)鎖定的互斥鎖。當(dāng)使用pthread_mutex_unlock解開(kāi)一個(gè)互斥鎖時(shí),如果有多個(gè)線程被該互斥鎖

35、阻塞,那么系統(tǒng)將根據(jù)調(diào)度策略決定由哪個(gè)線程獲得該互斥鎖。一般是按照優(yōu)先級(jí)高低來(lái)釋放阻塞線程。 第三節(jié)第三節(jié) Linux多線程庫(kù)編程多線程庫(kù)編程 五、幾個(gè)線程五、幾個(gè)線程API 第四節(jié)第四節(jié) 進(jìn)程創(chuàng)建以及進(jìn)程間通信進(jìn)程創(chuàng)建以及進(jìn)程間通信一、進(jìn)程概述一、進(jìn)程概述 二、進(jìn)程的相關(guān)函數(shù)二、進(jìn)程的相關(guān)函數(shù) 三、信號(hào)概述三、信號(hào)概述 四、信號(hào)的相關(guān)函數(shù)四、信號(hào)的相關(guān)函數(shù) 五、管道概述五、管道概述 六、管道相關(guān)函數(shù)六、管道相關(guān)函數(shù) 第四節(jié)第四節(jié) 進(jìn)程創(chuàng)建以及進(jìn)程間通信進(jìn)程創(chuàng)建以及進(jìn)程間通信 一、進(jìn)程概述一、進(jìn)程概述 在一個(gè)操作系統(tǒng)中,每個(gè)正在運(yùn)行的工作都可以稱為進(jìn)程(process)。它包括進(jìn)程標(biāo)識(shí)符和相關(guān)

36、的數(shù)據(jù),相關(guān)數(shù)據(jù)又包含進(jìn)程變量、外部變量以及進(jìn)程堆棧等。當(dāng)一個(gè)進(jìn)程啟動(dòng)之后,系統(tǒng)會(huì)指定一個(gè)唯一的數(shù)值來(lái)作為該進(jìn)程的進(jìn)程標(biāo)識(shí)符,即PID。 在Linux系統(tǒng)下,可以使用ps命令 查看進(jìn)程。ps命令用來(lái)顯示系統(tǒng)中 正在運(yùn)行的進(jìn)程及其狀態(tài) 如果想查看所有進(jìn)程及其它們的CPU、內(nèi)存占用率以及所屬用戶等信息,可以用top命令 在Linux系統(tǒng)中,進(jìn)程的相關(guān)函數(shù)包括:getpid():用來(lái)獲得當(dāng)前進(jìn)程的進(jìn)程標(biāo)識(shí)符。返回當(dāng)前進(jìn)程的pid。extern _pid_t getpid (void) _THROW;getppid():用來(lái)取得父進(jìn)程的進(jìn)程標(biāo)識(shí)符。返回當(dāng)前進(jìn)程的父進(jìn)程的pid。extern _pid_

37、t getppid (void) _THROW;exec():創(chuàng)建新進(jìn)程來(lái)取代舊進(jìn)程,此時(shí)新進(jìn)程的PID數(shù)值和舊進(jìn)程的PID數(shù)值相同。以上三個(gè)函數(shù)都在/usr/include/unistd.h中=定義。其中,exec()函數(shù)族運(yùn)行成功不會(huì)返回,運(yùn)行失敗則返回-1。該函數(shù)族包括如下函數(shù):extern int execv (_const char *_path, char *_const _argv) _THROW;extern int execle (_const char *_path, _const char *_arg, .) _THROW;extern int execl (_const

38、 char *_path, _const char *_arg, .) _THROW;extern int execvp (_const char *_file, char *_const _argv) _THROW;extern int execlp (_const char *_file, _const char *_arg, .) _THROW;第四節(jié)第四節(jié) 進(jìn)程創(chuàng)建以及進(jìn)程間通信進(jìn)程創(chuàng)建以及進(jìn)程間通信 二、進(jìn)程的相關(guān)函數(shù)二、進(jìn)程的相關(guān)函數(shù) system():該函數(shù)可以使用系統(tǒng)的函數(shù)庫(kù)來(lái)建立新進(jìn)程。使用格式如下:int system(const char *string);即可以將/bi

39、n/sh下的string命令行傳到execve函數(shù)中,之后運(yùn)行該程序即相當(dāng)于運(yùn)行string字符串所代表的命令。該函數(shù)調(diào)用/bin/sh時(shí)如果失敗則函數(shù)返回127;其他失敗狀況則函數(shù)返回-1;如果自變量string為空指針則返回非零值。fork():某個(gè)父進(jìn)程可以復(fù)制多個(gè)子進(jìn)程的操作。該函數(shù)用來(lái)產(chǎn)生新的子進(jìn)程,而調(diào)用fork函數(shù)的進(jìn)程則稱為父進(jìn)程。子進(jìn)程會(huì)復(fù)制父進(jìn)程的數(shù)據(jù),并且繼承父進(jìn)程的各種參數(shù),但是由于子進(jìn)程和父進(jìn)程并不使用相同的內(nèi)存空間,所以并不同步。如果創(chuàng)建成功,則在父進(jìn)程中會(huì)返回新建立的子進(jìn)程代碼(PID),子進(jìn)程中成功返回0,失敗則返回-1。 extern _pid_t fork

40、(void) _THROW;exit():用來(lái)終止進(jìn)程。extern void exit (int _status)status為進(jìn)程的退出狀態(tài)。如果為0,則表示進(jìn)程成功退出;否則如果非0則表示出錯(cuò)。第四節(jié)第四節(jié) 進(jìn)程創(chuàng)建以及進(jìn)程間通信進(jìn)程創(chuàng)建以及進(jìn)程間通信 二、進(jìn)程的相關(guān)函數(shù)二、進(jìn)程的相關(guān)函數(shù) wait():該函數(shù)能夠暫停父進(jìn)程的運(yùn)行,使其等待子進(jìn)程。當(dāng)子進(jìn)程運(yùn)行完畢之后,等待中的父進(jìn)程將會(huì)重新運(yùn)行。不過(guò)如果有多個(gè)子進(jìn)程在運(yùn)行,則當(dāng)?shù)谝粋€(gè)子進(jìn)程完成并返回,則父進(jìn)程開(kāi)始重新執(zhí)行。extern _pid_t wait (_WAIT_STATUS _stat_loc) _THROW;wait()函

41、數(shù)運(yùn)行成功之后返回子進(jìn)程PID,如果失敗則返回-1。waitpid():該函數(shù)能夠暫停當(dāng)前進(jìn)程的運(yùn)行,使其等待子進(jìn)程。當(dāng)子進(jìn)程運(yùn)行完畢之后,等待中的父進(jìn)程將會(huì)重新運(yùn)行。waitpid()函數(shù)運(yùn)行成功之后返回子進(jìn)程PID,如果失敗則返回-1。extern _pid_t waitpid (_pid_t _pid, int *_stat_loc, int _options) _THROW; 函數(shù)wait()和waitpid()都用于清除zombie進(jìn)程。所謂zombie進(jìn)程,是指已經(jīng)結(jié)束運(yùn)行,卻還沒(méi)有被清除的進(jìn)程。當(dāng)父進(jìn)程結(jié)束了之后,子進(jìn)程有可能還沒(méi)有結(jié)束,這樣的話子進(jìn)程就會(huì)作為zombie進(jìn)程而沒(méi)

42、有被清除。因此,可以在父進(jìn)程中調(diào)用wait()或者waitpid()函數(shù)以在父進(jìn)程結(jié)束之前自動(dòng)清除子進(jìn)程,保證清除zombie進(jìn)程。 第四節(jié)第四節(jié) 進(jìn)程創(chuàng)建以及進(jìn)程間通信進(jìn)程創(chuàng)建以及進(jìn)程間通信 二、進(jìn)程的相關(guān)函數(shù)二、進(jìn)程的相關(guān)函數(shù) 由于進(jìn)程的運(yùn)行和安排具有無(wú)序性,其具體操作過(guò)程都是由操作系統(tǒng)進(jìn)行統(tǒng)籌,因此有時(shí)需要人為對(duì)進(jìn)程進(jìn)行一定的順序化處理,這是通過(guò)在進(jìn)程之間進(jìn)行通信實(shí)現(xiàn)的。 在進(jìn)程之間的通信方法中,信號(hào)是常用的方法之一。進(jìn)程之間可以通過(guò)信號(hào)來(lái)通知異步事件的發(fā)生。信號(hào)本身并不直接攜帶信息,但是每種信號(hào)都有特定的含義。理解信號(hào)的各種含義之后,就可以編寫信號(hào)處理函數(shù)來(lái)實(shí)時(shí)響應(yīng)信號(hào)的發(fā)生。當(dāng)信號(hào)產(chǎn)

43、生之后,內(nèi)核會(huì)自動(dòng)將信號(hào)分送到相應(yīng)的進(jìn)程之中。如果編寫了相應(yīng)的信號(hào)處理函數(shù),則可以在接受這些信號(hào)之后進(jìn)行相關(guān)的處理,非常方便。第四節(jié)第四節(jié) 進(jìn)程創(chuàng)建以及進(jìn)程間通信進(jìn)程創(chuàng)建以及進(jìn)程間通信 三、信號(hào)概述三、信號(hào)概述常見(jiàn)的信號(hào)名稱及其含義如下表所示 信號(hào)名稱信號(hào)含義SIGALRM定時(shí)器計(jì)時(shí)完成信號(hào)SIGINT中斷信號(hào)(CTRL+C)SIGQUIT退出信號(hào)(CTRL+)SIGCHILD子進(jìn)程結(jié)束信號(hào)SIGTERM該信號(hào)由系統(tǒng)提供,用來(lái)終止進(jìn)程的運(yùn)行SIGUSR1 / SIGUSR2用戶保留自行發(fā)送信號(hào)SIGKILL該信號(hào)在進(jìn)程之間發(fā)送,接收信號(hào)的進(jìn)程將終止運(yùn)行SIGSTOP該信號(hào)可以使進(jìn)程暫時(shí)終止運(yùn)行

44、第四節(jié)第四節(jié) 進(jìn)程創(chuàng)建以及進(jìn)程間通信進(jìn)程創(chuàng)建以及進(jìn)程間通信 三、信號(hào)概述三、信號(hào)概述signal():用來(lái)接收一個(gè)指定類型的信號(hào),并調(diào)用相關(guān)的信號(hào)處理函數(shù)。void (*signal (int sig, void (*func)(int)(int)函數(shù)會(huì)根據(jù)sig指定的信號(hào)進(jìn)行處理。當(dāng)相關(guān)信號(hào)到達(dá)之后,就會(huì)自動(dòng)調(diào)轉(zhuǎn)到func指定的函數(shù)中運(yùn)行。運(yùn)行結(jié)束后,會(huì)返回到信號(hào)處理函數(shù)的函數(shù)指針,如果有錯(cuò)誤發(fā)生,則返回-1。signal的參數(shù)說(shuō)明如表2-4所示。第四節(jié)第四節(jié) 進(jìn)程創(chuàng)建以及進(jìn)程間通信進(jìn)程創(chuàng)建以及進(jìn)程間通信 四、信號(hào)的相關(guān)函數(shù)四、信號(hào)的相關(guān)函數(shù) 參數(shù)說(shuō)明sig用來(lái)指定相應(yīng)的信號(hào),但是不包括SI

45、GKILL和SIGSTOP。func信號(hào)處理函數(shù)的函數(shù)指針,表示對(duì)信號(hào)的處理方式。一般來(lái)說(shuō),參數(shù)func除了表示指定信號(hào)處理函數(shù)外,還可以表示兩個(gè)常量常量說(shuō)明SIG_IGN表示要忽略的信號(hào)。SIG_DFL表示要恢復(fù)系統(tǒng)對(duì)信號(hào)的默認(rèn)處理功能alarm():設(shè)置SIGALRM信號(hào)在經(jīng)過(guò)參數(shù)指定的秒數(shù)之后,傳送給當(dāng)前的進(jìn)程。extern unsigned int alarm (unsigned int _seconds) _THROW;kill():將sig參數(shù)所指定的信號(hào)傳送給pid參數(shù)所指定的進(jìn)程。extern int kill (_pid_t _pid, int _sig) _THROW;其中pid參數(shù)可以是某個(gè)PID,也可以是如表2-6所示的數(shù)值:pid參數(shù)的含義pid說(shuō)明pid=0信號(hào)被發(fā)送到和當(dāng)前進(jìn)程位于相同進(jìn)程組的所有進(jìn)程pid=-1信號(hào)按照pid從高到低的順序發(fā)送給所有的進(jìn)程pid-1信號(hào)發(fā)送給進(jìn)程組號(hào)為pid絕對(duì)值的所有進(jìn)程pause():該函數(shù)會(huì)暫停當(dāng)前的進(jìn)程,直到接收到信號(hào)之后再繼續(xù)運(yùn)行。該

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論