区别1:
vfork直接使用父进程存储空间,不拷贝
区别2:
vfork保证子进程先运行,当子进程调用exit退出后,父进程才执行
首先我们用fork创建一个进程
#include
#include
#include
int main()
{
pid_t pid1;
pid1 = fork();
if(pid1>0){
while(1){
printf("this father fork %d\n",getpid());
sleep(1);
}
}else if(pid1==0){
while(1){
printf("this child fork %d\n",getpid());
sleep(1);
}
}
}
效果如下:
可以看出父子进程同时运行
接下来用vfork创建一个进程
#include
#include
#include
int main()
{
pid_t pid1;
pid1 = vfork();
if(pid1>0){
while(1){
printf("this father fork %d\n",getpid());
sleep(1);
}
}else if(pid1==0){
while(1){
printf("this child fork %d\n",getpid());
sleep(1);
}
}
}
效果如下:
在子进程未退出的情况下,会一直运行子进程
现在我们将子进程运行一段时间后退出,看是否会运行父进程
#include
#include
#include
#include
int main()
{
int cnt=0;
pid_t pid1;
pid1 = vfork();
if(pid1>0){
while(1){
printf("this father fork %d\n",getpid());
sleep(1);
}
}else if(pid1==0){
while(1){
cnt++;
printf("this child fork %d\n",getpid());
sleep(1);
if(cnt==5){
exit(0);
}
}
}
}
进程退出:
正常退出:
1.main函数调用return
2.进程调用exit()
3.进程调用_exit()或者_Exit()
4.进程最后一个线程返回
5.最后一个线程调用phread_exit
异常退出
1.调用abort
2.当进程收到一些信号时
3. 最后一个线程对取消,请求做出响应
不管进程如何终止,最后都会执行内核中的同一段代码。这段代码为相应进程关闭所有打开描述符,释放它的存储器等。
对上述任意一种情形,我们都希望终止进程能够通知其父进程它是如何终止的。
为什么等待子进程退出:
创建子进程目的是为了处理我们所布置的任务
若子进程完成了我们所布置的任务,则为正常退出
若子进程没有完成了我们所布置的任务,则为异常退出
我们调用exit退出一个子进程时,exit会返回一个状态
子进程状态不被父状态收集,就会变成僵尸进程
在上段代码的基础上,我们可以查看一下进程
可以看出3211的子进程已经变成了僵尸进程
我们只需要wait这个函数,就可以让父进程收集子进程状态(fork也可用)
#include
#include
#include
#include
int main()
{
int cnt=0;
int a=10;//子进程退出状态
pid_t pid1;
pid1 = vfork();
if(pid1>0){
wait(&10);//调用wait传参
while(1){
printf("this father fork %d\n",getpid());
sleep(1);
}
}else if(pid1==0){
while(1){
cnt++;
printf("this child fork %d\n",getpid());
sleep(1);
if(cnt==5){
exit(0);
}
}
}
}
僵尸进程已经消失了!
那么如何检测子进程的退出状态呢
可以使用wait()
函数的传参,我们可以用WEXITSTATUS
宏来解析,具体使用方法如下
#include
#include
#include
#include
#include
int main()
{
int a=10;
int cnt=0;
pid_t pid1;
pid1 = vfork();
if(pid1>0){
wait(&a);//来接收子进程的返回状态
printf("the status is %d\n",WEXITSTATUS(a));//解析返回状态并打印
while(1){
printf("this father fork %d\n",getpid());
sleep(1);
}
}else if(pid1==0){
while(1){
cnt++;
printf("this child fork %d\n",getpid());
sleep(1);
if(cnt==5){
exit(0);
}
}
}
}
效果如下:
返回状态为0
孤儿进程:
父进程如果不等待子进程退出,在子进程退出前就结束了自己的生命,这时子进程叫做孤儿进程
Linux为了防止太多孤儿进程,就会有特定进程收留孤儿进程,成为孤儿进程的父进程
#include
#include
#include
#include
#include
int main()
{
int a=10;
int cnt=0;
pid_t pid1;
pid1 = fork();
if(pid1>0){
printf("this father fork %d\n",getpid());
}else if(pid1==0){
while(1){
cnt++;
printf("this child fork %d,father pid %d\n",getpid(),getppid());
if(cnt==5){
exit(0);
}
sleep(1);
}
}
}
我们通过上面代码创建一个孤儿,看会被哪个进程收留
经过多次测试发现,会被1127这个进程收留。被user收留,同时也没有了僵尸进程