fork 与vfork 的异同

vfork 与fork异同总结
前言
        调⽤fork或vfork函数是Linux创建⼀个新进程的⽅法.

fork
        由fork创建的新进程被称为⼦进程(child process)。该函数被调⽤⼀次,但返回两次。两次返回的区别是⼦进程的返回值是0,⽽⽗进程的返回 值则是新⼦进程的进程ID。

        fork之后经常跟随着exec。作为替代,使⽤了在写时复制(Copy-On-Write,COW)的技术。这些区域由⽗、⼦进程共享,⽽且内核将它们的存取许可权改变为只读的。如果有进程试图修改这些区域,则内核为有关部分,典型的是虚存系统中的“⻚”,做⼀个拷⻉。
 

#include <unistd.h>
 
#include <stdio.h>
 
#include <stdlib.h>
 
int         globvar = 6;              /* external variable in initialized data */
 
char       buf[] = "a write to stdout\n";
 
 
 
int
 
main(void)
 
{
 
       int         var;        /* automatic variable on the stack */
 
       pid_t     pid;
 
 
 
       var = 88;
 
       if (write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf)-1) //write函数是不带缓存的。
 
              exit(-1);
 
        //因为在fork之前调⽤write,所以其数据写到标准输出⼀次。但是,标准I/O库是带缓存的。
 
       //如果标准输出连到终端设备,则它是⾏缓存的,否则它是全缓存的。
 
       printf("before fork\n");   /* we don't flush stdout */
 
 
 
       if ((pid = fork()) < 0) {
 
              exit(-1);
 
       } else if (pid == 0) {         /* child */
 
              globvar++;                      /* modify variables */
 
              var++;
 
       } else {
 
              sleep(2);                           /* parent */
 
       }
 
 
 
       printf("pid = %ld, glob = %d, var = %d\n", (long)getpid(), globvar, var);
 
       exit(0);
 
}


 
vfork
        vfork与fork⼀样都创建⼀个⼦进程, 但是它并不将⽗进程的地址空间完全复制到⼦进程中,因为⼦进程会⽴即调⽤exec(或exit), 也就不会存访该地址空间。

        vfork和fork之间的另⼀个区别是:vfork保证⼦进程先运⾏,在它调⽤exec或exit之后⽗进程才可能被调度运⾏。(如果在调⽤这两个函数之前⼦进程依赖于⽗进程的进⼀步动作,则会导致死锁。)

        调用vfork后,如果子进程修改数据、函数调用、或者没有调用exec或exit之后就返回可能会出现未知的错误。

 

测试例子

#include <stdio.h>
 
#include <stdlib.h>
 
#include <sys/types.h>
 
#include <unistd.h>
 
 
 
int main(void)
 
{
 
    int count = 1;
 
    int child;
 
 
    printf("Before create son, the father's count is:%d\n", count);
 
    if((child = vfork())< 0)
 
    {
 
        perror("fork error : ");
 
    }
 
    else if(child == 0)    
 
    {
 
        printf("This is son, his count is: %d (%p). and his pid is: %d\n", ++count, &count, getpid());
 
        exit(0);  //如果不是exit或exec返回,将会发生未知错误
 
    }
    else
 
    {
        printf(" This is father, his count is: %d (%p), his pid is: %d\n", ++count, &count, getpid());
 
        sleep(1);
 
    }
    return EXIT_SUCCESS;
 
}


总结
       fork函数生成的子进程会写时复制的技术对父进程的数据进行复制。父子进程调度根据操作系统的调度来确定。

       vfork函数生成的子进程与父进程共享数据。并优先执行。通过 vfork() 创建的子进程会执行完后,才到父进程执行。

 

进程页表的定义
        The page table is where the operating system stores its mappings of virtual addresses to physical addresses, with each mapping also known as a page table entry。参考https://en.wikipedia.org/wiki/Page_table。

参考资料
[1].https://stackoverflow.com/questions/20030776/how-can-i-see-a-page-table-maintained-by-each-process-in-virtual-memory-linux

[2].http://man7.org/linux/man-pages/man2/vfork.2.html

[3].http://man7.org/linux/man-pages/man2/fork.2.html

[4].https://www.amazon.com/Advanced-Programming-UNIX-Environment-3rd/dp/0321637739


————————————————
版权声明:本文为CSDN博主「zhang_dawei666」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/xiangguiwang/article/details/81475345

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值