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

下載本文檔

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

文檔簡介

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

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

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

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

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

$gccwaitpid.c-owaitpid $./waitpid Nochildexited

Nochildexited Nochildexited

Nochildexited

Nochildexited

Nochildexited

Nochildexited

Nochildexited

Nochildexited

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

expression,如果其值為0,那么它先向stderr打印一條出錯(cuò)信息,然后通過調(diào)用abort來終止程序運(yùn)行。常用來檢測某些參數(shù)是否有不當(dāng)情況出現(xiàn),并在不當(dāng)情況發(fā)生時(shí)以結(jié)束進(jìn)程作為相應(yīng)處理。進(jìn)程的終止atexit實(shí)例assert實(shí)例system函數(shù)(選學(xué))system函數(shù)是一個(gè)和操作系統(tǒng)緊密相關(guān)的函數(shù)。用戶可以使用它在自己的程序中調(diào)用系統(tǒng)提供的各種命令。 system函數(shù)的說明如下:#include<stdlib.h>intsystem(constchar*cmdstring);參數(shù)cmdstring是一個(gè)字符串指針。如果cmd是一個(gè)空指針,則僅僅當(dāng)命令處理程序可用時(shí),system返回非0值。system函數(shù)(選學(xué))因?yàn)閟ystem在其實(shí)現(xiàn)中調(diào)用了fork,exec和waitpid,因此有三種返回值:1)如果fork失敗或者waitpid返回除EINTR之外的出錯(cuò),則system返回-1,而且errno中設(shè)置了錯(cuò)誤類型2).如果exec失敗(表示不能執(zhí)行shell),則其返回值如同shell執(zhí)行了exit(127)一樣。3).否則所有三個(gè)函數(shù)(fork,exec和waitpid)都執(zhí)行成功,并且system的返回值是shell的終止?fàn)顟B(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)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論