web-dev-qa-db-de.com

Unterschied zwischen Threads auf Benutzerebene und von Kernel unterstützten Threads?

Ich habe ein paar Notizen zu diesem Thema durchgesehen, und obwohl ich ein Verständnis für Threads im Allgemeinen habe, bin ich mir über die Unterschiede zwischen Benutzerebene und Kernel nicht wirklich sicher Thread-Ebene .

Ich weiß, dass Prozesse im Wesentlichen aus mehreren Threads oder einem einzelnen Thread bestehen. Handelt es sich jedoch um einen Thread der beiden zuvor genannten Typen?

Soweit ich weiß, haben kernelgestützte Threads Zugriff auf den Kernel für Systemaufrufe und andere Verwendungen, die für Threads auf Benutzerebene nicht verfügbar sind.

Sind Threads auf Benutzerebene einfach vom Programmierer erstellte Threads, wenn dann kernelgestützte Threads verwendet werden, um Vorgänge auszuführen, die aufgrund ihres Status normalerweise nicht ausgeführt werden konnten?

59
Cail Demetri

Bearbeiten: Die Frage war etwas verwirrend, daher beantworte ich sie auf zwei verschiedene Arten.

OS-Level-Threads vs Green Threads

Der Klarheit halber sage ich normalerweise "Betriebssystem-Threads" oder "native Threads" anstelle von "Kernel-Threads" (die ich in meiner ursprünglichen Antwort unten mit "Kernel-Threads" verwechselt habe). Betriebssystem-Threads werden von erstellt und verwaltet das Betriebssystem. Die meisten Sprachen unterstützen sie. (C, aktuelles Java usw.) Sie sind äußerst schwer zu verwenden, da Sie zu 100% dafür verantwortlich sind, Probleme zu vermeiden. In einigen Sprachen werden sogar die nativen Datenstrukturen (wie Hashes oder Wörterbücher) ohne zusätzlichen Sperrcode beschädigt.

Das Gegenteil eines OS-Threads ist ein grüner Thread , der von Ihrer Sprache verwaltet wird. Diese Fäden erhalten je nach Sprache verschiedene Namen (Coroutinen in C, Goroutinen in Go, Fasern in Ruby usw.). Diese Threads existieren nur in Ihrer Sprache und nicht in Ihrem Betriebssystem. Da die Sprache Kontextwechsel auswählt (d. H. Am Ende einer Anweisung), werden TONS subtiler Race-Bedingungen (z. B. das Anzeigen einer teilweise kopierten Struktur oder das Sperren der meisten Datenstrukturen) verhindert. Der Programmierer sieht "blockierende" Aufrufe (d. H. data = file.read()), aber die Sprache übersetzt sie in asynchrone Aufrufe an das Betriebssystem. In der Sprache können dann other grüne Threads ausgeführt werden, während auf das Ergebnis gewartet wird.

Grüne Threads sind für den Programmierer viel einfacher, aber ihre Leistung variiert: Wenn Sie viele Threads haben, können grüne Threads sowohl für die CPU als auch für den RAM besser sein. Auf der anderen Seite können die meisten Sprachen für grüne Threads nicht mehrere Kerne nutzen. (Sie können nicht einmal mehr einen Single-Core-Computer oder ein Telefon kaufen!). Und eine fehlerhafte Bibliothek kann die gesamte Sprache anhalten, indem sie einen OS-Aufruf blockiert.

Das Beste aus beiden Welten ist, einen Betriebssystem-Thread pro CPU und viele grüne Threads zu haben, die auf magische Weise auf Betriebssystem-Threads verschoben werden. Sprachen wie Go und Erlang können das.

systemaufrufe und andere Verwendungen, die für Threads auf Benutzerebene nicht verfügbar sind

Dies ist nur zur Hälfte wahr. Ja, Sie können leicht Probleme verursachen, wenn Sie das Betriebssystem selbst anrufen (d. H. Etwas tun, das blockiert). Da die Sprache jedoch normalerweise Ersetzungen enthält, bemerken Sie dies nicht einmal. Diese Ersetzungen rufen den Kernel nur geringfügig anders auf, als Sie denken.

Kernel-Threads vs User-Threads

