《LINUX教程:進(jìn)程管理之wait和waitpid》要點:
本文介紹了LINUX教程:進(jìn)程管理之wait和waitpid,希望對您有用。如果有疑問,可以聯(lián)系我們。
在介紹wait、waitpid和waitid函數(shù)之前,首先要介紹一下僵尸進(jìn)程,因為,這三個函數(shù)的本色任務(wù)就是處理僵尸進(jìn)程的問題.
進(jìn)程會我們的生命體一樣,也有消亡.進(jìn)程在退出時,內(nèi)核會清理進(jìn)程幾乎所有的資源.例如:內(nèi)存資源、文件資源、信號量資源、共享內(nèi)存資源或者引用數(shù)減一 又或釋放共享內(nèi)存資源.但還有少量的資源沒有被內(nèi)核清理,例如:進(jìn)程控制塊PCB task_struct、內(nèi)核棧資源.這些資源沒有被釋放,是為了保存一些進(jìn)程退出是的重要信息,例如:進(jìn)程消耗的系統(tǒng)cpu時間、用戶cpu時間;收到了多少信號等待這些信息,類似于“墓志銘”,總結(jié)了進(jìn)程的一生.而wait、waitpid和waitid函數(shù)就是來釋放這些“墓志銘”信息的.之后進(jìn)程就脫離了僵尸進(jìn)程的狀態(tài).
過程的僵尸過程的狀態(tài),是一種“刀槍不入的狀態(tài)”,即使是用kill -9 也無法殺死.只能通過wait這些函數(shù)活著是通過init過程來“收尸”;
對于創(chuàng)立了很多的子進(jìn)程的父進(jìn)程,獲取子進(jìn)程的退出信息是非常有意義的.
include <sys/wait.h>
pid_t wait(int *status);
由上述返回值的含義,等待所有子進(jìn)程的退出時,要注意不要丟掉對信號中斷情況的考慮,代碼如下:
pit_t my_wait(int *state) { int retval; while( (retval=wait(state))!=-1 && (error==EINIR) ); return retval; }
wait函數(shù)的參數(shù)和waitpid函數(shù)的參數(shù)是一個意思.但waitpid函數(shù)對wait函數(shù)的局限性做了擴(kuò)展,所以,在介紹waitpid時,再來講wait的參數(shù).
#include<sys/wait.h>
pid_t waitpid(pit_t pid,int *status,int options);
返回值和wait函數(shù)一樣.
pid參數(shù)的理解:
首先給父進(jìn)程要等待的子進(jìn)程分類.子進(jìn)程分為:和父進(jìn)程同一進(jìn)程組的子進(jìn)程,和父進(jìn)程不同進(jìn)程組的子進(jìn)程.子進(jìn)程可以設(shè)置自己的進(jìn)程組,所以某些子進(jìn)程不一定和父進(jìn)程歸屬于同一個進(jìn)程組;pid>0,很自然,代表要等待的子進(jìn)程pid,這叫做“精準(zhǔn)打擊”;還有情況就是分類等待子進(jìn)程.由上述分類可知,與父進(jìn)程為同一進(jìn)程組的子進(jìn)程怎么表示,調(diào)用waitpid函數(shù)的父進(jìn)程原來就知道自己的進(jìn)程組pid,所以,不用設(shè)置參數(shù)pid的值,即給0就行;那與父進(jìn)程不在同一進(jìn)程組的子進(jìn)程的話,就得設(shè)置參數(shù)pid的值了,但要和“精準(zhǔn)打擊”的方式區(qū)別開,所以給負(fù)值,但取絕對值;當(dāng)然,等待任意子進(jìn)程的需求還是有的,而現(xiàn)在也正好只剩下一個值“-1”,剛好給它用;綜述,通過上面的分析才有了pid參數(shù)的使用方式.
內(nèi)核之中,wait和waitpid函數(shù)調(diào)用的都是wait4函數(shù).根據(jù)pid的值來給wait_ opts結(jié)構(gòu)體變量wo中的wo_type復(fù)制,再以實參的形式傳參給do_wait函數(shù),do_wait函數(shù)來決定等待什么狀態(tài)的子進(jìn)程.
wait4中的部門代碼:
struct wait_opts wo;
.
. //給type復(fù)制的過程
.
wo.wo_type = type;
wo.wo_pid = pid;
.
.
.
ret = do_wait(&wo);
在do_ wait函數(shù)中,主要要完成兩個人物,第一,父進(jìn)程中的每個線程都會去遍歷子進(jìn)程,第二,篩選要等待的子進(jìn)程;在內(nèi)核中,task_struct成員中children變量是保留子進(jìn)程鏈表的鏈表頭,利用list_for_each_enpty函數(shù)來遍歷.利用eligible_pid函數(shù)來篩選.
遍歷子過程代碼:
static int do_wait_thread(struct wait_opts *wo,
struct task_struct *tsk)
{
struct task_struct *p;
list_for_each_enpty(p,&tsk->children,silbling)
{
int ret = wait_consider_task(wo,0,p);
if(ret)
return ret;
}
return 0;
}
篩選子過程的代碼:
static int eligible_pid(struct wait_opts *wo,
struct task_struct *p)
{
return wo->wo_type == PIDTYPE_MAX ||
task_pid_type(p,wo->wo_type) == wo->wo_pid;
}
當(dāng)waitpid函數(shù)參數(shù)pid的值為-1時,wo_type的值為PIDTYPE_MAX;其他三種情況由task_pid_type函數(shù)來處置.
是一個位掩碼,可以同時存在多個標(biāo)記.當(dāng)options的值為0時,行為和wait類似.
標(biāo)記位:
該參數(shù)存儲的信息時按位存儲的,我們沒方法解析status的值,只能通過系統(tǒng)提供的宏去解析.這些宏安功能分可以分為兩類:獲取子進(jìn)程狀態(tài)和判斷是非由相應(yīng)信號產(chǎn)生;
WIFEIXITED(status):正常退出,返回true;
WEXITSTATUS(status):正常退出,獲取進(jìn)程退出狀態(tài);
WIFSIGNALED(status): 被信號殺死,返回true;
WTREMSIG(status):被信號殺死,返回殺死進(jìn)程的pid;
WCOREDUMOP(status):子進(jìn)程產(chǎn)生core dump,返回true;
WIFSTOPPED(status):收到相關(guān)信號,暫停執(zhí)行,返回true;
WSTOPSIG(status):如果子進(jìn)程處于停止?fàn)顟B(tài),該宏返回導(dǎo)致子進(jìn)
程停止的信號值;
WIFCONTINUED(status): 遞送SIGCONT信號,子進(jìn)程回復(fù)執(zhí)行,返回true;
沒有需要返回使子進(jìn)程蘇醒的信號的值,因為只有唯一一個SIGCONT信號才能使進(jìn)程又停止?fàn)顟B(tài)恢復(fù)到執(zhí)行狀態(tài).
本文永遠(yuǎn)更新鏈接地址:
更多LINUX教程,盡在維易PHP學(xué)院專欄。歡迎交流《LINUX教程:進(jìn)程管理之wait和waitpid》!
轉(zhuǎn)載請注明本頁網(wǎng)址:
http://www.fzlkiss.com/jiaocheng/7686.html