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;
}
4

2 回答 2

28

在 Linux 上pthread使用clone带有特殊标志的系统调用CLONE_THREAD

请参阅系统调用的文档clone

CLONE_THREAD(从 Linux 2.4.0-test8 开始)

如果设置了 CLONE_THREAD,则子进程与调用进程位于同一线程组中。为了使 CLONE_THREAD 讨论的其余部分更具可读性,术语“线程”用于指代线程组中的进程。

线程组是 Linux 2.4 中添加的一项功能,用于支持共享单个 PID的一组线程的 POSIX 线程概念。在内部,这个共享的 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).
于 2012-05-01T02:49:24.797 回答
7

Linux 通常使用 pthread 的两种实现:LinuxThreadsNative POSIX Thread Library(NPTL),尽管前者在很大程度上已经过时。2.6 的内核提供了 NPTL,它提供了更接近 SUSv3 的一致性,并且性能更好,尤其是在有很多线程时。
可以使用命令查询shell下pthreads的具体实现:

getconf GNU_LIBPTHREAD_VERSION

您还可以在The Linux Programming Interface中获得更详细的实现差异。

于 2012-06-29T02:00:05.073 回答