歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux教程 >> Linux監聽子線程的函數

Linux監聽子線程的函數

日期:2017/2/28 16:14:49   编辑:Linux教程

waitpid系統調用

功能描述:
等待進程改變其狀態。所有下面哪些調用都被用於等待子進程狀態的改 變,獲取狀態已改變的子進程信息。狀態改變可被認為是:1.子進程已終止。2.信號導致子進程停止執行。3.信號恢復子進程的執行。在子進程終止的情況 下,wait調用將允許系統釋放與子進程關聯的資源。如果不執行wait,終止了的子進程會停留在"zombie"狀態。

如果發現子進程改變了狀態,這些調用會立即返回。反之,調用會被阻塞直到子進程狀態改變,或者由信號處理句柄所中斷(假如系統調用沒有通過sigaction的SA_RESTART標志重啟動)。

wait 系統調用掛起當前執行中的進程,直到它的一個子進程終止。waitpid掛起當前進程的執行,直到指定的子進程狀態發生變化。默認,waitpid只等待 終止狀態的子進程,但這種行為可通過選項來改變。waitid系統調用對於等待哪個子進程狀態改變提供了更精確的控制。

子進程已終 止,父進程尚未對其執行wait操作,子進程會轉入“僵死”狀態。內核為“僵死”狀態的進程保留最少的信息量(進程標識,終止狀態,資源使用信息),過後 父進程執行wait時可以獲取子進程信息。只要僵死的進程不通過wait從系統中移去,它將會占據內核進程表中的一個欄位。如果進程表被填滿,內核將不能 再產生新進程。如果父進程已終止,它的僵死子進程將由init進程收養,並自動執行wait將它們移去。


用法:
#include <sys/types.h>
#include <sys/wait.h>

pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);


參數:
pid:可能值有以下

小於-1 //意味著等待所有其進程組標識等於pid絕對值的子進程。
-1 //意味著等待任何子進程。
0 //意味著等待任何其組標識等於調用進程組標識的進程。
大於0 //意味著等待其進程標識等於pid的進程。

status:指向子進程的返回狀態,可通過以下宏進行檢索

WIFEXITED(status) //返回真如果子進程正常終止,例如:通過調用exit(),_exit(),或者從main()的return語句返回。
WEXITSTATUS(status) //返回子進程的退出狀態。這應來自子進程調用exit()或_exit()時指定的參數,或者來自main內部return語句參數的最低字節。只有WIFEXITED返回真時,才應該使用。
WIFSIGNALED(status) //返回真如果子進程由信號所終止
WTERMSIG(status) //返回導致子進程終止的信號數量。只有WIFSIGNALED返回真時,才應該使用。
WCOREDUMP(status) //返回真如果子進程導致內核轉存。只有WIFSIGNALED返回真時,才應該使用。並非所有平台都支持這個宏,使用時應放在#ifdef WCOREDUMP ... #endif內部。
WIFSTOPPED(status) //返回真如果信號導致子進程停止執行。
WSTOPSIG(status) //返回導致子進程停止執行的信號數量。只有WIFSTOPPED返回真時,才應該使用。
WIFCONTINUED(status) //返回真如果信號導致子進程繼續執行。

options:可以是0個或多個以下符號常量通過or運算的組合體

WNOHANG //如果沒有子進程退出,立即返回
WUNTRACED //如果有處於停止狀態的進程將導致調用返回。
WCONTINUED //如果停止了的進程由於SIGCONT信號的到來而繼續運行,調用將返回。

下面是Linux特有的選項,不能用於waitid
__WCLONE //只等待"clone"的子進程。一個"clone" 進程即是終止時不會給父進程發送信號,或者不會給父進程發送SIGCHLD信號的進程。
__WALL //等待所有類型的子進程,包括"clone"和"non-clone"。
__WNOTHREAD //不會等待同一線程組的其它線程的子孫。

WUNTRACED 和 WCONTINUED 只有在SIGCHLD信號沒有設置SA_NOCLDSTOP標志時才起作用。

idtype,id:這兩個參數結合在一起指出應選擇等待哪些子進程,可能情況有

idtype == P_PID //等待進程標識與id匹配的子進程。
idtype == P_PGID //等待進程組標識與id匹配的任何子進程。
idtype == P_ALL //等待任何子進程,id無作用

可在options參數中指定的感興趣的子進程狀態改變標志有以下常量,可以通過or運算加以組合

WEXITED //等待已終止的子進程。
WSTOPPED //等待由於信號已停止執行的子進程。
WCONTINUED //等待由於信號已恢復執行的子進程。
WNOHANG //作用如同waitpid。
WNOWAIT //保留子進程的可等待狀態,後面的wait調用可再次獲取子進程的狀態信息。

infop:成功執行返回時,waitid將填充infop所指向結構體的如下字段

si_pid //子進程標識。
si_uid //子進程的真實用戶標識。
si_signo //總被設置為SIGCHLD。
si_status //子進程的退出狀態,或者導致子進程退出,停止執行或恢復執行的信號,需要根據si_code字段來解釋。
si_code //可能值有CLD_EXITED(子進程調用_exit退出), CLD_KILLED(子進程被信號殺死),CLD_STOPPED(信號導致子進程停止執行),CLD_CONTINUED(信號恢復子進程繼續執行)。

返回說明:
wait():成功執行時,返回終止子進程的標識。失敗返回-1;
waitpid():成功執行時,返回狀態改變的子進程標識。失敗返回-1;如果指定WNOHANG標志,同時pid指定的進程狀態沒有發生變化,將返回0。
waitid():成功執行或者WNOHANG標志被設置而id指定的子進程狀態沒有發生變化時返回0。失敗返回-1。

出錯值可能有下面這些
ECHILD:參數指定的進程不存在,或者並非調用進程的子進程
EINTR;WNOHANG不被設置,同時捕捉到一個不被阻塞的信號或SIGCHLD信號
EINVAL:options參數無效

例子:

$ ./a.out &
Child PID is 32360
[1] 32359
$ kill -STOP 32360
stopped by signal 19
$ kill -CONT 32360
continued
$ kill -TERM 32360
killed by signal 15
[1]+ Done ./a.out
$

#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
pid_t cpid, w;
int status;

cpid = fork();
if (cpid == -1) { perror("fork"); exit(EXIT_FAILURE); }

if (cpid == 0) { /* 子進程執行 */
printf("Child PID is %ld\n", (long) getpid());
if (argc == 1)
pause(); /* Wait for signals */
_exit(atoi(argv[1]));

} else { /* 父進程執行 */
do {
w = waitpid(cpid, &status, WUNTRACED | WCONTINUED);
if (w == -1) { perror("waitpid"); exit(EXIT_FAILURE); }

if (WIFEXITED(status)) {
printf("exited, status=%d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("killed by signal %d\n", WTERMSIG(status));
} else if (WIFSTOPPED(status)) {
printf("stopped by signal %d\n", WSTOPSIG(status));
} else if (WIFCONTINUED(status)) {
printf("continued\n");
}
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
exit(EXIT_SUCCESS);
}

Copyright © Linux教程網 All Rights Reserved