Translate!

English Chinese (Simplified) French German Japanese

Newsletter: iscriviti!

Devi prima registrarti per poterti iscrivere ad una newsletter.
No account yet? Register

Statistiche

statistiche contatore

Siti Amici

I fondamenti di un sistema operativo, del software e l'interazione con l'hardware
Valutazione attuale: / 9
ScarsoOttimo 
Scritto da Administrator   
Lunedì 04 Maggio 2009 08:18

sistemi operativi

Non il classico articolo sull'ultimo sistema operativo Windows, Mac o Linux bensì una sorta di guida alla scoperta del generico sistema operativo visto da un punto di vista più propriamente tecnico, senza però calarci troppo in incomprensibili e superflui tecnicismi.

Normalmente ciò che verrà trattato di seguito è affrontato in qualunque (buon) Istituto Tecnico Industriale ad indirizzo informatico. Ovviamente mi riferisco ad una introduzione molto generale sui sistemi operativi. In questo articolo ho voluto raccogliere le mie conoscenze apprese in merito e semplificarle ulteriormente affinchè sia facile comprendere a grandi linee ciò di cui un sistema operativo si compone e come deve regolamentare l'accesso  delle richieste software all'hardware sul quale è installato.
 
Definizione e caratteristiche di un SO

Il sistema operativo è il gestore delle risorse (CPU, RAM, dispositivi I/O, memoria di massa) dell’elaboratore. Nella gestione di una risorsa hardware, il sistema operativo deve seguire quattro passi:

  • Deve tener traccia della risorsa (sapere cosa sta facendo in un determinato momento);
  • Deve avere una politica di allocazione delle risorse per determinare quale processo prenderà una risorsa, quando e per quanto tempo;
  • Deve allocare effettivamente la risorsa;
  • Deve deallocare la risorsa quando il processo non ne ha più bisogno.
Il sistema operativo è composto da moduli (gestore della memoria, dei file, della CPU,...) ed ognuno dovrà utilizzare queste quattro funzioni fondamentali.

Una classificazione intuitiva dei sistemi operativi è la seguente:

  • sistemi operativi monoprogrammati, in grado di svolgere un compito per volta (ad es. il DOS);
  • sistemi operativi multiprogrammati, che consentono di eseguire più programmi contemporaneamente e possono essere monoutente se è un solo utente a farlo o multiutente se ci sono in esecuzione più software contemporaneamente e usati da utenti diversi in contemporanea (sistemi operativi di questo tipo sono Windows Server, Linux,…);
  • sistemi operativi distribuiti, in grado di supportare la rete: le risorse non sono tutte su una macchina ma sono distribuite su più macchine.

Secondo l’uso, i sistemi operativi si classificano in:

  • di tipo batch, che hanno pochissima interazione con l’utente e svolgono operazioni sequenziali (file *.bat);
  • time-sharing, che dividono il tempo della CPU assegnandolo e distribuendolo equamente per ogni utente;
  • real time, in grado di rispondere in tempo reale a cambiamenti di situazione, agendo appunto in tempo reale (o meglio tempo utile). Questi sistemi operativi sono usati nei controlli di processo (ad esempio nelle industrie con catena di montaggio);
  • di teleprocessing, che prevedono la comunicazione a distanza. Oggi tutti i sistemi operativi, usando la rete, possono lavorare in modalità teleprocessing eseguendo elaborazioni a distanza;
  • dedicato, che esegue un compito ben preciso (ad esempio i sistemi operativi delle console, che devono far funzionare al meglio la grafica dei giochi, o quelli dei cellulari).

I moduli di un SO

