Il Sistema Operativo Linux
2004
Struttura dei sistemi operativi
Un sistema operativo non e’ un singolo software, anche se di solito chi utilizza un computer da poco tempo ha la tendenza a vederlo come tale, ma e’ bensi’ una collezione di software che consentono di utilizzare un computer. Non e’ detto che questi software siano scritti da un unico soggetto, anzi, solitamente e’ vero il contrario, sia che si parli di sistemi proprietari o di sistemi liberi; basti pensare ad esempio alle aziende produttrici di hardware che producono i driver necessari per l’utilizzo dei loro prodotti. I software che costituiscono il sistema operativo possono essere rappresentati in gruppi, detti livelli, in funzione della loro collocazione logica; si va in questo caso dal livello piu’ alto rappresentato dall’utente scendendo fino ai componenti elettronici della macchina.
Al livello piu’ basso, quindi piu’ vicino all’hardware della macchina, troviamo il kernel. Il kernel, come indica lo stesso termine nella sua traduzione letterale dall’inglese, e’ il nucleo del sistema operativo, e da esso dipende il funzionamento di tutta la macchina. In pratica si tratta dello strato software presente fra le applicazioni che girano nello spazio utente e la parte hardware composta dall’unita’ centrale e dalle varie periferiche installate nella macchina. Si occupa della gestione dei processori, della gestione della memoria, dell’assegnazione delle risorse ai vari processi in esecuzione. Il kernel si occupa anche della gestione di ogni periferica installata sulla macchina, in modo diretto se il codice necessario e’ stato incluso all’interno del kernel stesso, o indirettamente occupandosi del caricamento del codice esterno contenente i driver necessari al loro funzionamento.
I kernel possono essere di due tipi: parleremo di kernel monolitici, e Linux e’ uno di questi, se ci riferiamo ad un unico programma che si occupa di tutti gli aspetti relativi alla gestione della macchina e dei processi. Anche se alcune funzioni di questi possono essere incluse in moduli esterni da caricare all’occorrenza, di fatto poi questi moduli andranno comunque a costituire parte integrante del kernel stesso. L’alternativa e’ rappresentata dai cosiddetti microkernel, che delegano invece la maggior parte delle funzioni a programmi separati limitando al minimo le proprie funzionalita’. Questi ultimi, teorizzati da Tanenbaum, dovrebbero rappresentare la concezione piu’ moderna di kernel, ma non hanno avuto in pratica, almeno fino ad ora, quel seguito che Tanenbaum si sarebbe aspettato. Lo stesso Tanenbaum bollo’ come gia’ obsoleto il kernel Linux fin dalla sua nascita, soltanto per il fatto che era stato concepito come monolitico: i posteri gli hanno evidentemente dato torto.
Al di sopra del kernel troviamo le librerie di sistema, le quali sono composte da codice contenente le chiamate di sistema necessarie per interagire con il kernel e tutte quelle funzioni di cui ha bisogno ogni programma per svolgere il suo compito. In questo modo il programmatore che va a scrivere un’applicazione non dovra’ inserire direttamente all’interno della stessa tutto il codice necessario, ma si limitera’ a scrivere le funzioni specifiche dell’applicazione facendo in modo che vengano incluse le funzioni rese disponibili dalle librerie condivise a tutti i programmi che ne hanno bisogno, riducendo cosi’ drasticamente il carico del sistema e lo spazio occupato sul disco.
Salendo piu’ in alto troviamo tutti quei programmi di utilita’ necessari alla gestione della macchina. In questa categoria ricadono programmi che vengono avviati contestualmente all’avvio della macchina, e che quindi non vengono utilizzati spesso dall’utente ma funzionano in modo autonomo dopo essere stati appositamente configurati. Si tratta prevalentemente di software che provvedono al monitoraggio del sistema stesso o all’esecuzione di compiti ben determinati, come ad esempio l’avvio di operazioni a cadenza prestabilita o l’inizializzazione della coda di stampa.
Infine, al livello piu’ vicino all’utente, troviamo tutti quei programmi che presuppongono una stretta interazione con l’utente e che spesso costituiscono la dotazione dei comandi del sistema. Infatti i comandi di uso comune non sono altro che dei semplici programmi installati nel sistema al pari di qualunque altro software, e che invochiamo semplicemente, almeno nell’uso da linea di comando, chiamandoli per nome. Qui troviamo principalmente l’interfaccia utente, sia essa a linea di comando o grafica, tutti quei comandi e/o interfacce che ci permettono di interagire con il filesystem, varie utilita’ per la configurazione della macchina, programmi che ci permettano di editare file di testo, e cosi’ via.
Con questo avremmo gia’ un sistema funzionante, ma qualunque sistema operativo non puo’ non essere affiancato da una collezione di software per l’uso produttivo della macchina, e questa dotazione di software variera’ in funzione dell’utilizzo al quale e’ destinato quel sistema. Se ad esempio dobbiamo utilizzare la macchina come server da collegare ad internet, installeremo un server web, un server di posta, e cosi’ via. Se invece la macchina sara’ destinata a fare da workstation in un ufficio, dovremo installare un word processor, un gestionale, magari un software di disegno tecnico, eccetera.
POSIX
Linux e’ un moderno sistema operativo basato su UNIX. UNIX e’ forse il sistema operativo piu’ longevo, visto che venne introdotto nel 1970 quando ancora la diffusione dei computer presso l’utenza domestica e nei piccoli uffici era ancora (relativamente) lontana. UNIX ha conosciuto nel corso degli anni diversi cambi di proprietario e di licenza. Da UNIX vennero derivati diversi sistemi proprietari e non, e ad un certo punto si penso’ di fare in modo che lo sviluppo di questi sistemi cosi’ simili fra di loro non procedesse percorrendo strade lontane le une dalle altre. In particolare le case produttrici di software non volevano correre il rischio di dover creare vari rami di sviluppo troppo differenti tra loro per i prodotti che commercializzavano, in modo da farli funzionare su ognuna di queste piattaforme che di fatto avevano piu’ o meno tutte lo stesso target, erano cioe’ destinate alla stessa tipologia di utenza. Se da un lato UNIX rappresentava gia’ uno standard di per se’, dall’altro pero’ occorreva pagare per poter commercializzare un sistema come UNIX-compliant, e molti sistemi liberi nati nei momenti in cui parti di codice di UNIX erano state rilasciate con licenza libera, i cosiddetti sistemi UNIX-like, non potevano certo permettersi di pagare delle royalty.
Per questo motivo naquero due processi di standardizzazione, ad opera di due diversi enti, che poi confluirono in un unico standard: POSIX. Lo standard POSIX si occupa di definire alcuni concetti di base da seguire nella realizzazione del sistema operativo, in modo da garantire la portabilita’ delle applicazioni da un sistema all’altro con il minimo sforzo. La conseguenza di questo e’ una sostanziale uniformita’ di molti aspetti dei sistemi operativi, come ad esempio l’utilizzo di chiamate di sistema simili, la struttura dell’albero delle directory, i nomi dei comandi basilari ed il modo per invocarli con delle opzioni, il funzionamento di base dell’interprete dei comandi, e altre cose. In pratica, chi e’ abituato a utilizzare qualunque sistema conforme alle specifiche POSIX, si trovera’ a suo agio davanti ad un altro sistema POSIX.
La famiglia dei sistemi POSIX e’ piuttosto ampia e comprende diversi sistemi commerciali, per lo piu’ derivati direttamente da UNIX, (AIX, SunOs?, IRIX, ecc.) e molti sistemi a codice aperto come le diverse varianti di BSD e, naturalmente, Linux. In tempi relativamente recenti alla famiglia si e’ aggiunta anche Apple, che ha basato il suo sistema operativo MacOS? su BSD a partire dalla versione 10 (assumendo il nome di MacOS? X).
Linux
Linux ha un ruolo trainante nel mondo POSIX. L’espansione di Linux nei suoi 14 anni di vita, e l’interesse da parte di una folta schiera di programmatori e di software house che lo supportano, ha fatto si’ che venisse sviluppata una quantita’ non indifferente di software, e questo, unito alla facilita’ nel portare il software verso altri sistemi POSIX, ha contribuito indirettamente in modo positivo all’arricchimento della dotazione di questi. Ove vi fossero incompatibilita’ di licenza, o altre cose che non permettessero il porting diretto delle applicazioni, si e’ provveduto a realizzare uno strato di emulazione che permettesse di eseguire direttamente binari compilati per Linux; data la grande somiglianza fra questi sistemi, i programmi che mettono a disposizione questi ambienti emulati risultano estremamente efficienti. FreeBSD? e MacOSX? traggono giovamento da questo sistema.
Il supporto hardware di Linux non e’ assolutamente inferiore alla dotazione di applicativi. Oggi il kernel Linux supporta direttamente gran parte dell’hardware disponibile sul mercato. Molte case produttrici hanno contribuito a far si’ che il loro hardware venisse supportato, o fornendo le specifiche che permettessero lo sviluppo dei driver, oppure rilasciando esse stesse i moduli binari da caricare all’interno del kernel.
Linux, inoltre, e’ il sistema operativo che supporta il piu’ alto numero di piattaforme. Sebbene sia nato e si sia sviluppato su piattaforma x86, alla quale appartengono la grande maggioranza delle macchine che utilizziamo, Linux e’ stato in seguito portato anche su altre piattaforme. Al giorno d’oggi e’ disponibile una versione del kernel Linux per circa 20 diverse architetture, comprese le ultime architetture a 64 bit prodotte da AMD e Intel e derivate direttamente dall’originale x86 a 32 bit. Un settore nel quale Linux sta ultimamente riscuotendo un discreto successo e’ quello dei dispositivi embedded, sistemi che sono caratterizzati dal fatto di dover funzionare in ambiti ben specifici, la maggior parte delle volte senza dispositivi di memorizzazione di massa. Il fatto di poter compilare, grazie alla disponibilita’ del codice sorgente, una versione del kernel personalizzata che includesse solo le caratteristiche effettivamente necessarie, ha fatto si’ che sempre piu’ aziende produttrici di tali sistemi scegliessero Linux come base per lo sviluppo di sistemi operativi dedicati alla gestione di prodotti digitali. Fra questi sistemi troviamo ricevitori satellitari per la TV, video registratori digitali, computer palmari, telefoni cellulari multiuso.
Linux e’ un sistema operativo multitasking e multiutente estremamente stabile e performante. La gestione della memoria da parte del kernel di Linux e’ molto efficace. La memoria del sistema viene suddivisa in tante piccole parti chiamate pagine di memoria. Ogni programma venga lanciato sotto Linux da’ vita ad almeno un processo, il quale verra’ trasferito in un determinato spazio di memoria, e li’ verra’ eseguito. Altre aree di memoria conterranno parti di codice condiviso tra diverse applicazioni, verosimilmente librerie condivise, e aree destinate all’immagazzinamento temporaneo di dati. L’esecuzione contemporanea di vari processi e’ garantita dallo scheduler, una parte del kernel che si occupa di distribuire i cicli di CPU fra i processi che li richiedono prestando attenzione alla priorita’ di un processo rispetto ad un altro e al suo effettivo bisogno della CPU in quel dato istante. Inoltre, a differenza di altri sistemi operativi, gli applicativi in Linux, come negli altri POSIX, generalmente non accedono direttamente all’hardware. Mentre altrove questo, per ragioni architetturali, e’ quasi una prassi, l’architettura di Linux scoraggia di fatto il programmatore che delega, salvo quando effettivamente necessario, per queste operazioni il kernel.
Per tutti questi motivi, se un processo si blocca, non solo non causa il blocco di altre applicazioni che girano ognuna nel loro spazio di memoria, ma soprattutto non blocca il sistema operativo. Questo e’ vitale per qualunque sistema, come praticamente tutti i sistemi POSIX, che sono nati per essere installati su server di produzione; e’ semplicemente impensabile che una macchina che gestisca, ad esempio, il funzionamento di un’intera rete aziendale, fornendo servizi ai vari client, si blocchi improvvisamente paralizzando l’intera struttura.
Ma oltre ad essere un sistema stabile e performante Linux e’ anche un sistema con una particolare inclinazione alla sicurezza. La multiutenza in Linux, a differenza di altri sistemi che si spacciano per multiutente per il solo fatto di cambiare lo sfondo del desktop in funzione di chi ha effettuato il login, e’ realmente tale. Qualunque utente puo’ autenticarsi nel sistema anche quando vi sono altri utenti gia’ presenti, e per ogni utente vengono stabilite a priori le operazioni che si possono eseguire. Grazie alle caratteristiche dei file system utilizzati in Linux e’ possibile limitare gli accessi ai file, alle directory, e ai file eseguibili, ed inoltre il sistema operativo e’ in grado di assegnare ad ogni utente una determinata quantita’ di spazio sul disco e perfino un limite all’utilizzo delle risorse del sistema.
Ogni programma che viene eseguito sotto Linux eredita i privilegi dell’utente che lo ha lanciato, e da questo consegue che solo i programmi lanciati con l’identificatore dell’amministratore del sistema (che nei sistemi POSIX si chiama root) possono realmente essere pericolosi per l’integrita’ del sistema stesso. Fortunatamente pero’ in pratica l’amministratore non si autentica mai nel sistema come tale, ma piuttosto assume i privilegi necessari ai compiti che intende svolgere solo quando occorre. Inoltre pochi programmi vengono lanciati in esecuzione con l’identificatore di root, e si tratta per lo piu’ di programmi noti per la loro sicurezza, e questo consente a chi amministra un sistema Linux di poter andare a dormire la sera con relativa tranquillita’.