Hoe pthread_t af te drukken

Gezocht, maar geen bevredigend antwoord gevonden.

Ik weet dat er geen draagbare manier is om een ​​pthread_t af te drukken.

Hoe doe je dat in je app?

Bijwerken:

Eigenlijk heb ik geen pthread_t nodig, maar een kleine numerieke id, die in het foutopsporingsbericht verschillende threads identificeert.

Op mijn systeem (64-bits RHEL 5.3) is het gedefinieerd als unsigned long int, dus het is een groot aantal en alleen het printen neemt een waardevolle plaats in in de debug-regel. Hoe wijst gdbkorte getijden toe?


Antwoord 1, autoriteit 100%

Hiermee wordt een hexadecimale weergave van een pthread_tafgedrukt, ongeacht wat dat in werkelijkheid is:

void fprintPt(FILE *f, pthread_t pt) {
  unsigned char *ptc = (unsigned char*)(void*)(&pt);
  fprintf(f, "0x");
  for (size_t i=0; i<sizeof(pt); i++) {
    fprintf(f, "%02x", (unsigned)(ptc[i]));
  }
}

Om gewoon een kleine id voor elke pthread_taf te drukken, zou zoiets kunnen worden gebruikt (dit keer met iostreams):

void printPt(std::ostream &strm, pthread_t pt) {
  static int nextindex = 0;
  static std::map<pthread_t, int> ids;
  if (ids.find(pt) == ids.end()) {
    ids[pt] = nextindex++;
  }
  strm << ids[pt];
}

Afhankelijk van het platform en de feitelijke weergave van pthread_tkan het hier nodig zijn om een ​​operator<te definiëren voor pthread_t, omdat std::mapheeft een volgorde nodig op de elementen:

bool operator<(const pthread_t &left, const pthread_t &right) {
  ...
}

Antwoord 2, autoriteit 72%

GDB gebruikt de thread-id (ook bekend als kernel pid, ook bekend als LWP) voor korte nummers op Linux. Probeer:

 #include <syscall.h>
  ...
    printf("tid = %d\n", syscall(SYS_gettid));

Antwoord 3, autoriteit 49%

In dit geval hangt het af van het besturingssysteem, aangezien de POSIX-standaard vereist niet langer dat pthread_teen rekenkundig type is:

IEEE Std 1003.1-2001/Cor 2-2004, item XBD/TC2/D6/26 is toegepast, en voegt pthread_ttoe aan de lijst met typen die geen rekenkundige typen hoeven te zijn, waardoor pthread_tte definiëren als een structuur.

Je moet in je sys/types.hheader kijken en zien hoe pthread_tis geïmplementeerd; dan kunt u het afdrukken zoals u wilt. Aangezien er geen draagbare manier is om dit te doen en je niet zegt welk besturingssysteem je gebruikt, valt er niet veel meer te zeggen.

Bewerken:om uw nieuwe vraag te beantwoorden, GDB wijst zijn eigen thread-ID’s toe telkens wanneer een nieuwe thread wordt gestart:

Voor foutopsporingsdoeleinden associeert gdb zijn eigen threadnummer – altijd een enkel geheel getal – met elke thread in uw programma.

Als je een uniek nummer binnenin elke thread wilt afdrukken, is de meest eenvoudige optie waarschijnlijk om elke thread te vertellen welk nummer ze moeten gebruiken wanneer je eraan begint.


Antwoord 4, autoriteit 23%

OK, het lijkt erop dat dit mijn laatste antwoord is. We hebben eigenlijk 2 problemen:

  • Hoe krijg ik kortere unieke ID’s voor threads om te loggen.
  • Hoe dan ook, we moeten een echte pthread_t ID voor thread afdrukken (alleen om te linken naar POSIX-waarden tenminste).

1. POSIX-ID afdrukken (pthread_t)

Je kunt pthread_t gewoon behandelen als een reeks bytes met hexadecimale cijfers afgedrukt voor elke byte. U bent dus niet beperkt door een type met een vaste maat. Het enige probleem is de bytevolgorde. U vindt het waarschijnlijk prettig als de volgorde van uw afgedrukte bytes hetzelfde is als voor eenvoudig “int” afgedrukt. Hier is een voorbeeld voor little-endian en alleen de volgorde moet worden teruggedraaid (onder definitie?) voor big-endian:

#include <pthread.h>
#include <stdio.h>
void print_thread_id(pthread_t id)
{
    size_t i;
    for (i = sizeof(i); i; --i)
        printf("%02x", *(((unsigned char*) &id) + i - 1));
}
int main()
{
    pthread_t id = pthread_self();
    printf("%08x\n", id);
    print_thread_id(id);
    return 0;
}

2. Krijg een kortere afdrukbare thread-ID

In elk van de voorgestelde gevallen moet u de echte thread-ID (posix) vertalen naar de index van een tabel. Maar er zijn 2 significant verschillende benaderingen:

