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

vfork函数

  • vfork函数也可以创建进程,与fork有什么区别
  • 等待子进程退出

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

区别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);
      }
  }
}

效果如下:
Linux进程—vfork函数的使用,父进程等待子进程退出,vfork和fork区别_第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);
       }
      }

  }
}

Linux进程—vfork函数的使用,父进程等待子进程退出,vfork和fork区别_第2张图片
可以看出当子进程运行到一定次数退出时,父进程就会运行

等待子进程退出

进程退出:

正常退出:
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);
       }
      }

  }
}

效果如下:
Linux进程—vfork函数的使用,父进程等待子进程退出,vfork和fork区别_第3张图片
返回状态为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收留,同时也没有了僵尸进程

你可能感兴趣的:(Linux进程,linux,运维,服务器)