




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、第一章概述1.1UNIX的版本UNIX操作系統(tǒng)是貝爾實驗室于六十年代末用C語言研制開發(fā)的。經過幾十年的發(fā)展,已經成為流行于從大型機、小型機到工作站甚至微機等多種平臺的操作系統(tǒng)。UNIX的成功同時也推動了C語言的普及。本教材的目的是講解UNIX系統(tǒng)下的C程序設計,使C程序員快速掌握UNIX系統(tǒng)下的編程開發(fā)。作者在進行UNIX編程開發(fā)的實踐過程中,深感實例的重要性,一個簡短的C語言實例往往勝過長篇累牘的文字說明,當然了,文字說明也是必不可少的。本教材將本著實例優(yōu)先的原則,使您能夠對UNIX編程開發(fā)快速入門。UNIX的版本不統(tǒng)一是出了名的,從UNIX的發(fā)展歷史來看,主要有兩大流派:AT&T的UNIX
2、系統(tǒng)V版本和加州大學伯克利分校的BSD版本,在此基礎上,各家UNIX廠商均開發(fā)了各自的UNIX操作系統(tǒng)。如:工作站廠商中有HP的hpux、SUN的Solaris、SGI的irix、IBM的AIX等,小型機有VAX上的Ultrix,微機上有SCOUNIX、微軟的Xenix以及隨著Internet而風靡全球的Linux等。由于WindowsNT的異軍突起,對UNIX的市場形成巨大的威脅,各大UNIX廠商不得不聯(lián)合起來,在工作站市場上,統(tǒng)一以系統(tǒng)V版作為標準,加入BSD版本中的一些優(yōu)點,支持統(tǒng)一的CDE(CommonDesktopEnvironment)窗口環(huán)境,以與WindowsNT進行對抗。1.
3、2UNIX編程環(huán)境UNIX操作系統(tǒng)通過Shell程序實現(xiàn)系統(tǒng)與用戶的交互,在Shell提示符下,用戶鍵入UNIX命令,即可得到操作系統(tǒng)的輸出結果。BSD系統(tǒng)的常用Shell是CShell,缺省提示符是,系統(tǒng)V的常用Shell是BourneShell(現(xiàn)在多為KornShell),缺省提示符是$”,有關Shell的編程,我們在后面的章節(jié)中進行介紹。UNIX上的標準編譯器是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的編譯開關、DEBUG是調試宏、INC是頭
5、文件所在目錄、LDFLAGS定義了編譯連接庫、OBJ定義了目標文件名、TGTS定義了可執(zhí)行文件名。在Shell提示符下直接鍵入:$make即可將Makefile中指定的所有C文件進行編譯并生成可執(zhí)行文件。1.3UNIX編程中的基本概念在討論UNIX編程開發(fā)前,首先需要闡明系統(tǒng)調用和庫函數這兩個概念。一個系統(tǒng)調用指一個需要操作系統(tǒng)代表用戶程序來執(zhí)行某些任務的請求。例如:read是一個系統(tǒng)調用,它請求操作系統(tǒng)存儲在一個磁盤設備(或其他設備)上的數據去填充一個緩沖區(qū)。如果任何人在他們想執(zhí)行任務的時候都能隨便訪問設備,那么后果將是不可預測的。所以,這種服務必須請求操作系統(tǒng)來做,它(經常是透明地)記錄所
6、有處理每個設備的請求。而一個庫函數,并不經常需要操作系統(tǒng)來執(zhí)行其任務。例如數學庫函數中的sin(),cos()等,這些計算只需要簡單地對一個有限序列求和,所以并不需要操作系統(tǒng)干預。在UNIX操作系統(tǒng)中,有一個常用的命令man,可用來查閱命令、庫函數和系統(tǒng)調用等的具體使用方法。傳統(tǒng)Unix聯(lián)機幫助手冊的分節(jié)法為:用戶級命令(User-levelcommands)系統(tǒng)調用(Systemcalls)庫函數(Libraryfunctions設備及驅動程序(Devicesanddevicedriver)文件格式(Fileformats)游戲(Games)雜項(Variousmiscellaneousst
7、uff-macropackagesetc.系統(tǒng)維護及操作命令(Systemmaintenanceandoperationcommands第二章標準輸入/輸出庫2.1概述本章介紹UNIX的標準輸入/輸出庫,UNIX提供一些庫函數完成高級輸入/輸出,為程序員提供了三方面的主要功能:自動開辟緩沖區(qū)。即使一次讀或寫的數據只有幾個字節(jié),庫函數仍然在大到由數千個字節(jié)組成的塊中執(zhí)行實際輸入或輸出(緩沖區(qū)大小通常由頭文件stdio.h中的常量BUFSIZ定義)。這個緩沖區(qū)在內部開辟給庫函數使用,對于程序員來說是透明的;自動執(zhí)行輸入和輸出轉換。輸入輸出被自動格式化。以上兩點在C語言的教程中一般均以講到。在標準輸
8、入/輸出庫中,一個文件被稱為一串字符流,并且被一個指向類型為FILE的目標指針所描述,該指針被稱為文件指針。在UNIX中文件指針stdin、stdout、stderr是預先定義好的,分別對應標準輸入(鍵盤)、標準輸出(終端屏幕)和標準錯誤輸出。2.2庫函數介紹文件創(chuàng)建和關閉fopen()用于打開已存在的文件或創(chuàng)建新文件文件讀寫1、一次處理一個字符getc(),putc()2、一次處理多個字符fgets(),fputs()3、文件的二進制讀寫fread(),fwrite()4、文件的格式化輸入/輸出fscanf(),fprintf()5、字符串的格式化輸入/輸出sscanf(),sprintf(
9、)文件移動定位用于在文件中移動的標準輸入/輸出庫函數是fseek(),它接收三個參數:一個文件指針指向一個打開的字符流;一個整數指明要移動的字節(jié)數,稱為offset;個整數指明從文件中什么位置移動。第三章低級輸入/輸出3.1概述與第二章內容相對應,本章介紹UNIX系統(tǒng)中通過系統(tǒng)調用來實現(xiàn)的輸入/輸出,通常稱之為低級輸入/輸出。這些系統(tǒng)調用能夠直接實現(xiàn)對設備(如磁帶驅動器等)的輸入和輸出,程序員能夠決定要使用的緩沖區(qū)的大小,而不象標準輸入/輸出庫函數那樣透明設定緩沖區(qū)大小。在標準輸入/輸出庫中,一個文件是由一個文件指針來對應的。當使用低級界面時,則用一個文件描述字對應一個文件。文件描述字是一個小
10、的整數。有3個事先定義的文件描述字0、1和2,分別對應標準輸入、標準輸出和標準錯誤輸出。一般說來,文件描述字都是作為系統(tǒng)調用的第一個參數給出的。3.2相關系統(tǒng)調用介紹文件創(chuàng)建和關閉open()用于為讀寫而打開一個文件,或用它來創(chuàng)建新文件。intopen(constchar*path,intoflag,./*mode_tmode*/);open使用三個參數:一個字符串path包含要打開的文件名;一個整數oflag指明文件將被如何打開;整數mode在創(chuàng)建文件時使用。常用的oflag包括:O_RDONLY打開文件僅用于讀。O_WRONLY打開文件僅用于寫。O_RDWR打開文件用于讀寫。O_CREAT
11、如果文件不存在,則創(chuàng)建,此時mode作為第三個參數給出。close。用于關閉一個已經打開的文件。文件讀寫read()用于讀文件,格式為:read(intfildes,void*buf,size_tnbyte);三個參數說明如下:filedes是文件描述字;指針buf指向一個數據將被讀入的緩沖區(qū);整數nbytes指明要讀的字節(jié)個數。成功時返回實際讀入的字節(jié)數,出錯則返回-1。write()用于寫文件,與read類似,格式為:write(intfildes,void*buf,size_tnbyte);三個參數說明如下:filedes是文件描述字;指針buf指向一個數據將被寫入的緩沖區(qū);整數nbyt
12、es指明要寫的字節(jié)個數。成功時返回實際寫入的字節(jié)數,出錯則返回-1。文件移動定位用于在文件中移動的低級輸入/輸出系統(tǒng)調用是lseek(),與fseek()類似,它也接收三個參數:一個文件描述字對應一個打開的文件;一個整數指明要移動的字節(jié)數,稱為offset;一個整數指明從文件中什么位置移動。復制文件描述字有時候有不只一個文件描述字對應一個文件。當創(chuàng)建子進程時(參加后面關于進程開發(fā)的章節(jié)),這一點很常用。為了獲得一個新的文件描述字,并保證其與fd對應同一個文件,應調用fd2=dup(fd)fd2現(xiàn)在和fd對應同一個文件,并且和fd樣在文件中有相同的位置。四章文件與目錄編程4.1基本概念文件目錄概
13、述文件系統(tǒng)是UNIX對計算機技術的一大貢獻!UNIX系統(tǒng)的文件管理十分靈活、功能強大,許多首次在UNIX系統(tǒng)中出現(xiàn)的概念被其他操作系統(tǒng)所采用,如MS-DOS等。UNIX系統(tǒng)提供了一種層次目錄方案。目錄就象存放一組文件的柜子一樣,目錄也可以包括在其他目錄中,這樣就形成了一種龐大的、具有分支的組織方式,這種結構通常被稱為樹狀結構。目錄實際上也是一種特殊的文件。命令、數據文件、其他命令甚至設備(特別文件)都可以作為目錄中的項(文件)。I標識號、I列表和I節(jié)點一個目錄是由一系列結構組成的;每個結構包含一個文件名和一個指向文件自身的指針,該指針是一個整數,稱為文件的I標識號。當文件被訪問時,它的I標識號
14、用來作為索引打開一個系統(tǒng)表(I列表),系統(tǒng)中存放著文件(I節(jié)點)的實體。I節(jié)點包含了對文件的描述:文件自身的用戶和用戶組ID文件的保護碼文件內容所在的物理磁盤地址文件的大小最后一次I節(jié)點改變的時間,最后一次使用和修改的時間連接該文件的次數,即它出現(xiàn)在其他目錄中的次數一個指明文件類型的標記(目錄、普通文件、特別文件)文件的三級保護UNIX把使用文件的用戶分成三個等級:文件所有者、同組用戶和其他用戶。文件所有者也稱文件主,是文件的創(chuàng)建者,對該文件擁有所有權限;同組用戶是具有相同組標識號的所有用戶,文件主可以決定一個文件屬于哪個組以及該組用戶對文件的存取權;其他用戶是指與文件主無關的用戶,他們與文件
15、主不屬于同一個用戶組,其他用戶對一個文件的訪問權限也由該文件主決定的。一個文件的訪問權限存放在該文件I節(jié)點的di_mode域中,di_mode的08位表示文件主、文件組用戶和其他用戶對該文件的存取權限。舉個例子,用Is-l命令可列出文件hello.c的模式和屬性:-rwxr-xr-x1ydsuser589月25日10時54分hello.c最左面一欄顯示了該文件的模式:文件主對該文件可讀(r)、可寫(w)、可執(zhí)行(x),同組用戶對該文件可讀、可執(zhí)行,其他用戶對該文件可讀、可執(zhí)行。相應的,di_mode的08位為111101101(0755)。4.2文件編程介紹檢查訪問權限一access系統(tǒng)調用a
16、ccess系統(tǒng)調用的格式為:#includeintaccess(constchar*path,intamode);其中:參數path指出被檢查文件的路徑,參數amode指出訪問權限。Access判斷調用進程的實際用戶對文件path是否具有amode所指定的訪問權限,若有相應權限,access返回0,否則返回一1。參數amode可取以下值或它們的邏輯或:R_OK檢查讀權限W_OK檢查寫權限X_OK檢查執(zhí)行(搜索)權限F_OK檢查文件是否存在例如:access(hello.c,R_OK|W_OK),用來檢查實際用戶對文件hello.c是否具有讀/寫權;access(hello.c,F_OK)判斷文
17、件hello.c是否存在。鏈接與刪除文件-link和unlink系統(tǒng)調用link和unlink系統(tǒng)調用的格式為:#includeintlink(constchar*path1,constchar*path2);intunlink(constchar*path);其中:參數pathl指出已經存在的要被鏈接的文件路徑名,ath2指出要建立的鏈接文件dink實現(xiàn)path2到pathl的鏈接,相當于給pathl起了一個別名,同時文件pathl的鏈接計數加1。若成功則返回0,否則返回-1。參數path指出要被刪除的文件路徑名。Unlink刪除由path指出的文件,若成功則返回0,否則返回一1。從I節(jié)點上
18、獲取信息一stat與fstat系統(tǒng)調用stat與fstat的調用格式為:#include#includeintstat(constchar*path,structstat*buf);intfstat(intfildes,structstat*buf);說明:stat和fstat都用于獲取文件I節(jié)點中有關狀態(tài)信息。stat根據參數path給出的文件路徑名,搜索它對應的盤I節(jié)點,而fstat則根據參數fildes給出的文件描述字去查找對應的I節(jié)點。這兩個調用都把從I節(jié)點中獲取到的信息重組后放入參數buf指向的stat結構中(stat結構的說明在文件/usr/include/sys/stat.h中)
19、。這兩個調用成功時均返回0,否則返回-1。stat與fstat調用無論在使用上還是在功能上都是非常類似的,在參數上有一點區(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)調用獲取該文件的信息。假設當前命令下有一個名為xxx.c的文件,運行%statfilexxx.c后,將會輸出如下結果:statxxx.cfailsasitshould!fstatxxx.csucceedsasitshould!從中可知,當一個打開文件被刪除后,用stat無法獲取該文件的信息。而fstat就可獲取該文件的信息。這是由于文件名在unlink之后已從目錄中除去,無法找到該文件名,而文件描述字則因文件仍打開而保存下來。因此stat不能成功返回,但fstat仍可成功返回。使用stat調用來判定
22、一個文件為何種文件類型時相當有用。例如下列代碼: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以上代碼可判定當前目錄下的hello文件是否為目錄文件或其他類型的文件。4.3目錄編程介紹UNIX把目錄也視為一種文件,稱為目錄文件,并同普通文件一樣進行管理和保護。如open、close、read、lseek等文件操作對目錄文件都是有效
23、的。前面講到的文件編程中的各個系統(tǒng)調用對于目錄來說也同樣有效。但是與普通文件相比目錄文件又具有自身的一些特點:目錄文件的讀/寫/執(zhí)行訪問權限有特殊的含義:讀權限允許用戶讀取目錄項的內容;寫權限允許用戶創(chuàng)建或刪除一個文件;執(zhí)行權限則允許用戶檢索目錄(此時通常稱為目錄搜索權限)。目錄的創(chuàng)建、刪除與普通文件也不同,另外,任何用戶都不能對目錄文件以寫方式打開進行文件寫操作。目錄的創(chuàng)建和刪除一mkdir和rmdir系統(tǒng)調用mkdir和rmdir系統(tǒng)調用的格式為:#include#includeintmkdir(constchar*path,mode_tmode);#includeintrmdir(con
24、stchar*path);其中:參數path分別指出要創(chuàng)建和刪除的目錄文件的文件名。mkdir調用中的參數mode指出新創(chuàng)建目錄文件的文件模式。新創(chuàng)建目錄后,除.和.兩項外,無別的目錄項;刪除目錄時,要求目錄中除.和.兩項外,也無別的目錄項。這兩個系統(tǒng)調用Access成功時都返回0,否則返回一1。目錄的讀取一opendir/readdir/closedir庫函數目錄文件可以像普通文件一樣,先用系統(tǒng)調用open以讀方式打開,再用read調用讀取其中的內容。同時,由于目錄文件是由具有目錄結構的目錄項組成的,用read讀取其內容有些不方便UNIX提供的庫函數opendir/readdir/close
25、dir等可以方便地實現(xiàn)目錄讀取。函數說明如下:#include#includeDIR*opendir(char*filename);structdirect*readdir(DIR*dirp);voidclosedir(DIR*dirp);說明:參數filename指出要打開的目錄路徑名,庫函數opendir返回一個指向結構DIR(在文件/usr/include/sys/dir.h中定義)的指針。庫函數readdir和closedir均以這個指針作為參數,其中readdir返回一個指向結構direct的指針。有關目錄的操作均可基于這個指針。下面是一個例子,查找當前目錄下文件名為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;庫函數closedir關閉打開的目錄。值得注意的是,上面這一小段代碼在編程中很實用,稍加修改即可實現(xiàn)UNIX下類似ls的簡單命令。第五章基本進程編程5.1概述UNIX系統(tǒng)為程序員提供了一個強有力的工具:在一個程序中執(zhí)行
27、另一個程序。執(zhí)行一個程序最簡單的途徑就是使用庫函數system。該函數使用一個參數:一個包含要被執(zhí)行的命令的字符串。這一庫函數的特點是用法簡單,在程序中調用簡單的UNIX命令時很有用。但是由于它的調用要由SHELL進程來實現(xiàn),故效率并不高,在實際的編程中應用并不廣泛。本章主要介紹在實際編程中經常使用的有關進程控制和管理方面的系統(tǒng)調用,它們包括:fork創(chuàng)建一子進程exec執(zhí)行子進程exit終止進程執(zhí)行wait等待子進程暫停或終止setpgrp設置進程標識符getpid、getppid獲取進程標識符setuid、setgid設置進程的用戶標識符getuid、geteuid、getgid、gete
28、gid獲取進程的用戶標識符5.2進程控制1.fork系統(tǒng)調用系統(tǒng)調用fork是UNIX操作系統(tǒng)創(chuàng)建新進程的唯一手段,習慣上將新創(chuàng)建的進程稱為子進程,調用fork的進程稱為父進程。fork系統(tǒng)調用的格式為:intfork()fork系統(tǒng)調用沒有參數,如執(zhí)行成功,則創(chuàng)建一子進程,子進程繼承了父進程的某些屬性。當從該系統(tǒng)調用返回時,系統(tǒng)中已有兩個用戶級環(huán)境完全相同的進程存在。這兩個進程從fork調用中得到的返回值不同,其中子進程得到的返回值為零,父進程得到的返回值是最新創(chuàng)建的子進程的進程標識符。2.exec系統(tǒng)調用fork系統(tǒng)調用只是將父進程的環(huán)境拷貝到新進程中,而沒有啟動執(zhí)行一個新的目標程序。UN
29、IX系統(tǒng)提供了exec系統(tǒng)調用,用它更換進程的執(zhí)行映象,啟動新的目標程序。例如:UNIX系統(tǒng)中的所有命令都是通過exec來執(zhí)行的。exec系統(tǒng)調用有六種不同的使用格式,但在核心中只對應一個調用入口。它們有不同的調用格式和調用參數。這六種調用格式分別為:#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);說明:參數path指出一個可執(zhí)行目標文件的路徑名;參數file指出可執(zhí)行目標文件的文件名。arg0作為約定同path一樣指出目標文件的路徑名;參數argl到argn分別是該目標文件執(zhí)行時所帶的命令行參數;參數argv是一
31、個字符串指針數組,由它指出該目標程序使用的命令行參數表,按約定第一個字符指針指向與path或file相同的字符串;最后一個指針指向一個空字符串,其余的指向該程序執(zhí)行時所帶的命令行參數;參數envp同argv一樣也是一個字符指針數組,由它指出該目標程序執(zhí)行時的進程環(huán)境,它也以一個空指針結束。exec的六種格式在以下三點上有所不同:path是一個目標文件的完整路徑名,而file是目標文件名,它是可以通過環(huán)境變量PATH來搜索的;由path或file指定的目標文件的命令行參數是完整的參數列表或是通過一指針數組argv來給出的;環(huán)境變量是系統(tǒng)自動傳遞或者通過envp來給出的。下圖說明了exec系統(tǒng)調用
32、的六種不同格式對以上三點的支持。系統(tǒng)調用參數形式環(huán)境傳送路徑搜索Execl全部列表自動否Execv指針數組自動否Execle全部列表不自動否Execve指針數組不自動否Execlp全部列表自動是Execvp指針數組自動是3.exit、wait系統(tǒng)調用exit系統(tǒng)調用格式如下:#includevoidexit(intstatus);#includevoid_exit(intstatus);說明:exit的功能是終止進程的執(zhí)行,并釋放該進程所占用的某些系統(tǒng)資源。參數status是調用進程終止時傳遞給其父進程的值。如果調用進程執(zhí)行exit系統(tǒng)調用時,其父進程正在等待子進程暫?;蚪K止(使用wait系統(tǒng)
33、調用),則父進程可立刻得到該值;如果此時父進程并不處在等待狀態(tài),那么一旦父進程使用wait調用,便可立刻得到子進程傳過來的status值,注意:只有status的低八位才傳遞給其父進程。系統(tǒng)調用_exit與exit之間的差異是_exit只做部分的清除,因此建議不要輕易地使用這種調用形式。每個進程在消亡前都要調用該系統(tǒng)調用,沒有顯示地使用該系統(tǒng)調用,則生成目標文件的裝載程序為該進程隱含地做這一工作。wait系統(tǒng)調用格式如下:#include#includepid_twait(int*statptr);說明:wait系統(tǒng)調用將調用進程掛起,直到該進程收到一個被其捕獲的信號或者它的任何一個子進程暫停
34、或終止為止。如果在wait調用之前已有子進程暫停或終止,則該調用立刻返回。格式wait(int*)0)的功能是等待所有子進程終止oWait返回時,其返回值為該子進程的進程號。參數statptr的值為該子進程的終止原因:1、如果子進程暫停,statptr目的高八位存放使該子進程暫停的信號值(在第七章中介紹信號)低八位為01772、如果子進程由于調用exit終止,則該值的低八位為0,高八位為子進程終止時,exit系統(tǒng)調用中參數status值的低八位;3、如果子進程因信號終止,該值的高八位為0,低八位為引起終止的信號值。此外如低七位為1,則表示產生了一個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);當命令行參數的個數不為1時,程序使用fork系統(tǒng)調用產生一個子進程。子進程通過系統(tǒng)調用g
36、etpid獲得自己的進程標識符,然后調用exec執(zhí)行命令行中用戶提交的命令,如果exec執(zhí)行失敗,則子進程調用exit(5)終止。父進程使用wait系統(tǒng)調用等待子進程暫停或終止,然后輸出從wait中返回的信息。下面以三種方式執(zhí)行該程序:1不帶命令行參數%./feewpid=-1,H_stat=0,L_stat=0%不產生子進程,從運行結果來看,當無子進程時,wait的返回值為一1。2帶命令行參數,參數為合法的可執(zhí)行命令%./feew/bin/dateChildpid=17251998年2月16日(星期一)15時59分14秒CSTpid=1725,H_stat=0,L_stat=0產生子進程。子
37、進程輸出其進程標識符后,再調用exec執(zhí)行從命令行中提交的命令(bin/date),同時父進程等待子進程暫?;蚪K止,然后輸出從wait中得到的信息:子進程標識符或狀態(tài)參數stat的高八位、低八位的內容。從中可以看到:子進程因調用一個隱含的exit(O)而終止,終止時傳給父進程的值為0。3帶命令行參數,但參數不合法%./feew/etc/shudownChildpid=1760/etc/shutdown:只有超級用戶(root)能運行/etc/shutdown。pid=1760,H_stat=2,L_stat=0%子進程創(chuàng)建成功。但由于以普通用戶的身份執(zhí)行/etc/shutdown,因此exec
38、失敗,爾后調用exit(5)而終止;父進程調用wait得到返回值:子進程號和狀態(tài)參數stat的高八位、低八位的內容。從執(zhí)行結果可以看出:子進程因調用exit(5)而終止,終止時傳給父進程的值為5。5.3進程管理進程管理包括的面很廣,諸如進程的用戶標識符管理、進程標識符管理等。進程的用戶標識符有兩個:實際用戶標識符(realuserid)和有效用戶標識符(effectiveuserid),其對應的組標識符分別稱為實際組標識符(realgroupid)和有效組標識符(effectivegroudid)。一般而言,進程的實際用戶標識符為運行該進程的用戶標識符,通常只用于系統(tǒng)記帳,其他功能由有效用戶標
39、識符來完成,如用有效用戶標識符來完成對新創(chuàng)建文件賦予屬性關系、檢查文件的存取權限和利用kill系統(tǒng)調用向進程發(fā)送信號的權限。一般情況下,一進程的有效用戶標識符和實際用戶標識符是相等的,但系統(tǒng)允許改變進程的有效用戶標識符。進程的用戶標識符管理UNIX系統(tǒng)提供了一組系統(tǒng)調用來管理進程的用戶標識符,它們的使用形式是:#include#includeuid_tgetuid(void);uid_tgeteuid(void);gid_tgetgid(void);gid_tgetegid(void);intsetuid(uid_tuid);intsetgid(gid_tgid);說明:前四個系統(tǒng)調用沒有參數
40、,分別返回調用進程的實際用戶標識符、有效用戶標識符、實際用戶組標識符和有效組標識符。這些系統(tǒng)調用的執(zhí)行總能獲得成功,不會發(fā)生任何錯誤。系統(tǒng)調用setuid和setgid用于設置進程的實際用戶(組)標識符和有效用戶(組)標識符,如調用進程的有效用戶標識符是超級用戶標識符,則將調用的進程實際用戶(組)標識符和有效用戶(組)標識符設置為uid或gid;如調用進程的有效用戶標識符不是超級用戶標識符,但其實際用戶(組)標識符等于uid或gid時,則其有效用戶(組)標識符被設置為uid或gid;否則setuid或setgid調用失敗。系統(tǒng)調用setuid或setgid調用成功時返回0,失敗時返回1。進程標
41、識符管理UNIX系統(tǒng)使用進程標識符來管理當前系統(tǒng)中的進程。為對具有某類似特性的進程統(tǒng)一管理,系統(tǒng)又引入了進程組的概念,以組標識符來區(qū)別進程是否同組。進程的組標識符是從父進程繼承下來的,所以,通常進程的組標識符就是和它相關聯(lián)的注冊進程的標識符。進程的標識符是由系統(tǒng)為之分配的,不能被修改;組標識符可通過setpgrp系統(tǒng)調用修改。相關系統(tǒng)調用的格式如下:#include#includepid_tgetpid(void);pid_tgetpgrp(void);pid_tgetppid(void);pid_tgetpgid(pid_tpid);說明:前三個系統(tǒng)調用分別返回調用進程的進程標識符、進程組標
42、識符和其父進程標識符。它們總能成功地返回。第四個調用置進程組標識符,它將調用進程的進程組標識符改為調用進程的進程標識符,使其成為進程組首進程,并返回這一新的進程組標識符。下面我們來看一個實例:/*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í)行該程序的用戶為超級用戶,則只要命令行所給的用戶標識符大于0,無論所給的用戶標識符是否存在,執(zhí)行總能成功。#./setuid3434Beforeuid=0,euid=0Afteruid=3434,euid=3434ret=0結果分析:將進程的實際和有效用戶標識符均改為3434。2、如果執(zhí)行該程序的用戶為一般用戶,用d命令得到用戶uid和gid后,再調用該程序,過程如下:%iduid=1111(yds)gid=20(user)%./setuid3434Beforeuid=1111,euid=1111Afteruid=1111,euid=1111ret=-1
44、%./setuid1111Beforeuid=1111,euid=1111Afteruid=1111,euid=1111ret=0%結果分析:當命令行參數為1111時,setuid執(zhí)行成功,因為用戶的uid就是1111。值得注意的是:注冊程序login是個典型的setuid系統(tǒng)調用程序,login進程的有效用戶是超級用戶,該進程在建立用戶的Shell進程前,調用setuid將實際和有效用戶標識符調整為注冊用戶的用戶實際和有效標識符。六章設備輸入/輸出控制6.1概述UNIX將設備看成文件,這是UNIX的一大特色。這里需要介紹一個設備號的概念。設備特別文件與兩個設備號有關主設備號和次設備號。主設備
45、號告訴操作系統(tǒng),當涉及文件名時,將使用哪種設備類型。對于每一種類型的設備都有一段駐留在操作系統(tǒng)中的程序代碼,以控制相應類型的設備,這段代碼被稱為設備驅動程序。次設備號被傳遞給設備驅動程序,這個號碼用來決定使用哪種物理設備。例如,決定在一塊多重驅動控制卡上,哪個磁盤驅動器將被訪問,以及該磁盤驅動器中哪一部分將被使用;或者,當一個磁盤驅動器所請求的操作已經完成后,應該被恢復原狀。幾個設備(如同類型的磁盤驅動器)可以用同一個主設備號,但它們將有不同的次設備號??聪旅娴睦樱?ls-l/dev/ttyq*crw-w2ydsuser15,12月17日09時03分ttyq1crw-w2ydsuser15,
46、142月16日17時00分ttyq14%上例中15是主設備號,1和14是次設備號。用戶可以使用系統(tǒng)提供的統(tǒng)一而且獨立于設備的界面對文件進行操作的系統(tǒng)調用來操作設備,而沒有必要涉及設備的具體細節(jié)。大部分對文件進行操作的系統(tǒng)調用對它們仍起作用,例如,用open打開設備,用read/write對設備進行讀/寫,設備操作完成后,用close關閉設備。但有的系統(tǒng)調用在對設備文件進行操作時,其功效有所不同。如create及open的創(chuàng)建方式都不能創(chuàng)建設備文件。6.2設備輸入/輸出控制一ioctl系統(tǒng)調用ioctl是UNIX系統(tǒng)專門提供的用于設備控制的系統(tǒng)調用。該系統(tǒng)調用與設備類型(即主設備號)相關。不同的
47、設備,系統(tǒng)提供了不同的控制命令。ioctl的調用格式是:ioctl(intfd,intcmd,arg說明:參數fd是一設備文件的文件描述字,cmd是控制命令,它與設備相關,不同類型的設備有不同的控制命令。參數arg沒有固定的數據結構,它隨cmd的不同而不同。七章高級編程7.1處理信號信號是UNIX進程間最基本的通訊手段,主要作用是實現(xiàn)進程間異步事件的通訊。信號是傳送到進程的軟中斷,它通知進程在它們的環(huán)境中出現(xiàn)了非正常事件。進程接收到信號后要進行處理,處理方式為以下四種之一:(1)缺省方式(SIG_DFL):這是進程對信號的一般處理方式,在無特殊情況下,進程在接收到信號后將終止執(zhí)行。有一些信號,
48、在終止進程運行前需將終止進程的正文段、數據段、user結構和棧段內容寫到當前目錄的core文件中,以備調試工具分析與使用。(2)忽略方式(SIG_IGN):進程接收到一個已指明忽略的信號,則將該信號清除后,立即返回,不在任何工作。信號SIGKILL不能被忽略。(3)保持方式(SIG_HOLD):當進程處于該方式時,將接收的信號保存起來,等該進程的保持方式解除后,再進行處理。(4)捕獲方式(設置信號處理函數):這是用戶設置的信號處理方式,當進程接收到這種信號時,執(zhí)行用戶設置的信號處理函數,執(zhí)行完后,恢復現(xiàn)場,然后繼續(xù)往下執(zhí)行。常用信號種類UNIX信號的種類很多,下面介紹一些最常用的信號:SIGH
49、UP掛斷。這是當控制終端被掛起時送到進程的信號。SIGINT中斷。由鍵盤產生的中斷。SIGQUIT退出。由鍵盤產生的中斷。SIGKILL終止。這個信號不能被捕獲、阻塞或忽略。SIGALRM定時信號。SIGTERM軟件終止信號。SIGUSR1用戶定義的信號1。SIGUSR2用戶定義的信號2。這些信號值的聲明在/usr/include/sys/signal.h文件中。發(fā)送信號一kill系統(tǒng)調用用戶傳送信號到進程的系統(tǒng)調用是kill,調用格式為:#include#includeintkill(pid_tpid,intsig);說明:該系統(tǒng)調用把一個信號值為sig的信號發(fā)送給進程標識符為pid的相關進
50、程。成功時返回0,失敗時返回1。該調用執(zhí)行成功與否,依賴于調用進程的有效用戶標識符和參數pid的值,pid值的含義如下:大于0:將信號發(fā)送給進程號等于pid的進程。等于0:將信號發(fā)送給調用進程的同組進程(0和1進程除外)。等于1:將信號發(fā)送給實際用戶標識符等于調用進程的有效用戶標識符的所有進程(0和1進程除外),如調用進程的有效用戶是超級用戶,則將信號發(fā)送給除0和1進程外的所有進程。非一1的負數:將信號發(fā)送給進程組標識符為pid的絕對值的所有進程。在實際編程中,kill系統(tǒng)調用非常有用,具體說來:常用方式kill(pid,SIGUSR1)向進程號為pid的進程發(fā)送信號SIGUSR1用來判斷進程
51、是否存在:if(kill(pid,0)=0)進程號為pid的進程存在;else進程號為pid的進程不存在!用來殺掉子進程kill(pid,1)殺掉進程號為pid的進程2.處理信號一signal系統(tǒng)調用用戶處理信號的系統(tǒng)調用是signal,調用格式為:#includevoid(*signal(intsig,void(*func)()();說明:參數引g是一個信號值,func定義了該信號的處理方式。該系統(tǒng)定義的功能是按func的定義設置調用進程對信號sig的處理方式。執(zhí)行成功時,返回調用進程先前對信號sig處理方式的值,失敗則返回一1。參數取值為SIG_DFL或SIG_IGN或用戶信號處理函數的地
52、址時,分別表示缺省方式、忽略方式和捕獲方式。3.pause系統(tǒng)調用pause系統(tǒng)調用的格式為:pause()說明:該調用沒有參數,其功能為使調用進程睡眠直到其接收到一信號為止。該系統(tǒng)調用的結果依賴于調用進程對接收到的信號的處理方式。缺省方式:終止調用進程,pause無返回值;忽略方式:進程不受該信號的影響,繼續(xù)睡眠;捕獲方式:調用進程從信號處理函數返回后,繼續(xù)往下執(zhí)行。4.使用信號定時一alarm系統(tǒng)調用系統(tǒng)調用alarm可以實現(xiàn)定時器的功能,調用格式為:#includeunsignedalarm(unsignedsec);說明:參數sec指定定時的時間間隔,以秒為單位。用戶進程可以先通過si
53、gnal調用指定SIGALRM信號對應的捕獲函數,然后調用alarm來設定鬧鐘,在定時這段時間內做自己的工作。定時時間一到,進程就接收到一個SIGALRM信號,并執(zhí)行該信號對應的捕獲函數。系統(tǒng)調用alarm在多進程編程中非常有用。7.2管道通訊用信號來處理異常事件或錯誤是非常合適的,但它用來處理進程之間的大量信息傳送,就非常不適宜。為此,UNIX又提供了一種稱為管道的機構,主要處理進程間的大量信息傳送。所謂管道是指進程間連接起來的一條通訊通道。它也UNIX文件概念的一種推廣,管道通訊的介質是文件,稱為管道文件。用戶可以用文件操作的有關系統(tǒng)調用來操作管道文件,從而簡化管道應用程序的設計。管道的形
54、象描述如下圖:write寫端讀端read管道是UNIX最強大而最有特色的性能之一,特別是在命令行這一級,它允許任意的命令被順序連接起來。例如:%who|wc-l該命令通過管道把命令who的輸出送給字計數程序wc,選項-I告訴wc只計算行數。通過wc最終輸出的系統(tǒng)已注冊的用戶個數。1.管道程序設計在程序中可以用系統(tǒng)調用ipe建立一個管道。如果建立成功,就返回兩個文件描述符,一個用于寫入管道,一個用于從管道中讀出。Pipe調用的格式如下:intfiIedes2,retvaI;retvaI=pipe(fiIedes);其中,fildes是一個含有兩個整數的數組,用來存放標識管道的兩個文件描述符。如果
55、調用成功,fiIedesO將被打開用于從管道讀,fildes1將被打開用于向管道寫。管道一旦建立,就能直接用read和write操作它。當管道與系統(tǒng)調用fork聯(lián)用時,才能體現(xiàn)出管道的真正價值。這時,可以利用父進程已打開的文件,對于其子進程仍保持打開這一事實。下面的程序先建立一個管道,然后調用fork創(chuàng)建子進程,父進程通過管道向子進程發(fā)送信息。打開管道在父進程中向管道寫入在子進程中從管道讀入程序的輸入結果如下:ChildRead:hello,world#1ChildRead:hello,world#2ChildRead:hello,world#3管道是在先進先出的基礎上處理數據的。所以,首先放
56、入管道的數據,在其另一端首先被讀出。這個順序不能被改變,因為系統(tǒng)調用Iseek不能用于管道。2.命名管道一FIFO我們已經看到,管道是一種功能很強的進程通訊機構。但是,它也存在一些嚴重的缺點。首先,管道只能用于連接具有共同祖先的進程,如父子進程之間的連接。當要開發(fā)一個永遠保持存在的,提供為全系統(tǒng)范圍服務的程序時,這一缺點就更加突出,例如網絡控制服務程序和打印機的假脫機程序等。我們要求調用進程應該能夠用管道與任何服務進程進行通訊,然后再脫開。遺憾的是,普通管道不能實現(xiàn)上述功能。其次,管道不能是常設的,在需要時可以建立它們,但是當訪問它們的進程終止時,管道也隨之被撤銷。所以,它們不可能永久存在。事
57、實上,UNIX系統(tǒng)中的FIFO機制(又稱命名管道),彌補了上述管道的不足之處。FIFO與管道一樣,也是作為進程之間先進先出的通訊通道,但是FIFO是一種永久性的機構,并且具有一個UNIX文件名。FIFO也具有文件主、長度和訪問權限。它能象其他UNIX文件那樣被打開、關閉和刪除。但在讀和寫時,其性能與管道相同。在討論FIFO程序設計之前,我們先來看一下FIFO在命令級的使用。UNIX命令mknod可以用來創(chuàng)建一個FIFO文件channeI:%/etc/mknodchanneIp%Is-IchanneIprw-r-r-1ydsuser02月17日14時19分channeI命令Is的輸出結果中的首字
58、母p指出channel是一個FIFO類型的文件。從中我們還可以看到其訪問權限為文件主可讀寫,組內及其他用戶只讀。其用戶主是yds,所屬組為user,長度為0,此外還有文件建立的時間。FIFO程序設計大部分與管道相同,最主要的區(qū)別是在建立方面。FIFO是用mknod調用建立的,而不是用pipe建立的。另夕卜,必須把八進制數010000(定義在文件/usr/include/sys/stat.h的常量S_IFIFO中)加入文件模式中,以指明這是一個FIFO。下面是一個建立FIFO的例子:if(mknod(fifo,010600,0)0)perror(mknod(fifo)call);這個例子建立一個
59、名為fifo的FIFO,其權限為0600,所以此FIFO可以被其文件主讀寫。一旦建立一個FIFO,必須用系統(tǒng)調用open打開它,例如:#includefd=open(fifo,O_WRONLY);實現(xiàn)打開一個FIFO文件用于寫,下面的例子用于以非阻塞方式打開FIFO文件用于讀:if(fd=open(fifo,O_RDONLY|O_NDELAY)0)perror(openonfile);下面介紹兩個程序,說明FIFO的基本應用。值得注意的是,這兩個程序構成了FIFO編程的基本框架,稍微修改即可用于其他場合的FIFO應用。首先是sendfifo.c的程序清單,用于向FIFO文件寫入字串:下面是re
60、cvfifo.c的程序清單,實現(xiàn)從FIFO的讀入:運行結果如下:%recvfifo&11706%sendfifohelloworldFIFOmessagereceived:helloFIFOmessagereceived:world%首先,運行recvfifo程序創(chuàng)建FIFO文件fifo,并打開文件fifo用于讀;然后,運行sendfifo程序發(fā)送字符串helloworid,寫入文件fifo中。7.3IPC通訊機制IPC概述IPC是UNIX系統(tǒng)V提供的一套新的進程間通訊進制,它大大增強了進程間的通訊功能。IPC機構包括三種:消息、信號量和共享內存。三種IPC機構的程序設計接口比較相似,這說明它
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 期中測試卷(人教版)(解析版)
- 2025電力線路建設承包合同
- 2025短期勞動合同協(xié)議書模板
- 2025關于索取合同缺失的勞動合同證明事宜
- 《石油煉制中的脫硫工藝》課件
- 聊聊分數那些事兒-2025第二學期期中考試后主題班會講話稿
- 風力發(fā)電機組空氣過濾器更換
- 2025房產抵押借款合同模板2
- 五年級上冊信息技術教學設計-第11課 學校開放日-動畫創(chuàng)作與合成∣粵教版
- 《親子關系講座》課件
- 2025山西杏花村旅游開發(fā)有限公司招聘50人筆試參考題庫附帶答案詳解
- 貫徹落實清理規(guī)范非融資性擔保方案指導意見
- 工程甩項合同協(xié)議
- 期中模擬卷(新疆專用)-2024-2025學年八年級英語下學期核心素養(yǎng)素質調研模擬練習試題(考試版)A4
- 2025廣東省深圳市中考數學復習分類匯編《函數綜合題》含答案解析
- 金融工程重點總結
- 漁業(yè)資源與漁場學課件藍點馬鮫學習資料
- 2025年度毛絨玩具采購合同
- 2024年四川成都農業(yè)科技中心招聘筆試真題
- 胸腔積液課件
- 《內河運輸船舶重大事故隱患判定標準》知識培訓
評論
0/150
提交評論