як отримати ідентифікатор потоку pthread у програмі linux c?


89

Як надрукувати ідентифікатор потоку потоку, створеного бібліотекою pthread, у програмі linux c?
наприклад: ми можемо отримати процес процесу за допомогою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 Філіп

pthread_threadid_np доступний в OS X> = 10.6 та iOS> = 3.2.
bleater

@Bleater Чи можете ви надати офіційну документацію для pthread_threadid_np. Потрібно використовувати для проекту, тому потрібно перевірити надійність цього API на платформах iOS та OSX. Посилання посилалося на opensource.apple.com/source/Libc/Libc-583/pthreads/pthread.h, але не впевнений, що вони правильні.
Vivek Maran

@Vivek У мене немає жодного посилання на офіційні документи, лише заголовок, на який ви посилаєтесь, та джерело на opensource.apple.com/source/Libc/Libc-583/pthreads/pthread.c
bleater

9
@ Trade-IdeasPhilip - для уточнення _npозначає , що це не портативний. У Linux є свої _npречі, але вони не включають Apple pthread_getthreadid_np.
Джош Келлі,

80

Що? Людина запитувала конкретний 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- це фактично ідентифікатор потоку (тобто беззнаковий довгий int, визначений у 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();

це, мабуть, не таке "незалежне від платформи", як ви думаєте. на моїй реалізації це вирішує a pthread_t. На mac, який буде вказівником, а на Linux цілим числом. Він також не відображає "рідний" ідентифікатор, який ви могли б бачити, topнаприклад. Щось, про що слід знати, але, можливо, це чудово для деяких цілей.
Бред Олред

1
У C11 (питання стосувалося C) ви б використовували thrd_current () з thread.h
jerry
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.