




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
進程進程進程控制的相關函數進程的創建派生進程:fork(),vfork();創建執行其他程序的進程:exec();(選學)Linux系統特有的調用:__clone();(選學)進程的等待wait(),waitpid();進程的終止exit(),atexit(),on_exit(),abort(),_exit();其他函數system()(選學)
,getpid()。進程的創建fork()函數#include<sys/types.h>#include<unistd.h>pid_tfork(void);fork在英文中是“分叉”的意思。一個進程在運行中,如果使用了fork
,就產生了另一個進程,于是進程就“分叉”了。當前進程為父進程,通過fork()會產生一個子進程。對于父進程,返回子程序的進程號,而對于子程序則返回0,這就是fork函數的特點“調用一次,返回兩次”,出錯則返回-1。fork函數是Unix系統最杰出的成就之一。進程的創建fork函數實例以及說明:因父進程和子進程的運行無關,父進程或子進程返回的順序隨機的,因此運行結果不唯一。vfork()函數以及實例vfork創建新進程的主要目的在于用exec函數執行另外的程序,實際上,在沒調用exec或exit之前子進程的運行中是與父進程共享數據段的。在vfork調用中,子進程先運行,父進程掛起,直到子進程調用exec或exit,在這以后,父子進程的執行順序不再有限制。進程的創建fork函數實例以及說明:因父進程和子進程的運行無關,父進程或子進程返回的順序隨機的,因此運行結果不唯一。vfork()函數以及實例vfork創建新進程的主要目的在于用exec函數執行另外的程序,實際上,在沒調用exec或exit之前子進程的運行中是與父進程共享數據段的。在vfork調用中,子進程先運行,父進程掛起,直到子進程調用exec或exit,在這以后,父子進程的執行順序不再有限制。進程的創建fork運行結果vfork運行結果進程的創建fork運行結果vfork運行結果進程的創建(選學)exec()函數族用fork創建子進程后執行的是和父進程相同的程序(但有可能執行不同的代碼分支),子進程往往要調用一種exec函數以執行另一個程序。當進程調用一種exec函數時,該進程的用戶空間代碼和數據完全被新程序替換,從新程序的啟動例程開始執行。調用exec并不創建新進程,所以調用exec前后該進程的id并未改變。進程的創建(選學)其實有六種以exec開頭的函數,統稱exec函數:#include<unistd.h>intexecl(constchar*path,constchar*arg,...);intexeclp(constchar*file,constchar*arg,...);intexecle(constchar*path,constchar*arg,...,char*constenvp[]);intexecv(constchar*path,char*constargv[]);intexecvp(constchar*file,char*constargv[]);intexecve(constchar*path,char*constargv[],char*constenvp[]);進程的創建(選學)這些函數如果調用成功則加載新的程序從啟動代碼開始執行,不再返回,如果調用出錯則返回-1,所以exec函數只有出錯的返回值而沒有成功的返回值。在exec函數族中,后綴l、v、p、e添加到exec后,所指定的函數將具有某種操作能力有后綴:p(path)時,函數可以利用DOS的PATH變量查找子程序文件。假如你希望執行命令/bin/cat/etc/passwd/etc/group(通過cat命令查看/etc/passwd和/etc/group的內容)進程的創建(選學)l(list)時,希望接收以逗號分隔的參數列表,列表以NULL指針作為結束標志。execl("/bin/cat","/etc/passed","/etc/group",NULL);v(vector)時,希望接收到一個以NULL結尾的字符串數組的指針。char*argv[]={"/bin/cat","/etc/passed","/etc/group",NULL}execv("/bin/cat",argv);e(environment)時,函數傳遞參數envp,允許改變子進程的環境,無后綴e時,子進程使用當前程序的環境。envp也是一個以NULL結尾的字符串數組指針。進程的創建(選學)execl和execlp完全相同,execv和execvp完全相同。execl()和execv()要求提供可執行文件的絕對或相對路徑名,而execlp()和execvp()使用$PATH環境變量查找path。進程的創建(選學)一個完整的例子#include<unistd.h>#include<stdlib.h>intmain(void){ execlp("ps","ps","-o", "pid,ppid,pgrp,session,tpgid,comm",NULL); perror("execps");exit(1);}[root@localhostch06]#./execlpPIDPPIDPGRPSESSTPGIDCOMMAND91259122 9125 91259937 bash99379125 9937 91259937 ps進程的創建(選學)由于exec函數只有錯誤返回值,只要返回了一定是出錯了,所以不需要判斷它的返回值,直接在后面調用perror即可。注意在調用execlp時傳了兩個"ps"參數,第一個"ps"是程序名,execlp函數要在PATH環境變量中找到這個程序并執行它,而第二個"ps"是第一個命令行參數,execlp函數并不關心它的值,只是簡單地把它傳給ps程序,ps程序可以通過main函數的argv[0]取到這個參數。調用exec后,原來打開的文件描述符仍然是打開的。利用這一點可以實現I/O重定向。實例execve.c進程的創建(選學)Linux特有的調用——cloneclone是Linux2.0以后才具備的新功能,它較fork更強(可認為fork是clone要實現的一部分),可以使得創建的子進程共享父進程的資源,并且要使用此函數必須在編譯內核時設置clone_actually_works_ok選項。clone函數的原型為:#inlude<sched.h>intclone(int(*fn)(void*),void*child_stack,intflags,void*arg);此函數返回創建進程的PID,函數中的flags標志用于設置創建子進程時的相關選項,具體含義如下表:進程的創建(選學)標志含義CLONE_PARENT創建的子進程的父進程是調用者的父進程,新進程與創建它的進程成了“兄弟”而不是“父子”CLONE_FS子進程與父進程共享相同的文件系統,包括root、當前目錄、umaskCLONE_FILES子進程與父進程共享相同的文件描述符(filedescriptor)表CLONE_NEWNS在新的namespace啟動子進程,namespace描述了進程的文件hierarchyCLONE_SIGHAND子進程與父進程共享相同的信號處理(signalhandler)表CLONE_PTRACE若父進程被trace,子進程也被traceCLONE_VFORK父進程被掛起,直至子進程釋放虛擬內存資源CLONE_VM子進程與父進程運行于相同的內存空間CLONE_PID子進程在創建時PID與父進程一致CLONE_THREADLinux2.4中增加以支持POSIX線程標準,子進程與父進程共享相同的線程群進程等待在多進程處理時,用戶可能需要用到有關進程等待的操作。這種等待可以是進程組成員間的等待,也可以是父進程對子進程的等待。例如,當一個進程結束時,Linux系統將產生一個SIGCHLD信號通知其父進程。在父進程未查詢子進程結束的原因時,該子進程雖然停止了,但并未完全結束。此時該子進程被稱為僵尸進程(zombieprocess)這時的處理方法之一就是使用進程等待的系統調用wait
和waitpid。進程等待wait()函數#include<sys/types.h>#include<sys/wait.h>pid_twait(int*status);進程一旦調用了wait,就立即阻塞自己,由wait()函數分析是否當前的某個子進程已經退出,如果讓它找到了這樣一個已經變成僵尸的子進程,wait就會收集這個子進程的信息,并把它徹底銷毀后返回;如果沒有找到這樣一個子進程,wait就會一直阻塞在這里,直到有一個出現為止。可認為wait()系統調用的作用就是負責回收僵尸進程。進程等待因為在下列兩個事件都已經發生的情況下進程才會完全終止:(1)進程自己已經退出(或已經被一個信號殺死)(2)它的父進程已經執行了WAIT系統調用以觀察發生了什么。如果已經退出或被殺死而它的父進程還沒有為它執行WAIT的進程將進入某種掛起狀態,有時被稱為僵死狀態(ZombieState),這種進程不再參與調度,它的報警時鐘被關閉,但它仍將留在進程表中,它的內存被釋放。僵死是一種臨時狀態,很少會持續較長的時間,當父進程最后執行WAIT時,將釋放進程表項,并通知文件系統和內核。進程等待對于參數status是一個指向int型的變量,用來保存子進程退出時的狀態(例如子進程中有exit(2009)或return(2009),那么這個變量里的某些二進制位存放的就是2009,也就是子進程的返回值),但如果我們對這個子進程是如何死掉的毫不在意,只想把這個僵尸進程消滅掉,(事實上絕大多數情況下,我們都會這樣想),我們就可以設定這個參數為NULL,就象下面這樣:pid=wait(NULL);如果成功,wait會返回被收集的子進程的進程ID,如果調用進程沒有子進程,調用就會失敗,此時wait返回-1,同時errno被置為ECHILD。進程等待Wati()函數實例:wait1.c編譯并運行: $gccwait1.c-owait1 $./wait1 Thisischildprocesswithpidof1508 Icatchedachildprocesswithpidof1508可以明顯注意到,在第2行結果打印出來前有10秒鐘的等待時間,這就是我們設定的讓子進程睡眠的時間,只有子進程從睡眠中蘇醒過來,它才能正常退出,也就才能被父進程捕捉到。其實這里我們不管設定子進程睡眠的時間有多長,父進程都會一直等待下去。進程等待如果參數status的值不是NULL,wait就會把子進程退出時的狀態取出并存入其中,這是一個整數值,指出了子進程是正常退出還是被非正常結束的(一個進程也可以被其他進程用信號結束),以及正常結束時的返回值,或被哪一個信號結束的等信息。由于這些信息被存放在一個整數的不同二進制位中,所以用常規的方法讀取會非常麻煩,人們就設計了一套專門的宏(macro)來完成這項工作,下面我們來學習一下其中最常用的兩個:進程等待1、WIFEXITED(status)這個宏用來指出子進程是否為正常退出的,如果是,它會返回一個非零值。請注意,雖然名字一樣,這里的參數status并不同于wait唯一的參數--指向整數的指針status,而是那個指針所指向的整數,切記不要搞混了。2、WEXITSTATUS(status)當WIFEXITED返回非零值時,我們可以用這個宏來提取子進程的返回值,如果子進程調用exit(5)退出,WEXITSTATUS(status)就會返回5;如果子進程調用exit(7),WEXITSTATUS(status)就會返回7。請注意,如果進程不是正常退出的,也就是說,WIFEXITED返回0,這個值就毫無意義進程等待wait2.c實例。編譯并運行:[root@localhostch06]#gcc-owait2wait2.c[root@localhostch06]#./wait2Thisischildprocesswithpidof12668.thechildprocess12668exitnormally.thereturncodeis3.父進程準確捕捉到了子進程的返回值3,并把它打印了出來。進程等待waitpid()函數waitpid()
系統調用在Linux函數庫中的原型是: #include<sys/types.h> /#include<sys/wait.h> pid_twaitpid(pid_tpid,int*status,intoptions);從本質上講,系統調用waitpid和wait的作用是完全相同的,但waitpid多出了兩個可由用戶控制的參數pid和options,從而為我們編程提供了另一種更靈活的方式。下面我們就來詳細介紹一下這兩個參數:進程等待pid參數pid>0時,只等待進程ID等于pid的子進程,不管其它已經有多少子進程運行結束退出了,只要指定的子進程還沒有結束,waitpid就會一直等下去。pid=-1時,等待任何一個子進程退出,沒有任何限制,此時waitpid和wait的作用一模一樣。pid=0時,等待同一個進程組中的任何子進程,如果子進程已經加入了別的進程組,waitpid不會對它做任何理睬。pid<-1時,等待一個指定進程組中的任何子進程,這個進程組的ID等于pid的絕對值。進程等待options參數options提供了一些額外的選項來控制waitpid,目前在Linux中只支持WNOHANG和WUNTRACED兩個選項,這是兩個常數,可以用"|"運算符把它們連接起來使用,比如:ret=waitpid(-1,NULL,WNOHANG|WUNTRACED);
如果我們不想使用它們,也可以把options設為0,如:ret=waitpid(-1,NULL,0);如果使用了WNOHANG參數調用waitpid,即使沒有子進程退出,它也會立即返回,不會像wait那樣永遠等下去。而WUNTRACED參數,由于涉及到一些跟蹤調試方面的知識,加之極少用到,這里就不多講。進程等待Waitpid()函數實例編譯并運行:
$gccwaitpid.c-owaitpid $./waitpid Nochildexited
Nochildexited Nochildexited
Nochildexited
Nochildexited
Nochildexited
Nochildexited
Nochildexited
Nochildexited
Nochildexited successfullygetchild1526父進程經過10次失敗的嘗試之后,終于收集到了退出的子進程。進程等待父進程調用wait或waitpid時可能會:阻塞(如果它的所有子進程都還在運行)。帶子進程的終止信息立即返回(如果一個子進程已終止,正等待父進程讀取其終止信息)。出錯立即返回(如果它沒有任何子進程)。這兩個函數的區別是:如果父進程的所有子進程都還在運行,調用wait將使父進程阻塞,而調用waitpid時如果在options參數中指定WNOHANG可以使父進程不阻塞而立即返回0。wait等待第一個終止的子進程,而waitpid可以通過pid參數指定等待哪一個子進程。進程的終止進程結束可通過相應的函數實現:voidexit(intstatus);void_exit(intstatus);終止正在運行的程序,關閉所有被該文件打開的文件描述符_exit與exit不同的是可以關閉一些Linux下特有的退出句柄。intatexit(void(*function)(void));用于注冊一個不帶參數也沒有返回值的函數以供程序正常退出時被調用。參數function是指向所調用程序的文件指針。調用成功返回0,否則返回-1,并將errno設置為相應值進程的終止inton_exit(void(*function)(int,void*),void*arg);作用與atexit類似,不同是其注冊的函數具有參數,退出狀態和參數arg都是傳遞給該函數使用。voidabort(void);用來發送一個SIGABRT信號,該信號將使當前進程終止。voidassert(intexpression);先計算表達式
expression,如果其值為0,那么它先向stderr打印一條出錯信息,然后通過調用abort來終止程序運行。常用來檢測某些參數是否有不當情況出現,并在不當情況發生時以結束進程作為相應處理。進程的終止atexit實例assert實例system函數(選學)system函數是一個和操作系統緊密相關的函數。用戶可以使用它在自己的程序中調用系統提供的各種命令。 system函數的說明如下:#include<stdlib.h>intsystem(constchar*cmdstring);參數cmdstring是一個字符串指針。如果cmd是一個空指針,則僅僅當命令處理程序可用時,system返回非0值。system函數(選學)因為system在其實現中調用了fork,exec和waitpid,因此有三種返回值:1)如果fork失敗或者waitpid返回除EINTR之外的出錯,則system返回-1,而且errno中設置了錯誤類型2).如果exec失敗(表示不能執行shell),則其返回值如同shell執行了exit(127)一樣。3).否則所有三個函數(fork,exec和waitpid)都執行成功,并且system的返回值是shell的終止狀態,其格式已經在waitpid中說明。system函數(選學)如果一
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 電纜購銷合同
- 烘焙店創業計劃書
- 風險共擔合同書
- 中國戲曲課件
- 工程合作投資合同模板
- 幼兒園教師聘用合同
- 城市綠化養護項目勞務承包合同
- 胃腸道造瘺管護理
- 維修工程師聘任合同
- 竇性心律失常的護理措施
- 衛生法(教學講解課件)
- 高三沖刺100天勵志主題班會課件
- 全國工業產品生產許可證申請書
- 德能勤績廉個人總結的
- 中層干部崗位競聘報名表格評分表格評分標準
- 思想道德與法治課件:第六章 第一節 社會主義法律的特征和運行
- 有限空間作業及應急物資清單
- 《個人信息保護法》解讀
- GB∕T 3216-2016 回轉動力泵 水力性能驗收試驗 1級、2級和3級
- 新疆高速公路建設工程季節性施工方案
- 新版(七步法案例)PFMEA
評論
0/150
提交評論