9

我在Advanced Linux Programming中遇到了一个概念。这是一个链接:参考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

我知道要创建一个线程,linux 在内部调用clone(大多数情况下),就像fork系统调用创建一个进程一样。唯一的区别是进程中创建的线程共享相同的进程地址空间,而父进程创建的进程复制父进程地址空间。所以,我认为在线程中打印进程 ID 会导致相同的 processID。但是,它在书中的结果不一样。

请告诉我他在说什么..?书中/我的答案是否错误..?

4

4 回答 4

9

我得到与包含 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

libc (1)使用linuxthreadspthread的实现

而libc (2)使用NPTL("Native posix thread library")实现pthread

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

每个线程实际上是一个具有不同 PID 的不同进程,发送到线程 PID 的信号只能由该线程处理

因此,在使用linuxthreads实现的旧 libc 中,每个线程都有其不同的 PID

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

NPTLredhat团队开发。并且根据redhat NPTL文档:实现中解决的问题之一NPTL是:

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

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


这解释了你的问题。

您正在使用包含NPTLpthread (“Native posix thread library”)实现的新 libc 版本

并且本书使用了旧版本的 libc,其中包含linuxthreadspthread 的实现

于 2013-10-30T08:28:46.997 回答
7

您正在使用的文本非常古老(2001 年)。旧版本的 Linux 将线程实现为具有共享地址空间的独立进程。每个线程都有一个单独的 pid。然而,这个线程模型不符合 POSIX,并且存在许多可移植性问题。

从 2.6 左右开始,Linux 切换到“Native POSIX Thread Library”(NPTL)。在此实现中,线程不会获得自己的 PID。

于 2013-10-30T07:45:18.427 回答
2

一个进程创建的所有线程按定义都属于这一进程。要获得这一进程的 process-id use getpid(),无论来自哪个进程的线程。

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

要获取为单个线程创建的不同进程的进程 ID,请使用(Linux 特定)*1gettid()


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

于 2013-10-30T07:25:18.840 回答
-2

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

于 2013-10-30T07:31:51.097 回答