Leser wie Sie helfen, MUO zu unterstützen. Wenn Sie über Links auf unserer Website einen Kauf tätigen, erhalten wir möglicherweise eine Affiliate-Provision. Weiterlesen.

Unter Linux können Sie Threads in C/C++ mit der POSIX-Thread-Bibliothek (pthread) erstellen und verwalten. Im Gegensatz zu anderen Betriebssystemen gibt es in Linux kaum einen Unterschied zwischen einem Thread und einem Prozess. Aus diesem Grund bezeichnet Linux seine Threads oft als leichtgewichtige Prozesse.

Mit der pthread-Bibliothek können Sie Threads erstellen, auf ihre Beendigung warten und sie explizit beenden.

Die Geschichte der Thread-Nutzung unter Linux

Vor der Linux-Version 2.6 war die Haupt-Thread-Implementierung LinuxThreads. Diese Implementierung hatte erhebliche Einschränkungen in Bezug auf Leistung und Synchronisierungsvorgänge. Eine Begrenzung der maximalen Anzahl von Threads, die ausgeführt werden konnten, beschränkte sie auf 1000.

Im Jahr 2003 gelang es einem Team unter der Leitung von Entwicklern von IBM und RedHat, die

Native POSIX-Thread-Bibliothek (NPTL) Projekt verfügbar. Es wurde erstmals in RedHat Enterprise Version 3 eingeführt, um Leistungsprobleme mit der Java Virtual Machine unter Linux zu beheben. Heute enthält die GNU-C-Bibliothek Implementierungen beider Threading-Mechanismen.

Keines davon ist eine Implementierung grüner Threads, die eine virtuelle Maschine im reinen Benutzermodus verwalten und ausführen würde. Wenn Sie die pthread-Bibliothek verwenden, erstellt der Kernel bei jedem Programmstart einen Thread.

Thread-spezifische Informationen für jeden laufenden Prozess finden Sie in den Dateien unter /proc//task. Dies ist der Standardspeicherort für Prozessinformationen unter der procfs-Linux-Standard. Bei Single-Thread-Anwendungen scheint es, als gäbe es in diesem Verzeichnis einen Task-Datensatz mit dem gleichen Wert wie die PID.

Arbeitslogik von Threads

Threads sind wie Prozesse, die derzeit auf dem Betriebssystem ausgeführt werden. Bei Einprozessorsystemen (z. B. Mikrocontrollern) simuliert der Betriebssystemkern Threads. Dadurch können Transaktionen durch Slicing gleichzeitig ausgeführt werden.

Ein Single-Core-Betriebssystem kann nur einen Prozess gleichzeitig ausführen. Allerdings hinein Mehrkern- oder Mehrprozessorsysteme, können diese Prozesse gleichzeitig ablaufen.

Threaderstellung in C

Du kannst den... benutzen pthread_create Funktion zum Erstellen eines neuen Threads. Der pthread.h Header-Datei enthält ihre Signaturdefinition zusammen mit anderen Thread-bezogenen Funktionen. Threads verwenden denselben Adressraum und dieselben Dateideskriptoren wie das Hauptprogramm.

Die pthread-Bibliothek enthält auch die notwendige Unterstützung für Mutex- und Bedingungsoperationen, die für Synchronisationsoperationen erforderlich sind.

Wenn Sie die Funktionen der pthread-Bibliothek verwenden, müssen Sie sicherstellen, dass der Compiler die Gewinde Bibliothek in Ihre ausführbare Datei. Bei Bedarf können Sie den Compiler anweisen, mit der Bibliothek auf die Bibliothek zu verlinken -l Möglichkeit:

gcc-o prüfen test_thread.c -lpthread

Die Funktion pthread_create hat die folgende Signatur:

intpthread_create(pthread_t *Gewinde, konstpthread_attr_t *attr, Leere *(*start_routine)(Leere *), Leere *arg)

Es gibt 0 zurück, wenn die Prozedur erfolgreich ist. Wenn ein Problem auftritt, wird ein Fehlercode ungleich Null zurückgegeben. In der obigen Funktionssignatur:

  • Der Gewinde Parameter ist vom Typ pthread_t. Der erstellte Thread wird immer mit dieser Referenz zugänglich sein.
  • Der attr Mit dem Parameter können Sie ein benutzerdefiniertes Verhalten angeben. Sie können eine Reihe Thread-spezifischer Funktionen verwenden, beginnend mit pthread_attr_ um diesen Wert einzustellen. Mögliche Anpassungen sind die Planungsrichtlinie, die Stapelgröße und die Trennrichtlinie.
  • start_routine gibt die Funktion an, die der Thread ausführen wird.
  • Arg stellt eine generische Datenstruktur dar, die vom Thread an die Funktion übergeben wird.

