9  Il sistema operativo

Data di Pubblicazione

23 settembre 2026

La prima cosa che viene immediatamente dopo l’hardware è il sistema operativo (o OS, per operating system), che per alcuni versi è il programma più importante di tutti—quello che gestisce tutte le risorse all’interno del computer in modo che gli utenti e le loro applicazioni possano utilizzarle.

Tra le altre cose, il sistema operativo:

Esistono letteralmente dozzine di sistemi operativi—da quelli mainstream fino a quelli di nicchia che operano su sistemi embedded specializzati. Con ogni probabilità avrete sentito parlare (e forse utilizzate) Windows, Mac-OS e GNU-Linux; Android, che utilizza il kernel Linux, e iOS sono pure sistemi operativi, in questo caso dedicati ai dispositivi mobili.

Questo sarà un capitolo molto breve, in cui elencheremo alcuni semplici fatti a proposito di due aspetti specifici: il terminale (o shell), che abbiamo già incontrato nel Capitolo 2, ed il filesystem, che è l’infrastruttura alla base dell’archiviazione dei file.

9.1 Il terminale

Il programma che in un computer espone all’utente i servizi forniti dal sistema operativo (e.g., gestione di file e processi, esecuzione di programmi, controllo e configurazione della macchina) prende generalmente il nome di shell o, a seconda del contesto, terminale o prompt dei comandi. La shell è un interprete testuale da linea di comando deputata al processamento e all’esecuzione dei comandi inseriti dall’utente.

In un mondo in cui smartphone e tablet hanno ormai preso il sopravvento, la shell può apparire come una curiosità storica più adatta ad un corso di archeologia che ad uno di computazione. Le interfacce grafiche, che un tempo erano percepite come un layer interattivo al di sopra del terminale, sono ormai essenzialmente l’unico modo in cui la maggior parte di noi interagisce con i computer; e l’introduzione dei touch screen, se da una parte ha permesso di implementare modalità di interazione nuove ed estremamente efficaci, dall’altra ci ha allontanato ancora di più dalla realizzazione di questo semplice fatto: ogni volta che fate qualcosa su un computer, uno smartphone, o un tablet, questo qualcosa può essere espresso a basso livello come una serie di comandi. E se non aveste un touch screen o un’interfaccia grafica, questi comandi li digitereste nel terminale.

La domanda è allora: il terminale è ancora rilevante ai tempi degli smartphone? E la risposta, per noi, è sicuramente sì, almeno per il momento. Ed il motivo è molto semplice: quando analizzate dati—e specialmente grandi quantità di dati—vi troverete spesso a fare operazioni complesse e ripetitive. Ora, se ci pensate un secondo, questa è una pessima combinazione di cose sia per il mouse che per il touch screen. Il terminale, invece, si presta naturalmente ad automatizzare i task.

Avviso

In un mondo in cui i cambiamenti indotti a tutti i livelli dalla cosiddetta intelligenza artificiale, che procedono ad una velocità incommensurabile alle dinamiche umane, è difficile prevedere se la risposta sarà la stessa tra \(5\) o \(10\) anni. Per quel che conta, è difficile prevedere cosa di queste note sarà ancora rilevante tra \(5\) o \(10\) anni. Sarà mia cura rimuovere questa sezione quando l’AI prenderà il controllo del mondo e le persone non avranno più la necessità di utilizzare la tastiera.

9.2 Il filesystem

Il filesystem è l’infrastruttura deputata all’organizzazione di file e cartelle, e costituisce una delle astrazioni fondamentali che il sistema operativo mette a disposizione dell’utente—provate per un attimo a immaginare come sarebbe la vita se, per leggere da/scrivere su disco una foto dovessimo fisicamente indirizzare ogni bit di memoria scrivendo il contenuto di ciascun pixel, e dovessimo oltretutto farlo tenendo esplicitamente in conto le specificità dell’hardware nel nostro calcolatore.

Cominciamo, al solito, da un po’ di nomenclatura.

File: unità fondamentale di archiviazione dei dati.

Percorso o path: stringa che identifica univocamente un file all’interno della gerarchia del filesystem.

Da un punto di vista strettamente funzionale il filesystem fornisce accesso ai file presenti su un dispositivo di archiviazione di massa. Oltre ai dati, il filesystem è tipicamente responsabile della gestione dei metadati ad essi associati, e.g., la dimensione su disco, le date di creazione e/o ultimo accesso, i permessi.

9.2.1 Percorsi

La quasi totalità dei filesystem moderni supporta l’organizzazione di file all’interno di cartelle (anche note come directory, o folder) ed ha una natura gerarchica, nel senso che prevede la possibilità per ciascuna cartella di contenere altre cartelle. Da un punto di vista logico la posizione di un file può essere vista come una foglia in un albero, in cui le cartelle rappresentano rami via via più piccoli a partire da una radice. Il percorso, allora non è altro che la stringa che, a partire da questa radice, identifica tutte le cartelle intermedie fino a quella che contiene il file.

