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()獲取子進程退出狀態
2)WIFSIGNALED() 真
WTERMSIG()獲取導致子進程終止的信號的 編碼