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