Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger

 << zurück
Linux-UNIX-Programmierung von Jürgen Wolf
Das umfassende Handbuch – 2., aktualisierte und erweiterte Auflage 2006
Buch: Linux-UNIX-Programmierung

Linux-UNIX-Programmierung
1216 S., mit CD, 49,90 Euro
Rheinwerk Computing
ISBN 3-89842-749-8
gp Kapitel 10 Threads
  gp 10.1 Unterschiede zwischen Threads und Prozessen
  gp 10.2 Thread-Bibliotheken
  gp 10.3 Kernel- und User-Threads
  gp 10.4 Scheduling und Zustände von Threads
  gp 10.5 Die grundlegenden Funktionen zur Thread–Programmierung
    gp 10.5.1 pthread_create – einen neuen Thread erzeugen
    gp 10.5.2 pthread_exit – einen Thread beenden
    gp 10.5.3 pthread_join – auf das Ende eines Threads warten
    gp 10.5.4 pthread_self – die ID von Threads ermitteln
    gp 10.5.5 pthread_equal – die ID von zwei Threads vergleichen
    gp 10.5.6 pthread_detach – einen Thread unabhängig machen
  gp 10.6 Die Attribute von Threads und das Scheduling
  gp 10.7 Threads synchronisieren
    gp 10.7.1 Mutexe
    gp 10.7.2 Condition-Variablen (Bedingungsvariablen)
    gp 10.7.3 Semaphore
    gp 10.7.4 Weitere Synchronisationstechniken im Überblick
  gp 10.8 Threads abbrechen (canceln)
  gp 10.9 Erzeugen von Thread-spezifischen Daten (TSD-Data)
  gp 10.10 pthread_once – Codeabschnitt einmal ausführen
  gp 10.11 Thread-safe (thread-sichere Funktionen)
  gp 10.12 Threads und Signale
  gp 10.13 Zusammenfassung und Ausblick


Rheinwerk Computing

10.5 Die grundlegenden Funktionen zur Thread–Programmierundowntop


Hinweis   Einen Hinweis gleich zu Beginn der Thread-Programmierung – alle Funktionen aus der pthread-Bibliothek geben bei Erfolg 0, ansonsten bei einem Fehler -1 zurück.



Rheinwerk Computing

10.5.1 pthread_create – einen neuen Thread erzeugedowntop

Einen neuen Thread kann man mit der Funktion pthread_create erzeugen:

#include <pthread. h.>
int pthread_create( pthread_t *thread, 
                    const pthread_attr_t *attribute,
                    void *(*funktion)(void *),
                    void *argumente );

Wenn Sie sich die Funktion betrachten, dürfte Ihnen die Ähnlichkeit zur Funktion clone() auffallen (siehe Manual Page), worauf sich pthread_create() unter Linux ja auch beruft. Jeder Thread bekommt eine eigene Identifikationsnummer (ID) vom Datentyp pthread_t, die in der Variablen des ersten Parameters thread abgelegt wird. Anhand dieser ID werden alle anderen Threads voneinander unterschieden. Mit dem zweiten Parameter attribute können Sie bei dem neu zu startenden Thread Attribute setzen wie die Priorität, die Stackgröße und noch einiges mehr. Auf die einzelnen Attribute wird noch eingegangen. Geben Sie hierfür NULL an, werden die Standardattribute für den Thread vorgenommen. Mit dem dritten Parameter geben Sie die »Funktion« für einen Thread selbst an. Hierbei geben Sie die Anfangsadresse einer Routine an, die der Thread verwenden soll. Wenn sich die hier angegebene Funktion beendet, bedeutet dies auch automatisch das Ende des Threads. Argumente, die Sie dem Thread mitgeben wollen, können Sie mit dem vierten Parameter argumente übergeben. Meistens wird dieser Parameter verwendet, um Daten an Threads zu übergeben. Hierzu wird in der Praxis häufig die Adresse einer Strukturvariablen herangezogen.

