Werden Threads unter Linux als Prozesse implementiert?

65

Ich gehe dieses Buch durch , Advanced Linux Programming von Mark Mitchell, Jeffrey Oldham und Alex Samuel. Es ist von 2001, also ein bisschen alt. Aber ich finde es trotzdem ganz gut.

Ich habe jedoch einen Punkt erreicht, an dem es von dem abweicht, was mein Linux in der Shell-Ausgabe erzeugt. Auf Seite 92 (116 im Viewer) beginnt das Kapitel 4.5 GNU / Linux-Thread-Implementierung mit dem Absatz, der diese Anweisung enthält:

Die Implementierung von POSIX-Threads unter GNU / Linux unterscheidet sich in einem wichtigen Punkt von der Thread-Implementierung auf vielen anderen UNIX-ähnlichen Systemen: Unter GNU / Linux werden Threads als Prozesse implementiert.

Dies scheint ein wichtiger Punkt zu sein und wird später mit einem C-Code veranschaulicht. Die Ausgabe im Buch ist:

main thread pid is 14608
child thread pid is 14610

Und in meinem Ubuntu 16.04 ist es:

main thread pid is 3615
child thread pid is 3615

ps Ausgabe unterstützt dies.

Ich denke, zwischen 2001 und jetzt muss sich etwas geändert haben.

Das nächste Unterkapitel auf der nächsten Seite, 4.5.1 Signalbehandlung, baut auf der vorherigen Anweisung auf:

Das Verhalten der Interaktion zwischen Signalen und Threads variiert von einem UNIX-ähnlichen System zum anderen. In GNU / Linux wird das Verhalten durch die Tatsache bestimmt, dass Threads als Prozesse implementiert werden.

Und es sieht so aus, als würde dies später in diesem Buch noch wichtiger werden. Könnte jemand erklären, was hier los ist?

Ich habe dieses gesehen. Sind Linux-Kernel-Threads wirklich Kernel-Prozesse? , aber es hilft nicht viel. Ich bin verwirrt.

Dies ist der C-Code:

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

void* thread_function (void* arg)
{
    fprintf (stderr, "child thread pid is %d\n", (int) getpid ());
    /* Spin forever. */
    while (1);
    return NULL;
}

int main ()
{
    pthread_t thread;
    fprintf (stderr, "main thread pid is %d\n", (int) getpid ());
    pthread_create (&thread, NULL, &thread_function, NULL);
    /* Spin forever. */
    while (1);
    return 0;
}
Tomasz
quelle
1
Ich verstehe nicht, woher Ihre Verwirrung stammt. Threads werden als Prozesse implementiert, die den Adressraum mit ihrem übergeordneten Element gemeinsam nutzen.
Johan Myréen
2
@ JohanMyréen Also warum sind die Thread Pids gleich?
Tomasz
Ah, jetzt verstehe ich. Ja, etwas hat sich wirklich geändert. Siehe @ ilkkachus Antwort.
Johan Myréen
5
Threads werden weiterhin als Prozesse implementiert. Sie geben jedoch jetzt getpideine sogenannte Threadgruppen-ID zurück und erhalten eine eindeutige ID für einen Prozess, den Sie verwenden müssen gettid. Mit Ausnahme des Kernels bezeichnen die meisten Benutzer und Tools eine Thread-Gruppe als Prozess und einen Prozess als Thread, um die Konsistenz mit anderen Systemen zu gewährleisten.
user253751
Nicht wirklich. Ein Prozess hat seinen eigenen Speicher und Datei - Deskriptoren, es nie einen Thread aufgerufen wird, so zu tun wäre , in Einklang mit den anderen Systemen.
reinierpost

Antworten:

50

Ich denke, dieser Teil der clone(2)Manpage kann den Unterschied bezüglich aufklären. die PID:

