UNIX環(huán)境C語言編程_第1頁
UNIX環(huán)境C語言編程_第2頁
UNIX環(huán)境C語言編程_第3頁
UNIX環(huán)境C語言編程_第4頁
UNIX環(huán)境C語言編程_第5頁
已閱讀5頁,還剩33頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、第一章概述1.1UNIX的版本UNIX操作系統(tǒng)是貝爾實驗室于六十年代末用C語言研制開發(fā)的。經(jīng)過幾十年的發(fā)展,已經(jīng)成為流行于從大型機(jī)、小型機(jī)到工作站甚至微機(jī)等多種平臺的操作系統(tǒng)。UNIX的成功同時也推動了C語言的普及。本教材的目的是講解UNIX系統(tǒng)下的C程序設(shè)計,使C程序員快速掌握UNIX系統(tǒng)下的編程開發(fā)。作者在進(jìn)行UNIX編程開發(fā)的實踐過程中,深感實例的重要性,一個簡短的C語言實例往往勝過長篇累牘的文字說明,當(dāng)然了,文字說明也是必不可少的。本教材將本著實例優(yōu)先的原則,使您能夠?qū)NIX編程開發(fā)快速入門。UNIX的版本不統(tǒng)一是出了名的,從UNIX的發(fā)展歷史來看,主要有兩大流派:AT&T的UNIX

2、系統(tǒng)V版本和加州大學(xué)伯克利分校的BSD版本,在此基礎(chǔ)上,各家UNIX廠商均開發(fā)了各自的UNIX操作系統(tǒng)。如:工作站廠商中有HP的hpux、SUN的Solaris、SGI的irix、IBM的AIX等,小型機(jī)有VAX上的Ultrix,微機(jī)上有SCOUNIX、微軟的Xenix以及隨著Internet而風(fēng)靡全球的Linux等。由于WindowsNT的異軍突起,對UNIX的市場形成巨大的威脅,各大UNIX廠商不得不聯(lián)合起來,在工作站市場上,統(tǒng)一以系統(tǒng)V版作為標(biāo)準(zhǔn),加入BSD版本中的一些優(yōu)點,支持統(tǒng)一的CDE(CommonDesktopEnvironment)窗口環(huán)境,以與WindowsNT進(jìn)行對抗。1.

3、2UNIX編程環(huán)境UNIX操作系統(tǒng)通過Shell程序?qū)崿F(xiàn)系統(tǒng)與用戶的交互,在Shell提示符下,用戶鍵入UNIX命令,即可得到操作系統(tǒng)的輸出結(jié)果。BSD系統(tǒng)的常用Shell是CShell,缺省提示符是,系統(tǒng)V的常用Shell是BourneShell(現(xiàn)在多為KornShell),缺省提示符是$”,有關(guān)Shell的編程,我們在后面的章節(jié)中進(jìn)行介紹。UNIX上的標(biāo)準(zhǔn)編譯器是cc。在Shell提示符下(以CShell為例)鍵入下列命令:$cc-ohellohello.c即將C文件hello.c編譯為可執(zhí)行文件hello。在編譯多個文件生成一個可執(zhí)行文件時,UNIX提供命令make。用戶需要針對多個C

4、文件,按照一定的格式編寫一個叫做Makefile的文本文件。下面是SGI上的一個Makefile的例子:CC=ccCFLAGS=$(DEBUG)-cckr-I$(INC)/X11-DSYSVDEBUG=-gINC=/usr/includeLDFLAGS=-lXext-lXm-lXt-lX11-lPW-lcOBJS=initx.owindowx.oTGTS=showxwinall:$(TGTS)showxwin:$(OBJS)$(CC)-o$(OBJS)$(CFLAGS)$(LDFLAGS)大寫字母的字串是一些宏,CC是編譯器的名字、CFLAGS定義CC的編譯開關(guān)、DEBUG是調(diào)試宏、INC是頭

5、文件所在目錄、LDFLAGS定義了編譯連接庫、OBJ定義了目標(biāo)文件名、TGTS定義了可執(zhí)行文件名。在Shell提示符下直接鍵入:$make即可將Makefile中指定的所有C文件進(jìn)行編譯并生成可執(zhí)行文件。1.3UNIX編程中的基本概念在討論UNIX編程開發(fā)前,首先需要闡明系統(tǒng)調(diào)用和庫函數(shù)這兩個概念。一個系統(tǒng)調(diào)用指一個需要操作系統(tǒng)代表用戶程序來執(zhí)行某些任務(wù)的請求。例如:read是一個系統(tǒng)調(diào)用,它請求操作系統(tǒng)存儲在一個磁盤設(shè)備(或其他設(shè)備)上的數(shù)據(jù)去填充一個緩沖區(qū)。如果任何人在他們想執(zhí)行任務(wù)的時候都能隨便訪問設(shè)備,那么后果將是不可預(yù)測的。所以,這種服務(wù)必須請求操作系統(tǒng)來做,它(經(jīng)常是透明地)記錄所