Il sistema operativo è un software estremamente complesso, per cui è necessaria una certa organizzazione per poterlo realizzare correttamente. Il sistema operativo si divide in moduli, ciascuno dei quali ha uno specifico compito e sono interconnessi tra loro. La struttura gerarchica di un sistema operativo, che si compone di moduli, è la seguente:

  • iniziando dal basso, troviamo l’hardware, il livello 0;
  • c’è poi il kernel, la parte del sistema operativo che interagisce direttamente con l’hardware;
  • il gestore della memoria, che gestisce la memoria centrale;
  • il gestore dell’input/output, che gestisce le unità di input/output;
  • il file system che si occupa della gestione dei file;
  • l’interprete dei programmi (explorer.exe in Windows);
  • programmi ed utilità.

I moduli dovrebbero essere quanto più possibile indipendenti tra loro: sostituendo anche solo un modulo, il sistema operativo deve essere in grado di continuare a funzionare correttamente.

 

Esecuzione di software su un sistema operativo: job, processi e processore

Il job è la singola richiesta di utilizzo di una risorsa, presente all’interno del programma in via di esecuzione.

Il processo è l’esecuzione di un job: è il job associato alla risorsa richiesta.

Il processore è quel dispositivo che consente di eseguire i processi.

Il ciclo di vita di un processo segue il seguente schema:
 
ciclo di vita di un processo
 
Il ciclo di vita di un processo è la vita che ha un programma dal momento in cui viene eseguito fino a quando non viene terminato. Il programma, dovrà attraversare le seguenti fasi:
  • lancio: il software in questa fase viene avviato e va in esecuzione nel calcolatore;
  • se poi l’elaboratore possiede tutte le risorse richieste dal programma, si transita in una fase di acquisizione, altrimenti il programma termina;
  • si passa poi nella fase di pronto, se tutte le risorse sono disponibili tranne la CPU, dove il programma diviene un processo vero e proprio;
  • nella fase di pronto, ci sono tutti i processi in coda per ottenere la CPU; quindi ogni processo, a turno, occuperà la CPU per un certo periodo di tempo Δt (brevissimo), dopodiché tornerà da capo in pronto liberando la CPU e rendendola disponibile per gli altri job in coda, a meno che non ha già terminato e quindi va in terminato. Potrebbe anche succedere che, durante il tempo Δt, il job richieda di fare un input da un dispositivo, quindi va nella fase di attesa da cui verrà risvegliato non appena l’input sarà completato dopodiché tornerà nella fase di pronto a riprendere la coda.

Il traffic controller è un modulo del sistema operativo che analizza lo stato delle periferiche e, quando queste sono attive, risveglia il job riportandolo poi alla fase di pronto. Il process scheduler decide quali fra i processi in coda, in stato di pronto, può ottenere la CPU. Il job scheduler fa transitare dallo stato di acquisizione a quello di pronto.

Il tempo totale di esecuzione di un programma è dato dalla somma dei tempi dei job più i tempi di attesa w (wait), ovvero quando il job attende i dati che devono arrivare dalle periferiche di I/O. Sfruttando i tempi di attesa, due programmi possono essere eseguiti in parallelo. Tutto ciò è appunto possibile se ci sono tempi di attesa, altrimenti se non ce ne sono non vale la pena nel caso di singola CPU; se però la CPU è coadiuvato da altri chip come il DMAC si creano tempi di attesa per la CPU che resta inutilizzata e quindi è possibile sfruttarla.

 

Programmazione parallela

Tutti i moderni linguaggi di programmazione dispongono di costrutti per programmare in parallelo. Il costrutto fork/join è usato in C: quando si vuol ad esempio farm andare una procedura in parallelo con l’esecuzione del programma principale, si invoca il comando fork seguito dal nome della procedura. Il join, a cui andrà sempre affiancato il nome della procedura, serve al programma principale per interrogare il processo (procedura) che si sta eseguendo in parallelo e, nel caso la procedura non è ancora terminata, il programma ne attenderà il termine. In Java si usano i thread per eseguire azioni in parallelo, mentre per altri linguaggi esistono altri costrutti per la programmazione in parallelo tra cui il cobegin/coend.

 

La programmazione concorrente: problema nell'attribuzione della risorsa hardware