Nach dem Aufruf von pthread_create() kehrt diese Funktion sofort wieder zurück und fährt mit der Ausführung hinter pthread_create() fort. Der neu erzeugte Thread führt sofort asynchron seine Arbeit aus. Jetzt würden praktisch zwei Threads gleichzeitig ausgeführt, der Haupt-Thread und der neue Thread, der vom Haupt-Thread mit pthread_create() erzeugt wurde. Welcher der beiden Threads hierbei zunächst mit seiner Ausführung beginnt, ist nicht festgelegt (selbes Verhalten wie bei fork).


Rheinwerk Computing

10.5.2 pthread_exit – einen Thread beenden  downtop

Beenden können Sie einen Thread auf unterschiedliche Weise. Meistens werden Threads mit der Funktion pthread_exit() beendet:

#include <pthread. h.>
void pthread_exit( void * wert );

Diese Funktion beendet nur den Thread, indem Sie diese aufrufen. Mit dem Argument wert geben Sie den Exit-Status des Threads an. Diesen Status können Sie mit pthread_join() ermitteln (folgt in Kürze). Natürlich darf auch hierbei, wie eben C-üblich, der Rückgabewert kein lokales Speicherobjekt vom Thread sein, da dieses (wie eben bei Funktionen auch) nach der Beendigung des Threads nicht mehr gültig ist.

Neben der Möglichkeit, einen Thread mit pthread_exit() zu beenden, sind noch folgende Dinge zu beachten:

gp  Ruft ein beliebiger Thread die Funktion exit() auf, werden alle Threads, einschließlich des Haupt-Threads, beendet (also das komplette Programm). Genauso sieht dies aus, wenn Sie dem Prozess das Signal SIGTERM oder SIGKILL senden.
gp  Ein Thread, der mittels pthread_create() erzeugt wurde, lässt sich auch mit return [wert] beenden. Dies entspricht exakt dem Verhalten von pthread_exit(). Der Rückgabewert kann hierbei ebenfalls mit pthread_join() ermittelt werden.

Exit-Handler für Threads einrichten

Wenn Sie einen Thread beenden, können Sie auch einen Exit-Handler einrichten. Dies wird in der Praxis recht gerne verwendet, um z. B. temporäre Dateien zu löschen, Mutexe freizugeben oder eben sonstige »Reinigungsarbeiten« zu machen. Ein solcher eingerichteter Exit-Handler wird dann automatisch bei Beendigung eines Threads mit z. B. pthread_exit() oder return automatisch ausgeführt. Das Prinzip ist ähnlich, wie Sie es von der Standardbibliotheksfunktion atexit() kennen sollten. Auch hierbei werden bei mehreren Exit-Handlern die einzelnen Funktionen in umgekehrter Reihenfolge (da Stack) der Einrichtung ausgeführt. Hier die Funktionen dazu:

#include <pthread. h.>
void pthread_cleanup_push( void (*function)(void *),
                           void *arg );
void pthread_cleanup_pop( int exec );

Eine solche Funktion richten Sie also mit der Funktion pthread_cleanup_push() ein. Als ersten Parameter übergeben Sie dabei die Funktion, die ausführt werden soll, und als zweiten Parameter die Argumente für den Exit-Handler (falls nötig). Den zuletzt eingerichteten Exit-Handler können Sie wieder mit der Funktion pthread_cleanup_pop() vom Stack entfernen. Geben Sie allerdings einen Wert ungleich 0 als Parameter exec an, so wird diese Funktion zuvor noch ausgeführt, was bei einer Angabe von 0 nicht gemacht wird.

Etwas, was mich hier schon zur Weißglut gebracht hat, ist, dass die beiden Funktionen pthread_cleanup_push() und pthread_cleanup_pop() als Makros implementiert sind. Was nicht so schlimm wäre, wenn pthread_cleanup_push() eine sich öffnend geschweifte Klammer enthält und pthread_cleanup_pop() eine sich schließende. Dies bedeutet, Sie müssen beide Funktionen im selben Anweisungsblock ausführen. Daher müssen Sie immer ein _push und ein _pop verwenden, auch wenn Sie wissen, dass eine _pop-Stelle nie erreicht wird.


