Quali discussioni condividono in generale?


20

Bene, questa è una domanda generale. E se qualcuno vuole renderlo specifico per l'implementazione, preferirò cose relative a Unix. Ma prima devi conoscere i seguenti problemi in generale:

Ho letto singolo processo può avere più thread. Più thread dello stesso processo condividono cose tra loro. Voglio sapere cosa condividono e cosa no. Considerando il processo è composto da spazio indirizzo, stack, heap, variabili globali, codice, dati, risorse del sistema operativo, cosa tra loro è condiviso dai thread? Ho le seguenti ipotesi:

  1. Variabili globali - Ho letto la variabile globale delle condivisioni thread. Inoltre durante la programmazione in Java e C #, ho creato thread per condividere variabili a livello di classe. Quindi credo che i thread condividano variabili globali (anche se non sono sicuro che i concetti nei linguaggi di programmazione di alto livello si traducano in fatti a basso livello di sistema operativo).

  2. Heap: poiché la variabile globale è memorizzata nell'heap, l'heap è condiviso tra i thread.

  3. Stack: poiché ogni thread può avere la propria sequenza / codice di esecuzione, deve avere il proprio stack sul quale potrebbe spingere / pop il contenuto del contatore del programma (quando si verificano chiamate di funzione e ritorni). Quindi i thread dello stesso processo non condividono lo stack.

