Linux vfork简介
来源:互联网 发布:知呱呱 靠不靠谱 编辑:程序博客网 时间:2024/05/23 05:07
(一)vfork和fork的区别
fork 是创建一个子进程,并把父进程的内存数据copy到子进程中。
vfork 是创建一个子进程,并和父进程的内存数据share一起用。
为什么有vfork,因为大多数fork的子进程就直接exec
或者exit
那么再copy一份内存数据就显得没必要了。
在子进程调用exec和exit之前,都在父进程的空间中运行。
所以,BSD搞出了个父子进程共享的 vfork,这样成本比较低。因此,vfork本就是为了exec而生。
另外vfork跟fork还有一个区别就是:vfork保证子进程先运行,在它调用exec或者exit之后父进程才被调度,当子进程调用这两个函数中的任意一个时,父进程会恢复运行。
(二)vfork与core dump
详情见vfork挂掉的一个问题
代码见:https://github.com/NearXdu/APUE
在子进程中使用return就会挂掉:
//bad_vfork.c#include <stdio.h>#include <stdlib.h>#include <unistd.h>int glob = 6;intmain(void){ int var; pid_t pid; var = 88; printf("before vfork\n"); if ((pid = vfork()) < 0) { printf("vfork error"); exit(-1); } else if (pid == 0) { /* 子进程 */ glob++; var++; return 0; } printf("pid=%d, glob=%d, var=%d\n", getpid(), glob, var); return 0;}
从上面我们知道,结束子进程的调用是exit()而不是return,如果你在vfork中return了,那么,这就意味main()函数return了,
注意因为函数栈父子进程共享,所以整个程序的栈就跪了。
如果你在子进程中return,那么基本是下面的过程:
1)子进程的main() 函数 return了,于是程序的函数栈发生了变化。
2)而main()函数return后,通常会调用 exit()或相似的函数(如:_exit(),exitgroup())
3)这时,父进程收到子进程exit(),开始从vfork返回,但是尼玛,老子的栈都被你子进程给return干废掉了,你让我怎么执行?(注:栈会返回一个诡异一个栈地址,对于某些内核版本的实现,直接报“栈错误”就给跪了,然而,对于某些内核版本的实现,于是有可能会再次调用main(),于是进入了一个无限循环的结果,直到vfork 调用返回 error
好了,现在再回到 return 和 exit,return会释放局部变量,并弹栈,回到上级函数执行。
exit直接退掉。如果你用c++ 你就知道,return会调用局部对象的析构函数,exit不会。(注:exit不是系统调用,是glibc对系统调用_exit()
或_exitgroup()
的封装)
可见,子进程调用exit() 没有修改函数栈,所以,父进程得以顺利执行。
但是!注意!如果你调用 exit() 函数,还是会有问题的,正确的方法应该是调用 _exit()
函数,因为 exit()
函数 会 flush 并 close 所有的 标准 I/O
这样会导致父进程受到影响。
正确的代码:
#include <stdio.h>#include <stdlib.h>#include <unistd.h>int glob = 6; intmain(void){ int var; pid_t pid; var = 88; printf("before vfork\n"); if ((pid = vfork()) < 0) { printf("vfork error"); exit(-1); } else if (pid == 0) { /* 子进程 */ glob++; var++; _exit(0); } printf("pid=%d, glob=%d, var=%d\n", getpid(), glob, var); return 0;}
也不需要在父进程中sleep,因为vfork保证了直到执行exec或者exit,父进程都处于休眠状态。
(三)fork的优化
很明显,fork太重,而vfork又太危险,所以,就有人开始优化fork这个系统调用。优化的技术用到了著名的写时拷贝(COW)。
也就是说,对于fork后并不是马上拷贝内存,而是只有你在需要改变的时候,才会从父进程中拷贝到子进程中,这样fork后立马执行exec的成本就非常小了。
(四)参考
- APUE
- http://coolshell.cn/articles/12103.html
- Linux vfork简介
- Linux进程创建函数vfork简介
- LINUX vfork
- Linux下vfork实例
- linux fork 和 vfork
- Linux之vfork
- linux创建线程之vfork
- linux下vfork的学习
- linux函数fork,vfork,clone
- linux 的fork 和 vfork
- vfork
- vfork
- vfork()
- vfork
- linux进程之fork vs vfork
- linux进程之fork vs vfork
- linux进程之fork vs vfork
- Linux下的fork 与 vfork
- 练习1-13 编写一个程序,打印输入中单词长度的直方图(垂直)
- 2017春招笔试题
- Python不使用int()函数把字符串转换为数字
- 数据结构之图
- 前端开发环境搭建
- Linux vfork简介
- 2017年2月历史文章汇总
- Gradle sync failed: SSL peer shut down incorrectly
- Hibernate初识(上)
- Kotlin编程之可见性修饰词(private,protected,internal,public)
- 传递闭包——洛谷P2881 [USACO07MAR]排名的牛Ranking the Cows
- 记下简单的笔记和最近的问题
- 2017年3月历史文章汇总
- 记录大牛的博客