Docsity
Docsity

Prepara i tuoi esami
Prepara i tuoi esami

Studia grazie alle numerose risorse presenti su Docsity


Ottieni i punti per scaricare
Ottieni i punti per scaricare

Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium


Guide e consigli
Guide e consigli


Gestione dei Processi e Interruzioni nel Sistema Operativo, Appunti di Sistemi Operativi

Libro di Michael Dahlin, Thomas Anderson tradotto in italiano (13 capitoli).

Tipologia: Appunti

2017/2018

In vendita dal 09/09/2018

maDave
maDave 🇮🇹

12 documenti

1 / 5

Toggle sidebar

Questa pagina non è visibile nell’anteprima

Non perderti parti importanti!

bg1
Lezione 2
Architettura del computer: Un modello semplificato.
Il sistema operativo si contrappone tra gli utenti e l’hardware. Quest’ultimo lo considereremo come hardware
di base. Le ipotesi che faremo è di avere una CPU standard, una memoria principale, un set di periferiche,
l’interazione attraverso gli interrupt e infine il bus DMA.
Composizione CPU:
Registri di stato e di controllo:
•.1. Program Counter: Indirizzo dell’istruzione che si sta eseguendo
•.2. Il puntatore allo stack (SP), esso serve a memorizzare le informazioni di controllo, ovvero il
buon funzionamento dell’esecuzione di un programma
•.3. Il registro che contiene la parola di stato (PS), è un registro che contiene tanti flag binari che
dice cosa sta succedendo, o è successo durante l’esecuzione del programma.
Ciclo fetch-execute:
L’istruzione viene prelevate e poi eseguite. Una nota importante, ogni singola istruzione è atomica (questa
non viene interrotta fin quando non è stata eseguita completamente). Le periferiche quando finiscono il loro
lavoro lo segnalano attraverso le interruzioni (ovvero sospendere ciò che si sta facendo momentaneamente
e passare alla gestione della periferica, Nota: Le interruzioni possono essere abilitate come disattivate
attraverso un bit, ovviamente deve essere fatto in linguaggio macchina e non ad hardware (Possono essere
eseguite in modalità Kernel)).
Le tecniche utilizzate per risolvere i problemi dei Sistemi Operativi, sono le stesse della nostra vita
quotidiana. È importante capire come fermarsi e ripartire da dove si è stato interrotti. All’inizio si va a vedere
se esiste un’interruzione, se questo è vero => si gestire l’interruzione. Se invece non esiste un’interruzione
=> viene caricata l’istruzione il cui indirizzo è nel Program Counter, si punta a quella successiva (tutte le
istruzioni si ipotizza che sono di 4 byte), e viene eseguita l’istruzione precedente a quest’ultima.
Program Status Register: Contiene lo stato dell’ultima istruzione che è stata eseguita, se durante
l’esecuzione di quella istruzione succede qualcosa di strano viene segnalato, altrimenti non si fa nulla
(overflow, divisione per 0), e un altro bit per vedere se stiamo eseguendo in modalità Kernel o User chiamato
EFLAGS.
Problemi principali del Kernel: La sfida principale del Kernel è quella di garantire una protezione. Il
codice utente viene eseguito con privilegi ristretti poiché si vuole evitare che eventuali malfunzionamenti
possono attaccare il sistema. Alcuni esempi di programmi che non possono essere eseguiti in modalità
Kernel sono:
Scaricare una pagina con all’interno degli script (per renderla dinamica ed attraente) ad esempio
Javascript
Un programma che scarichiamo e installiamo da Internet, quanto riusciamo a fidarci?
Abbiamo scritto noi il programma.
Processo: L’attività di esecuzione di un programma con uno stato particolare, con privilegi limitati.
Nell’esempio del browser ho lo stesso programma, ma se avessi due schede, queste lavorerebbero su dati
differenti. Tutti i dati del processo sono contenuti in una struttura dati del sistema operativo chiamata
PROCESS CONTROL BLOCK (PCB). Tutti i PCB sono contenuti in una tabella (è un vettore come
struttura dati nel quale sono salvati i diritti di un processo per esempio), la dimensione della tabella mi
determina quanti processi possono essere eseguiti.
pf3
pf4
pf5

Anteprima parziale del testo

Scarica Gestione dei Processi e Interruzioni nel Sistema Operativo e più Appunti in PDF di Sistemi Operativi solo su Docsity!

Lezione 2

Architettura del computer: Un modello semplificato.

Il sistema operativo si contrappone tra gli utenti e l’hardware. Quest’ultimo lo considereremo come hardware di base. Le ipotesi che faremo è di avere una CPU standard, una memoria principale, un set di periferiche, l’interazione attraverso gli interrupt e infine il bus DMA.

Composizione CPU:

  • (^) Registri di stato e di controllo:

•.1. Program Counter: Indirizzo dell’istruzione che si sta eseguendo