Bearbeiten: Dies ist meine ursprüngliche Antwort, aber es geht um User-Space-Threads gegen Kernel-only-Threads, die (im Nachhinein) wahrscheinlich nicht die Frage waren.

Benutzer- und Kernel-Threads sind genau gleich. (Sie können sehen, indem Sie in/proc/nachsehen, dass auch die Kernel-Threads vorhanden sind.)

Ein User-Thread ist ein Thread, der User-Space-Code ausführt. Es kann jedoch jederzeit in den Kernel-Space aufgerufen werden. Es wird immer noch als "Benutzer" -Thread betrachtet, obwohl es Kernel-Code mit erhöhten Sicherheitsstufen ausführt.

Ein Kernel-Thread führt nur Kernel-Code aus und ist keinem User-Space-Prozess zugeordnet. Dies sind wie "UNIX-Daemons", nur dass es sich um reine Kernel-Daemons handelt. Man könnte also sagen, dass der Kernel ein Multithread-Programm ist. Zum Beispiel gibt es einen Kernel-Thread zum Tauschen. Dadurch werden alle Auslagerungsprobleme gezwungen, in einem einzigen Stream "serialisiert" zu werden.

Wenn ein Benutzer-Thread etwas benötigt, ruft er den Kernel auf, der diesen Thread als inaktiv markiert. Später findet der Auslagerungs-Thread die Daten, sodass er den Benutzer-Thread als ausführbar markiert. Später kehrt der "Benutzer-Thread" vom Kernel zurück in das Benutzerland, als wäre nichts passiert.

Tatsächlich beginnen all Threads im Kernelraum, da die clone () - Operation im Kernelraum stattfindet. (Und es gibt eine Menge Kernel-Accounting zu tun, bevor Sie zu einem neuen Prozess im Benutzerbereich zurückkehren können.)

76

Bevor wir zum Vergleich übergehen, lassen Sie uns zunächst verstehen, was ein Thread ist. Threads sind einfache Prozesse im Bereich unabhängiger Prozesse. Sie sind erforderlich, weil Prozesse schwer sind, viel Ressourcen verbrauchen und vor allem

zwei separate Prozesse können sich keinen Speicherplatz teilen.

Angenommen, Sie öffnen einen Texteditor. Es ist ein unabhängiger Prozess, der im Speicher mit einem separaten adressierbaren Speicherort ausgeführt wird. Innerhalb dieses Prozesses benötigen Sie viele Ressourcen, z. B. Grafiken einfügen, Rechtschreibprüfungen usw. Es ist nicht möglich, für jede dieser Funktionen separate Prozesse zu erstellen und diese unabhängig voneinander im Speicher zu verwalten. Um es zu umgehen,

innerhalb eines Prozesses können mehrere Threads erstellt werden, die sich einen gemeinsamen Speicherbereich teilen, der unabhängig innerhalb eines Prozesses vorhanden ist.

Kommen wir nun nacheinander auf Ihre Fragen zurück.

Ich bin mir nicht sicher, was die Unterschiede zwischen Threads auf Benutzerebene und auf Kernelebene angeht.

Threads werden grob als Threads auf Benutzerebene und Kernel-Level-Threads basierend auf klassifiziert ihre Domäne der Ausführung. Es gibt auch Fälle, in denen ein oder mehrere Benutzerthreads einem oder mehreren Kernelthreads zugeordnet sind .

- User Level Threads

Threads auf Benutzerebene befinden sich meist auf Anwendungsebene, auf der eine Anwendung diese Threads erstellt, um ihre Ausführung im Hauptspeicher aufrechtzuerhalten. Sofern nicht erforderlich, arbeiten diese Threads isoliert mit Kernel-Threads.

Diese sind einfacher zu erstellen, da sie nicht auf viele Register verweisen müssen und die Kontextumschaltung viel schneller ist als ein Thread auf Kernel-Ebene.

Thread auf Benutzerebene kann meist Änderungen auf Anwendungsebene verursachen, und der Thread auf Kernelebene wird weiterhin in seinem eigenen Tempo ausgeführt.

- Kernel Level Threads

Diese Threads sind weitgehend unabhängig von den laufenden Prozessen und werden vom Betriebssystem ausgeführt.

Diese Threads werden vom Betriebssystem für Aufgaben wie Speicherverwaltung, Prozessverwaltung usw. benötigt.