CLONE_THREAD (seit Linux 2.4.0-test8)
Wenn CLONE_THREAD festgelegt ist, wird das untergeordnete Element in dieselbe Threadgruppe wie der aufrufende Prozess gestellt.
Thread-Gruppen wurden in Linux 2.4 hinzugefügt, um den POSIX-Thread-Begriff einer Gruppe von Threads zu unterstützen, die eine einzelne PID gemeinsam nutzen. Intern ist diese gemeinsame PID die sogenannte Thread-Gruppen-ID (TGID) für die Thread-Gruppe. Seit Linux 2.4 geben Aufrufe von getpid (2) die TGID des Aufrufers zurück.

Der Ausdruck "Threads werden als Prozesse implementiert" bezieht sich auf das Problem von Threads, die in der Vergangenheit separate PIDs hatten. Grundsätzlich hatte Linux ursprünglich keine Threads innerhalb eines Prozesses, sondern nur separate Prozesse (mit separaten PIDs), die möglicherweise über gemeinsam genutzte Ressourcen wie virtuellen Speicher oder Dateideskriptoren verfügten. CLONE_THREADDurch die Trennung von Prozess-ID (*) und Thread-ID ähnelt das Linux-Verhalten eher anderen Systemen und den POSIX-Anforderungen in diesem Sinne. Obwohl das Betriebssystem technisch noch keine separaten Implementierungen für Threads und Prozesse hat.

Signalverarbeitung war ein weiterer Problembereich mit der alten Implementierung, dies wird ausführlicher in dem beschriebenen Papier @FooF verweist in ihrer Antwort .

Wie in den Kommentaren vermerkt, wurde Linux 2.4 im selben Jahr wie das Buch auch im Jahr 2001 veröffentlicht. Es ist also nicht verwunderlich, dass die Nachrichten nicht in diesen Druck gelangten.

ilkkachu
quelle
2
Separate Prozesse, die möglicherweise über gemeinsam genutzte Ressourcen verfügen, z. B. virtueller Speicher oder Dateideskriptoren. So funktionieren Linux-Threads nach wie vor, und die von Ihnen erwähnten Probleme wurden behoben. Ich würde sagen, dass das Aufrufen der im Kernel verwendeten Planungseinheiten "Threads" oder "Prozesse" wirklich irrelevant ist. Die Tatsache, dass sie unter Linux nur "Prozesse" genannt wurden, bedeutet nicht, dass das alles ist, was sie jetzt sind.
Andrew Henle
@ AndrewHenle, ja, ein bisschen bearbeitet. Ich hoffe, dass dies Ihren Gedanken widerspiegelt, auch wenn mir die Formulierung schwer fällt. (Gehen Sie vor und bearbeiten Sie diesen Teil, wenn Sie möchten.) Ich habe verstanden, dass einige andere Unix-ähnliche Betriebssysteme eine deutlichere Trennung zwischen Threads und Prozessen aufweisen, wobei Linux eine Art Ausnahme darstellt, wenn nur wirklich ein Typ bereitgestellt wird beide Funktionen. Aber ich weiß nicht genug über andere Systeme und habe keine Quellen zur Hand, daher ist es schwierig, etwas Konkretes zu sagen.
ilkkachu
@tomas Beachten Sie, dass diese Antwort erklärt, wie Linux jetzt funktioniert. Wie Ilkkachu andeutet, funktionierte es anders, als das Buch geschrieben wurde. Die Antwort von FooF erklärt, wie Linux damals funktionierte.
Gilles 'SO- hör auf böse zu sein'
38

Sie haben Recht, tatsächlich "muss sich zwischen 2001 und jetzt etwas geändert haben". Das Buch, das Sie lesen, beschreibt die Welt gemäß der ersten historischen Implementierung von POSIX-Threads unter Linux, LinuxThreads genannt (siehe auch Wikipedia- Artikel für einige).

