stack del kernel e stack dello spazio utente


110

Qual è la differenza tra lo stack del kernel e lo stack utente? Perché viene utilizzato lo stack del kernel? Se una variabile locale viene dichiarata in un ISR, dove verrà memorizzata? Ogni processo ha il proprio stack del kernel? Allora come si coordina il processo tra queste due pile?

Risposte:


188
  1. Qual è la differenza tra lo stack del kernel e lo stack utente?

In breve, niente - a parte l'utilizzo di una posizione diversa in memoria (e quindi un valore diverso per il registro stackpointer) e di solito diverse protezioni di accesso alla memoria. Cioè quando si esegue in modalità utente, la memoria del kernel (parte della quale è lo stack del kernel) non sarà accessibile anche se mappata. Viceversa, senza essere esplicitamente richiesto dal codice del kernel (in Linux, tramite funzioni come copy_from_user()), la memoria utente (incluso lo stack utente) di solito non è direttamente accessibile.

  1. Perché viene utilizzato uno stack del kernel [separato]?

Separazione di privilegi e sicurezza. Per prima cosa, i programmi in spazio utente possono rendere il loro stack (puntatore) tutto ciò che vogliono, e di solito non c'è alcun requisito architettonico per averne uno valido. Il kernel quindi non può fidarsi che lo stackpointer dello spazio utente sia valido o utilizzabile, e quindi ne richiederà uno impostato sotto il proprio controllo. Diverse architetture di CPU lo implementano in modi diversi; Le CPU x86 cambiano automaticamente stackpointer quando si verificano cambi di modalità di privilegio ei valori da utilizzare per diversi livelli di privilegio sono configurabili - dal codice privilegiato (cioè solo il kernel).

  1. Se una variabile locale viene dichiarata in un ISR, dove verrà memorizzata?

Nello stack del kernel. Il kernel (kernel Linux, cioè) non aggancia gli ISR ​​direttamente alle porte di interrupt dell'architettura x86 ma delega invece l'invio di interrupt a un meccanismo comune di entrata / uscita degli interrupt del kernel che salva lo stato del registro pre-interrupt prima di chiamare i gestori registrati . La stessa CPU durante l'invio di un interrupt potrebbe eseguire un privilegio e / o uno stack switch, e questo viene utilizzato / impostato dal kernel in modo che il codice di ingresso dell'interrupt comune possa già fare affidamento sulla presenza di uno stack del kernel.
Detto questo, le interruzioni che si verificano durante l'esecuzione del codice del kernel semplicemente (continueranno a) utilizzare lo stack del kernel in posizione in quel punto. Questo può, se i gestori di interrupt hanno percorsi di chiamata profondamente annidati, portare a overflow dello stack (se un percorso di chiamata profondo del kernel viene interrotto e il gestore causa un altro percorso profondo; in Linux, il codice RAID del filesystem / software viene interrotto dal codice di rete con iptables attivo è noto per attivare tale in kernel più vecchi non sintonizzati ... la soluzione è aumentare le dimensioni dello stack del kernel per tali carichi di lavoro).

  1. Ogni processo ha il proprio stack del kernel?

Non solo ogni processo: ogni thread ha il proprio stack del kernel (e, in effetti, anche il proprio stack utente). Ricorda che l'unica differenza tra processi e thread (per Linux) è il fatto che più thread possono condividere uno spazio di indirizzi (formando un processo).

  1. Come si coordina il processo tra entrambi questi stack?