Nota

Curiosamente, questo è vero anche per il vostro smartphone ed il vostro tablet, anche se l’ecosistema tipico di un sistema mobile sembra fare di tutto per nasconderlo: le interfacce utente dei sistemi moderni sono così lontane dal filesystem, che la semplice domanda “dove è questo file?” è diventata sorprendentemente complicata per i più. Cosa vuol dire “dove”? So scorrere le foto con il dito nella galleria, e questa è l’unica cosa che importa, no?

Per esempio, sotto GNU/Linux, la stringa

/home/lbaldini/Documents/presentazione.pdf

indica un possibile percorso ad un file pdf in cui

  • / è la radice, o root, del filesystem;
  • presentazione.pdf è il nome del file (e, tecnicamente, pdf è l’estensione);
  • tutti gli elementi intermedi sono cartelle, contenuta l’una nell’altra da sinistra a destra: la radice contiene una cartella chiamata home, la quale contiene una cartella chiamata lbaldini, e così via.

Il carattere / riveste un ruolo speciale sotto GNU/Linux e Mac-OS, perché è utilizzato come separatore. E siccome il mondo sarebbe troppo semplice se tutte usassimo le stesse convenzioni, sotto Windows il carattere che riveste il ruolo di separatore nei percorsi è il backslash \. Ma facciamo ordine.

Separatore: carattere speciale utilizzato dal sistema operativo per separare i vari elementi del percorso ad un file o una cartella. GNU/Linux e Mac-OS usano il carattere / (slash) come separatore, Windows usa il carattere \ (backslash).

Estensione: combinazione di caratteri (tipicamente tre o quattro) che indica il tipo di file, ed è separata dal nome del file vero e proprio da un carattere . (punto).

Potremmo spendere letteralmente giorni a parlare di filesystem in astratto e delle differenze tra i particolari filesystem usati dai vari sistemi operativi—ad esempio, mentre in GNU/Linux il filesystem ha una sola radice, Windows ha il concetto di device, o dispositivi multipli, che tipicamente sono chiamati con una lettera, e.g., C:\, D:\ e così via.

Ma la cosa che ci interessa veramente è molto più prosaica, ovvero: dove trovo il percorso al file di dati che voglio analizzare, ad esempio per aprire il file stesso nel mio programma Python? Beh: se siete pratiche con il terminale è facile, perché la shell vi permette di navigare il filesystem. Se invece siete più abituate al mouse che alla tastiera, aprite il file browser del vostro sistema, localizzate il file, e tra le varie cose che vi offre il tasto destro dovrebbe essercene una che si chiama “Proprietà” o “Properties” che, tra le varie cose, dovrebbe fornire la stringa del percorso da copiare ed incollare.

9.2.2 Directory di lavoro e percorsi relativi

Il percorso che abbiamo visto nella sezione precedente

/home/lbaldini/Documents/presentazione.pdf

si chiama percorso assoluto perché parte dalla radice del filesystem.

Ora: una cosa interessante in cui non abbiamo ancora avuto l’occasione di imbatterci è che ogni volta che digitiamo un comando nel terminale, e ogni volta che eseguiamo un programma in Python, implicitamente questo non avviene nel vuoto, ma da un punto preciso del filesystem. Questo punto si chiama present working directory o pwd per brevità. Potete usare il comando pwd nel terminale per vedere dove siete: Il percorso che abbiamo visto nella sezione precedente

$ pwd
/home/lbaldini/teaching/unipi-physics-lab/lab1-computing

(Per quel che conta, potete anche cambiare la pwd, ma la cosa, in questo momento, è irrilevante.)

Perché diciamo questo? Perché oltre ai percorsi assoluti esistono anche i percorsi relativi, ovvero quelli che sono riferiti alla present working directory anziché alla radice del filesystem. Così, se la pwd è /home/lbaldini/, i due percorsi

/home/lbaldini/Documents/presentazione.pdf
Documents/presentazione.pdf

sono equivalenti—il primo è assoluto, il secondo è relativo.

Nota

Se siete incerte sul da farsi la scelta di minima azione è usare sempre percorsi assoluti: dovrete digitare più caratteri, ma il significato non dipende da dove siete nel filesystem, per cui avete effettivamente eliminato un elemento di potenziale confusione.

9.2.3 Nominare i file: insidie e buone norme

Ci sono regole e buone pratiche in termini di come nominare file e cartelle, a parte le ovvietà come cercare di dare nomi espressivi e che riflettano l’intento del contenuto?

Mentre qualche decennio fa i sistemi operativi tendevano a dare poca flessibilità in termini di numero e tipo di caratteri—DOS, ad esempio utilizzava la convenzione \(8.3\), ovvero \(8\) caratteri per il nome propriamente detto e \(3\) per l’estensione—sui sistemi moderni siete libere di fare più o meno quello che volete. Questo, va da sé, non vuol dire che questa libertà dobbiate usarla tutta e in tutte le occasioni 🙂