6、有處理每個設(shè)備的請求。而一個庫函數(shù),并不經(jīng)常需要操作系統(tǒng)來執(zhí)行其任務(wù)。例如數(shù)學(xué)庫函數(shù)中的sin(),cos()等,這些計算只需要簡單地對一個有限序列求和,所以并不需要操作系統(tǒng)干預(yù)。在UNIX操作系統(tǒng)中,有一個常用的命令man,可用來查閱命令、庫函數(shù)和系統(tǒng)調(diào)用等的具體使用方法。傳統(tǒng)Unix聯(lián)機(jī)幫助手冊的分節(jié)法為:用戶級命令(User-levelcommands)系統(tǒng)調(diào)用(Systemcalls)庫函數(shù)(Libraryfunctions設(shè)備及驅(qū)動程序(Devicesanddevicedriver)文件格式(Fileformats)游戲(Games)雜項(Variousmiscellaneousst

7、uff-macropackagesetc.系統(tǒng)維護(hù)及操作命令(Systemmaintenanceandoperationcommands第二章標(biāo)準(zhǔn)輸入/輸出庫2.1概述本章介紹UNIX的標(biāo)準(zhǔn)輸入/輸出庫,UNIX提供一些庫函數(shù)完成高級輸入/輸出,為程序員提供了三方面的主要功能:自動開辟緩沖區(qū)。即使一次讀或?qū)懙臄?shù)據(jù)只有幾個字節(jié),庫函數(shù)仍然在大到由數(shù)千個字節(jié)組成的塊中執(zhí)行實際輸入或輸出(緩沖區(qū)大小通常由頭文件stdio.h中的常量BUFSIZ定義)。這個緩沖區(qū)在內(nèi)部開辟給庫函數(shù)使用,對于程序員來說是透明的;自動執(zhí)行輸入和輸出轉(zhuǎn)換。輸入輸出被自動格式化。以上兩點在C語言的教程中一般均以講到。在標(biāo)準(zhǔn)輸

8、入/輸出庫中,一個文件被稱為一串字符流,并且被一個指向類型為FILE的目標(biāo)指針?biāo)枋?,該指針被稱為文件指針。在UNIX中文件指針stdin、stdout、stderr是預(yù)先定義好的,分別對應(yīng)標(biāo)準(zhǔn)輸入(鍵盤)、標(biāo)準(zhǔn)輸出(終端屏幕)和標(biāo)準(zhǔn)錯誤輸出。2.2庫函數(shù)介紹文件創(chuàng)建和關(guān)閉fopen()用于打開已存在的文件或創(chuàng)建新文件文件讀寫1、一次處理一個字符getc(),putc()2、一次處理多個字符fgets(),fputs()3、文件的二進(jìn)制讀寫fread(),fwrite()4、文件的格式化輸入/輸出fscanf(),fprintf()5、字符串的格式化輸入/輸出sscanf(),sprintf(

9、)文件移動定位用于在文件中移動的標(biāo)準(zhǔn)輸入/輸出庫函數(shù)是fseek(),它接收三個參數(shù):一個文件指針指向一個打開的字符流;一個整數(shù)指明要移動的字節(jié)數(shù),稱為offset;個整數(shù)指明從文件中什么位置移動。第三章低級輸入/輸出3.1概述與第二章內(nèi)容相對應(yīng),本章介紹UNIX系統(tǒng)中通過系統(tǒng)調(diào)用來實現(xiàn)的輸入/輸出,通常稱之為低級輸入/輸出。這些系統(tǒng)調(diào)用能夠直接實現(xiàn)對設(shè)備(如磁帶驅(qū)動器等)的輸入和輸出,程序員能夠決定要使用的緩沖區(qū)的大小,而不象標(biāo)準(zhǔn)輸入/輸出庫函數(shù)那樣透明設(shè)定緩沖區(qū)大小。在標(biāo)準(zhǔn)輸入/輸出庫中,一個文件是由一個文件指針來對應(yīng)的。當(dāng)使用低級界面時,則用一個文件描述字對應(yīng)一個文件。文件描述字是一個小

10、的整數(shù)。有3個事先定義的文件描述字0、1和2,分別對應(yīng)標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯誤輸出。一般說來,文件描述字都是作為系統(tǒng)調(diào)用的第一個參數(shù)給出的。3.2相關(guān)系統(tǒng)調(diào)用介紹文件創(chuàng)建和關(guān)閉open()用于為讀寫而打開一個文件,或用它來創(chuàng)建新文件。intopen(constchar*path,intoflag,./*mode_tmode*/);open使用三個參數(shù):一個字符串path包含要打開的文件名;一個整數(shù)oflag指明文件將被如何打開;整數(shù)mode在創(chuàng)建文件時使用。常用的oflag包括:O_RDONLY打開文件僅用于讀。O_WRONLY打開文件僅用于寫。O_RDWR打開文件用于讀寫。O_CREAT

11、如果文件不存在,則創(chuàng)建,此時mode作為第三個參數(shù)給出。close。用于關(guān)閉一個已經(jīng)打開的文件。文件讀寫read()用于讀文件,格式為:read(intfildes,void*buf,size_tnbyte);三個參數(shù)說明如下:filedes是文件描述字;指針buf指向一個數(shù)據(jù)將被讀入的緩沖區(qū);整數(shù)nbytes指明要讀的字節(jié)個數(shù)。成功時返回實際讀入的字節(jié)數(shù),出錯則返回-1。write()用于寫文件,與read類似,格式為:write(intfildes,void*buf,size_tnbyte);三個參數(shù)說明如下:filedes是文件描述字;指針buf指向一個數(shù)據(jù)將被寫入的緩沖區(qū);整數(shù)nbyt

12、es指明要寫的字節(jié)個數(shù)。成功時返回實際寫入的字節(jié)數(shù),出錯則返回-1。文件移動定位用于在文件中移動的低級輸入/輸出系統(tǒng)調(diào)用是lseek(),與fseek()類似,它也接收三個參數(shù):一個文件描述字對應(yīng)一個打開的文件;一個整數(shù)指明要移動的字節(jié)數(shù),稱為offset;一個整數(shù)指明從文件中什么位置移動。復(fù)制文件描述字有時候有不只一個文件描述字對應(yīng)一個文件。當(dāng)創(chuàng)建子進(jìn)程時(參加后面關(guān)于進(jìn)程開發(fā)的章節(jié)),這一點很常用。為了獲得一個新的文件描述字,并保證其與fd對應(yīng)同一個文件,應(yīng)調(diào)用fd2=dup(fd)fd2現(xiàn)在和fd對應(yīng)同一個文件,并且和fd樣在文件中有相同的位置。四章文件與目錄編程4.1基本概念文件目錄概

13、述文件系統(tǒng)是UNIX對計算機(jī)技術(shù)的一大貢獻(xiàn)!UNIX系統(tǒng)的文件管理十分靈活、功能強(qiáng)大,許多首次在UNIX系統(tǒng)中出現(xiàn)的概念被其他操作系統(tǒng)所采用,如MS-DOS等。UNIX系統(tǒng)提供了一種層次目錄方案。目錄就象存放一組文件的柜子一樣,目錄也可以包括在其他目錄中,這樣就形成了一種龐大的、具有分支的組織方式,這種結(jié)構(gòu)通常被稱為樹狀結(jié)構(gòu)。目錄實際上也是一種特殊的文件。命令、數(shù)據(jù)文件、其他命令甚至設(shè)備(特別文件)都可以作為目錄中的項(文件)。I標(biāo)識號、I列表和I節(jié)點一個目錄是由一系列結(jié)構(gòu)組成的;每個結(jié)構(gòu)包含一個文件名和一個指向文件自身的指針,該指針是一個整數(shù),稱為文件的I標(biāo)識號。當(dāng)文件被訪問時,它的I標(biāo)識號

14、用來作為索引打開一個系統(tǒng)表(I列表),系統(tǒng)中存放著文件(I節(jié)點)的實體。I節(jié)點包含了對文件的描述:文件自身的用戶和用戶組ID文件的保護(hù)碼文件內(nèi)容所在的物理磁盤地址文件的大小最后一次I節(jié)點改變的時間,最后一次使用和修改的時間連接該文件的次數(shù),即它出現(xiàn)在其他目錄中的次數(shù)一個指明文件類型的標(biāo)記(目錄、普通文件、特別文件)文件的三級保護(hù)UNIX把使用文件的用戶分成三個等級:文件所有者、同組用戶和其他用戶。文件所有者也稱文件主,是文件的創(chuàng)建者,對該文件擁有所有權(quán)限;同組用戶是具有相同組標(biāo)識號的所有用戶,文件主可以決定一個文件屬于哪個組以及該組用戶對文件的存取權(quán);其他用戶是指與文件主無關(guān)的用戶,他們與文件

