Linux clone()系统调用最终是否依赖于fork功能?

Linux clone()系统调用最终是否依赖于fork功能?,linux,clone,fork,Linux,Clone,Fork,对于我正在学习的一个类,我一直在直接使用Linux中的clone()系统调用进行一些工作。我对它的实际工作原理感到好奇,于是开始做一些挖掘工作。让我困惑的是,它似乎依赖于一些与fork()功能相同的基础(它们调用相同的do\u fork()函数,尽管参数不同)。一方面,这对我来说是有意义的,因为线程实际上只是一个轻量级的进程,但我总是觉得线程的创建方式和进程的创建方式之间存在一些显著的差异。我对do\u fork()的实现做了一些深入的研究,随后又对copy\u process()(其中do\u

对于我正在学习的一个类,我一直在直接使用Linux中的
clone()
系统调用进行一些工作。我对它的实际工作原理感到好奇,于是开始做一些挖掘工作。让我困惑的是,它似乎依赖于一些与
fork()
功能相同的基础(它们调用相同的
do\u fork()
函数,尽管参数不同)。一方面,这对我来说是有意义的,因为线程实际上只是一个轻量级的进程,但我总是觉得线程的创建方式和进程的创建方式之间存在一些显著的差异。我对
do\u fork()
的实现做了一些深入的研究,随后又对
copy\u process()
(其中
do\u 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);
}
谢谢

中没有任何内容表明它是“轻量级”的

关键的区别在于
fork
创建一个新的地址空间,而
clone
可以选择在父级和子级之间共享地址空间以及文件句柄等


这个共享的地址空间在以后启用了轻量级IPC,但进程本身并不是更瘦。

实际上,在概念层面上,Linux内核对进程或线程一无所知,它只知道“任务”

Linux任务可以是进程、线程或介于两者之间的任何东西。(顺便说一句,这意味着vfork()创建的奇怪子对象完全适合Linux“任务”范式)

现在,任务可以共享一些内容,请参见克隆(2)手册页中的所有克隆标志。(并非所有这些标志都可以描述为共享,有些标志指定了更复杂的行为)

或者,新任务可以选择拥有各自资源的副本。从2.6.16开始,它们可以在启动后执行此操作,请参见取消共享(2)

例如,vfork()调用和fork()调用之间的唯一区别是vfork()设置了CLONE\u VM和CLONE\u vfork。CLONE_VM使其共享其父级内存(与线程共享内存的方式相同),而CLONE_vWork使父级块一直保持到子级释放其内存映射为止(通过调用execve()或_exit())


请注意,Linux并不是唯一一个以这种方式概括进程和线程的操作系统。计划9有rfork()。

我知道所有三个克隆、fork和vfork之间的区别在于标志,因为最后所有三个调用内核中的do_fork()

fork()-->C_lib-->sys_fork()-->do_fork()

vWork()-->C_lib-->sys_vWork()-->do_fork()

clone()-->C_lib-->sys_clone()-->do_fork()

fork和vfork之间的区别在于vfork保证子级将首先执行,父级将阻塞,直到子级调用exit或exec。vWork传递的额外标志是CLONE_VM,该标志要求内核不要复制页表,原因很简单,子项将执行exit或exec,如果子项退出,则什么也不做,如果子项执行exec,则页表肯定会更改。我希望fork和vfork标志现在在内核级别是清晰的。 现在让我们看看克隆标志


clone的主要用途是实现线程,在线程中,内存空间共享,然后是堆栈。除了与fork和vfork相同的参数外,克隆还将函数指针作为参数,在创建子进程时立即调用该参数。

Hmm,很有趣。我理解创建新地址空间与共享地址空间的概念,但我一直听说线程被称为“轻量级进程”,因为它们没有自己的地址空间,而是共享父线程的地址空间以及以相同方式创建的所有其他线程的地址空间。这是不正确的区别吗?或者是一个技术上不正确,但用来帮助正在学习的人理解它的版本。@Chris:Linux的目标一直是使进程和任务调度切换尽可能轻和快。这意味着线程不能比进程快。其他一些操作系统对线程的簿记更少,因此它们的速度更快(或者进程更慢,请随意选择)。@Chris:NPTL提供了linux轻量级线程<基于代码>克隆的线程并不特别轻量级。我不确定这两者之间是否有线程技术。NPTL是基于
克隆的线程。在此之前是LinuxThreads,它是基于
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);
}