Pthread 库实际上是用户线程解决方案吗?
Posted
技术标签:
【中文标题】Pthread 库实际上是用户线程解决方案吗?【英文标题】:Is Pthread library actually a user thread solution? 【发布时间】:2012-01-28 04:14:33 【问题描述】:标题可能不够清楚,因为我实际上不知道如何定义我的问题。
我了解 Pthread 是一个符合 POSIX 标准的线程库(关于 POSIX,请参阅***:http://en.wikipedia.org/wiki/Posix)。它在类 Unix 操作系统中可用。
关于线程,我读到有三种不同的模型:
用户级线程:内核不知道。用户自己创建/实现/销毁线程。
内核级线程:内核直接支持一个进程中的多线程控制。
轻量级进程(LWP):由内核调度,但可以与用户线程绑定。
你看到我的困惑了吗?当我调用pthread_create()
创建线程时,我是否创建了用户级线程?大概吧。那么我可以说,Pthread 为线程提供了用户级解决方案吗?不能操作内核/LWP?
【问题讨论】:
【参考方案1】:@paulsm4 我怀疑你关于内核知道一切的评论。在这个用户级线程的特定上下文中,内核不知道这样的事情正在发生。用户级线程的调度由用户自己维护(通过库提供的接口),内核最终只为整个进程分配一个内核线程。内核会将进程视为单线程,并且其中一个线程的任何阻塞调用最终都会阻塞该进程的所有线程。 参考http://www.personal.kent.edu/~rmuhamma/OpSystems/Myos/threads.htm
【讨论】:
如果它不使用内核线程就会发生这种情况。另一种方式。如果它会在用户空间处理这个问题,那么您最终将只使用一个内核,因为用户空间无法控制内核,也无法在没有内核交互的情况下在内核上调度某些内容。【参考方案2】:在 Linux 中,pthread 是implemented as a lightweight process。内核(v2.6+)实际上是用NPTL 实现的。让我引用维基内容:
NPTL 是所谓的 1×1 线程库,用户创建的线程(通过 pthread_create() 库函数)与内核中的可调度实体(任务,在 Linux 案例中)一一对应)。这是最简单的线程实现。
所以linux内核中的pthread实际上是作为内核线程来实现的。
【讨论】:
这应该是公认的答案。 Linux 中的 Pthreads 是使用 NPTL 实现的,NPTL 实际上是一种一对一的线程模型。每创建一个用户级线程,都会有一个与之关联的内核级线程。这意味着使用 NPTL 实现的 Pthread 可以利用多核 CPU @dantebarba:Junji Zhi 是正确的(昨天我赞成他的回答,并且几年前也更新了我的回答),你错了。重要说明: 1) Pthreads 只是一个接口。实施将因环境而异。 2)“线程”与“进程”的 linux 实现确实不必然对应于一般操作系统教科书中经常描述的内容。 3)具体来说,Linux pthreads的实现一般使用LinuxNTPL,“……一个所谓的1x1线程库”。 您只是在回复我之前在评论中所说的内容......而且我并不是唯一一个说您的回答具有误导性的人。您特别说过“内核知道一切”,这在 N:1 线程模型上是不正确的。 NPTL 是 1-1 模型的实现这一事实并不意味着所有实现都应该以相同的方式运行。【参考方案3】:pthreads 本身并不是真正的线程库。 pthreads 是特定线程库使用该平台上可用的并发资源实现的接口。所以在linux上、bsd上、solaris上等都有pthreads的实现,虽然接口(头文件和调用的含义)是一样的,但各自的实现是不同的。
因此,就内核线程对象而言,pthread_create 的实际作用因操作系统和 pthread 库实现而异。在第一个近似值上,您不需要知道(这是 pthread 抽象允许您不需要知道的东西)。最终,您可能需要看到“幕后”,但对于大多数 pthread 用户来说,这不是必需的。
如果您想知道 /specific/ pthread 实现在特定操作系统上的作用,您需要澄清您的问题。例如,Solaris 和 Linux 所做的就非常不同。
【讨论】:
【参考方案4】:问:我理解 Pthread 是一个符合 POSIX 标准的线程库
答:是的。实际上,“Pthreads”代表“Posix 线程”: http://en.wikipedia.org/wiki/Pthreads
问:在类 Unix 操作系统中可用。
A:实际上,它适用于许多不同的操作系统……包括 Windows、MacOS……当然还有 Linux、BSD 和 Solaris。
问:关于线程,我读到有三种不同的模型
现在你变得模糊了。 “线程”是一个非常通用的术语。有很多很多不同的模型。还有很多很多不同的方式可以描述和/或实现“线程”。包括 Java 线程模型或 Ada 线程模型之类的东西。
问:当我调用 pthread_create() 创建线程时,我是否创建了一个线程? 用户级线程?
答:是的:您在用户空间中所做的几乎所有事情都在您自己的私有“用户空间”中受到“保护”。
问:用户级线程:内核不知道。
A:不。内核知道一切 :)
Q:内核级线程:内核直接支持多线程 过程中的控制。
A:是的,有“内核线程”之类的东西。
而且,碰巧的是,Linux 广泛使用内核线程。例如,Linux 系统中的每一个进程都是一个“内核线程”。并且每个用户创建的 pthread 也被实现为一个新的“内核线程”。 “工作线程”也是如此(对任何用户级进程完全不可见)。
但这是一个高级主题,您无需了解即可有效使用 pthread。这是一本很好的书,详细讨论了这一点 - 以及许多其他主题:
[Linux 内核开发,罗伯特·洛夫][1]
记住:“Pthreads”是一个接口。它的实现方式取决于平台。 Linux 使用内核线程; Windows 使用 Win32 线程等。
================================================ ============================== 附录:
由于人们似乎仍然在关注这个旧线程,我认为参考这篇文章会很有用:
https://***.com/a/11255174/421195
Linux 通常使用两种 pthread 实现: LinuxThreads 和 Native POSIX Thread Library(NPTL), 尽管前者在很大程度上已经过时了。 2.6 的内核提供 NPTL,它提供更接近 SUSv3 的一致性,并执行 尤其是当有很多线程时更好。
您可以查询 shell下pthreads使用命令的具体实现:
getconf GNU_LIBPTHREAD_VERSION
您还可以在The Linux Programming Interface 中获得更详细的实现差异。
“Pthreads”是一个库,基于 Posix 标准。 pthreads 库的实现方式因平台和库而异。 [1]:http://www.amazon.com/Linux-Kernel-Development-Robert-Love/dp/0672329468
【讨论】:
您是不是在这里制造了一些混乱? 1. 原发帖人从未询问过 Linux 的具体细节 2. 内核并不知道一切,尤其是在用户级线程的上下文中,因为它们不是由内核调度的,而是由库“切换”,在这种情况下是 Pthreads。 3. 术语“线程”是通用的。没错,但是,问题更多是关于线程上下文中的操作系统和应用程序接口,答案应该是关于抽象的。 确实,这个答案完全是错误的。内核不知道用户空间线程;如果创建线程需要通知内核(通过系统调用),那么您的线程将不再是“用户空间”。这里的正确答案包括***.com/a/12169068/1424877和***.com/a/27581327/1424877; ***.com/a/8639239/1424877 是这个答案正确部分的一个很好的表达(但缺乏使其他部分对 OP 真正有帮助的 Linux 细节)。 每个Linux进程怎么可能是内核线程? Linux中的一个进程在struct task_struct结构体中定义为PCB(进程控制块)。 这个答案令人误解。用户级线程对内核不可见。这就是 N:1 线程模型的全部内容。您可以在每本基本的操作系统概念书上阅读此内容,例如 Silberschatz 第 7 版或 Stallings 第 7 版。另外,正如第一个用户描述的那样,共有三种线程模型: N:1 模型:多个 ULT 映射到 KLT 1:1 模型:每个 KLT 一个 ULT。 N:M 模型:一个 ULT 映射到一个 LWP 映射到多个 KLT。 老兄——事实上,Linux 做的事情“有些不同”(有很好的理由,结果非常好)。因此,您在“每本基本操作系统概念书”上阅读的内容可能适用于也可能不适用于每个细节。是的,我也读过 Stallings。也许您应该阅读Love, 3rd Ed,然后自己重新阅读Stallings ;) 或者只是在下面回复Fin's 或Junji Zhi's。【参考方案5】:我发现以前的答案不像我希望的那样令人满意或清晰,所以这里是:
当你打电话时
pthread_create(...)
您总是创建一个新的用户级线程。假设有操作系统,总是有一个或多个内核线程......但让我们更深入地了解:
根据“操作系统概念”第 10 版,我们应该查看的实际分类(当涉及线程库时)是用户级线程如何映射到内核线程(这就是问题的真正含义)。
模型是一对一(单个进程中的每个用户级线程都映射到不同的内核线程),多对一(线程库是“用户级别”,因此单个进程中的所有不同线程都映射到单个内核线程,并且线程数据结构,上下文切换等在用户级别而不是由操作系统处理[意味着如果线程阻塞一些 I/O 调用,整个进程可能会阻塞])和多对多(介于两者之间,显然用户级线程的数量大于或等于它的内核线程的数量正在映射到)。
现在,pthreads 是一个规范,而不是一个实现,并且实现确实取决于它所写入的操作系统。它可以是这些模型中的任何一种(请注意,“多对多”非常灵活)。
因此,例如,在 Linux 和 Windows(多年来最流行的操作系统,模型是“一对一”)上,实现是“一对一”。
【讨论】:
【参考方案6】:Pthreads 只是线程库的标准化接口。创建操作系统线程还是轻量级线程取决于您使用的库。不过,我的第一个客人是您的线程是“真正的”操作系统级线程。
【讨论】:
这个答案在技术上似乎是正确的,但没有提供任何有用的信息。以上是关于Pthread 库实际上是用户线程解决方案吗?的主要内容,如果未能解决你的问题,请参考以下文章
[Linux用户空间编程-7]:pThread线程库-线程管理代码示例
Linux_多线程(进程与线程的联系_pthread库_线程创建_线程等待_线程正常终止_线程取消_线程分离_pthread_t与LWP)