Linux多進程--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);
       }
   }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章