如何在 linuxc 程序中获得 pthread 的线程 id?

在 Linux C 程序中,如何打印由 pthread 库创建的线程的线程 id?例如,我们如何通过 getpid()获得进程的 pid。

312213 次浏览

你可以使用 pthread_self()

在成功执行 pthread_create()之后,父线程可以知道线程 id,但是在执行线程时,如果我们想访问线程 id,我们必须使用函数 pthread_self()

函数将给出当前线程的线程 ID。

pthread_t pthread_self(void);

pthread_self()函数返回调用线程的 Pthread 句柄。Pthread _ self ()函数不返回调用线程的整数线程。必须使用 pthread_getthreadid_np()返回线程的整数标识符。

注意:

pthread_id_np_t   tid;
tid = pthread_getthreadid_np();

比这些调用快得多,但提供了相同的行为。

pthread_id_np_t   tid;
pthread_t         self;
self = pthread_self();
pthread_getunique_np(&self, &tid);

正如在其他答案中指出的,pthread 不定义检索整体线程 ID 的平台无关的方法。

在 Linux 系统上,您可以这样获得线程 ID:

#include <sys/types.h>
pid_t tid = gettid();

在许多基于 BSD 的平台上,这个答案 https://stackoverflow.com/a/21206357/316487提供了一种不可移植的方法。

但是,如果您认为需要线程 ID 的原因是为了知道运行在您控制的另一个线程上的是同一个线程还是不同的线程,那么您可能会发现这种方法的一些实用性

static pthread_t threadA;


// On thread A...
threadA = pthread_self();


// On thread B...
pthread_t threadB = pthread_self();
if (pthread_equal(threadA, threadB)) printf("Thread B is same as thread A.\n");
else printf("Thread B is NOT same as thread A.\n");

如果你只是想知道你是否在主线上,还有其他的方法,在这个问题的答案 如何判断 pthread _ self 是否是进程中的主(第一)线程?中有记录。

什么?这个人要求特定于 Linux,并且相当于 getpid ()。不是 BSD 也不是苹果。答案是 gettid ()并返回一个整型。您必须使用 syscall ()调用它,如下所示:

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


....


pid_t x = syscall(__NR_gettid);

虽然这可能不能移植到非 Linux 系统,但是线程可以直接比较,并且获取速度非常快。它可以像普通整数一样打印(比如对于 LOG)。

这一行给出了 pid,每个线程和 spid。

 printf("before calling pthread_create getpid: %d getpthread_self: %lu tid:%lu\n",getpid(), pthread_self(), syscall(SYS_gettid));

我的 Mac OS X 上没有 pthread_getthreadid_nppthread_t是一种不透明的类型。别想太多了。只要把它分配到 void*就可以了。如果你需要 printf使用 %p

pid_t tid = syscall(SYS_gettid);

Linux 提供了这样的系统调用,允许您获取线程的 id。

还有另一种获取线程 ID 的方法

int pthread_create(pthread_t * thread, const pthread_attr_t * attr, void * (*start_routine)(void *), void *arg);

函数调用; 第一个参数 pthread_t * thread实际上是一个线程 id (即在 bit/pthreadtypees.h 中定义的无符号长整型数)。另外,最后一个参数 void *arg是传递给要进行线程化的 void * (*start_routine)函数的参数。

您可以创建一个结构来传递多个参数并发送一个指向结构的指针。

typedef struct thread_info {
pthread_t thread;
//...
} thread_info;
//...
tinfo = malloc(sizeof(thread_info) * NUMBER_OF_THREADS);
//...
pthread_create (&tinfo[i].thread, NULL, handler, (void*)&tinfo[i]);
//...
void *handler(void *targs) {
thread_info *tinfo = targs;
// here you get the thread id with tinfo->thread
}

与平台无关的方式(从 c + + 11开始)是:

#include <thread>


std::this_thread::get_id();

I think not only is the question not clear but most people also are not cognizant of the difference. Examine the following saying,

方法返回的线程 ID 不同 Linux 特定的 gettid()系统调用。分配 POSIX 线程 ID 并由线程实现维护。线程 ID 返回 by gettid() is a number (similar to a process ID) that is assigned by 尽管每个 POSIX 线程都有一个惟一的内核线程 ID 在 Linux NPTL 线程实现中,通常是一个应用程序 不需要知道内核 ID (如果它是可移植的,那么它就不是可移植的) depends on knowing them).

节选自: Linux 编程接口: Linux 和 UNIX 系统编程手册,Michael Kerrisk

恕我直言,只有一种可移植的方式可以传递一个结构,其中以升序方式定义一个保存数字的变量,例如 1,2,3...到每个线程。通过这样做,可以跟踪线程的 id。尽管如此,还是应该使用 int pthread_equal(tid1, tid2)函数。

if (pthread_equal(tid1, tid2)) printf("Thread 2 is same as thread 1.\n");
else printf("Thread 2 is NOT same as thread 1.\n");

You can also write in this manner and it does the same. For eg:

for(int i=0;i < total; i++)
{
pthread_join(pth[i],NULL);
cout << "SUM of thread id " << pth[i] << " is " << args[i].sum << endl;
}

这个程序设置一个 pthread _ t 数组,并计算每个数组的和。所以它用线程 id 打印每个线程的总和。

对于不同的操作系统有不同的答案。

你可以试试这个:

#include <unistd.h>
#include <sys/syscall.h>


int get_thread_id() {
#if defined(__linux__)
return syscall(SYS_gettid);
#elif defined(__FreeBSD__)
long tid;
thr_self(&tid);
return (int)tid;
#elif defined(__NetBSD__)
return _lwp_self();
#elif defined(__OpenBSD__)
return getthrid();
#else
return getpid();
#endif
}