Rheinwerk Computing

10.5.3 pthread_join – auf das Ende eines Threads warten  downtop

Bevor Sie sich dem ersten Listing widmen können, benötigen Sie noch die Kenntnisse zur Funktion pthread_join().

#include <pthread. h.>
int pthread_join( pthread_t thread, void **thread_return );

pthread_join() hält den aufrufenden Thread (meistens den Haupt-Thread), der einen Thread mit pthread_create() erzeugt hat, so lange an, bis der Thread mit der ID thread vom Typ pthread_t beendet wurde. Der Exit-Status (bzw. Rückgabewert) des Threads wird an die Adresse von thread_return geschrieben. Sind Sie nicht am Rückgabewert interessiert, können Sie hier auch NULL verwenden. pthread_join() ist also das, was Sie bei den Prozessen mit waitpid() kennen.

Ein Thread, der sich beendet, wird eben so lange nicht »freigegeben« bzw. als beendeter Thread anerkannt, bis ein anderer Thread pthread_join() aufruft. Diesen Zusammenhang können Sie bei den Prozessen mit »Zombie-Prozessen« vergleichen. Daher sollte man für jeden erzeugten Thread einmal pthread_join() aufrufen, es sei denn, man hat einen Thread »abgehängt« (aber dazu in Kürze mehr).


Rheinwerk Computing

10.5.4 pthread_self – die ID von Threads ermitteln  downtop

Die Identifikationsnummer eines auszuführenden Threads können Sie sich mit der Funktion pthread_self() erfragen.

#include <pthread. h.>
pthread_t pthread_self(void);

Als Rückgabewert erhalten Sie die Thread-ID vom Datentyp pthread_t.

Hierzu soll nun ein einfaches Beispiel erstellt werden, das alle bisher vorgestellten Funktionen in klarer Weise demonstrieren soll.

/* thread1.c */
#include <stdio.h>
#include <stdlib.h>
#include <pthread. h.>
/* insg. MAX_THREADS Threads erzeugen */
#define MAX_THREADS 3
#define BUF 255
/* Einfache Daten für die Wertübergabe an den Thread */
struct data {
   int wert;
   char msg[BUF];
};
/* Ein einfacher Exit-Handler für Threads, der  *
 * pthread_cleanup_push und pthread_cleanup_pop *
 * in der Praxis demonstrieren soll             */ 
static void exit_handler_mem( void * arg ) {
   printf("\tExit-Handler aufgerufen ...");
   struct data *mem =  (struct data *)arg;
   /* Speicher freigeben */
   free(mem);
   printf("Speicher freigegeben\n");
}
/* Die Thread-Funktion */
static void mythread (void *arg) {
   struct data *f = (struct data *)arg;
   /* Exit-Handler einrichten - wird automatisch nach *
    * pthread_exit oder Thread-Ende aufgerufen        */
   pthread_cleanup_push( exit_handler_mem, (void*)f );
   /* Daten ausgeben */
   printf("\t-> Thread mit ID:%ld gestartet\n",
      pthread_self());
   printf("\tDaten empfangen: \n");
   printf("\t\twert = \"%d\"\n", f->wert);
   printf("\t\tmsg  = \"%s\"\n", f->msg);
   /* Den Exit-Handler entfernen, aber trotzdem ausführen, *
    * da als Angabe 1 anstatt 0 verwendet wurde           */
   pthread_cleanup_pop( 1 );
   /* Thread beenden - Als Rückgabewert Thread-ID verwenden.
    * Alternativ kann hierfür auch:
    * return(void) pthread_self();  
    * verwendet werden */
   pthread_exit((void *)pthread_self());
}
int main (void) {
   pthread_t th[MAX_THREADS];
   struct data *f;
   int i;
   static int ret[MAX_THREADS];
   /* Haupt-Thread gestartet */
   printf("\n-> Main-Thread gestartet (ID:%ld)\n",
      pthread_self());
   /* MAX_THREADS erzeugen */
   for (i = 0; i < MAX_THREADS; i++) {
      /* Speicher für Daten anfordern u. m. Werten belegen*/
      f = (struct data *)malloc(sizeof(struct data));
      if(f == NULL) {
         printf("Konnte keinen Speicher reservieren ...!\n");
         exit(EXIT_FAILURE);
      }
      /* Zufallszahl zwischen 1 und 10 (Spezial) */
      f->wert =  1+(int) (10.0*rand()/(RAND_MAX+1.0)); 
      snprintf (f->msg, BUF, "Ich bin Thread Nr. %d", i+1);
      /* Jetzt Thread erzeugen */
      if(pthread_create(&th[i], NULL, &mythread, f) != 0) {
         fprintf (stderr, "Konnte Thread nicht erzeugen\n");
         exit (EXIT_FAILURE);
      }
   }
   /* Auf das Ende der Threads warten */
   for( i=0; i < MAX_THREADS; i++)
      pthread_join(th[i], &ret[i]);
   /* Rückgabewert der Threads ausgeben */
   for( i=0; i < MAX_THREADS; i++)
       printf("<-Thread %ld ist fertig\n", ret[i]);
   /* Haupt-Thread ist jetzt auch fertig */
   printf("<- Main-Thread beendet (ID:%ld)\n", 
      pthread_self());
   return EXIT_SUCCESS;
}

