jak uzyskać identyfikator wątku pthread w programie Linux c?

89

W programie linux c, jak wydrukować identyfikator wątku utworzonego przez bibliotekę pthread?
na przykład: możemy uzyskać pid procesu przezgetpid()

Ravi Chandra
źródło

Odpowiedzi:

80

pthread_self() funkcja poda identyfikator wątku bieżącego wątku.

pthread_t pthread_self(void);

pthread_self()Funkcja zwraca uchwyt Pthread wątku wywołującego. Funkcja pthread_self () NIE zwraca integralnego wątku wątku wywołującego. Należy użyć, pthread_getthreadid_np()aby zwrócić integralny identyfikator dla wątku.

UWAGA:

pthread_id_np_t   tid;
tid = pthread_getthreadid_np();

jest znacznie szybszy niż te wywołania, ale zapewnia takie samo zachowanie.

pthread_id_np_t   tid;
pthread_t         self;
self = pthread_self();
pthread_getunique_np(&self, &tid);
Abhitesh khatri
źródło
37
Pierwotne pytanie dotyczyło Linuksa. Linux nie zawiera funkcji _np. (Nie zawiera ich stron podręcznika, nie sprawdzałem dalej.)
Trade-Ideas Philip
pthread_threadid_np jest dostępny na OS X> = 10.6 i iOS> = 3.2.
bleater
@Bleater Czy możesz podać oficjalną dokumentację dotyczącą pthread_threadid_np. Muszę korzystać z projektu, więc muszę sprawdzić niezawodność tego interfejsu API na platformach iOS i OSX. Skorzystałem z linku na opensource.apple.com/source/Libc/Libc-583/pthreads/pthread.h, ale nie byłem pewien, czy to właściwy.
Vivek Maran
@Vivek Nie mam żadnego linku do oficjalnych dokumentów, tylko nagłówek, do którego
linkujesz,
9
@ Trade-IdeasPhilip - aby wyjaśnić, _npoznacza nieprzenośny. Linux ma swoje własne _nprzeczy, ale nie obejmuje Apple pthread_getthreadid_np.
Josh Kelley
81

Co? Osoba zapytała o specyficzny dla Linuksa odpowiednik getpid (). Nie BSD ani Apple. Odpowiedzią jest gettid () i zwraca typ całkowity. Będziesz musiał wywołać to za pomocą syscall (), na przykład:

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

 ....

 pid_t x = syscall(__NR_gettid);

Chociaż może to nie być przenośne na systemy inne niż Linux, identyfikator wątku jest bezpośrednio porównywalny i bardzo szybki do uzyskania. Można go wydrukować (na przykład dla LOG) jak normalną liczbę całkowitą.

Evan Langlois
źródło
9
To powinna być prawdziwa odpowiedź
Matthew S
Osoba zapytała o coś, co działało w systemie Linux. Wydaje mi się, że zrobienie tego w sposób przenośny jest preferowanym sposobem. Jeśli przenośność się nie liczy, to myślę, że Linux naprawdę staje się nowym Windowsem ...
Jasper Siepkes,
2
@Jasper Siepkes Nie rozumiesz. Poprosił o wywołanie LINUX-a, które było odpowiednikiem getpid () dla wątków. To jest gettid (). Pytanie nie dotyczyło przenośności ani POSIX. Zbyt wiele osób chce się popisywać i próbować uczyć, zamiast zadawać zadane pytanie. pthread_self () nie zwraca identyfikatora wątku jądra i nie można nim manipulować w sposób ułatwiający drukowanie. Ponadto pthread_self jest prawdopodobnie wskaźnikiem i nie należy nim manipulować, a jedynie porównywać z pthread_equal (). Pytanie o identyfikator, który można wydrukować, to gettid ().
Evan Langlois
3
@EvanLanglois Pracuje z biblioteką pthread, dosłownie biblioteką wątków POSIX. Tworzenie odpowiedzi zgodnej z POSIX nie jest takie dziwne. „Poprosił o wywołanie LINUX-a, które było odpowiednikiem getpid () dla wątków”. Nie, getpid()podano jako przykład. Nie było powiedziane, że semantyka była twardą specyfikacją. Uświadomienie ludziom robienia rzeczy w sposób zgodny z POSIX, tak aby inne społeczności poza Linuksem (takie jak FreeBSD, Illumos, OS X itp.) Mogły z nich skorzystać, nie jest „popisywaniem się”. Tak jak powiedziałem, wydaje mi się, że Linux naprawdę stał się kolejnym Windowsem.
Jasper Siepkes
14

Jak zauważono w innych odpowiedziach, pthreads nie definiuje niezależnego od platformy sposobu pobierania integralnego identyfikatora wątku.

W systemach Linux można uzyskać identyfikator wątku w ten sposób:

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

Na wielu platformach opartych na BSD ta odpowiedź https://stackoverflow.com/a/21206357/316487 daje nieprzenośny sposób.

