#### wait函数 ####
wait函数只是针对一个子进程情况,查看man手册wait用法:pid_t wait(int *status);
参数是int*类型,返回值是pid_t类型;
wait执行原理:
1,子进程先结束,会发一个信号SIGCHLD
2,父进程调用wait等待子进程结束,再执行父进程下来的代码;如果子进程没有结束,就一直在等,会阻塞。
3,有资源回收函数,信号发给父进程,此时就可以回收(僵尸进程),父进程可以及时回收资源。没有资源回收函数,什么时候回收资源,父进程安排,通信是异步通信的。
4,如果父进程没有子进程,wait返回值错误。
演示代码:
#include
#include
#include
/*
wait对父子进程的影响:使得父进程处于阻塞状态,一直等待资子进程结束,wait结束,再去执行父进程
*/
int main()
{
pid_t pid;
int status = 1;
pid = fork();
if (pid > 0)
{
printf("father process :\n");
wait(&status);//父进程执行到此,会停止,处于wait状态,等待子进程执行结束,然后父进程才会再执行
printf("father process end : \n");
exit(0);//每当一个进程执行结束,最好使用exit将其退出
}
else if (0 == pid)
{
printf("son process : \n");
exit(0);
}
else
{
perror("fork");
exit(0);
}
return 0;
}
执行结果:
表明:程序先进入父进程执行输出father process;然后发现wait函数,去执行子进程,输出son process,子进程结束后,父进程再重新继续执行
演示代码:(如果子进程不结束,父进程wait一直会阻塞)
#include
#include
#include
int main()
{
pid_t pid;
int status = 1;
pid = fork();
if (pid > 0)
{
printf("father process :\n");
wait(&status);
printf("father process end : \n");
exit(0);
}
else if (0 == pid)
while(1) //当父进程执行到wait时,开始执行子进程,如果子进程死循环,则父进程会永远阻塞下去
{
sleep(1);
printf("son process : \n");
}
else
{
perror("fork");
exit(0);
}
return 0;
}
输出结果:
father process :
son process :
son process :
son process :
son process :
^C
最后强制退出;子进程死循环,父进程就一直wait阻塞。
#### wait测试状态 ####
wait函数中测试父进程是否正常退出,父进程是否由外界信号中断,以及子进程返回值的三个状态:
WIFEXITED测试进程是否是正常退出:逻辑值(真或假)
WEXITSTATUS测试你的子进程结束时的返回值(正常终止)
WIFSIGNALED测试你的子进程是否时被外界信号终止(非正常终止)
演示代码:
#include
#include
#include
int main()
{
pid_t pid ,child_pid;
int status = 1;
pid = fork();
if (pid > 0)
{
sleep(1);
printf("father process : \n");
child_pid = wait(&status);
// printf("process end normally = %d \n",WIFEXITED(status));
//如果父进程处于wait状态,WIFEXITED测试是否正常退出,输出为逻辑>值,若果正常退出,则输出1;否则为0
printf("process end & test son process return vealue = %d \n",WEXITSTATUS(status));
//测试子进程结束时的返回值(正常终止)
printf("process end ennormally = %d \n",WIFSIGNALED(status));
//测试父进程是否被外界信号中断,(非正常终止)
printf("father process end;\n");
}
else if (0 == pid)
{
printf("son process : \n");
sleep(1);
return 3;
}
else
{
perror("fork");
exit(0);
}
return 0;
}
son process :
father process :
process end & test son process return vealue = 3
process end ennormally = 0
father process end;
#### waitpid函数 ####
/*
waitpid函数可以让父进程等待指定的pid
用法:
pid_t waitpid(pid_t pid, int *status, int options);
waitpid(-1,int *status,int options); 如果为-1表示等待任意子进程
pid_t pid的取值:
< -1 meaning wait for any child process whose process group ID is
equal to the absolute value of pid.取该pid的绝对值,如果任意子进程的进程组ID等于该绝对值,则该组进程中任一子进程中的进程状态发生变化都会触发waitpid()
的回调。
-1 meaning wait for any child process.监听范围扩大到任意子进程。
0 meaning wait for any child process whose process group ID is
equal to that of the calling process.监听限制为子进程的进程组ID与父进程相等。
> 0 meaning wait for the child whose process ID is equal to the
value of pid.监听限制为指定子进程进程ID值。
*/
演示代码:
#include
#include
#include
int main()
{
pid_t pid,child_pid;
int status = 1;
pid = fork();
if (pid > 0)
{
sleep(1);
printf("father process ; \n");
// child_pid = waitpid(-1,&status,0); //&status值可以为NULL当不为NULL时,用于存储触发状态变化的信息号值和exit(code)的code值
//等待任意子进程pid
// child_pid = waitpid(pid,&status,0);
//等待指定子进程pid
child_pid = waitpid(pid+1,&status,0);
//如果等待一个不存在的子进程pid,阻塞的父进程就不会阻塞,运行返回值-1,继续执行父进程代码
printf("child_pid = %d \n",child_pid);
printf("father process end;\n");
}
else if (0 == pid)
{
printf("son process ; \n");
}
else
{
perror("fork");
exit(0);
}
return 0;
}
输出结果:
son process ;
father process ;
child_pid = -1
father process end;
#### waitpid第三个参数 ####
/*
pid_t waitpid(pid_t pid, int *status, int options);
waitpid第三个参数:
0:返回wait的进程的pid
WNOHANG:如果子进程不存在就立即返回
WUNTRACED
WCONTINUED
*/
演示代码:
#include
#include
#include
#include
#include
int main()
{
pid_t pid,child_pid;
int status = 1;
pid = fork();
if (pid > 0)
{
sleep(1);
printf("father process ;\n");
// child_pid = waitpid(pid,&status,WNOHANG);
//WNOHANG如果子进程不存在就立即返回
child_pid = waitpid(pid,&status,0);
//0返回wait的子进程的pid
printf("son process pid = %d \n",child_pid);
printf("father process end;\n");
}
else if (0 == pid)
{
printf("son process pid in son process = %d \n",getpid());
}
else
{
perror("fork");
exit(0);
}
return 0;
}