了解Pthreads

我在高级Linux编程中遇到了一个概念。 这里有一个链接 :参考4.5 GNU / Linux线程实现

我很清楚作者所说的概念,但是我已经解释了为打印线程的processID所解释的程序。

这是代码

#include <pthread.h> #include <stdio.h> #include <unistd.h> void* thread_function (void* arg) { fprintf (stderr, "child thread pid is %d\n", (int) getpid ()); /* Spin forever. */ while (1); return NULL; } int main () { pthread_t thread; fprintf (stderr, "main thread pid is %d\n", (int) getpid ()); pthread_create (&thread, NULL, &thread_function, NULL); /* Spin forever. */ while (1); return 0; } 

根据作者的上述代码的输出是

 % cc thread-pid.c -o thread-pid -lpthread % ./thread-pid & [1] 14608 main thread pid is 14608 child thread pid is 14610 

我编译时得到的输出是

 [1] 3106 main thread pid is 3106 child thread pid is 3106 

我明白,要创build一个线程,Linux内部调用克隆 (大部分情况下), 系统调用一样创build一个进程。 唯一的区别是在进程中创build的线程共享相同的进程地址空间,而由父进程创build的进程复制父进程地址空间。 所以,我认为在线程中打印进程ID会导致相同的进程ID。 但是,其结果并不相同。

请告诉我他在说什么? 这本书/我的答案是错的吗?

Solutions Collecting From Web of "了解Pthreads"

我得到了与包含libc libuClibc-0.9.30.1.so (1)的 linux相同的结果。

 root@OpenWrt:~# ./test main thread pid is 1151 child thread pid is 1153 

我试图用一个包含来自ubuntu libc6 (2)的libc的linux来运行这个程序,

 $ ./test main thread pid is 2609 child thread pid is 2609 

(1)使用linuxthreads实现pthread

而libc (2)使用pthread的NPTL (“Native posix线程库”)实现

根据linuxthreads FAQ (在J.3中的答案):

每个线程实际上是一个独特的PID过程,发送给线程PID的信号只能由该线程处理

所以在使用linuxthreads实现的旧libc中,每个线程都有其独特的PID

在使用NPTL实现的新libc版本中,所有线程都具有与主进程相同的PID。

NPTL是由红帽团队开发的。 根据国家红新月会文件 : NPTL实施中解决的问题之一是:

(章节:现有实施的问题,第5页)

每个具有不同进程ID的线程都会导致与其他POSIX线程实现的兼容性问题。 这部分是一个有争议的问题,因为信号不能很好地使用,但仍然很明显


这就解释了你的问题。

您正在使用包含pthread的NPTL (“本地posix线程库”)实现的新libc版本

本书使用包含linuxthreads实现pthread的libc旧版本

你正在工作的文本是非常古老的(2001年)。 老版本的Linux将线程实现为具有共享地址空间的独立进程。 每个线程都有一个独立的pid。 但是这个线程模型不符合POSIX标准,并且有许多可移植性问题。

从2.6左右开始,Linux切换到“本地POSIX线程库”(NPTL)。 在这个实现中,线程没有得到自己的PID。

由进程创建的所有线程都通过定义属于这一个进程。 为了得到这个进程的进程ID使用getpid() ,无论从哪个进程的线程。

链接文档的作者是正确的,在Linux (p)下,线程被实现为与它们所属的进程共享相同地址空间的不同进程。 后者然而并不反映getpid() ,链接文档的作者是错误的这个假设。

获取为单个线程使用(特定于Linux) gettid() * 1创建的独特进程的进程ID。


* 1:请注意,glibc不提供这个函数调用的包装。 使用syscall()来调用它。

正如作者所指出的那样,在Linux中,线程是轻量级进程,共享相同的地址空间。 每个进程都有唯一的PID,而每个线程都有一个线程ID TID。 主线程的线程ID同时也是一个双重用途。 要获得调用线程的threadID,可以使用pthread_self()函数。