waitid:
pid_t wait(int *status);
注:
①status==NULL,表明不管子进程现在是什么状态,我都要等
②wait(NULL) 时,它将暂停执行,直到任何一个子进程终止。在等待期间,父进程会阻塞,并且不会继续执行后面的代码,直到子进程结束或出现错误。
③返回值:如果执行成功则返回子进程识别码(PID), 如果有错误发生则返回-1. 失败原因存于errno 中.
waitpid:
pid_t waitpid(pid_t pid, int *status, int options);
注:
①pid==-1,等待任意一个子进程,与wait等效
pid>0,等待指定进程
②options==0,表示阻塞等待
options==WNOHANG,代表父进程非阻塞等待,在等待子进程期间,可以做其它任务
③返回值:
>0表示等待子进程成功
<0表示等待子进程失败
④waitpid(pid,NULL,0)等价于wait(NULL)
⑤进程退出码:(status>>8) & 0xFF
⑥进程退出信号:status & 0x7F
僵尸进程:至少要保留该进程的PCB信息。task_struct里面保留了任何进程退出时的退出结果信息!!!
故waitid和waitpid的本质就是读取子进程的task_struct结构
示例:
#include
#include
#include
#include
#include
int main()
{
pid_t id=fork();
if(id<0)
{
printf("创建子进程失败\n");
exit(-1);
}
else if(id==0)
{
int cnt=5;
while(cnt)
{
printf("我是子进程:%d\n",cnt--);
sleep(1);
}
exit(11);//11仅仅用来测试
}
else
{
//父进程
int status=0;
//只有在子进程退出(cnt为0)时,waitpid才会返回得到result[此时父进程依旧还活着呢!]
//wait/waitpid可以在目前的情况下,让进程退出具有一定的顺序性!
//将来可以让父进程进行更多的收尾工作
pid_t result =waitpid(id,&status,0);//阻塞等待
if(result > 0)
{
printf("父进程等待成功,退出码:%d, 退出信号:%d\n",(status>>8)&0xFF,status&0x7F);
}
}
}
运行结果:
退出信号 0 表示子进程正常退出,没有收到任何信号导致终止。在这种情况下,退出码可以用来表示子进程的结束状态。
printf("父进程等待成功,退出码:%d, 退出信号:%d\n",(status>>8)&0xFF,status&0x7F);
涉及到位运算,对新手不友好。故创造了WIFEXITED和WEXITSTATUS函数来实现功能:、
if(WIFEXITED(status))
{
//子进程是正常退出的
printf("子进程执行完毕,没有出错,子进程的退出码: %d\n",WEXITSTATUS(status));
}
else
{
printf("子进程异常退出: %d\n",WIFEXITED(status));
}
示例:
#include
#include
#include
#include
#include
int main()
{
pid_t id=fork();
if(id<0)
{
printf("创建子进程失败\n");
exit(-1);
}
else if(id==0)
{
int cnt=5;
while(cnt)
{
printf("我是子进程:%d\n",cnt--);
sleep(1);
}
exit(11);//11仅仅用来测试
}
else
{
//父进程
int status=0;
//只有在子进程退出(cnt为0)时,waitpid才会返回得到result[此时父进程依旧还活着呢!]
//wait/waitpid可以在目前的情况下,让进程退出具有一定的顺序性!
//将来可以让父进程进行更多的收尾工作
pid_t result =waitpid(id,&status,0);//阻塞等待
if(result > 0)
{
// printf("父进程等待成功,退出码:%d, 退出信号:%d\n",(status>>8)&0xFF,status&0x7F);
if(WIFEXITED(status))
{
//子进程是正常退出的
printf("子进程执行完毕,没有出错,子进程的退出码: %d\n",WEXITSTATUS(status));
}
else
{
printf("子进程异常退出: %d\n",WIFEXITED(status));
}
}
}
}