進程管理函數(shù)_第1頁
進程管理函數(shù)_第2頁
進程管理函數(shù)_第3頁
進程管理函數(shù)_第4頁
進程管理函數(shù)_第5頁
已閱讀5頁,還剩34頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

進程進程進程控制的相關(guān)函數(shù)進程的創(chuàng)建派生進程:fork(),vfork();創(chuàng)建執(zhí)行其他程序的進程:exec();(選學(xué))Linux系統(tǒng)特有的調(diào)用:__clone();(選學(xué))進程的等待wait(),waitpid();進程的終止exit(),atexit(),on_exit(),abort(),_exit();其他函數(shù)system()(選學(xué))

,getpid()。進程的創(chuàng)建fork()函數(shù)#include<sys/types.h>#include<unistd.h>pid_tfork(void);fork在英文中是“分叉”的意思。一個進程在運行中,如果使用了fork

,就產(chǎn)生了另一個進程,于是進程就“分叉”了。當前進程為父進程,通過fork()會產(chǎn)生一個子進程。對于父進程,返回子程序的進程號,而對于子程序則返回0,這就是fork函數(shù)的特點“調(diào)用一次,返回兩次”,出錯則返回-1。fork函數(shù)是Unix系統(tǒng)最杰出的成就之一。進程的創(chuàng)建fork函數(shù)實例以及說明:因父進程和子進程的運行無關(guān),父進程或子進程返回的順序隨機的,因此運行結(jié)果不唯一。vfork()函數(shù)以及實例vfork創(chuàng)建新進程的主要目的在于用exec函數(shù)執(zhí)行另外的程序,實際上,在沒調(diào)用exec或exit之前子進程的運行中是與父進程共享數(shù)據(jù)段的。在vfork調(diào)用中,子進程先運行,父進程掛起,直到子進程調(diào)用exec或exit,在這以后,父子進程的執(zhí)行順序不再有限制。進程的創(chuàng)建fork函數(shù)實例以及說明:因父進程和子進程的運行無關(guān),父進程或子進程返回的順序隨機的,因此運行結(jié)果不唯一。vfork()函數(shù)以及實例vfork創(chuàng)建新進程的主要目的在于用exec函數(shù)執(zhí)行另外的程序,實際上,在沒調(diào)用exec或exit之前子進程的運行中是與父進程共享數(shù)據(jù)段的。在vfork調(diào)用中,子進程先運行,父進程掛起,直到子進程調(diào)用exec或exit,在這以后,父子進程的執(zhí)行順序不再有限制。進程的創(chuàng)建fork運行結(jié)果vfork運行結(jié)果進程的創(chuàng)建fork運行結(jié)果vfork運行結(jié)果進程的創(chuàng)建(選學(xué))exec()函數(shù)族用fork創(chuàng)建子進程后執(zhí)行的是和父進程相同的程序(但有可能執(zhí)行不同的代碼分支),子進程往往要調(diào)用一種exec函數(shù)以執(zhí)行另一個程序。當進程調(diào)用一種exec函數(shù)時,該進程的用戶空間代碼和數(shù)據(jù)完全被新程序替換,從新程序的啟動例程開始執(zhí)行。調(diào)用exec并不創(chuàng)建新進程,所以調(diào)用exec前后該進程的id并未改變。進程的創(chuàng)建(選學(xué))其實有六種以exec開頭的函數(shù),統(tǒng)稱exec函數(shù):#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[]);進程的創(chuàng)建(選學(xué))這些函數(shù)如果調(diào)用成功則加載新的程序從啟動代碼開始執(zhí)行,不再返回,如果調(diào)用出錯則返回-1,所以exec函數(shù)只有出錯的返回值而沒有成功的返回值。在exec函數(shù)族中,后綴l、v、p、e添加到exec后,所指定的函數(shù)將具有某種操作能力有后綴:p(path)時,函數(shù)可以利用DOS的PATH變量查找子程序文件。假如你希望執(zhí)行命令/bin/cat/etc/passwd/etc/group(通過cat命令查看/etc/passwd和/etc/group的內(nèi)容)進程的創(chuàng)建(選學(xué))l(list)時,希望接收以逗號分隔的參數(shù)列表,列表以NULL指針作為結(jié)束標志。execl("/bin/cat","/etc/passed","/etc/group",NULL);v(vector)時,希望接收到一個以NULL結(jié)尾的字符串數(shù)組的指針。char*argv[]={"/bin/cat","/etc/passed","/etc/group",NULL}execv("/bin/cat",argv);e(environment)時,函數(shù)傳遞參數(shù)envp,允許改變子進程的環(huán)境,無后綴e時,子進程使用當前程序的環(huán)境。envp也是一個以NULL結(jié)尾的字符串數(shù)組指針。進程的創(chuàng)建(選學(xué))execl和execlp完全相同,execv和execvp完全相同。execl()和execv()要求提供可執(zhí)行文件的絕對或相對路徑名,而execlp()和execvp()使用$PATH環(huán)境變量查找path。進程的創(chuàng)建(選學(xué))一個完整的例子#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進程的創(chuàng)建(選學(xué))由于exec函數(shù)只有錯誤返回值,只要返回了一定是出錯了,所以不需要判斷它的返回值,直接在后面調(diào)用perror即可。注意在調(diào)用execlp時傳了兩個"ps"參數(shù),第一個"ps"是程序名,execlp函數(shù)要在PATH環(huán)境變量中找到這個程序并執(zhí)行它,而第二個"ps"是第一個命令行參數(shù),execlp函數(shù)并不關(guān)心它的值,只是簡單地把它傳給ps程序,ps程序可以通過main函數(shù)的argv[0]取到這個參數(shù)。調(diào)用exec后,原來打開的文件描述符仍然是打開的。利用這一點可以實現(xiàn)I/O重定向。實例execve.c進程的創(chuàng)建(選學(xué))Linux特有的調(diào)用——cloneclone是Linux2.0以后才具備的新功能,它較fork更強(可認為fork是clone要實現(xiàn)的一部分),可以使得創(chuàng)建的子進程共享父進程的資源,并且要使用此函數(shù)必須在編譯內(nèi)核時設(shè)置clone_actually_works_ok選項。clone函數(shù)的原型為:#inlude<sched.h>intclone(int(*fn)(void*),void*child_stack,intflags,void*arg);此函數(shù)返回創(chuàng)建進程的PID,函數(shù)中的flags標志用于設(shè)置創(chuàng)建子進程時的相關(guān)選項,具體含義如下表:進程的創(chuàng)建(選學(xué))標志含義CLONE_PARENT創(chuàng)建的子進程的父進程是調(diào)用者的父進程,新進程與創(chuàng)建它的進程成了“兄弟”而不是“父子”CLONE_FS子進程與父進程共享相同的文件系統(tǒng),包括root、當前目錄、umaskCLONE_FILES子進程與父進程共享相同的文件描述符(filedescriptor)表CLONE_NEWNS在新的namespace啟動子進程,namespace描述了進程的文件hierarchyCLONE_SIGHAND子進程與父進程共享相同的信號處理(signalhandler)表CLONE_PTRACE若父進程被trace,子進程也被traceCLONE_VFORK父進程被掛起,直至子進程釋放虛擬內(nèi)存資源CLONE_VM子進程與父進程運行于相同的內(nèi)存空間CLONE_PID子進程在創(chuàng)建時PID與父進程一致CLONE_THREADLinux2.4中增加以支持POSIX線程標準,子進程與父進程共享相同的線程群進程等待在多進程處理時,用戶可能需要用到有關(guān)進程等待的操作。這種等待可以是進程組成員間的等待,也可以是父進程對子進程的等待。例如,當一個進程結(jié)束時,Linux系統(tǒng)將產(chǎn)生一個SIGCHLD信號通知其父進程。在父進程未查詢子進程結(jié)束的原因時,該子進程雖然停止了,但并未完全結(jié)束。此時該子進程被稱為僵尸進程(zombieprocess)這時的處理方法之一就是使用進程等待的系統(tǒng)調(diào)用wait