Nella programmazione concorrente, due o più processi concorrenti competono per l’attribuzione di una stessa risorsa, cercando di usarla nello stesso istante. Dunque il sistema operativo deve poter regolamentare l’utilizzo e l’accesso alle risorse. Due processi che concorrono possono trovarsi in tre situazioni distinte:

  • cooperazione: c’è un processo produttore ed un processo consumatore che consuma ciò che ha prodotto il processo produttore. Un esempio è la masterizzazione: il software di masterizzazione, quando lanciato, è suddiviso in due processi: un produttore che preleva i dati dall’hard disk e consumatore che scrive i dati prelevati dal produttore su CD; produttore e consumatore si scambiano le informazioni attraverso un’area di memoria chiamata buffer;
  • competizione: entrambi i processi cercano di utilizzare la stessa risorsa;
  • interferenza: è un’anomalia in cui se si lancia un processo il suo risultato dipende da quando lo si manda in esecuzione. In questa situazione il sistema operativo non sa regolamentare l’accesso ad una risorsa e i due processi la ottengono contemporaneamente; immaginiamo due processi che vogliono accedere alla stampante per stampare: se lo fanno entrambi contemporaneamente il documento stampato sarebbe una mescolanza di ciò che i due processi vorrebbero stampare distintamente.
La competizione tra processi c’è sempre, la cooperazione avviene spesso e l’interferenza non dovrebbe avvenire mai. Per risolvere il problema dell’accesso simultaneo alle risorse da parte dei processi, entra in gioco il kernel del sistema operativo, che contiene le funzioni che regolamentano l’accesso alle risorse; il ciclo pronto/esecuzione/attesa, così come le interruzioni, sono ad esempio gestiti dal kernel.

I semafori sono l’idea più facile per consentire l’accesso ordinato ad una risorsa. Si tenga presente un semaforo con una luce rossa (risorsa impegnata e quindi non accessibile) ed una luce verde (risorsa libera, a disposizione di un processo). Il principio del semaforo utilizza due funzioni elementari del sistema operativo (dette primitive), che usano una variabile s (0: risorsa occupata ; 1: risorsa libera); le due funzioni sono P(s) e V(s). La funzione P(s) viene richiamata dal processo che vuole occupare la risorsa e se dal controllo risulta che s=1 allora la risorsa è libera e accessibile, altrimenti in caso contrario (0) bisognerà aspettare finché il flag scatti a 1. Quindi a questo punto per far sì che la risorsa venga attribuita al processo viene settato s=0 (occupato). Infine richiamando la funzione V(s) s verrà settato ad 1, per liberare la risorsa, il che significa che la risorsa tornerà ad essere nuovamente disponibile per altri processi:

semaforo
s rappresenta il semaforo, ed è la generica variabile che il sistema operativo assegna per ogni risorsa; la stessa variabile è condivisa per tutti i processi in esecuzione nel sistema.
 
Ma nel caso di processi concorrenti in cooperazione, produttore e consumatore, riprendendo il discorso della masterizzazione e dell’utilizzo del buffer, non funzionano le due primitive di prima, in quanto se ad esempio, essendo produttore e consumatore concorrenti, accede per primo il consumatore al buffer, non legge niente, quindi non basta un semaforo ma ne servono due: s1 ed s2. Dunque si presenta questa situazione:
semaforo

In questo modo, alla fine ognuno deve liberare il semaforo dell’altro.

Supponiamo di avere ad esempio più di un buffer utilizzabile; si potrebbero avere cinque semafori per ogni buffer (s1, s2, s3, s4, s5). Ma usando il semaforo generalizzato, che si rende utile nel caso di una risorsa hardware con molteplicità n, si chiede non più se s=1, ma se s>0; questo perché ci può essere più di un uso della risorsa. Quindi se s=3, viene decrementato di 1 il numero di processi che possono usare la risorsa e si va avanti. Quando un processo libererà il buffer, s verrà incrementato di 1 e l’eventuale processo in attesa potrà usare il buffer.
 
