Linux内核3.2中pthread是如何实现的?

18

大家好,

以下代码来自“Unix环境高级编程”一书,它创建了一个新的线程,并打印主线程和新线程的进程id和线程id。

在这本书中,它说在Linux系统中,该代码的输出会显示两个线程有不同的进程id,因为pthread使用轻量级进程来模拟线程。然而,当我在Ubuntu 12.04(内核版本3.2)上运行该代码时,打印的是相同的pid。

所以,新的Linux内核是否改变了pthread的内部实现方式呢?

#include "apue.h"
#include <pthread.h>

pthread_t ntid;

void printids(const char *s) {
  pid_t     pid;
  pthread_t tid;
  pid = getpid();
  tid = pthread_self();
  printf("%s pid %u tid %u (0x%x)\n",
         s, (unsigned int)pid, (unsigned int)tid, (unsigned int)tid);
}

void *thread_fn(void* arg) {
  printids("new thread: ");
  return (void *)0;
}

int main(void) {
  int err;
  err = pthread_create(&ntid, NULL, thread_fn, NULL);
  if (err != 0)
    err_quit("can't create thread: %s\n", strerror(err));
  printids("main thread: ");
  sleep(1);
  return 0;
}

另请参见:https://dev59.com/52035IYBdhLWcg3wSN4G - Zifei Tong
3
维基百科有一篇不错的文章,介绍了Linux在2.6内核中转向NPTL的过程:http://en.wikipedia.org/wiki/Native_POSIX_Thread_Library。同时还有一篇较短的文章,解释了旧线程模型LinuxThreads的一些缺点:http://en.wikipedia.org/wiki/LinuxThreads。 - Michael Burr
2个回答

28
在Linux中,pthread使用特殊标志CLONE_THREADclone系统调用。关于clone系统调用的详细信息请参见文档CLONE_THREAD(自Linux 2.4.0-test8起)允许将子进程放置在与调用进程相同的线程组中。为了使后面关于CLONE_THREAD的讨论更容易理解,术语“线程”用于指代线程组内的进程。 线程组是Linux 2.4中新增的功能,用于支持POSIX线程的概念,即一组共享单个PID的线程。内部上,这个共享的PID被称为线程组标识符(TGID)。从Linux 2.4开始,调用getpid(2)将返回调用者的TGID。实际上,Linux已经改变了其线程实现,因为POSIX.1要求线程共享相同的进程ID。有关详情,请参见此处此处的文档。
   In the obsolete LinuxThreads implementation, each of the threads in a process
   has a different process ID.  This is in violation of the POSIX threads
   specification, and is the source of many other nonconformances to the
   standard; see pthreads(7).

7

Linux通常使用两种pthread实现:LinuxThreadsNative POSIX Thread Library(NPTL),尽管前者已经基本过时。内核从2.6版本开始提供NPTL,它更接近于SUSv3标准,并且在存在许多线程时性能更好。
您可以在shell下使用以下命令查询特定的pthread实现:

getconf GNU_LIBPTHREAD_VERSION

您也可以在The Linux Programming Interface中了解更详细的实现差异。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接