等待子程序狀态改變函數wait
函數原型:pid_t wait(int *status);
頭檔案:#include <sys/types.h> #include <sys/wait.h>
輸入參數:
status: int型指針,用于擷取子程序狀态發生改變時,傳回的狀态值。
傳回值:pid_t是一個宏定義,其實質是int被定義在#include <sys/types.h>
函數說明
調用wait函數将會使目前程序處于阻塞狀态,直到有一個子程序的狀态發生改變,當子程序接收到某個信号停止運作或者從stop狀态轉為繼續執行時,被認為子程序的狀态發生改變。
在子程序停止運作的狀态下,執行wait函數将會使系統釋放與子程序相關聯的系統資源,如果不執行該函數,則子程序将會處于“僵停”狀态,成為僵屍程序。
如果子程序的狀态已經發生了改變(比如子程序已經停止運作)。調用wait函數将會立即傳回。
如果函數執行成功傳回程序PID,如果函數執行失敗,則傳回-1
等待指定子程序狀态改變函數waitpid
函數原型:pid_t wait(pid_t pid,int *status,int options);
頭檔案:#include <sys/types.h> #include <sys/wait.h>
輸入參數:
pid: 指定的子程序pid
status: int型指針,用于擷取子程序狀态發生改變時,傳回的狀态值。
options: 選項,
傳回值:pid_t是一個宏定義,其實質是int被定義在#include <sys/types.h>
函數說明
waitpid函數的調用将阻塞調用程序的執行,直到pid參數指定的子程序狀态發生了改變,預設情況下,waitpid隻等待子程序的終止,但是這個行為可以通過options參數進行修改。
參數pid如何指定特定的程序或程序的集合
參數pid本質上是int型參數,其值可以分為四類表示,具體描述如下:
- pid值小于-1,表示等待pid的絕對值與該參數相等的程序的所有子程序狀态發生改變,比如傳入的pid = -100 則調用該函數,系統所有pid值為100的程序的子程序狀态發生改變,都會導緻函數傳回,停止阻塞。
- pid值等于-1,表示等待目前程序的所有子程序狀态發生改變。
- pid值等于0,表示等待和調用該函數的程序擁有同一個程序組ID的程序狀态發生改變(比如擁有同一個父程序的程序)。
- pid值大于0,表示表示指定的程序的pid。
參數options的使用
參數options的值可以通過以下幾個常量的值進行或運算取得,其字段名稱以及具體含義如下:
- WNOHANG: 通知核心在沒有已終止程序項時不要阻塞。即如果沒有子程序已經終止,則立即傳回。
- WUNTRACED:若實作支援作業控制,而pid指定的任一子程序已經暫停,且其狀态尚未報告,則傳回其狀态。
- WCONTINUED:如果程序從stop狀态變為繼續執行狀态時,傳回該狀态。
如果waitpid函數執行成功,傳回狀态發生改變的程序PID,如果WNOHANG被設定,并且同時有多個程序已經退出了,傳回0,如果函數執行失敗傳回-1
錯誤類型
wait函數和waitpid函數錯誤狀态保持一緻,其錯誤資訊由status字段擷取。函數執行失敗的錯誤類型的具體表述如下:
- ECHILD:對于wait函數傳回該錯誤,表示目前沒有任何未被釋放的子程序。對于waitpid函數傳回該錯誤,表示通過pid參數指定的程序不存在,或者該pid是目前調用程序的PID。
- EINTR:目前沒有設定WNOHANG狀态,并且在函數執行過程中捕獲到了SIGCHILD信号或者是其他不被阻塞的信号。
- EINVAL:選項字段設定的狀态無效。
官方例程
#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) { /* Code executed by child */
printf("Child PID is %ld\n", (long) getpid());
if (argc == 1)
pause(); /* Wait for signals */
_exit(atoi(argv[1]));
} else { /* Code executed by parent */
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);
}
}