semaforo

Il semaforo generalizzato diviene semaforo binario se il valore di partenza, S, è ad 1.

 

Lo stallo: spiacevole situazione da evitare

Un sistema è in stallo (o in dead lock) quando i processi non riescono ad andare a termine. Lo stallo è una situazione imprevedibile ma verificabile a causa del numero di processi elevato in esecuzione nel sistema. Un esempio di stallo è dato dal seguente grafico, detto grafo di allocazione delle risorse:

stallo

Nei cerchi vengono indicati i processi, mentre nei quadrati le risorse. Quando una freccia va da una risorsa a un processo vuol dire che quella risorsa è assegnata a quel processo; quando invece la freccia va dal processo alla risorsa vuol dire che il processo richiede l’uso della risorsa per andare avanti. Nella situazione in esempio, P1 ha assegnato R1 e per andare avanti ha bisogno di R2, mentre P2 ha assegnato R2 e per andare avanti ha bisogno di R1. Questa, più che stallo, è detta attesa circolare: solo se tutti i processi del sistema sono in attesa circolare il sistema è in stallo.

Per risolvere queste situazioni di contesa delle risorse si usano i semafori, tuttavia va eliminato il busy waiting, ovvero quell’attesa occupata che si verifica quando il processo esegue il P(s) per interrogare circa la disponibilità di una risorsa. Difatti così facendo il processo impegna la CPU senza fare nulla. Non è uno stallo ma è qualcosa che bisognerà evitare nella realizzazione dei semafori. Difatti queste primitive di base sono superate dai monitor, funzioni efficienti per garantire la sincronizzazione tra processi.

Può avvenire uno stallo se:

  • Il sistema operativo effettua una allocazione parziale delle risorse: il sistema operativo assegna cioè le risorse ai processi man mano che i processi le richiedono, però questo può portare ad uno stallo poiché se invece prima che parte il programma il sistema operativa assegna immediatamente tutte le risorse, sicuramente la risorsa sarà destinata a quel singolo processo. Ma in termini di prestazioni è uno svantaggio;
  • Negazione del prerilascio forzato: se il sistema operativo non riesce a sottrarre la risorsa del processo;
  • Attesa circolare: ogni processo in coda aspetta delle risorse da un altro processo per poter andare a termine.

Uno stallo si può prevenire, o riconoscerlo ed eliminarlo:

MECCANISMI DI PREVENZIONE:

  • Allocazione globale delle risorse: le risorse vengono date tutte e subito al processo (tecnica opposta all’allocazione parziale);
  • Allocazione gerarchica delle risorse: viene assegnato un livello (numero) ad ogni risorsa e il sistema operativo, quando un processo richiede una risorsa di un certo livello, controlla il livello massimo di risorse che il processo detiene e, se ha una risorsa di livello inferiore rispetto a quella che vuole, deve rilasciare la risorsa in suo possesso per potervi accedere;
  • Algoritmo del banchiere: il sistema operativo analizza le richieste di risorse da parte dei processi e decide di assegnare le risorse a un processo in modo che ne rimangano a sufficienza per almeno un altro processo per terminare il suo lavoro. Tuttavia bisognerà conoscere il numero massimo di risorse che il processo utilizzerà durante il suo lavoro e a priori non si sa sempre; inoltre nel caso reale l’algoritmo del banchiere è molto più complicato.

MECCANISMI DI RICONOSCIMENTO E “CURA”:

  • Il sistema operativo termina tutti i processi, anche se in realtà non sono tutti ad aver generato lo stallo;
  • Il sistema operativo termina uno per volta i processi, fin quando lo stallo viene eliminato;
  • Rilascio forzato di una risorsa: se c’è un processo che usa molte risorse o una risorsa molto ricercata dai processi, il sistema operativo costringe il processo a rilasciare quella risorsa.