Das Programm bei der Ausführung:

$ gcc -o thread1 thread1.c -lpthread
$ ./thread1
-> Main-Thread gestartet (ID:-1209412512)
        -> Thread mit ID:-1209414736 gestartet
        Daten empfangen:
                wert = "9"
                msg  = "Ich bin Thread Nr. 1"
        Exit-Handler aufgerufen ... Speicher freigegeben
        -> Thread mit ID:-1217807440 gestartet
        Daten empfangen:
                wert = "4"
                msg  = "Ich bin Thread Nr. 2"
        Exit-Handler aufgerufen ... Speicher freigegeben
        -> Thread mit ID:-1226200144 gestartet
        Daten empfangen:
                wert = "8"
                msg  = "Ich bin Thread Nr. 3"
        Exit-Handler aufgerufen ...Speicher freigegeben
<-Thread -1209414736 ist fertig
<-Thread -1217807440 ist fertig
<-Thread -1226200144 ist fertig
<- Main-Thread beendet (ID:-1209412512)

Hinweis am Rande   Bevor sich jemand über die Warnmeldung des Compilers wundert, noch ein Satz zum Casten von void *. In der Programmiersprache C ist ein Casten von oder nach void * nicht nötig. Aber wen die Warnmeldung stört, der kann dies gerne trotzdem nachholen.


Dieses Beispiel demonstriert auch auf einfache Weise, wie Sie Daten an einen neu erzeugten Thread übergeben können (hier mit der Struktur data). Ebenfalls gezeigt wurde hier die Verwendung eines Exit-Handlers, der nur den im Haupt-Thread angeforderten Speicherbereich freigibt. Zugegeben, das ließe sich auch im Thread »mythread« einfacher realisieren, aber zu Anschauungszwecken sind solch einfache Codebeispiele immer noch am besten. Im Beispiel wurden außerdem drei Threads »mythread« erzeugt, die im Prinzip alle dasselbe machen, nämlich eine einfache Ausgabe der Daten, die an die Threads übergeben wurden. Hierbei muss nochmals explizit darauf hingewiesen werden, dass die Ausführung, in welcher Reihenfolge die Threads starten, nicht vorgegeben ist, auch wenn dies hier einen anderen Anschein macht. Hierzu werden Synchronisationsmechanismen erforderlich. Jeder Thread wurde hier mit pthread_exit() und der eignen Thread-ID als Rückgabewert beendet. Genauso gut kann dies natürlich auch mit return gemacht werden. Der Rückgabewert von den einzelnen Threads wird im Haupt-Thread von pthread_join() erwartet und ausgegeben. Der Haupt-Thread beendet sich am Ende erst, wenn alle Threads fertig sind.

