学习fork与vfrok的一些感悟
fork与vfork的区别:
一、fork创建的子进程拷贝父进程的数据段,父子进程是相互独立的;而vfork创建的子进程和父进程共享数据段
二、fork创建的进程,父子进程执行顺序随机;而vfork创建的子进程优先运行,后运行父进程
以上两者初学者都比较清楚的知识点,但根据此知识点看下面的两个程序的运行结果:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(void)
{
}
此程序会显示的count是4和4,没问题
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(void)
{
}
此程序会显示4和1,并且会提示有Bus error
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main(void)
{
}
此时程序count的结果是4和5,且不报任何错误
由此大家会开始纳闷了,我考虑了很久同时查找相关的资料,得到一些感想:
首先,对于第一个程序,fork创建的父子程序数据段独立,在任一进程执行完后,会执行
return 0语句,这样自己进程里的变量会被系统收回,而另一进程由于有自己独立的数据段故不会受此影响,结果正确
然后,根据上述理论分析第二个程序,vfork创建子进程,父子进程是共享数据段的,且子进程先运行,当子进程运行到return 0后,就将公共数据区里的count变量收回。再运行父进程,此时父进程里没有count变量,有些及其可能会是个随机数,得到的打印的count值会很大,而大部分的机器在没有初始化变量的情况下会默认count值为0,故此时可以打印出1。然而
最后经过上述理解,我觉得问题主要出在return 0上,
exit()(或return 0)会调用终止处理程序和用户空间的标准I/O清理程序(如fclose),这样会清楚本进程内或者函数内的数据, 而 _exit和_Exit不调用而直接由内核接管进行清理,故不会立即进程变量的回收和清理,因为内核的清理一般是整个程序结束时才会进行空间回收。所以大家以后在使用vfork时返回函数一定使用_exit(),而尽量不要使用exit()或者return。
自己学习过程中的一点感悟,希望对大家有用!