POSIX Threads如何在linux中运行?

时间:2010-09-14 02:56:10

标签: c linux pthreads

我认为pthread使用 clone 在linux中生成一个新的线程。但如果是这样,所有线程都应该有单独的 pid 。否则,如果它们具有相同的 pid ,则 libc 中的全局变量似乎是共享的。但是,当我运行以下程序时,我得到了相同的 pid ,但 errno 的地址不同。

extern errno;
void*
f(void *arg)
{
    printf("%u,%p\n", getpid(), &errno);
    fflush(stdin);
    return NULL;
}

int
main(int argc, char **argv)
{
    pthread_t tid;
    pthread_create(&tid, NULL, f, NULL);
    printf("%u,%p\n", getpid(), &errno);
    fflush(stdin);
    pthread_join(tid, NULL);
    return 0;
}

然后,为什么?

2 个答案:

答案 0 :(得分:4)

我不确定调用pthread_create()时究竟是如何使用clone()的。也就是说,看clone() man page,看起来有一个名为CLONE_THREAD的标志:

  

如果设置了CLONE_THREAD,那么孩子就是   放在同一个线程组中   呼叫过程。做剩下的   关于CLONE_THREAD的讨论更多   可读,术语“线程”用于   引用线程中的进程   基。

     

线程组是添加的功能   Linux 2.4支持POSIX线程   共享一组线程的概念   一个PID。在内部,这是共享的   PID是所谓的线程组   线程的标识符(TGID)   组。自Linux 2.4以来,调用   getpid(2)返回的TGID   呼叫者。

接下来讨论一个gettid()函数,用于获取进程中单个线程的唯一ID。修改你的代码:

#include <stdio.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <unistd.h>

int errno;
void*
f(void *arg)
{
    printf("%u,%p, %u\n", getpid(), &errno, syscall(SYS_gettid));
    fflush(stdin);
    return NULL;
}

int
main(int argc, char **argv)
{
    pthread_t tid;
    pthread_create(&tid, NULL, f, NULL);
    printf("%u,%p, %u\n", getpid(), &errno, syscall(SYS_gettid));
    fflush(stdin);
    pthread_join(tid, NULL);
    return 0;
}

(确保使用“-lpthread”!)我们可以看到单个线程ID确实是唯一的,而pid保持不变。

rascher@coltrane:~$ ./a.out 
4109,0x804a034, 4109
4109,0x804a034, 4110

答案 1 :(得分:3)

  1. 全局变量:您的错误是errno不是全局变量,而是扩展为int类型左值的宏。在实践中,它会扩展到(*__errno_location())或类似。
  2. getpid是一个库函数,它返回POSIX过程中的进程 id,而不是伪造的Linux每个clone pid。如今Linux具有最小的内核级功能,可以使线程具有近乎POSIX的兼容性,但是大多数仍然依赖于用户空间libc级别的丑陋黑客。