linux进程创建提供了几个常用的函数,像fork,vfork,clone等,在用的时候总是感觉难以运用自如,特别是vfork的使用,在写下自己的一点心得体会!
与fork相比,vfork的工作机制更清晰一些。vfork用于创建一个新进程,而该进程的目的是exec一个新程序,与fork不同,vfork并不将父进程的地址空间完全复制到子进程中,因为子进程会立即调用exec(或exit),于是也就不会存放该地址空间。在子进程调用exec或exit之前,它在父进程的空间中运行,这种优化工作方式在某些unix的页式虚拟存储器实现中提高了效率。比写时复制的部分复制更快一些。
对于fork而言,它完全复制父进程的数据空间、堆和栈,父子进程共享正文段。由于fork之后经常跟随exec,现在流行一种写是复制(Copy-On-Write)技术,这些区域由父子进程共享,而且内核将他们的访问权限改变为只读,如果父子进程中的任意一个试图修改这些区域,则内核只为修改区域的那块内存制作一个副本,通常是虚拟存储系统中的“一页”。
vfork和fork的另一个区别是:vfork保证子进程先运行,在他调用exec或exit之后父进程才可能被调度。
所以下面的代码 父子进程的输出结果是不一样的,子进程修改属于自己的区域或是采用写时复制复制出要改变的数据,所以子进程输出的是修改后的,父进程不变!
#include
#include
#include
int global = 100;
int main( int argc, char *argv[])
{
int var=1;
pid_t pid;
if((pid=fork())<0)
{
printf("Fork error!\n");
}
else if( pid == 0)
{
printf("In child\n");
global++;
var++;
_exit(0);
}
printf("Pid is %d\n",getpid());
printf("the values of global and var are %d,%d\n",global,var);
}
倘若把fork改为vfork,则子进程的输出结果是自加之后的值,父进程的输出结果是未定义的,还有可能会报出段错误!因为父进程要等待子进程调用exec或是exit之后才能调度。
修改如下:
#include
#include
#include
int global = 100;
int main( int argc, char *argv[])
{
int var=1;
pid_t pid;
if((pid=vfork())<0)
{
printf("VFork error!\n");
}
else if( pid == 0)
{
printf("In child\n");
global++;
var++;
_exit(0);
}
else
{
sleep(2);
}
printf("Pid is %d\n",getpid());
printf("the values of global and var are %d,%d\n",global,var);
exit(0);
}
执行完毕,子进程对父进程的数据进行了修改!
阅读(1496) | 评论(0) | 转发(0) |