和waitpid。進程等待wait()函數(shù)#include<sys/types.h>#include<sys/wait.h>pid_twait(int*status);進程一旦調(diào)用了wait,就立即阻塞自己,由wait()函數(shù)分析是否當前的某個子進程已經(jīng)退出,如果讓它找到了這樣一個已經(jīng)變成僵尸的子進程,wait就會收集這個子進程的信息,并把它徹底銷毀后返回;如果沒有找到這樣一個子進程,wait就會一直阻塞在這里,直到有一個出現(xiàn)為止??烧J為wait()系統(tǒng)調(diào)用的作用就是負責回收僵尸進程。進程等待因為在下列兩個事件都已經(jīng)發(fā)生的情況下進程才會完全終止:(1)進程自己已經(jīng)退出(或已經(jīng)被一個信號殺死)(2)它的父進程已經(jīng)執(zhí)行了WAIT系統(tǒng)調(diào)用以觀察發(fā)生了什么。如果已經(jīng)退出或被殺死而它的父進程還沒有為它執(zhí)行WAIT的進程將進入某種掛起狀態(tài),有時被稱為僵死狀態(tài)(ZombieState),這種進程不再參與調(diào)度,它的報警時鐘被關(guān)閉,但它仍將留在進程表中,它的內(nèi)存被釋放。僵死是一種臨時狀態(tài),很少會持續(xù)較長的時間,當父進程最后執(zhí)行WAIT時,將釋放進程表項,并通知文件系統(tǒng)和內(nèi)核。進程等待對于參數(shù)status是一個指向int型的變量,用來保存子進程退出時的狀態(tài)(例如子進程中有exit(2009)或return(2009),那么這個變量里的某些二進制位存放的就是2009,也就是子進程的返回值),但如果我們對這個子進程是如何死掉的毫不在意,只想把這個僵尸進程消滅掉,(事實上絕大多數(shù)情況下,我們都會這樣想),我們就可以設(shè)定這個參數(shù)為NULL,就象下面這樣:pid=wait(NULL);如果成功,wait會返回被收集的子進程的進程ID,如果調(diào)用進程沒有子進程,調(diào)用就會失敗,此時wait返回-1,同時errno被置為ECHILD。進程等待Wati()函數(shù)實例:wait1.c編譯并運行: $gccwait1.c-owait1 $./wait1 Thisischildprocesswithpidof1508 Icatchedachildprocesswithpidof1508可以明顯注意到,在第2行結(jié)果打印出來前有10秒鐘的等待時間,這就是我們設(shè)定的讓子進程睡眠的時間,只有子進程從睡眠中蘇醒過來,它才能正常退出,也就才能被父進程捕捉到。其實這里我們不管設(shè)定子進程睡眠的時間有多長,父進程都會一直等待下去。進程等待如果參數(shù)status的值不是NULL,wait就會把子進程退出時的狀態(tài)取出并存入其中,這是一個整數(shù)值,指出了子進程是正常退出還是被非正常結(jié)束的(一個進程也可以被其他進程用信號結(jié)束),以及正常結(jié)束時的返回值,或被哪一個信號結(jié)束的等信息。由于這些信息被存放在一個整數(shù)的不同二進制位中,所以用常規(guī)的方法讀取會非常麻煩,人們就設(shè)計了一套專門的宏(macro)來完成這項工作,下面我們來學(xué)習一下其中最常用的兩個:進程等待1、WIFEXITED(status)這個宏用來指出子進程是否為正常退出的,如果是,它會返回一個非零值。請注意,雖然名字一樣,這里的參數(shù)status并不同于wait唯一的參數(shù)--指向整數(shù)的指針status,而是那個指針所指向的整數(shù),切記不要搞混了。2、WEXITSTATUS(status)當WIFEXITED返回非零值時,我們可以用這個宏來提取子進程的返回值,如果子進程調(diào)用exit(5)退出,WEXITSTATUS(status)就會返回5;如果子進程調(diào)用exit(7),WEXITSTATUS(status)就會返回7。請注意,如果進程不是正常退出的,也就是說,WIFEXITED返回0,這個值就毫無意義進程等待wait2.c實例。編譯并運行:[root@localhostch06]#gcc-owait2wait2.c[root@localhostch06]#./wait2Thisischildprocesswithpidof12668.thechildprocess12668exitnormally.thereturncodeis3.父進程準確捕捉到了子進程的返回值3,并把它打印了出來。進程等待waitpid()函數(shù)waitpid()

