Sistemi operativi
1) Definizione di sistema operativo
Un Sistema Operativo (SO) è un software, quasi sempre molto complesso, che virtualizza una macchina reale (elaboratore elettronico) e le sue risorse, gestendone e coordinandone l'uso da parte delle applicazioni. Il SO crea un ambiente di lavoro nel quale le applicazioni vengono eseguite ed assegna (alloca) loro le risorse della macchina reale in base alle richieste e alla disponibilità. Il SO è schematizzabile come costituito da un nucleo detto Kernel (insieme di tutto ciò che può essere eseguito sulla macchina in stato supervisore, normalmente interdetto all'utilizzo da parte dell'utente, e responsabile della creazione dell'ambiente di lavoro) e da un interprete dei comandi (espressi in apposito linguaggio di comando simbolico detto JCL, Job Control Language) detto Shell (si pensi al prompt dell'MS-DOS).
Per i primi sistemi di elaborazione l'unico tipo di programmazione previsto era il Linguaggio Macchina (il programmatore si occupava di tutto: algoritmo, controllo periferiche, settaggio dei bit di stato, flag del processore, e così via). I primi SO erano semplici insiemi di Drivers, programmi che fungono da interfaccia tra l'unità centrale e i dispositivi periferici. Successivamente fu ideato il primo programma Caricatore, il cui compito era caricare programmi e dati, da schede perforate o nastri magnetici, nella memoria dell'elaboratore (un programma in linguaggio simbolico poteva richiedere per la sua esecuzione più operazioni di caricamento... prima l'opportuno compilatore che generava il testo in Assembly, poi l'assemblatore che produceva il codice oggetto in formato binario e che veniva infine caricato in memoria per l'esecuzione).
La necessità di limitare progressivamente l'uso delle schede perforate diede impulso alla creazione di macchine dedicate al trasferimento dei “contenuti” da schede perforate a nastri magnetici e, poiché se ne occupava un operatore umano, fu presto evidente che il processo di trasferimento era tanto più efficace se applicato ad un numero considerevole di schede per volta: nacque il concetto di Batch o Lotto. Si capì che la CPU di una macchina poteva essere sfruttata per eseguire alternativamente diversi Processi attivi purché questa Multiprogrammazione (e i problemi che comportava) fosse opportunamente gestita.
Il trasferimento di contenuti dalle schede perforate venne presto indirizzato alle unità a disco (che hanno il vantaggio di essere ad accesso casuale, anziché sequenziale come i nastri magnetici) e la procedura adottata prese il nome di Spooling (Spool è acronimo di Simultaneous Peripheral Operations On-Line e si riferisce allo spostamento di immagini di lavoro, da svolgere o da inviare a dispositivi periferici, attraverso la temporanea memorizzazione in un buffer, in memoria o più frequentemente su disco rigido): in pratica i contenuti delle schede perforate e dei nastri venivano massicciamente trasferiti a lotti su unità a disco, indicizzati in una tabella, in modo da poter essere poi all'occorrenza caricati in memoria su richiesta di utenti e programmi in tempi molto rapidi grazie all'accesso casuale dei dischi; naturalmente lo Spooling valeva non solo in Input ma anche in Output, consentendo di usare il disco come buffer temporaneo per l'invio differito nel tempo di dati a dispositivi periferici (la più comune applicazione dello Spool è proprio lo spooling di stampa, un sistema che attraverso una coda FIFO è in grado di somministrare ad una stampante una grande quantità di pagine, secondo i tempi che le sono congeniali, agendo in background, in modo che, durante la stampa, i tempi morti della CPU siano sfruttati dall'utente per eseguire processi a più alta priorità); con questo meccanismo era possibile caricare su disco un grosso pool di jobs, trasferirne di volta in volta una parte in memoria ed eseguirli uno per uno fino ad esaurimento, attingendo quando necessario direttamente dal disco i dati utili, con la possibilità di swappare un processo (in attesa di un evento o sospeso) su disco a vantaggio di un altro, così da tenere sempre in attività la CPU: si parla di Multiprogrammazione di tipo Batch o Batch Multiprogrammato.
Diverso approccio alla gestione di job multipli è la Multiprogrammazione di tipo Time Sharing, nel quale la potenza di calcolo della CPU viene distribuita ciclicamente, per piccole frazioni di tempo, ad N utenti attraverso N terminali (ciascun utente ha l'impressione di avere le risorse del sistema tutte per sé, il singolo processo del singolo utente diventa Running per un breve intervallo di tempo e poi resta Ready nel tempo in cui operano gli altri utenti). Nel Batch Multiprogrammato con Partizione Time Sharing i jobs degli utenti (considerati prioritari perché conversazionali, ovvero richiedono interazione con l'utente e devono sottostare a stringenti tempi di risposta) sono gestiti tramite il Time Sharing (Scheduling a Breve Termine), e solo in assenza di jobs conversazionali vengono avviati i jobs di background in modalità Batch (Scheduling a Lungo Termine); una possibile variante del modello consiste nel non fare sì che la CPU sia monopolizzata totalmente dai processi utente e prevede che una piccola frazione di tempo utile ciclico della CPU sia comunque concessa al carico di lavoro Batch.
I sistemi che forniscono risposte in tempi brevi sono classificati in Hard Real Time o Real Time (non Hard) rispettivamente se tempi di risposta estremamente rapidi sono decisivi per la correttezza del sistema oppure se tempi “medi” di risposta sono comunque accettabili. Con l'avvento dei MicroProcessori i computer divennero personal e i SO offrirono un ambiente di lavoro più user friendly: il concetto di multiprogrammazione era inizialmente assente nei primi SO (si riteneva fosse legato necessariamente ad una pluralità di utenti e comunque richiedeva potenze di calcolo proibitive per l'epoca) ma oggi è supportato da tutti i SO moderni. Negli ultimi 20 anni, infine, si è dato impulso all'aggregazione di PC per costituire Sistemi Distribuiti, comunemente detti Reti, geograficamente dislocate.
Classificazione dei sistemi operativi
Dal punto di vista dell'utente, i SO possono essere classificati in sistemi dedicati, sistemi batch (a lotti), sistemi interattivi o conversazionali, sistemi in tempo reale e sistemi transazionali. Un sistema dedicato fornisce un interprete dei comandi, la possibilità di lanciare programmi e di gestire file, il tutto dedicato ad un unico utente, caratterizzandosi per il basso sfruttamento della CPU durante le interazioni con l'utente e l'assenza di una virtualizzazione delle risorse: viene denominato Supervisore o DOS, per evidenziare rispettivamente il controllo esercitato sull'esecuzione dei lavori o il supporto alla gestione del disco.
Un sistema batch (a lotti) gestisce singolarmente l'avanzamento di lavori raggruppati in lotti memorizzati su disco, privilegiando lo sfruttamento della CPU (vantaggio) a prezzo dell'assenza di interazione con l'utente, che deve fornire il suo lavoro in via preliminare e che può attenderne il completamento anche per ore o giorni (svantaggio): le unità di I/O sono virtualizzate e ciò rende le operazioni su di esse più veloci (vantaggio).
Un sistema interattivo o conversazionale assegna, agli utenti che interagiscono attraverso terminali, le risorse per “quanti di tempo”, riducendo il tempo di risposta e dando loro la sensazione di operare su un sistema dedicato (vantaggio): questo meccanismo produce necessariamente un overhead (svantaggio).
Un sistema transazionale consente ad utenti ed applicazioni di eseguire sequenze di operazioni elementari (tipicamente manipolazione di archivi) in forma di transazioni, rispettando le proprietà di atomicità, consistenza, isolamento e persistenza. Un sistema in tempo reale esegue programmi che, interagendo con l'ambiente esterno, garantiscono a dati di ingresso risposte in tempo utile rispetto alle costanti di tempo proprie dell'ambiente esterno stesso: la correttezza del sistema dipende in modo critico dalla velocità di esecuzione. Si noti che in campo commerciale “real time” è sinonimo di conversazionale o transazionale, tuttavia i due tipi di sistemi non coincidono.
In base all'organizzazione interna possono essere inoltre classificati in sistemi monoprogrammati, sistemi multiprogrammati, sistemi time-sharing (a partizione di tempo) e sistemi ad uso speciale. In base infine all'architettura del sistema di elaborazione su cui sono calati, i SO possono essere classificati in SO per sistemi di calcolo monolitici, per sistemi di calcolo distribuiti e per sistemi di calcolo paralleli.
Struttura a livelli del SO
Il SO offre all'utente dei servizi e questi ne ha visibilità attraverso i comandi che consentono di richiamarli: i comandi espliciti sono gestiti dalla Shell, i comandi impliciti sono invece generati da un compilatore/assemblatore. Le principali funzioni offerte dal SO e viste dall'utente possono essere raggruppate in funzioni per la gestione dei lavori (qualificarsi nei confronti del sistema, richiedere l'allocazione di risorse, richiedere l'esecuzione di una o una successione di azioni), supporti per la programmazione (programmi per il trattamento testi, per la gestione delle librerie, per il supporto al testing e al debugging del codice dei programmi), meccanismi di I/O (mascheramento delle modalità con cui le operazioni di I/O vengono eseguite, mascheramento dei conflitti nell'uso di periferiche condivise, gestione dei malfunzionamenti) e funzioni di gestione archivi (accesso tramite riferimenti logici, garanzia di sicurezza negli accessi e dell'integrità dei dati).
Una tipica schematizzazione del SO a livelli consente di riconoscere 8 livelli, via via più bassi quanto più ci si avvicina alla macchina reale, via via più alti quanto più le macchine virtuali sono astratte e mettono a disposizione funzionalità evolute:
- 1) Programma Utente
- 2) Shell Interprete dei comandi
- 3) Utility Supporto allo sviluppo (editor, testing, debugging) dei programmi, fogli elettronici e altre utilità
- 4) File System Gestione (con controllo degli accessi) di blocchi di informazioni logicamente strutturati registrati su disco, ovvero i File
- 5) Periferiche Virtuali Simulazione di periferiche virtuali (implementazione primitive I/O e gestione malfunzionamenti)
- 6) Memoria Virtuale Allocazione memoria ai programmi che la richiedono usando se necessario la memoria secondaria (gestione corrispondenza indirizzi fisici / logici, caricamento / scaricamento / swapping, protezione dalle violazioni)
- 7) Nucleo Allocazione della CPU ai processi (Scheduling), primitive di gestione degli eventi asincroni e di sincronizzazione (richiamate tramite SVC)
- 8) Hardware Macchina Base o Reale
Ogni macchina virtuale di livello superiore utilizza i servizi offerti dalla macchina virtuale (eventualmente reale) di livello inferiore, che espone una apposita interfaccia; i livelli (2) e (3) sono da considerarsi paritari, ovvero non necessariamente dipendenti l'uno dall'altro; i livelli da (1) a (3) formano un macrolivello costituito da processi dedicati, mentre i restanti dal (4) al (7) costituiscono il Kernel del SO in senso esteso; al livello (8) c'è un'unica CPU, Memoria, Disco e un insieme discreto di periferiche; il livello (7) costituisce una macchina virtuale rispetto alla quale tutti i processi vedono ciascuno una propria CPU; il livello (6) costituisce una macchina virtuale rispetto alla quale tutti i processi vedono ciascuno una propria CPU e una propria memoria; il livello (5) costituisce una macchina virtuale rispetto alla quale tutti i processi vedono ciascuno una propria CPU, una propria memoria e un insieme non condiviso di periferiche... ogni livello insomma astrae sempre di più la macchina reale facendola apparire progressivamente, in ogni suo componente, dedicata al singolo processo attivo.
Interrupt e Supervisor Call
Una Interrupt o Interruzione è il più facile meccanismo (comunemente adottato da tutti i sistemi programmabili e da tutti i modelli di CPU sul mercato) che consente di interrompere e modificare il normale flusso di esecuzione delle operazioni da parte della CPU al verificarsi di un evento. Una Interrupt Hardware è generata da dispositivi esterni alla CPU e serve a comunicare il verificarsi di un evento generalmente asincrono (un dispositivo I/O informa la CPU che è disponibile a fornire o ricevere dati, il clock segnala la scadenza di un quanto di tempo, ...).
Un Interrupt Software o Trap è generata invece da istruzioni assembly (INT x, SYSCALL, ...) assimilabili a chiamate a sottoprogrammi con le quali un processo richiede una System Call o Supervisor Call (esecuzione di una primitiva del SO, accesso diretto a risorse controllate dal SO, ...) oppure segnala una exception (tentata divisione per zero, la violazione della memoria, disconnessione dalla rete, errore di trasferimento dati, ...). Le interruzioni possono inoltre essere abilitate o disabilitate con apposite istruzioni assembly (STI Set Interrupt e CLI Clear Interrupt).
Una Interrupt Request o IRQ o Richiesta di Interruzione (usata spesso erroneamente come sinonimo di Interrupt) è il meccanismo con cui lo specifico evento viene segnalato alla CPU, inviando opportuni segnali ai pin fisici di collegamento della CPU stessa: a seconda dello stato in cui si trova la CPU, la IRQ può essere servita o accantonata per essere eseguita in un secondo tempo, e questo perché gli IRQ sono organizzati in gerarchie di priorità e una IRQ di livello più basso può essere scavalcata - e l'interruzione da essa generata a sua volta interrotta - da una IRQ di livello alto, a meno che non sia associata ad una Non Maskable Interrupt o NMI, che non può essere accantonata e va eseguita immediatamente. Diversi tipi di CPU generalmente standardizzano i loro IRQ in modo che ad un certo IRQ corrisponda sempre lo stesso tipo di evento: tasto premuto sulla tastiera, comunicazione in arrivo su porta seriale, e così via.
La gestione degli Interrupt prevede che, quando la CPU riceve una IRQ, la prima esigenza sia determinare quale dispositivo l'ha generata e questo può essere fatto con due diversi sistemi, la scansione degli interrupt (o polling) e la vettorizzazione degli interrupt. Nel primo caso si effettua l'interrogazione di ciascuno dei dispositivi collegati per una eventuale conferma della richiesta di interruzione inviata. Nel secondo caso si usa invece un opportuno circuito integrato detto Programmable Interrupt Controller o PIC, che riceve in ingresso un certo numero di linee di IRQ usate appunto dai dispositivi per richiedere un'interruzione: quando il PIC riceve una IRQ, si occupa di segnalare alla CPU tale richiesta di interruzione e - se la CPU conferma la richiesta (potrebbe non confermarla se le interruzioni sono disabilitate) – deposita nel bus dati l'indice di un Vettore di Interrupt o Vettore di Interruzione, cioè l'indice che consenta di indirizzare una vera e propria tabella chiamata anche Interrupt Vector Table o Interrupt Descriptor Table, in cui siano memorizzati gli indirizzi delle diverse Interrupt Service Routine o ISR o Interrupt Handler associata alle interruzioni, ovvero funzioni di tipo callback (una funzione specializzata passata come parametro a un'altra funzione che invece è generica) che contengono le operazioni la cui esecuzione è prevista nel caso di ogni specifica interruzione.
In sintesi, quando la CPU riceve una IRQ, recepisce un indice di interruzione, lo usa per indirizzare la tabella o vettore delle interruzioni e trova un puntatore ad una specifica procedura, predisposta dal programmatore o più spesso dal SO; affinché il meccanismo di interruzione funzioni correttamente, è necessario che l'esecuzione della ISR sia trasparente al processo interrotto e quindi serve che la CPU, prima di mandare in esecuzione la ISR, faccia un salvataggio del contesto del processo in corso in un apposito stack e che poi, a seguito del ritorno dall'interruzione tramite l'istruzione RTE, lo ripristini com'era; poiché l'interruzione va gestita rapidamente non va perso tempo a salvare tutto il contesto del processo (ad esempio le sue variabili globali) ma solo quello che effettivamente verrà modificato dall'ISR, e siccome la CPU non conosce in anticipo che cosa l'ISR modificherà, quando si verifica una interruzione essa provvede ad effettuare il salvataggio almeno del Registro di Stato del processo o Program Status Word o PSW (un'area di memoria o un registro che contiene informazioni sullo stato dei programmi in esecuzione sul SO) e del Program Counter o PC.
Il compito del SO, relativamente al meccanismo di gestione degli interrupt, consiste essenzialmente nel predisporre gli opportuni sottoprogrammi di gestione degli interrupt per tutte le periferiche, così come i sottoprogrammi di gestione delle eccezioni, inserendo i loro indirizzi nella tabella degli interrupt.
Si definiscono istruzioni privilegiate di un SO quelle istruzioni riservate all'uso esclusivo da parte del SO (allo scopo di rendere impossibili le interferenze reciproche di processi concorrenti) concernenti essenzialmente la manipolazione del sistema delle interruzioni, la commutazione della CPU tra processi, le operazioni di I/O, l'accesso ai registri utilizzati dall'hardware per la protezione della memoria e l'arresto della CPU (halt). La maggioranza degli elaboratori opera in due modalità distinte, il Supervisor Mode (modo privilegiato, system mode, monitor mode) e lo User Mode (modo utente, modo non privilegiato) e le istruzioni privilegiate sono permesse solo nel Supervisor Mode; il passaggio dal modo utente al modo privilegiato ha luogo automaticamente al verificarsi di una delle 4 seguenti condizioni: un processo utente effettua un richiamo del SO (Supervisor Call o SVC o System Call) allo scopo di eseguire una funzione che richieda l'esecu
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.
-
Affidabilità di Sistemi Software Complessi
-
Appunti di Ingegneria del Software
-
Riassunto processo e sviluppo del software
-
Esercizi/appunti di ingegneria del software