wait()函數:回收僵屍程序
父程序調用wait函數可以回收子程序終止資訊。該函數有三個功能:
1) 阻塞等待子程序退出
2) 回收子程序殘留資源
3) 擷取子程序結束狀态(退出原因)
/***
zoom_test.c
***/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void)
{
pid_t pid, wpid;
pid = fork();
int status;
if (pid == 0) {
printf("---child, my parent= %d, going to sleep 10s\n", getppid());
sleep(20);
printf("-------------child die--------------\n");
exit(77);
} else if (pid > 0) {
while (1) {
printf("I am parent, pid = %d, myson = %d\n", getpid(), pid);
wpid = wait(&status);
if (wpid == -1) {
perror("wait error");
exit(1);
}
if (WIFEXITED(status)) { //為真說明子程序正常結束
printf("child exit with %d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) { //為真說明子程序被信号終止(異常)
printf("child is killed by %d\n", WTERMSIG(status));
}
sleep(1);
}
} else {
perror("fork");
return 1;
}
return 0;
}
pid_t wit(int *status); 成功:清理掉的子程序ID;失敗:-1(沒有子程序)
當程序終止時,作業系統的隐式回收進制會:
- 關閉所有的檔案描述符;
- 釋放使用者空間的記憶體;
核心的PCB仍存在。其中儲存該程序的退出狀态。(正常終止—>推出值;異常退出—>終止信号)
可使用wait函數傳出參數status來儲存程序的退出狀态。借助宏函數來進一步判斷程序終止的具體原因。宏函數可以分為以下三組:
-
WIFEXITED(status) 為非0 à 程序正常結束
WEXITSTATUS(status)如上宏為真,使用此宏à擷取程序的退出狀态(exit參數)
-
WIFSIGNALED(status)為非0 à 程序異常終止
WTERMSIG(status)如上宏為真,使用此宏 à 取得使程序終止的那個信号的編号
/***
wait1.c
***/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h>
int main(void)
{
pid_t pid, wpid;
pid = fork();
if(pid == -1){
perror("fork error");
exit(1);
} else if(pid == 0){ //son
printf("I'm process child, pid = %d\n", getpid());
sleep(7); //困了...
} else {
lable:
wpid = wait(NULL); //死等!!!
if(wpid == -1){
perror("wait error");
goto lable;
}
printf("I'm parent, I catched child process,"
"pid = %d\n", wpid);
}
return 0;
}
/***
wait2.c
***/
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h>
int main(void)
{
pid_t pid, wpid;
int status;
pid = fork();
if(pid == -1){
perror("fork error");
exit(1);
} else if(pid == 0){ //son
printf("I'm process child, pid = %d\n", getpid());
#if 1
execl("./abnor", "abnor", NULL);
perror("execl error");
exit(1);
#endif
sleep(1);
exit(10);
} else {
//wpid = wait(NULL); //傳出參數
wpid = wait(&status); //傳出參數
if(WIFEXITED(status)){ //正常退出
printf("I'm parent, The child process "
"%d exit normally\n", wpid);
printf("return value:%d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) { //異常退出
printf("The child process exit abnormally, "
"killed by signal %d\n", WTERMSIG(status));
//擷取信号編号
} else {
printf("other...\n");
}
}
return 0;
}
wait(status):
傳回:成功:pid 失敗 -1
status:傳出參數
1: 阻塞等待子程序
2: 回收子程序資源
3: 擷取子程序結束狀态:1)WIFEXITED()真
WEXITSTATUS()擷取子程序退出狀态