2009-11-19 26 views
179

Recentemente, mi è stata fatta una domanda in un'intervista qual è la differenza tra un processo e un thread. Davvero, non conoscevo la risposta. Ho pensato per un minuto e ho dato una risposta molto strana.Quali risorse sono condivise tra i thread?

I thread condividono la stessa memoria, i processi no. Dopo aver risposto a questo, l'intervistatore mi ha rivolto un sorriso malvagio e mi ha rivolto le seguenti domande:

Q. Conosci i segmenti in cui un programma viene diviso?

La mia risposta: sì (pensano che sia un compito facile) Pila, dati, codice, Mucchio

D. Allora, dimmi: che i segmenti non thread condividono?

Non ho potuto rispondere e sono finito a dire tutti loro.

Per favore, qualcuno può presentare le risposte corrette e impressionanti per la differenza tra un processo e una discussione?

+5

I thread condividono lo stesso _address-space_ virtuale, processo no. – Benoit

+2

possibile duplicato di [Qual è la differenza tra un processo e un thread] (http://stackoverflow.com/questions/200469/what-is-the-difference-between-a-process-and-a-thread) – sashoalm

risposta

111

Sei praticamente corretto, ma i thread condividono tutti i segmenti tranne lo stack. I thread hanno stack di chiamate indipendenti, tuttavia la memoria in altri stack di thread è ancora accessibile e in teoria si può tenere un puntatore alla memoria nel frame di stack locale di qualche altro thread (anche se probabilmente si dovrebbe trovare un posto migliore per mettere quella memoria!).

+13

La parte interessante è che anche se i thread hanno stack di chiamate indipendenti, la memoria in altri stack è ancora accessibile. –

10

I thread condividono il codice, i segmenti di dati e l'heap, ma non condividono lo stack.

+9

C'è una differenza tra "poter accedere ai dati nello stack" e condividere lo stack. Questi thread hanno i propri stack che vengono spinti e spuntati quando chiamano i metodi. –

+2

Sono entrambe viste ugualmente valide. Sì, ogni thread ha il proprio stack nel senso che esiste una corrispondenza uno a uno tra thread e stack e ogni thread ha uno spazio che utilizza per il proprio normale utilizzo dello stack. Ma sono anche risorse di processo completamente condivise e, se lo si desidera, qualsiasi thread può accedere a qualsiasi altro stack di thread tanto facilmente quanto il proprio. –

+0

@DavidSchwartz, posso riepilogare il tuo punto come segue: Ogni thread ha il suo stack e lo stack è composto da 2 parti: la prima parte condivisa tra thread prima che il processo sia multithread e la seconda parte popolata quando il thread proprietario è in esecuzione .. Accetto? – FaceBro

1

Thread condividere l'heap (esiste una ricerca sull'heap specifico del thread) ma l'implementazione corrente condivide l'heap. (e ovviamente il codice)

5

I thread condividono dati e codice mentre i processi no. Lo stack non è condiviso per entrambi.

I processi possono anche condividere memoria, codice più preciso, ad esempio dopo un Fork(), ma questo è un dettaglio di implementazione e (sistema operativo) di ottimizzazione. Il codice condiviso da più processi sarà (si spera) duplicato nella prima scrittura sul codice - questo è noto come copy-on-write. Non sono sicuro della semantica esatta per il codice dei thread, ma presumo codice condiviso.

 
      Process Thread 

    Stack private private 
    Data private shared 
    Code private1 shared2 

Il codice è logicamente privata, ma potrebbe essere condivisa per motivi di prestazioni. Non sono sicuro al 100%.

+0

Direi che il segmento di codice (segmento di testo), a differenza dei dati, è quasi sempre in sola lettura sulla maggior parte delle architetture. –

46

