comment obtenir l'ID de thread d'un pthread dans un programme linux c?

89

Dans le programme Linux C, comment imprimer l'ID de thread d'un thread créé par la bibliothèque pthread?
par exemple: on peut obtenir le pid d'un processus engetpid()

Ravi Chandra
la source

Réponses:

80

pthread_self() La fonction donnera l'identifiant du thread actuel.

pthread_t pthread_self(void);

La pthread_self()fonction renvoie le handle Pthread du thread appelant. La fonction pthread_self () ne renvoie PAS le thread intégral du thread appelant. Vous devez utiliser pthread_getthreadid_np()pour renvoyer un identificateur intégral pour le thread.

REMARQUE:

pthread_id_np_t   tid;
tid = pthread_getthreadid_np();

est nettement plus rapide que ces appels, mais offre le même comportement.

pthread_id_np_t   tid;
pthread_t         self;
self = pthread_self();
pthread_getunique_np(&self, &tid);
Abhitesh khatri
la source
37
La question initiale concernait Linux. Linux n'inclut pas les fonctions _np. (Cela n'inclut pas leurs pages de manuel, je n'ai pas vérifié plus loin que cela.)
Trade-Ideas Philip
pthread_threadid_np est disponible sur OS X> = 10.6 et iOS> = 3.2.
bleater
@Bleater Pouvez-vous s'il vous plaît fournir la documentation officielle pour pthread_threadid_np. J'ai besoin d'utiliser pour un projet, donc je dois vérifier la fiabilité de cette API sur les plates-formes iOS et OSX. J'ai référencé le lien sur opensource.apple.com/source/Libc/Libc-583/pthreads/pthread.h mais je ne sais pas si c'est le bon.
Vivek Maran
@Vivek Je n'ai aucun lien vers les documents officiels, juste l'en-tête que vous liez et la source à opensource.apple.com/source/Libc/Libc-583/pthreads/pthread.c
bleater
9
@ Trade-IdeasPhilip - Pour clarifier, _npsignifie non portable. Linux a ses propres _nptrucs, mais il n'inclut pas ceux d'Apple pthread_getthreadid_np.
Josh Kelley
81

Quelle? La personne a demandé des informations spécifiques à Linux et l'équivalent de getpid (). Pas BSD ou Apple. La réponse est gettid () et renvoie un type intégral. Vous devrez l'appeler en utilisant syscall (), comme ceci:

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

 ....

 pid_t x = syscall(__NR_gettid);

Bien que cela puisse ne pas être portable sur les systèmes non Linux, le threadid est directement comparable et très rapide à acquérir. Il peut être imprimé (comme pour les journaux) comme un entier normal.

Evan Langlois
la source
9
Cela devrait être la vraie réponse
Matthew S
La personne a posé des questions sur quelque chose qui fonctionnait sous Linux. Le faire de manière portable me semble être la meilleure façon de le faire. Si la portabilité ne compte pour rien, alors je suppose que Linux devient vraiment le nouveau Windows ...
Jasper Siepkes
2
@Jasper Siepkes Vous manquez le point. Il a demandé un appel LINUX qui était l'équivalent de getpid () pour les threads. C'est gettid (). La question ne portait pas sur la portabilité ou POSIX. Trop de gens veulent se montrer et essayer d'enseigner plutôt que de poser la question telle qu'elle est posée. pthread_self () ne retourne pas l'identifiant du thread du noyau et il n'est pas manipulable d'une manière qui facilite l'impression. De plus, pthread_self est probablement un pointeur et ne devrait pas être manipulé, uniquement comparé à pthread_equal (). La question demandait un identifiant que vous pouvez imprimer, et c'est gettid ().
Evan Langlois
3
@EvanLanglois Il travaille avec la bibliothèque pthread, littéralement la bibliothèque de threads POSIX. Faire une réponse compatible POSIX n'est pas si étrange. "Il a demandé un appel LINUX qui était l'équivalent de getpid () pour les threads." Non, a getpid()été donné à titre d'exemple. Il n'a pas dit que la sémantique était une spécification dure. Faire prendre conscience aux gens de faire les choses d'une manière compatible POSIX afin que d'autres communautés en dehors de Linux (comme FreeBSD, Illumos, OS X, etc.) puissent en bénéficier n'est pas "se faire valoir". Comme je l'ai dit, je suppose que Linux est vraiment devenu le prochain Windows.
Jasper Siepkes
14

Comme indiqué dans d'autres réponses, pthreads ne définit pas un moyen indépendant de la plate-forme de récupérer un ID de thread intégral.