Hier ist eine Beispielanwendung:

#enthalten
#enthalten
#enthalten
#enthalten

Leere *Arbeiter(Leere *Daten)
{
verkohlen *name = (verkohlen*)Daten;

für (int ich = 0; ich < 120; i++)
{
du schläfst(50000);
Druckf("Hallo vom Thread-Namen = %s\n", Name);
}

Druckf("Thread %s fertig!\n", Name);
zurückkehrenNULL;
}

inthauptsächlich(Leere)
{
pthread_t th1, th2;
pthread_create(&th1, NULL, Arbeiter, "X");
pthread_create(&th2, NULL, Arbeiter, "Y");
schlafen(5);
Druckf("Beenden des Hauptprogramms\n");
zurückkehren0;
}

Thread-Typen

Wenn ein Thread von der zurückkehrt hauptsächlich() Funktion in einer Anwendung, alle Threads werden beendet und das System gibt alle Ressourcen frei, die das Programm verwendet hat. Ebenso beim Beenden eines Threads mit einem Befehl wie an Ausfahrt(), beendet Ihr Programm alle Threads.

Mit dem pthread_join -Funktion können Sie stattdessen auf die Beendigung eines Threads warten. Der Thread, der diese Funktion verwendet, wird blockiert, bis der erwartete Thread beendet wird. Die Ressourcen, die sie vom System verwenden, werden nicht zurückgegeben, selbst in Fällen wie der Beendigung von beitretbaren Threads, die von der CPU nicht geplant sind oder sogar bei einem Scheitern der Teilnahme ptread_join.

Manchmal gibt es Situationen, in denen das Joinen mit pthread_join keinen Sinn macht; wenn zum Beispiel das Ende des Threads nicht vorhersehbar ist. In diesem Fall können Sie sicherstellen, dass das System alle Ressourcen automatisch an der Stelle zurückgibt, an der der Thread zurückkehrt.

Um dies zu erreichen, sollten Sie die entsprechenden Threads mit starten LOSGELÖST Status. Wenn Sie einen Thread beginnen, ABLÖSEN Der Status kann über einen Thread-Attributwert oder mit dem gesetzt werden pthread_detach Funktion:

intpthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
intpthread_detach(pthread_t Gewinde);

Hier ist ein Beispiel für die Verwendung von pthread_join(). Ersetzen Sie die Hauptfunktion im ersten Programm durch Folgendes:

inthauptsächlich(Leere)
{
pthread_t th1, th2;
pthread_create(&th1, NULL, Arbeiter, "X");
pthread_create(&th2, NULL, Arbeiter, "Y");
schlafen(5);
Druckf("Beenden des Hauptprogramms\n");
pthread_join (th1, NULL);
pthread_join (th2, NULL);
zurückkehren0;
}

Wenn Sie das Programm kompilieren und ausführen, lautet Ihre Ausgabe:

Hallo aus Thread Y
Hallo aus Thread X
Hallo aus Thread Y
...
Hallo aus Thread Y
Verlassen des Hauptprogramms
Hallo aus Thread X
...
Hallo aus Thread X
Thema X erledigt!
Hallo aus Thread Y
Thread Y fertig!

Thread-Beendigung

Sie können einen Thread mit einem Aufruf von pthread_cancel abbrechen und die entsprechende übergeben pthread_t Ausweis:

intpthread_cancel(pthread_t Gewinde);

Sie können dies im folgenden Code in Aktion sehen. Wieder nur die hauptsächlich Funktion ist anders:

inthauptsächlich(Leere)
{
pthread_t th1, th2;
pthread_create(&th1, NULL, Arbeiter, "X");
pthread_create(&th2, NULL, Arbeiter, "Y");
schlafen(1);
Druckf("> Thread abbrechen Y!!\n");
pthread_cancel (th2);
du schläfst(100000);
Druckf("> Thread X abbrechen!\n");
pthread_cancel (th1);
Druckf("Beenden des Hauptprogramms\n");
zurückkehren0;
}

Warum werden Threads erstellt?

Betriebssysteme versuchen immer, Threads auf einer oder mehreren CPUs auszuführen, entweder aus einer selbst erstellten Liste oder aus einer vom Benutzer erstellten Thread-Liste. Einige Threads können nicht ausgeführt werden, da sie auf ein Eingabe-/Ausgabesignal von der Hardware warten. Sie können auch freiwillig warten, auf eine Antwort von einem anderen Thread warten oder von einem anderen Thread blockiert werden.

Sie können die Ressourcen anpassen, die Sie Threads zuweisen, die Sie mit pthread erstellen. Dies kann eine benutzerdefinierte Planungsrichtlinie sein, oder Sie können bei Bedarf Planungsalgorithmen wie FIFO oder Round-Robin auswählen.