天天看點

Linux多程序--wait/waitpid等待子程序狀态改變函數wait等待指定子程序狀态改變函數waitpid錯誤類型官方例程

等待子程序狀态改變函數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型參數,其值可以分為四類表示,具體描述如下:

  1. pid值小于-1,表示等待pid的絕對值與該參數相等的程序的所有子程序狀态發生改變,比如傳入的pid = -100 則調用該函數,系統所有pid值為100的程序的子程序狀态發生改變,都會導緻函數傳回,停止阻塞。
  2. pid值等于-1,表示等待目前程序的所有子程序狀态發生改變。
  3. pid值等于0,表示等待和調用該函數的程序擁有同一個程序組ID的程序狀态發生改變(比如擁有同一個父程序的程序)。
  4. pid值大于0,表示表示指定的程序的pid。

參數options的使用

參數options的值可以通過以下幾個常量的值進行或運算取得,其字段名稱以及具體含義如下:

  1. WNOHANG: 通知核心在沒有已終止程序項時不要阻塞。即如果沒有子程序已經終止,則立即傳回。
  2. WUNTRACED:若實作支援作業控制,而pid指定的任一子程序已經暫停,且其狀态尚未報告,則傳回其狀态。
  3. WCONTINUED:如果程序從stop狀态變為繼續執行狀态時,傳回該狀态。

如果waitpid函數執行成功,傳回狀态發生改變的程序PID,如果WNOHANG被設定,并且同時有多個程序已經退出了,傳回0,如果函數執行失敗傳回-1

錯誤類型

wait函數和waitpid函數錯誤狀态保持一緻,其錯誤資訊由status字段擷取。函數執行失敗的錯誤類型的具體表述如下:

  1. ECHILD:對于wait函數傳回該錯誤,表示目前沒有任何未被釋放的子程序。對于waitpid函數傳回該錯誤,表示通過pid參數指定的程序不存在,或者該pid是目前調用程序的PID。
  2. EINTR:目前沒有設定WNOHANG狀态,并且在函數執行過程中捕獲到了SIGCHILD信号或者是其他不被阻塞的信号。
  3. 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);
       }
   }
           

繼續閱讀