•.2. Il puntatore allo stack (SP), esso serve a memorizzare le informazioni di controllo, ovvero il buon funzionamento dell’esecuzione di un programma

•.3. Il registro che contiene la parola di stato (PS), è un registro che contiene tanti flag binari che dice cosa sta succedendo, o è successo durante l’esecuzione del programma.

Ciclo fetch-execute:

L’istruzione viene prelevate e poi eseguite. Una nota importante, ogni singola istruzione è atomica (questa non viene interrotta fin quando non è stata eseguita completamente). Le periferiche quando finiscono il loro lavoro lo segnalano attraverso le interruzioni (ovvero sospendere ciò che si sta facendo momentaneamente e passare alla gestione della periferica, Nota: Le interruzioni possono essere abilitate come disattivate attraverso un bit, ovviamente deve essere fatto in linguaggio macchina e non ad hardware (Possono essere eseguite in modalità Kernel)).

Le tecniche utilizzate per risolvere i problemi dei Sistemi Operativi, sono le stesse della nostra vita quotidiana. È importante capire come fermarsi e ripartire da dove si è stato interrotti. All’inizio si va a vedere se esiste un’interruzione, se questo è vero => si gestire l’interruzione. Se invece non esiste un’interruzione => viene caricata l’istruzione il cui indirizzo è nel Program Counter, si punta a quella successiva (tutte le istruzioni si ipotizza che sono di 4 byte), e viene eseguita l’istruzione precedente a quest’ultima.

Program Status Register: Contiene lo stato dell’ultima istruzione che è stata eseguita, se durante l’esecuzione di quella istruzione succede qualcosa di strano viene segnalato, altrimenti non si fa nulla (overflow, divisione per 0), e un altro bit per vedere se stiamo eseguendo in modalità Kernel o User chiamato EFLAGS.

Problemi principali del Kernel: La sfida principale del Kernel è quella di garantire una protezione. Il codice utente viene eseguito con privilegi ristretti poiché si vuole evitare che eventuali malfunzionamenti possono attaccare il sistema. Alcuni esempi di programmi che non possono essere eseguiti in modalità Kernel sono:

  • Scaricare una pagina con all’interno degli script (per renderla dinamica ed attraente) ad esempio Javascript
  • Un programma che scarichiamo e installiamo da Internet, quanto riusciamo a fidarci?
  • Abbiamo scritto noi il programma.

Processo: L’attività di esecuzione di un programma con uno stato particolare, con privilegi limitati. Nell’esempio del browser ho lo stesso programma, ma se avessi due schede, queste lavorerebbero su dati differenti. Tutti i dati del processo sono contenuti in una struttura dati del sistema operativo chiamata PROCESS CONTROL BLOCK (PCB). Tutti i PCB sono contenuti in una tabella (è un vettore come struttura dati nel quale sono salvati i diritti di un processo per esempio), la dimensione della tabella mi determina quanti processi possono essere eseguiti.

PCB: Contiene i puntatori ai thread, ha una memoria assegnata, e altre risorse. Il nome del processo è la posizione che occupa all’interno del PCB.

  • Processo utente: Viene eseguito con diritti limitati, deve poter essere interrotto. Per poter ripartire del punto in cui sono stato interrotto, devo salvarmi alcuni dati (come ad esempio il Program Counter).

Poiché possono esserci tanti processi della stessa natura, conviene salvare il processo principale (es: il programma che tutti condividono) e dividere in thread le informazioni diverse tra di loro : in quest’ultimi ci sono solo le informazioni che mi permettono di eseguire il thread. È fondamentale che ogni processo deve poter accedere solo al suo spazio di memoria riservato.

Modalità utente vs Modalità kernel: L’utente ha dei privilegi ristretti, il kernel no. Dobbiamo poter passare da una modalità all’altra poiché per esempio l’utente può eseguire delle istruzioni non dannose, ma delle istruzioni particolare devono essere eseguite PER FORZA dal kernel. Nella modalità kernel il processo può utilizzare tutte le istruzioni macchina e utilizzare tutto l’hardware.

OSS: Per poter passare da una modalità all’altra abbiamo bisogno di ulteriore hardware che mi serve per scegliere tra due modalità.

