GNU/Linux >> Linux Esercitazione >  >> Linux

Utilizzo dei registri di segmentazione

  1. Devi aver letto dei libri molto vecchi perché nessuno programma per la modalità reale più;-) In modalità reale , puoi ottenere l'indirizzo fisico di un accesso alla memoria con phyical address = segment register * 0x10 + offset , l'offset è un valore all'interno di uno dei registri generici. Poiché questi registri sono larghi 16 bit, un segmento sarà lungo 64 kb e non c'è niente che tu possa fare per la sua dimensione, solo perché non c'è alcun attributo! Con il * 0x10 moltiplicazione, diventa disponibile 1 MB di memoria, ma ci sono combinazioni sovrapposte a seconda di ciò che inserisci nei registri di segmento e il registro degli indirizzi . Non ho compilato alcun codice per la modalità reale , ma penso che spetti al sistema operativo impostare i registri di segmento durante il caricamento del binario, proprio come un caricatore allocherebbe alcune pagine durante il caricamento di un binario ELF. Tuttavia ho compilato il codice del kernel bare-metal e ho dovuto impostare questi registri da solo.

  2. Quattro segmenti sono obbligatori nel modello piatto a causa dei vincoli dell'architettura. In modalità protetta i registri di segmento non contiene più l'indirizzo di base del segmento, ma un selettore di segmento che è fondamentalmente un offset nel GDT. A seconda del valore del selettore di segmento , la CPU sarà in un dato livello di privilegio, questo è il CPL (Current Privilege Level). Il selettore di segmenti punta a un descrittore di segmento che ha un DPL (Descriptor Privilege Level), che alla fine è il CPL se il registro del segmento è riempito con questo selettore (almeno vero per il selettore del segmento di codice). Pertanto hai bisogno di almeno un paio di selettori di segmento per differenziare il kernel dalla userland. Inoltre, i segmenti sono segmenti di codice o segmenti di dati, quindi alla fine ti ritroverai con quattro descrittori di segmento nel GDT.

  3. Non ho alcun esempio di sistema operativo serio che faccia uso della segmentazione, solo perché la segmentazione è ancora presente per la conformità all'indietro. Usare l'approccio del modello piatto non è altro che un mezzo per sbarazzarsene. Ad ogni modo, hai ragione, il paging è molto più efficiente e versatile e disponibile su quasi tutte le architetture (almeno i concetti). Non posso spiegare qui gli interni del paging, ma tutte le informazioni che devi sapere sono all'interno dell'eccellente Intel man:Intel® 64 and IA-32 ArchitecturesSoftware Developer's ManualVolume 3A:System Programming Guide, Part 1


Ampliando la risposta di Benoit alla domanda 3...

La divisione dei programmi in parti logiche come codice, dati costanti, dati modificabili e stack viene eseguita da agenti diversi in momenti diversi.

Innanzitutto, il tuo compilatore (e linker) crea file eseguibili in cui è specificata questa divisione. Se guardi un numero di formati di file eseguibili (PE, ELF, ecc.), vedrai che supportano alcuni tipi di sezioni o segmenti o come vuoi chiamarli. Oltre agli indirizzi, alle dimensioni e alle posizioni all'interno del file, quelle sezioni contengono attributi che indicano al sistema operativo lo scopo di queste sezioni, ad es. questa sezione contiene il codice (ed ecco il punto di ingresso), questo - dati costanti inizializzati, quello - dati non inizializzati (in genere non occupano spazio nel file), ecco qualcosa sullo stack, laggiù c'è l'elenco delle dipendenze (ad es. DLL), ecc.

Successivamente, quando il sistema operativo avvia l'esecuzione del programma, analizza il file per vedere di quanta memoria ha bisogno il programma, dove e quale protezione della memoria è necessaria per ogni sezione. Quest'ultimo viene comunemente eseguito tramite le tabelle delle pagine. Le code page sono contrassegnate come eseguibili e di sola lettura, le pagine di dati costanti sono contrassegnate come non eseguibili e di sola lettura, le altre pagine di dati (comprese quelle dello stack) sono contrassegnate come non eseguibili e di lettura-scrittura. Questo è come dovrebbe essere normalmente.

Spesso i programmi necessitano di regioni di lettura-scrittura e, allo stesso tempo, eseguibili per il codice generato dinamicamente o semplicemente per poter modificare il codice esistente. L'accesso RWX combinato può essere specificato nel file eseguibile o richiesto in fase di esecuzione.

Possono esserci altre pagine speciali come le pagine di guardia per l'espansione dinamica dello stack, vengono posizionate accanto alle pagine dello stack. Ad esempio, il tuo programma inizia con un numero sufficiente di pagine allocate per uno stack da 64 KB e quindi, quando il programma tenta di accedere oltre quel punto, il sistema operativo intercetta l'accesso a quelle pagine di guardia, alloca più pagine per lo stack (fino alla dimensione massima supportata) e sposta ulteriormente le pagine di guardia. Queste pagine non devono essere specificate nel file eseguibile, il sistema operativo può gestirle da solo. Il file dovrebbe specificare solo le dimensioni dello stack e forse la posizione.

Se non c'è hardware o codice nel sistema operativo per distinguere la memoria del codice dalla memoria dei dati o per far rispettare i diritti di accesso alla memoria, la divisione è molto formale. I programmi DOS in modalità reale a 16 bit (COM ed EXE) non avevano segmenti di codice, dati e stack contrassegnati in qualche modo speciale. I programmi COM avevano tutto in un segmento comune di 64KB e iniziavano con IP=0x100 e SP=0xFFxx e l'ordine del codice e dei dati poteva essere arbitrario all'interno, potevano intrecciarsi praticamente liberamente. I file DOS EXE specificavano solo le posizioni iniziali CS:IP e SS:SP e oltre a ciò i segmenti di codice, dati e stack erano indistinguibili per DOS. Tutto quello che doveva fare era caricare il file, eseguire il riposizionamento (solo per EXE), impostare il PSP (Program Segment Prefix, contenente il parametro della riga di comando e alcune altre informazioni di controllo), caricare SS:SP e CS:IP. Non poteva proteggere la memoria perché la protezione della memoria non è disponibile nella modalità dell'indirizzo reale, quindi i formati eseguibili DOS a 16 bit erano molto semplici.


Linux
  1. Come usare BusyBox su Linux

  2. Come uso cron in Linux

  3. Perché le pagine man di Unix usano i doppi backtick al posto delle doppie virgolette?

  4. Come utilizzare le pagine man per imparare a usare i comandi?

  5. Linux – Uso di O_direct su Linux?

Perché uso rxvt come terminale

Usa vi Editor

Come utilizzare Instagram nel terminale

Impara a usare le pagine man in modo efficiente in Linux

Come usare il comando PS

Come usare il comando TOP