Heim >Betrieb und Instandhaltung >Betrieb und Wartung von Linux >Vertiefte Kenntnisse der Linux-Systemprogrammierung – (Pthread)-Thread-Erstellung und -Nutzung
Dieser Artikel vermittelt Ihnen Wissen über die Erstellung und Verwendung von Threads unter Linux. Ich hoffe, er wird Ihnen hilfreich sein.
Der Unterschied zwischen Threads und Prozessen (1) Prozess: Es ist die kleinste Einheit der Betriebssystemplanung. Unter Linux können Sie detaillierte Informationen zum Prozess über Befehle wie ps und top anzeigen. (2) Thread: Dies ist die kleinste Einheit der Prozessplanung. Jeder Prozess verfügt über einen Hauptthread. Das Wichtigste dabei ist der Thread.
(3) Im gesamten System ist die Prozess-ID die eindeutige Kennung, und die Verwaltung des Prozesses erfolgt über PID. Jedes Mal, wenn ein Prozess erstellt wird, erstellt der Kernel eine Struktur zum Speichern aller Informationen über den Prozess. Jeder Knoten, der Prozessinformationen speichert, speichert auch seine eigene PID. Wenn Sie den Prozess verwalten müssen, können Sie diese ID verwenden, um dies zu erreichen (z. B. das Senden eines Signals). Wenn der untergeordnete Prozess endet und recycelt werden muss (der untergeordnete Prozess ruft zum Beenden Exit () auf oder wird der Code ausgeführt), muss dies über den Systemaufruf wait () erfolgen. Der nicht recycelte tote Prozess wird zu einem Der Zombie-Prozess und seine Prozessentität existieren nicht mehr, belegen jedoch PID-Ressourcen, sodass eine Wiederverwertung erforderlich ist.
Wenn Sie für Threads aktiv beenden möchten, müssen Sie pthread_exit () aufrufen, und der Hauptthread muss pthread_join () aufrufen, um ihn wiederzuverwenden (vorausgesetzt, der Thread legt das „Ablösungsattribut“ nicht fest). Das Senden von Thread-Signalen wie Threads wird auch durch Thread-IDs erreicht
Kommunikationsmethoden zwischen Prozessen: A. Gemeinsamer Speicher B. Nachrichtenwarteschlange C. Semaphor D. Benannte Pipe E. Unbenannte Pipe F. Signal G. Datei H. Socket zwischen Threads Kommunikationsmethode : A. Mutex B. Spin-Lock C. Bedingungsvariable D. Lese-/Schreibsperre E. Thread-Signal F. Globale Variable
Die zwischen Prozessen verwendete Kommunikationsmethode erfordert entweder das Umschalten des Kernel-Kontexts oder den Zugriff auf Peripheriegeräte (named Pipe, Datei). Die Geschwindigkeit wird also langsamer sein. Wenn der Thread seine eigene einzigartige Kommunikationsmethode verwendet, wird er grundsätzlich in seinem eigenen Prozessraum abgeschlossen und es findet kein Wechsel statt, sodass die Kommunikationsgeschwindigkeit schneller ist. Mit anderen Worten: Zusätzlich zu den Unterschieden in der Art unterscheiden sich die zwischen Prozessen und Threads verwendeten Kommunikationsmethoden auch in der Geschwindigkeit.
Hinweis: Wenn ein Prozess, der mehrere Threads ausführt, ein Signal empfängt, wird nur der Hauptthread blockiert und andere untergeordnete Threads werden weiterhin ausgeführt, ohne dass dies Auswirkungen hat.
2.1 Threads erstellen
pthread_create ist eine Funktion zum Erstellen von Threads in Unix-Betriebssystemen (Unix, Linux usw.). Sie müssen beim Kompilieren die Linkbibliothek angeben: -lpthread-Funktionsprototyp
#include <pthread.h> int pthread_create ( pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg );
Parametereinführung
Der erste Parameter ist ein Zeiger auf die Thread-ID. Der zweite Parameter wird zum Festlegen von Thread-Eigenschaften verwendet. NULL kann standardmäßig ausgefüllt werden. Der dritte Parameter ist die Startadresse der Thread-Ausführungsfunktion. Der letzte Parameter ist der Parameter zum Ausführen der Funktion. Es sind keine Parameter erforderlich und NULL kann ausgefüllt werden. Funktionshilfe unter Linux anzeigen: # man pthread_create
Rückgabewert: Wenn der Thread erfolgreich erstellt wurde, wird 0 zurückgegeben. Wenn die Thread-Erstellung fehlschlägt, wird eine Fehlernummer zurückgegeben. Nachdem der Thread erfolgreich erstellt wurde, wird der Parameter attr verwendet, um verschiedene Thread-Attribute anzugeben. Der neu erstellte Thread beginnt mit der Ausführung von der Adresse der Funktion start_rtn. Diese Funktion verfügt nur über einen universellen Zeigerparameter arg. Wenn mehr als ein Parameter an die Thread-Arbeitsfunktion übergeben werden muss, müssen diese Parameter in eine Struktur eingefügt werden. und dann wird die Adresse dieser Struktur als arg-Parameter übergeben.
Beispiel:
#include <stdio.h> #include <pthread.h> //线程函数1 void *pthread_func1(void *arg) { while(1) { printf("线程函数1正在运行.....\n"); sleep(2); } } //线程函数2 void *pthread_func2(void *arg) { while(1) { printf("线程函数2正在运行.....\n"); sleep(2); } } int main(int argc,char **argv) { pthread_t thread_id1; pthread_t thread_id2; /*1. 创建线程1*/ if(pthread_create(&thread_id1,NULL,pthread_func1,NULL)) { printf("线程1创建失败!\n"); return -1; } /*2. 创建线程2*/ if(pthread_create(&thread_id2,NULL,pthread_func2,NULL)) { printf("线程2创建失败!\n"); return -1; } /*3. 等待线程结束,释放线程的资源*/ pthread_join(thread_id1,NULL); pthread_join(thread_id2,NULL); return 0; } //gcc pthread_demo_code.c -lpthread
2.2 Beenden des Threads
Der Thread beendet die Ausführung durch Aufrufen der Funktion pthread_exit, genau wie der Prozess die Exit-Funktion aufruft, wenn er endet. Die Funktion dieser Funktion besteht darin, den Thread, der sie aufruft, zu beenden und einen Zeiger auf ein Objekt zurückzugeben.
Die Funktion dieser Funktion besteht darin, den Thread, der sie aufruft, zu beenden und einen Zeiger auf ein Objekt zurückzugeben. Der Rückgabewert kann über den zweiten Parameter der Funktion pthread_join abgerufen werden.
Funktionsprototyp
#include <pthread.h> void pthread_exit(void *retval);
Parameteranalyse Die Rücksprungadresse des Threads. Hinweis: Der Thread-Stack muss freigegeben werden, wenn der Thread endet. Dies bedeutet, dass die Thread-Funktion zum Beenden pthread_exit () aufrufen muss. Andernfalls wird er erst freigegeben, wenn die Hauptprozessfunktion beendet wird
2.3 Warten Sie, bis der Thread endet
pthread_join()-Funktion, die blockierend auf die Thread-Spezifikation wartet Der Thread endet. Wenn die Funktion zurückkehrt, werden die Ressourcen des wartenden Threads zurückgefordert. Wenn der Thread beendet ist, kehrt die Funktion sofort zurück. Und der durch Thread angegebene Thread muss ein verknüpfbares Attribut (Kombinationsattribut) sein. Funktionsprototyp
#include <pthread.h> int pthread_join(pthread_t thread, void **retval);
Parameter Der erste Parameter: Thread-ID, also Thread-ID, identifiziert den eindeutigen Thread. Der letzte Parameter: ein benutzerdefinierter Zeiger, der zum Speichern der vom wartenden Thread zurückgegebenen Adresse verwendet wird. Ein Rückgabewert von 0 steht für Erfolg. Wenn dies fehlschlägt, wird eine Fehlernummer zurückgegeben. Beispiel für den Empfang eines Thread-Rückgabewerts:
//退出线程 pthread_exit ("线程已正常退出"); //接收线程的返回值 void *pth_join_ret1; pthread_join( thread1, &pth_join_ret1);
2.4 Thread-Trennungsattribut
创建一个线程默认的状态是joinable(结合属性),如果一个线程结束运行但没有调用pthread_join,则它的状态类似于进程中的Zombie Process(僵死进程),即还有一部分资源没有被回收(退出状态码),所以创建线程者应该pthread_join来等待线程运行结束,并可得到线程的退出代码,回收其资源(类似于进程的wait,waitpid)。但是调用pthread_join(pthread_id)函数后,如果该线程没有运行结束,调用者会被阻塞,在有些情况下我们并不希望如此。
pthread_detach函数可以将该线程的状态设置为detached(分离状态),则该线程运行结束后会自动释放所有资源。 函数原型
#include <pthread.h> int pthread_detach(pthread_t thread);
参数 线程标识符 返回值 0表示成功。错误返回错误码。 EINVAL线程并不是一个可接合线程。 ESRCH没有线程ID可以被发现。
2.5 获取当前线程的标识符
pthread_self函数功能是获得线程自身的ID。 函数原型
#include <pthread.h> pthread_t pthread_self(void);
返回值 当前线程的标识符。 pthread_t的类型为unsigned long int,所以在打印的时候要使用%lu方式,否则显示结果出问题。
2.6 自动清理线程资源
线程可以安排它退出时需要调用的函数,这样的函数称为线程清理处理程序。用于程序异常退出的时候做一些善后的资源清理。 在POSIX线程API中提供了一个pthread_cleanup_push()/pthread_cleanup_pop()函数用于自动释放资源。从pthread_cleanup_push()的调用点到pthread_cleanup_pop()之间的程序段中的终止动作(包括调用 pthread_exit()和异常终止)都将执行pthread_cleanup_push()所指定的清理函数。
注意:pthread_cleanup_push函数与pthread_cleanup_pop函数需要成对调用。 函数原型
void pthread_cleanup_push(void (*routine)(void *),void *arg); //注册清理函数 void pthread_cleanup_pop(int execute); //释放清理函数
参数 void (*routine)(void *) :处理程序的函数入口。 void *arg :传递给处理函数的形参。 int execute:执行的状态值。 0表示不调用清理函数。1表示调用清理函数。
导致清理函数调用的条件:
调用pthread_exit()函数
pthread_cleanup_pop的形参为1。 注意:return不会导致清理函数调用。
2.7 自动清理线程示例代码
#include <stdio.h> #include <pthread.h> #include <stdlib.h> //线程清理函数 void routine_func(void *arg) { printf("线程资源清理成功\n"); } //线程工作函数 void *start_routine(void *dev) { pthread_cleanup_push(routine_func,NULL); //终止线程 // pthread_exit(NULL); pthread_cleanup_pop(1); //1会导致清理函数被调用。0不会调用。 } int main(int argc,char *argv[]) { pthread_t thread_id; //存放线程的标识符 /*1. 创建线程*/ if(pthread_create(&thread_id,NULL,start_routine,NULL)!=0) { printf("线程创建失败!\n"); } /*2.设置线程的分离属性*/ if(pthread_detach(thread_id)!=0) { printf("分离属性设置失败!\n"); } while(1){} return 0; }
2.8 线程取消函数
pthread_cancel函数为线程取消函数,用来取消同一进程中的其他线程。
头文件: #include <pthread.h> 函数原型:pthread_cancel(pthread_t tid);
相关推荐:《Linux视频教程》
Das obige ist der detaillierte Inhalt vonVertiefte Kenntnisse der Linux-Systemprogrammierung – (Pthread)-Thread-Erstellung und -Nutzung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!