Da Wikipedia (Credo che farebbe una buona risposta per l'intervistatore: P)

Filati differiscono dal tradizionale sistema operativo multitasking processi dal fatto che:

  • processi sono tipicamente indipendente, mentre i thread esistono come sottoinsiemi di un processo
  • i processi contengono informazioni di stato considerevoli, mentre più fili all'interno di uno stato processo condividono così come memoria e altre risorse
  • processi hanno spazi di indirizzi separati, mentre thread condividono il loro spazio indirizzo
  • processi interagiscono solo attraverso meccanismi di comunicazione tra processi forniti dal sistema.
  • Il cambio di contesto tra thread nello stesso processo è in genere più rapido rispetto al cambio di contesto tra i processi .
+1

riguardo al punto 2 sopra: per i thread anche la CPU mantiene un contesto. – Jack

4

thread condividono tutto [1]. C'è uno spazio di indirizzi per l'intero processo.

Ogni thread ha il proprio stack e registri, ma tutti gli stack dei thread sono visibili nello spazio di indirizzamento condiviso.

Se un thread alloca un oggetto nello stack e invia l'indirizzo a un altro thread, entrambi avranno accesso uguale a quell'oggetto.


In realtà, ho appena notato un problema più ampio: Credo che tu stia confondendo due usi della parola segmento.

Il formato file per un file eseguibile (ad esempio ELF) ha sezioni distinte, che possono essere definiti segmenti, contenenti codice compilato (testo), dati inizializzati, simboli linker, informazioni di debug, ecc. Non ci sono heap o stack segmenti qui, poiché quelli sono costrutti di sola esecuzione.

Questi segmenti di file binari possono essere mappati separatamente nello spazio di indirizzamento del processo, con autorizzazioni diverse (ad esempio, eseguibile di sola lettura per codice/testo e non-eseguibile copy-on-write per dati inizializzati).

Le aree di questo spazio indirizzo vengono utilizzate per diversi scopi, come l'allocazione dell'heap e gli stack di thread, per convenzione (applicata dalle librerie di runtime della lingua). È tutto solo memoria, e probabilmente non segmentato a meno che non stiate correndo in modalità 8086 virtuale. Lo stack di ogni thread è un blocco di memoria allocato al momento della creazione del thread, con l'indirizzo superiore dello stack corrente memorizzato in un registro del puntatore dello stack e ogni thread mantiene il proprio puntatore dello stack insieme agli altri registri.


[1] OK, lo so: maschere di segnale, TSS/TSD ecc Lo spazio di indirizzi, compresi tutti i suoi segmenti di programma mappate, sono ancora condivisi però.

24

Comunicare all'intervistatore che dipende interamente dall'implementazione del sistema operativo.

Prendere Windows x86 ad esempio. Ci sono solo segmenti [1], Codice e Dati. E sono entrambi mappati all'intero spazio degli indirizzi da 2 GB (lineare, utente). Base = 0, limite = 2 GB. Avrebbero realizzato uno ma x86 non consente a un segmento di essere sia in lettura/scrittura che in esecuzione. Quindi ne fecero due, e impostarono CS in modo che indicasse il codice descrittore, e il resto (DS, ES, SS, ecc.) Per puntare all'altro [2]. Ma entrambi indicano la stessa roba!

La persona che ha intervistato ha fatto un'assunzione nascosta che lui/lei non ha dichiarato, e quello è uno stupido trucco da tirare.

Quindi per quanto riguarda

D. Quindi mi quale thread segmento quota di dire?

I segmenti sono irrilevanti per la domanda, almeno su Windows. I thread condividono l'intero spazio degli indirizzi. C'è solo 1 segmento di stack, SS, e punta allo stesso identico materiale che DS, ES e CS fanno [2]. Cioè l'intero spazio utente insanguinato. 0-2GB. Naturalmente, ciò non significa che i thread hanno solo 1 stack. Naturalmente ognuno ha il proprio stack, ma i segmenti x86 non vengono utilizzati per questo scopo.

Forse * nix fa qualcosa di diverso. Chissà. La premessa su cui si basava la domanda era stata infranta.


  1. Almeno per spazio utente.
  2. Da ntsd notepad: cs=001b ss=0023 ds=0023 es=0023
+0

Sì ... I segmenti dipendono dal sistema operativo e dal compilatore/linker. A volte esiste un segmento BSS separato dal segmento DATI. A volte c'è RODATA (dati come stringhe costanti che possono essere in pagine contrassegnate come Sola lettura). Alcuni sistemi interrompono anche i DATA in SMALL DATA (accessibili da una base + offset a 16 bit) e (FAR) DATA (offset a 32 bit richiesto per l'accesso). È anche possibile che ci sia un segmento TLS DATA aggiuntivo (Thread Local Store) che viene generato su una base per thread – Adisak

+4

Ah, no! Stai confondendo segmenti con sezioni! Le sezioni sono come il linker divide il modulo in parti (dati, rdata, testo, bss, ecc.) Come descritto. Ma sto parlando di segmenti, come specificato nell'hardware intel/amd x86. Non correlato a compilatori/linker. Spero che abbia senso. –

+0

Tuttavia, Adisak ha ragione riguardo al negozio locale di Thread. È privato del thread e non è condiviso. Sono a conoscenza del sistema operativo Windows e non sono sicuro di altri sistemi operativi. – Jack

2

In un quadro 86, si possono dividere i segmenti (fino a 2^16-1). Le direttive ASM SEGMENT/ENDS consentono questo e gli operatori SEG e OFFSET consentono l'inizializzazione dei registri di segmento. CS: IP vengono generalmente inizializzati dal caricatore, ma per DS, ES, SS l'applicazione è responsabile dell'inizializzazione. Molti ambienti consentono le cosiddette "definizioni di segmenti semplificate" come .code, .data, .bss, .stack ecc. E, in base anche al "modello di memoria" (piccolo, grande, compatto ecc.) Il caricatore inizializza il segmento registra di conseguenza. Di solito .data, .bss, .stack e altri soliti segmenti (non l'ho fatto da 20 anni, quindi non ricordo tutto) sono raggruppati in un singolo gruppo - questo è il motivo per cui solitamente DS, ES e SS puntano stessa area, ma questo è solo per semplificare le cose.