15、主不屬于同一個用戶組,其他用戶對一個文件的訪問權(quán)限也由該文件主決定的。一個文件的訪問權(quán)限存放在該文件I節(jié)點的di_mode域中,di_mode的08位表示文件主、文件組用戶和其他用戶對該文件的存取權(quán)限。舉個例子,用Is-l命令可列出文件hello.c的模式和屬性:-rwxr-xr-x1ydsuser589月25日10時54分hello.c最左面一欄顯示了該文件的模式:文件主對該文件可讀(r)、可寫(w)、可執(zhí)行(x),同組用戶對該文件可讀、可執(zhí)行,其他用戶對該文件可讀、可執(zhí)行。相應(yīng)的,di_mode的08位為111101101(0755)。4.2文件編程介紹檢查訪問權(quán)限一access系統(tǒng)調(diào)用a

16、ccess系統(tǒng)調(diào)用的格式為:#includeintaccess(constchar*path,intamode);其中:參數(shù)path指出被檢查文件的路徑,參數(shù)amode指出訪問權(quán)限。Access判斷調(diào)用進(jìn)程的實際用戶對文件path是否具有amode所指定的訪問權(quán)限,若有相應(yīng)權(quán)限,access返回0,否則返回一1。參數(shù)amode可取以下值或它們的邏輯或:R_OK檢查讀權(quán)限W_OK檢查寫權(quán)限X_OK檢查執(zhí)行(搜索)權(quán)限F_OK檢查文件是否存在例如:access(hello.c,R_OK|W_OK),用來檢查實際用戶對文件hello.c是否具有讀/寫權(quán);access(hello.c,F_OK)判斷文

17、件hello.c是否存在。鏈接與刪除文件-link和unlink系統(tǒng)調(diào)用link和unlink系統(tǒng)調(diào)用的格式為:#includeintlink(constchar*path1,constchar*path2);intunlink(constchar*path);其中:參數(shù)pathl指出已經(jīng)存在的要被鏈接的文件路徑名,ath2指出要建立的鏈接文件dink實現(xiàn)path2到pathl的鏈接,相當(dāng)于給pathl起了一個別名,同時文件pathl的鏈接計數(shù)加1。若成功則返回0,否則返回-1。參數(shù)path指出要被刪除的文件路徑名。Unlink刪除由path指出的文件,若成功則返回0,否則返回一1。從I節(jié)點上

18、獲取信息一stat與fstat系統(tǒng)調(diào)用stat與fstat的調(diào)用格式為:#include#includeintstat(constchar*path,structstat*buf);intfstat(intfildes,structstat*buf);說明:stat和fstat都用于獲取文件I節(jié)點中有關(guān)狀態(tài)信息。stat根據(jù)參數(shù)path給出的文件路徑名,搜索它對應(yīng)的盤I節(jié)點,而fstat則根據(jù)參數(shù)fildes給出的文件描述字去查找對應(yīng)的I節(jié)點。這兩個調(diào)用都把從I節(jié)點中獲取到的信息重組后放入?yún)?shù)buf指向的stat結(jié)構(gòu)中(stat結(jié)構(gòu)的說明在文件/usr/include/sys/stat.h中)

19、。這兩個調(diào)用成功時均返回0,否則返回-1。stat與fstat調(diào)用無論在使用上還是在功能上都是非常類似的,在參數(shù)上有一點區(qū)別。下面我們來看一個例子。/*statfile.c*/#include#include#include#includemain(argc,argv)intargc;char*argv;intfd;structstatstatbuf;if(argc!=2)printf(usage:statfilefilename!n);exit(1);if(fd=fopen(argv1,O_RDONLY)=-1)fprintf(stderr,Cannotopen%s!n,argv1);if(

20、unlink(argv1)=-1)fprintf(stderr,Cannotunlink%s!n,argv1);if(stat(argv1,&statbuf)=-1)/*byfilename*/fprintf(stderr,stat%sfailsasitshould!n);elseprintf(stat%ssucceed!n,argv1);if(fstat(fd,&statbuf)=-1)/*byfiledescriptor*/fprintf(stderr,fstat%sfails!n,argv1);elseprintf(fstat%ssucceedsasitshould!n,argv1);程

21、序首先打開命令行中指定的文件,然后用unlink將該文件刪除,接著分別用stat與fstat系統(tǒng)調(diào)用獲取該文件的信息。假設(shè)當(dāng)前命令下有一個名為xxx.c的文件,運行%statfilexxx.c后,將會輸出如下結(jié)果:statxxx.cfailsasitshould!fstatxxx.csucceedsasitshould!從中可知,當(dāng)一個打開文件被刪除后,用stat無法獲取該文件的信息。而fstat就可獲取該文件的信息。這是由于文件名在unlink之后已從目錄中除去,無法找到該文件名,而文件描述字則因文件仍打開而保存下來。因此stat不能成功返回,但fstat仍可成功返回。使用stat調(diào)用來判定

22、一個文件為何種文件類型時相當(dāng)有用。例如下列代碼:stat(hello,&statbuf);if(statbuf.st_mod&S_IFMT)=S_IFDIR)printf(Thisisadirectoryfile!n);elseif(statbuf.st_mod&S_IFMT)=S_IFREG)printf(Thisisaregularfile!n);else以上代碼可判定當(dāng)前目錄下的hello文件是否為目錄文件或其他類型的文件。4.3目錄編程介紹UNIX把目錄也視為一種文件,稱為目錄文件,并同普通文件一樣進(jìn)行管理和保護(hù)。如open、close、read、lseek等文件操作對目錄文件都是有效

23、的。前面講到的文件編程中的各個系統(tǒng)調(diào)用對于目錄來說也同樣有效。但是與普通文件相比目錄文件又具有自身的一些特點:目錄文件的讀/寫/執(zhí)行訪問權(quán)限有特殊的含義:讀權(quán)限允許用戶讀取目錄項的內(nèi)容;寫權(quán)限允許用戶創(chuàng)建或刪除一個文件;執(zhí)行權(quán)限則允許用戶檢索目錄(此時通常稱為目錄搜索權(quán)限)。目錄的創(chuàng)建、刪除與普通文件也不同,另外,任何用戶都不能對目錄文件以寫方式打開進(jìn)行文件寫操作。目錄的創(chuàng)建和刪除一mkdir和rmdir系統(tǒng)調(diào)用mkdir和rmdir系統(tǒng)調(diào)用的格式為:#include#includeintmkdir(constchar*path,mode_tmode);#includeintrmdir(con

