0.常用的宏
1.WIFEXITED(status):为非0 --->判断进程是否正常结束
WEXITSTATUS(status):
如果WIFEXITED(status)为非0,使用WEXITSTATUS(status)
--->[获取进程退出状态(exit/return的参数)]
2.WIFSIGNALED(status):为非0--->判断进程是否被信号终止
WTERMSIG(status):
如果WIFSIGNALED(status)为非0,使用WTERMSIG(status)
--->[取得使进程终止的那个信号的编号]
3.WIFSTOPPED(status) //为非0--->如果信号导致子进程停止执行。
WSTOPSIG(status)
--->返回导致子进程停止执行的信号数量
代码:
if(WIFEXITED(status))
printf("exit value:%d\n",WEXITSTATUS(status));
if(WIFSIGNALED(status))
printf("exit by signal:%d\n",WTERMSIG(status));
if(WIFSTOPPED(status))
printf("进程停止:%d\n",WSTOPSIG(status));
1.wait-阻塞函数
pid_t wait(int* status);
注意:该函数调用一次只能回收一个子进程
返回值:
-1:回收失败,已经没有子进程
>0:回收是子进程对应的pid
传出参数:status
判断子进程是如何死的
正常退出
被某个信号杀死了
案例1
程序功能:
使用kill -9 子进程pid杀死子进程后,在父进程中调用wait函数去回收子进程。
int main(){
pid_t pid=fork();
if(pid<0){
perror("fork fail");
exit(1);
}
if(pid==0){
while(1){ //子进程一直循环printf------>调用[kill -9 子进程pid]杀死该进程
sleep(1);
printf("child=%d,parent=%d\n",getpid(),getppid());
}
}
if(pid>0){//父进程:调用wait函数,释放死掉的子进程
printf("parent=%d\n",getpid());
int status;
//子进程没死亡,一直阻塞在wait函数处;
//当子进程死亡后,wait函数回收子进程资源&&退出
pid_t w_pid=wait(&status);
if(WIFEXITED(status))
printf("exit value:%d\n",WEXITSTATUS(status));
if(WIFSIGNALED(status))
printf("exit by signal:%d\n",WTERMSIG(status));
printf("died child pid=%d\n",w_pid);
}
return 0;
}
2.waitpid
pid_t waitpid(pid_t pid, int *status, int options);
参数:
1.pid
pid>0:指定pid的子进程
pid==-1:等待任意一个子进程(等价于wait)
—循环回收:while((w_pid=waitpid(-1,&status,WNOANG)!=-1)
pid==0:当前进程组所有的子进程
pid<0:
2.status:子进程的退出状态,用法同wait函数(使用宏)
3.options:
设为0,函数为阻塞
设为WNOHANG,函数为非阻塞
返回值:
-1:回收失败,已经没有子进程
>0:返回清理掉的子进程ID
如果为非阻塞:
=0:子进程处于运行状态
案例2
父进程产生两个子进程
子进程1,调用ls -l
子进程2,产生段错误
父进程,负责使用wait或waitpid回收退出的子进程
int main(){
int i;
pid_t pid;
for(i=0;i<2;i++){
pid=fork();
if(pid==0)
break;
}
if(i==0){
execlp("ls","ls","-l",NULL);
perror("execl");
exit(1);
}
if(i==1){
char* p="Student";
p[5]='K'; //会发生段错误
}
if(i==2){ //父进程,回收死亡的子进程
int status;
pid_t w_pid;
/*case1:wait*/
while((w_pid=wait(&status))!=-1){
/*
case2:waitpid
while( (w_pid=waitpid(-1,&status,WNOHANG))!=-1 ){ //循环回收
if(w_pid==0) //返回值为0,返回的是正在运行的进程的pid(而不是死亡的进程的pid)
continue;
*/
printf("------wait child's pid = %d\n",w_pid);
if(WIFEXITED(status))
printf("return value=%d\n",WEXITSTATUS(status));
if(WIFSIGNALED(status))
printf("signal value=%d\n",WTERMSIG(status));
}
}
return 0;
}
[gjw@localhost homework]$ ./test
总用量 16
-rwxrwxr-x. 1 gjw gjw 8696 10月 15 09:59 test
-rw-rw-r--. 1 gjw gjw 812 10月 15 09:59 test.c
------wait child's pid = 8730
return value=0
------wait child's pid = 8731
signal value=11 //信号11表示的是[段错误]