[Linux C Multithreading] Erstellung von Threads, Erfassung von Thread-Informationen und Erfassung von Thread-Rückgabewerten

Thread-Erstellung

Inhalt der Spalte :

  • Santian Engine-Kernel-Architektur
    In dieser Kolumne sprechen wir über die Santian Engine-Kernel-Architektur und wie man Multi-Lesen und Multi-Schreiben von Multi-Maschinen-Datenbankknoten erreicht, den Unterschied zu herkömmlichen Aktiv- und Standby-Knoten, MPP, Analyse technischer Schwierigkeiten, Daten-Metadaten-Synchronisierung, Multi-Master. Unterstützung für Fehlerbehebung bei Knoten.

  • In dieser Kolumne werden hauptsächlich die Entwicklung der handgeschriebenen Datenbank toadb
    von Grund auf, die Entwicklungsschritte, die Prinzipien des Entwicklungsprozesses, die aufgetretenen Probleme usw. vorgestellt, damit alle mithalten und sich gemeinsam weiterentwickeln können, sodass jeder, der sie benötigt, dies tun kann Werden Sie Teilnehmer.
    Diese Spalte wird regelmäßig aktualisiert, und der entsprechende Code wird ebenfalls regelmäßig aktualisiert. Der Code in jeder Phase wird mit Tags versehen, um das Lernen in jeder Phase zu erleichtern.

Open- Source-Beiträge :

Persönliche Homepage : Meine Homepage
Management-Community : Open-Source-Datenbank
Motto: Wenn der Himmel stark ist, strebt ein Gentleman nach Selbstverbesserung; wenn das Gelände gut ist, trägt ein Gentleman große Tugenden.

Vorwort

Moderne CPUs sind alle Mehrkernprozessoren, und bei Intel-Prozessoren kann jeder Kern über mehrere Prozessoren verfügen und so eine Hardwarearchitektur für die parallele Verarbeitung mehrerer Aufgaben bilden. Die Architektur serverseitiger Prozessoren ist etwas anders. Traditionell ist SMP ein Bei der symmetrischen Multitasking-Architektur kann jede Aufgabe gleichermaßen auf alle Speicher, Peripheriegeräte usw. zugreifen. Heutzutage wird auf CPUs der ARM-Serie meist die NUMA-Architektur verwendet, die den CPU-Kern in mehrere Gruppen unterteilt. Entsprechender Speicher und Peripheriegeräte werden zugewiesen Der CPU-Kern jeder Gruppe. Wenn die CPU auf den entsprechenden Speicher und die entsprechenden Peripheriegeräte zugreift, ist die Geschwindigkeit optimal. Beim gruppenübergreifenden Zugriff ist die Leistung geringer.

Mit der kontinuierlichen Weiterentwicklung der Hardwaretechnologie wird ihre Fähigkeit, die Leistung allgemeiner Anwendungen zu optimieren, immer stärker. Gleichzeitig werden höhere Anforderungen an die Entwicklung von Serversoftware gestellt. Wenn Sie eine extrem hohe Parallelität und Leistung erreichen möchten Sie müssen die Eigenschaften der aktuellen Hardware-Architektur voll ausnutzen und sie komprimieren. Dann muss unsere Anwendung zumindest eine Multitasking-Architektur übernehmen, sei es eine Multi-Thread- oder Multi-Prozess-Multitasking-Architektur, damit sie die Hardwareressourcen voll ausnutzen und effiziente Verarbeitungsfunktionen erreichen kann.

Natürlich geht es bei der Einführung eines Multitasking-Frameworks nicht nur um die Ausführung von Multithreads, sondern auch um die Bewältigung der durch Multitasking verursachten Probleme, z. B. das Erhalten des Rückgabewerts der Aufgabenausführung und die Übertragung von Daten zwischen Aufgaben , und die Reihenfolge der Aufgabenausführung koordinieren; natürlich handelt es sich nicht um eine Aufgabe. Je mehr Verarbeitung, desto schneller. Es ist notwendig, zu verhindern, dass zu viele Threads das Betriebssystem zum Erliegen bringen, und um zu verhindern, dass Aufgaben zu schnell im Leerlauf laufen , was zu einem Anstieg der CPU-Auslastung führt.