系統(tǒng)調(diào)用在Linux函數(shù)庫中的原型是: #include<sys/types.h> /#include<sys/wait.h> pid_twaitpid(pid_tpid,int*status,intoptions);從本質(zhì)上講,系統(tǒng)調(diào)用waitpid和wait的作用是完全相同的,但waitpid多出了兩個可由用戶控制的參數(shù)pid和options,從而為我們編程提供了另一種更靈活的方式。下面我們就來詳細介紹一下這兩個參數(shù):進程等待pid參數(shù)pid>0時,只等待進程ID等于pid的子進程,不管其它已經(jīng)有多少子進程運行結(jié)束退出了,只要指定的子進程還沒有結(jié)束,waitpid就會一直等下去。pid=-1時,等待任何一個子進程退出,沒有任何限制,此時waitpid和wait的作用一模一樣。pid=0時,等待同一個進程組中的任何子進程,如果子進程已經(jīng)加入了別的進程組,waitpid不會對它做任何理睬。pid<-1時,等待一個指定進程組中的任何子進程,這個進程組的ID等于pid的絕對值。進程等待options參數(shù)options提供了一些額外的選項來控制waitpid,目前在Linux中只支持WNOHANG和WUNTRACED兩個選項,這是兩個常數(shù),可以用"|"運算符把它們連接起來使用,比如:ret=waitpid(-1,NULL,WNOHANG|WUNTRACED);