24、stchar*path);其中:參數(shù)path分別指出要創(chuàng)建和刪除的目錄文件的文件名。mkdir調(diào)用中的參數(shù)mode指出新創(chuàng)建目錄文件的文件模式。新創(chuàng)建目錄后,除.和.兩項外,無別的目錄項;刪除目錄時,要求目錄中除.和.兩項外,也無別的目錄項。這兩個系統(tǒng)調(diào)用Access成功時都返回0,否則返回一1。目錄的讀取一opendir/readdir/closedir庫函數(shù)目錄文件可以像普通文件一樣,先用系統(tǒng)調(diào)用open以讀方式打開,再用read調(diào)用讀取其中的內(nèi)容。同時,由于目錄文件是由具有目錄結(jié)構(gòu)的目錄項組成的,用read讀取其內(nèi)容有些不方便UNIX提供的庫函數(shù)opendir/readdir/close

25、dir等可以方便地實現(xiàn)目錄讀取。函數(shù)說明如下:#include#includeDIR*opendir(char*filename);structdirect*readdir(DIR*dirp);voidclosedir(DIR*dirp);說明:參數(shù)filename指出要打開的目錄路徑名,庫函數(shù)opendir返回一個指向結(jié)構(gòu)DIR(在文件/usr/include/sys/dir.h中定義)的指針。庫函數(shù)readdir和closedir均以這個指針作為參數(shù),其中readdir返回一個指向結(jié)構(gòu)direct的指針。有關(guān)目錄的操作均可基于這個指針。下面是一個例子,查找當(dāng)前目錄下文件名為name的文件。

26、len=strlen(name);dirp=opendir(.);if(dirp=NULL)returnNOT_FOUND;while(dp=readdir(dirp)!=NULL)if(dp-d_namlen=len&!strcmp(dp-d_name,name)closedir(dirp);returnFOUND;closedir(dirp);returnNOT_FOUND;庫函數(shù)closedir關(guān)閉打開的目錄。值得注意的是,上面這一小段代碼在編程中很實用,稍加修改即可實現(xiàn)UNIX下類似ls的簡單命令。第五章基本進(jìn)程編程5.1概述UNIX系統(tǒng)為程序員提供了一個強(qiáng)有力的工具:在一個程序中執(zhí)行

27、另一個程序。執(zhí)行一個程序最簡單的途徑就是使用庫函數(shù)system。該函數(shù)使用一個參數(shù):一個包含要被執(zhí)行的命令的字符串。這一庫函數(shù)的特點是用法簡單,在程序中調(diào)用簡單的UNIX命令時很有用。但是由于它的調(diào)用要由SHELL進(jìn)程來實現(xiàn),故效率并不高,在實際的編程中應(yīng)用并不廣泛。本章主要介紹在實際編程中經(jīng)常使用的有關(guān)進(jìn)程控制和管理方面的系統(tǒng)調(diào)用,它們包括:fork創(chuàng)建一子進(jìn)程exec執(zhí)行子進(jìn)程exit終止進(jìn)程執(zhí)行wait等待子進(jìn)程暫?;蚪K止setpgrp設(shè)置進(jìn)程標(biāo)識符getpid、getppid獲取進(jìn)程標(biāo)識符setuid、setgid設(shè)置進(jìn)程的用戶標(biāo)識符getuid、geteuid、getgid、gete

28、gid獲取進(jìn)程的用戶標(biāo)識符5.2進(jìn)程控制1.fork系統(tǒng)調(diào)用系統(tǒng)調(diào)用fork是UNIX操作系統(tǒng)創(chuàng)建新進(jìn)程的唯一手段,習(xí)慣上將新創(chuàng)建的進(jìn)程稱為子進(jìn)程,調(diào)用fork的進(jìn)程稱為父進(jìn)程。fork系統(tǒng)調(diào)用的格式為:intfork()fork系統(tǒng)調(diào)用沒有參數(shù),如執(zhí)行成功,則創(chuàng)建一子進(jìn)程,子進(jìn)程繼承了父進(jìn)程的某些屬性。當(dāng)從該系統(tǒng)調(diào)用返回時,系統(tǒng)中已有兩個用戶級環(huán)境完全相同的進(jìn)程存在。這兩個進(jìn)程從fork調(diào)用中得到的返回值不同,其中子進(jìn)程得到的返回值為零,父進(jìn)程得到的返回值是最新創(chuàng)建的子進(jìn)程的進(jìn)程標(biāo)識符。2.exec系統(tǒng)調(diào)用fork系統(tǒng)調(diào)用只是將父進(jìn)程的環(huán)境拷貝到新進(jìn)程中,而沒有啟動執(zhí)行一個新的目標(biāo)程序。UN

29、IX系統(tǒng)提供了exec系統(tǒng)調(diào)用,用它更換進(jìn)程的執(zhí)行映象,啟動新的目標(biāo)程序。例如:UNIX系統(tǒng)中的所有命令都是通過exec來執(zhí)行的。exec系統(tǒng)調(diào)用有六種不同的使用格式,但在核心中只對應(yīng)一個調(diào)用入口。它們有不同的調(diào)用格式和調(diào)用參數(shù)。這六種調(diào)用格式分別為:#includeintexecl(constchar*path,constchar*arg0,.,constchar*argn,(char*)0);intexecv(constchar*path,char*const*argv);intexecle(constchar*path,constchar*arg0,.,constchar*argn,(c

30、har*0),constchar*envp);intexecve(constchar*path,char*const*argv,char*const*envp);intexeclp(constchar*file,constchar*arg0,.,constchar*argn,(char*)0);intexecvp(constchar*file,char*const*argv);說明:參數(shù)path指出一個可執(zhí)行目標(biāo)文件的路徑名;參數(shù)file指出可執(zhí)行目標(biāo)文件的文件名。arg0作為約定同path一樣指出目標(biāo)文件的路徑名;參數(shù)argl到argn分別是該目標(biāo)文件執(zhí)行時所帶的命令行參數(shù);參數(shù)argv是一

31、個字符串指針數(shù)組,由它指出該目標(biāo)程序使用的命令行參數(shù)表,按約定第一個字符指針指向與path或file相同的字符串;最后一個指針指向一個空字符串,其余的指向該程序執(zhí)行時所帶的命令行參數(shù);參數(shù)envp同argv一樣也是一個字符指針數(shù)組,由它指出該目標(biāo)程序執(zhí)行時的進(jìn)程環(huán)境,它也以一個空指針結(jié)束。exec的六種格式在以下三點上有所不同:path是一個目標(biāo)文件的完整路徑名,而file是目標(biāo)文件名,它是可以通過環(huán)境變量PATH來搜索的;由path或file指定的目標(biāo)文件的命令行參數(shù)是完整的參數(shù)列表或是通過一指針數(shù)組argv來給出的;環(huán)境變量是系統(tǒng)自動傳遞或者通過envp來給出的。下圖說明了exec系統(tǒng)調(diào)用