In dieser Kolumne wird hauptsächlich vorgestellt, wie ein Multitasking-Anwendungsframework mithilfe von Multithreading- und Multiprozessmodellen erstellt wird, und es werden auch verwandte Kenntnisse über Datenkommunikation, Datensynchronisierung, Aufgabensteuerung sowie CPU-Kern- und Aufgabenbindung unter Multitasking vermittelt dass jeder ganz einfach sein eigenes Multitasking-Programm in der tatsächlichen Entwicklung erstellen kann.

Überblick

In diesem Artikel werden hauptsächlich die Erstellung und Beendigung von Multithreads sowie die Einstellung von Thread-Attributen, die Rückgabe von Thread-Ausführungen und andere verwandte Posix-APIs sowie Prozesse beschrieben.

Beim Aufbau einer Multitasking-Architektur wird häufig Multithreading verwendet, da Threads im Vergleich zu Prozessen leichte Aufgaben sind und auch die kleinsten Aufgabeneinheiten darstellen. Ein weiterer wichtiger Punkt ist, dass die Kommunikationsmethode zwischen Threads flexibler und bequemer ist, die Kommunikation zwischen Prozessen muss sich auf Kernel-Mittel verlassen.

Der Thread-Nutzungsprozess umfasst hauptsächlich das Erstellen und Starten von Threads, das Beenden von Threads, die Erfassung des Rückgabewerts von Thread-Aufgaben, die Verwaltung von Thread-Informationen usw.

Unter Linux verwenden wir zur Einführung die Posix-Thread-Bibliothek, die beim Kompilieren hinzugefügt -lpthreadund die Header-Datei eingebunden werden muss # include <pthread.h>.

Einführung in Threads

Wir wissen bereits, dass ein Thread eine leichte Aufgabeneinheit ist. Er wird in einem Prozess erstellt und teilt den Speicherkontext des aktuellen Prozesses. Das heißt, der Thread steht unter der Kontrolle des Prozesses. Wenn der Prozess nicht existiert, Der Thread wird beendet. Dies bedeutet: „Wenn die Haut weg ist, werden die Haare daran befestigt.“

Ein weiteres wichtiges Merkmal ist das Thread-Speichermodell. Alle Threads im selben Prozess teilen sich den Speicherplatz des aktuellen Prozesses. Dies bedeutet, dass die Änderungen globaler Variablen durch verschiedene Threads füreinander sichtbar sind und der vom dynamischen Speicher beanspruchte Speicher berücksichtigt werden kann kann auch gesehen werden. werden aneinander übergeben und lokale statische Variablen werden ebenfalls gemeinsam genutzt.

Erstelle einen Thread

Um einen Thread unter Linux zu erstellen, müssen Sie den Thread-Deskriptor, die Aufgabenausführungsfunktion des Threads und seine Eingabeparameter angeben. Natürlich können Sie auch die Attribute des Threads festlegen.

  • Funktion zum Erstellen eines Threads
#include <pthread.h>
int pthread_create(pthread_t *restrict thread,
                          const pthread_attr_t *restrict attr,
                          void *(*start_routine)(void *),
                          void *restrict arg);
  • Parameterbeschreibung
    thread , Thread-Deskriptor, Thread-Satz-ID aufzeichnen;

attr, Thread-Attribute können das Thread-Verhalten steuern;

start_routine, die vom Thread ausgeführte Hauptfunktion; das Deklarationsformat istvoid * func(void *pointer);

arg, Eingabeparameter der Hauptfunktion. Da die Hauptfunktion automatisch vom Thread-Scheduler aufgerufen wird, müssen die Parameter beim Erstellen angegeben werden.

Thread verlassen

Der Thread kann auf folgende Weise beendet werden:

  • Der start_routine-Thread führt die Funktion aus und kehrt normal zurück. Beispielsweise wird return ausgeführt, wenn die Funktion abgeschlossen ist.
  • Rufen Sie die Thread-Exit-Funktion pthread_exit auf, was dem frühen Beenden der Ausführungsfunktion entspricht.
  • Verwenden Sie die Thread-Steuerungsfunktion pthread_cancel, um einen Thread beenden zu lassen.
  • Der Prozess, in dem sich der Thread befindet, wird beendet oder Exit aufgerufen oder die Hauptfunktion main kehrt zurück, was dazu führt, dass alle Threads unter dem Prozess beendet werden.

Rückgabewert abrufen

Nach dem Ende der Thread-Ausführung gibt es oft einen Rückgabewert. Der Aufrufer muss anhand des Rückgabewerts entscheiden, welche Aufgabe ausgeführt werden soll. Wie erhalte ich den Rückgabewert der Thread-Ausführungsfunktion?