Ora non sono sicuro della condivisione delle seguenti cose

  1. Spazio indirizzo - Non sono sicuro di cosa contenga esattamente lo spazio indirizzo. Ma suppongo che lo spazio degli indirizzi sia generalmente utilizzato nel contesto dei processi, non dei thread. E poiché tutti i thread dello stesso processo risiedono nello stesso spazio degli indirizzi del processo parent, si dice che i thread condividano lo spazio degli indirizzi. (Ma poi mantengono stack diversi all'interno dello stesso spazio degli indirizzi?)

  2. Risorse del sistema operativo - Immagino che questo possa essere molto specifico per l'implementazione. Ad esempio, il processo parent può selezionare selettivamente l'handle dello stesso file ad alcuni dei suoi thread e non a tutti. O sto sbagliando e le risorse del sistema operativo significano qualcosa di diverso dai file?

  3. Codice: i thread possono avere un codice diverso, quindi la condivisione del codice non è sempre il caso.

  4. Dati: incerti su cosa considerare in base ai dati. Ma certo che le variabili globali sono condivise tra i thread. E sicuro che le variabili locali non sono condivise in modo simile.

Nel complesso, sono considerevolmente confuso a causa di termini vaghi, super generalizzazioni fatte nei libri sui sistemi operativi e dettagli specifici sull'implementazione extra forniti online. Quindi sto cercando di trovare una risposta che possa soddisfarmi.

Risposte:


13

In generale ogni thread ha i suoi registri (incluso il proprio contatore dei programmi), il proprio puntatore di stack e il proprio stack. Tutto il resto è condiviso tra i thread che condividono un processo.

In particolare un processo è generalmente considerato costituito da un insieme di thread che condividono uno spazio degli indirizzi, heap, dati statici e segmenti di codice e descrittori di file * .

Uno spazio di indirizzi è semplicemente la mappatura di indirizzi logici su specifici pezzi di memoria fisica. Quindi, quando diciamo che tutti i thread in un processo condividono lo stesso spazio degli indirizzi, intendiamo che quando si accede a una variabile foonell'ambito globale tutti i thread vedranno la stessa variabile. Allo stesso modo, i thread possono tutti eseguire un punto diverso nel codice in un determinato momento, ma sono tutti autorizzati a chiamare la funzione globale bar(), che corrisponderà alla stessa funzione per ogni thread nel processo.

La maggior parte dei sistemi operativi moderni ha aggiunto una nozione di thread storage locale , che sono variabili di portata globale che non sono condivise. Il solito esempio dell'uso di questo è per la variabile errno. Questa è una singola variabile di portata globale, ma nella maggior parte dei sistemi operativi moderni a ogni thread viene assegnata la propria copia locale, in modo che un errore nella chiamata di una libreria su un thread non influisca sul comportamento di altri thread.

* C'è un ulteriore stato del processo condiviso da tutti i thread in un processo, cose come l'id del processo, la gestione del segnale e i blocchi dei file. Per un elenco completo dello stato del processo condiviso dai thread, è necessario consultare la documentazione per l'implementazione del threading specifica. Ad esempio, la pagina man di pthreads .


4

Le discussioni emergono in due prospettive: sistemi operativi e linguaggi di programmazione. In entrambi i casi, c'è qualche variazione negli attributi di un thread.

Una definizione minima di un thread è che è roba che accade in sequenza, una cosa dopo l'altra.

In un tipico modello di esecuzione della macchina, ogni thread ha il proprio set di registri di uso generale e il proprio contatore di programmi. Se la macchina imposta un registro specifico come puntatore di stack, c'è una copia per thread.

Dal punto di vista del sistema operativo, il minimo che un sistema operativo deve fare per supportare i thread è fornire un modo per passare da uno all'altro. Ciò può avvenire automaticamente ( multitasking preventivo o solo quando il thread formula una richiesta esplicita (multitasking cooperativo; in tal caso i thread vengono talvolta chiamati fibre ). Esistono anche modelli ibridi con prelazione sia preventiva che cooperativa, ad es. Prelazione tra thread di gruppi diversi o attività ma rendimenti espliciti tra thread dello stesso gruppo / attività. Il passaggio tra thread implica almeno il salvataggio dei valori di registro del thread precedente e il ripristino dei valori di registro del nuovo thread.

In un sistema operativo multitasking che fornisce isolamento tra attività (o processi , è possibile trattare questi termini come sinonimi in un contesto di sistema operativo), ogni attività ha le proprie risorse, in particolare lo spazio degli indirizzi, ma anche file aperti, privilegi, ecc. L'isolamento ha deve essere fornito dal kernel del sistema operativo , un'entità che è al di sopra dei processi. Ogni attività ha normalmente almeno un thread - un'attività che non esegue il codice non è di grande utilità. Il sistema operativo può o meno supportare più thread nella stessa attività; ad esempio Unix originale no. Un'attività può ancora eseguire più thread organizzando il passaggio tra di essi - questo non richiede alcun privilegio speciale. Questo si chiama " thread utente", Specialmente in un contesto Unix. Oggi la maggior parte dei sistemi Unix fornisce thread del kernel, in particolare perché è l'unico modo per avere più thread dello stesso processo in esecuzione su processori diversi.

La maggior parte delle risorse del sistema operativo, a parte il tempo di calcolo, sono associate alle attività, non ai thread. Alcuni sistemi operativi (ad esempio Linux) delimitano esplicitamente gli stack, nel qual caso ogni thread ha il suo; ma ci sono sistemi operativi in ​​cui il kernel non sa nulla degli stack, fanno solo parte dell'heap per quanto riguarda. Il kernel in genere gestisce anche un contesto del kernel per ogni thread, che è una struttura di dati contenente informazioni su ciò che il thread sta attualmente facendo; questo consente al kernel di gestire più thread bloccati in una chiamata di sistema contemporaneamente.

Per quanto riguarda il sistema operativo, i thread di un'attività eseguono lo stesso codice, ma si trovano in posizioni diverse in quel codice (valori del contatore del programma diversi). Può capitare o no che alcune parti del codice di un programma vengano sempre eseguite in thread specifici, ma di solito esiste un codice comune (ad es. Funzioni di utilità) che può essere chiamato da qualsiasi thread. Tutti i thread vedono gli stessi dati, altrimenti sarebbero considerati compiti diversi; se alcuni dati sono accessibili solo da un determinato thread, di solito è solo la competenza del linguaggio di programmazione, non del sistema operativo.

Nella maggior parte dei linguaggi di programmazione, l'archiviazione è condivisa tra thread dello stesso programma. Questo è un modello di memoria condivisa di programmazione concorrente; è molto popolare, ma anche molto soggetto a errori, perché il programmatore deve fare attenzione quando è possibile accedere agli stessi dati da più thread poiché possono verificarsi condizioni di competizione . Nota che anche le variabili locali possono essere condivise tra thread: "variabile locale" (di solito) significa una variabile il cui nome è valido solo durante un'esecuzione di una funzione, ma un altro thread può ottenere un puntatore a quella variabile e accedervi.

Esistono anche linguaggi di programmazione in cui ogni thread ha la propria memoria e la comunicazione tra di essi avviene inviando messaggi sui canali di comunicazione. Questo è il modello di passaggio dei messaggi di programmazione concorrente. Erlangè il principale linguaggio di programmazione che si concentra sul passaggio dei messaggi; il suo ambiente di esecuzione ha una gestione dei thread molto leggera e incoraggia i programmi scritti con molti thread di breve durata, in contrasto con la maggior parte degli altri linguaggi di programmazione in cui la creazione di un thread è un'operazione relativamente costosa e l'ambiente di runtime non può supportare una dimensione molto grande numero di thread contemporaneamente. Il sottoinsieme sequenziale di Erlang (la parte del linguaggio che accade all'interno di un thread, in particolare la manipolazione dei dati) è (principalmente) puramente funzionale; pertanto un thread può inviare un messaggio a un altro thread contenente alcuni dati e nessuno dei due thread deve preoccuparsi che i dati vengano modificati dall'altro thread mentre lo sta utilizzando.

Alcune lingue combinano i due modelli offrendo uno storage thread-local, con o senza un sistema di tipi per distinguere la posizione dello storage thread-local da quelli globali. L'archiviazione locale di thread è in genere una funzionalità utile che consente a un nome di variabile di designare posizioni di archiviazione diverse in thread diversi.

Alcuni (difficili) follow-up che potrebbero essere di interesse per capire quali thread sono:

  • Qual è il minimo che un kernel deve fare per supportare più thread?
  • In un ambiente multiprocessore, cosa serve per migrare un thread da un processore a un altro?
  • Cosa sarebbe necessario per implementare il multithreading cooperativo ( coroutine ) nel tuo linguaggio di programmazione preferito senza il supporto del sistema operativo e senza utilizzare il suo supporto integrato? (Attenzione che la maggior parte dei linguaggi di programmazione non ha le primitive necessarie per implementare le coroutine all'interno di un singolo thread.)
  • Come potrebbe essere un linguaggio di programmazione se avesse una concorrenza ma nessun concetto (esplicito) di thread? (Primo esempio: il pi-calculus .)

Questa è la cosa più interessante che leggo da mesi.
JSON,

2

Dipende. Se consideri i thread come definiti ad es. Da POSIX (e offerti dai sistemi Unix) o da Windows (non hai familiarità con i successivi, dovresti chiedere in modo specifico), allora questo dà la tua risposta (essenzialmente come spiega la risposta di @WanderingLogic). Linux ha una propria idea di thread, usando la clone(2)chiamata di sistema non standard . Offre un controllo piuttosto preciso di ciò che i genitori e i figli condividono. Si spinge fino ad avere fork(2)e vfork(2)sostanzialmente avvolgere l'interno clone(2), chiamandolo con flag specifici, cioè puoi creare "thread" che non condividono quasi nulla con il genitore. Consulta la sua pagina di manuale per i dettagli, sono disponibili online, ad esempio qui . Sì, Linux offre thread in stile POSIX, ma molto di più.


0

Le discussioni condividono:

  • Spazio indirizzo
  • Mucchio
  • Dati statici
  • Segmenti di codice
  • Descrittori di file
  • Variabili globali
  • Processi secondari
  • Allarmi in sospeso
  • Segnali e gestori di segnali
  • Informazioni contabili

Le discussioni hanno le loro:

  • Contatore di programma
  • registri
  • Pila
  • Stato
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.