Wie bekomme ich die Thread-ID eines Pthreads in einem Linux C-Programm?

85

Wie drucke ich im Linux C-Programm die Thread-ID eines von der pthread-Bibliothek erstellten Threads?
Zum Beispiel: Wir können einen Prozess durch bekommengetpid()

Ravi Chandra
quelle

Antworten:

78

pthread_self() Die Funktion gibt die Thread-ID des aktuellen Threads an.

pthread_t pthread_self(void);

Die pthread_self()Funktion gibt das Pthread-Handle des aufrufenden Threads zurück. Die Funktion pthread_self () gibt NICHT den integralen Thread des aufrufenden Threads zurück. Sie müssen verwenden pthread_getthreadid_np(), um einen integralen Bezeichner für den Thread zurückzugeben.

HINWEIS:

pthread_id_np_t   tid;
tid = pthread_getthreadid_np();

ist deutlich schneller als diese Aufrufe, bietet aber das gleiche Verhalten.

pthread_id_np_t   tid;
pthread_t         self;
self = pthread_self();
pthread_getunique_np(&self, &tid);
Abhitesh Khatri
quelle
36
Die ursprüngliche Frage betraf Linux. Linux enthält die _np-Funktionen nicht. (Es enthält nicht ihre Manpages, ich habe nicht weiter nachgesehen.)
Trade-Ideas Philip
pthread_threadid_np ist unter OS X> = 10.6 und iOS> = 3.2 verfügbar.
Bleater
@Bleater Können Sie bitte die offizielle Dokumentation für pthread_threadid_np. Ich muss für ein Projekt verwenden, muss also die Zuverlässigkeit dieser API auf iOS- und OSX-Plattformen überprüfen. Verweis auf den Link unter opensource.apple.com/source/Libc/Libc-583/pthreads/pthread.h, aber nicht sicher, ob sie die richtigen sind.
Vivek Maran
@Vivek Ich habe keinen Link zu offiziellen Dokumenten, nur den Header, den Sie verlinken, und die Quelle unter opensource.apple.com/source/Libc/Libc-583/pthreads/pthread.c
Bleater
9
@ Trade-IdeasPhilip - Zur Verdeutlichung _npbedeutet nicht tragbar. Linux hat seine eigenen _npSachen, aber keine von Apple pthread_getthreadid_np.
Josh Kelley
75

Was? Die Person fragte nach Linux-spezifisch und dem Äquivalent von getpid (). Nicht BSD oder Apple. Die Antwort lautet gettid () und gibt einen ganzzahligen Typ zurück. Sie müssen es mit syscall () wie folgt aufrufen:

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

 ....

 pid_t x = syscall(__NR_gettid);

Während dies möglicherweise nicht auf Nicht-Linux-Systeme portierbar ist, ist die Thread-ID direkt vergleichbar und sehr schnell zu erwerben. Es kann wie eine normale Ganzzahl gedruckt werden (z. B. für LOGs).

Evan Langlois
quelle
8
Dies sollte die richtige Antwort sein
Matthew S
Die Person fragte nach etwas, das unter Linux funktioniert. Dies auf tragbare Weise zu tun, scheint mir die bevorzugte Art zu sein, dies zu tun. Wenn Portabilität für nichts zählt, wird Linux wohl wirklich zum neuen Windows ...
Jasper Siepkes
2
@ Jasper Siepkes Sie verpassen den Punkt. Er bat um einen LINUX-Aufruf, der getpid () für Threads entsprach. Das ist gettid (). Bei der Frage ging es nicht um Portabilität oder POSIX. Zu viele Menschen möchten angeben und versuchen zu unterrichten, anstatt die gestellte Frage zu stellen. pthread_self () gibt die Kernel-Thread-ID nicht zurück und kann nicht so manipuliert werden, dass das Drucken vereinfacht wird. Außerdem ist pthread_self wahrscheinlich ein Zeiger und sollte nicht manipuliert werden, sondern nur im Vergleich zu pthread_equal (). Die Frage nach einer ID, die Sie drucken können, und das ist gettid ().
Evan Langlois
3
@EvanLanglois Er arbeitet mit der pthread-Bibliothek, buchstäblich der POSIX-Thread-Bibliothek. Eine POSIX-kompatible Antwort zu machen ist nicht so seltsam. "Er hat nach einem LINUX-Aufruf gefragt, der getpid () für Threads entspricht." Nein, getpid()wurde als Beispiel gegeben. Es wurde nicht gesagt, dass die Semantik eine harte Spezifikation war. Menschen darauf aufmerksam zu machen, Dinge auf POSIX-kompatible Weise zu tun, damit andere Communities außer Linux (wie FreeBSD, Illumos, OS X usw.) davon profitieren können, ist kein "Angeberei". Wie gesagt, ich denke, Linux ist wirklich das nächste Windows geworden.
Jasper Siepkes
12

Wie in anderen Antworten erwähnt, definiert pthreads keine plattformunabhängige Methode zum Abrufen einer integralen Thread-ID.

Auf Linux-Systemen können Sie die Thread-ID folgendermaßen abrufen:

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

Auf vielen BSD-basierten Plattformen bietet diese Antwort https://stackoverflow.com/a/21206357/316487 einen nicht portablen Weg.