2.1. Volg discussielijnen.

Je kunt de thread-ID van alle bestaande threads in de tabel volgen (hun pthread_create()-aanroepen moeten worden ingepakt) en een “overbelaste” id-functie hebben waarmee je alleen de tabelindex krijgt, niet de echte thread-ID. Dit schema is ook erg handig voor het debuggen van interne threads en het bijhouden van bronnen. Voor de hand liggend voordeel is een neveneffect van de traceer- / debug-faciliteit op threadniveau met toekomstige uitbreiding mogelijk. Nadeel is de vereiste om elke creatie / vernietiging van threads te volgen.

Hier is een voorbeeld van gedeeltelijke pseudocode:

pthread_create_wrapper(...)
{
   id = pthread_create(...)
   add_thread(id);
}
pthread_destruction_wrapper()
{
   /* Main problem is it should be called.
      pthread_cleanup_*() calls are possible solution. */
   remove_thread(pthread_self());
}
unsigned thread_id(pthread_t known_pthread_id)
{
  return seatch_thread_index(known_pthread_id);
}
/* user code */
printf("04x", thread_id(pthread_self()));

2.2. Registreer gewoon een nieuwe thread-ID.

Tijdens het loggen roept u pthread_self() aan en zoekt u in de interne tabel als deze een thread kent.
Als een thread met zo’n ID is gemaakt, wordt de index ervan gebruikt (of hergebruikt van een eerdere thread, eigenlijk maakt het niet uit, want er zijn geen 2 dezelfde ID’s voor hetzelfde moment). Als de thread-ID nog niet bekend is, wordt er een nieuw item gemaakt, zodat een nieuwe index wordt gegenereerd / gebruikt.

Voordeel is eenvoud. Nadeel is het niet volgen van het aanmaken/vernietigen van threads. Dus om dit bij te houden is een aantal externe mechanica vereist.


Antwoord 5, autoriteit 10%

Op Centos 5.4 x86_64 is pthread_t een typedef voor een unsigned long.

Daarom zouden we dit kunnen doen…

#include <iostream>
#include <pthread.h>
int main() {
    pthread_t x;
    printf("%li\n", (unsigned long int) x);
    std::cout << (unsigned long int) x << "\n";
}

Antwoord 6, autoriteit 8%

Je zou zoiets als dit kunnen doen:

int thread_counter = 0;
pthread_mutex_t thread_counter_lock = PTHREAD_MUTEX_INITIALIZER;
int new_thread_id() {
    int rv;
    pthread_mutex_lock(&thread_counter_lock);
    rv = ++thread_counter;
    pthread_mutex_unlock(&thread_counter_lock);
    return rv;
}
static void *threadproc(void *data) {
    int thread_id = new_thread_id();
    printf("Thread %d reporting for duty!\n", thread_id);
    return NULL;
}

Als je erop kunt vertrouwen dat je GCC hebt (clang werkt ook in dit geval), kun je ook dit doen:

int thread_counter = 0;
static void *threadproc(void *data) {
    int thread_id = __sync_add_and_fetch(&thread_counter, 1);
    printf("Thread %d reporting for duty!\n", thread_id);
    return NULL;
}

Als uw platform dit ondersteunt, een vergelijkbare optie:

int thread_counter = 0;
int __thread thread_id = 0;
static void *threadproc(void *data) {
    thread_id = __sync_add_and_fetch(&thread_counter, 1);
    printf("Thread %d reporting for duty!\n", thread_id);
    return NULL;
}

Dit heeft het voordeel dat je thread_id niet hoeft te gebruiken in functie-aanroepen, maar het werkt niet b.v. op Mac OS.


7, Autoriteit 5%

Ik weet het, deze thread is erg oud. Na het lezen van alle bovenstaande berichten, wil ik nog een idee toevoegen om dit op een nette manier aan te pakken:
Als u sowieso in de MAPPING-business binnenkomt (pthread_to naar een int), kunt u net zo goed een stap verder gaan in de leesbaarheid. Maak je pthread_create_wrapper zodanig dat het ook een string duurt … de naam van de draad.
Ik heb geleerd deze “Setthreadname ()” -functie op Windows en Windows CE te waarderen.
Voordelen: Uw ID’s zijn niet alleen nummers, maar u ziet ook, welke van uw threads welk doel.


8, Autoriteit 3%

U kunt proberen het te converteren naar een niet-ondertekende korte en drukt u vervolgens precies de laatste vier hex-cijfers af. De resulterende waarde kan uniek genoeg zijn voor uw behoeften.


9

Zoals James hierboven vermeld, is de beste manier om naar de koptekst te kijken waar het type is gedefinieerd.

U vindt de definitie van pthread_t in pthreadtypes.h die te vinden is op:

/Usr/include/BITS/PTHREADTYPES.H

Other episodes