LinuxThreads hatte einige Kompatibilitätsprobleme mit dem POSIX-Standard - zum Beispiel Threads, die keine PIDs gemeinsam haben - und einige andere schwerwiegende Probleme. Um diese Fehler zu beheben, wurde von Red Hat eine weitere Implementierung mit dem Namen NPTL (Native POSIX Thread Library) eingeführt, die die Unterstützung für Kernel und User Space Library hinzufügt, um eine bessere POSIX-Kompatibilität zu erreichen. Next Generation Posix Threads "), siehe Wikipedia-Artikel zu NPTL ). Die zusätzlichen Flags, die dem clone(2)Systemaufruf hinzugefügt wurden (insbesondere CLONE_THREADdie @ikkkachuin seiner Antwort aufgeführten ), sind wahrscheinlich der offensichtlichste Teil der Kernelmodifikationen. Der User Space Teil der Arbeit wurde schließlich in die GNU C Library integriert.

Heutzutage verwenden einige eingebettete Linux-SDKs die alte LinuxThreads-Implementierung, da sie eine Version von uClibc (auch als µClibc bezeichnet) mit geringerem Speicherbedarf verwenden. Es dauerte einige Jahre, bis die NPTL-User-Space-Implementierung von GNU LibC als portiert und angenommen wurde Standardmäßige POSIX-Threading-Implementierung, da diese speziellen Plattformen im Allgemeinen nicht danach streben, blitzschnell den neuesten Moden zu folgen. Dies kann beobachtet werden, indem festgestellt wird, dass PIDs für verschiedene Threads auf diesen Plattformen auch anders sind als im POSIX-Standard angegeben - genau wie in dem Buch, das Sie gerade lesen. Eigentlich mal angerufenpthread_create()Sie hatten plötzlich die Prozessanzahl von eins auf drei erhöht, da zusätzlicher Prozess erforderlich war, um das Chaos zusammenzuhalten.

Die Handbuchseite zu Linux pthreads (7) bietet einen umfassenden und interessanten Überblick über die Unterschiede zwischen den beiden. Eine weitere aufschlussreiche, wenn auch veraltete Beschreibung der Unterschiede ist dieses Papier von Ulrich Depper und Ingo Molnar über das Design von NPTL.

Ich empfehle Ihnen, diesen Teil des Buches nicht zu ernst zu nehmen. Ich empfehle stattdessen Butenhofs Programmieren von POSIX-Threads sowie POSIX- und Linux-Handbuchseiten zu diesem Thema. Viele Tutorials zu diesem Thema sind ungenau.

FooF
quelle
22

(Userspace-) Threads werden unter Linux nicht als Prozesse implementiert, da sie keinen eigenen privaten Adressraum haben und dennoch den Adressraum des übergeordneten Prozesses gemeinsam nutzen.

Diese Threads sind jedoch so implementiert, dass sie das Kernel-Prozess-Abrechnungssystem verwenden. Sie erhalten daher eine eigene Thread-ID (TID), jedoch die gleiche PID und 'Thread-Gruppen-ID' (TGID) wie der übergeordnete Prozess. Dies steht im Gegensatz zu Eine Verzweigung, bei der eine neue TGID und PID erstellt werden und die TID mit der PID identisch ist.

Es scheint also, dass neuere Kernel eine separate TID hatten, die abgefragt werden kann. Dies ist für Threads unterschiedlich. Ein geeignetes Code-Snippet, um dies in jeder der obigen main () thread_function () anzuzeigen, lautet:

    long tid = syscall(SYS_gettid);
    printf("%ld\n", tid);

Also wäre der gesamte Code mit diesem Code:

#include <pthread.h>                                                                                                                                          
#include <stdio.h>                                                                                                                                            
#include <unistd.h>                                                                                                                                           
#include <syscall.h>                                                                                                                                          

void* thread_function (void* arg)                                                                                                                             
{                                                                                                                                                             
    long tid = syscall(SYS_gettid);                                                                                                                           
    printf("child thread TID is %ld\n", tid);                                                                                                                 
    fprintf (stderr, "child thread pid is %d\n", (int) getpid ());                                                                                            
    /* Spin forever. */                                                                                                                                       
    while (1);                                                                                                                                                
    return NULL;                                                                                                                                              
}                                                                                                                                                             