32、的六種不同格式對以上三點的支持。系統(tǒng)調(diào)用參數(shù)形式環(huán)境傳送路徑搜索Execl全部列表自動否Execv指針數(shù)組自動否Execle全部列表不自動否Execve指針數(shù)組不自動否Execlp全部列表自動是Execvp指針數(shù)組自動是3.exit、wait系統(tǒng)調(diào)用exit系統(tǒng)調(diào)用格式如下:#includevoidexit(intstatus);#includevoid_exit(intstatus);說明:exit的功能是終止進(jìn)程的執(zhí)行,并釋放該進(jìn)程所占用的某些系統(tǒng)資源。參數(shù)status是調(diào)用進(jìn)程終止時傳遞給其父進(jìn)程的值。如果調(diào)用進(jìn)程執(zhí)行exit系統(tǒng)調(diào)用時,其父進(jìn)程正在等待子進(jìn)程暫?;蚪K止(使用wait系統(tǒng)

33、調(diào)用),則父進(jìn)程可立刻得到該值;如果此時父進(jìn)程并不處在等待狀態(tài),那么一旦父進(jìn)程使用wait調(diào)用,便可立刻得到子進(jìn)程傳過來的status值,注意:只有status的低八位才傳遞給其父進(jìn)程。系統(tǒng)調(diào)用_exit與exit之間的差異是_exit只做部分的清除,因此建議不要輕易地使用這種調(diào)用形式。每個進(jìn)程在消亡前都要調(diào)用該系統(tǒng)調(diào)用,沒有顯示地使用該系統(tǒng)調(diào)用,則生成目標(biāo)文件的裝載程序為該進(jìn)程隱含地做這一工作。wait系統(tǒng)調(diào)用格式如下:#include#includepid_twait(int*statptr);說明:wait系統(tǒng)調(diào)用將調(diào)用進(jìn)程掛起,直到該進(jìn)程收到一個被其捕獲的信號或者它的任何一個子進(jìn)程暫停

34、或終止為止。如果在wait調(diào)用之前已有子進(jìn)程暫?;蚪K止,則該調(diào)用立刻返回。格式wait(int*)0)的功能是等待所有子進(jìn)程終止oWait返回時,其返回值為該子進(jìn)程的進(jìn)程號。參數(shù)statptr的值為該子進(jìn)程的終止原因:1、如果子進(jìn)程暫停,statptr目的高八位存放使該子進(jìn)程暫停的信號值(在第七章中介紹信號)低八位為01772、如果子進(jìn)程由于調(diào)用exit終止,則該值的低八位為0,高八位為子進(jìn)程終止時,exit系統(tǒng)調(diào)用中參數(shù)status值的低八位;3、如果子進(jìn)程因信號終止,該值的高八位為0,低八位為引起終止的信號值。此外如低七位為1,則表示產(chǎn)生了一個core文件。下面我們來看一個例子,該例是一個