Da diese Threads die vom Betriebssystem benötigten Prozesse verwalten, ausführen und melden. Das Erstellen und Verwalten von Kernel-Level-Threads ist teurer und das Wechseln des Kontexts dieser Threads ist langsam.

Die meisten Kernel-Level-Threads können von den User-Level-Threads nicht ausgeschlossen werden.

MS DOS written for Intel 8088 didn't have dual mode of operation. Thus, a user level process had the ability to corrupt the entire operating system.

- Threads auf Benutzerebene, die über Kernel-Threads zugeordnet sind

Dies ist vielleicht der interessanteste Teil. Viele Threads auf Benutzerebene sind Kernel-Threads zugeordnet, die wiederum mit dem Kernel kommunizieren.

Einige der wichtigsten Abbildungen sind:

Eins zu eins

Wenn ein Thread auf Benutzerebene nur einem Kernel-Thread zugeordnet ist.

vorteile: Jeder Benutzer-Thread ist einem Kernel-Thread zugeordnet. Auch wenn einer der Benutzer-Threads einen Systemaufruf blockiert, bleiben die anderen Prozesse davon unberührt.

nachteile: Jeder Benutzer-Thread benötigt einen Kernel-Thread für die Interaktion und die Erstellung und Verwaltung von Kernel-Threads ist teuer.

Viele zu Eins

Wenn viele Benutzer-Threads einem Kernel-Thread zugeordnet sind.

vorteile: Mehrere Kernel-Threads sind nicht erforderlich, da ähnliche Benutzer-Threads einem Kernel-Thread zugeordnet werden können.

nachteil: Selbst wenn einer der Benutzer-Threads einen Systemaufruf blockiert, werden alle anderen Benutzer-Threads, die diesem Kernel-Thread zugeordnet sind, blockiert.

Ein gutes Maß an Parallelität kann auch nicht erreicht werden, da der Kernel jeweils nur einen Kernel-Thread verarbeitet.

Viel zu viel

Wenn viele Benutzer-Threads der gleichen oder einer geringeren Anzahl von Kernel-Threads zugeordnet sind. Der Programmierer entscheidet, wie viele Benutzer-Threads wie vielen Kernel-Threads zugeordnet werden. Einige der Benutzer-Threads werden möglicherweise nur einem Kernel-Thread zugeordnet.

vorteile: ein hohes niveau an nebenläufigkeit wird erreicht. Der Programmierer kann einige potenziell gefährliche Threads bestimmen, die möglicherweise einen Systemaufruf blockieren, und sie mit der Eins-zu-Eins-Zuordnung platzieren.

nachteil: Die Anzahl der Kernel-Threads kann das System verlangsamen, wenn sie nicht vorsichtig entschieden werden.

Der andere Teil Ihrer Frage:

von Kernel unterstützte Threads haben Zugriff auf den Kernel für Systemaufrufe und andere Verwendungen, die für Threads auf Benutzerebene nicht verfügbar sind.

Sind Threads auf Benutzerebene einfach vom Programmierer erstellte Threads, wenn dann kernelgestützte Threads verwendet werden, um Vorgänge auszuführen, die aufgrund ihres Status normalerweise nicht ausgeführt werden konnten?

Teilweise richtig. Fast alle Kernel-Threads haben Zugriff auf Systemaufrufe und andere kritische Interrupts, da Kernel-Threads für die Ausführung der Prozesse des Betriebssystems verantwortlich sind. Der Benutzer-Thread hat keinen Zugriff auf einige dieser wichtigen Funktionen. z.B. Ein Texteditor kann niemals einen Thread erstellen, der die physikalische Adresse des Prozesses ändern kann. Bei Bedarf kann ein Benutzer-Thread dem Kernel-Thread zugeordnet werden und einige der Systemaufrufe ausgeben, die er als unabhängige Entität nicht ausführen kann. Der Kernel-Thread ordnet diesen Systemaufruf dann dem Kernel zu und führt Aktionen aus, falls dies für geeignet erachtet wird.

15
Yusuf Hassan