int main ()                                                                                                                                                   
{                                                                                                                                               
    pthread_t thread;                                                                               
    long tid = syscall(SYS_gettid);     
    printf("main TID is %ld\n", tid);                                                                                             
    fprintf (stderr, "main thread pid is %d\n", (int) getpid ());                                                    
    pthread_create (&thread, NULL, &thread_function, NULL);                                           
    /* Spin forever. */                                                                                                                                       
    while (1);                                                                                                                                                
    return 0;                                                                                                                                                 
} 

Geben Sie eine Beispielausgabe von:

main TID is 17963
main thread pid is 17963
thread TID is 17964
child thread pid is 17963
einonm
quelle
3
@tomas einonm ist richtig. Ignorieren Sie, was das Buch sagt, es ist schrecklich verwirrend. Keine Ahnung, welche Idee der Autor vermitteln wollte, aber er scheiterte schwer. Unter Linux gibt es also Kernel-Threads und User-Space-Threads. Kernel-Threads sind im Wesentlichen Prozesse ohne Benutzerbereich. User-Space-Threads sind normale POSIX-Threads. Benutzerbereichsprozesse verwenden Dateideskriptoren gemeinsam, können Codesegmente gemeinsam nutzen, befinden sich jedoch in vollständig getrennten virtuellen Adressräumen. Benutzerbereichsthreads in einem Prozess teilen Codesegment, statischen Speicher und Heap (dynamischer Speicher), haben jedoch separate Prozessorregistersätze und -stapel.
Boris Burkov
8

Grundsätzlich sind die Informationen in Ihrem Buch historisch korrekt, da die Implementierungshistorie von Threads unter Linux schändlich schlecht ist. Diese Antwort von mir auf eine verwandte Frage zu SO dient auch als Antwort auf Ihre Frage:

https://stackoverflow.com/questions/9154671/unterscheidung-zwischen-prozessen-und-threads-in-linux/9154725#9154725

Diese Verwirrungen rühren alle von der Tatsache her, dass die Kernel-Entwickler ursprünglich eine irrationale und falsche Ansicht vertraten, dass Threads unter Verwendung von Kernel-Prozessen als Grundelement fast vollständig im Benutzerbereich implementiert werden könnten, solange der Kernel eine Möglichkeit bietet, sie dazu zu bringen, Speicher und Dateideskriptoren gemeinsam zu nutzen . Dies führte zu der notorisch schlechten LinuxThreads-Implementierung von POSIX-Threads, die eher eine Fehlbezeichnung darstellte, da sie nichts enthielt, was der POSIX-Thread-Semantik im entferntesten ähnelte. Schließlich wurde LinuxThreads (durch NPTL) ersetzt, aber viele der verwirrenden Begriffe und Missverständnisse bestehen fort.

Das erste und wichtigste, was zu erkennen ist, ist, dass "PID" verschiedene Dinge im Kernelraum und im Benutzerraum bedeutet. Was der Kernel PIDs nennt, sind eigentlich Thread-IDs auf Kernel-Ebene (oft TIDs genannt), nicht zu verwechseln mit pthread_tdenen ein separater Bezeichner. Jeder Thread im System, egal ob im selben oder in einem anderen Prozess, hat eine eindeutige TID (oder "PID" in der Kernel-Terminologie).

Was als PID im POSIX-Sinne von "process" angesehen wird, wird im Kernel als "Thread-Gruppen-ID" oder "TGID" bezeichnet. Jeder Prozess besteht aus einem oder mehreren Threads (Kernel-Prozessen) mit jeweils einer eigenen TID (Kernel-PID), die sich jedoch alle dieselbe TGID teilen, die der TID (Kernel-PID) des ersten Threads entspricht, in dem der Prozess ausgeführt wird main.

Wenn topSie Threads anzeigen, werden TIDs (Kernel-PIDs) und nicht PIDs (Kernel-TGIDs) angezeigt. Aus diesem Grund hat jeder Thread einen eigenen Thread.

Mit dem Aufkommen von NPTL wurden die meisten Systemaufrufe, die ein PID-Argument annehmen oder auf den aufrufenden Prozess einwirken, geändert, um die PID als TGID zu behandeln und auf die gesamte "Thread-Gruppe" (POSIX-Prozess) einzuwirken.