35、fork、exec、exit和wait聯(lián)合使用的一個實例程序,我們稱之為feew.c:/*feew.c*/main(argc,argv)intargc;char*argv;intpid,stat;if(argc!=1)if(pid=fork()=0)printf(Childpid=%dn,getpid();execl(argv1,argv1,0);exit(5);pid=wait(&stat);printf(pid=%d,H_stat=%d,L_stat=%dn,pid,stat8,stat&0 xff);當(dāng)命令行參數(shù)的個數(shù)不為1時,程序使用fork系統(tǒng)調(diào)用產(chǎn)生一個子進(jìn)程。子進(jìn)程通過系統(tǒng)調(diào)用g

36、etpid獲得自己的進(jìn)程標(biāo)識符,然后調(diào)用exec執(zhí)行命令行中用戶提交的命令,如果exec執(zhí)行失敗,則子進(jìn)程調(diào)用exit(5)終止。父進(jìn)程使用wait系統(tǒng)調(diào)用等待子進(jìn)程暫?;蚪K止,然后輸出從wait中返回的信息。下面以三種方式執(zhí)行該程序:1不帶命令行參數(shù)%./feewpid=-1,H_stat=0,L_stat=0%不產(chǎn)生子進(jìn)程,從運行結(jié)果來看,當(dāng)無子進(jìn)程時,wait的返回值為一1。2帶命令行參數(shù),參數(shù)為合法的可執(zhí)行命令%./feew/bin/dateChildpid=17251998年2月16日(星期一)15時59分14秒CSTpid=1725,H_stat=0,L_stat=0產(chǎn)生子進(jìn)程。子

37、進(jìn)程輸出其進(jìn)程標(biāo)識符后,再調(diào)用exec執(zhí)行從命令行中提交的命令(bin/date),同時父進(jìn)程等待子進(jìn)程暫停或終止,然后輸出從wait中得到的信息:子進(jìn)程標(biāo)識符或狀態(tài)參數(shù)stat的高八位、低八位的內(nèi)容。從中可以看到:子進(jìn)程因調(diào)用一個隱含的exit(O)而終止,終止時傳給父進(jìn)程的值為0。3帶命令行參數(shù),但參數(shù)不合法%./feew/etc/shudownChildpid=1760/etc/shutdown:只有超級用戶(root)能運行/etc/shutdown。pid=1760,H_stat=2,L_stat=0%子進(jìn)程創(chuàng)建成功。但由于以普通用戶的身份執(zhí)行/etc/shutdown,因此exec

38、失敗,爾后調(diào)用exit(5)而終止;父進(jìn)程調(diào)用wait得到返回值:子進(jìn)程號和狀態(tài)參數(shù)stat的高八位、低八位的內(nèi)容。從執(zhí)行結(jié)果可以看出:子進(jìn)程因調(diào)用exit(5)而終止,終止時傳給父進(jìn)程的值為5。5.3進(jìn)程管理進(jìn)程管理包括的面很廣,諸如進(jìn)程的用戶標(biāo)識符管理、進(jìn)程標(biāo)識符管理等。進(jìn)程的用戶標(biāo)識符有兩個:實際用戶標(biāo)識符(realuserid)和有效用戶標(biāo)識符(effectiveuserid),其對應(yīng)的組標(biāo)識符分別稱為實際組標(biāo)識符(realgroupid)和有效組標(biāo)識符(effectivegroudid)。一般而言,進(jìn)程的實際用戶標(biāo)識符為運行該進(jìn)程的用戶標(biāo)識符,通常只用于系統(tǒng)記帳,其他功能由有效用戶標(biāo)

39、識符來完成,如用有效用戶標(biāo)識符來完成對新創(chuàng)建文件賦予屬性關(guān)系、檢查文件的存取權(quán)限和利用kill系統(tǒng)調(diào)用向進(jìn)程發(fā)送信號的權(quán)限。一般情況下,一進(jìn)程的有效用戶標(biāo)識符和實際用戶標(biāo)識符是相等的,但系統(tǒng)允許改變進(jìn)程的有效用戶標(biāo)識符。進(jìn)程的用戶標(biāo)識符管理UNIX系統(tǒng)提供了一組系統(tǒng)調(diào)用來管理進(jìn)程的用戶標(biāo)識符,它們的使用形式是:#include#includeuid_tgetuid(void);uid_tgeteuid(void);gid_tgetgid(void);gid_tgetegid(void);intsetuid(uid_tuid);intsetgid(gid_tgid);說明:前四個系統(tǒng)調(diào)用沒有參數(shù)

40、,分別返回調(diào)用進(jìn)程的實際用戶標(biāo)識符、有效用戶標(biāo)識符、實際用戶組標(biāo)識符和有效組標(biāo)識符。這些系統(tǒng)調(diào)用的執(zhí)行總能獲得成功,不會發(fā)生任何錯誤。系統(tǒng)調(diào)用setuid和setgid用于設(shè)置進(jìn)程的實際用戶(組)標(biāo)識符和有效用戶(組)標(biāo)識符,如調(diào)用進(jìn)程的有效用戶標(biāo)識符是超級用戶標(biāo)識符,則將調(diào)用的進(jìn)程實際用戶(組)標(biāo)識符和有效用戶(組)標(biāo)識符設(shè)置為uid或gid;如調(diào)用進(jìn)程的有效用戶標(biāo)識符不是超級用戶標(biāo)識符,但其實際用戶(組)標(biāo)識符等于uid或gid時,則其有效用戶(組)標(biāo)識符被設(shè)置為uid或gid;否則setuid或setgid調(diào)用失敗。系統(tǒng)調(diào)用setuid或setgid調(diào)用成功時返回0,失敗時返回1。進(jìn)程標(biāo)

41、識符管理UNIX系統(tǒng)使用進(jìn)程標(biāo)識符來管理當(dāng)前系統(tǒng)中的進(jìn)程。為對具有某類似特性的進(jìn)程統(tǒng)一管理,系統(tǒng)又引入了進(jìn)程組的概念,以組標(biāo)識符來區(qū)別進(jìn)程是否同組。進(jìn)程的組標(biāo)識符是從父進(jìn)程繼承下來的,所以,通常進(jìn)程的組標(biāo)識符就是和它相關(guān)聯(lián)的注冊進(jìn)程的標(biāo)識符。進(jìn)程的標(biāo)識符是由系統(tǒng)為之分配的,不能被修改;組標(biāo)識符可通過setpgrp系統(tǒng)調(diào)用修改。相關(guān)系統(tǒng)調(diào)用的格式如下:#include#includepid_tgetpid(void);pid_tgetpgrp(void);pid_tgetppid(void);pid_tgetpgid(pid_tpid);說明:前三個系統(tǒng)調(diào)用分別返回調(diào)用進(jìn)程的進(jìn)程標(biāo)識符、進(jìn)程組標(biāo)

42、識符和其父進(jìn)程標(biāo)識符。它們總能成功地返回。第四個調(diào)用置進(jìn)程組標(biāo)識符,它將調(diào)用進(jìn)程的進(jìn)程組標(biāo)識符改為調(diào)用進(jìn)程的進(jìn)程標(biāo)識符,使其成為進(jìn)程組首進(jìn)程,并返回這一新的進(jìn)程組標(biāo)識符。下面我們來看一個實例:/*setuid.c*/main(argc,argv)intargc;char*argv;intret,uid;uid=atoi(argv1);printf(Beforeuid=%d,euid=%dn,getuid(),geteuid();ret=setuid(uid);printf(Afteruid=%d,euid=%dn,getuid(),geteuid();printf(ret=%dn,ret);下

43、面分三種情況討論該程序的執(zhí)行:1、如果執(zhí)行該程序的用戶為超級用戶,則只要命令行所給的用戶標(biāo)識符大于0,無論所給的用戶標(biāo)識符是否存在,執(zhí)行總能成功。#./setuid3434Beforeuid=0,euid=0Afteruid=3434,euid=3434ret=0結(jié)果分析:將進(jìn)程的實際和有效用戶標(biāo)識符均改為3434。2、如果執(zhí)行該程序的用戶為一般用戶,用d命令得到用戶uid和gid后,再調(diào)用該程序,過程如下:%iduid=1111(yds)gid=20(user)%./setuid3434Beforeuid=1111,euid=1111Afteruid=1111,euid=1111ret=-1

44、%./setuid1111Beforeuid=1111,euid=1111Afteruid=1111,euid=1111ret=0%結(jié)果分析:當(dāng)命令行參數(shù)為1111時,setuid執(zhí)行成功,因為用戶的uid就是1111。值得注意的是:注冊程序login是個典型的setuid系統(tǒng)調(diào)用程序,login進(jìn)程的有效用戶是超級用戶,該進(jìn)程在建立用戶的Shell進(jìn)程前,調(diào)用setuid將實際和有效用戶標(biāo)識符調(diào)整為注冊用戶的用戶實際和有效標(biāo)識符。六章設(shè)備輸入/輸出控制6.1概述UNIX將設(shè)備看成文件,這是UNIX的一大特色。這里需要介紹一個設(shè)備號的概念。設(shè)備特別文件與兩個設(shè)備號有關(guān)主設(shè)備號和次設(shè)備號。主設(shè)備

45、號告訴操作系統(tǒng),當(dāng)涉及文件名時,將使用哪種設(shè)備類型。對于每一種類型的設(shè)備都有一段駐留在操作系統(tǒng)中的程序代碼,以控制相應(yīng)類型的設(shè)備,這段代碼被稱為設(shè)備驅(qū)動程序。次設(shè)備號被傳遞給設(shè)備驅(qū)動程序,這個號碼用來決定使用哪種物理設(shè)備。例如,決定在一塊多重驅(qū)動控制卡上,哪個磁盤驅(qū)動器將被訪問,以及該磁盤驅(qū)動器中哪一部分將被使用;或者,當(dāng)一個磁盤驅(qū)動器所請求的操作已經(jīng)完成后,應(yīng)該被恢復(fù)原狀。幾個設(shè)備(如同類型的磁盤驅(qū)動器)可以用同一個主設(shè)備號,但它們將有不同的次設(shè)備號。看下面的例子:%ls-l/dev/ttyq*crw-w2ydsuser15,12月17日09時03分ttyq1crw-w2ydsuser15,

46、142月16日17時00分ttyq14%上例中15是主設(shè)備號,1和14是次設(shè)備號。用戶可以使用系統(tǒng)提供的統(tǒng)一而且獨立于設(shè)備的界面對文件進(jìn)行操作的系統(tǒng)調(diào)用來操作設(shè)備,而沒有必要涉及設(shè)備的具體細(xì)節(jié)。大部分對文件進(jìn)行操作的系統(tǒng)調(diào)用對它們?nèi)云鹱饔?,例如,用open打開設(shè)備,用read/write對設(shè)備進(jìn)行讀/寫,設(shè)備操作完成后,用close關(guān)閉設(shè)備。但有的系統(tǒng)調(diào)用在對設(shè)備文件進(jìn)行操作時,其功效有所不同。如create及open的創(chuàng)建方式都不能創(chuàng)建設(shè)備文件。6.2設(shè)備輸入/輸出控制一ioctl系統(tǒng)調(diào)用ioctl是UNIX系統(tǒng)專門提供的用于設(shè)備控制的系統(tǒng)調(diào)用。該系統(tǒng)調(diào)用與設(shè)備類型(即主設(shè)備號)相關(guān)。不同的

47、設(shè)備,系統(tǒng)提供了不同的控制命令。ioctl的調(diào)用格式是:ioctl(intfd,intcmd,arg說明:參數(shù)fd是一設(shè)備文件的文件描述字,cmd是控制命令,它與設(shè)備相關(guān),不同類型的設(shè)備有不同的控制命令。參數(shù)arg沒有固定的數(shù)據(jù)結(jié)構(gòu),它隨cmd的不同而不同。七章高級編程7.1處理信號信號是UNIX進(jìn)程間最基本的通訊手段,主要作用是實現(xiàn)進(jìn)程間異步事件的通訊。信號是傳送到進(jìn)程的軟中斷,它通知進(jìn)程在它們的環(huán)境中出現(xiàn)了非正常事件。進(jìn)程接收到信號后要進(jìn)行處理,處理方式為以下四種之一:(1)缺省方式(SIG_DFL):這是進(jìn)程對信號的一般處理方式,在無特殊情況下,進(jìn)程在接收到信號后將終止執(zhí)行。有一些信號,

48、在終止進(jìn)程運行前需將終止進(jìn)程的正文段、數(shù)據(jù)段、user結(jié)構(gòu)和棧段內(nèi)容寫到當(dāng)前目錄的core文件中,以備調(diào)試工具分析與使用。(2)忽略方式(SIG_IGN):進(jìn)程接收到一個已指明忽略的信號,則將該信號清除后,立即返回,不在任何工作。信號SIGKILL不能被忽略。(3)保持方式(SIG_HOLD):當(dāng)進(jìn)程處于該方式時,將接收的信號保存起來,等該進(jìn)程的保持方式解除后,再進(jìn)行處理。(4)捕獲方式(設(shè)置信號處理函數(shù)):這是用戶設(shè)置的信號處理方式,當(dāng)進(jìn)程接收到這種信號時,執(zhí)行用戶設(shè)置的信號處理函數(shù),執(zhí)行完后,恢復(fù)現(xiàn)場,然后繼續(xù)往下執(zhí)行。常用信號種類UNIX信號的種類很多,下面介紹一些最常用的信號:SIGH

49、UP掛斷。這是當(dāng)控制終端被掛起時送到進(jìn)程的信號。SIGINT中斷。由鍵盤產(chǎn)生的中斷。SIGQUIT退出。由鍵盤產(chǎn)生的中斷。SIGKILL終止。這個信號不能被捕獲、阻塞或忽略。SIGALRM定時信號。SIGTERM軟件終止信號。SIGUSR1用戶定義的信號1。SIGUSR2用戶定義的信號2。這些信號值的聲明在/usr/include/sys/signal.h文件中。發(fā)送信號一kill系統(tǒng)調(diào)用用戶傳送信號到進(jìn)程的系統(tǒng)調(diào)用是kill,調(diào)用格式為:#include#includeintkill(pid_tpid,intsig);說明:該系統(tǒng)調(diào)用把一個信號值為sig的信號發(fā)送給進(jìn)程標(biāo)識符為pid的相關(guān)進(jìn)

50、程。成功時返回0,失敗時返回1。該調(diào)用執(zhí)行成功與否,依賴于調(diào)用進(jìn)程的有效用戶標(biāo)識符和參數(shù)pid的值,pid值的含義如下:大于0:將信號發(fā)送給進(jìn)程號等于pid的進(jìn)程。等于0:將信號發(fā)送給調(diào)用進(jìn)程的同組進(jìn)程(0和1進(jìn)程除外)。等于1:將信號發(fā)送給實際用戶標(biāo)識符等于調(diào)用進(jìn)程的有效用戶標(biāo)識符的所有進(jìn)程(0和1進(jìn)程除外),如調(diào)用進(jìn)程的有效用戶是超級用戶,則將信號發(fā)送給除0和1進(jìn)程外的所有進(jìn)程。非一1的負(fù)數(shù):將信號發(fā)送給進(jìn)程組標(biāo)識符為pid的絕對值的所有進(jìn)程。在實際編程中,kill系統(tǒng)調(diào)用非常有用,具體說來:常用方式kill(pid,SIGUSR1)向進(jìn)程號為pid的進(jìn)程發(fā)送信號SIGUSR1用來判斷進(jìn)程

51、是否存在:if(kill(pid,0)=0)進(jìn)程號為pid的進(jìn)程存在;else進(jìn)程號為pid的進(jìn)程不存在!用來殺掉子進(jìn)程kill(pid,1)殺掉進(jìn)程號為pid的進(jìn)程2.處理信號一signal系統(tǒng)調(diào)用用戶處理信號的系統(tǒng)調(diào)用是signal,調(diào)用格式為:#includevoid(*signal(intsig,void(*func)()();說明:參數(shù)引g是一個信號值,func定義了該信號的處理方式。該系統(tǒng)定義的功能是按func的定義設(shè)置調(diào)用進(jìn)程對信號sig的處理方式。執(zhí)行成功時,返回調(diào)用進(jìn)程先前對信號sig處理方式的值,失敗則返回一1。參數(shù)取值為SIG_DFL或SIG_IGN或用戶信號處理函數(shù)的地

52、址時,分別表示缺省方式、忽略方式和捕獲方式。3.pause系統(tǒng)調(diào)用pause系統(tǒng)調(diào)用的格式為:pause()說明:該調(diào)用沒有參數(shù),其功能為使調(diào)用進(jìn)程睡眠直到其接收到一信號為止。該系統(tǒng)調(diào)用的結(jié)果依賴于調(diào)用進(jìn)程對接收到的信號的處理方式。缺省方式:終止調(diào)用進(jìn)程,pause無返回值;忽略方式:進(jìn)程不受該信號的影響,繼續(xù)睡眠;捕獲方式:調(diào)用進(jìn)程從信號處理函數(shù)返回后,繼續(xù)往下執(zhí)行。4.使用信號定時一alarm系統(tǒng)調(diào)用系統(tǒng)調(diào)用alarm可以實現(xiàn)定時器的功能,調(diào)用格式為:#includeunsignedalarm(unsignedsec);說明:參數(shù)sec指定定時的時間間隔,以秒為單位。用戶進(jìn)程可以先通過si

53、gnal調(diào)用指定SIGALRM信號對應(yīng)的捕獲函數(shù),然后調(diào)用alarm來設(shè)定鬧鐘,在定時這段時間內(nèi)做自己的工作。定時時間一到,進(jìn)程就接收到一個SIGALRM信號,并執(zhí)行該信號對應(yīng)的捕獲函數(shù)。系統(tǒng)調(diào)用alarm在多進(jìn)程編程中非常有用。7.2管道通訊用信號來處理異常事件或錯誤是非常合適的,但它用來處理進(jìn)程之間的大量信息傳送,就非常不適宜。為此,UNIX又提供了一種稱為管道的機(jī)構(gòu),主要處理進(jìn)程間的大量信息傳送。所謂管道是指進(jìn)程間連接起來的一條通訊通道。它也UNIX文件概念的一種推廣,管道通訊的介質(zhì)是文件,稱為管道文件。用戶可以用文件操作的有關(guān)系統(tǒng)調(diào)用來操作管道文件,從而簡化管道應(yīng)用程序的設(shè)計。管道的形

54、象描述如下圖:write寫端讀端read管道是UNIX最強(qiáng)大而最有特色的性能之一,特別是在命令行這一級,它允許任意的命令被順序連接起來。例如:%who|wc-l該命令通過管道把命令who的輸出送給字計數(shù)程序wc,選項-I告訴wc只計算行數(shù)。通過wc最終輸出的系統(tǒng)已注冊的用戶個數(shù)。1.管道程序設(shè)計在程序中可以用系統(tǒng)調(diào)用ipe建立一個管道。如果建立成功,就返回兩個文件描述符,一個用于寫入管道,一個用于從管道中讀出。Pipe調(diào)用的格式如下:intfiIedes2,retvaI;retvaI=pipe(fiIedes);其中,fildes是一個含有兩個整數(shù)的數(shù)組,用來存放標(biāo)識管道的兩個文件描述符。如果

55、調(diào)用成功,fiIedesO將被打開用于從管道讀,fildes1將被打開用于向管道寫。管道一旦建立,就能直接用read和write操作它。當(dāng)管道與系統(tǒng)調(diào)用fork聯(lián)用時,才能體現(xiàn)出管道的真正價值。這時,可以利用父進(jìn)程已打開的文件,對于其子進(jìn)程仍保持打開這一事實。下面的程序先建立一個管道,然后調(diào)用fork創(chuàng)建子進(jìn)程,父進(jìn)程通過管道向子進(jìn)程發(fā)送信息。打開管道在父進(jìn)程中向管道寫入在子進(jìn)程中從管道讀入程序的輸入結(jié)果如下:ChildRead:hello,world#1ChildRead:hello,world#2ChildRead:hello,world#3管道是在先進(jìn)先出的基礎(chǔ)上處理數(shù)據(jù)的。所以,首先放

56、入管道的數(shù)據(jù),在其另一端首先被讀出。這個順序不能被改變,因為系統(tǒng)調(diào)用Iseek不能用于管道。2.命名管道一FIFO我們已經(jīng)看到,管道是一種功能很強(qiáng)的進(jìn)程通訊機(jī)構(gòu)。但是,它也存在一些嚴(yán)重的缺點。首先,管道只能用于連接具有共同祖先的進(jìn)程,如父子進(jìn)程之間的連接。當(dāng)要開發(fā)一個永遠(yuǎn)保持存在的,提供為全系統(tǒng)范圍服務(wù)的程序時,這一缺點就更加突出,例如網(wǎng)絡(luò)控制服務(wù)程序和打印機(jī)的假脫機(jī)程序等。我們要求調(diào)用進(jìn)程應(yīng)該能夠用管道與任何服務(wù)進(jìn)程進(jìn)行通訊,然后再脫開。遺憾的是,普通管道不能實現(xiàn)上述功能。其次,管道不能是常設(shè)的,在需要時可以建立它們,但是當(dāng)訪問它們的進(jìn)程終止時,管道也隨之被撤銷。所以,它們不可能永久存在。事

57、實上,UNIX系統(tǒng)中的FIFO機(jī)制(又稱命名管道),彌補(bǔ)了上述管道的不足之處。FIFO與管道一樣,也是作為進(jìn)程之間先進(jìn)先出的通訊通道,但是FIFO是一種永久性的機(jī)構(gòu),并且具有一個UNIX文件名。FIFO也具有文件主、長度和訪問權(quán)限。它能象其他UNIX文件那樣被打開、關(guān)閉和刪除。但在讀和寫時,其性能與管道相同。在討論FIFO程序設(shè)計之前,我們先來看一下FIFO在命令級的使用。UNIX命令mknod可以用來創(chuàng)建一個FIFO文件channeI:%/etc/mknodchanneIp%Is-IchanneIprw-r-r-1ydsuser02月17日14時19分channeI命令I(lǐng)s的輸出結(jié)果中的首字

58、母p指出channel是一個FIFO類型的文件。從中我們還可以看到其訪問權(quán)限為文件主可讀寫,組內(nèi)及其他用戶只讀。其用戶主是yds,所屬組為user,長度為0,此外還有文件建立的時間。FIFO程序設(shè)計大部分與管道相同,最主要的區(qū)別是在建立方面。FIFO是用mknod調(diào)用建立的,而不是用pipe建立的。另夕卜,必須把八進(jìn)制數(shù)010000(定義在文件/usr/include/sys/stat.h的常量S_IFIFO中)加入文件模式中,以指明這是一個FIFO。下面是一個建立FIFO的例子:if(mknod(fifo,010600,0)0)perror(mknod(fifo)call);這個例子建立一個

59、名為fifo的FIFO,其權(quán)限為0600,所以此FIFO可以被其文件主讀寫。一旦建立一個FIFO,必須用系統(tǒng)調(diào)用open打開它,例如:#includefd=open(fifo,O_WRONLY);實現(xiàn)打開一個FIFO文件用于寫,下面的例子用于以非阻塞方式打開FIFO文件用于讀:if(fd=open(fifo,O_RDONLY|O_NDELAY)0)perror(openonfile);下面介紹兩個程序,說明FIFO的基本應(yīng)用。值得注意的是,這兩個程序構(gòu)成了FIFO編程的基本框架,稍微修改即可用于其他場合的FIFO應(yīng)用。首先是sendfifo.c的程序清單,用于向FIFO文件寫入字串:下面是re

60、cvfifo.c的程序清單,實現(xiàn)從FIFO的讀入:運行結(jié)果如下:%recvfifo&11706%sendfifohelloworldFIFOmessagereceived:helloFIFOmessagereceived:world%首先,運行recvfifo程序創(chuàng)建FIFO文件fifo,并打開文件fifo用于讀;然后,運行sendfifo程序發(fā)送字符串helloworid,寫入文件fifo中。7.3IPC通訊機(jī)制IPC概述IPC是UNIX系統(tǒng)V提供的一套新的進(jìn)程間通訊進(jìn)制,它大大增強(qiáng)了進(jìn)程間的通訊功能。IPC機(jī)構(gòu)包括三種:消息、信號量和共享內(nèi)存。三種IPC機(jī)構(gòu)的程序設(shè)計接口比較相似,這說明它

溫馨提示

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

評論

0/150

提交評論