如何在Linux C程序中获取pthread的线程ID?


Answers:


80

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);

37
最初的问题是关于Linux的。Linux不包含_np函数。(它不包括他们的手册页,我没有做更多检查。)
Trade-Ideas Philip

pthread_threadid_np在OS X> = 10.6和iOS> = 3.2上可用。
bleater 2014年

@Bleater能否提供的官方文档pthread_threadid_np。我需要用于一个项目,因此需要检查iOS和OSX平台中该API的可靠性。请参考opensource.apple.com/source/Libc/Libc-583/pthreads/pthread.h上的链接,但不确定它们是否正确。
Vivek Maran 2015年

@Vivek我没有指向官方文档的任何链接,只有您链接的标题和opensource.apple.com/source/Libc/Libc-583/pthreads/pthread.c上
bleater 2015年

9
@ Trade-IdeasPhilip-要澄清,_np表示不可携带。Linux有自己的_np东西,但不包括Apple的东西pthread_getthreadid_np
2015年

81

什么?该人员要求提供特定于Linux的内容,等效于getpid()。不是BSD或Apple。答案是gettid()并返回整数类型。您将必须使用syscall()来调用它,如下所示:

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

 ....

 pid_t x = syscall(__NR_gettid);

尽管这可能无法移植到非Linux系统,但是threadid是直接可比的,并且获取速度非常快。可以像普通整数一样打印(例如用于LOG)。


9
这应该是正确的答案
Matthew S

该人询问了在Linux上可以运行的某些功能。在我看来,以可移植的方式执行此操作是更可取的方式。如果可移植性不算什么,那么我想Linux真的将成为新的Windows ...
Jasper Siepkes

2
@Jasper Siepkes您错过了重点。他要求进行LINUX调用,该调用等效于线程的getpid()。那就是gettid()。该问题并未询问可移植性或POSIX。太多的人想要炫耀并尝试教书,而不是按要求提出问题。pthread_self()不返回内核线程ID,并且无法以易于打印的方式进行操作。同样,仅与pthread_equal()相比,pthread_self可能是指针,不应对其进行操作。这个问题要求您可以打印一个ID,那就是gettid()。
Evan Langlois,

3
@EvanLanglois他正在使用pthread库,即POSIX线程库。做出与POSIX兼容的答案并不奇怪。“他要求一个LINUX调用,该调用相当于线程的getpid()。” 不,getpid()仅作为示例。它并没有说语义是一个严格的规范。让人们意识到以POSIX兼容的方式来做事,这样Linux之外的其他社区(例如FreeBSD,Illumos,OS X等)也可以从中受益,这并不是“炫耀”。就像我说的,我猜Linux确实已经成为下一个Windows。
Jasper Siepkes

14

如其他答案所述,pthreads没有定义与平台无关的方式来检索整数线程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是否是进程中的主(第一个)线程?


12
pid_t tid = syscall(SYS_gettid);

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


9

您可以使用 pthread_self()

父级在pthread_create()成功执行完之后会知道线程ID ,但是在执行线程时,如果我们要访问线程ID,则必须使用function pthread_self()


7

这行代码为您提供pid,每个threadid和spid。

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

3

pthread_getthreadid_np不在我的Mac OS X上。 pthread_t是不透明的类型。不要把头撞过去。只需将其分配给void*并称其为好即可。如果需要printf使用%p


1
是的,这可行。我所需要的只是将其打印出来进行调试,因此0x23423423423abcdef与tid = 1234一样有用。谢谢!
齐帆

3

我认为不仅这个问题不清楚,而且大多数人也不了解这种差异。检查以下说法:

POSIX线程ID与Linux特定gettid()系统调用返回的线程ID不同。POSIX线程ID由线程实现分配和维护。返回的线程IDgettid()是内核分配的数字(类似于进程ID)。尽管在Linux NPTL线程实现中,每个POSIX线程都有一个唯一的内核线程ID,但是应用程序通常不需要知道内核ID(并且,如果依赖于它们,就不会具有可移植性)。

摘自:《 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");

gettid()实际上是一个很好的建议,谢谢!但是,我需要在这里关注Sergey L.的回答:stackoverflow.com/a/21280941/2430526
SRG,

1

还有另一种获取线程ID的方法。在创建线程时

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

函数调用 第一个参数pthread_t * thread实际上是线程ID(在bits / pthreadtypes.h中定义的无符号long int)。同样,最后一个参数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
}

-1

您也可以以这种方式编写,并且执行相同的操作。例如:

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的每个线程的总和。


它不能回答问题,甚至代码说明也是错误的!
U. Windl

-2

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

#include <thread>

std::this_thread::get_id();

如您所想,这可能不是“与平台无关”。在我的实现中,它解析为pthread_t。在Mac上将是指针,在Linux上将是整数。例如,它也不反映您可能看到的“本机” ID top。有一些要注意的地方,但对于某些用途可能是好的。
布拉德·艾瑞德

1
在C11(关于C的问题)中,您将使用threads.h中的thrd_current()
jerry
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.