R ..
quelle
8

Intern gibt es im Linux-Kernel keine Prozesse oder Threads. Prozesse und Threads sind meistens ein Userland-Konzept. Der Kernel selbst sieht nur "Tasks", dh ein planbares Objekt, das möglicherweise keine, einige oder alle Ressourcen mit anderen Tasks gemeinsam nutzt. Threads sind Tasks, die so konfiguriert wurden, dass sie die meisten Ressourcen (Adressraum, MMAPs, Pipes, Open File Handler, Sockets usw.) für die übergeordnete Task freigeben. Prozesse sind Tasks, die so konfiguriert wurden, dass sie nur minimale Ressourcen für die übergeordnete Task freigeben .

Wenn Sie die Linux-API direkt verwenden ( clone () anstelle von fork () und pthread_create () ), können Sie viel flexibler festlegen, wie viele Ressourcen freigegeben oder nicht freigegeben werden sollen, und Sie können Aufgaben erstellen, die nicht vollständig a sind prozess noch voll ein thread. Wenn Sie diese Low-Level-Aufrufe direkt verwenden, ist es auch möglich, eine Aufgabe mit einer neuen TGID (die von den meisten Userland-Tools als Prozess behandelt wird) zu erstellen, die tatsächlich alle Ressourcen für die übergeordnete Aufgabe freigibt, oder umgekehrt Eine Aufgabe mit gemeinsam genutzter TGID (wird daher von den meisten Userland-Tools als Thread behandelt), die keine Ressource mit ihrer übergeordneten Aufgabe gemeinsam nutzt.

Während Linux 2.4 TGID implementiert, dient dies hauptsächlich der Ressourcenabrechnung. Viele Benutzer und Userspace-Tools finden es hilfreich, verwandte Aufgaben zu gruppieren und ihre Ressourcennutzung gemeinsam zu melden.

Die Implementierung von Tasks unter Linux ist viel flüssiger als die Prozesse und Threads, die die Userspace-Tools in der Welt darstellen.

Lüge Ryan
quelle
Das Papier @FooF verknüpfen eine Reihe von Punkten beschreibt , wo die Kernel - Prozesse und Threads als getrennte Einheiten (zB Signalverarbeitung und exec ()) zu berücksichtigen hat, so nach dem Lesen, würde ich nicht wirklich sagen , dass „es gibt keine solche als Prozesse oder Threads im Linux-Kernel. "
ilkkachu
5

Linus Torvalds erklärte 1996 in einem Posting der Kernel-Mailing-Liste, dass "sowohl Threads als auch Prozesse als 'Kontext der Ausführung' behandelt werden", was "nur ein Konglomerat des gesamten Zustands dieses CoE ist ... einschließlich Dinge wie CPU Status, MMU - Status, Berechtigungen und verschiedene Kommunikationsstatus (offene Dateien, Signalhandler usw.) ".

// simple program to create threads that simply sleep
// compile in debian jessie with apt-get install build-essential
// and then g++ -O4 -Wall -std=c++0x -pthread threads2.cpp -o threads2
#include <string>
#include <iostream>
#include <thread>
#include <chrono>

// how many seconds will the threads sleep for?
#define SLEEPTIME 100
// how many threads should I start?
#define NUM_THREADS 25

using namespace std;

// The function we want to execute on the new thread.
void threadSleeper(int threadid){
    // output what number thread we've created
    cout << "task: " << threadid << "\n";
    // take a nap and sleep for a while
    std::this_thread::sleep_for(std::chrono::seconds(SLEEPTIME));
}

void main(){
    // create an array of thread handles
    thread threadArr[NUM_THREADS];
    for(int i=0;i<NUM_THREADS;i++){
        // spawn the threads
        threadArr[i]=thread(threadSleeper, i);
    }
    for(int i=0;i<NUM_THREADS;i++){
        // wait for the threads to finish
        threadArr[i].join();
    }
    // program done
    cout << "Done\n";
    return;
}