Niente affatto - non è necessario. La pianificazione (come / quando vengono eseguiti diversi thread, come il loro stato viene salvato e ripristinato) è l'attività del sistema operativo ei processi non devono occuparsene. Man mano che i thread vengono creati (e ogni processo deve avere almeno un thread), il kernel crea gli stack del kernel per loro, mentre gli stack dello spazio utente vengono creati / forniti esplicitamente da qualsiasi meccanismo utilizzato per creare un thread (funzioni come makecontext()o pthread_create()consentono al chiamante di specifica una regione di memoria da utilizzare per lo stack del thread "figlio") o ereditata (dalla clonazione della memoria all'accesso, solitamente chiamata "copia su scrittura" / COW, quando si crea un nuovo processo).
Detto ciò,(dichiara, tra questi c'è lo stackpointer del thread). Ci sono diversi modi per questo: i segnali UNIX, setcontext(), pthread_yield()/ pthread_cancel(), ... - ma questo è un po 'disgressing dalla domanda iniziale.


Ottime risposte FrankH. Grazie.
kumar

1
@FrankH Ottima risposta .. ma ho piccole domande relative ad essa, ma in architettura ARM .. Come questo stack del kernel è correlato alla diversa modalità del processore?
Rahul

2
@Rahul: "il margine di un commento SO è troppo piccolo per contenere una risposta del genere". Come funzionano i registri stack / stackpointer nelle diverse modalità della CPU ARM (che implementano un banked SP) è una buona domanda, ma richiede più spazio per rispondere di quanto possa dare un commento. Lo stesso vale per cose come i task gate x86 o gli IST: non esiste un puntatore allo stack del kernel "singolo" (proprio come non esiste un puntatore allo stack utente "singolo"), e quale supporto / mandato hardware esiste per puntatori di stack separati in diverse modalità operative è ... molto dipendente dall'hardware.
FrankH.

@FrankH. Ho creato una nuova domanda per lo stesso ... stackoverflow.com/q/22601165/769260 Spero che ora tu possa aiutarmi senza preoccuparti dello spazio :)
Rahul

1
@FrankH. Potete fornire un diagramma che mostra dove appartiene lo stack del kernel nel layout di memoria di un processo?
Jithin Pavithran,

19

La mia risposta viene raccolta da altre domande SO con i miei articoli.

What's the difference between kernel stack and user stack?

Come programmatore del kernel, sai che il kernel dovrebbe essere limitato da programmi utente errati. Supponiamo di mantenere lo stesso stack sia per il kernel che per lo spazio utente, quindi un semplice segfault nell'applicazione utente blocca il kernel e richiede il riavvio.

C'è uno "stack del kernel" per CPU come ISR Stack e uno "stack del kernel" per processo. C'è uno "stack utente" per ogni processo, sebbene ogni thread abbia il proprio stack, inclusi i thread utente e kernel.

http://linux.derkeiler.com/Mailing-Lists/Kernel/2004-10/3194.html

Why kernel stack is used?

Quindi, quando siamo in modalità kernel, è necessario un meccanismo di tipo stack per gestire le chiamate di funzione, variabili locali simili allo spazio utente.

http://www.kernel.org/doc/Documentation/x86/kernel-stacks

If a local variable is declared in an ISR, where it will be stored?

Verrà memorizzato nello stack ISR (IRQSTACKSIZE). L'ISR viene eseguito su uno stack di interrupt separato solo se l'hardware lo supporta. In caso contrario, gli stack frame ISR vengono inseriti nello stack del thread interrotto.

Lo spazio utente non sa e francamente non si preoccupa del fatto che l'interrupt sia servito nello stack del kernel del processo corrente o in uno stack ISR separato. Poiché gli interrupt vengono forniti per cpu, quindi lo stack ISR deve essere per cpu.

 Does each process has its own kernel stack ?

Sì. Ogni processo ha il proprio stack del kernel.

 Then how the process coordinates between both these stacks?

La risposta di @ FrankH mi sembra fantastica.


4
  1. Qual è la differenza tra stack del kernel e stack utente

Facendo riferimento al Linux Kernel Development di Robert Love, la differenza principale è la dimensione:

Lo spazio utente può cavarsela con l'allocazione statica di molte variabili sullo stack, incluse strutture enormi e array di mille elementi.
Questo comportamento è legale perché lo spazio utente ha un grande stack che può crescere dinamicamente.
Lo stack del kernel non è né grande né dinamico; è piccolo e di dimensioni fisse.
La dimensione esatta dello stack del kernel varia in base all'architettura.
Su x86, la dimensione dello stack è configurabile in fase di compilazione e può essere 4KB o 8KB.
Storicamente, lo stack del kernel è di due pagine, il che generalmente implica che sia 8 KB su architetture a 32 bit e 16 KB su architetture a 64 bit: questa dimensione è fissa e assoluta.
Ogni processo riceve il proprio stack.

Inoltre lo stack del kernel contiene un puntatore alla struttura thread_info contenente le informazioni sul thread.

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.