Die Beziehung zwischen Threads im selben Prozess ist gleich. Solange Sie die Identität des Threads kennen, können Sie den Rückgabewert der anderen Partei abrufen, indem Sie die folgende Funktion aufrufen.

#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);
  • Parameterbeschreibung
    thread, Thread-Identifikation, wird beim Erstellen eines Threads abgerufen;

retval, Rückgabecode; zurückgegeben von pthread_exit oder return;

  • Bedienungsanleitung

Der Aufrufer wird nach dem Aufruf dieser Funktion blockiert, bis der durch Thread identifizierte Thread zurückkehrt.

Thread-Informationen

Nachdem der Thread erstellt wurde, kann der Aufrufer nicht nur die Thread-Identität erhalten, sondern auch der Thread selbst kann über die Funktion seine eigene Identität erhalten.

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

Beispielcode

Speicherort des Beispielcodes

multipleThreads/example_01

threadCreate.c
Makefile 

Code wie folgt anzeigen:

/* 
 * created by senllang 2023/12/24 
 * mail : [email protected] 
 * Copyright (C) 2023-2023, senllang
 */
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>


void *thread(void *arg) 
{
    
    
  char *ret;
  printf("thread() entered with argument '%s'\n", arg);
  if ((ret = (char*) malloc(20)) == NULL) 
  {
    
    
    perror("malloc() error");
    exit(2);
  }

  strcpy(ret, "This is a test");
  pthread_exit(ret);
}

int main(int argc, char *argv[]) 
{
    
    
  pthread_t thid;
  void *ret;

  if (pthread_create(&thid, NULL, thread, "thread 1") != 0) 
  {
    
    
    perror("pthread_create() error");
    exit(1);
  }

  if (pthread_join(thid, &ret) != 0) 
  {
    
    
    perror("pthread_create() error");
    exit(3);
  }

  printf("thread exited with '%s'\n", ret);
}

Beim Kompilieren müssen Sie die Thread-Bibliothek lpthread hinzufügen. Die laufenden Ergebnisse lauten wie folgt:

[senllang@hatch example_01]$ ll
total 8
-rw-r--r--. 1 senllang develops 1265 Dec 24 20:32 Makefile
-rw-r--r--. 1 senllang develops  781 Dec 24 20:33 threadCreate.c
[senllang@hatch example_01]$ make
gcc  -I./ -DTEST_PRO -lpthread -g -c threadCreate.c
gcc  -I./ -DTEST_PRO -lpthread -g *.o -o hatch-0-01
[senllang@hatch example_01]$ ll
total 40
-rwxr-xr-x. 1 senllang develops 21368 Dec 24 20:34 hatch-0-01
-rw-r--r--. 1 senllang develops  1265 Dec 24 20:32 Makefile
-rw-r--r--. 1 senllang develops   781 Dec 24 20:33 threadCreate.c
-rw-r--r--. 1 senllang develops  7600 Dec 24 20:34 threadCreate.o
[senllang@hatch example_01]$ ./hatch-0-01 
thread() entered with argument 'thread 1'
thread exited with 'This is a test'

Zusammenfassen

Dieser Artikel konzentriert sich auf die gemeinsame Nutzung der Erstellung und Verwendung von Threads. Im Wesentlichen müssen Sie auf das Ende des Threads warten, da es sich um den Hauptthread des aktuellen Prozesses handelt. Wenn er vorzeitig endet, werden auch alle von ihm erstellten Threads beendet früh, daher muss gewartet werden, bis alle Threads beendet sind. Erst dann können Sie den Vorgang beenden.

Später werden wir weiterhin mehr Wissen über Threads einführen und die Funktion eines allgemeinen Thread-Pools vervollständigen.

Die Codes aller Beispiele wurden auf gitcode in das Projekt hatchCode hochgeladen . Wenn Sie interessiert sind, können Sie auf den Stern klicken, um zu folgen.

Ende

Vielen Dank für Ihre Unterstützung. Vergessen Sie nicht, beim Stöbern Ihre wertvollen Kommentare zu hinterlassen. Wenn Sie der Meinung sind, dass es eine Ermutigung wert ist, liken Sie es bitte und speichern Sie es. Ich werde härter arbeiten!

E-Mail des Autors: [email protected]
Wenn es Fehler oder Auslassungen gibt, weisen Sie bitte darauf hin und lernen Sie voneinander.

おすすめ

転載: blog.csdn.net/senllang/article/details/135186478