Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
vuoi
o PayPal
tutte le volte che vuoi
OPZIONI
Può valere zero oppure essere in OR con:
WNOHANG
: ritorno immediato se i figli non sono uscitiWUNTRACED
: ritorno anche se i figli sono fermi
shm_open()
Ritorna, in caso di successo, un file descriptor che si riferisce all'oggetto in memoria condivisa creato; in caso di errore -1.
FLAG
O_CREAT
: crea l'oggetto se non esisteO_RDWR
: apre l'oggetto in lettura e scritturaO_RDONLY
: apre l'oggetto in sola letturaO_EXCL
: ritorna errore se l'oggetto esiste giàO_TRUNC
: se l'oggetto esiste, lo tronca a 0 byte
MODE
S_IRWXG
: il gruppo ha tutti i permessiS_IRWXU
: il proprietario ha tutti i permessiS_IRWXO
: tutti hanno i permessi
shm_unlink()
Rimuove il segmento di memoria condivisa indicato. Restituisce 0 in caso di successo.
ftruncate()
Fa in modo che il file specificato dal file descriptor fd abbia lunghezza length byte. Il file deve essere...
aperto in scrittura. Ritorna 0 in caso di successo, altrimenti -1.
mmap()
void* mmap(void* start, size_t length, int prot, int flags, int fd, off_t offset);
Esegue la mappatura in memoria del file specificato dal file destriptor fd. Restituisce il puntatore alla zona mappata in caso di successo, altrimenti -1. La mappatura inizia da start per length byte. Offset deve essere un multiplo della dimensione della pagina.
PROT
- PROT_EXEC: le pagine si possono eseguire
- PROT_READ: le pagine si possono leggere
- PROT_WRITE: le pagine si possono scrivere
- PROT_NONE: l'accesso alle pagine è vietato
FLAGS
- MAP_SHARED
Gestione della Memoria
Come vengono trattati gli indirizzi durante la produzione e poi durante l'esecuzione di un file eseguibile?
Ciascuna istruzione macchina contenuta in un segmento di codice viene indicata univocamente alla CPU mediante un indirizzo lineare specificato da due parti:
- il contenuto del registro di segmento CS che indica (in una forma dipendente dal processore)
l'indirizzo di inizio del segmento di codice che contiene l'istruzione• un offset contenuto nel registro Instruction Pointer che indica lo scostamento di tale istruzione rispetto all'inizio del segmento stesso.
Analogamente, ciascun byte in memoria in un segmento dati o stack, viene indicato univocamente alla CPU mediante un indirizzo lineare specificato da due parti:
- il contenuto di un registro di segmento (DS o SS) che indica (in una forma dipendente dal processore) l'indirizzo di inizio del segmento data o• stack che contiene il byte
- un offset che indica lo scostamento di tale byte rispetto all'inizio del segmento stesso.
Quindi, l'indirizzo di una istruzione macchina o il byte viene indicato mediante la coppia <segmento : offset> in cui segmento indica l'inizio del segmento ed offset indica lo scostamento rispetto all'inizio del segmento.
Per accedere ad un'istruzione macchina o a un byte in memoria, la CPU specifica una
coppia <segmento : offset>. La posizione in memoria RAM fisica cioè l'indirizzo fisico dell'istruzione macchina o del byte specificati dalla coppia viene calcolata da un hardware specifico, denominato MMU (memory management unit). Questo indirizzo fisico è l'indirizzo che viene inserito nel bus degli indirizzi per accedere in memoria alla istruzione macchina oppure al byte specificati.
Le operazioni che la MMU effettua per calcolare l'indirizzo fisico a partire dalla coppia posso essere assai complesse perché dipendono da come il sistema operativo ha coerentemente configurato il funzionamento della CPU, organizzato le tabelle che descrivono lo stato dei segmenti in memoria e impostato l'uso di memoria virtuale per swappare su disco pagine di memoria dei processi.
Anche le operazioni di compilazione e linking per creare un eseguibile devono sapere come il sistema operativo tratterà i segmenti in memoria, in modo da poter specificare.
correttamente gli indirizzi nei salti da un'istruzione ad un'altra. Invece, i meccanismi di paginazione e di memoria virtuale non devono essere noti al compilatore e al linker: sono meccanismi trasparenti all'eseguibile. Quindi, il modo con cui un'istruzione macchina di un eseguibile specifica un indirizzo di un operando o di un'istruzione (cioè specifica il contenuto della coppiaindirizzo logico, specificato dalla coppia <segmento : offset>, viene associato l'indirizzo fisico in memoria RAM fisica. Quindi, l'address binding è il mappaggio degli indirizzi logici negli indirizzi fisici. Anche se viene concretizzato dall'azione della MMU, dipende dalle azioni cooperanti svolte dal compilatore, dal linker, dal loader e in generale dal sistema operativo che mantiene in memoria le tabelle necessarie. Nei sistemi moderni, il binding viene effettuato utilizzando i meccanismi di segmentazione, paginazione e memoria virtuale. Poiché tale tipo di binding utilizza anche alcuni meccanismi che operano a run-time, cioè durante l'esecuzione dell'eseguibile, questo tipo di binding viene genericamente indicato come binding dinamico. L'uso della memoria virtuale può causare un ritardo nell'accesso alla memoria, nel caso in cui occorra caricare da disco la pagina di memoria quando questa era stata swappata su disco.
Nei sistemi real-time questo ritardo non è accettabile, quindi non utilizzano il meccanismo di memoria virtuale ed effettuano un binding più semplice. Inoltre, CPU minimali dedicate a sistemi monoprogrammati (esecuzione di un solo processo alla volta) possono preferire l'uso del solo meccanismo di segmentazione, o addirittura ridurre ad uno solo i segmenti utilizzati (memoria piatta).
Nei singoli moduli oggetto compilati, in cui c'è visibilità di un solo modulo alla volta, si considerano gli indirizzi logici. Nell'eseguibile creato dal linker, in cui sono stati accorpati i diversi moduli oggetto, si considerano gli indirizzi logici. Quando il linker crea l'eseguibile a partire dai moduli oggetto, effettua la rilocazione statica degli indirizzi assoluti.
Prima dell'esecuzione, durante il caricamento in memoria dell'eseguibile, il loader effettua la rilocazione dinamica degli indirizzi: decide dove collocare in memoria i segmenti dell'eseguibile.
Completa le tabelle (del sistema operativo) dei segmenti inserendo le descrizioni e le posizioni dei segmenti, assegna ai registri di segmento il valore degli indirizzi di inizio dei segmenti a cui si riferiscono.
Se il sistema operativo non usa la paginazione, il loader carica effettivamente in memoria fisica i segmenti e quindi gli indirizzi a cui ci si riferisce sono indirizzi fisici, cioè indirizzi di celle RAM fisica.
Se invece il sistema operativo usa la paginazione, il caricamento viene effettuato in memoria virtuale, cioè l'eseguibile viene caricato nella memoria swappata su disco e allora gli indirizzi a cui ci si riferisce non sono indirizzi fisici bensì indirizzi virtuali (detti anche lineari).
Durante l'esecuzione dell'eseguibile, per quei sistemi operativi che prevedono la paginazione, le pagine che servono all'esecuzione vengono caricate da disco e collocate in memoria ed allora gli indirizzi a cui ci si riferisce sono indirizzi...
fisici.Binding durante il caricamento: Binding durante la compilazione:
vantaggi: vantaggi:
- permette di gestire la multiprogrammazione
- non richiede hardware speciale
svantaggi: svantaggi:
- richiede una traduzione degli indirizzi da parte del loader, e quindi formati particolare dei file eseguibili
- non funziona con la multiprogrammazione
Indirizzi
In un processore come quelli della famiglia intel, l'indirizzo di una locazione di memoria è specificato mediante due contributi, il primo che specifica l'inizio del segmento in cui si trova la locazione di memoria e il secondo che specifica lo scostamento (offset) della locazione di memoria rispetto all'inizio del segmento.
Per quanto riguarda la sezione text (il codice), l'inizio del segmento viene specificato dal registro CS (code segment register) mentre lo scostamento viene indicato dal registro IP (instruction pointer). La somma dei due
eseguire. Le istruzioni di salto possono essere condizionali o incondizionali. Le istruzioni condizionali permettono di eseguire un salto solo se una determinata condizione è verificata, altrimenti si passa alla prossima istruzione. Le istruzioni incondizionali eseguono sempre il salto, indipendentemente dalla condizione. I moduli oggetto sono file che contengono codice macchina compilato da un linguaggio di programmazione. Questi moduli possono essere collegati insieme per formare un programma eseguibile. Durante il collegamento, il linker si occupa di risolvere i riferimenti tra i moduli, in modo che le istruzioni di salto possano puntare correttamente alle istruzioni di destinazione. Per formattare il testo utilizzando tag html, puoi utilizzare i seguenti tag: - `` per evidenziare il testo in grassetto - `` per evidenziare il testo in corsivo - `` per evidenziare il testo in apice - `` per evidenziare il testo in pedice - `` per inserire un'interruzione di linea - `
` per evidenziare il testo come codice
Ecco un esempio di come potrebbe essere formattato il testo utilizzando i tag html:
```html
Contributi (solitamente denotata col termine program counter) indica lalocazione di memoria in cui si trova la prossima istruzione da eseguire. Per la sezione data, il registro di segmento usato è DS (data segment). Infine, per la sezione stack, il registro di segmento usato è SS (stack segment) mentre il registro SP (stack pointer) contiene lo scostamento della cima dello stack rispetto all'inizio del segmento di stack.
Istruzioni di salto e moduli oggetto
Le istruzioni dette "di salto" (jump) specificano esplicitamente quale è la prossima istruzione da eseguire. Vengono impiegate per implementare i costrutti linguistici quali le iterazioni (for, while), i costrutti condizionali (if, else, switch) e le chiamate a funzione.
L'effetto di una istruzione di salto è di modificare il contenuto del registro IP (instruction pointer) ed in qualche caso anche del registro CS (code segment) in modo da indicare la prossima istruzione macchina da eseguire. Le istruzioni di salto possono essere condizionali o incondizionali. Le istruzioni condizionali permettono di eseguire un salto solo se una determinata condizione è verificata, altrimenti si passa alla prossima istruzione. Le istruzioni incondizionali eseguono sempre il salto, indipendentemente dalla condizione.
I moduli oggetto sono file che contengono codice macchina compilato da un linguaggio di programmazione. Questi moduli possono essere collegati insieme per formare un programma eseguibile. Durante il collegamento, il linker si occupa di risolvere i riferimenti tra i moduli, in modo che le istruzioni di salto possano puntare correttamente alle istruzioni di destinazione.
```eseguire.Una istruzione di salto può essere dipendente da una specifica condizione ed in tal caso viene detto "salto condizionale". Se la condizione è vera l'istruzione fa saltare all'indirizzo specificato dall'istruzione stessa, se invece la condizione è falsa il salto non viene effettuato e l'istruzione che verrà eseguita dopo l'istruzione di salto sarà l'istruzione che nell'eseguibile si trova dopo l'istruzione di salto stesso.
Un salto non condizionale, invece, specifica la prossima istruzione senza richiedere alcuna condizione.
La condizione da verificare di solito è il valore di alcuni bit di un registro detto flags. Questi bit sono settati durante l'esecuzione di alcune istruzioni, ad esempio le istruzioni di confronto (ad esempio, l'istruzione cmp ax, 0 controlla se il registro ax contiene il valore 0 e a seconda del risultato del confronto setta a 1 o a 0 il valore di
alcuni bit del registro flags; l'istruzione jz (jump if zero) fa saltare all'indirizzo specificato se i bit del registro flags indicano che il confronto precedente ha verificato la presenza di uno zero).