【问题标题】:Does the clone() system call ultimately rely on fork functionality?clone() 系统调用最终是否依赖于 fork 功能?
【发布时间】:2011-05-08 14:45:44
【问题描述】:

对于我正在学习的课程,我一直在直接使用 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);
}

谢谢!

【问题讨论】:

标签: linux clone fork


【解决方案1】:

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

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

这个共享地址空间以后可以实现轻量级 IPC,但进程本身并不瘦。

【讨论】:

  • 嗯,很有趣。我理解创建新地址空间与共享地址空间的概念,但我一直听说线程被称为“轻量级进程”,因为它们没有自己的地址空间,而是共享父地址空间和与以相同方式创建的所有其他线程。这是不正确的区分吗?或者它是不是在技术上不正确,而是为了帮助正在学习的人理解它。
  • @Chris:Linux 的目标一直是进程和任务调度切换尽可能轻且快。这意味着线程不能比进程更快地完成它。其他一些操作系统对线程的记录较少,因此它们更快(或者进程更慢,随你选择)。
  • @Chris:NPTL 提供了 linux 轻量级线程。基于clone 的线程并不是特别轻量级。我不确定这两者之间是否有线程技术。
  • NPTL 基于clone的线程。在此之前是 LinuxThreads,它是基于 fork 的“线程”。
【解决方案2】:

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

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

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

或者新任务可以选择拥有各自资源的自己的副本。并且从 2.6.16 开始,他们可以在启动后这样做,请参阅 unshare(2)。

例如,vfork() 和 fork() 调用之间的唯一区别是 vfork() 设置了 CLONE_VM 和 CLONE_VFORK。 CLONE_VM 使其共享其父级的内存(与线程共享内存的方式相同),而 CLONE_VFORK 使父级阻塞,直到子级释放其内存映射(通过调用 execve() 或 _exit())。

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

【讨论】:

    【解决方案3】:

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

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

    vfork()-->C_lib-->sys_vfork()-->do_fork()

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

    fork 和 vfork 的区别在于 vfork 保证 child 将首先执行,而 parent 将阻塞,直到 child 调用 exit 或 exec。 vfork 传递了额外的标志,即 CLONE_VM,这个标志要求内核不要复制页表,原因很简单,孩子要么退出要么执行,如果孩子退出什么都不做,如果孩子执行 exec,页表肯定会被改变。我希望 fork 和 vfork 标志现在在内核级别是清晰的。 现在让我们看看克隆标志

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

    【讨论】:

      猜你喜欢
      • 2012-06-06
      • 2020-01-04
      • 1970-01-01
      • 2021-12-31
      • 1970-01-01
      • 2017-01-16
      • 1970-01-01
      • 2021-04-24
      • 1970-01-01
      相关资源
      最近更新 更多