我在高级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。 但是,其结果并不相同。
请告诉我他在说什么? 这本书/我的答案是错的吗?
我得到了与包含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()
函数。