在2號手冊里查wait()。wait()等待任意一個子進程的狀態。
wait()等待成功會返回該子進程的id,返回失敗會返回-1:
小實驗? ? ?子進程的退出碼
子進程執行work(),父進程wait子進程。
子進程跑完5秒之后就exit(0)退出。
子進程跑的時候是run狀態
當子進程跑完,父進程接收到子進程的狀態,即僵尸狀態,然后父進程會跑10秒,10秒過后父進程也結束進程。
代碼如下:
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>void work()
{int cnt=5; while(cnt--) { printf("子進程開始啟動:pid:%d,ppid:%d,cnt:%d\n",getpid(),getppid(),cnt); sleep(1); }
} int main()
{ sleep(10); pid_t id=fork(); if(id==0) //子進程{ work(); exit(0); } else //父進程{pid_t ret=wait(NULL); if(ret==id) {printf("wait success,pid:%d\n",getpid());}
}sleep(10);return 0;}
~
結論:子進程在跑,父進程就要進行阻塞等待。等子進程跑完,父進程才wait sucess,總結如下:
waitpid()
用法:
?三個參數,重點講一下? stauts
status是輸出型參數,所謂輸出型參數需要用戶自己定義變量,然后傳參,操作系統接收這個參數經過操作之后再返回給用戶級變量
如下,定義一個int型變量,變量名為status,取地址傳參,然后等如果父進程等待子進程之后就把status的值打印出來看看:
結果如下:
status是一個整形,有32位,分為高八位和低八位:
?如果進程正常退出,就返回低八位的0,高八位的退出狀態。
如果異常退出,就返回低七位的終止信號,為什么不是低八位呢? 低八位的第一位是core dump標志,所以只返回低七位。
如下,我們把子進程的退出碼改為exit(10),再讓父進程去等待:運行結果:
status為2560。
因為退出碼10的二進制為1010,又因為異常所以在高八位,如下:
轉化為十進制就是2560;
exit sign為stautus的信號退出碼,exit code為status的進程退出碼:
printf("wait success,pid:%d,status返回碼:%d, exit sign:%d ,exit code:%d\n",getpid(),ret,status&0x7F,(status>>8)&0xFF);
為什么exit sign是 status&0x7F?
因為信號退出碼在低七位? 7是3個1,F是4個1,合起來就是7個1,&7個1就把低七位保留,其他位全變0
同理,exit code為高八位??
運行結果:
退出信號為0,退出碼為10、
如果我們把子進程的退出碼改為正常退出碼,即0,再跑,就會退出信號為0,退出碼為0:
我們給子進程寫一個除0錯誤:
?退出信號會顯示8:
我們讓子進程出現空指針錯誤:
退出信號為11:11就是段錯誤:
第二個實驗? 手動退出
我們讓子進程不要退出了,一直運行:
此時運行之后子進程就會一直跑,然后我們輸入kill -9 pid終止進程,進程退出信號會顯示9:
小結
父進程得到子進程的退出結果實際上是調用stautus這個整型變量,可以用一個指針解引用即可得到status。
WIFEXITED? ??WEXITSTAUS
?用這兩個宏就我們就可以不用關注返回值,宏會自己獲取子進程的返回值。
調用WIFEXITED獲取是否正常退出,如果為假,直接輸出else里面的異常。
如果為真,就調用WEXITSTAUS獲取子進程的退出碼并打印出來。
我們可以先搞一個異常出來,把子進程死循環:
運行:
我們再把子進程改為正常的再運行:
非阻塞輪巡/非阻塞等待
與阻塞式等待相對。
阻塞式等待父進程什么事情也不干,就在那等著子進程返回值。
阻塞式等待可以干自己的事情,等子進程返回的時候接收一下就可以了。