Cambio di modalità: Quando si passa da utente a kernel?

  1. (^) Interruzioni hardware: periferiche o da timer -> (spiegato più giù). Quando arriva un’interruzione devo immediatamente gestirla, interrompendo il processo utente e passando in modalità kernel che attraverso l’interrupt vector (dove sono contenute tutte le possibili interruzioni) viene gestita.
  2. Eccezioni: overflow, divisione per 0, violazione della memoria, comportamenti malevoli (il processo deve essere ucciso).
  3. (^) SystemCall: È una chiamata di procedura del sistema operativo, sono richieste che vengono fatte dal programma al kernel. Sono delicatissime, poiché sono delle porte che mi permettono di passare da privilegi ristretti ad avere privilegi totali. ES: Se i parametri passati alle SystemCall, per esempio caratteri speciali, potrei avere effetti collaterali devastanti (l’utente ha il controllo completo del sistema).
  4. (^) Upcall: In questo caso è il sistema operativo che chiede al processo di far qualcosa (arriva un email e questa ci viene notificata, non l’ha chiesto il processo utente, ma il sistema operativo te lo segnala).
  5. OSS: Una volta gestita il passaggio da utente a kernel (per i 3 motivi spiegati su), devo ritornare al processo utente (non è obbligatorio che venga rimesso lo stesso che è stato interrotto, per esempio un processo chiama un altro processo (attraverso gli handlers)).

Cambio di modalità in modo sicuro: Si ha un vettore di tanti elementi, ognuno dei quali punta alla routine di gestione di una particolare interruzione. Quando si va ad eseguire una nuova procedura viene cambiata il program counter, per poter ritornare al punto in cui sono stato interrotto devo salvarmi il vecchio program counter, la parola di stato, ed essendo un processo devo salvarmi anche il valore dello stack pointer. Tutto ciò viene salvato in uno stack chiamato INTERRUPT STACK (di cui il kernel ne è proprietario poiché sono informazioni estremamente delicate). Finché è in esecuzione un processo utente il kernel stack è vuoto. Quando si effettua un cambio di contesto, nello stack del kernel vengono memorizzate le informazioni citate precedentemente. I registri generali vengono salvati prima dell’esecuzione della prima istruzione della gestione dell’interruzione.

IL CAMBIO DI MODALITA’ DEVE ESSERE FATTO IN MODO ATOMICO.

Mascheramento interruzioni: Le interruzioni possono essere mascherate, questo viene fatto con un altro vettore davanti al vettore interruzioni, e attraverso un and vedo se l’interruzione è abilitata o meno. Dobbiamo agire sull’hardware => deve esserci un’istruzione privilegiata in linguaggio macchina. Nel caso del processore x86, il codice operativo CLI: disattiva le interruzioni, STI: le abilita.

OSS: Un processo per poter funzionare ha i propri registri generali. Appena vengono eseguite le prime istruzioni del gestore dell’interruzione, vengono salvati i registri generali nello stack del kernel e gestire l’interruzione. Quando ho finito riporto i registri generali al processore e soltanto dopo, riporto i valori dello stack pointer, program counter e parola di stato (in un'unica istruzione); l’istruzione IRET , mi permette di fare tutto ciò (in sostanza sto facendo l’operazione inversa).

Nel caso in cui metto un altro processo in esecuzione, i dati stanno nel PCB del nuovo processo. Questi li metto nello stack interrupt => i valori del processo precedente (che sono attualmente contenuti nello stack interrupt) vengono messi nel suo PCB.

System Call

Può darsi che io sia chiamato a interrompere il mio lavoro da un’interruzione “interna”. Ci sono varie cose che gli utenti non possono fare, per esempio agire direttamente sul disco, periferiche etc. L’utente allora può chiedere al sistema operativo di eseguire alcune operazioni (delicate e pericolose).

Es: Apertura di un file, chiediamo al sistema operativo di aprire un file, o scriverci dentro.

Quindi l’handler della system call:

  • Guarda dove sono gli argomenti
  • Li copia nella sua memoria
  • (^) Li controlla.
  • Esegue la SystemCall
  • Restituisce il risultato

Booting

Il sistema operativo risiede nel disco (la parte iniziale, la memoria è permanente quindi non la prendo). Per caricarlo, esiste un pezzo di programma corto BIOS (scritto all’interno della ROM), che copia, da una posizione fissa del disco, la prima parte del sistema operativo chiamata bootloader che viene messo in esecuzione. Quest’ultimo prende il kernel, istruzione e dati e li carica in memoria trasferendogli il controllo. Quest’ultimo esegue la login app, e da qui parte il tutto.

Upcall

In UNIX sono i “segnali”. Il kernel interrompe il processo utente, poiché deve fare qualcosa per sé.

Esempio: Quando arriva un email l’utente sta facendo altre cose (tra le preferenze ho che se arrivasse, questa mi verrebbe segnalata). Come fa a sapere il nostro user agent quando arriva un email? Il sistema operativo, quando ha un’interruzione dalla scheda di rete, interrompe l’esecuzione del processo e segnala all’utente che è arrivata una nuova email attraverso le Upcall. La gestione non è fatta dal kernel, ma dall’utente. Se volessimo utilizzare le UpCall, dobbiamo avere una porzione di codice che mi permette di fare. E’ esattamente come un’interruzione ma all’interno del nostro processo, quindi avrò uno stack signal nel mio processo.

Operazioni:

  • Salvo il Program Counter
  • (^) Salvo lo stack pointer
  • Salvo i registri ed eseguo la handler della signal (upcall).