对于我正在学习的课程,我一直在Linux中使用clone()
系统调用进行一些工作。我很好奇它是如何工作的,并开始做一些挖掘。令我感到困惑的是,它似乎依赖于fork()
功能的一些相同基础(它们使用不同的参数调用相同的do_fork()
函数)。一方面,这对我来说是有道理的,因为线程实际上只是一个轻量级的过程,但我总是认为创建线程的方式和创建过程的方式之间存在一些显着差异。我做了一些挖掘do_fork()
和随后copy_process()
(do_fork()
调用)的实现,但我无法说服自己,我明白发生了什么。
所以,对于那里的大师,我错过了什么或者这实际上是如何运作的?是否有标志基本上告诉操作系统要复制多少以及开始执行新任务的指令(我认为答案必须是是,但我只是不确定他们如何翻译)?
以下是我正在查看的代码,也许您可以解释传递的参数如何控制是否创建了轻量级或重量级的进程。
asmlinkage int sys_fork(struct pt_regs *regs){
#ifdef CONFIG_MMU
return do_fork(SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL);
#else
/* can not support in nommu mode */
return(-EINVAL);
#endif
}
asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
int __user *parent_tidptr, int tls_val,
int __user *child_tidptr, struct pt_regs *regs)
{
if (!newsp)
newsp = regs->ARM_sp;
return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr);
}
谢谢!
答案 0 :(得分:4)
实际上,在概念层面,Linux内核对进程或线程一无所知,只知道“任务”。
Linux任务可以是进程,线程或介于两者之间的东西。 (顺便说一句,这意味着vfork()创建的奇怪孩子非常适合Linux“任务”范例。)
现在,任务可以共享多个内容,请参阅clone(2)联机帮助页中的所有CLONE_ *标志。 (并非所有这些标志都可以描述为共享,有些则指定更复杂的行为)。
或者新任务可以选择拥有自己的相应资源副本。从2.6.16开始,他们可以在启动后执行此操作,请参阅unshare(2)。
例如,vfork()和fork()调用之间的唯一区别是vfork()设置了CLONE_VM和CLONE_VFORK。 CLONE_VM使它共享其父内存(与线程共享内存的方式相同),而CLONE_VFORK生成父块,直到子块释放其内存映射(通过调用execve()或_exit())。
请注意,Linux并不是以这种方式概括流程和线程的唯一操作系统。计划9有rfork()。
答案 1 :(得分:3)
the clone
manpage中没有任何内容表明它是“轻量级的”。
关键区别在于fork
创建了一个新的地址空间,而clone
可选地共享父和子之间的地址空间,以及文件句柄等。
此共享地址空间可以在以后启用轻量级IPC,但该过程本身并不苗条。
答案 2 :(得分:1)
我理解所有三个clone,fork和vfork之间的区别在于flags,因为最后所有三个调用内核中的do_fork()
叉() - > C_lib - > sys_fork() - > do_fork()
的vfork() - > C_lib - > sys_vfork() - > do_fork()
克隆() - > C_lib - > sys_clone() - > do_fork()
fork和vfork之间的区别在于vfork保证child将首先执行,而parent将阻塞,直到child调用exit或exec。 vfork传递额外的标志是CLONE_VM,这个标志要求内核不要复制页面表,原因很简单,孩子要么退出或执行,如果子退出什么都行,如果子进行exec页表肯定会改变了。我希望fork和vfork标志现在在内核级别清楚。 现在让我们看一下克隆标志
clone的主要用途是实现线程,其中内存空间与堆栈共享。除了与fork和vfork相同的参数外,clone还将函数指针作为参数,一旦创建子进程就会调用它。