Wenn Sie jedoch der Meinung sind, dass Sie eine Thread-ID benötigen, um zu wissen, ob Sie auf demselben oder einem anderen Thread als einem anderen von Ihnen kontrollierten Thread ausgeführt werden, finden Sie möglicherweise einen Nutzen in diesem Ansatz

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

Wenn Sie nur wissen müssen, ob Sie sich im Hauptthread befinden, gibt es zusätzliche Möglichkeiten, die in Antworten auf diese Frage dokumentiert sind. Wie kann ich feststellen, ob pthread_self der Hauptthread (der erste) im Prozess ist? .

Bleater
quelle
12
pid_t tid = syscall(SYS_gettid);

Linux bietet einen solchen Systemaufruf an, damit Sie die ID eines Threads erhalten.

Weiqi Gu
quelle
8

Sie können verwenden pthread_self()

Das übergeordnete pthread_create()Element lernt die Thread-ID kennen, nachdem das erfolgreich ausgeführt wurde. Wenn wir jedoch während der Ausführung des Threads auf die Thread-ID zugreifen möchten, müssen wir die Funktion verwenden pthread_self().

Jeff
quelle
6

Diese einzelne Zeile gibt Ihnen PID, jede Threadid und Spid.

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

pthread_getthreadid_npwar nicht auf meinem Mac OS X. pthread_tist ein undurchsichtiger Typ. Schlagen Sie nicht Ihren Kopf darüber. Weisen Sie void*es einfach zu und nennen Sie es gut. Wenn Sie printfverwenden %p.


quelle
1
Ja, das funktioniert. Ich muss es nur zum Debuggen drucken, damit 0x23423423423abcdef genauso hilfreich ist wie tid = 1234. Danke dir!
Qi Fan
3

Ich denke, nicht nur die Frage ist nicht klar, auch die meisten Menschen sind sich des Unterschieds nicht bewusst. Untersuche das folgende Sprichwort:

POSIX-Thread-IDs stimmen nicht mit den von Linux-spezifischen Thread-IDs zurückgegebenen Thread-IDs überein gettid() Systemaufruf zurückgegeben werden. POSIX-Thread-IDs werden von der Threading-Implementierung zugewiesen und verwaltet. Die von zurückgegebene Thread-ID gettid()ist eine Nummer (ähnlich einer Prozess-ID), die vom Kernel zugewiesen wird. Obwohl jeder POSIX-Thread eine eindeutige Kernel-Thread-ID in der Linux NPTL-Threading-Implementierung hat, muss eine Anwendung im Allgemeinen nicht über die Kernel-IDs Bescheid wissen (und ist nicht portierbar, wenn es darauf ankommt, sie zu kennen).

Auszug aus: Die Linux-Programmierschnittstelle: Ein Handbuch zur Linux- und UNIX-Systemprogrammierung, Michael Kerrisk

IMHO gibt es nur einen tragbaren Weg, der eine Struktur übergibt, in der eine Variable mit aufsteigenden Zahlen definiert wird, z 1,2,3... . B. pro Thread. Auf diese Weise kann die ID des Threads verfolgt werden. Trotzdem sollte die int pthread_equal(tid1, tid2)Funktion verwendet werden.

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
quelle
Das gettid()ist eigentlich ein guter Vorschlag, danke! Ich musste jedoch der Antwort von Sergey L. hier folgen: stackoverflow.com/a/21280941/2430526
SRG
1

Es gibt auch eine andere Möglichkeit, die Thread-ID abzurufen. Beim Erstellen von Threads mit

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

Funktionsaufruf; Der erste Parameter pthread_t * threadist tatsächlich eine Thread-ID (dh ein vorzeichenloses langes int, das in bits / pthreadtypes.h definiert ist). Auch das letzte Argumentvoid *arg ist auch das Argument, das an die zu übergebende void * (*start_routine)Funktion übergeben wird.

Sie können eine Struktur erstellen, um mehrere Argumente zu übergeben und einen Zeiger auf eine Struktur zu senden.

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 kann
quelle
-1

Sie können auch auf diese Weise schreiben und es tut das gleiche. Zum Beispiel:

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

Dieses Programm erstellt ein Array von pthread_t und berechnet jeweils die Summe. Es wird also die Summe jedes Threads mit der Thread-ID gedruckt.

Pranav Kumar
quelle
Die Frage wird nicht beantwortet, und selbst die Beschreibung des Codes ist falsch!
U. Windl
-2

Plattformunabhängiger Weg (ab C ++ 11) ist:

#include <thread>

std::this_thread::get_id();
Oleg Oleg
quelle
Dies ist wahrscheinlich nicht so "plattformunabhängig", wie Sie denken. Bei meiner Implementierung wird es in a aufgelöst pthread_t. Auf einem Mac ist das ein Zeiger und unter Linux eine Ganzzahl. Es spiegelt auch nicht die "native" ID wider, die Sie beispielsweise sehen könnten top. Etwas zu beachten, aber vielleicht ist es für einige Zwecke in Ordnung.
Brad Allred
1
In C11 (war die Frage nach C) würden Sie verwenden thrd_current () von threads.h
Jerry