как получить идентификатор потока pthread в программе linux c?


89

В программе linux c, как распечатать идентификатор потока потока, созданного библиотекой pthread?
например: мы можем получить представление о процессе с помощьюgetpid()

Ответы:


80

pthread_self() функция даст идентификатор потока текущего потока.

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 01

@Bleater Не могли бы вы предоставить официальную документацию для pthread_threadid_np. Мне нужно использовать его для проекта, поэтому мне нужно проверить надежность этого API на платформах iOS и OSX. Ссылался на ссылку на opensource.apple.com/source/Libc/Libc-583/pthreads/pthread.h, но не уверен, что они правильные.
Вивек Маран,

@Vivek У меня нет ссылки на официальные документы, только заголовок, на который вы
ссылаетесь,

9
@ Trade-IdeasPhilip - Чтобы уточнить, _npозначает непереносимый . У Linux есть свои собственные _npвещи, но они не включают Apple pthread_getthreadid_np.
Джош Келли

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 напрямую сопоставим и очень быстро получить. Его можно напечатать (например, для журналов регистрации) как обычное целое число.


9
Это должен быть правдивый ответ
Matthew S

Человек спросил о том, что работает в Linux. Мне кажется, что делать это портативным способом лучше. Если переносимость ничего не значит, тогда я полагаю, что Linux действительно становится новой Windows ...
Джаспер Сипкес

2
@Jasper Siepkes Вы упускаете суть. Он попросил вызвать LINUX, который был эквивалентом getpid () для потоков. Это gettid (). Вопрос не касался переносимости или POSIX. Слишком много людей хотят похвастаться и попытаться преподавать, вместо того чтобы задавать вопросы, как их задают. pthread_self () не возвращает идентификатор потока ядра и не может быть изменен таким образом, чтобы облегчить печать. Кроме того, pthread_self, скорее всего, является указателем, и им нельзя манипулировать, только по сравнению с pthread_equal (). Был задан вопрос об идентификаторе, который можно распечатать, и это gettid ().
Эван Ланглуа

3
@EvanLanglois Он работает с библиотекой pthread, буквально библиотекой потоков POSIX. Сделать ответ, совместимый с POSIX, не так уж и странно. «Он запросил вызов LINUX, который был эквивалентом getpid () для потоков». Нет, getpid()приведен в качестве примера. Он не сказал, что семантика была жесткой спецификацией. Информировать людей о том, что они делают что-то совместимым с POSIX способом, чтобы другие сообщества, помимо Linux (например, FreeBSD, Illumos, OS X и т. Д.), Могли получить от них пользу, не является «хвастовством». Как я уже сказал, я полагаю, что Linux действительно стала следующей Windows.
Джаспер Сипкес,

14

Как отмечалось в других ответах, pthreads не определяет независимый от платформы способ получения интегрального идентификатора потока.

В системах Linux вы можете получить идентификатор потока следующим образом:

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

На многих платформах на основе BSD этот ответ https://stackoverflow.com/a/21206357/316487 дает непереносимый способ.

Однако, если причина, по которой вы считаете, что вам нужен идентификатор потока, заключается в том, чтобы знать, работаете ли вы в одном или другом потоке с другим потоком, который вы контролируете, вы можете найти некоторую полезность в этом подходе.

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 предоставляет такой системный вызов, чтобы вы могли получить идентификатор потока.


9

Ты можешь использовать pthread_self()

Родитель узнает идентификатор потока после pthread_create()успешного выполнения, но при выполнении потока, если мы хотим получить доступ к идентификатору потока, мы должны использовать функцию 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. Спасибо!
Qi Fan

3

Я думаю, что не только вопрос не ясен, но и большинство людей не осознают разницу. Изучите следующее высказывание:

Идентификаторы потоков POSIX не совпадают с идентификаторами потоков, возвращаемыми gettid()системным вызовом Linux . Идентификаторы потоков POSIX назначаются и поддерживаются реализацией потоковой передачи. Идентификатор потока, возвращаемый функцией, gettid()представляет собой номер (аналогичный идентификатору процесса), присвоенный ядром. Хотя каждый поток POSIX имеет уникальный идентификатор потока ядра в реализации потоков Linux NPTL, приложению обычно не требуется знать идентификаторы ядра (и оно не будет переносимым, если это зависит от их знания).

Взято из: Интерфейс программирования Linux: Справочник по системному программированию Linux и UNIX, Майкл Керриск

IMHO, есть только один переносимый способ передать структуру, в которой определяют номера хранения переменных по возрастанию, например, 1,2,3... для каждого потока. Таким образом можно отслеживать идентификатор потока. Тем не менее, 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()самом деле это хорошее предложение, спасибо! Однако мне нужно было следить за ответом Сергея Л. здесь: stackoverflow.com/a/21280941/2430526
SRG

1

Есть еще один способ получить идентификатор потока. При создании потоков с

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

вызов функции; первый параметр pthread_t * threadна самом деле является идентификатором потока (это длинное целое число без знака, определенное в файле bits / pthreadtypes.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
}

-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 и вычисляет сумму для каждого. Таким образом, он печатает сумму каждого потока с идентификатором потока.


Он не отвечает на вопрос, и даже описание кода неверно!
Уиндл,

-2

Независимый от платформы способ (начиная с c ++ 11):

#include <thread>

std::this_thread::get_id();

вероятно, это не так "платформенно-независимый", как вы думаете. в моей реализации он разрешается в pthread_t. На Mac это будет указатель, а на Linux - целое число. Он также не отражает «родной» идентификатор, который вы можете увидеть, topнапример. Кое-что нужно знать, но, возможно, для некоторых целей это нормально.
Брэд Оллред

1
В C11 (вопрос был о C) вы должны использовать thrd_current () из threads.h
Джерри
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.