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