与fork()函数有所不同,fork()函数在创建一个子进程后,子进程的地址空间完全和父进程分开。父子进程是两个独立的进程,接受系统调度和分配的机会均等。因此父进程和子进程更像是一对兄弟。
而vfork()函数不同,vfork()函数产生的子进程和父进程完全共享地址空间,包括代码段,数据段和堆栈段。子进程对这些共享资源的修改会影响父进程,vfork()产生的更像是一个线程。再者,vfork()函数产生的进程一定比父进程先运行,子进程运行完了以后,父进程再运行。
看段代码:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int goal=1;
int main()
{
pid_t pid;
int a=2;
int *p;
p=(int *)malloc(sizeof(int));
*p=6;
pid=vfork();
if(pid<0){exit(1);}
else if(pid==0)
{
goal=goal+3;
a=a+7;
(*p)=(*p)+8;
printf("%d,%d,%d\n",goal,a,*p);
exit(1);
}
sleep(2);
printf("%d,%d,%d\n",goal,a,*p);
运行结果:
4,9,14
4,9,14
使用vfork()函数时应当注意不要在子函数内调用它。
看段代码:
#include<stdio.h>
#include<unistd.h>
int f1()
{vfork();
return 0;}
int f2(int a,int b)
{
return a+b;
}
int main()
{
int c;
f1();
c=f2(1,2);
printf("%d\n",c);
return 0;
}
运行结果:
3
段错误(吐核)
错误的原因是:两个进程共享堆栈段,两个进程都要从f1函数中返回。由于子进程先于父进程运行,所以子进程从f1返回,并且调用f2函数。其栈帧覆盖了原来的f1函数的栈帧,当子进程结束时父进程运行时,就出错了。。。由此可知,使用vfork()函数之后,子进程对父进程的影响是巨大的,其同步措施势在必行,同时也可以体会到,线程的同步是多么的重要!!!
(文中内容基本出自《Linux c程序设计大全》吴岳)