如果我們不想使用它們,也可以把options設(shè)為0,如:ret=waitpid(-1,NULL,0);如果使用了WNOHANG參數(shù)調(diào)用waitpid,即使沒有子進程退出,它也會立即返回,不會像wait那樣永遠等下去。而WUNTRACED參數(shù),由于涉及到一些跟蹤調(diào)試方面的知識,加之極少用到,這里就不多講。進程等待Waitpid()函數(shù)實例編譯并運行:

$gccwaitpid.c-owaitpid $./waitpid Nochildexited

Nochildexited Nochildexited

Nochildexited

Nochildexited

Nochildexited

Nochildexited

Nochildexited

Nochildexited

Nochildexited successfullygetchild1526父進程經(jīng)過10次失敗的嘗試之后,終于收集到了退出的子進程。進程等待父進程調(diào)用wait或waitpid時可能會:阻塞(如果它的所有子進程都還在運行)。帶子進程的終止信息立即返回(如果一個子進程已終止,正等待父進程讀取其終止信息)。出錯立即返回(如果它沒有任何子進程)。這兩個函數(shù)的區(qū)別是:如果父進程的所有子進程都還在運行,調(diào)用wait將使父進程阻塞,而調(diào)用waitpid時如果在options參數(shù)中指定WNOHANG可以使父進程不阻塞而立即返回0。wait等待第一個終止的子進程,而waitpid可以通過pid參數(shù)指定等待哪一個子進程。進程的終止進程結(jié)束可通過相應(yīng)的函數(shù)實現(xiàn):voidexit(intstatus);void_exit(intstatus);終止正在運行的程序,關(guān)閉所有被該文件打開的文件描述符_exit與exit不同的是可以關(guān)閉一些Linux下特有的退出句柄。intatexit(void(*function)(void));用于注冊一個不帶參數(shù)也沒有返回值的函數(shù)以供程序正常退出時被調(diào)用。參數(shù)function是指向所調(diào)用程序的文件指針。調(diào)用成功返回0,否則返回-1,并將errno設(shè)置為相應(yīng)值進程的終止inton_exit(void(*function)(int,void*),void*arg);作用與atexit類似,不同是其注冊的函數(shù)具有參數(shù),退出狀態(tài)和參數(shù)arg都是傳遞給該函數(shù)使用。voidabort(void);用來發(fā)送一個SIGABRT信號,該信號將使當前進程終止。voidassert(intexpression);先計算表達式

expression,如果其值為0,那么它先向stderr打印一條出錯信息,然后通過調(diào)用abort來終止程序運行。常用來檢測某些參數(shù)是否有不當情況出現(xiàn),并在不當情況發(fā)生時以結(jié)束進程作為相應(yīng)處理。進程的終止atexit實例assert實例system函數(shù)(選學(xué))system函數(shù)是一個和操作系統(tǒng)緊密相關(guān)的函數(shù)。用戶可以使用它在自己的程序中調(diào)用系統(tǒng)提供的各種命令。 system函數(shù)的說明如下:#include<stdlib.h>intsystem(constchar*cmdstring);參數(shù)cmdstring是一個字符串指針。如果cmd是一個空指針,則僅僅當命令處理程序可用時,system返回非0值。system函數(shù)(選學(xué))因為system在其實現(xiàn)中調(diào)用了fork,exec和waitpid,因此有三種返回值:1)如果fork失敗或者waitpid返回除EINTR之外的出錯,則system返回-1,而且errno中設(shè)置了錯誤類型2).如果exec失敗(表示不能執(zhí)行shell),則其返回值如同shell執(zhí)行了exit(127)一樣。3).否則所有三個函數(shù)(fork,exec和waitpid)都執(zhí)行成功,并且system的返回值是shell的終止狀態(tài),其格式已經(jīng)在waitpid中說明。system函數(shù)(選學(xué))如果一

溫馨提示

  • 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論