Einige Entwicklungsumgebungen oder -sprachen fügen eigene Threads hinzu, z. B. Features, die zur Ausnutzung von Umgebungskenntnissen geschrieben wurden. Beispielsweise kann eine GUI-Umgebung einige Thread-Funktionen implementieren, mit denen zwischen Benutzerthreads in jeder Ereignisschleife gewechselt wird. Eine Spielebibliothek könnte ein Thread-ähnliches Verhalten für Charaktere aufweisen. Manchmal kann das Benutzer-Thread-ähnliche Verhalten auf eine andere Weise implementiert werden, zum Beispiel arbeite ich viel mit Kakao, und es hat einen Timer-Mechanismus, der Ihren Code alle x Anzahl von Sekunden ausführt, Sekundenbruchteile verwendet und es wie ein Thread. Ruby hat eine Ertragsfunktion, die kooperativen Threads ähnelt. Der Vorteil von Benutzer-Threads ist, dass sie zu vorhersehbareren Zeiten wechseln können. Mit Kernel-Thread muss ein Thread bei jedem Neustart neu geladen werden Daten, an denen gearbeitet wurde, dies kann einige Zeit dauern. Bei Benutzer-Threads können Sie wechseln, wenn Sie mit der Arbeit an einigen Daten fertig sind, sodass sie nicht neu geladen werden müssen. Ich bin nicht auf Benutzer-Threads gestoßen, die wie der Kernel aussehen Threads, nur Thread-ähnliche Mechanismen wie der Timer, obwohl ich sie in älteren Lehrbüchern gelesen habe, und ich frage mich, ob sie in der Vergangenheit populärer waren, aber mit dem Aufkommen echter Multithread-Betriebssysteme (modernes Windows und Mac OS X) und leistungsstärkere Hardware Ich frage mich, ob sie in Ungnade gefallen sind.

2
Nathan Day

Der Unterschied zwischen User-Threads und Kernel-Threads

ser-Threads

  • Kann auf jedem Betriebssystem ausgeführt werden
  • Die Threadverwaltung erfolgt über die Threadbibliothek
  • Kernel ist sich der Existenz von Threads nicht bewusst
  • Die Thread-Bibliothek enthält Code zum Erstellen und Löschen von Threads
  • Dies sind die Threads, die Anwendungsprogrammierer in ihren Programmen verwenden

Kernel-Threads

  • Speziell für das Betriebssystem
  • Thread-Verwaltung durch den Kernel
  • Es gibt keinen Thread-Management-Code im Anwendungsbereich
  • Wird direkt vom Betriebssystem unterstützt
  • Wenn ein Thread in einem Prozess blockiert ist, kann der Kernel einen anderen Thread desselben Prozesses planen
  • Kernel-Threads sind im Allgemeinen langsamer zu erstellen und zu verwalten als die Benutzer-Threads
0

benutzer-Threads: 1. Die Bibliothek bietet Unterstützung für das Erstellen, Planen und Verwalten von Threads ohne Unterstützung durch den Kernel. 2. Der Kernel, der die Erstellung und Planung von Threads auf Benutzerebene nicht kennt, wird im Benutzerbereich ausgeführt, ohne dass der Kernel eingreift. 3. Thread auf Benutzerebene sind im Allgemeinen schnell zu erstellen und zu verwalten, haben jedoch Nachteile. 4. Wenn der Kernel Single-Threaded ist, blockiert jeder Thread auf Benutzerebene, der einen Systemaufruf blockiert, den gesamten Prozess, auch wenn andere Threads zur Ausführung in der Anwendung verfügbar sind. 5. Zu den Benutzer-Thread-Bibliotheken gehören POSIX-Pthreads, Mach-C-Threads und Solaris 2-UI-Threads.

Kernel-Threads: 1. Der Kernel erstellt, plant und verwaltet Threads im Kernel-Space. 2. Kernel-Threads sind in der Regel langsamer zu erstellen und zu verwalten als Benutzer-Threads. 3. Der Kernel verwaltet die Threads, wenn ein Thread einen Systemaufruf blockiert. 4. In einer Multiprozessor-Umgebung kann der Kernel Threads auf verschiedenen Prozessoren planen. 5. Einschließlich Kernel-Threads, die Windows NT, Windows 2000, Solaris 2, BeOS und Tru64 UNIX (ehemals Digital UN1X) unterstützen.

0
Razib Palash