vfork 和 exit

vfork

       对于创建一个子进程,我们最常用的就是 fork,但其实 vfork 也是用来创建子进程的,但 vfork 和 fork 的差距却是非常大的。

  • fork 的父子进程各自拥有独立的程序地址空间,在运行时互不干扰;而 vfork 父子进程共用一个程序地址空间,一个进程修改了内存中的内容,下一次另一个进程就会读到被修改的内容
  • vfork 保证子进程先执行,只有当子进程调用 exec 族函数 或 退出时,父进程才可以被执行

       用代码来验证一下:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int a = 10;

int main()
{
    printf("before vfork a = %d\n", a);
    pid_t pid = vfork();
    if(pid == -1) {
        perror("vfork failed!\n");
        return 1;
    } else if(pid == 0) {
        a += 5;
        printf("I am child: %d, a = %d\n", getpid(), a);
        _exit(0);
    } else {
        printf("I am father: %d, a = %d\n", getpid(), a);
    }

    return 0;
}

       运行后可以看到,当子进程修改了变量 a 后,父进程读取到的是修改后的值

       在 vfork 中还有一个要注意的点是:通常情况下,子进程不允许调用 exit(),而只能调用 _exit(),这里的原因就要从这两个函数的区别来看了。

_exit 和 exit

       _exit 是操作系统为我们提供的系统调用,它的原型如下,status 参数定义了进程的终止状态

#include <unistd.h>
void _exit(int status);

       exit 是 glibc 库中为我们封装好的库函数,它实际上也是调用了 _exit,但在调用 _exit 之前它还做了一些其他的事情

  1. 执行用户通过 atexit 或 on_exit 定义的清理函数
  2. 关闭所有打开的流,冲刷缓冲区
  3. 调用 _exit

       通过一张图来理解一下 _exit 与 exit 之间的关系:

       明白了 _exit 和 exit 的区别后我们就能明白为什么 vfork 通常情况下是不允许调用 exit 的,因为 vfork 的机制是子进程执行完毕后才会执行父进程,并且父子进程共用同一块程序地址空间,如果子进程在退出时调用了 exit,那么它就会关闭流并且冲刷缓冲区,导致后续父进程的操作无法正常执行。

       还有一种更为常见的退出方式就是 return,其实 return 调用的就是 exit 函数,执行 return n 实际上就是 执行 exit(n)。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值