linux中建立新的进程-fork、vfork、clone解析

来源:互联网 发布:软件测试过程管理 编辑:程序博客网 时间:2024/05/22 12:40

1.pid_t fork(void)

asmlinkage int sys_fork(unsigned long r0, unsigned long r1, unsigned long r2,unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6,struct pt_regs regs){#ifdef CONFIG_MMUreturn do_fork(SIGCHLD, regs.spu, &regs, 0, NULL, NULL);#elsereturn -EINVAL;#endif /* CONFIG_MMU */}


2.pid_t vfork(void)

/* * This is trivial, and on the face of it looks like it * could equally well be done in user mode. * * Not so, for quite unobvious reasons - register pressure. * In user mode vfork() cannot have a stack frame, and if * done by calling the "clone()" system call directly, you * do not have enough call-clobbered registers to hold all * the information you need. */asmlinkage int sys_vfork(unsigned long r0, unsigned long r1, unsigned long r2,unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6,struct pt_regs regs){return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.spu, &regs, 0,NULL, NULL);}

3.int clone(int (*fn)(void *), void *child_stack, int flags, void *arg)

asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, unsigned long parent_tidptr, unsigned long child_tidptr, unsigned long r4, unsigned long r5, unsigned long r6, struct pt_regs regs){if (!newsp)newsp = regs.spu;return do_fork(clone_flags, newsp, &regs, 0,       (int __user *)parent_tidptr, (int __user *)child_tidptr);}


fork与vfork对比分析

fork 、 vfork 、clone函数最终都是调用do_fork,只是传递的参数不同,重点在于clone_flags参数的不同。fork传递的只有SIGCHLD, vfork传递的是CLONE_VFORK | CLONE_VM | SIGLCHLD。而clone函数可操作性比较大,可以自主设置clone_flags。

1.vfork保证子进程先运行,在它调用exec或exit之后父进程才可能被调度运行。如果在调用这两个函数之前子进程依赖于父进程的进一步动作,则会导致死锁。

2.fork要拷贝父进程的进程环境;而vfork则不需要完全拷贝父进程的进程环境,在子进程没有调用exec和exit之前,子进程与父进程共享进程环境(观察源码发现主要是CLONE_VM,共享用户虚拟地址空间),此时父进程阻塞等待。

为什么会有vfork呢?

因为以前的fork当它创建一个子进程时,将会创建一个新的地址空间,并且拷贝父进程的资源,然后将会有两种行为:

1.执行从父进程那里拷贝过来的代码段

2.调用一个exec执行一个新的代码段

当进程调用exec函数时,一个新程序替换了当前进程的正文,数据,堆和栈段。这样,前面的拷贝工作就是白费力气了,这种情况下,聪明的人就想出了vfork。vfork并不复制父进程的进程环境,子进程在父进程的地址空间中运行,所以子进程不能进行写操作,并且在儿子“霸占”着老子的房子时候,要委屈老子一下了,让他在外面歇着(阻塞),一旦儿子执行了exec或者exit后,相当于儿子买了自己的房子了,这时候就相当于分家了。

因此,如果创建子进程是为了调用exec执行一个新的程序的时候,就应该使用vfork





原创粉丝点击