Jeśli jednak powodem, dla którego uważasz, że potrzebujesz identyfikatora wątku, jest wiedza, czy pracujesz w tym samym lub innym wątku z innym wątkiem, który kontrolujesz, możesz znaleźć narzędzie w tym podejściu

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

Jeśli chcesz tylko wiedzieć, czy jesteś w głównym wątku, istnieją dodatkowe sposoby, udokumentowane w odpowiedziach na to pytanie, w jaki sposób mogę stwierdzić, czy pthread_self jest głównym (pierwszym) wątkiem w procesie? .

bleater
źródło
12
pid_t tid = syscall(SYS_gettid);

Linux udostępnia takie wywołanie systemowe, które pozwala uzyskać identyfikator wątku.

Weiqi Gu
źródło
9

Możesz użyć pthread_self()

Rodzic poznaje identyfikator wątku po pthread_create()pomyślnym wykonaniu wątku, ale podczas wykonywania wątku, jeśli chcemy uzyskać dostęp do identyfikatora wątku, musimy użyć funkcji pthread_self().

Jeff
źródło
7

Ta pojedyncza linia podaje pid, każdy threadid i spid.

 printf("before calling pthread_create getpid: %d getpthread_self: %lu tid:%lu\n",getpid(), pthread_self(), syscall(SYS_gettid));
nandan
źródło
3

pthread_getthreadid_npnie było na moim Mac OS X. pthread_tjest nieprzezroczysty. Nie bij się tym głową. Po prostu przypisz to void*i nazwij to dobrze. Jeśli potrzebujesz printfużyć %p.


źródło
1
Tak, to działa. Wszystko, czego potrzebuję, to wydrukować go do debugowania, więc 0x23423423423abcdef jest tak pomocny jak tid = 1234. Dziękuję Ci!
Qi Fan,
3

Myślę, że nie tylko pytanie jest niejasne, ale większość ludzi również nie zdaje sobie sprawy z różnicy. Przeanalizuj następujące powiedzenie:

Identyfikatory wątków POSIX nie są takie same, jak identyfikatory wątków zwracane przez gettid()wywołanie systemowe specyficzne dla Linuksa . Identyfikatory wątków POSIX są przypisywane i obsługiwane przez implementację wątków. Identyfikator wątku zwracany przez gettid()to liczba (podobna do identyfikatora procesu) przypisywana przez jądro. Chociaż każdy wątek POSIX ma unikalny identyfikator wątku jądra w implementacji wątków NPTL Linuksa, aplikacja generalnie nie musi wiedzieć o identyfikatorach jądra (i nie będzie przenośna, jeśli zależy to od ich znajomości).

Fragment z: Interfejs programowania systemu Linux: Podręcznik programowania systemów Linux i UNIX, Michael Kerrisk

IMHO, istnieje tylko jeden przenośny sposób, który przekazuje strukturę, w której definiuje zmienną posiadającą numery w sposób rosnący, np. 1,2,3... Do każdego wątku. W ten sposób można śledzić identyfikator wątków. Niemniej jednak int pthread_equal(tid1, tid2)należy korzystać z funkcji.

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");
snr
źródło
To gettid()naprawdę dobra sugestia, dziękuję! Musiałem jednak postępować zgodnie z odpowiedzią Sergeya L. tutaj: stackoverflow.com/a/21280941/2430526
SRG
1

Istnieje również inny sposób uzyskania identyfikatora wątku. Podczas tworzenia wątków z

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

wywołanie funkcji; pierwszym parametrem pthread_t * threadjest w rzeczywistości identyfikator wątku (to jest długość int bez znaku zdefiniowana w bits / pthreadtypes.h). Ponadto ostatni argument void *argjest argumentem przekazywanym do void * (*start_routine)funkcji, która ma być wątkowana.

Możesz utworzyć strukturę, aby przekazać wiele argumentów i wysłać wskaźnik do struktury.

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
}
emre może
źródło
-1

Możesz też pisać w ten sposób i robi to samo. Na przykład:

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

Ten program ustawia tablicę pthread_t i oblicza sumę na każdym z nich. Więc wypisuje sumę każdego wątku z identyfikatorem wątku.

Pranav Kumar
źródło
Nie odpowiada na pytanie, a nawet opis kodu jest błędny!
U. Windl
-2

Sposób niezależny od platformy (zaczynając od C ++ 11) to:

#include <thread>

std::this_thread::get_id();
Oleg Oleg
źródło
prawdopodobnie nie jest to tak „niezależne od platformy”, jak myślisz. w mojej implementacji jest to plik pthread_t. Na komputerze Mac będzie to wskaźnik, aw systemie Linux liczbą całkowitą. Nie odzwierciedla również „natywnego” identyfikatora, który możesz zobaczyć topna przykład. Coś, o czym należy pamiętać, ale może w niektórych przypadkach jest w porządku.
Brad Allred,
1
W C11 (pytanie dotyczyło C) użyłbyś thrd_current () z wątków. H
jerry