Würden Sie in diesem Beispiel pthread_join() weglassen, so würde sich der Haupt-Thread noch vor den anderen Threads beenden. Dies bedeutet, dass alle anderen Threads zwar noch laufen, aber auf nun nicht mehr gültige Strukturvariablen zugreifen würden.

Rückgabewert von Threads

Zwar wurde schon auf den Rückgabewert von Threads eingegangen, aber hierbei wurden nur Thread-spezifische Daten zurückgegeben (hier die Thread-ID). Aber genauso wie schon bei der Wertübergabe an Threads können Sie hierbei auch ganze Strukturen zurückgeben, was in der Praxis auch häufig so der Fall ist. Hierzu ein ähnliches Beispiel wie schon »thread1.c«, nur dass jetzt die Daten der Struktur aus dem Thread zurückgegeben und im Haupt-Thread mit pthread_join() »abgefangen« und anschließend ausgegeben werden. Auf die Verwendung eines Exit-Handlers wurde der Übersichtlichkeit halber zuliebe verzichtet.

/* thread2.c */
#include <stdio.h>
#include <stdlib.h>
#include <pthread. h.>
/* insg. MAX_THREADS Threads erzeugen */
#define MAX_THREADS 3
#define BUF 255
/* Einfache Daten für die Wertübergabe an den Thread */
struct data {
   int wert;
   char msg[BUF];
};
/* Die Thread-Funktion */
static void *mythread (void *arg) {
   struct data *f= (struct data *)arg;
   /* Zufallszahl zwischen 1 und 10 (Spezial) */
   f->wert =  1+(int) (10.0*rand()/(RAND_MAX+1.0)); 
   snprintf (f->msg, BUF, "Ich bin Thread Nr. %ld",
      pthread_self());
   /* Thread beenden - Als Rückgabewert Strukturdaten 
    * verwenden - Alternativ auch pthread_exit( f );  */
   return arg;
}
int main (void) {
   pthread_t th[MAX_THREADS];
   int i;
   struct data *ret[MAX_THREADS];
   /* Haupt-Thread gestartet */
   printf("\n-> Main-Thread gestartet (ID:%ld)\n",
      pthread_self());
   /* Speicher reservieren */
   for (i = 0; i < MAX_THREADS; i++){
      ret[i] = (struct data *)malloc(sizeof(struct data));
      if(ret[i] == NULL) {
         printf("Konnte keinen Speicher reservieren ...!\n");
         exit(EXIT_FAILURE);
      }
   }   
   /* MAX_THREADS erzeugen */
   for (i = 0; i < MAX_THREADS; i++) {
      /* Jetzt Thread erzeugen */
      if(pthread_create(&th[i],NULL,&mythread,ret[i]) !=0) {
         fprintf (stderr, "Konnte Thread nicht erzeugen\n");
         exit (EXIT_FAILURE);
      }
   }
   /* Auf das Ende der Threads warten */
   for( i=0; i < MAX_THREADS; i++)
      pthread_join(th[i], (void **)&ret[i]);
   /* Daten ausgeben */
   for( i=0; i < MAX_THREADS; i++) {
      printf("Main-Thread: Daten empfangen: \n");
      printf("\t\twert = \"%d\"\n", ret[i]->wert);
      printf("\t\tmsg  = \"%s\"\n", ret[i]->msg);
   }
   /* Haupt-Thread ist jetzt auch fertig */
   printf("<- Main-Thread beendet (ID:%ld)\n",
      pthread_self());
   return EXIT_SUCCESS;
}

Das Programm bei der Ausführung:

$ gcc -o thread2 thread2.c -lpthread
$ ./thread2
-> Main-Thread gestartet (ID:-1209412512)
Main-Thread: Daten empfangen:
                wert = "9"
                msg  = "Ich bin Thread Nr. -1209414736"
