![Linux中线程的定义依赖于系统调用吗?](https://linux22.com/image/222721/Linux%E4%B8%AD%E7%BA%BF%E7%A8%8B%E7%9A%84%E5%AE%9A%E4%B9%89%E4%BE%9D%E8%B5%96%E4%BA%8E%E7%B3%BB%E7%BB%9F%E8%B0%83%E7%94%A8%E5%90%97%EF%BC%9F.png)
克隆
clone()
在/clone3()
系统调用的手册页中我发现:
CLONE_THREAD(自 Linux 2.4.0 起)。
如果设置了 CLONE_THREAD,则子进程将被放置在与调用进程相同的线程组中。为了使 CLONE_THREAD 的讨论的其余部分更具可读性,术语“线程”用于指代线程组中的进程。
因此,据我了解,从clone
的角度来看,线程是使用CLONE_THREAD
标志集创建的(因此,最终与调用者位于同一线程组中)。
富泰克斯
但是,例如,查看 的手册页futex()
,我发现:
FUTEX_PRIVATE_FLAG(自 Linux 2.6.22 起)
该选项位可用于所有 futex 操作。它告诉内核 futex 是进程私有的,不与另一个进程共享(即,它仅用于之间的同步)同一进程的线程)。这允许内核进行一些额外的性能优化。
这似乎与 的定义有关clone
,但又不完全有关。当创建一个线程(如克隆中那样(即CLONE_THREAD
指定标志)时,创建的任务也会必须分享他们的虚拟机。然而,可以创建两个不是线程的任务(如在克隆中),它们仍然共享VM(只需指定CLONE_VM
)。但是,从FUTEX :新的私有 futexes文章/补丁中,用于 futexes 的优化_PRIVATE
是使用 futex 字的虚拟地址而不是物理地址,因此,人们可能可以在使用CLONE_VM
... 创建的任务中使用私有 futexes,但 man forfutex()
禁止这样做。
不过,这不是一个关键问题:手册施加了(看似不必要的)限制,但它并没有破坏任何东西。那么,这里有一个更令人兴奋的例子。
关闭
从系统调用手册中close()
:
此外,考虑以下场景,其中两个线程 对同一个文件描述符执行操作:
(1) 1个 线 在文件描述符上的 I/O 系统调用中被阻止。例如,它尝试向已满的管道写入(2),或尝试从当前没有可用数据的流套接字读取(2)。
(2)另一个线关闭文件描述符。
这种情况下的行为因系统而异。 <...>
显然,这里假设两个任务共享一个文件描述符表,但作为线程(如在克隆中)既没有必要也不足以声称它们共享文件描述符表!
如果使用 创建任务CLONE_THREAD|...|CLONE_FILES
,那么一切都很好,但如果只是CLONE_THREAD|...
(这是允许的),则两个线程(如在 clone 中)不共享文件描述符,并且使用 克隆的任务...|CLONE_FILES
是不是线程但是做共享文件描述符!
问题
首先,这(至少是示例close()
)是手册中的错误吗?难道是因为它是在clone()
系统调用设计之前写的?或者我错过了什么?
一般来说:当使用手册中使用术语“线程”的特定系统调用时,我如何知道其含义是什么?
特别是(假设我想编写适用于未来内核版本的代码):在共享VM但不是线程(如克隆)的任务中使用私有futexes可以吗?close
在线程中调用(如在克隆中)是否可以线程安全不是正如常识所示,共享文件描述符表?
答案1
2.4 是引入我们所知的“线程”的 Linux 版本(在这里讨论)。 AndCLONE_THREAD
是向clone() 请求线程而不是进程的标志。
在 2.4 之前,Linux 只有“进程”...并且“线程”一词历史上用于指代任何并行执行。所以从历史上看,进程是线程的一种形式。
克隆页面中的措辞可以被理解为向理解一切都是进程的观众解释线程的新概念(正如我们现在所知道的那样)。因此,clone() 的措辞已经非常过时了。但并不“错”。
也就是说,这句话介绍了