Una cosa di cui vi accorgerete immediatamente se cominciate ad utilizzare il terminale, ad esempio, è che gli spazi nei nomi dei file sono estremamente fastidiosi, perché quando digitiamo comandi siamo costretti ad aggiungere caratteri aggiuntivi per raggruppare i vari pezzi. Ci sono tanti modi per emulare la funzione logica di separazione per cui usiamo tipicamente gli spazi, i più usati tra i quali sono la convenzione snake case

relazione_densità.pdf

o quella camel case, nelle sue due varianti

relazioneDensità.pdf
RelazioneDensità.pdf

Usate pure una a caso tra le due—entrambe sono meglio di

relazione densità.pdf

9.2.4 Imparare ad amare il backslash

Supponiamo di voler analizzare dei dati sotto Windows, e supponiamo che il percorso assoluto al file che contiene questi dati sia

c:\abc\def\ghi.txt

(Non vi preoccupate della “c” minuscola, tra le molte fantastiche cose che offre Windows c’è anche il fatto che è case insensitive, ovvero non distingue maiuscole e minuscole.) Vi posso garantire che vi troverete prima o poi nella situazione in cui vorreste letteralmente sbattere la testa nel muro perché Python si ostina a dire che il file non esiste, nonostante voi sappiate in cuor vostro che il percorso è giusto—lo avete copiato dalla finestrella delle proprietà. (Per la precisione: leggere attentamente questa sezione è un modo possibile per non trovarsi in questa situazione.) Ebbene, non preoccupatevi: non siete sole nella vostra confusione.

Ma facciamo un passo indietro e diamo un’occhiata a questo snippet:

file_path = "c:\abc\def\ghi.txt"
print(file_path)
c:bc\def\ghi.txt
<>:1: SyntaxWarning: invalid escape sequence '\d'
<>:1: SyntaxWarning: invalid escape sequence '\d'
/tmp/ipykernel_2769/4099420625.py:1: SyntaxWarning: invalid escape sequence '\d'
  file_path = "c:\abc\def\ghi.txt"

Oh ho. Ci sono esattamente un backslash ed una lettera a che mancano all’appello subito dopo i due punti!

La questione è che il backslash ha un significato particolare in molti linguaggi di programmazione, incluso Python: conferisce un significato differente dal solito al carattere (o alla serie di caratteri) che lo segue, in quello che tecnicamente si chiama una sequenza di escape, e che tipicamente si usa per rappresentare i caratteri di controllo della tabella ASCII (codici \(0\)–\(31\)). L’esempio forse più noto è quello dell’andata a capo, o line feed, che corrisponde al code point \(10\) della tabella ASCII, e che nella quasi totalità dei linguaggi di programmazione si rappresenta come \n. Python, come il C, riconosce, tra le altre, le queste sequenze di escape:

Tabella 9.1: Sequenze di escape riconosciute da Python.
Sequenza di escape Significato Codice ASCII
\\ Backslash (\) 92
\' Single quote (') 39
\" Double quote (") 34
\a ASCII Bell (BEL) 7
\b ASCII Backspace (BS) 8
\f ASCII Formfeed (FF) 12
\n ASCII Linefeed (LF) 10
\r ASCII Carriage Return (CR) 13
\t ASCII Horizontal Tab (TAB) 9
\v ASCII Vertical Tab (VT) 11

Cominciamo capire cosa sta succedendo. Nel frammento sopra i due caratteri \a sono interpretati (correttamente) come la sequenza di escape corrispondente al codice di controllo \(7\) nella tabella ASCII, vale a dire BEL, ovverosia la campanella del terminale—se eseguite il frammento interattivamente nel prompt di Python e non avete disabilitato la campanella del terminale, dovreste sentire un suono!

Tornando al problema originale forse la scelta della Microsoft di utilizzare il backslash come separatore delle directory non è stata proprio delle più felici, che dite? Ma a parte questo—inutile cercare di dare colpe a distanza di più di quarant’anni—se all’interno di una stringa un backslash fa qualcosa di magico con i caratteri che seguono, come faccio a scrivere un backslash all’interno di una stringa?

Una possibilità ce la fornisce la prima riga della Tabella 9.1: possiamo usare un backslash per fare l’escape di se stesso, il che vuol dire che la sequenza di escape \\ si traduce in un \ semplice. Questo funziona come una si aspetta nella maggior parte delle situazioni. In alternativa, Python fornisce la possibilità di aggiungere una lettera r o R prima della virgoletta iniziale della stringa: così facendo si crea quella che si chiama una stringa grezza (raw string), in cui il backslash è trattato alla pari di un qualsiasi altro carattere.

file_path = "c:\\abc\\def\\ghi.txt"
print(file_path)
file_path = r"c:\abc\def\ghi.txt"
print(file_path)
c:\abc\def\ghi.txt
c:\abc\def\ghi.txt

E se pensate che il divertimento con il backslash finisca qui, aspettate di leggere l’Appendice A!