Lo starvation è una situazione di blocco individuale, in cui c’è un certo numero di processi che non va avanti mentre comunque gli altri continuano il loro lavoro: ad esempio se il sistema operativo assegna le risorse solo ai processi a priorità alta, ignorando quelli a priorità bassa.  

 

Brevi cenni sugli albori dei sistemi operativi

Mentre Windows 95 e Windows 98 sono diversi da Windows 2000 in quanto molto legati a MS-DOS, Windows NT era già un sistema operativo di classe server, distaccato dal DOS, e Windows 2000 riprende NT irrobustendolo e rendendolo più stabile e con una gui più avanzata, facendolo diventare un sistema operativo anche per il client. Windows 2000 è organizzato su tre livelli: modo utente e modo kernel (che si occupa della gestione di interrupt e servizi richiesti dagli altri moduli del SO) scritti in linguaggio C object-oriented, e il modo HAL (hardware abstraction layer) scritto in assembly. Le applicazioni usano le API (application program interface), che sono delle funzioni standard usate per accedere a determinati sottomoduli del sistema operativo.

UNIX è un sistema operativo nato alla fine degli anni Sessanta che poteva funzionare solo su macchine con hardware dell’epoca potenti (mainframes). Era multitasking e progettato per un uso interattivo. Dalla prima versione di Unix ne sono nate altre, dopodiché Linus Torvald, come tesi universitaria, creò un piccolo kernel con un minimo di funzioni di base per un sistema operativo e pubblicò il suo risultato su internet; grazie dunque alla “pubblicità” di internet, ma anche all’hardware del tempo più potente, in poco tempo ha avuto supporto da altri utenti e in pochi anni è nata una comunità di sviluppo del sistema operativo che sarà chiamato Linux, le cui caratteristiche principali sono: multitasking; una o più shell (interprete dei comandi, interfaccia a riga di comando molto usata in ambiente server in sostituzione di una GUI); un file system con struttura ad albero; supporto alla rete con meccanismi di protezione elevati. Nelle prime versioni, il kernel di Linux era monolitico e dunque doveva essere caricato interamente nella RAM, mentre in seguito venne diviso in moduli in modo da caricare in memoria solo i moduli necessari. In linux l’unità fondamentale è il processo, inteso come una serie di azioni in esecuzione. Ogni programma genera più processi e in alcuni momenti i processi sono in attesa di ricevere una risorsa (sono in wait, “addormentati”). Linux utilizza il fork all’interno di un programma in esecuzione per generare un nuovo processo figlio, identico al processo padre, ma individuato da un codice numerico (PID) differente, che potrà svolgere in parallelo altre operazioni. Linux è scritto interamente in C classico, non object oriented.

sistemi operativi
Commenti (6)add comment
137
pindol: ...
Complimenti bella guida
1

maggio 04, 2009
62
admin: ...
Grazie! smilies/cheesy.gif
2

maggio 04, 2009
0
alexander: ...
Grande! Purtroppo vado ad un liceo classico e queste cose non le farò mai a scuola, stasera con calma me lo leggo bene
Grazie mille e complimenti per l'ottimo sito smilies/wink.gif
3

maggio 04, 2009
62
admin: ...
Grazie a te per avermi fatto visita! smilies/wink.gif
4

maggio 04, 2009
0
Aldo Marturano: ...
Fatto molto bene, davvero utile nella sua semplicità.

Grazie mille
5

luglio 13, 2009
62
admin: ...
Grazie, Aldo! smilies/smiley.gif
6

luglio 13, 2009

Scrivi commento
più piccolo | più grande

busy

Articoli correlati:
Articoli più recenti:
Articoli meno recenti:

 
Copyright © 2009 InformaticaEasy. Tutti i diritti riservati.
E' vietata la riproduzione di qualunque contenuto del sito senza aver richiesto autorizzazione.
  Le recensioni e gli articoli sono scritti e di esclusiva proprietà di Paolo Vinella; se presenti su altri siti/forum, sono stati inseriti dallo stesso
 
Sito realizzato e gestito da Paolo Vinella.