In generale, tutti i registri di segmento possono avere valori diversi in fase di esecuzione. Quindi, la domanda dell'intervista era giusta: quale dei CODICE, DATI e STACK sono condivisi tra i thread. La gestione dell'heap è un'altra cosa: è semplicemente una sequenza di chiamate al sistema operativo. Ma cosa succede se non hai affatto un sistema operativo, come in un sistema embedded? Puoi ancora avere/eliminare nel tuo codice?

Il mio consiglio ai giovani - leggere un buon libro di programmazione di assemblaggio. Sembra che i curricula universitari siano piuttosto mediocri in questo senso.

15

Generalmente, i thread sono chiamati processo leggero. Se dividiamo la memoria in tre sezioni, allora sarà: Codice, dati e Stack. Ogni processo ha le proprie sezioni di codice, dati e stack e, a causa di questo contesto, il tempo di commutazione è un po 'alto. Per ridurre il tempo di commutazione del contesto, le persone hanno escogitato il concetto di thread, che condivide il segmento Data e codice con altri thread/processi e ha il proprio segmento STACK.

13

Un processo ha segmenti di codice, dati, heap e stack. Ora, il puntatore di istruzioni (IP) di un thread OR thread punta al segmento di codice del processo. I segmenti di dati e heap sono condivisi da tutti i thread. Ora, per quanto riguarda l'area dello stack? Qual è in realtà l'area dello stack? È un'area creata dal processo solo per il suo thread da usare ... perché gli stack possono essere utilizzati in un modo molto più rapido di heap, ecc. L'area di stack del processo è divisa tra thread, cioè se ci sono 3 thread, quindi l'area di stack del processo è divisa in 3 parti e ciascuna viene assegnata ai 3 thread. In altre parole, quando diciamo che ogni thread ha il proprio stack, quella pila è in realtà una parte dell'area di stack del processo allocata a ciascun thread. Quando un thread termina la sua esecuzione, la pila del thread viene recuperata dal processo. Infatti, non solo la pila di un processo è divisa tra i thread, ma tutti i registri che un thread utilizza come SP, PC e registri di stato sono i registri del processo. Quindi quando si parla di condivisione, il codice, i dati e le aree dell'heap sono condivisi, mentre l'area dello stack è appena divisa tra i thread.

30

Qualcosa che deve davvero essere sottolineato è che ci sono davvero due aspetti di questa domanda: l'aspetto teorico e l'aspetto delle implementazioni.

In primo luogo, esaminiamo l'aspetto teorico. Devi capire che processo è concettualmente capire la differenza tra un processo e un thread e ciò che è condiviso tra loro.

Abbiamo il seguente dalla sezione 2.2.2 Il modello di thread classica in Modern Operating Systems 3e da Tanenbaum:

Il modello di processo si basa su due concetti indipendenti: risorsa raggruppamento e l'esecuzione. A volte è utile separarli; questo è dove le discussioni sono disponibili in ....

E continua:

Un modo di guardare ad un processo è che si tratta di un modo per risorse correlate raggruppare. Un processo ha uno spazio indirizzo contenente testo e dati del programma, nonché altre risorse. Queste risorse possono includere file aperti, processi figlio, allarmi in attesa, gestori di segnale , informazioni di contabilità e altro. Inserendoli insieme sotto forma di processo, possono essere gestiti più facilmente. L'altro concetto di un processo è un thread di esecuzione, in genere abbreviato in solo thread. Il thread ha un contatore di programmi che mantiene la traccia di quale istruzione eseguire successivamente. Ha registri, che mantengono le sue variabili di lavoro correnti. Ha una pila, che contiene la cronologia di esecuzione , con una cornice per ogni procedura chiamata ma non ancora restituita da. Sebbene un thread debba essere eseguito in qualche processo, il thread e il suo processo sono concetti diversi e possono essere trattati separatamente . I processi vengono utilizzati per raggruppare le risorse; thread sono le entità pianificate per l'esecuzione sulla CPU.

Più in basso si fornisce la seguente tabella:

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  | 

Quanto sopra è ciò che è necessario per i thread di lavorare. Come altri hanno sottolineato, le cose come i segmenti sono dettagli di implementazione dipendenti dall'OS.

+2

Questa è una grande spiegazione. Ma probabilmente dovrebbe essere legato alla domanda in qualche modo da considerare una "risposta" – catalyst294

Problemi correlati