Main-Thread: Daten empfangen:
                wert = "4"
                msg  = "Ich bin Thread Nr. -1217807440"
Main-Thread: Daten empfangen:
                wert = "8"
                msg  = "Ich bin Thread Nr. -1226200144"
<- Main-Thread beendet (ID:-1209412512)

Rheinwerk Computing

10.5.5 pthread_equal – die ID von zwei Threads vergleichen  downtop

Um einen Thread mit einem anderen Thread zu vergleichen, kann die Funktion pthread_equal() verwendet werden. Dies wird häufig verwendet, um sicherzugehen, dass nicht ein Thread gleich derselbe ist. Ein Wert ungleich 0 wird zurückgegeben, wenn beide Threads gleich sind, und 0 wird zurückgegeben, wenn die Threads eine unterschiedliche Identifikationsnummer (ID) besitzen.

Das folgende Beispiel erzeugt drei Threads mit derselben »Funktion«, hierbei soll jeder Thread wiederum eine andere Aktion ausführen. Im Beispiel ist dies zwar nur die Ausgabe eines Textes, aber in der Praxis könnten Sie hierbei neue Funktionen aufrufen. Für die ersten drei Threads wird jeweils eine bestimmte Aktion festgelegt. Alle anderen Threads führen nur noch die else-Aktion aus. Dies ist z. B. sinnvoll, wenn Sie in Ihrer Anwendung Vorbereitungen treffen wollen (im Beispiel eben drei Vorbereitungen) so wie Dateien anlegen, Müll beseitigen, eine Server-Verbindung herstellen und noch vieles mehr. Sind diese Vorbereitungen getroffen, wird immer mit der gleichen Funktion fortgefahren. Damit der Vergleich von Threads mit pthread_equal() auch funktioniert, wurden die Thread-IDs, die beim Anlegen mit pthread_create() erzeugt worden sind, in globale Variablen gespeichert – und sind daher auch für alle Threads »sichtbar«. Hier das Beispiel, dessen Ausgabe eigentlich auch einiges erklärt.

/* thread3.c */
#include <stdio.h>
#include <stdlib.h>
#include <unistd. h.>
#include <pthread. h.>
#define MAX_THREADS 5
#define BUF 255
/* Globale Variable mit Thread-IDs *
 * für alle Threads sichtbar       */
static pthread_t th[MAX_THREADS];
static void aktion(void *name) {
   while( 1 ) {
      if(pthread_equal(pthread_self(),th[0])) {
         printf("\t->(%ld): Aufgabe \"abc\" Ausführen \n",
            pthread_self());
         break;
      }
      else if(pthread_equal(pthread_self(),th[1])) {
         printf("\t->(%ld): Aufgabe \"efg\" Ausführen \n",
            pthread_self());
         break;
      }
      else if(pthread_equal(pthread_self(),th[2])) {
         printf("\t->(%ld): Aufgabe \"jkl\" Ausführen \n",
            pthread_self());
         break;
      }
      else {
         printf("\t->(%ld): Aufgabe \"xyz\" Ausführen \n", 
            pthread_self());
         break;
      }
   }
   pthread_exit((void *)pthread_self());
}
int main (void) {
   int i;
   static int ret[MAX_THREADS];
   printf("->Haupt-Thread (ID:%ld) gestartet...\n",
      pthread_self());
   /* Threads erzeugen */
   for (i = 0; i < MAX_THREADS; i++) {
      if (pthread_create (&th[i],NULL,&aktion,NULL) != 0) {
         printf ("Konnte keinen Thread erzeugen\n");
         exit (EXIT_FAILURE);
      }
   }
   /* Auf die Threads warten */
   for (i = 0; i < MAX_THREADS; i++)
      pthread_join (th[i], &ret[i]);
   /* Rückgabe der Threads auswerten */
   for (i = 0; i < MAX_THREADS; i++)
      printf("\t<-Thread %ld mit Arbeit fertig\n", ret[i]);
   printf("->Haupt-Thread (ID:%ld) fertig ...\n", 
      pthread_self());
   return EXIT_SUCCESS;
}

