Linux进程—vfork函数的使用,父进程等待子进程退出,vfork和fork区别

vfork函数也可以创建进程,与fork有什么区别

区别1:
vfork直接使用父进程存储空间,不拷贝
区别2:
vfork保证子进程先运行,当子进程调用exit退出后,父进程才执行
首先我们用fork创建一个进程

#include<stdio.h>
#include <unistd.h>
#include <sys/types.h>
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<stdio.h>
#include <unistd.h>
#include <sys/types.h>
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<stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
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<stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
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<stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/wait.h>
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<stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdlib.h>
#include <sys/wait.h>
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收留,同时也没有了僵尸进程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

pg_hj

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值