2009-11-19 2 views
179

Kürzlich wurde ich in einem Interview gefragt, was der Unterschied zwischen einem Prozess und einem Thread ist. Wirklich, ich kannte die Antwort nicht. Ich dachte eine Minute nach und gab eine sehr seltsame Antwort.Welche Ressourcen werden zwischen Threads geteilt?

Threads teilen sich den gleichen Speicher, Prozesse nicht. Nachdem er dies beantwortet hatte, gab mir der Interviewer ein böses Lächeln und feuerte die folgenden Fragen an mich:

Q. Kennen Sie die Segmente, in denen ein Programm geteilt wird?

Meine Antwort: yep (dachte, es leicht gefallen war) Stapel, Daten, Code, Heap

Q. Also, sagen Sie mir: welche Segmente teilen Fäden?

Ich konnte das nicht beantworten und endete damit, sie alle zu sagen.

Bitte kann jemand die richtigen und beeindruckenden Antworten für den Unterschied zwischen einem Prozess und einem Thread präsentieren?

+5

Threads teilen sich dasselbe virtuelle _address-space_, Prozess nicht. – Benoit

+2

möglich Duplikat von [Was ist der Unterschied zwischen einem Prozess und einem Thread] (http://stackoverflow.com/questions/200469/what-is-the-difference-between-a-process-and-a-thread) – sashoalm

Antwort

111

Sie sind ziemlich richtig, aber Threads teilen alle Segmente außer den Stapel. Threads haben unabhängige Callstacks, aber der Speicher in anderen Thread-Stacks ist immer noch zugänglich und theoretisch könnte man einen Zeiger auf Speicher im lokalen Stack-Frame eines anderen Threads halten (obwohl Sie wahrscheinlich einen besseren Platz finden sollten, um diesen Speicher zu platzieren!).

+13

Der interessante Teil ist, dass obwohl Threads unabhängige Call-Stacks haben, der Speicher in anderen Stacks immer noch zugänglich ist. –

10

Threads teilen sich die Code- und Datensegmente und den Heap, aber sie teilen sich den Stack nicht.

+9

Es besteht ein Unterschied zwischen "Zugriff auf Daten im Stapel" und dem Teilen des Stapels. Diese Threads haben ihre eigenen Stacks, die beim Aufruf von Methoden gepusht und gepoppt werden. –

+2

Sie sind beide gleichermaßen gültige Ansichten. Ja, jeder Thread hat seinen eigenen Stack in dem Sinne, dass es eine Eins-zu-Eins-Entsprechung zwischen Threads und Stacks gibt und jeder Thread einen Space hat, der für seine eigene normale Stack-Nutzung verwendet wird. Aber es gibt auch vollständig gemeinsam genutzte Prozessressourcen, und wenn gewünscht, kann jeder Thread so einfach auf den Stapel eines anderen Threads zugreifen. –

+0

@DavidSchwartz, kann ich Ihren Punkt wie folgt zusammenfassen: Jeder Thread hat seinen eigenen Stack und der Stack besteht aus 2 Teilen - dem ersten Teil, der zwischen Threads geteilt wird, bevor der Prozess Multi-Threading ist, und dem zweiten Teil, der gefüllt wird wenn der besitzende Thread läuft .. einverstanden? – FaceBro

1

Thread teilen den Haufen (es gibt eine Forschung über threadspezifische Heap), aber aktuelle Implementierung teilen den Haufen. (und natürlich der Code)

5

Threads teilen Daten und Code, während Prozesse nicht. Der Stapel ist nicht für beide freigegeben.

Prozesse können auch Speicher teilen, genauer Code, zum Beispiel nach einer Fork(), aber dies ist ein Implementierungsdetail und (Betriebssystem-) Optimierung. Code, der von mehreren Prozessen gemeinsam genutzt wird, wird (hoffentlich) beim ersten Schreiben in den Code dupliziert - dies wird copy-on-write genannt. Ich bin mir nicht sicher über die genaue Semantik für den Code von Threads, aber ich gehe von gemeinsamem Code aus.

 
      Process Thread 

    Stack private private 
    Data private shared 
    Code private1 shared2 

Der Code ist logisch privat, aber vielleicht aus Performance-Gründen geteilt werden. Ich bin mir nicht 100% sicher.

+0

Ich würde sagen, Code-Segment (Text-Segment), im Gegensatz zu Daten, ist fast immer Readonly auf den meisten Architekturen. –

46

Von Wikipedia (denke ich, dass eine wirklich gute Antwort für die Interviewer machen würde: P)

Themen unterscheiden sich von traditionellen Multitasking-Betriebssystem Prozesse, dass:

  • Prozesse sind in der Regel unabhängig, während Threads existieren als Teilmengen von Prozess
  • Prozesse tragen erhebliche Zustandsinformationen, während mehrere sowie Fäden innerhalb eines Zustandsprozess Teilen als Speicher und andere Ressourcen
  • Prozesse haben getrennte Adreßräume, während ihre Fäden Adreßraum
  • Prozessen interagieren nur durch vom System bereitgestellte Interprozess-Kommunikationsmechanismen teilen.
  • Kontextwechsel zwischen Threads im selben Prozess ist in der Regel schneller als Kontextwechsel zwischen Prozesse.
+1

über Punkt Nr. 2 oben: Für Threads auch CPU pflegt einen Kontext. – Jack

4

Themen Aktie alles [1]. Es gibt einen Adressraum für den gesamten Prozess.

Jeder Thread hat seinen eigenen Stapel und Register, aber alle Stapel der Threads sind im freigegebenen Adressraum sichtbar.

Wenn ein Thread ein Objekt auf seinem Stack zuweist und die Adresse an einen anderen Thread sendet, haben beide denselben Zugriff auf dieses Objekt.


Eigentlich habe ich gerade bemerkt, ein breiteres Problem: Ich glaube, Sie verwechseln zwei Verwendungen des Wortes Segment.

Das Dateiformat für eine ausführbare Datei (z. B. ELF) enthält verschiedene Abschnitte, die als Segmente bezeichnet werden können und kompilierten Code (Text), initialisierte Daten, Linkersymbole, Debuginformationen usw. enthalten Heap- oder Stack-Segmente hier, da diese nur Laufzeit-Konstrukte sind.

Diese binären Dateisegmente können separat in den Prozessadressraum mit verschiedenen Berechtigungen (z. B. schreibgeschützte ausführbare Datei für Code/Text und nicht ausführbare Kopie-für-Datei für initialisierte Daten) abgebildet werden.

Bereiche dieses Adressraums werden für verschiedene Zwecke verwendet, z. B. Heap-Zuweisung und Thread-Stacks (durch Ihre Sprachlaufzeitbibliotheken erzwungen). Es ist jedoch nur Speicher und wahrscheinlich nicht segmentiert, es sei denn, Sie laufen im virtuellen 8086-Modus. Der Stapel jedes Threads ist ein Stapel Speicher, der zur Thread-Erzeugungszeit zugeordnet ist, wobei die aktuelle Stapelanfangsadresse in einem Stapelzeigerregister gespeichert ist und jeder Thread seinen eigenen Stapelzeiger zusammen mit seinen anderen Registern behält.


[1] OK, ich weiß: Signalmasken, TSS/TSD usw. Der Adressraum, einschließlich aller zugeordneten Programmsegmente, sind aber immer noch geteilt.

24

Sagen Sie dem Interviewer, dass es ausschließlich auf die Implementierung des Betriebssystems ankommt.

Nehmen Sie Windows x86 zum Beispiel. Es gibt nur Segmente [1], Code und Daten. Und sie sind beide dem gesamten Adressraum von 2 GB (linear, Benutzer) zugeordnet. Basis = 0, Limit = 2 GB. Sie hätten einen erstellt, aber x86 lässt nicht zu, dass ein Segment sowohl Lesen/Schreiben als auch Ausführen ist. Also machten sie zwei und setzten CS, um auf den Code-Deskriptor zu zeigen, und der Rest (DS, ES, SS, usw.), um auf den anderen zu zeigen [2]. Aber beide verweisen auf dasselbe Zeug!

Die Person, die Sie interviewt hat, hat eine versteckte Annahme gemacht, die er/sie nicht angegeben hat, und das ist ein blöder Trick, um zu ziehen.

So in Bezug auf

Q. mich So Thread Aktie, welches Segment sagen?

Die Segmente sind für die Frage, zumindest unter Windows, irrelevant. Threads teilen sich den gesamten Adressraum. Es gibt nur ein Stack-Segment, SS, und es zeigt genau das gleiche an, was DS, ES und CS tun [2]. I.e. der ganze blutige Benutzerraum. 0-2GB. Das bedeutet natürlich nicht, dass Threads nur einen Stack haben. Natürlich hat jeder seinen eigenen Stack, aber x86-Segmente werden nicht für diesen Zweck verwendet.

Vielleicht * nix macht etwas anderes. Wer weiß. Die Prämisse, auf der die Frage beruhte, war gebrochen.


  1. Mindestens für Benutzerraum.
  2. Von ntsd notepad: cs=001b ss=0023 ds=0023 es=0023
+0

Yep ... Segmente hängt vom Betriebssystem und dem Compiler/Linker ab. Manchmal gibt es ein separates BSS-Segment aus dem DATA-Segment. Manchmal gibt es RODATA (Daten wie konstante Zeichenketten, die in Seiten sein können, die als Read Only markiert sind). Einige Systeme brechen sogar DATA in SMALL DATA (zugänglich von einer Basis + 16-Bit-Offset) und (FAR) DATA (32-Bit-Offset erforderlich für den Zugriff). Es ist auch möglich, dass es ein zusätzliches TLS DATA-Segment (Thread Local Store) gibt, das pro Thread generiert wird. – Adisak

+4

Ah, nein! Sie verwirren Segmente mit Abschnitten! Abschnitte sind, wie der Linker das Modul in Teile teilt (Daten, Daten, Text, BSS, etc ..) wie Sie beschrieben. Aber ich spreche über Segmente, wie in Intel/AMD x86-Hardware angegeben. Nicht verwandt mit Compilern/Linkern. Hoffnung, die Sinn macht. –

+0

Adisak hat jedoch recht, was den lokalen Thread-Laden betrifft. Es ist privat für den Thread und wird nicht geteilt. Ich kenne Windows OS und nicht sicher von anderen Betriebssystemen. – Jack

2

In einem x86-Rahmen, kann man so viele Segmente unterteilt (bis 2^16-1). Die ASM-Anweisungen SEGMENT/ENDS erlauben dies, und die Operatoren SEG und OFFSET erlauben die Initialisierung von Segmentregistern. CS: IP werden normalerweise vom Loader initialisiert, aber für DS, ES, SS ist die Anwendung mit der Initialisierung verantwortlich. Viele Umgebungen erlauben die sogenannten "vereinfachten Segmentdefinitionen" wie .code, .data, .bss, .stack etc. und je nach "Speichermodell" (klein, groß, kompakt etc.) initialisiert der Loader das Segment registriert sich entsprechend. Normalerweise .data, .bss, .stack und andere übliche Segmente (ich habe das seit 20 Jahren nicht mehr gemacht, so dass ich mich nicht an alle erinnere) sind in einer einzigen Gruppe zusammengefasst - deshalb weisen normalerweise DS, ES und SS darauf hin der gleiche Bereich, aber das ist nur um die Dinge zu vereinfachen.

Im Allgemeinen können alle Segmentregister zur Laufzeit unterschiedliche Werte haben. Also, die Interviewfrage war richtig: Welche von CODE, DATA und STACK werden zwischen Threads geteilt. Heap-Management ist etwas anderes - es ist einfach eine Abfolge von Aufrufen an das Betriebssystem. Aber was, wenn Sie überhaupt kein Betriebssystem haben, wie in einem Embedded-System - können Sie in Ihrem Code noch neue/löschen?

Mein Rat an die jungen Leute - lies ein paar gute Montage Programmierbuch. Es scheint, dass die Lehrpläne der Universitäten in dieser Hinsicht ziemlich schlecht sind.

15

Im Allgemeinen werden Threads leichter Prozess genannt. Wenn wir den Speicher in drei Abschnitte unterteilen, dann wird es sein: Code, Daten und Stack. Jeder Prozess hat seine eigenen Code-, Daten- und Stack-Abschnitte und aufgrund dieses Zusammenhangs ist die Switch-Zeit ein wenig hoch. Um die Kontextumschaltzeit zu reduzieren, haben die Leute ein Konzept des Threads entwickelt, das Daten und Code-Segmente mit anderen Threads/Prozessen teilt und ein eigenes STACK-Segment hat.

13

Ein Prozess hat Code-, Daten-, Heap- und Stack-Segmente. Der Anweisungspointer (IP) eines Threads oder Threads verweist jetzt auf das Codesegment des Prozesses. Die Daten- und Heapsegmente werden von allen Threads gemeinsam verwendet. Was ist nun mit dem Stapelbereich? Was ist eigentlich der Stapelbereich? Es ist ein Bereich, der durch den Prozess nur für seinen Thread erstellt wurde, da Stacks viel schneller als Heaps usw. verwendet werden können. Der Stapelbereich des Prozesses ist auf Threads aufgeteilt, dh wenn es 3 Threads gibt, dann wird der Stackbereich des Prozesses aufgeteilt Stack-Bereich des Prozesses ist in 3 Teile unterteilt und jeder ist auf die 3 Threads gegeben. Mit anderen Worten, wenn wir sagen, dass jeder Thread seinen eigenen Stapel hat, ist dieser Stapel tatsächlich ein Teil des Prozessstapelbereichs, der jedem Thread zugewiesen ist. Wenn ein Thread seine Ausführung beendet, wird der Stack des Threads vom Prozess zurückgewonnen. In der Tat ist nicht nur der Stapel eines Prozesses unter Threads aufgeteilt, sondern alle Registersätze, die ein Thread verwendet, wie SP, PC und Zustandsregister, sind die Register des Prozesses. Also, wenn es um das Teilen geht, sind die Code-, Daten- und Heap-Bereiche geteilt, während der Stapelbereich nur unter Threads aufgeteilt ist.

30

Etwas, das wirklich hervorgehoben werden muss, ist, dass es wirklich zwei Aspekte gibt - den theoretischen Aspekt und den Implementierungsaspekt.

Zunächst betrachten wir den theoretischen Aspekt. Sie müssen verstehen, was ein Prozess ist, um den Unterschied zwischen einem Prozess und einem Thread und dem, was zwischen ihnen geteilt wird, zu verstehen.

Wir haben die aus dem Abschnitt folgend 2.2.2 Das klassische Themen-Modell in Modern Operating Systems 3e von Tanenbaum:

Das Prozessmodell basiert auf zwei voneinander unabhängigen Konzepten: Ressourcen Gruppierung und Ausführung. Manchmal ist es nützlich, sie zu trennen. das ist, wo Fäden in kommen ....

Er fährt fort:

Eine Möglichkeit, an einem Prozess der Suche ist, dass es eine Möglichkeit, um gruppenbezogenen Ressourcen zusammen ist. Ein Prozess hat einen Adressraum , der Programmtext und -daten sowie andere Ressourcen enthält. Diese Ressource kann offene Dateien, untergeordnete Prozesse, ausstehende Alarme, Signalhandler, Buchhaltungsinformationen und mehr enthalten. Indem sie sie in Form eines Prozesses zusammenfügen, können sie leichter verwaltet werden. Das andere Konzept, das ein Prozess hat, ist ein Thread der Ausführung, normalerweise verkürzt auf nur Thread. Der Thread hat einen Programmzähler, der verfolgt, welcher Befehl als nächstes ausgeführt werden soll. Es hat Register, die seine aktuellen Arbeitsvariablen halten. Es hat einen Stapel, der die Ausführungshistorie enthält, mit einem Rahmen für jede aufgerufene Prozedur, aber nicht noch zurückgegeben von. Obwohl ein Thread in einem Prozess ausgeführt werden muss, sind der Thread und sein Prozess unterschiedliche Konzepte und können separat behandelt werden . Prozesse werden verwendet, um Ressourcen zusammenzufassen. Die Threads sind die Entitäten, die zur Ausführung auf der CPU geplant sind.

Weiter unten sieht er die folgende Tabelle:

Per process items    | Per thread items 
------------------------------|----------------- 
Address space     | Program counter 
Global variables    | Registers 
Open files     | Stack 
Child processes    | State 
Pending alarms    | 
Signals and signal handlers | 
Accounting information  | 

Die oben ist, was Sie brauchen für Themen zu arbeiten. Wie andere darauf hingewiesen haben, sind Dinge wie Segmente Betriebssystem-abhängige Implementierungsdetails.

+2

Das ist eine großartige Erklärung. Aber es sollte wahrscheinlich an die Frage geknüpft sein, irgendwie als "Antwort" zu gelten – catalyst294