Nel disegno mancano alcune importanti ipotesi sottostanti.
Il kernel non ha bisogno di mmap()
per accedere alla memoria dello spazio utente. Se un processo utente ha memoria, è già mappato nello spazio indirizzo per definizione. In questo senso, la memoria è già condivisa tra utente e kernel.
mmap()
crea una nuova area nello spazio degli indirizzi virtuali dell'utente, in modo che l'area dell'indirizzo possa essere popolata dalla memoria fisica se successivamente acceduta. L'effettiva allocazione della memoria e la modifica della voce della tabella di pagina vengono eseguite dal kernel.
mmap()
ha senso solo per la gestione della metà utente dello spazio di indirizzi virtuali. La metà del kernel dello spazio degli indirizzi è gestita in modo completamente diverso.
Inoltre, la metà del kernel è condivisa da tutti i processi nel sistema. Ogni processo ha il suo spazio di indirizzamento virtuale dedicato, ma le tabelle delle pagine sono programmate in modo tale che le voci della tabella di pagina per metà del kernel siano impostate esattamente allo stesso modo per tutti i processi.
Ancora, il kernel non è mmap()
per accedere alla memoria dello spazio utente. mmap()
è piuttosto un servizio fornito dal kernel all'utente per modificare il mapping corrente nello spazio degli indirizzi virtuali dell'utente.
BTW, il kernel in realtà ha alcuni modi per accedere alla memoria utente, se lo desidera.
Prima di tutto, il kernel ha una regione dedicata di spazio indirizzo del kernel (come parte del suo spazio del kernel) che mappa l'interezza della memoria fisica presente in modo consecutivo. (Questo è vero in tutti i sistemi a 64 bit. Nel sistema a 32 bit il kernel deve "rimappare" al volo per ottenere ciò.)
Secondo, se il kernel viene immesso tramite una chiamata di sistema o un'eccezione non con l'interrupt hardware, hai un contesto di processo valido, quindi il kernel può direttamente "dereferenziare" il puntatore dello spazio utente per ottenere il valore corretto.
In terzo luogo, se il kernel vuole deferire un puntatore dello spazio utente di un processo mentre esegue un contesto preso in prestito come in un gestore di interrupt, il kernel può tracciare l'indirizzo virtuale del processo attraversando l'albero vm_area_struct
per il permesso e spostando la tabella della pagina su scoprire la cornice fisica effettiva della pagina.
Sì. Questo è fondamentalmente corretto. Lo disegnerei con la pesante freccia nera che punta a destra. Cioè, condivide le stesse pagine fisiche. Non ottiene lo stesso indirizzo virtuale del kernel e in qualche modo "punta" sull'area dei dati del kernel. Invece ottiene la propria mappatura indipendente alle stesse pagine di memoria fisica. –
Spesso posso leggere che ogni thread in Linux ottiene una propria area di memoria virtuale suddivisa in un kernel da 1 GB e uno spazio utente da 3 GB. In questo caso: alcune parti del modulo del kernel si trovano all'interno dello spazio del kernel parte dell'applicazione dello spazio utente? – Alex44
Sì. In quel modello, lo spazio di indirizzamento virtuale del kernel è il primo 1GB (per x86 a 32 bit). Lo spazio in modalità utente è il 3GB in basso. Quindi condividono lo spazio di indirizzi virtuali da 4 GB. Quando è presente un interruttore di contesto, viene installata una nuova tabella di pagina. Ha gli stessi mapping per 1 GB superiore ma nuovi mapping per la modalità utente del nuovo processo. Tuttavia, la modalità utente non può mai accedere al primo 1GB (ad esempio, se tenta di accedere a quella memoria, riceverà un "SIGSEGV" a causa di restrizioni di accesso alla tabella di pagina). La modalità kernel * può * accedere tecnicamente allo spazio in modalità utente direttamente, anche se generalmente avviene tramite un'API. –