Sur les systèmes Linux, vous pouvez obtenir l'ID de thread comme suit:

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

Sur de nombreuses plates-formes basées sur BSD, cette réponse https://stackoverflow.com/a/21206357/316487 donne un moyen non portable.

Cependant, si la raison pour laquelle vous pensez avoir besoin d'un ID de thread est de savoir si vous exécutez sur le même thread ou sur un autre thread que vous contrôlez, vous pouvez trouver un utilitaire dans cette approche

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

Si vous avez juste besoin de savoir si vous êtes sur le fil principal, il existe des moyens supplémentaires, documentés dans les réponses à cette question, comment puis-je savoir si pthread_self est le (premier) fil principal du processus? .

bleater
la source
12
pid_t tid = syscall(SYS_gettid);

Linux fournit un tel appel système pour vous permettre d'obtenir l'ID d'un thread.

Weiqi Gu
la source
9

Vous pouvez utiliser pthread_self()

Le parent apprend à connaître l'ID de thread après l' pthread_create()exécution réussie de l ', mais lors de l'exécution du thread si nous voulons accéder à l'ID de thread, nous devons utiliser la fonction pthread_self().

Jeff
la source
7

Cette seule ligne vous donne pid, chaque threadid et spid.

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

pthread_getthreadid_npn'était pas sur mon Mac os x. pthread_test un type opaque. Ne vous cognez pas la tête dessus. Attribuez-le simplement void*et dites-le bien. Si vous devez printfutiliser %p.


la source
1
Oui, cela fonctionne. Tout ce dont j'ai besoin est de l'imprimer pour le débogage, donc 0x23423423423abcdef est aussi utile que tid = 1234. Merci!
Qi Fan
3

Je pense que non seulement la question n'est pas claire, mais la plupart des gens ne sont pas non plus conscients de la différence. Examinez le dicton suivant,

Les ID de thread POSIX ne sont pas les mêmes que les ID de thread renvoyés par l' gettid()appel système spécifique à Linux . Les ID de thread POSIX sont attribués et conservés par l'implémentation de thread. L'ID de thread renvoyé par gettid()est un nombre (similaire à un ID de processus) attribué par le noyau.Bien que chaque thread POSIX ait un ID de thread de noyau unique dans l'implémentation de thread Linux NPTL, une application n'a généralement pas besoin de connaître les ID de noyau (et ne sera pas portable si cela dépend de leur connaissance).

Extrait de: The Linux Programming Interface: A Linux and UNIX System Programming Handbook, Michael Kerrisk

À mon humble avis, il n'y a qu'un seul moyen portable qui passe une structure dans laquelle définir une variable tenant des nombres de manière ascendante, par exemple 1,2,3... à par thread. En faisant cela, l'identifiant des threads peut être conservé. Néanmoins, la int pthread_equal(tid1, tid2)fonction doit être utilisée.

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
la source
C'est en gettid()fait une bonne suggestion, merci! Cependant, je devais suivre la réponse de Sergey L. ici: stackoverflow.com/a/21280941/2430526
SRG
1

Il existe également un autre moyen d'obtenir l'ID de thread. Lors de la création de fils avec

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

appel de fonction; le premier paramètre pthread_t * threadest en fait un identifiant de thread (c'est-à-dire un long int non signé défini dans bits / pthreadtypes.h). En outre, le dernier argument void *argest l'argument qui est passé à la void * (*start_routine)fonction à threader.

Vous pouvez créer une structure pour transmettre plusieurs arguments et envoyer un pointeur vers une structure.

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 peut
la source
-1

Vous pouvez également écrire de cette manière et cela fait de même. Par exemple:

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

Ce programme met en place un tableau de pthread_t et calcule la somme sur chacun. Donc, il imprime la somme de chaque thread avec l'ID de thread.

Pranav Kumar
la source
Cela ne répond pas à la question, et même la description du code est fausse!
U. Windl
-2

La méthode indépendante de la plate-forme (à partir de c ++ 11) est:

#include <thread>

std::this_thread::get_id();
Oleg Oleg
la source
ce n'est probablement pas aussi «indépendant de la plate-forme» que vous le pensez. sur ma mise en œuvre, il se résout à un pthread_t. Sur un mac qui sera un pointeur et sur Linux un entier. Il ne reflète pas non plus l'identifiant "natif" que vous pourriez voir toppar exemple. Quelque chose dont il faut être conscient, mais peut-être que c'est bien pour certaines utilisations.
Brad Allred
1
En C11 (la question concernait C), vous utiliseriez thrd_current () de threads.h
jerry