Wie Sie sehen, erzeugt dieses Programm 25 Threads auf einmal, von denen jeder 100 Sekunden lang ruht und sich dann wieder dem Hauptprogramm anschließt. Nachdem alle 25 Threads das Programm wieder verbunden haben, ist das Programm abgeschlossen und wird beendet.

Unter Verwendung von sehen topSie 25 Instanzen des Programms "threads2". Aber kidna langweilig. Die Ausgabe von ps auwxist noch weniger interessant ... ABER ps -eLfwird ein bisschen aufregend.

UID        PID  PPID   LWP  C NLWP STIME TTY          TIME CMD
debian     689   687   689  0    1 14:52 ?        00:00:00 sshd: debian@pts/0  
debian     690   689   690  0    1 14:52 pts/0    00:00:00 -bash
debian    6217   690  6217  0    1 15:04 pts/0    00:00:00 screen
debian    6218  6217  6218  0    1 15:04 ?        00:00:00 SCREEN
debian    6219  6218  6219  0    1 15:04 pts/1    00:00:00 /bin/bash
debian    6226  6218  6226  0    1 15:04 pts/2    00:00:00 /bin/bash
debian    6232  6219  6232  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6233  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6234  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6235  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6236  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6237  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6238  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6239  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6240  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6241  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6242  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6243  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6244  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6245  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6246  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6247  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6248  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6249  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6250  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6251  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6252  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6253  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6254  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6255  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6256  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6232  6219  6257  0   26 15:04 pts/1    00:00:00 ./threads2
debian    6260  6226  6260  0    1 15:04 pts/2    00:00:00 ps -eLf

Hier sehen Sie alle 26 CoEs, die das thread2Programm erstellt hat. Sie haben alle dieselbe Prozess-ID (PID) und übergeordnete Prozess-ID (PPID), aber jede hat eine andere LWP-ID (Lightweight-Prozess). Die Anzahl der LWPs (NLWP) gibt an, dass es 26 CoEs gibt - das Hauptprogramm und die 25 davon gespawnte Threads.

ivanivan
quelle
Richtig, ein Thread ist nur ein leichter Prozess (LWP)
fpmurphy
2

Wenn es um Linux Prozesse kommt und Threads sind Art von derselben Sache. Was zu sagen ist , dass sie mit dem gleichen Systemaufruf erstellt werden: clone.

Wenn Sie darüber nachdenken, besteht der Unterschied zwischen Threads und Prozessen darin, in welchen Kernelobjekten das untergeordnete und das übergeordnete Element gemeinsam genutzt werden. Bei Prozessen ist es nicht viel: offene Dateideskriptoren, Speichersegmente, in die noch nichts geschrieben wurde, wahrscheinlich ein paar andere, an die ich auf Anhieb nicht denken kann. Bei Threads werden viel mehr Objekte gemeinsam genutzt, aber nicht alle.

Was Threads und Objekte unter Linux näher bringt, ist der unshareSystemaufruf. Kernel-Objekte, die als gemeinsam genutzt beginnen, können nach der Thread-Erstellung freigegeben werden. So können Sie beispielsweise zwei Threads desselben Prozesses mit unterschiedlichem Speicherplatz für Dateideskriptoren verwenden (indem Sie die gemeinsame Nutzung von Dateideskriptoren widerrufen, nachdem die Threads erstellt wurden). Sie können es selbst testen, indem Sie einen Thread erstellen, unsharebeide Threads aufrufen und dann alle Dateien schließen und neue Dateien, Pipes oder Objekte in beiden Threads öffnen. Dann schauen /proc/your_proc_fd/task/*/fdSie rein und Sie werden sehen, dass jede task(die Sie als Thread erstellt haben) unterschiedliche FDS hat.

Tatsächlich sind sowohl das Erstellen neuer Threads als auch neuer Prozesse Bibliotheksroutinen, die clonedarunter aufrufen und angeben, welches der Kernelobjekte das neu erstellte Prozess-Thread-Ding-amajig (dh task) für den aufrufenden Prozess / Thread freigibt .

Dmitry Rubanovich
quelle