wait和waitpid出現的原因 SIGCHLD --當子進程退出的時候,內核會向父進程發送SIGCHLD信號,子進程的退出是個異步事件(子進程可以在父進程運行的任何時刻終止) --子進程退出時,內核將子進程置為僵屍狀態,這個進程成為僵屍進程,它只保留最小的一些內核數據結構,以便父進程查詢子進程的退出狀態 --父進程查詢子進程的退出狀態可以用wait/waitpid函數
wait獲取staus后檢測處理
宏定義 描述
WIFEXITED(status) 如果進程子進程正常結束,返回一個非零值
WEXITSTATUS(status) 如果WIFEXITED非零,返回子進程退出碼
WIFSIGNALED(status) 子進程因為捕獲信號而終止,返回非零值
WTERMSIG(status) 如果WIFSIGNALED非零,返回信號代碼
WIFSTOPPED(status) 如果進程被暫停,返回一個非零值
WSTOPSIG(status) 如果WIFSTOPPED非零,返回信號代碼
wait系統調用在Linux函數庫中的原型是:
#include <sys/types.h> #include <sys/wait.h> pid_t wait(int *status)
進程一旦調用了wait,就立即阻塞自己,由wait自動分析是否當前進程的某個子進程已經 退出,如果讓它找到了這樣一個已經變成僵屍的子進程,wait就會收集這個子進程的信息,並把它徹底銷毀后返回;如果沒有找到這樣一個子進程,wait就 會一直阻塞在這里,直到有一個出現為止。
參數status用來保存被收集進程退出時的一些狀態,它是一個指向int類型的指針。但如果我們對這個子進程是如何死掉的毫不在意,只想把這個僵屍進程消滅掉,(事實上絕大多數情況下,我們都會這樣想),我們就可以設定這個參數為NULL,就象下面這樣
pid = wait(NULL);
waitpid系統調用在Linux函數庫中的原型是:
函數功能:用來等待某個特定進程的結束
status如果不為空,會把狀態信息寫到它指向的位置
options允許改變waitpid的行為,最有用的一個選項是WNOHANG,它的作用是防止waitpid把調用者的執行掛起
返回值:成功返回等待子進程的pid,失敗返回-1
#include <sys/types.h> #include <sys/wait.h> pid_t waitpid(pid_t pid,int *status,int options)
- pid>0時,只等待進程ID等於pid的子進程,不管其它已經有多少子進程運行結束退出了,只要指定的子進程還沒有結束,waitpid就會一直等下去。
- pid=-1時,等待任何一個子進程退出,沒有任何限制,此時waitpid和wait的作用一模一樣。
- pid=0時,等待同一個進程組中的任何子進程,如果子進程已經加入了別的進程組,waitpid不會對它做任何理睬。
- pid<-1時,等待一個指定進程組中的任何子進程,這個進程組的ID等於pid的絕對值。
options提供了一些額外的選項來控制waitpid,目前在Linux中只支持WNOHANG和WUNTRACED兩個選項,這是兩個常數,可以用"|"運算符把它們連接起來使用,比如:
ret=waitpid(-1,NULL,WNOHANG | WUNTRACED);
如果我們不想使用它們,也可以把options設為0,如:
ret=waitpid(-1,NULL,0);
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int arg,char *args[])
{
pid_t pid=fork();
if(pid==-1)
{
printf("fork() failed ! error message:%s\n",strerror(errno));
return -1;
}
if(pid>0)
{
int status=0;
printf("父進程\n");
wait(&status);
if(WIFEXITED(status))//WIFEXITED宏的釋義: wait if exit ed
{
printf("子進程返回信息碼:%d\n",WEXITSTATUS(status));
}else if(WIFSIGNALED(status))
{
printf("子進程信號中斷返回信息碼:%d\n",WTERMSIG(status));
}else if(WIFSTOPPED(status))
{
printf("子進程暫停返回信息碼:%d\n",WSTOPSIG(status));
}else
{
printf("其他退出信息!\n");
}
}else if(pid==0)
{
printf("i am child !\n");
abort();
//exit(100);
}
printf("game is over!\n");
return 0;
}
wait()函數成功返回等待子進程的pid,失敗返回-1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int arg, char *args[])
{
pid_t pid = 0;
int i = 0, ret = 0;
for (i = 0; i < 10; i++)
{
pid = fork();
if (pid == -1)
{
printf("fork() failed ! error message:%s\n", strerror(errno));
return -1;
}
if (pid == 0)
{
printf("child haved run!\n");
exit(0);
}
}
while (1)
{
//wait()函數的返回值是子進程的pid
ret = wait(NULL);
printf("子進程pid=%d\n", ret);
if (ret == -1)
{
//父進程wait()函數阻塞過程中,有可能被別的信號中斷,需要做異常處理
if (errno == EINTR)
{
continue;
}
break;
}
}
printf("game is over!\n");
return 0;
}