Das Programm bei der Ausführung:

$ gcc -o thread3 thread3.c -lpthread
$ ./thread3
->Haupt-Thread (ID:-1209412512) gestartet...
        ->(-1209414736): Aufgabe "abc" Ausführen
        ->(-1217807440): Aufgabe "efg" Ausführen
        ->(-1226200144): Aufgabe "jkl" Ausführen
        ->(-1234592848): Aufgabe "xyz" Ausführen
        ->(-1242985552): Aufgabe "xyz" Ausführen
        <-Thread -1209414736 mit Arbeit fertig
        <-Thread -1217807440 mit Arbeit fertig
        <-Thread -1226200144 mit Arbeit fertig
        <-Thread -1234592848 mit Arbeit fertig
        <-Thread -1242985552 mit Arbeit fertig
->Haupt-Thread (ID:-1209412512) fertig ...

Sie können daran erkennen, dass die ersten drei Threads jeweils »abc«, »efg« und »jkl« ausführen. Alle noch folgenden Threads führen dann »xyz« aus. Zugegeben, das lässt sich eleganter mit den Synchronisationsmechanismen der Thread-Bibliothek lösen, aber das Beispiel demonstriert den Sachverhalt der Funktion pthread_equal() recht gut.


Rheinwerk Computing

10.5.6 pthread_detach – einen Thread unabhängig machen  toptop

Das Gegenteil von pthread_join() stellt die Funktion pthread_detach() dar. Mit dieser Funktion legen Sie fest, dass nicht mehr auf die Beendigung des Threads gewartet werden soll.

#include <pthread. h.>
int pthread_detach( pthread_t thread );

Sie lösen hiermit praktisch den Thread mit der ID thread von der Hauptanwendung los. Sie können diesen Vorgang gerne mit den Daemon-Prozessen vergleichen. Dass dieser Thread dann selbstständig ist, ist nichts Magisches, im Grunde »markieren« Sie den Thread damit nur, so dass bei seinem Beenden der Exit-Status und die Thread-ID gleich freigegeben werden. Ohne pthread_detach() würde dies erst der Fall nach einem pthread_join-Aufruf sein. Natürlich bedeutet die Verwendung von pthread_detach(), dass hierbei auch kein pthread_join() mehr auf das Ende des Threads reagiert.


Hinweis   Ein Thread, der mit pthread_detach() oder dem Attribut PTHREAD_CREATE_DETACHED von den anderen Threads losgelöst wurde, kann nicht mehr mit pthread_join() abgefangen werden. Der Thread läuft praktisch ohne äußere Kontrolle weiter.


Ein typischer Codeausschnitt, wie Sie einen Thread von den anderen loslösen können, sieht wie folgt aus:

pthread_t a_thread;
int ret;
...
/* Einen neuen Thread erzeugen */
ret = pthread_create( &a_thread, NULL, 
                      thread_function, NULL);
/* bei Erfolg den Thread abhängen ... */
if (ret == 0) {
   pthread_detach(a_thread);
}
 << zurück
  
  Zum Rheinwerk-Shop
Neuauflage: Linux-UNIX-Programmierung
Neuauflage:
Linux-UNIX-
Programmierung

bestellen
 Ihre Meinung?
Wie hat Ihnen das Openbook gefallen?
Ihre Meinung

 Buchtipps
Zum Rheinwerk-Shop: Linux-Server






 Linux-Server


Zum Rheinwerk-Shop: Das Komplettpaket LPIC-1 & LPIC-2






 Das Komplettpaket
 LPIC-1 & LPIC-2


Zum Rheinwerk-Shop: Linux-Hochverfügbarkeit






 Linux-
 Hochverfügbarkeit


Zum Rheinwerk-Shop: Shell-Programmierung






 Shell-
 Programmierung


Zum Rheinwerk-Shop: Linux Handbuch






 Linux Handbuch


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
Info





Copyright © Rheinwerk Verlag GmbH 2006
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern