例程

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h>
int main ()
{
pid_t fpid; //fpid表示fork函式返回的值
int count=0;
int status,i;
fpid=fork();
if (fpid < 0)
printf("error in fork!");
else if (fpid == 0) {
sleep(10);
printf("I am the child process, my process id is %d\n",getpid());
count++;
exit(123);
}
else {
printf("I am the parent process, my process id is %d\n",getpid());
count++;
int res = wait(&status);
i = WEXITSTATUS(status);
printf("The child exits status:%d\n", i);
}
printf("count is: %d\n",count);
return 0;
}

編譯執行上面的程式碼,然後,刪除下面兩行程式碼再次編譯執行。

int res = wait(&status);
i = WEXITSTATUS(status);

對比兩次執行結果,很容易發現wait的作用:讓父程序等待子程序執行結束並且接收子程序的退出狀態。

什麼場景需要用到wait?當子程序和父程序協同完成一項任務並且在父程序中彙總任務結果的時候。

本文的主題,便是探討如何實現wait和exit。

wait

在父程序中使用wait。流程如下:

  1. 父程序沒有子程序,呼叫wait後,不阻塞父程序,父程序按照正常流程執行。
  2. 父程序有子程序,但是所有子程序的狀態都不是“掛起”狀態,把父程序設定成“等待”狀態。
  3. 父程序有子程序,而且這個子程序的狀態是“掛起”狀態,回收子程序佔用的程序表,並且解除父程序的阻塞。

exit

在子程序中使用exit。流程如下:

  1. 子程序是C,父程序是P。
  2. 遍歷程序表陣列,找到程序P。
  3. 如果P是“等待“狀態,回收C佔用的程序表,解除P的阻塞。
  4. 如果P不是”等待“狀態,把C設定為”掛起“狀態。
  5. 還沒有結束,還需要處理C的子程序。
  6. 把C的子程序”過繼“給INIT程序。
  7. INIT程序是什麼程序?所有的程序都通過這個程序呼叫fork產生。
  8. 所謂”過繼“,就是把子程序的父程序由C設定成INIT。
  9. 接著判斷INIT的狀態是否為”等待“狀態,然後判斷子程序的狀態是否為”掛起“狀態。
  10. 如果答案都是”是”,把INIT程序設定成”執行“態,回收子程序。
  11. C的其他子程序呼叫了exit,怎麼處理?
  12. 使用一個迴圈,迴圈體內,INIT程序呼叫wait。如此,INIT程序能不斷處理呼叫了exit的其他子程序。