%%
%% Dispense corso amministrazione 
%%
%% Copyright (C) 2003-2018 Simone Piccardi and Truelite Srl. 
%%
%% This work is licensed under the Creative Commons Attribution-ShareAlike 4.0
%% International License. To view a copy of this license, visit
%% \url{http://creativecommons.org/licenses/by-sa/4.0/} or send a letter to
%% Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
%%
%% S. Piccardi Sep. 2003
%% 
%% stradmin.tex: Amministrazione straordinaria del sistema
%%

%%
%% INIZIO: Parte generale da non includere in systemd
%%
\ifx\systemdspecificsection\undefined

\chapter{Amministrazione straordinaria del sistema}
\label{cha:straordinary_admin}



\section{La gestione dei dischi e dei filesystem}
\label{sec:disk_filesystem_admin}

In questa sezione, dopo una introduzione su alcune nozioni di base relative
all'hardware, tratteremo in dettaglio le modalità con cui vengono gestiti in
un sistema GNU/Linux dischi e filesystem, quelle con cui si può accedere ai
dati in essi contenuti, le strategie di partizionamento e tutto quanto
riguarda le operazioni di manutenzione, gestione e controllo degli stessi.


\subsection{Alcune nozioni generali}
\label{sec:disk_structure}

Prima di affrontare l'uso dei programmi per la gestione di dischi e filesystem
occorre introdurre qualche concetto relativo al funzionamento della gestione
dei dischi.  In genere, e per questo sono chiamati dispositivi a blocchi, lo
spazio disponibile sui piatti magnetici di un disco viene suddiviso in blocchi
elementari di dati delle dimensioni di 512 byte chiamati \textsl{settori},
anche se con alcuni dischi più recenti e le ultime versioni degli standard è
divenuto possibile usare settori di 4096 byte. Dal disco si può sempre leggere
un settore alla volta e non un singolo byte. Questo viene fatto direttamente
dal kernel o dal BIOS che dice all'interfaccia hardware di leggere un
determinato settore fornendogli l'indirizzo dello stesso.

In generale l'accesso ai dischi deve essere eseguito attraverso una apposita
interfaccia hardware che consente al processore di farsi inviare in memoria i
dati mantenuti sul disco. Inizialmente nel mondo dei PC la stragrande
maggioranza dei computer montava come interfaccia per l'accesso ai dispositivi
a blocchi (dischi, CDROM) una interfaccia di gestione chiamata
alternativamente IDE (acronimo di \textit{Integrated Drive Electronics}, come
indicato nella specificazione originaria della Western Digital) o ATA
(acronimo di \textit{Advanced Technology Attachment}).

%%
%% ### OBSOLETE BEGIN ###
%% Materiale obsoleto su IDE, di scarso interesse oggi
%%
\ifx\obsoletesection\undefined

\relax
\else

L'interfaccia IDE/ATA ha subito diverse evoluzioni,\footnote{un excursus
  storico sulla evoluzione delle diverse caratteristiche di questa interfaccia
  può essere trovato su Wikipedia a questo indirizzo:
  \url{http://en.wikipedia.org/wiki/Integrated_Drive_Electronics}.}  volte
principalmente a migliorarne le prestazioni, ma una caratteristica rimasta
sempre presente è quella di poter supportare due dispositivi per ciascun
canale di comunicazione, vale a dire la possibilità di poter collegare due
dischi (o altre periferiche IDE, come CDROM o masterizzatori) sullo stesso
cavo, denominate \textit{master} e \textit{slave}, e determinate da appositi
\textit{jumper} da impostare sui dischi.

Ogni dispositivo è in grado di agire sia da \textit{master} che da
\textit{slave}, a seconda delle opportune impostazioni che si possono
effettuare su di esso. Questo si effettua in genere in modo manuale attraverso
dei ponticelli, i \textit{jumper} appunto, che sono presenti sul dispositivo
insieme allo schema in cui viene riportata l'indicazione del significato delle
varie posizioni. In questo modo si può indicare un ruolo esplicito o far
decidere alla posizione sul cavo.\footnote{le sigle usate sono in genere
  \texttt{MA} per \textit{master}, \texttt{SL} per \textit{slave} e
  \texttt{CS} per \textit{cable select}, che indica la selezione automatica
  con la posizione sul cavo, ovviamente nel collegamento occorrerà che tutti i
  dischi sullo stesso canale siano impostati in maniera coerente.}

%%
%% ### OBSOLETE END ###
%% Materiale obsoleto su IDE e affini
%%
\fi

Le interfacce IDE/ATA sono state supportate da Linux fin dalle prime versioni
del kernel. Per il loro classico utilizzo come interfacce per l'accesso ai
dischi, le relative periferiche sono da sempre associate a file di dispositivo
che iniziano con il prefisso \texttt{hd} (da \textit{hard disk}), con una
terza lettera che, in ordine alfabetico, identifica la periferica a cui si fa
riferimento.

%%
%% ### OBSOLETE BEGIN ###
%% Materiale obsoleto su IDE, di scarso interesse oggi
%%
\ifx\obsoletesection\undefined

\relax
\else

Il nome non varia anche quando il dispositivo non corrisponde ad un disco:
anche un CDROM sarà identificato come
\texttt{/dev/hd\textsl{X}}. L'assegnazione dei nomi dei dispositivi però 
risente della caratteristica dell'interfaccia di consentire due dischi per
canale, per cui l'ordine non è detto sia strettamente alfabetico, dato che ad
ogni canale sono sempre assegnate due lettere consecutive.

Questo significa che, nella configurazione più comune in cui si hanno due
canali IDE/ATA,\footnote{in genere il \textit{chipset} che fornisce
  l'interfaccia IDE gestisce almeno due canali, anche se esistono
  \textit{chipset} che gestiscono un numero di canali più elevato.} i
dispositivi sul primo canale saranno identificati come \texttt{/dev/hda} (per
il \textit{master}) e \texttt{/dev/hdb} (per lo \textit{slave}) mentre i
dispositivi posti sul secondo canale avranno rispettivamente i nomi
\texttt{/dev/hdc} e \texttt{/dev/hdd}, e questo indipendentemente dal fatto
che sul primo canale siano stati effettivamente collegati dei dispositivi o
meno. Si tenga presente poi che nel caso di dischi non si usano quasi mai
questi dispositivi dato che normalmente vi si accede facendo riferimento ad
una partizione, identificata tramite un ulteriore numero (vedi
sez.~\ref{sec:partitioning}).

%%
%% ### OBSOLETE END ###
%% Materiale obsoleto su IDE e affini
%%
\fi

A lungo l'unica alternativa alle interfacce IDE/ATA è stata l'interfaccia SCSI
(vedi sez.~\ref{sec:SCSI_interface}) che fin dall'inizio presentava una serie
di vantaggi tecnici, come quello di permettere il collegamento di più
periferiche su uno stesso cavo e quello di avere velocità di trasferimento più
alte, ma lo svantaggio di essere nettamente più costosa.

Dato che con una interfaccia SCSI l'accesso alle periferiche viene gestito in
maniera completamente diversa rispetto ad IDE anche i file di dispositivo sono
stati indicati in maniera diversa, utilizzando il prefisso \texttt{sd} (da
\textit{SCSI disk}), sempre seguito da una lettera progressiva in ordine
alfabetico che identifica i diversi dischi presenti, assegnata secondo
l'ordine di riconoscimento degli stessi.

Questo significa che il primo disco SCSI riconosciuto sarà \texttt{/dev/sda},
il secondo \texttt{/dev/sdb}, il terzo \texttt{/dev/sdc}, ecc.  Si tenga
presente però che a differenza delle interfacce IDE, il file di dispositivo
generico \texttt{/dev/sd\textsl{X}} viene usato soltanto per i dischi, vedremo
in sez.~\ref{sec:SCSI_interface} che per gli altri tipi di dispositivi (come i
CDROM) vengono utilizzati nomi diversi.

Una caratteristica importante dell'interfaccia SCSI è quella che ha visto fin
dal principio la creazione di un protocollo generico per gestire l'accesso ai
dischi, utilizzabile con qualunque disco SCSI. Questo protocollo è stato
implementato nel kernel in maniera indipendente dal supporto per lo specifico
hardware sottostante (vedi fig.~\ref{fig:SCSI_kernel_schema}) per cui è stato
possibile riutilizzarlo anche con interfacce di comunicazione completamente
diverse come l'USB (vedi sez.~\ref{sec:USB_interface}) o la IEEE 1394 (più
nota come \textit{Firewire} o \textit{i.LINK}). Questo ha fatto si che anche
con queste interfacce si è continuato ad usare per i file di dispositivo gli
stessi nomi di una interfaccia SCSI vera e propria.

Inoltre oggi le interfacce IDE/ATA classiche sono ormai universalmente
sostituite dallo standard \textit{Serial ATA} (SATA), che consente velocità di
comunicazione più elevate con un cablaggio più compatto. In questo caso, a
parte un breve periodo di transizione in cui anche questi dispositivi venivano
trattati come i normali IDE/ATA, in tutti i kernel attuali l'accesso è gestito
in maniera unificata attraverso una libreria interna, chiamata
\textit{libATA}, che di nuovo usa il protocollo SCSI per gestire la
comunicazione con i dischi.

Infine più recentemente anche il supporto di molti \textit{chipset} che usano
il tradizionale standard IDE/ATA (quello che ormai viene chiamato
\textit{parallel ATA}) è stato riscritto per utilizzare l'accesso tramite
\textit{libATA}. Il risultato finale è che al giorno d'oggi praticamente tutti
i dischi vengono visti come dischi SCSI e sono acceduti attraverso file di
dispositivo nella forma \texttt{/dev/sd\textsl{X}}, pur essendo collegati
fisicamente con le interfacce più diverse. Le eccezioni a questa regola ormai
sono soltanto alcuni controller RAID hardware (vedi
sez.~\ref{sec:RAID_in_Linux}) ed i dischi virtuali ad uso dei sistemi di
virtualizzazione.


%%
%% ### OBSOLETE BEGIN ###
%% Materiale obsoleto su CHS e affini
%%
\ifx\obsoletesection\undefined

\relax
\else

Ma anche se sul piano della diffusione dell'hardware le interfacce IDE/ATA
classiche sono ormai scomparse, esistono una serie di concetti ereditati da
esse che continuano ad essere presenti, come quello della cosiddetta
\textsl{geometria} dei dischi. Le prime interfacce IDE/ATA infatti separavano
fisicamente le linee di indirizzamento che consentivano di richiedere la
lettura di un particolare settore all'interno del disco in tre gruppi diversi,
pertanto una operazione di accesso imponeva di utilizzare tre parametri
diversi (uno per linea) per indicarne su quale settore operare.

Il primo gruppo di linee serviva per indirizzare le testine dei diversi piatti
del disco, da cui il nome \textit{head} e la sigla \texttt{H} usati per
indicare il corrispondente parametro; in sostanza vedendo il disco come un
cilindro questo parametro indicava la coordinata in altezza lungo l'asse dello
stesso, facendo riferimento ad un determinato piatto nel disco.

Il secondo gruppo serviva per muoversi lungo la coordinata angolare
all'interno di un piatto, da cui il nome \textit{sector} e la sigla
\texttt{S}; infine l'ultimo gruppo indicava come muoversi lungo la coordinata
radiale, da cui il nome \textit{cylinder} e la sigla \texttt{C}. Questa
nomenclatura sopravvive ancora oggi quando si parla di \textsl{geometria} di
un disco, per cui quando se ne vuole identificare la dimensione si indicano i
rispettivi valori massimi di questi tre parametri (la terna chiamata CHS),
moltiplicando i quali si ottiene il numero totale dei settori, e quindi la
capacità del disco.

Nelle prime interfacce IDE erano previste 10 linee per indicare il cilindro, 4
per le testine, e 6 per i settori, impostati attraverso altrettanti valori
binari dei parametri di controllo, ma ben presto i segnali vennero utilizzati
per una indicazione \textsl{logica} e non fisica dato che in realtà nella
suddivisione fisica delle tracce, il numero di settori è in genere variabile,
avendo più spazio sulle tracce esterne rispetto alle interne.  Restarono
comunque le dimensioni indicate, che consentivano un totale di 1024x16x63
settori, dato che praticamente da sempre il numero di settore è stato indicato
con un valore da 1 a 63, ed il settore 0 non viene mai usato. Il tutto porta
ad un totale di 504Mb di dimensione massima.

Anche i primi BIOS usavano questa suddivisione nella funzione di accesso al
disco che richiedeva, per accedere ad un certo settore, una terna di valori
indicanti appunto il numero di cilindro, testina e settore.  Questi venivano
passati tramite il contenuto di alcuni registri del processore, ed in
particolare 10 bit erano utilizzati per indicare il cilindro, 6 bit per
indicare il settore ed 8 bit per la testina.\footnote{la funzione di accesso
  del BIOS, denominata INT13 perché faceva uso della tredicesima trappola di
  interruzione software del processore, prendeva come argomenti alcuni
  registri di processore, usando 16 bit per cilindro e settore, e 8 bit per la
  testina; per tutti i dettagli sui registri e sulle varie limitazioni che si
  sono susseguite storicamente si può leggere il
  \href{http://www.tldp.org/HOWTO/Large-Disk-HOWTO/index.html}{\textit{Large
      Disk HOWTO}}.}

La corrispondenza diretta fra valori di \textit{head}, \textit{sector} e
\textit{cylinder} e coordinate fisiche del settore indirizzato è andata persa
quasi subito. Ma per mantenere la compatibilità con i sistemi operativi che
usavano il BIOS per leggere e scrivere su disco, l'interfaccia di accesso di
quest'ultimo è rimasta invariata molto più a lungo. L'accesso ad un settore
veniva poi eseguito direttamente dall'hardware in maniera trasparente,
indipendentemente dalla geometria reale del disco. Dato che il parametro
indicante la testina ha una dimensione massima di 8 bit la dimensione massima
di un disco ottenibile con questa interfaccia è di un totale di 1024x256x63
settori, pari a circa 8.4Gb, all'epoca considerata una dimensione
irraggiungibile.

La dimensione irraggiungibile però venne raggiunta piuttosto velocemente, e a
quel punto ci si trovò di fronte al limite non più superabile delle
restrizioni sui valori massimi di cilindro, testina e settore dovuti alla
modalità con cui veniva invocata la funzione di accesso, da cui derivava il
problema di non poter accedere a dischi superiori a detta dimensione che
affliggeva i BIOS di quel tempo, con quello che venne chiamato il
``\textsl{limite del 1024-simo cilindro}''.

Tutto questo venne superato con l'introduzione del cosiddetto \textit{Linear
  Block Addressing} (in breve LBA), in cui anche per i dischi IDE l'accesso
viene eseguito, come per i dischi SCSI, specificando semplicemente un numero
di settore che cresce linearmente da 0 al valore massimo. Il protocollo SCSI
infatti non ha mai avuto problemi di geometria, dato che ha sempre previsto
l'uso di un valore lineare per indicare il settore di un disco, anche se poi
il BIOS si doveva inventare una sua geometria fittizia per poter continuare ad
usare le sue routine di accesso.

Per questo tutti i BIOS attuali al posto della vecchia funzione di accesso
usano una nuova funzione che utilizza direttamente il numero del settore in
forma lineare e non soffrono più di questo limite. Anche qui comunque sono
entrati in gioco altri limiti, come il valore massimo del numero, che nelle
versioni più recenti è passato da 32 bit (LBA32) che consentiva un massimo di
2 Tb, ormai raggiunti, a 48 bit (LBA48) che per il momento sembrano alquanto
lontani.

Per un certo periodo perciò alcuni sistemi operativi e vari programmi non sono
stati in grado di utilizzare questa nuova interfaccia, non potendo quindi
accedere ai contenuti del disco posti sopra il limite del 1024-simo cilindro.
Questo problema non si è mai posto per Linux, dato che il kernel è sempre
stato in grado di accedere nativamente all'interfaccia IDE ed indirizzare
direttamente l'accesso ai singoli settori, non risentendo delle limitazioni
del BIOS.  Il problema si presentava però per i \textit{bootloader} che
dovendo stare nei pochi byte a disposizione nel \textit{Master Boot Record}
(il primo settore di un disco, dove viene installato il\textit{bootloader} e
la tabella delle partizioni, vedi sez.~\ref{sec:partitioning}) non possono
implementare un accesso al disco indipendente e devono usare le funzioni del
BIOS.

Dato che il compito di un \textit{bootloader} (vedi
sez.~\ref{sec:struct_kernel_boot}) è lanciare il kernel leggendolo dal disco,
questo risultava impossibile quando il kernel era posto una zona del disco che
il BIOS non riusciva a raggiungere. Con tutti i computer attuali questo
problema è totalmente superato, ma si presentava installando dischi più nuovi
su macchine molto vecchie. In tal caso si doveva avere l'accortezza di mettere
il kernel in una sezione di disco che sia entro il 1024-simo cilindro, cioè
nella parte iniziale del disco.  Questo comportava la necessità di creare una
partizione iniziale, per la quale il \textit{Filesystem Hierarchy Standard}
prevede l'uso della directory \texttt{/boot}, su cui mantenere le immagini del
kernel. Oggi l'unica ragione tecnica resta quella di mantenere su una
partizione in chiaro quanto necessario ad avviare di un sistema installato
completamente su dispositivi cifrati.

%%
%% ### OBSOLETE END ###
%% Materiale obsoleto su CHS e affini
%%
\fi


\subsection{Il partizionamento dei dischi}
\label{sec:partitioning}

Uno dei compiti di preparazione da eseguire tutte le volte che si installa un
nuovo disco è quello di suddividerne lo spazio in opportune
\textsl{partizioni}. In genere questo viene fatto dal programma di
installazione del sistema, che in tutte le distribuzioni più recenti è in
grado di eseguire il compito in maniera semi-automatica. Quando però si vuole
installare un nuovo disco, o si vuole effettuare l'operazione manualmente per
avere un maggior controllo, occorre saper utilizzare un programma di
partizionamento.

Prima di entrare nel dettaglio del funzionamento dei vari programmi di
partizionamento è opportuno fornire alcune informazioni di base relativamente
alla gestione delle partizioni. Le partizioni nacquero infatti come
funzionalità fornita dal BIOS per consentire di suddividere un singolo disco
in più parti, in modo che queste potessero essere accedute in maniera
indipendente l'una dall'altra, come fossero dispositivi separati.

\itindbeg{Master~Boot~Record (MBR)}

Nell'architettura tradizionale dei PC tutte le informazioni sulle partizioni
venivano originariamente mantenute nel primo settore di ciascun disco, il
cosiddetto \textit{Master Boot Record} (MBR), chiamato così perché è su di
esso che viene installato il \textit{bootloader}, cioè il programma di avvio
usato dal BIOS per lanciare il sistema operativo (vedi
sez.~\ref{sec:struct_boot}).  Una parte di questo settore costituisce la
cosiddetta \textsl{tabella delle partizioni}, dove vengono memorizzati i
valori del settore di inizio e di fine di quelle che oggi sono note come
\textsl{partizioni primarie}. Dato lo spazio limitato disponibile nell'MBR,
nella tabella delle partizioni non possono essere memorizzate più di quattro
partizioni.

Architetture meno obsolete, come SPARC, PowerPC, o Alpha, o anche i PC più
recenti con EFI e GPT (che tratteremo più avanti) non hanno mai avuto questo
limite, ed il numero di partizioni è molto più grande, ad esempio sui vecchi
MacIntosh PowerPC il limite era di 16. Nell'architettura PC, per mantenere la
compatibilità con le vecchie versioni e superare questa limitazione, sono
state introdotte le cosiddette \textsl{partizioni logiche}. Per poterle
utilizzare è necessario marcare una delle partizioni primarie mantenute nella
tabella delle partizioni dell'MBR come \textsl{partizione estesa} e a questo
punto sarà possibile utilizzare il primo settore di detta partizione per
installare una tabella secondaria che è quella su cui si indicheranno le
ulteriori partizioni logiche, per questo motivo le partizioni logiche talvolta
vengono chiamate anche \textsl{partizioni secondarie}.

\itindend{Master~Boot~Record (MBR)}

Partizioni primarie e secondarie possono coesistere, nei termini in cui si usa
lo spazio di una partizione primaria come partizione estesa dove indicare la
tabella delle successive partizioni secondarie.  In genere questo si fa
creando tre partizioni primarie ed utilizzando la quarta come partizione
estesa per poter poi creare anche le partizioni secondarie; ma si può usare
una partizione primaria qualunque, (ad esempio la seconda) tenendo presente
però che quando si usa una partizione primaria come partizione estesa per
introdurre le partizioni logiche, le partizioni primarie successive
(nell'esempio la terza e la quarta) non saranno più utilizzabili, anche se in
realtà se la partizione estesa non esaurisce tutto lo spazio disco questo non
è vero, ma questo tipo di configurazione non è consigliata dato che non tutti
i sistemi o i programmi di partizionamento sono in grado di capirla.

Il kernel legge la tabella delle partizioni all'avvio, ed usa per ciascuna
partizione un diverso file di dispositivo grazie al quale è possibile accedere
direttamente al contenuto della stessa. Questo comporta che se si modifica la
tabella delle partizioni il kernel può non essere in grado di vedere le
modifiche fino al riavvio successivo, se il disco è in uso infatti la funzione
che consente la rilettura della tabella delle partizioni fallirà, per evitare
che il kernel possa usare una versione non corrispondente a quella in uso al
momento.

Usualmente il nome del file di dispositivo associato ad una partizione viene
ottenuto aggiungendo il numero della partizione al nome del file di
dispositivo associato al disco.  Le partizioni primarie sono numerate da 1 a
4, mentre quelle logiche vanno dal 5 in poi, tradizionalmente il kernel
prevede un massimo di 63 partizioni per i dischi IDE e di 16 per gli SCSI, con
dei limiti che originano da ragioni storiche relative ai valori dei
\textit{minor number} (vedi sez.~\ref{sec:struct_privileged_operations}) dei
relativi dispositivi, in realtà oggi, grazie all'uso di LVM (vedi
sez.~\ref{sec:disk_LVM}) l'uso di un gran numero di partizioni non è più
necessario, potendo utilizzare alla bisogna un gran numero di volumi logici.
% Così ad esempio \texttt{/dev/hda2} è la seconda partizione primaria del primo
% disco del primo canale IDE, mentre \texttt{/dev/hdb5} è la prima partizione
% logica del secondo disco del primo canale IDE, e \texttt{/dev/sda6} è la
% seconda partizione logica del primo disco SCSI,\footnote{o meglio, se si
%   ricorda quanto detto in sez.~\ref{sec:disk_structure}, del primo disco
%   gestito con il protocollo SCSI, quindi anche USB, \textit{Serial ATA}, ecc.}
% e così via.

Sui PC il comando utilizzato tradizionalmente per partizionare un disco è
\index{comando!\texttt{fdisk}} \texttt{fdisk}, che si trova con lo stesso
nome, anche se con sintassi diverse, anche in altri sistemi operativi. Non
tratteremo qui le altre architetture, che in genere hanno programmi diversi.
Ad esso si sono in seguito aggiunti altri programmi, caratterizzati per lo più
da una interfaccia più funzionale o più semplice. In particolare alcuni di
questi, come \texttt{qtparted} o \texttt{gparted}, sono dotati di interfaccia
grafica e sono in grado di effettuare anche operazioni di ridimensionamento
dei filesystem contenuti nelle partizioni (vedi
sez.~\ref{sec:filesystem_resize}).

%% inessenziale
% Il comando opera esclusivamente sulla tabella delle partizioni, ed in genere
% se si effettuano modifiche su di esse il relativo contenuto viene
% perduto.\footnote{a meno di non aver fatto un semplice ridimensionamento e
%   trattato opportunamente il filesystem, vedi sempre
%   sez.~\ref{sec:filesystem_resize}.} Per questo motivo l'utilizzo di
% \texttt{fdisk} è in genere limitato al momento dell'installazione del sistema
% o di un nuovo disco.

Il comando prende come argomento il file di dispositivo del disco su cui si
vuole operare, le uniche opzioni che ha senso usare sono \texttt{-l} che si
limita a stampare la tabella delle partizioni presente e \texttt{-s} che
stampa le dimensioni totali di una partizione (se passata come argomento con
il relativo file di dispositivo) o del disco. Le altre opzioni servono per
specificare le caratteristiche del disco e normalmente non servono in quanto i
valori sono determinati automaticamente, e per quanto riguarda numero di
cilindri, testine e settori possono essere modificati anche all'interno del
comando.

Quando il comando viene lanciato stampa un messaggio di benvenuto e, qualora
presenti avvisa di potenziali problemi, \ifx\obsoletesection\undefined \relax
\else (quelli accennati in sez.~\ref{sec:disk_structure}) quando il numero dei
cilindri è maggiore di 1024, avviso ormai obsoleto a meno di non usare sistemi
operativi obsoleti;\fi un esempio del risultato del comando è il seguente:
\begin{Console}
hain:/root# \textbf{fdisk /dev/sda}
 
WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
         switch off the mode (command 'c') and change display units to
         sectors (command 'u').

Command (m for help):
\end{Console}
dopo la stampa iniziale \texttt{fdisk} si pone in attesa dei comandi che
vengono specificati con le relative lettere; se vogliamo una lista dei comandi
disponibili possiamo premere \texttt{m} come indicato, ottenendo:
\begin{Console}
Command (m for help): \textbf{m}
Command action
   a   toggle a bootable flag
   b   edit bsd disklabel
   c   toggle the dos compatibility flag
   d   delete a partition
   l   list known partition types
   m   print this menu
   n   add a new partition
   o   create a new empty DOS partition table
   p   print the partition table
   q   quit without saving changes
   s   create a new empty Sun disklabel
   t   change a partition's system id
   u   change display/entry units
   v   verify the partition table
   w   write table to disk and exit
   x   extra functionality (experts only)
\end{Console}
questo ci dice che con \texttt{p} possiamo stampare la tabella delle
partizioni corrente, nel caso otterremo:
\begin{Console}
Command (m for help): \textbf{p}
 
Disk /dev/sda: 1798.8 GB, 1798752436224 bytes
255 heads, 63 sectors/track, 218685 cylinders, total 3513188352 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x0004fb07

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *        2048     1953791      975872   83  Linux
/dev/sda2         1953792   783204351   390625280   83  Linux
/dev/sda3       783206398  3513186303  1364989953    5  Extended
/dev/sda5       783206400  3513186303  1364989952   8e  Linux LVM
\end{Console}
che ci mostra come nel disco siano presenti quattro
partizioni. \ifx\obsoletesection\undefined \relax \else Si noti anche come
viene riportata una geometria per il disco; questa è quella che è vista dal
kernel, ed in genere coincide con quanto visto dal BIOS, ma è possibile
cambiarla con uno dei comandi delle funzionalità avanzate. \fi

A questo punto si potrà usare \texttt{d} per cancellare una partizione (il
comando ne chiederà il numero), ed \texttt{n} per crearne una nuova, nel qual
caso \texttt{fdisk} prima chiederà se primaria o secondaria e poi il relativo
numero. Una volta scelta la partizione il programma chiederà il settore di
partenza, proponendo come default il primo che risulta libero, e la
dimensione.  Quest'ultima può essere specificata in varie unità di misura o
direttamente con il settore finale, il comando propone sempre come default
l'ultimo settore del disco.

Il comando \texttt{t} permette di impostare il valore numerico che identifica
il \textsl{tipo} di partizione; questo viene in genere utilizzato per indicare
che tipo di filesystem sarà contenuto nella stessa. Per i filesystem di Linux
il valore è \texttt{83} (in esadecimale) e vale per tutti i filesystem.  I
filesystem Windows invece usano vari codici diversi a seconda del tipo di
filesystem. Il valore \texttt{82} è invece usato per indicare una partizione
destinata all'uso come \textit{swap} (vedi
sez.~\ref{sec:swap_CDROM_management}). Altri valori usati da Linux sono
\texttt{fd} o \texttt{da} per indicare le partizioni usate per il RAID
software (vedi sez.~\ref{sec:RAID_mdadm}) e \texttt{8e} per quelle usate per
il \textit{Logical Volume Manager} (vedi sez.~\ref{sec:disk_LVM}).

Qualunque modifica si sia effettuata sulla tabella delle partizioni questa non
verrà scritta su disco a meno di non effettuare una richiesta esplicita di
scrittura con il comando \texttt{w}; questo comunque chiederà conferma prima
di effettuare la scrittura, avvertendo che si possono perdere tutti i dati
presenti sul disco. Si esce da \texttt{fdisk} con il comando \texttt{q}, che
non salva le modifiche effettuate.

Un comando alternativo a \texttt{fdisk} è \index{comando!\texttt{cfdisk}}
\texttt{cfdisk}, un programma più \textsl{amichevole} che permette l'uso di
una interfaccia testuale semigrafica ed interattiva in cui si possono eseguire
le varie operazioni spostandosi su comandi e partizioni con l'uso delle
frecce.  In fig.~\ref{fig:cfdisk_screen} è mostrata la schermata iniziale di
\texttt{cfdisk}, dalla quale è possibile dare tutti i comandi.

\begin{figure}[htb]
\centering
\includegraphics[scale=0.5]{images/cfdisk}
\caption{Schermata del comando \texttt{cfdisk}.}
\label{fig:cfdisk_screen}
\end{figure}

Infine un terzo programma che consente di manipolare la tabella delle
partizioni è \index{comando!\texttt{sfdisk}} \texttt{sfdisk}, che ha la
caratteristica di operare a riga di comando in modalità non interattiva, e
pertanto può essere utilizzato anche all'interno di script. Il comando prende
sempre come argomento il file di dispositivo relativo ad un disco (ad esempio
\texttt{/dev/sda}), tranne che quando invocato con l'opzione \texttt{-s}, che
stampa la dimensione delle partizioni, nel qual caso si può usare anche il
file di dispositivo di una singola partizione. Con l'opzione \texttt{-l}
invece il comando stampa la tabella delle partizioni in un formato leggibile,
e se non si specifica nessun dispositivo esegue l'operazione per tutti i
dischi.

Se invocato senza opzioni il comando legge dallo \textit{standard input} le
istruzioni relative al partizionamento del disco indicato; quando invocato su
un terminale le istruzioni sono richieste in modalità interattiva, ma qualora
si sia rediretto lo \textit{standard input} queste possono essere lette
direttamente da un file consentendo così di automatizzare le operazioni di
partizionamento in modalità non interattiva.

Le istruzioni consentono di cancellare, spostare e modificare le partizioni, e
seguono una sintassi specifica (per i dettagli si può consultare la pagina di
manuale); benché il comando abortisca qualora si commetta un errore di
sintassi, si deve avere ben presente che basta inserire un qualche valore
sbagliato per perdere il partizionamento di un disco. Per questo vengono
fornite le opzioni \texttt{-O} e \texttt{-I}.

L'opzione \texttt{-O} consente di salvare, sul file indicato come parametro,
il contenuto di tutti i settori modificati dalla conseguente esecuzione di
\texttt{sfdisk}.  Questo significa che se si devono effettuare delle modifiche
con \texttt{sfdisk} è sempre opportuno invocarlo come \texttt{sfdisk /dev/sda
  -O sda.save}, in questo modo se si è commesso un errore sarà possibile
ripristinare la situazione precedente invocando il comando con l'opzione
\texttt{-I}, sarà cioè possibile tornare indietro con \texttt{sfdisk /dev/sda
  -I sda.save}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-s} & stampa la dimensione delle partizioni di un disco o della
                  singola partizione.\\
    \texttt{-l} & stampa una lista delle partizioni presenti sul disco.\\
    \texttt{-d} & scrive il contenuto della tabella delle partizioni di un
                  disco nel formato delle istruzioni di \texttt{sfdisk}, così
                  che l'output del comando può essere usato come input per una
                  successiva invocazione dello stesso.\\
    \texttt{-V} & esegue una verifica della tabella delle partizioni e riporta
                  ogni eventuale anomalia.\\
    \texttt{-n} & simula le operazioni senza scrivere nulla sul disco.\\
    \texttt{-O \textsl{file}} & salva sul file passato come parametro il
                                contenuto binario dei settori modificati dal
                                comando.\\ 
    \texttt{-I \textsl{file}} & ripristina il contenuto del disco utilizzando
                                le informazioni ottenute dal file passato come
                                parametro (che deve essere stato prodotto
                                usando l'opzione \texttt{-O} nella precedente
                                invocazione del comando).\\
%    \texttt{} & .\\
    \hline
  \end{tabular}
  \caption{Le principali opzioni del comando \texttt{sfdisk}.} 
  \label{tab:sfdisk_options}
\end{table}

In realtà l'uso di \texttt{sfdisk} per eseguire delle modifiche manuali è
piuttosto ridotto, dato che un comando come \texttt{cfdisk} è molto più
comodo; dove esso diventa molto utile è quando si vogliono partizionare molti
dischi nella stessa maniera come nel caso in cui si devono impostare le
partizioni dei vari dischi componenti un RAID 1 (vedi
sez.~\ref{sec:disk_RAID}).  In tal caso infatti è possibile eseguire il
partizionamento del primo disco, e poi salvare la struttura della tabella
delle partizioni con l'opzione \texttt{-d}, che genera sullo \textit{standard
  output} una serie di istruzioni che possano essere a loro volta utilizzate
come input per lo stesso \texttt{sfdisk}; così se si vuole replicare il
partizionamento di \texttt{/dev/sda} su \texttt{/dev/sdc} basterà eseguire il
comando:
\begin{Example}
sfdisk -d /dev/sda | sfdisk /dev/sdc
\end{Example}

Si tenga presente però che \texttt{-d} non è una alternativa all'uso di
\texttt{-O} per ripristinare un cambiamento di tabella delle partizioni, se
infatti si può riportare la tabella delle partizioni nella forma originaria,
non saranno recuperate eventuali modifiche fatte ad altre parti del disco,
come può accadere qualora si creino delle partizioni logiche su dischi ove non
esistevano e poi si voglia tornare indietro.

Come accennato all'inizio la tabella delle partizioni mantenuta nell'MBR
comporta molte limitazioni. Oltre al numero delle stesse la più seria è che
essendo il numero di settore che le delimita indicato con valori a 32 bit, la
dimensione massima utilizzabile per un disco, con settori di 512 byte, è di
due terabyte, ormai già superata da vari produttori. Per questo, anche se
viene comunque supportata per compatibilità, nelle macchine più recenti,
insieme all'uso di UEFI (vedi sez.~\ref{sec:struct_boot}) al posto del BIOS
tradizionale, è stato adottato un nuovo formato delle partizioni denominato
GPT (\textit{GUID Partition Table}).

Il nuovo formato prevede che vengano utilizzati i primi 34 e gli ultimi 33
settori del disco. Il primo settore è riservato e non viene mai utilizzato da
GPT. Questo consente di mantenervi un MBR tradizionale contenente una tabella
delle partizioni classica che può essere utilizzato su macchine che non
supportano GPT, oppure di proteggere la partizione GPT stessa allocando tutto
lo spazio disponibile in modo che i programmi che non la riconoscono evitino
di sovrascriverla. 

Il settore seguente (che viene replicato sull'ultimo settore del disco)
contiene la cosiddetta \textsl{intestazione primaria} (\textit{Primary GPT
  header}) con un GUID (un \textit{Globally Unique Identifier}, un
identificativo pseudocasuale di 16 byte) che identifica il disco, la posizione
dell'\textsl{intestazione secondaria} (la \textit{Secondary GPT header} che
viene copiata sull'ultimo settore del disco), il numero e le dimensioni degli
elementi mantenuti della successiva tabella della partizioni, ed una
\textit{checksum} globale che viene usata dal \textit{firmware} di avvio
(UEFI, vedi sez.~\ref{sec:struct_kernel_boot}) per verificarne l'integrità.

I dati della tabella vengono poi memorizzati nei seguenti 32 settori
successivi e prevedono per ciascuna partizione un altro GUID che ne identifica
il tipo (che fa le veci dell'analogo di un solo byte nell'MBR) seguiti
dall'inizio e la fine della stessa in termine di numero di settori (indicato a
64 bit) e dall'eventuale nome ed attributi della stessa. Questi 32 settori
vengono copiati per ridondanza anche in fondo al disco, immediatamente sotto
l'intestazione secondaria.

Dato che il formato è completamente diverso, per la gestione delle partizioni
GPT sono stati creati altri programmi analoghi ai precedenti, caratterizzati
dall'uso della ``\texttt{g}'' al posto della ``\texttt{f}''. Pertanto il
comando di base per modificare una partizione GPT è
\index{comando!\texttt{gdisk}} \texttt{gdisk}, che ha un comportamento analogo
a \texttt{fdisk} (anche per il significato dell'opzione \texttt{-l}); se
invocato su un disco partizionato con GPT otterremo infatti:
\begin{Console}
hain:/root# \textbf{gdisk /dev/sda}
 GPT fdisk (gdisk) version 0.8.1

Partition table scan:
  MBR: protective
  BSD: not present
  APM: not present
  GPT: present

Found valid GPT with protective MBR; using GPT.

Command (? for help): 
\end{Console}

I comandi, ottenibili stavolta premendo ``\texttt{?}'', sono analoghi a quelli
di \texttt{fdisk}, ad esempio premendo ``\texttt{p}'' si può stampare la
tabella delle partizioni, ottenendo qualcosa come:
\begin{Console}
Command (? for help): \textbf{p}
Disk /dev/sda: 5860533168 sectors, 2.7 TiB
Logical sector size: 512 bytes
Disk identifier (GUID): 5FDEE2EA-D7CE-4007-BD9C-5BD47FCF6273
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 5860533134
Partitions will be aligned on 2048-sector boundaries
Total free space is 2014 sectors (1007.0 KiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            4096         8392703   4.0 GiB     FD00  
   2         8392704        39849983   15.0 GiB    FD00  
   3        39849984      5860533134   2.7 TiB     FD00  
   4            2048            4095   1024.0 KiB  EF02  
\end{Console}

Anche i restanti comandi principali sono analoghi a quelli di \texttt{fdisk};
con ``\texttt{d}'' si può cancellare una partizione indicandone poi il numero,
con ``\texttt{n}'' crearne una nuova, di nuovo si dovrà indicare il numero e
poi inizio, fine e tipo. Con ``\texttt{q}'' si può uscire dal programma e come
per \texttt{fdisk} nessuna modifica verrà registrata se non avendo fatto una
richiesta esplicita con ``\texttt{w}'' confermando la scrittura. Inoltre è
possibile salvare un backup della tabella delle partizioni con ``\texttt{b}''
(chiederà il nome del file su cui scriverlo) e ricaricarlo con ``\texttt{l}''.

La differenza più significativa resta nell'indicazione del tipo di partizione,
che si può fare su una partizione esistente usando ``\texttt{t}'' ed indicando
poi il numero della stessa, in questo caso visto la complessità di scrivere un
GUID di 16 byte, vengono usati valori di due byte (quattro cifre esadecimali)
analoghi a quelli usati per \texttt{fdisk} cui vengono aggiunti due zeri, la
cui lista si ottiene premendo \texttt{L}; la conversione al corretto GUID
viene realizzata internamente da \texttt{gdisk}.

Oltre a \texttt{gdisk} esistono gli ulteriori comandi
\index{comando!\texttt{cgdisk}} \texttt{cgdisk}, che replica l'interfaccia
semigrafica di \texttt{cfdisk}, e \index{comando!\texttt{sgdisk}}
\texttt{sgdisk} che consente di eseguire le operazioni in modalità non
interattiva come \texttt{sfdisk} anche se in questo caso la sintassi del
comando è completamente diversa. L'uso di quest'ultimo comando è comunque
sconsigliato se non per l'uso all'interno di script, in quanto a differenza di
\texttt{sfdisk} non effettua nessun controllo di errore sulle informazioni che
gli vengono passate, ed è pertanto facile fare danni.

Ovviamente il partizionamento di un disco è una operazione privilegiata, che
può compiere solo l'amministratore, e richiede il permesso di scrittura sul
dispositivo su cui si esegue il relativo comando. E come accennato è anche un
compito molto delicato, in quanto se si cambia la tabella delle partizioni
cancellando o modificando una di quelle presenti il relativo contenuto andrà
perso. Occorre quindi stare molto attenti ed evitare di salvare le modifiche
fintanto che non si è assolutamente sicuri di quanto si è fatto.

Infatti, anche se in realtà gli unici dati che vengono cambiati sono quelli
della tabella delle partizioni, una volta che questa è stata modificata non
saranno più presenti sul disco i confini delle partizioni preesistenti e dato
che ogni filesystem viene creato per stare esattamente nelle dimensioni di una
partizione, se se ne modificano dimensioni o posizione i dati del filesystem
in essa contenuto non saranno più utilizzabili.

Questo ci dice anche che, fintanto che non si va a modificare il contenuto
effettivo del disco, l'accesso ai dati può essere riottenuto ripristinando la
tabella delle partizioni. Per farlo esistono molti metodi, a partire da quello
più semplice di tutti che consiste nel segnarsi il contenuto precedente,
operazione che come abbiamo visto è semplicissima da fare con
\texttt{sfdisk} e con \texttt{gdisk}. 

Un altro metodo, più complesso, ed utilizzabile solo se nel frattempo non si è
riavviata la macchina, è quello di recuperare i dati dalle informazioni
mantenute dal kernel attraverso il contenuto di \texttt{/proc/partitions} ed i
risultati del comando \texttt{hdparm}. Si ricordi infatti che il kernel legge
la tabella delle partizioni all'avvio e la mantiene in memoria e che è per
questo che se si ripartiziona un disco in uso occorre riavviare il sistema per
vedere le modifiche.

Infine si può usare il comando \index{comando!\texttt{gpart}} \texttt{gpart},
da eseguire a disco non montato, che è in grado di trovare, utilizzando
opportuni criteri di identificazione dei dati dei filesystem, i confini di
partizioni preesistenti, così da poterle ripristinare. In questo caso
ovviamente i tempi sono molto più lunghi, ed i risultati non sono sicuri.


Il fatto che la modifica delle dimensioni di una partizione comporti, a meno
di opportune contromisure di salvaguardia, la perdita dei dati in essa
contenuti ci fa capire che è sempre opportuno pianificare con cura le
dimensioni assegnate alle varie partizioni fin dall'installazione del sistema,
perché modificarle in un secondo tempo comporta spesso la necessità di dover
fare un backup dei contenuti. Infatti, a parte il caso in cui la si allarga
con dello spazio disponibile alla sua fine, in genere nel modificare una
partizione occorre anche operare sul filesystem in essa contenuto, e questo
può comportare diversi problemi.  Vedremo in sez.~\ref{sec:filesystem_resize}
il comando \texttt{parted} che permette di ridimensionare un filesystem e
restringere, allargare o spostare la partizione che lo contiene, ma
l'operazione resta complessa e delicata.

Tutto questo significa che nell'installazione occorre decidere una buona
\textsl{strategia di partizionamento}, cioè decidere quante partizioni fare e
come assegnarle. Per questo occorre tenere ben presenti le indicazioni sul
contenuto delle varie directory di sistema illustrate in
sez.~\ref{sec:file_FHS}. Una delle strategie più semplici è quella di creare
una partizione unica e mettere tutto quanto su di essa. Questo schema ha il
vantaggio di non doversi preoccupare del dimensionamento delle altre
partizioni né del rischio di esaurire lo spazio su una partizione mentre le
altre sono vuote. Ha però lo svantaggio che qualora si debba eseguire una
reinstallazione verranno sovrascritti i dati degli utenti (normalmente quelli
sotto \texttt{/home}) e quelli di sistema (come pagine web, posta archiviata e
tutto quanto in genere si tiene sotto \texttt{/var} o \texttt{/srv}). Inoltre
se si hanno più dischi non è ovviamente possibile mettere tutto su una sola
partizione.  Infine anche qualora si usi una sola partizione per tutto il
sistema, è in generale una buona pratica creare comunque una seconda
partizione per l'area di \textit{swap} (vedi
sez.~\ref{sec:swap_CDROM_management}).

Per questo motivo di solito si preferisce creare almeno un'altra partizione su
cui montare \texttt{/home} per i dati degli utenti. O qualora si abbiano dati
di sistema un'altra per \texttt{/var} o \texttt{/srv}. Se poi si vuole
separare anche quanto non strettamente necessario all'avvio dal resto del
sistema si può mettere anche \texttt{/usr} su una partizione separata, anche
se questo è sconsigliato nei sistemi più recenti, in quanto alcuni programmi si
aspettano, nonostante non sia garantito dal FHS, che questa sia posta
direttamente sotto la radice.

Inoltre, onde evitare che gli utenti possano riempire la radice con file
temporanei, può essere opportuno usare una partizione separata per
\texttt{/tmp}. Su questo aiuta la quota di disco riservata per
l'amministratore che molti filesystem supportano (vedi
sez.~\ref{sec:filesystem_create}), salvo il caso in cui è l'amministratore
stesso a creare, per sbaglio, troppi file temporanei.  Infine in certi casi
può essere necessario creare una partizione separata per \texttt{/boot}, in
particolare quando si esegue una installazione su dispositivi cifrati, in tal
caso infatti il \textit{bootloader} dovrà accedere ai file necessari all'avvio
(vedi sez.~\ref{sec:struct_boot}) in chiaro mentre tutto il resto sarà
cifrato.

Usare diverse partizioni (e più dischi) ha comunque una serie di
controindicazioni. Anzitutto si può sprecare inutilmente spazio disco quando
una partizione si riempie mentre le altre sono vuote, e a questo punto si ha
solo l'alternativa di ripartizionare o di spostare pezzi da una partizione
all'altra e farvi riferimento con dei link simbolici, che non è il massimo
della semplicità di gestione e può comportare una serie di problemi con i
programmi di backup che di norma, per evitare di inserire nel backup cose che
non c'entrano nulla, prevedono di archiviare solo i file presenti sul
filesystem corrente.

Inoltre una volta che si sono spostate su partizioni diverse \texttt{/home},
\texttt{/var}, \texttt{/srv}, \texttt{/tmp} e \texttt{/usr} (ed eventualmente
\texttt{/opt}) non è che resti molto altro da spostare, a parte esercizi di
stile come lo spostamento di \texttt{/var/tmp} o \texttt{/usr/local}, la cui
utilità, visto l'aumento della complessità di gestione, è molto
dubbia. Inoltre per quanto grandi si possano fare le partizioni, non si
risolverà mai il problema di esaurire lo spazio in quelle con la maggior parte
dei contenuti, quando l'occupazione dei dati di una partizione cresce oltre la
capacità del più grande dei dischi che si hanno. 

In casi come questo si è costretti ad usare più dischi dividendo i contenuti
che normalmente starebbero sotto una sola directory, cosa che può rendere la
gestione molto più complicata, specie se questo accade per directory che non
siano \texttt{/home}. Per quest'ultima infatti, che è quella più facilmente
soggetta alla possibilità di esaurimento dello spazio, è sempre stata
prevista, sia pure al prezzo di una maggiore attenzione nella creazione degli
utenti (si ricordi quanto visto in sez.~\ref{sec:cmd_users}), la possibilità
di suddividerne il contenuto su più dischi, creando le home directory degli
utenti su pathname diversi.

Come si vede l'uso delle partizioni comporta una serie di potenziali problemi
di gestione, dovuti alla necessità di pianificare adeguatamente in fase di
installazione la gestione dello spazio disco, cosa che non sempre è possibile
fare in maniera sicura, anche perché le condizioni di uso di una macchina
possono cambiare.  Per risolverli alla radice è perciò disponibile, a partire
dai kernel della serie 2.4.x, il sistema del \textit{Logical Volume Manager}
che permette di unire partizioni\footnote{si noti come in
  fig.~\ref{fig:cfdisk_screen} compaia appunto una partizione di tipo
  \texttt{Linux LVM}, che è quella da usare per i volumi fisici che verranno
  usati con LVM come componenti di un volume logico.} e dischi fisici diversi,
utilizzando poi dei \textsl{volumi logici} all'interno dei quali creare i
relativi filesystem senza dover fare riferimento diretto ad una specifica
partizione. Tratteremo questo argomento in sez.~\ref{sec:disk_LVM}.


\subsection{La gestione del contenuto dei dischi}
\label{sec:file_disk_management}

Come illustrato in sez.~\ref{sec:file_FHS} una delle caratteristiche dei
sistemi unix-like che disorientano maggiormente chi proviene da altri sistemi
operativi è la presenza di un unico albero delle directory. Dato che il
concetto di volume o disco come entità separata non esiste, la conseguenza è
che il contenuto dei dischi, o degli altri dispositivi contenenti file come
CDROM, floppy o chiavette USB, deve essere fatto apparire all'interno
dell'unico albero dei file, così che possa essere visto dal sistema
all'interno di opportune directory.

Come già accennato l'operazione che permette di fare comparire i dati del
filesystem contenuto in un dispositivo all'interno di una directory viene
chiamata ``\textsl{montaggio}'', ed una delle caratteristiche di Linux (e
degli altri Unix) è che all'avvio del sistema il kernel si limita a montare
soltanto la directory radice che deve il suo nome appunto all'essere la
\textsl{radice} dell'albero dei file.\footnote{vedremo in
  sez.~\ref{sec:struct_boot} come definire quale sia il dispositivo su cui si
  trova il filesystem che contiene la radice sia una delle impostazioni
  fondamentali relative all'avvio del sistema.} Questo significa che se si è
seguita la prassi comune di installare i dati su partizioni separate, queste
dovranno essere montate in un secondo momento.  Lo stesso dicasi se si
vogliono utilizzare dati presenti in un dispositivo (floppy, CDROM, o altro)
reso disponibile in un tempo successivo all'avvio.

Le distribuzioni moderne vengono incontro all'utente prevedendo, come supporto
per il software installato insieme all'interfaccia grafica, un meccanismo di
riconoscimento automatico di eventuali altri ``\textsl{volumi}'' resisi
disponibili, con tanto di montaggio automatico degli stessi, ciò non toglie
che l'operazione debba comunque essere effettuata. Noi vedremo qui come lo si
fa in maniera ``\textsl{manuale}'', che è la modalità con cui lo si fa
normalmente sui server dove l'interfaccia grafica in genere non viene neanche
installata. 

\itindbeg{mount~point}

Il comando che permette di montare il filesystem contenuto in un disco
all'interno di una directory è \index{comando!\texttt{mount}} \texttt{mount},
che di norma si limita ad invocare la omonima \textit{system call} del
kernel. Si tenga presente poi che per alcuni filesystem (in particolare per
quelli di rete come \texttt{nfs} e \texttt{smbfs}) per l'esecuzione del
comando non è sufficiente la chiamata alla omonima \textit{system call}, ma
devono essere usati dei programmi ausiliari; questi vengono lanciati con
l'invocazione automatica di un corrispondente programma
\texttt{/sbinmount.fs\_type}.

Se lo si invoca senza argomenti il comando si limita a mostrare l'elenco dei
filesystem attualmente montati, ma normalmente esso viene sempre invocato
nella forma:
\begin{Example}
mount -t fs_type /dev/device /path/to/dir
\end{Example}
dove l'opzione \texttt{-t} serve a specificare il tipo di filesystem che è
contenuto nel dispositivo che si vuole montare, che deve essere indicato
tramite il suo file di dispositivo \texttt{/dev/device}. Infine
\texttt{/path/to/dir} indica la directory, che viene detta \textit{mount
  point}, in cui il filesystem verrà \textsl{montato}, vale a dire la
directory all'interno della quale comparirà il contenuto del filesystem.

\itindend{mount~point}

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Tipo} & \textbf{Descrizione} \\
    \hline
    \hline
    \texttt{adfs}    & \textit{Acorn Disc Filing System}, il filesystem del
                       sistema operativo RiscOS.\\ 
    \texttt{btrfs}   & \textit{B-tree File System}, un filesystem di nuova
                       generazione, progettato per le funzionalità più
                       avanzate e indicato come futuro sostituto dei vari
                       \textit{extN}.\\
    \texttt{cramfs}  & \textit{Compressed ROM File System}, un filesystem su
                       ROM per sistemi embedded.\\ 
    \texttt{ext2}    & \textit{Second Extended File System}, il vecchio 
                       filesystem standard di Linux.\\
    \texttt{ext3}    & \textit{Third Extended File System}, evoluzione di
                       \textit{ext2} con supporto per il \textit{journaling}.\\ 
    \texttt{ext4}    & \textit{Fourth Extended File System}, ultima versione del
                       filesystem standard di Linux, ulteriore evoluzione del
                       precedente \textit{ext3}.\\
    \texttt{hfs}     & \textit{Hierarchy File System}, il filesystem
                       del MacOS (non MacOS X).\\  
    \texttt{hfsplus} & \textit{Hierarchy File System Plus}, il filesystem
                       del MacOS X.\\  
    \texttt{hpfs}    & \textit{High Performance File System}, il filesystem di
                       OS/2. \\  
    \texttt{iso9660} & il filesystem dei CD-ROM, definito dallo standard ISO
                       9660.\\ 
    \texttt{udf}     & \textit{Universal Disk Format}, filesystem per i
                       dispositivi ottici (CD e DVD), successore di ISO
                       9660.\\
    \texttt{jfs}     & \textit{Journaling File System}, il filesystem della IBM
                       con il supporto per il \textit{journaling} portato su
                       Linux.\\  
    \texttt{minix}   & \textit{Minix File System}, il filesystem del sistema
                       operativo Minix.\\
    \texttt{ntfs}    & \textit{NT File System}, il filesystem di Windows NT.\\
    \texttt{qnx4}    & \textit{QNX4 File System}, il filesystem usato da QNX4
                       e QNX6. \\ 
    \texttt{reiserfs}& \textit{Reiser File System} il primo filesystem di
                       Linux a supportare il \textit{journaling}.\\ 
    \texttt{romfs}   & un filesystem speciale per accedere ai dati memorizzati
                       su una ROM.\\  
    \texttt{ufs}     & \textit{Unix File System}, il filesystem usato da vari
                       Unix derivati da BSD (SunOS, FreeBSD, NetBSD, OpenBSD
                       e MacOS X).\\
    \texttt{vxfs}    & \textit{Veritas VxFS File System}, filesystem standard
                       di UnixWare disponibile anche su HP-UX e Solaris.\\ 
    \texttt{xfs}     & \textit{X File System}, il filesystem di IRIX, portato
                       dalla SGI su Linux. \\ 
    \texttt{befs}    & \textit{BeOS File System}, il filesystem del sistema
                       operativo BeOS.\\ 
    \texttt{msdos}   & il filesystem elementare usato dall'MSDOS.\\ 
    \texttt{vfat}    & il filesystem FAT usato da Windows 95/98.\\ 
    \texttt{proc}    & filesystem virtuale che fornisce informazioni sul
                       sistema.\\ 
    \texttt{tmpfs}   & filesystem usato per mantenere su un'area di
                       memoria dati temporanei che si appoggia al sistema della
                       memoria virtuale, i file non vengono mai salvati su
                       disco, ma in caso di necessità viene utilizzata la
                       partizione di \textit{swap} (vedi
                       sez.~\ref{sec:swap_CDROM_management}) per non perdere 
                       il contenuto.\\
    \texttt{sysfs}   & filesystem virtuale, introdotto con i kernel della
                       serie 2.6.x, che permette di accedere alle
                       informazioni relative ai dispositivi presenti e
                       relativi driver.\\
    \texttt{devpts}  & filesystem virtuale per consentire un accesso
                       efficiente ai terminali virtuali. \\
%    \texttt{usbdevfs}& filesystem virtuale contente le informazioni relative
%                       al bus USB.\\ 
    \texttt{nfs}     & \textit{Network File System}, filesystem per la
                       condivisione di file attraverso la rete tramite il
                       protocollo NFS (vedi sez.~\ref{sec:net_NFS_server})
                       creato da Sun.\\
    \texttt{coda}    & \textit{Coda File System}, filesystem distribuito su
                       rete che supporta funzionalità evolute come
                       autenticazione, replicazione e operazioni
                       disconnesse.\\
    \texttt{smbfs}   & \textit{SMB File System}, filesystem usato per montare
                       le directory condivise di Windows. \\ 
    \hline
  \end{tabular}
  \caption{Principali filesystem disponibili su Linux e relativi nomi per
    l'opzione \texttt{-t} di \texttt{mount}.}
  \label{tab:file_filesystem_types}
\end{table}

Il comando richiede quindi la conoscenza del tipo di filesystem presente nel
dispositivo che si vuole montare, da indicare come parametro per l'opzione
\texttt{-t}. L'elenco dei nomi dei principali tipi di filesystem supportati è
riportato in tab.~\ref{tab:file_filesystem_types}, è possibile comunque usare
anche un meccanismo di ricerca automatico, che viene attivato o usando
\texttt{auto} come tipo di filesystem o non specificando l'opzione. In questo
caso viene effettuato automaticamente un controllo se nel dispositivo è
presente uno dei filesystem riconosciuti per il quale viene usato il comando
\texttt{blkid} che vedremo a breve.

Se il riconoscimento non riesce viene effettuato un ulteriore tentativo
tentando di usare i tipi eventualmente elencati in
\index{configurazione!\texttt{/etc/filesystems}} \texttt{/etc/filesystems} e
poi, se questo file non esiste (come di default) quelli presenti in
\index{filesystem~\texttt{/proc}!\texttt{/proc/filesystems}}
\texttt{/proc/filesystems}, che contiene l'elenco dei filesystem supportati
nel kernel in esecuzione.  In genere si usa \texttt{/etc/filesystems} se si
vuole cambiare l'ordine in cui vengono provati i filesystem supportati, ad
esempio per provare prima \texttt{vfat} di \texttt{msdos}, evitando di usare
quest'ultimo quando è disponibile il primo, o se si vuole che eventuali moduli
aggiuntivi per i filesystem indicati vengano caricati
automaticamente.\footnote{si danno per noti i concetti relativi alla gestione
  dei moduli del kernel che verranno tratti in sez.~\ref{sec:kernel_modules}.}
Se si è creato \texttt{/etc/filesystems} si può inoltre richiedere l'uso
ulteriore dei dati di \texttt{/proc/filesystems} terminandone il contenuto con
un asterisco.

Come accennato \texttt{/proc/filesystems} contiene l'elenco di tutti i
filesystem supportati dal kernel in esecuzione, ed ovviamente per poterlo
utilizzare occorre che a sua volta il filesystem virtuale \texttt{/proc} (che
abbiamo già incontrato in sez.~\ref{sec:file_FHS}) sia stato preventivamente
montato. Il file elenca tutti i filesystem, compresi i cosiddetti
\textit{filesystem virtuali}, che non fanno riferimento ai dati di un
dispositivo (come lo stesso \texttt{/proc}) caratterizzati dalla presenza
della parola chiave \texttt{nodev}. Ovviamente nel tentativo di riconoscimento
automatico di un filesystem questi ultimi non vengono presi in considerazione.
Un estratto del contenuto di questo file, preso da una Debian Squeeze, è il
seguente:
\begin{FileExample}[label=/proc/filesystems]
nodev   sysfs
nodev   rootfs
nodev   bdev
nodev   proc
...
	ext3
nodev	rpc_pipefs
nodev	nfs
...
\end{FileExample}


Altre due importanti opzioni di \texttt{mount} sono \texttt{-L} e \texttt{-U}
che consentono di indicare il filesystem che deve essere montato senza fare
riferimento al relativo file di dispositivo.  Entrambe necessitano dell'uso
del file \index{filesystem~\texttt{/proc}!\texttt{/proc/partitions}}
\texttt{/proc/partitions}, dove sono mantenute le informazioni relative alle
partizioni dei dischi ed al loro contenuto. 

\itindbeg{Universal~Unique~Identifier (UUID)} 

Usando \texttt{-L} è possibile indicare quale filesystem montare invece che
attraverso il corrispondente file di dispositivo tramite una etichetta (che
deve essere stata impostata in fase di creazione del filesystem, vedi
sez.~\ref{sec:filesystem_create}), mentre con \texttt{-U} si può fare la
stessa operazione usando invece il valore del cosiddetto UUID
(\textit{Universally Unique Identifier}) associato al filesystem. L'UUID è un
numero di 128 bit utilizzato per identificare univocamente un oggetto molto
usato nella gestione dei dischi e che ritroveremo in varie occasioni; in
genere viene espresso con 32 cifre esadecimali suddivise in 5 sezioni separate
dal carattere ``\texttt{-}''; la prima versione cercava di garantire
l'univocità facendo riferimento al \textit{MAC address} (vedi
sez.~\ref{sec:net_arp}) del proprio computer e ad una marca temporale, le
versioni più recenti prevedono una opportuna generazione di un numero
univoco.\footnote{per i dettagli si consulti
  \url{http://en.wikipedia.org/wiki/UUID}.}

Queste due opzioni sono oggi utilizzate sempre più spesso, proprio in quanto
consentono (in particolare la seconda, che assicura la non ambiguità della
identificazione) di rendere non più necessari i riferimenti espliciti ai vari
file di dispositivo, che, come vedremo in sez.~\ref{sec:udev_hotplug}, ormai
vengono allocati prevalentemente in maniera dinamica tramite il sistema di
\textit{udev} e possono, in particolare con la diffusione dei dischi
rimuovibili, essere di volta in volta diversi.

L'uso di identificativi generici che permettono di riconoscere esattamente un
filesystem, indipendentemente dal nome assegnato al rispettivo file di
dispositivo, comporta anche la necessità di disporre degli opportuni programmi
che consentano di rilevare dette corrispondenze. Se sono note o l'etichetta o
l'UUID associato ad un filesystem il rispettivo file di dispositivo può essere
trovato con il comando \index{comando!\texttt{findfs}} \texttt{findfs}. Il
comando è molto semplice e prende un argomento nella forma
\texttt{LABEL=etichetta} o \texttt{UUID=valore}, stampando il corrispondente
file di dispositivo. L'operazione inversa può essere fatta con il comando
\index{comando!\texttt{blkid}} \texttt{blkid}, che prende come argomento un
file di dispositivo e stampa come risultato le proprietà del filesystem in
esso contenuto, ad esempio:
\begin{Console}
oppish:~# \textbf{blkid /dev/sda1}
/dev/sda1: UUID="aaf4126a-0dc0-4bb8-8429-557eb8c56fba" TYPE="ext3" 
\end{Console}

Il comando stampa le proprietà (file di dispositivo, tipo di filesystem,
eventuale etichetta e UUID) relative a qualunque dispositivo a blocchi. Se
invocato senza argomenti esegue l'elenco per tutti i dispositivi a blocchi
presenti, altrimenti si può effettuare una selezione passando come argomento
il nome di un file di dispositivo. Inoltre si può, attraverso l'opzione
\texttt{-t}, eseguire la selezione per etichetta, UUID o tipo di filesystem,
passando all'opzione un parametro rispettivamente nella forma
\texttt{LABEL=value}, \texttt{UUID=value} o \texttt{TYPE=value}, dove in
quest'ultimo caso il tipo di filesystem deve essere indicato con uno dei
valori di tab.~\ref{tab:file_filesystem_types}.

\itindend{Universal~Unique~Identifier (UUID)} 

Altre opzioni importanti del comando \texttt{mount}, utilizzate spesso
nell'invocazione, sono \texttt{-v}, che aumenta la prolissità dei messaggi e
\texttt{-a} che monta tutti i filesystem elencati per il montaggio automatico
in \texttt{/etc/fstab} (sul cui uso torneremo a breve). Si sono riportate le
altre principali opzioni in tab.~\ref{tab:mount_cmd_options}, mentre per
l'elenco completo si può consultare la pagina di manuale, accessibile con
\texttt{man mount}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-a} & monta tutti i filesystem marcati per il montaggio automatico
                  all'avvio in \texttt{/etc/fstab}.\\
    \texttt{-n} & non aggiorna l'elenco dei filesystem montati mantenuto in
                  \texttt{/etc/mtab}.\\ 
    \texttt{-o \textsl{opt}} & specifica una opzione di montaggio
                  \texttt{\textsl{opt}}.\\ 
    \texttt{-r} & monta il filesystem in sola lettura.\\
    \texttt{-t \textsl{type}} & specifica il tipo di filesystem
                  \texttt{\textsl{type}}.\\ 
    \texttt{-w} & monta il filesystem in sola scrittura.\\
    \texttt{-v} & aumenta la prolissità nella stampa dei messaggi.\\
%    \texttt{} & .\\
    \hline
  \end{tabular}
  \caption{Le principali opzioni del comando \texttt{mount}.}
  \label{tab:mount_cmd_options}
\end{table}

Si è lasciata per ultima, da trattare a parte per la sua rilevanza peculiare,
l'opzione \texttt{-o} che viene usata per specificare le cosiddette
\textsl{opzioni di montaggio} con cui si possono impostare la caratteristiche
di utilizzo del filesystem che viene montato. Ogni filesystem infatti può
presentare diverse modalità di funzionamento, che vengono controllate appunto
attraverso le sue opzioni di montaggio. Alle opzioni specifiche di ogni
singolo filesystem si aggiungono quelle generiche, che sono disponibili per
qualunque filesystem, riportate in tab.~\ref{tab:file_default_mount_options}.

Ciascuna opzione di montaggio è identificata da un nome, che viene passato
come parametro di \texttt{-o}; se ne può anche specificare una lista,
scrivendone i rispettivi nomi separati da virgole e senza spazi in mezzo.  Si
tenga presente che alcune delle opzioni elencate in
tab.~\ref{tab:file_default_mount_options}, in particolare \texttt{auto},
\texttt{user}, \texttt{users} e \texttt{defaults} e relative negazioni, hanno
significato solo quando vengono usate nel quarto campo del file
\texttt{/etc/fstab}, su cui torneremo fra breve.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Valore} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{async}   & tutto l'I/O sul filesystem viene eseguito in maniera
                       asincrona, cioè le funzioni di scrittura ritornano ed è
                       il kernel che si incarica di eseguire la effettiva
                       scrittura dei dati nel momento più opportuno (è il
                       default).\\
    \texttt{atime}   & Aggiorna il valore del tempo di ultimo accesso ai file
                       (vedi sez.~\ref{sec:struct_filesystem_arch}) presenti
                       sul filesystem, era il default fino al kernel
                       2.6.30.\\
    \texttt{auto}    & tutti i filesystem con questa opzione citati in
                       \texttt{/etc/fstab} vengono montati dal comando
                       \texttt{mount -a} (che in genere è quello che viene
                       eseguito all'avvio del sistema).\\  
    \texttt{defaults}& usa le opzioni di default: \texttt{rw}, \texttt{suid},
                       \texttt{dev}, \texttt{exec}, \texttt{auto},
                       \texttt{nouser}, e \texttt{async}.\\
    \texttt{dev}     & consente la presenza di file 
                       di dispositivo all'interno del filesystem (è il
                       default).\\
    \texttt{dirsync} & esegue in maniera sincrona le operazioni che
                       comportano una scrittura sulle directory: creazione di
                       link, creazione, spostamento e cancellazione di file,
                       creazione e cancellazione di directory e file di dispositivo.\\
    \texttt{group}   & consente ad un utente di montare il filesystem se
                       questi appartiene al gruppo proprietario del
                       relativo dispositivo; questa opzione comporta
                       automaticamente come restrizioni le opzioni
                       \texttt{noexec}, \texttt{nosuid}, e \texttt{nodev}, se
                       non soprassedute esplicitamente con \texttt{exec},
                       \texttt{suid}, e \texttt{dev}.\\
    \texttt{exec}   &  consente l'esecuzione di programmi presenti sul
                       filesystem (è il default).\\ 
    \texttt{\_netdev}& indica che il filesystem è su un dispositivo che
                       richiede l'uso della rete (ad esempio un disco
                       \textit{iSCSI}) ed evita che questo sia montato
                       automaticamente prima che essa diventi disponibile.\\
    \texttt{noatime}&  non aggiorna il valore del tempo di ultimo accesso al
                       file (utile quando si vogliono evitare ulteriori
                       accessi al disco).\\
    \texttt{noauto}  & il filesystem deve essere montato esplicitamente (viene
                       ignorato dall'opzione \texttt{-a}).\\
    \texttt{nodev}   & non consente l'uso di  file
                       di dispositivo presenti sul filesystem.\\ 
    \texttt{noexec}  & non consente l'esecuzione di programmi presenti sul
                       filesystem.\\ 
    \texttt{nosuid}  & non consente che i bit \textsl{suid} e \textsl{sgid} (vedi
                       sez.~\ref{sec:struct_file_perm}) abbiano effetto.\\  
    \texttt{relatime}& aggiorna il tempo di ultimo accesso al file soltanto
                       quando questo è anteriore al tempo di ultima
                       modifica col le stesse prestazioni di \texttt{noatime}
                       senza causare ai programmi che usano il tempo di ultimo
                       accesso per identificare i file che sono stati letti. A
                       partire dal kernel 2.6.30 questa opzione è diventata il
                       default, e  può riottenere il precedente comportamento
                       con l'indicazione esplicita della nuova opzione
                       \texttt{strictatime}.\\  
    \texttt{ro}      & chiede il montaggio del filesystem in sola lettura.\\
    \texttt{rw}      & chiede il montaggio del filesystem in lettura e
                       scrittura (è il default).\\ 
    \texttt{suid}    & consente che i bit \textsl{suid} e \textsl{sgid} (vedi
                       sez.~\ref{sec:struct_file_perm}) abbiano effetto (è il
                       default).\\
    \texttt{sync}    & tutto l'I/O sul filesystem deve essere sincrono (vale a
                       dire che le funzioni di scrittura prima di proseguire 
                       aspettano che i dati vengano scritti su disco).\\
    \texttt{user}    & consente anche ad un utente normale di montare il
                       filesystem, con le stesse restrizioni viste per
                       \texttt{group}; il nome utente viene scritto su
                       \texttt{/etc/mtab} e solo lui potrà smontarlo.\\ 
    \texttt{nouser}  & solo l'amministratore può montare il filesystem (è
                       il default).\\
    \texttt{users}   & consente ad un qualunque utente di montare il
                       filesystem, con le stesse restrizioni viste per
                       \texttt{group}, e ad un qualunque altro di
                       smontarlo.\\ 
    \hline
  \end{tabular}
  \caption{Valori delle opzioni di montaggio disponibili per qualunque tipo di
    filesystem.}
  \label{tab:file_default_mount_options}
\end{table}

Oltre a specificare delle opzioni di montaggio coi valori riportati in
tab.~\ref{tab:file_default_mount_options} l'opzione \texttt{-o} consente anche
di effettuare alcune operazioni speciali; ad esempio utilizzando il valore
\texttt{remount} diventa possibile rimontare al volo un filesystem già montato
senza smontarlo, per cambiare alcune delle opzioni precedenti. Uno degli usi
più comuni per questa opzione è quello di rimontare in lettura/scrittura un
filesystem che si è montato in sola lettura per poterci effettuare un
controllo, o viceversa.\footnote{si tenga presente però che fin quando ci sono
  file aperti in lettura/scrittura, l'operazione di rimontaggio in sola
  lettura fallirà.}

Un'altra opzione molto utile è \texttt{loop}; in questo caso in realtà non si
tratta propriamente di una opzione di montaggio relativa ad un filesystem
quanto di un modo per effettuare automaticamente l'impostazione di un
dispositivo di \textit{loopback} tramite il quale diventa possibile montare un
filesystem contenuto in un ordinario file di dati (ovviamente il file deve
contenere un filesystem completo). Così se ad esempio il file
\texttt{geomorphix.iso} è l'immagine ISO di un CD, si potrà accedere al
contenuto della stessa in maniera trasparente, montando il file come se fosse
un CD, con il comando:
\begin{Example}
mount -t iso9660 -o loop geomorphix.iso /mnt/images
\end{Example}

Con questa stessa interfaccia è possibile anche montare un filesystem
opportunamente cifrato, nel qual caso si dovrà specificare l'opzione
\texttt{encryption} per indicare l'algoritmo di cifratura usato e l'opzione
\texttt{keybits} per specificare la lunghezza (in bit) della chiave; la
password di accesso verrà chiesta sul terminale. Questo uso è comunque
deprecato, e non più disponibile sui kernel recenti, in quanto presenta grossi
problemi di sicurezza, al suo posto può essere utilizzato il sistema del
\textit{device mapper} che vedremo in sez.~\ref{sec:encrypted_disks}.

Come accennato l'uso dell'opzione \texttt{loop} è un meccanismo semplificato
per eseguire automaticamente l'impostazione di un dispositivo di
\textit{loopback}. Questo non è altro che un dispositivo virtuale che consente
di accedere al contenuto di un file di dati come se si trattasse di un
dispositivo fisico. In generale l'impostazione deve essere fatta manualmente
con il comando \index{comando!\texttt{losetup}} \texttt{losetup}, che consente
di associare il contenuto di un file, passato come argomento, ad un apposito
dispositivo, accessibile con il nome \texttt{/dev/loop\textsl{N}}, dove
\texttt{\textsl{N}} è un numero progressivo che, se non si specifica niente,
viene allocato automaticamente.\footnote{questo fintanto che non si supera il
  numero massimo di dispositivi di \textit{loopback} disponibili; il valore di
  default del limite è 8, ma può essere cambiato fino ad un massimo assoluto
  di 256 caricando il modulo di kernel che implementa il dispositivo con una
  opportuna opzione (vedi sez.~\ref{sec:kernel_modules}).}

Il comando consente anche, con \texttt{-f}, di indicare quale specifico file
di dispositivo deve essere usato, passandolo come parametro all'opzione, o di
ottenere il primo dispositivo libero se non si specifica nessun argomento. Si
può poi rimuovere l'associazione e liberare il dispositivo con l'opzione
\texttt{-d} (che prende come argomento il nome del dispositivo stesso), o
ottenere un elenco dei dispositivi definiti con l'opzione \texttt{-a}; per
l'elenco delle opzioni e tutti i dettagli sul comando si consulti la pagina di
manuale.

Ci si può chiedere, a parte l'esempio citato, a cosa possa servire una
funzionalità come quella del \textit{loopback}, dato che avere a disposizione
un file contenente un filesystem può sembrare un caso abbastanza esoterico. In
realtà, dato che in un sistema unix-like tutto è un file, il caso è abbastanza
comune; basta infatti copiare con \texttt{dd} un file di dispositivo su un
file per ottenere l'immagine del contenuto del dispositivo stesso, come
illustrato in sez.~\ref{sec:backup_misc_command}, ed a questo punto poterne
ispezionare il contenuto e verificare l'integrità è senz'altro molto utile.


% TODO bind mount !!!

Come accennato più volte in precedenza nel funzionamento di \texttt{mount} è
fondamentale il file \index{configurazione!\texttt{/etc/fstab}}
\texttt{/etc/fstab} (il cui nome sta per \textit{\textbf{f}ile \textbf{s}ystem
  \textbf{tab}le}) che può essere considerato come una specie di file di
configurazione del comando. In generale è cura della procedura di
installazione creare un file \texttt{/etc/fstab} che contenga tutte le
informazioni necessarie a montare tutti i filesystem creati sulla base delle
scelte sul partizionamento fatte in tale occasione.

Il formato del file è molto semplice: ogni linea definisce un filesystem da
montare, ed è composta da sei campi.  Linee vuote o che iniziano per
``\texttt{\#}'' vengono ignorate, i campi di ogni linea sono separati da spazi
o tabulatori. La pagina di manuale, accessibile con \texttt{man fstab}, ne
spiega i dettagli, un esempio classico del suo contenuto è il seguente:
\begin{FileExample}[label=/etc/fstab]
# /etc/fstab: static file system information.
#
# file system mount point     type    options                        dump  pass
/dev/hdb5     /               ext2    defaults,errors=remount-ro      0       1
/dev/hdb6     none            swap    sw                              0       0
proc          /proc           proc    defaults                        0       0
/dev/fd0      /floppy         auto    defaults,user,noauto            0       0
/dev/cdrom    /cdrom          iso9660 defaults,ro,user,noauto         0       0
/dev/hdb1     /boot           ext2    rw                              0       2
/dev/hda1     /mnt/win        vfat    defaults,user,noauto            0       0
/dev/hdc4     /mnt/zip        auto    defaults,user,noauto            0       0
\end{FileExample}
%/dev/sr0      /mnt/cdrom      iso9660 defaults,ro,user,noauto         0       0

Il primo campo specifica quale è il filesystem da montare che viene
normalmente indicato tramite il file di dispositivo su cui lo stesso risiede:
nel caso dell'esempio si avevano due dischi rigidi IDE con varie partizioni,
indicati con i vari \texttt{/dev/hda\textsl{N}} e \texttt{/dev/hdb\textsl{N}},
un floppy, indicato con \texttt{/dev/fd0}, uno ZIP su IDE, indicato come
\texttt{/dev/hdc4}, un CDROM ed un masterizzatore SCSI, indicati
rispettivamente con \texttt{/dev/cdrom} e \texttt{/dev/sr0}, dove nel caso del
CDROM si era usato un link simbolico.

Si noti che per il filesystem \texttt{/proc}, il cui contenuto non è mantenuto
in nessun dispositivo fisico ma viene fornito direttamente dal kernel, si è
usata invece la parola chiave \texttt{proc}. Se ci fossero stati dei
filesystem di rete montati con NFS (vedi sez.~\ref{sec:net_NFS_client}) si
sarebbero potute avere anche righe del tipo:
\begin{FileExample}[label=/etc/fstab]
davis.truelite.it:/data /mnt/nfs    nfs    defaults,user,noauto     0       0
\end{FileExample}
in cui nel primo campo viene indicata la directory remota da montare.

L'esempio illustrato fa riferimento ad una installazione precedente la versione
2.3 del FHS, che non prevedeva sistemi di rilevazione automatica dei
dispositivi rimuovibili e non richiedeva l'uso della directory \texttt{/media}
per i dispositivi rimuovibili. Oggi l'uso diretto dei file di dispositivo è
sempre meno comune ed un esempio più recente di \texttt{/etc/fstab} potrebbe
essere il seguente estratto, ottenuto da una installazione ordinaria di una
Debian Squeeze:
\begin{FileExample}[label=/etc/fstab]
# <file system> <mount point>   <type>  <options>       <dump>  <pass>
proc            /proc           proc    defaults         0       0
/dev/scd0       /media/cdrom0   udf,iso9660 user,noauto  0       0

# / was on /dev/sda1 during installation
UUID=4edbcf3d-d8bd-49e0-8af5-7f40cea66bb4 /    ext3   errors=remount-ro 0    1
# swap was on /dev/sda5 during installation
UUID=a2331c52-91ab-445b-bc55-7f42a3b9e2e1 none swap   sw                0    0
\end{FileExample}


In questo caso si noti come i file di dispositivo siano sostituiti dagli UUID
ad essi associati, specificati in forma di assegnazione alla parola chiave
\texttt{UUID}. Alternativamente si possono indicare i dispositivi con
eventuali etichette usando la parola chiave \texttt{LABEL} con la stessa
sintassi, ottenendo un effetto equivalente all'uso delle opzioni \texttt{-U} e
\texttt{-L} di \texttt{mount}, ed anche in questo caso per il funzionamento
del sistema deve essere disponibile \texttt{/proc/partitions}.

La scelta dell'uso degli UUID al posto dei file di dispositivo è ormai comune
in tutte le distribuzioni più recenti che fanno questa scelta per evitare
problemi con eventuali variazioni dei nomi dei file di dispositivo dovuta alla
loro allocazione dinamica da parte del sistema di \textit{udev}, come può
avvenire perché i dischi sono stati rimontati su un diverso canale IDE, o per
il passaggio all'uso di \textit{libATA} che fa apparire i dischi IDE come
SCSI, o per un diverso ordine di riconoscimento sul bus SCSI che può avvenire
con i dischi USB rimuovibili o con l'uso di controller multipli.

Il secondo campo di \texttt{/etc/fstab} indica il \textit{mount point}, cioè
la directory dove i file contenuti nel dispositivo indicato nel primo campo
saranno resi disponibili, e deve essere specificato con il suo pathname
assoluto.  Se sul dispositivo non esiste un filesystem che deve essere
montato, come avviene nel caso di una partizione di \textit{swap} (vedi
sez.~\ref{sec:swap_CDROM_management}), al posto del pathname si deve usare la
parola chiave \texttt{none}.

Il terzo campo indica il tipo di filesystem che sta sul dispositivo che si
vuole montare, e deve essere specificato allo stesso modo con cui lo si indica
all'opzione \texttt{-t} di \texttt{mount}, utilizzando gli stessi valori già
riportati in tab.~\ref{tab:file_filesystem_types}.  Si noti però come negli
esempi precedenti venga usata anche la parola chiave \texttt{swap}, che non
compare in tab.~\ref{tab:file_filesystem_types}. Essa infatti serve ad
indicare che il dispositivo non contiene un filesystem, ma viene usato per la
\textit{swap} (vedi sez.~\ref{sec:swap_CDROM_management}).

Il quarto campo di \texttt{/etc/fstab} indica le opzioni con cui si deve
montare il filesystem, e prende gli stessi valori dell'opzione \texttt{-o} di
\texttt{mount}, riportati in tab.~\ref{tab:file_default_mount_options}. Nel
caso si usi l'opzione \texttt{defaults} la successiva specificazione di
un'altra opzione soprassiede il valore di default. Come per \texttt{-o} più
opzioni vanno specificate di seguito, separate da virgole e senza spazi
interposti.

Gli ultimi due campi sono relativi alla manutenzione del filesystem, il quinto
campo indica se effettuare il \textit{dump}\footnote{è un valore utilizzabile
  solo per i filesystem (attualmente ext2 ed ext3) che supportano il comando
  di backup \texttt{dump}; % (vedi sez.~\ref{sec:dump_restore});
  se attivato con un valore non nullo verranno salvate le informazioni che
  consentono a \texttt{dump} di eseguire i backup incrementali.} del
filesystem ed in genere viene lasciato a 0 (per attivarlo occorre usare invece
1) mentre il sesto campo indica la sequenza con cui all'avvio viene lanciato
il comando \texttt{fsck} per controllare lo stato dei dischi (vedi
sez.~\ref{sec:filesystem_check}), uno zero indica che il controllo non deve
essere eseguito.

L'uso principale di \texttt{/etc/fstab} è il controllo del comportamento del
comando \texttt{mount -a} che viene utilizzato nella procedura di avvio del
sistema per montare automaticamente tutte le directory del sistema se queste
sono state installate su filesystem separati rispetto alla radice. In questo
caso è necessario marcare la riga relativa con l'opzione \texttt{auto}. Per i
filesystem che non devono essere montati all'avvio (ad esempio i CD-ROM) si
deve specificare invece l'opzione \texttt{noauto}.

La presenza di una configurazione in \texttt{/etc/fstab} permette inoltre di
semplificare l'uso di \texttt{mount} poiché per i filesystem in esso elencati
il comando può essere invocato specificando solo il \textit{mount point} o
solo il file di dispositivo. Inoltre questa sintassi consente l'uso di
\texttt{mount} anche agli utenti normali, i quali potranno montare un
dispositivo qualora si siano specificate le opzioni \texttt{user},
\texttt{group} o \texttt{users} nella riga relativa. L'operazione di montaggio
di un filesystem è privilegiata e può essere effettuata in modo generico solo
dall'amministratore. In questo modo si può permettere agli utenti di montare i
propri CD e floppy, senza però consentirgli di modificare il \textit{mount
  point} o le opzioni di montaggio.

Dal punto di vista dell'amministrazione si potrà avere che fare con
\texttt{/etc/fstab} tutte le volte che si aggiunge un disco, o un nuovo
dispositivo a blocchi, o si cambiano le partizioni. In questo caso occorrerà
identificare qual'è il file di dispositivo o l'UUID da usare e scegliere una
directory su cui montarlo. Deve poi essere specificato il filesystem da usare
(o \texttt{auto} se si vuole tentare il riconoscimento automatico) e le
eventuali opzioni di montaggio.

Si noti come nel primo esempio per ZIP e floppy si sia consentito agli utenti
di montare il filesystem, ma si sia disabilitato il montaggio all'avvio, e
pure il controllo dello stato del filesystem, dato che non è detto che il
floppy o lo ZIP siano inseriti nel rispettivo lettore.  Lo stesso vale per il
CDROM e il masterizzatore, per i quali però si è pure aggiunta l'opzione di
montaggio in sola lettura.

Le distribuzioni più recenti tendono comunque a gestire i dispositivi
rimuovibili attraverso programmi dedicati che sono in grado di rilevare la
loro presenza e montarli automaticamente per cui eventuali voci di questo tipo
sono assenti nel secondo esempio, in tal caso infatti quello che in genere
viene fatto è inserire l'utente in un apposito gruppo che contiene tutti
quelli a cui è consentito utilizzare dispositivi rimuovibili (su Debian ed
Ubuntu il gruppo è \texttt{plugdev}).

Un secondo file collegato all'uso di \texttt{mount} è
\index{configurazione!\texttt{/etc/mtab}} \texttt{/etc/mtab}, che contiene
l'elenco dei filesystem montati mostrato dal comando quando lo si invoca senza
opzioni. Il file viene creato ed aggiornato automaticamente da \texttt{mount}
nelle sue operazioni e non deve essere modificato manualmente, ma si tenga
presente che se la radice è in sola lettura (o se si è usata l'opzione
\texttt{-n} per eseguire un montaggio) le sue informazioni possono non essere
aggiornate.

Le stesse informazioni sono presenti anche all'interno di
\index{filesystem~\texttt{/proc}!\texttt{/proc/mounts}} \texttt{/proc/mounts},
ma in questo caso sono mantenute direttamente dal kernel e sono quindi sempre
aggiornate, tanto che talvolta si suggerisce di sostituire \texttt{/etc/mtab}
con un link simbolico a questo file.  In realtà in \texttt{/etc/mtab} vengono
mantenute informazioni aggiuntive, come l'utente che ha montato un filesystem
nel caso dell'opzione \texttt{user}, che non sarebbe disponibile nel caso di
un link simbolico.

Si tenga presente che quando si monta un filesystem su una directory un
eventuale contenuto di quest'ultima viene \textsl{oscurato} dal contenuto del
nuovo filesystem, e non sarà più possibile accedervi fintanto che questo non
viene smontato. Se però si sono aperti dei file in essa presenti questi
continueranno a funzionare regolarmente in quanto sono visti attraverso il
loro \textit{inode} (si ricordi quanto detto in
sez.~\ref{sec:struct_filesystem_arch}).  Inoltre a partire dal kernel 2.4
diventa possibile \textsl{impilare} più operazioni di mount sulla stessa
directory, che presenterà il contenuto dell'ultimo filesystem montato, valendo
quanto appena detto per il contenuto dei precedenti.

In maniera analoga a come lo si è montato, quando non si ha più la necessità
di accedere ad un filesystem, questo potrà essere \textsl{smontato}. In questo
modo diventa possibile rimuovere, nel caso di kernel modulare, (vedi
sez.~\ref{sec:kernel_modules}) le eventuali risorse aggiuntive, e liberare la
directory utilizzata per il montaggio per un eventuale riutilizzo. Come
accennato a partire dalla serie 2.4.x del kernel questo non è più necessario,
in quanto si possono \textsl{impilare} più montaggi sulla stessa directory, è
comunque necessario smontare un device rimovibile come il floppy o il CD,
prima di poterlo estrarre e sostituire.

Il comando in questo caso è \index{comando!\texttt{umount}} \texttt{umount}
(si dice che la \texttt{n} si sia persa nei meandri delle prime
implementazioni di Unix) che può prendere come argomento sia il \textit{mount
  point} che il file di dispositivo, e distacca il relativo filesystem
dall'albero dei file.  Si tenga presente che fintanto che il filesystem è
utilizzato questa operazione non viene permessa: questo significa che fintanto
che si hanno processi che hanno aperto dei file contenuti nel filesystem, o la
cui directory di lavoro (vedi sez.~\ref{sec:struct_proc_property}) è nel
filesystem, non sarà possibile effettuarne lo smontaggio, e l'uso del comando
darà luogo ad un errore di risorsa occupata.

Il problema può risultare particolarmente antipatico quando si ha a che fare
con un dispositivo rimovibile che si vuole estrarre, in tal caso però si può
ricorrere al comando \texttt{lsof} (vedi sez.~\ref{sec:diagnostic_command})
per individuare i processi che stanno ancora utilizzando il filesystem e
terminarli o cambiargli directory di lavoro (se trattasi di shell). Inoltre
dal kernel 2.4.11 è disponibile un \textit{lazy umount}, attivabile con
l'opzione \texttt{-l}, che distacca immediatamente il filesystem (impedendo
ogni ulteriore accesso allo stesso) ma esegue le successive operazioni di
pulizia e la chiusura del filesystem soltanto quando tutte le risorse occupate
vengono liberate.

Una sintassi alternativa per \texttt{umount} è l'uso dell'opzione \texttt{-a},
che smonta tutti i filesystem elencati in \texttt{/etc/mtab} (tranne, a
partire dalla versione 2.7 del comando, \texttt{/proc}), in questo caso
ovviamente non è necessario indicare quale dispositivo smontare, ma si può
restringere le operazioni a tutti i filesystem di un determinato tipo,
specificando quest'ultimo con l'opzione \texttt{-t}. L'elenco completo delle
opzioni del comando è disponibile nella relativa pagina di manuale,
accessibile con \texttt{man umount}.

Si tenga presente che quando si smonta un filesystem tutte le modifiche
effettuate fino a quel momento dovranno essere registrate su disco. Questo
significa, dato che il kernel prevede la bufferizzazione dei
dati,\footnote{dato che l'accesso a disco è lento il kernel cerca di eseguire
  i trasferimenti dei dati nella maniera più efficace possibile, salvando le
  modifiche in memoria ed effettuando le scritture in gruppo al momento
  reputato più opportuno.} che in certe occasioni l'uso di \texttt{umount} può
risultare piuttosto lento e scatenare una forte attività di accesso al disco,
dato che il comando non termina fintanto che tutti i buffer sono stati
scaricati. Questa operazione può essere forzata, senza dover smontare il
filesystem, con il comando \index{comando!\texttt{sync}} \texttt{sync} che si
limita semplicemente a richiedere al kernel che lo scarico dei buffer sia
effettuato immediatamente.

Altri comandi essenziali per la gestione dei dischi sono quelli che consentono
di verificare lo spazio disco utilizzato e la percentuale di uso dei vari
filesystem. Il primo di questi è \index{comando!\texttt{df}} \texttt{df}; se
invocato senza argomenti il comando stampa l'occupazione dello spazio disco di
ciascun filesystem montato, con un sommario della relativa dimensione totale,
dei blocchi occupati e liberi e della percentuale di occupazione. 

Il comando si cura di riportare soltanto quelli che hanno un contenuto reale,
non vengono cioè mostrati filesystem virtuali come \texttt{/proc} o
\texttt{/sys} che non hanno una reale occupazione di spazio disco o di altre
risorse. Un esempio del possibile risultato è qualcosa del tipo:
\begin{Console}
piccardi@hain:~$ \textbf{df}
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/md0             114389928  82038556  26540668  76% /
tmpfs                   258436         0    258436   0% /lib/init/rw
udev                     10240        64     10176   1% /dev
tmpfs                   258436         4    258432   1% /dev/shm
/dev/sda1            192292124 115097092  67427112  64% /bacula
\end{Console}
%$

Il default prevede che il comando indichi l'occupazione di spazio disco in
blocchi da 1K (1024 byte), ma si possono richiedere dimensioni diverse o la
stampa in un formato più leggibile con l'opzione \texttt{-h} che invece di
riportare i numeri per esteso usa alla bisogna i suffissi dei multipli
decimali (K, M, G) e scrive le dimensioni in byte rendendo più evidenti i
numeri in gioco.

Si può inoltre indicare al comando un singolo filesystem, per ottenere i dati
relativi solo a quello o un tipo tramite l'opzione \texttt{-t}, che prende
come parametro uno del valori di tab.~\ref{tab:file_filesystem_types}. Infine
con l'opzione \texttt{-i} si può richiedere un rapporto relativo all'uso degli
\textit{inode} invece che a quello dello spazio disco. Al solito per i
dettagli e tutte le opzioni si consulti la pagina di manuale.

Qualora invece del totale a livello di intero filesystem si voglia conoscere
lo spazio disco occupato dai file posti all'interno di una certa directory si
può usare il comando \index{comando!\texttt{du}} \texttt{du}. Il comando
prende come argomenti una lista di file e directory e stampa un sommario dello
spazio occupato da ciascuno di essi, in kilobyte. Se non si specificano
argomenti viene usata la directory corrente.

Il comando stampa ricorsivamente la quantità di spazio disco occupato
all'interno di ciascuna sottodirectory a partire da quelle indicate come
argomenti, se si vuole conoscere solo il totale relativo alle directory
indicate si può utilizzare l'opzione \texttt{-s}. Una seconda opzione utile è
\texttt{-c} che permette, quando si indicano più argomenti, di ottenere anche
la stampa dell'occupazione totale relativa a tutti gli argomenti. Il comando,
come \texttt{df}, supporta anche l'opzione \texttt{-h} per la stampa dei
numeri con le abbreviazioni. Per i dettagli sul funzionamento del comando
(cambiare unità di misura, escludere file dal calcolo, ecc.) si consulti al
solito la pagina di manuale.


\subsection{La creazione di un filesystem}
\label{sec:filesystem_create}

Abbiamo visto in sez.~\ref{sec:file_disk_management} come si può rendere
disponibile il contenuto di un filesystem nell'albero delle directory. Quando
si installa il sistema o quando si aggiunge un disco però i filesystem devono
essere creati, in modo da strutturare per l'uso lo spazio disponibile (che sia
una partizione o un dispositivo fisico o virtuale), operazione comunemente
detta \textsl{formattazione}.

\begin{table}[!htb]
  \footnotesize
  \centering
  \begin{tabular}[c]{|l|l|p{10cm}|}
    \hline
    \textbf{Tipo} & \textbf{Opzione} & \textbf{Descrizione} \\
    \hline
    \hline
    \texttt{reiserfs}& \multicolumn{2}{|c|}{\texttt{mkreiserfs}} \\ 
    \cline{2-3}
    & \texttt{-b \textsl{N}}    & specifica la dimensione dei blocchi.\\
    & \texttt{-j \textsl{file}} & specifica un file di dispositivo per il giornale.\\ 
%    & \texttt{-h \textsl{hash}} & specifica un algoritmo di 
%                                  \textit{hashing} per la
%                                  ricerca veloce dei file all'interno delle
%                                  directory.\\
    & \texttt{-l \textsl{label}}& imposta una etichetta sul filesystem (16
                                  caratteri).\\ 
    & \texttt{-s \textsl{N}}    & specifica la dimensione del giornale.\\
    & \texttt{-u \textsl{UUID}} & associa un UUID al filesystem.\\ 
    \hline
    \texttt{msdos}&  \multicolumn{2}{|c|}{\texttt{mkdosfs} o \texttt{mkfs.msdos}} \\
    \cline{2-3}
%    & \texttt{-c}      & esegue il controllo del dispositivo per eventuali
%                         settori difettosi.\\
    & \texttt{-F \textsl{N}} & specifica la dimensione della FAT (\textit{File
                         Allocation Table}).\\
    & \texttt{-n \textsl{name}} & specifica un nome per il volume (11
                         caratteri).\\ 
    \hline
    \texttt{vfat} &\multicolumn{2}{|c|}{\texttt{mkfs.vfat}}\\
    \cline{2-3}
    & \texttt{} & esegue \texttt{mkdosfs}.\\
    \hline
    \texttt{ext2} & \multicolumn{2}{|c|}{\texttt{mke2fs} o \texttt{mkfs.ext2}}\\
    \cline{2-3}
    & \texttt{-b \textsl{N}}& specifica la dimensione dei blocchi.\\
%    & \texttt{-c}      & esegue il controllo del dispositivo per eventuali
%                         settori difettosi.\\
    & \texttt{-F}      & forza successivo controllo del filesystem.\\
    & \texttt{-i \textsl{N}} & specifica ogni quanti byte di spazio disco deve
                         essere creato un \textit{inode}, non
                         può essere inferiore alle dimensioni di un blocco.\\
    & \texttt{-j}      & crea il giornale per il filesystem (equivalente ad
                         invocare il comando come \texttt{mkfs.ext3}).\\
    & \texttt{-J \textsl{opts}} & permette di specificare i parametri per la
                         gestione del file di giornale.\\
    & \texttt{-L \textsl{label}}& associa un'etichetta al filesystem.\\
    & \texttt{-m \textsl{N}}& specifica la percentuale di spazio disco
                         riservata per l'amministratore che gli utenti normali
                         non possono usare. \\
    & \texttt{-T \textsl{type}} & specifica la tipologia di utilizzo del
                         filesystem, con un'indicazione generica che consente
                         di stabilire lo spazio da assegnare ad 
                         \textit{inode} e spazio per i file.\\
    & \texttt{-U \textsl{UUID}} & associa un UUID al filesystem.\\
    \hline
    \texttt{ext3} & \multicolumn{2}{|c|}{\texttt{mkfs.ext3}}\\
     \cline{2-3}
   & \texttt{} & esegue \texttt{mke2fs} con le opportune opzioni.\\
    \hline
    \texttt{ext4} & \multicolumn{2}{|c|}{\texttt{mkfs.ext4}}\\
     \cline{2-3}
   & \texttt{} & esegue \texttt{mke2fs} con le opportune opzioni.\\
    \hline
    \texttt{xfs}&  \multicolumn{2}{|c|}{\texttt{mkfs.xfs}} \\
    \cline{2-3}
    & \texttt{-b \textsl{N}}    & specifica la dimensione dei blocchi.\\
    & \texttt{-d \textsl{opt}}  & imposta le opzioni per la gestione dei dati
                                  dei file.\\
    & \texttt{-f}               & forza la sovrascrittura di un filesystem già
                                  presente.\\
    & \texttt{-i \textsl{opt}}  & imposta le opzioni per la gestione degli \textit{inode}.\\
%    & \texttt{-s \textsl{N}}    & specifica la dimensione dei settori.\\
    & \texttt{-l \textsl{opt}}  & imposta le opzioni per il
                                  \textit{journaling} del filesystem.\\
    & \texttt{-L \textsl{label}}& associa un'etichetta al filesystem (12 caratteri).\\
    & \texttt{-m \textsl{opt}}  & imposta le opzioni di gestione generali per
                                  i metadati del filesystem.\\
    & \texttt{-n \textsl{opt}}  & imposta le opzioni di gestione per le directory.\\
    & \texttt{-N}               & stampa i parametri del filesystem che
                                  verrebbe creato, senza scrivere sul disco.\\
%    & \texttt{-p \textsl{file}} & legge le impostazioni per la creazione
%                                  da un file di ``\textsl{prototipo}''.\\
    & \texttt{-s \textsl{N}}    & specifica la dimensione dei settori.\\
    \hline
    \texttt{btrfs} &\multicolumn{2}{|c|}{\texttt{mkfs.btrfs}}\\
    \cline{2-3}
    & \texttt{-b  \textsl{N}}   & specifica la dimensione del filesystem (in byte).\\
    & \texttt{-d  \textsl{type}}& specifica la distribuzione dei dati (prende
                                  come valori uno fra: \texttt{raid0},
                                  \texttt{raid1}, \texttt{raid5},
                                  \texttt{raid6}, \texttt{raid10} o \texttt{single}).\\ 
    & \texttt{-L \textsl{label}}& associa un'etichetta al filesystem.\\
    & \texttt{-U \textsl{UUID}} & associa un UUID al filesystem.\\
    \hline
  \end{tabular}
  \caption{Principali comandi, e relative opzioni, per la creazione dei filesystem.}
  \label{tab:file_mkfs_options}
\end{table}

%%
%% ### OBSOLETE BEGIN ###
%% Materiale obsoleto su fdformat e formattazione a basso livello
%%
\ifx\obsoletesection\undefined

\relax
\else
Si tenga presente che questa è una operazione diversa dalla formattazione
\textsl{fisica} del dispositivo che divide lo spazio sul disco in tracce e
settori, come quella che di solito si fa sui dischetti. In genere per i dischi
questa operazione non è più necessaria dato che viene eseguita direttamente
dal fabbricante una volta per tutte.  Si deve invece eseguirla per i floppy,
con il comando \index{comando!\texttt{fdformat}} \texttt{fdformat}, ma questo
non comporta che poi si possa utilizzarlo, occorrerà anche creare il
filesystem. Con Linux infatti la formattazione fisica del dispositivo e la
creazione del filesystem, che sono delle operazioni distinte, vengono sempre
tenute separate, nonostante alcuni sistemi operativi le eseguano insieme.
%%
%% ### OBSOLETE END ###
%% Materiale obsoleto su fdformat e formattazione a basso livello
%%
\fi

La creazione di un filesystem su un dispositivo si esegue con il comando
\index{comando!\texttt{mkfs}} \texttt{mkfs}, questo prende come unico
argomento il file di dispositivo su cui si vuole creare il filesystem, mentre
il tipo di filesystem che si vuole creare si specifica con l'opzione
\texttt{-t}. Fa eccezione il caso di \textit{btrfs} che consente di
specificare più dispositivi (come vedremo più avanti questo filesystem ha
caratteristiche più evolute rispetto a quelli tradizionali).

In realtà \texttt{mkfs} è solo un comando generico, che chiama per ciascun
tipo di filesystem, indicato con l'opzione \texttt{-t} nella forma \texttt{-t
  \textsl{type}} dove \texttt{\textsl{type}} è uno dei valori di
tab.\ref{tab:file_filesystem_types}, uno specifico sotto-comando
\texttt{mkfs.\textsl{type}}. Così ad esempio se si vuole creare un filesystem
FAT per Windows, usando \texttt{mkfs -t vfat}, verrà invocato il comando
\index{comando!\texttt{mkfs.vfat}} \texttt{mkfs.vfat}.

In generale i programmi di creazione sono forniti insieme agli altri programmi
di supporto per il filesystem, come quelli per il controllo di consistenza o
il ridimensionamento, e possono avere un loro nome specifico: ad esempio per
\textit{ReiserFS} il programma si chiama \index{comando!\texttt{mkreiserfs}}
\texttt{mkreiserfs} mentre quello per
\textit{ext2}/\textit{ext3}/\textit{ext4} è \texttt{mke2fs}, e possono anche
essere invocati direttamente. Perché la forma generica \texttt{mkfs -t
  \textsl{type}} funzioni però deve essere presente il corrispondente comando
\texttt{mkfs.\textsl{type}}, cosa che nel caso di filesystem come XFS e
\textit{btrfs} è comunque automaticamente vero, dato che i relativi comandi
nativi di formattazione sono proprio \texttt{mkfs.xfs} e \texttt{mkfs.btrfs}.

Tutte le altre opzioni da passare ad \texttt{mkfs} dipendono dal filesystem
scelto, e possono essere trovate nella pagina di manuale del relativo comando
specifico, accessibile al solito con \texttt{man mkfs.\textsl{type}}. Un
elenco delle principali opzioni disponibili per i principali filesystem usati
su Linux è riportato in tab.~\ref{tab:file_mkfs_options}.

Nella ``\textsl{formattazione}'' di un nuovo disco la prima scelta da fare è
quella del tipo di filesystem che si vuole usare, cosa che dipende
principalmente dall'utilizzo che se ne farà. Ad esempio se si vuole formattare
una chiavetta USB, la scelta più comune è l'uso di un filesystem VFAT per
garantire la leggibilità dello stesso anche da Windows, visto che l'uso più
comune di queste chiavette è proprio quello per lo scambio di dati.

Se però il disco deve contenere dei dati del sistema gestiti con Linux questa
scelta non è adatta, non disponendo quel filesystem del supporto necessario
per utenti e permessi. In tal caso le considerazioni che si devono fare
attengono principalmente alle prestazioni ed alle funzionalità, ma soprattutto
alla stabilità ed affidabilità del filesystem, che è il requisito fondamentale
dato che scopo principale di un filesystem è quello di mantenere i dati. Per
questo motivo ogni distribuzione sceglie quello che ritiene essere il
``migliore'' come filesystem di default.

Benché oggi esistano molteplici alternative con diverse caratteristiche, il
filesystem più usato su Linux è \textit{ext4}, evoluzione del primo filesystem
nativo, di cui comunque resta ancora piuttosto utilizzata anche la versione
precedente \textit{ext3} ed in misura minore anche la originaria
\textit{ext2}. Tutte queste versioni usano una strutturazione dei dati su
disco analoga, per cui alla fine i vari programmi di manutenzione sono gli
stessi e mantengono i nomi originari nati con \textit{ext2}. Per questo
motivo, e per la maggior diffusione, li tratteremo in maniera più estesa
rispetto agli altri filesystem. Il primo di questi comandi è quello di
creazione, \index{comando!\texttt{mke2fs}} \texttt{mke2fs}, un cui esempio è:
\begin{Console}
anarres:/home/piccardi# \textbf{mke2fs /dev/sdd1}
mke2fs 1.42.2 (9-Apr-2012)
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
Stride=0 blocks, Stripe width=0 blocks
65024 inodes, 259680 blocks
12984 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=67371008
32 block groups
8192 blocks per group, 8192 fragments per group
2032 inodes per group
Superblock backups stored on blocks: 
	8193, 24577, 40961, 57345, 73729, 204801, 221185

Allocating group tables: done                            
Writing inode tables: done                            
Writing superblocks and filesystem accounting information: done 
\end{Console}

Se usato senza specificare altro che il dispositivo da formattare,
\texttt{mke2fs} si limita a creare il filesystem, stampando tutta una serie di
informazioni ad esso relative.  È particolarmente significativa quella
relativa a dove sono stati posti i vari backup del
\textit{superblock}.\footnote{la spiegazione dettagliata del significato dei
  vari parametri, come quelli relativi a \textit{group blocks} e
  \textit{fragments}, va al di là dello scopo di questo testo, ma in breve si
  può dire che un filesystem \textit{ext2} divide lo spazio disco in blocchi
  raggruppati nei \textit{group blocks}, che contengono al loro interno le
  tabelle degli \textit{inode} e lo spazio per i blocchi di dati e le
  informazioni per evitare la frammentazione dello spazio disco; per una
  spiegazione più completa si può leggere il file \texttt{filesystem/ext2.txt}
  distribuito nella documentazione allegata ai sorgenti del kernel.} Questo è
un blocco speciale che contiene tutte le informazioni relative alla
configurazione del filesystem, ed è essenziale per poterlo montare.  La
perdita del \textit{superblock} causerebbe la perdita completa del filesystem
per cui ne vengono mantenute varie copie in modo che in caso di distruzione o
corruzione si possa usare una delle copie. Pertanto è bene annotarsi la
posizione delle varie copie, anche se è possibile recuperarla in un secondo
momento con \texttt{dumpe2fs}.

Benché normalmente il comando richieda come argomento un file di dispositivo,
volendo si può anche usare un file normale per crearvi un filesystem che potrà
poi essere montato in \textit{loopback}. In tal caso però il comando,
accorgendosi di non avere a che fare con un disco (anzi per essere precisi con
un dispositivo a blocchi), chiede esplicitamente se proseguire o meno.

\index{inode|(}

Al di là della invocazione semplice appena mostrata il comando prevede
numerose opzioni che permettono di impostare tutta una serie di
caratteristiche del filesystem che si va a creare.  Una delle principali è la
dimensione dei \textsl{blocchi} in cui lo spazio disco viene suddiviso, da
specificare tramite l'opzione \texttt{-b}.  Con \textsl{blocco} si indica in
genere l'unità minima di spazio disco che viene allocata per inserirvi i dati
di un file; in genere, anche se per alcuni filesystem più evoluti esistono dei
meccanismi automatici che permettono di mettere il contenuto di diversi file
di piccole dimensioni in un solo blocco, ogni file consuma almeno un blocco, e
le dimensioni dei file sono dei multipli interi di questo valore.  Valori
tipici sono 1024, 2048 o 4096.

Qualora si ometta questo parametro il suo valore viene stabilito con una
valutazione euristica sulla base della dimensione del disco e del tipo di uso
che si vuole fare del filesystem. Questo può essere indicato tramite l'opzione
\texttt{-T}, che prende i tre valori \texttt{news} (un \textit{inode} ogni
4kb), \texttt{largefile} (un \textit{inode} ogni 1Mb) e \texttt{largefile4}
(un \textit{inode} ogni 4Mb) per assegnare un diverso rapporto fra numero di
\textit{inode} e spazio disco disponibile.  Qualora si usi un valore negativo
questo viene preso come limite inferiore per la dimensione di un blocco.

Un altro parametro importante è quello del numero di \textit{inode} da creare,
si ricordi infatti che, come illustrato in
sez.~\ref{sec:struct_filesystem_arch}, ogni file è sempre associato ad un
\textit{inode}.  Questi di norma vengono mantenuti in una sezione apposita del
filesystem, le cui dimensioni, nel caso di
\textit{ext2}/\textit{ext3}/\textit{ext4} vengono determinate in sede di
creazione e non possono più essere modificate in un secondo tempo a meno di
non espandere le dimensioni del filesystem.

Il comando permette, con l'uso dell'opzione \texttt{-i} di impostare ogni
quanti byte di spazio disco deve essere creato un \textit{inode}. Si deve dare
cioè la valutazione della dimensione media di un file sul disco: specificare
un valore troppo alto creerà pochi \textit{inode}, con il rischio di
esaurirli, un valore troppo basso ne creerà troppi, con conseguente spreco di
risorse e soprattutto un maggior lavoro per le operazioni sugli stessi, che
dovranno essere eseguite su intervalli più ampi.

Si tenga presente che per la gestione dei file in un filesystem blocchi e
\textit{inode} sono due risorse indipendenti, si possono cioè esaurire sia i
blocchi liberi che gli \textit{inode} disponibili, anche se il primo caso è di
gran lunga quello più comune, e trovarsi così nella condizione di non poter
più creare nuovi file.  Per questo motivo per una gestione ottimale del disco
di solito occorre una scelta opportuna sia delle dimensioni dei blocchi che
del rapporto fra blocchi disponibili e \textit{inode}. Tenere le dimensioni
dei blocchi basse riduce lo spreco di spazio per quelli occupati parzialmente,
ma implica un maggiore lavoro per la gestione (e maggiore spazio per le
informazioni relative). Usare pochi \textit{inode} permette di risparmiare
spazio ed essere più veloci nella ricerca, ma si corre il rischio di finirli
prima di esaurire lo spazio disco.

\index{inode|)}


\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Parametro} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{dir\_index}   & usa una struttura ad alberi ed hash per la
                            gestione del contenuto delle directory.\\
    \texttt{extent}       & usa una diversa e più efficiente modalità di
                            allocazione dei dati, disponibile solo per
                            \textit{ext4}.\\
    \texttt{filetype}     & memorizza il tipo di file nelle voci delle
                            directory. \\
    \texttt{has\_journal} & crea anche il file per il giornale (equivalente
                            all'uso di \texttt{-j}).\\
    \texttt{journal\_dev} & richiede che sul dispositivo indicato sia creato un
                            giornale invece di un filesystem.\\
    \texttt{large\_files} & il filesystem può contenere file di dimensione
                            superiore a 2Gb (attivato automaticamente nei
                            kernel recenti alla creazione di un tale file).\\
    \texttt{resize\_inode}& riserva dello spazio per consentire un successivo
                            allargamento del filesystem con
                            \texttt{resize2fs} (vedi
                            sez.~\ref{sec:filesystem_resize}).\\
    \texttt{sparse\_super}& crea un filesystem con meno copie del
                            \textit{superblock} per non sprecare spazio sui
                            filesystem molto grandi.\\
    % \texttt{flex\_bg}     & . \\
    % \texttt{uninit\_bg}   & . \\
                            
    \hline
  \end{tabular}
  \caption{Principali parametri per l'attivazione delle funzionalità dei
    filesystem \textit{ext2}/\textit{ext3}/\textit{ext4} attivabili mediante
    l'opzione \texttt{-O} di \texttt{mke2fs}.} 
  \label{tab:ext2_options}
\end{table}

Dato che la struttura di base è sempre la stessa, quello che contraddistingue
le varie versioni della famiglia di filesystem \textit{extN} sono le
funzionalità che vengono abilitate. Queste possono essere impostate
singolarmente in fase di creazione attraverso l'opzione \texttt{-O}, che
prende una lista di parametri, separata da virgole se sono più di uno, che
specificano le funzionalità da abilitare. Se si fa precedere un parametro da
un accento circonflesso ``\texttt{\circonf}'' si richiede invece la
disabilitazione della relativa funzionalità, inoltre l'uso del valore speciale
\texttt{none} permette di disabilitare tutte le caratteristiche aggiuntive.

I valori possibili per i parametri di \texttt{-O} sono illustrati in
tab.~\ref{tab:ext2_options}, ed in realtà quello che contraddistingue le
differenze fra le varie versioni è proprio quali di queste funzionalità
vengono abilitate, le più avanzate delle quali sono disponibili solo su
\textit{ext4}. Nelle vecchie versioni del comando di default venivano attivate
solo le due caratteristiche \texttt{sparse\_super} e \texttt{filetype}, che
comunque non sono compatibili con le implementazioni di \textit{ext2}
antecedenti i kernel della serie 2.2.x. Oggi il default è controllato dalla
voce \texttt{base\_features} del file
\index{configurazione!\texttt{/etc/mke2fs.conf}} \texttt{/etc/mke2fs.conf},
per la cui sintassi si rimanda alla pagina di manuale. Queste in genere sono
solo le funzionalità più elementari per cui se si usa semplicemente
\texttt{mke2fs} il filesystem viene formattato come \textit{ext2}.

Nel caso si voglia creare un filesystem di tipo \textit{ext3}, si deve
utilizzare l'opzione \texttt{-j} o invocare il comando come
\texttt{mkfs.ext3}, in tal caso vengono attivate anche le ulteriori
funzionalità riportate nella configurazione \texttt{/etc/mke2fs.conf} che
prevede la possibilità di indicare queste (e quelle relative ad \textit{ext4})
all'interno di altrettante direttive di configurazione specifiche. In questo
caso la funzionalità aggiuntiva in questione è \texttt{has\_journal}, che
permette di creare un file apposito per il giornale (affronteremo il tema dei
filesystem che supportano il \textit{journaling} in
sez.~\ref{sec:filesystem_check}).

Quando con \texttt{mke2fs} si attiva il giornale, indipendentemente dalle
modalità utilizzate, si può poi utilizzare l'ulteriore opzione \texttt{-J} che
permette di specificarne le caratteristiche. Se questa non viene utilizzata
sono utilizzati i valori di default, altrimenti questi possono essere
specificati nella forma \texttt{parametro=valore}. Un elenco dei parametri
specificabili con \texttt{-J} è illustrato in
tab.~\ref{tab:e2fs_journal_options}, con relativa spiegazione.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Parametro} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{device}  & permette di impostare un dispositivo esterno per
                       mantenere il giornale. Al posto di un file di
                       dispositivo si può specificare una l'etichetta
                       associata al filesystem  (con l'opzione
                       \texttt{-L}). Il dispositivo che fa da 
                       giornale deve essere inizializzato con
                       \texttt{mke2fs -O journal\_dev}.\\ 
    \texttt{size}    & specifica la dimensione del giornale, da specificare in
                       megabyte. Deve essere un minimo di 1024 blocchi, e non
                       può superare 102400 blocchi.\\
    \hline
  \end{tabular}
  \caption{Parametri per la gestione del giornale di un filesystem
    \textit{ext3} specificabili tramite l'opzione \texttt{-J} di
    \texttt{mke2fs}.} 
  \label{tab:e2fs_journal_options}
\end{table}

Qualora si voglia creare un filesystem \textit{ext4}, che ha ulteriori
funzionalità avanzate, come l'uso dei cosiddetti \textit{extent} che consente
una allocazione più efficiente e veloce dei dati, ed opzioni di gestione dei
metadati che consentono controllo e successiva riparazione del filesystem in
caso di problemi molto più veloce (vedi sez.~\ref{sec:filesystem_check})
occorre invece usare il comando come \texttt{mkfs.ext4}.

%%
%% ### OBSOLETE BEGIN ###
%% Materiale obsoleto per dettagli badblocks, di scarso interesse oggi
%%
\ifx\obsoletesection\undefined

\relax
\else
Infine un problema che si può avere nella gestione dei dischi è quello dei
settori difettosi. È comunque possibile creare il filesystem in modo da non
utilizzare i blocchi contenenti settori difettosi, tramite l'opzione
\texttt{-c} che prima della creazione del filesystem esegue un controllo per
verificarne la presenza ed escluderli dall'uso qualora rilevati. Se l'opzione
viene specificata due volte il controllo viene eseguito in maniera più
approfondita, ed estremamente lenta, scrivendo e rileggendo tutto il
disco. Specificando l'opzione \texttt{-l} invece di eseguire il controllo si
indica l'uso di una lista di blocchi difettosi letta da un file.

Di norma questa lista può essere prodotta in maniera indipendente dal
programma \index{comando!\texttt{badblocks}} \texttt{badblocks}, che è quello
che viene eseguito anche quando si usa l'opzione \texttt{-c} per effettuare il
controllo, ma non entreremo in ulteriori dettagli dato che questa pratica è
comunque assolutamente sconsigliabile, dato che in genere il verificarsi di
errori di questo tipo indica che il disco si sta degradando ed è prossimo ad
una rottura definitiva per cui è bene provvedere ad un backup ed alla sua
sostituzione.  Le altre opzioni principali di \texttt{mke2fs} sono riportate
nella lista di tab.~\ref{tab:file_mkfs_options} e per un elenco completo si
faccia al solito riferimento alla pagina di manuale.

Se lo si usa indipendentemente da \texttt{mke2fs} anche \texttt{badblocks}
vuole come argomento il file di dispositivo da esaminare, ed opzionalmente il
blocco di partenza e quello finale del controllo. Si deve aver cura di
specificare con l'opzione \texttt{-b} la dimensione dei blocchi, che dovrà
ovviamente coincidere con quella usata con \texttt{mke2fs}, per cui in genere
è sempre meglio non usare direttamente il programma, ma invocarlo tramite
\texttt{mke2fs} o \texttt{e2fsck}.

L'opzione \texttt{-c} permette di selezionare quanti blocchi vengono
controllati alla volta (il default è 16); aumentandolo si accresce la velocità
di esecuzione del comando ma anche il suo consumo di memoria. Con l'opzione
\texttt{-i} si indica un file contenente una lista nota di blocchi danneggiati
(quella presente nel filesystem è ottenibile con \texttt{dumpe2fs}), mentre
con \texttt{-o} si indica un file su scrivere i risultati.

Infine ci sono una serie di opzioni per indicare il tipo di test da eseguire,
normalmente viene eseguita una lettura dei blocchi per verificare errori, se
non ce ne sono si prosegue. Con \texttt{-p} che può specificare quante volte
ripetere la scansione di un blocco prima di decidere che non ci sono errori.
Con \texttt{-w} si richiede di eseguire il controllo scrivendo dei dati e poi
rileggendoli per verificarne l'integrità; il metodo è molto più preciso, ma
anche molto più lento, inoltre in questo modo il controllo è distruttivo in
quanto sovrascrive i dati, pertanto non può essere usato su un filesystem
montato.  Si può eseguire questo stesso tipo di test in modalità non
distruttiva con l'opzione \texttt{-n}, nel qual caso però il controllo diventa
\textsl{estremamente} lento.  Per le rimanenti opzioni del comando si può al
solito fare riferimento alla pagina di manuale.

%%
%% ### OBSOLETE END ###
%% Materiale obsoleto per dettagli badblocks, di scarso interesse oggi
%%
\fi

Una volta creato il filesystem si possono modificarne alcune caratteristiche
in un secondo tempo con l'uso del comando \index{comando!\texttt{tune2fs}}
\texttt{tune2fs}. L'uso più comune di \texttt{tune2fs} è probabilmente quello
per trasformare un filesystem \textit{ext2} in un filesystem \textit{ext3}
creando il giornale. Questo è ottenibile immediatamente con l'opzione
\texttt{-j}, e si può usare \texttt{-J} con le stesse opzioni di
tab.~\ref{tab:e2fs_journal_options} per indicare le caratteristiche del
giornale.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-C \textsl{N}}   & modifica il contatore del numero di volte che
                               un filesystem è stato montato.\\
    \texttt{-c \textsl{N}}   & imposta il numero di volte che un filesystem
                               può essere rimontato prima di subire un
                               controllo.\\
    \texttt{-e \textsl{val}} & modifica il comportamento del kernel quando
                               viene rilevato un errore sul filesystem, prende
                               come parametro uno dei valori:
                               \texttt{continue} (continua ignorando
                               l'errore), \texttt{remount-ro} (rimonta il
                               filesystem in sola lettura), \texttt{panic} (si
                               ferma causando un \textit{kernel panic}).\\
    \texttt{-g \textsl{grp}} & imposta il gruppo che può usare i blocchi
                               riservati.\\ 
    \texttt{-i \textsl{time}}& imposta l'intervallo di tempo fra due controlli
                               successivi; prende come parametro un numero di
                               giorni, di settimane se si pospone il carattere
                               ``\texttt{w}'', di mesi se si pospone il
                               carattere ``\texttt{m}''.\\ 
    \texttt{-j}              & aggiunge un giornale per il filesystem.\\
    \texttt{-J \textsl{val}} & sovrascrive i parametri del giornale, prende
                               come parametro uno dei valori di
                               tab.~\ref{tab:e2fs_journal_options}.\\
    \texttt{-L \textsl{labl}}& imposta il nome del volume, per un massimo di
                               16 caratteri.\\  
    \texttt{-l}              & stampa i contenuti del \textit{superblock} (come
                               se si eseguisse \texttt{dumpe2fs}), vedi
                               sez.~\ref{sec:filesystem_check}).\\
    \texttt{-m \textsl{N}}   & imposta la percentuale di blocchi riservati.\\
    \texttt{-O \textsl{val}} & imposta le caratteristiche avanzate del
                               filesystem, prende come parametri uno dei
                               valori di tab.~\ref{tab:ext2_options}.\\ 
    \texttt{-r \textsl{N}}   & imposta il numero di blocchi riservati.\\
    \texttt{-T \textsl{time}}& modifica il valore del tempo in cui il
                               filesystem è stato verificato per l'ultima
                               volta; prende come parametro l'indicazione
                               della data nel formato usato da \texttt{date} o
                               \texttt{now} per indicare il tempo corrente.\\
    \texttt{-U \textsl{uuid}}& imposta l'UUID del filesystem.\\ 
    \texttt{-u \textsl{user}}& imposta l'utente che può usare i blocchi
                               riservati.\\ 
    \hline
  \end{tabular}
  \caption{Principali opzioni per il comando \texttt{tune2fs}.} 
  \label{tab:tune2fs_options}
\end{table}

Un'altra opzione di uso comune è \texttt{-c} che permette di impostare il
numero di volte che il filesystem può essere montato senza che venga forzato
un controllo di consistenza con \texttt{fsck}, analoga a questa è \texttt{-i}
che specifica l'intervallo massimo, in giorni, mesi o settimane, fra due
controlli. Con \texttt{-C} si può anche modificare a mano il contatore del
numero di volte che un filesystem è stato montato, in modo da poter forzare il
controllo ad un successivo riavvio. 

Con l'opzione \texttt{-O} si possono modificare in un secondo tempo le
caratteristiche avanzate specificando come parametro una lista dei valori già
illustrati in tab.~\ref{tab:ext2_options}, in questo caso per disabilitare una
funzionalità si può apporre un carattere ``\verb|^|'' al corrispondente
parametro. Si tenga presente che se si modificano o abilitano alcune
funzionalità (questo avviene se ad esempio si attivano quelle per
\textit{ext4}) per poterle davvero utilizzare quasi sempre è necessario
eseguire preventivamente una riparazione/ricostruzione del filesystem con
\texttt{e2fsck}.

Infine si può usare l'opzione \texttt{-L} per impostare una etichetta sul
filesystem, che viene a costituire il nome del volume.  Analogamente si può
modificare il valore dell'UUID associato al filesystem con l'opzione
\texttt{-U}, cui deve essere passato come parametro il nuovo valore.  Diventa
così possibile, come visto in sez.~\ref{sec:file_disk_management}, fare
riferimento al filesystem in \texttt{/etc/fstab} usando l'etichetta o l'UUID
al posto del file di dispositivo.  Le altre opzioni principali sono illustrate
in tab.~\ref{tab:tune2fs_options}, al solito si può ottenere l'elenco completo
ed una descrizione dettagliata dalla pagina di manuale del comando.

Per quanto riguarda le possibili alternative a \textit{ext4}, ad oggi
\textit{ReiserFS}, che è stato il primo a disporre del \textit{journaling} e
che per questo ottenne una buona adozione, è ormai in sostanziale disuso: lo
sviluppo infatti è fermo alla versione 3 per la sola correzione degli errori,
la successiva versione 4 infatti è stata rifiutata dagli sviluppatori del
kernel e praticamente non viene più sviluppata.

%%
%% ### OBSOLETE BEGIN ###
%% Materiale obsoleto per dettagli badblocks, di scarso interesse oggi
%%
\ifx\obsoletesection\undefined

\relax \else 

Benché possa essere ancora presente in macchine molto vecchie, oggi non esiste
nessun motivo valido, a parte la curiosità, per creare un filesystem
\textit{ReiserFS}. Pertanto a parte citare il comando che esegue questo
compito, \texttt{mkreiserfs}, lasciamo i dettagli riguardo ad opzioni e
comportamento alla lettura della relativa pagina di manuale.

Nel caso si debba intervenire su una vecchia macchina invece può essere utile
conoscere \index{comando!\texttt{reiserfstune}} \texttt{reiserfstune}, analogo
di \texttt{tune2fs}, che consente di modificare i parametri di un filesystem
\textit{ReiserFS}; ad esempio con l'opzione \texttt{-l} si può impostare una
etichetta sul filesystem mentre con \texttt{-u} se ne può modificare l'UUID.
Il comando richiede che si specifichi sempre come argomento il dispositivo su
cui è presente il filesystem; le altre opzioni principali sono riportate in
tab.~\ref{tab:reiserfstune_options}, e per i dettagli si consulti come sempre
la pagina di manuale.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-B} \texttt{\textsl{file}} & imposta lista dei blocchi difettosi
                                         leggendola dal file passato come
                                         parametro.\\ 
    \texttt{-c} \texttt{\textsl{days}} & imposta il numero massimo di giorni
                                         che possono passare dall'ultimo
                                         controllo del filesystem.\\
    \texttt{-l} \texttt{\textsl{labl}}  & imposta l'etichetta passata come
                                         parametro.\\
    \texttt{-m} \texttt{\textsl{N}} & imposta il numero massimo di montaggi
                                         che possono essere effettuati
                                         dall'ultimo controllo del filesystem.\\
    \texttt{-u} \texttt{\textsl{uuid}} & imposta l'UUID passato come
                                         parametro.\\
%    \texttt{} & .\\
    \hline
  \end{tabular}
  \caption{Principali opzioni di \texttt{reiserfstune}.} 
  \label{tab:reiserfstune_options}
\end{table}

%%
%% ### OBSOLETE END ###
%% Materiale obsoleto per dettagli badblocks, di scarso interesse oggi
%%
\fi

Anche lo sviluppo di \textit{ext4} è sostanzialmente terminato in termine di
nuove funzionalità, in quanto il nuovo filesystem nativo di Linux dovrebbe
essere \textit{btrfs}, che presenta una serie di funzionalità avanzate, come
la possibilità di essere suddiviso su un numero arbitrario di dispositivi
(rendendo superfluo LVM), il supporto nativo a replicazioni di tipo RAID (vedi
sez.~\ref{sec:RAID_intro}), la possibilità di creare \textit{snapshot} e
sotto-volumi da montare come filesystem separati, e molto altro. Il problema
però è che al momento non è ancora considerato sufficientemente stabile e
nessuna distribuzione lo ha adottato come default.

Per questo motivo la sola alternativa a \textit{ext4} che fornisca tutte le
garanzie di stabilità e affidabilità necessarie è \textit{XFS}, che presenta
anche altri vantaggi, ed il cui sviluppo prosegue sia in termini di
miglioramento di prestazioni che di aggiunta di nuove funzionalità. La sua
diffusione sta crescendo anche in ragione del fatto e che è stato adottato
come default da varie distribuzioni (in particolare da RedHat con versione 7
della sua ``\textit{Enterprise Linux}'').

A parte quelli in termini di prestazioni, che pur nominalmente migliori
(specie per file di grandi dimensioni) sono spesso ambigui perché dipendono
dal tipo di utilizzo del filesystem,\footnote{un punto debole del filesystem
  era la velocità di scrittura per i metadati degli \textit{inode}, ma a
  partire dal kernel 3.2 il problema è stato risolto e le prestazioni secondo
  gli sviluppatori sono anche superiori a quelle dei concorrenti.} il
principale vantaggio di XFS rispetto ad \textit{ext4} è che non esiste più la
rigida suddivisione fra spazio per gli \textit{inode} e spazio per i blocchi
per cui una allocazione iniziale può essere modificata in un tempo
successivo. Inoltre il filesystem è in grado di auto-ripararsi a caldo e non
prevede, tranne casi gravi ed evidenti di corruzione, la necessità di un
controllo periodico all'avvio.  Insieme ai vantaggi il filesystem presenta
anche qualche svantaggio, come il fatto che può essere ridimensionato solo in
accrescimento.

Come accennato il comando di creazione di un filesystem XFS è
\index{comando!\texttt{mkfs.xfs}} \texttt{mkfs.xfs}. Senza opzioni, a meno che
non rilevi la presenza di un altro filesystem, nel qual caso è necessario
applicare l'opzione \texttt{-f}, il comando si limita alla creazione del
filesystem sul dispositivo indicato come argomento, applicando una serie di
default per le varie caratteristiche dello stesso, che poi stampa a video con
qualcosa del tipo:
\begin{Console}
root@monk:~# \textbf{mkfs.xfs /dev/sdb1} 
meta-data=/dev/sdb1              isize=256    agcount=4, agsize=15262348 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=0        finobt=0
data     =                       bsize=4096   blocks=61049389, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=0
log      =internal log           bsize=4096   blocks=29809, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
\end{Console}

Il comando riporta i valori dei parametri usati per le varie caratteristiche
di gestione del filesystem, elencando in successione quelli per i metadati
generali usati dal filesystem (sezione \texttt{\textsl{meta-data}}), quelli
per i dati dei file (sezione \texttt{\textsl{data}}), quelli per i contenuti e
l'indicizzazione delle directory (sezione \texttt{\textsl{naming}}), quelli
per il sistema del \textit{journaling} (sezione \texttt{\textsl{log}}) e
quelli della gestione dell'I/O in \textit{realtime}\footnote{la versione
  originaria di IRIX, in presenza di hardware specializzato, consentiva di
  fornire un rate di I/O garantito ai programmi \textit{realtime} che ne
  avevano bisogno, questa garanzia non è disponibile su Linux, che comunque
  non è un sistema operativo \textit{realtime}.}  (sezione
\texttt{\textsl{realtime}}).

Queste caratteristiche possono essere modificate in fase di creazione del
filesystem usando rispettivamente le opzioni \texttt{-m}, \texttt{-d},
\texttt{-n}, \texttt{-l} e \texttt{-r} del comando, cui si aggiunge
\texttt{-i} per impostare le caratteristiche degli \textit{inode}. Tutte
queste opzioni richiedono che si passi un argomento con l'indicazione di
parametri e relativi valori come lista di assegnazioni nella forma
\texttt{\textsl{chiave=valore}} separate da virgole; alternativamente si può
ripetere più volte l'uso di una opzione per impostare parametri diversi.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Chiave} & \textbf{Significato} \\
    \hline
    \hline
    % \multicolumn{2}{|c|}{Caratteristiche per i meta-dati (opzione \texttt{-m})}\\
    % \hline
    % \texttt{}   & .\\
    % \hline
    \multicolumn{2}{|c|}{Caratteristiche per gli \textit{inode} (opzione \texttt{-i})}\\
    \hline
    \texttt{maxpct}  & indica la percentuale massima di spazio del
                       filesystem che può essere allocata per gli
                       \textit{inode}, il default è il 25\% per i filesystem
                       sotto un terabyte e decresce al 5\% per quelli fino a
                       50 terabyte e all'1\% sopra.\\
    \hline
    \multicolumn{2}{|c|}{Caratteristiche per i dati (opzione \texttt{-d})}\\
    \hline
    \texttt{file}   & indica se il filesystem deve essere creato su un file
                      ordinario (valore 1) o no (valore 0), se non specificato
                      si assume 0, se specificato senza assegnazione si
                      intende 1 e questo è necessario per creare l'immagine di
                      un filesystem XFS su un file.\\
    \texttt{name}   & nel caso si sia richiesta la creazione del filesystem su
                      un file ordinario, indica il nome dello stesso; quando
                      si è usata questa opzione il giornale deve essere
                      necessariamente interno.\\
    \texttt{size}   & indica le dimensioni della sezione dati del filesystem,
                      la si usa quando si vuol creare un'immagine su un file
                      ordinario, per indicarne le dimensioni, o se si vuole
                      lasciare dello spazio libero in coda ad un dispositivo.\\
    \hline
    \multicolumn{2}{|c|}{Caratteristiche del \textit{journaling} (opzione \texttt{-l})}\\
    \hline
    \texttt{logdev}   & imposta il dispositivo su cui mantenere il giornale
                        del filesystem, richiede che si indichi il relativo
                        file di dispositivo.\\
    \texttt{size}     & imposta la dimensione del giornale, richiede un valore
                        numerico.\\
    \texttt{internal} & prende i valori 0 e 1, e quest'ultimo, il default, indica che il
                        giornale viene gestito insieme ai dati; se specificato
                        esplicitamente è incompatibile con l'uso di \texttt{logdev}.\\
    \hline
  \end{tabular}
  \caption{Principali caratteristiche del filesystem impostabili con \texttt{mkfs.xfs}.} 
  \label{tab:mkfs.xfs_options_keys}
\end{table}

In genere se non ci sono necessità specifiche, non si ha ragione per
modificare i default, ma se ad esempio si vuole indicare una specifica
dimensione per il giornale, occorrerà usare l'opzione \texttt{-l} ed usare la
parola chiave \texttt{size} per dichiararla. I valori dei parametri dipendono
ovviamente dalla caratteristica che si vuole impostare, ma sono per lo più
numerici e quando indicano delle dimensioni relative a spazio disco supportano
i suffissi \texttt{s}, \texttt{b}, \texttt{k}, \texttt{m}, \texttt{g},
\texttt{t} (e via a salire) per indicare rispettivamente numero di settori,
byte, kilobyte, megabyte, gigabyte, terabyte, ecc. Si sono riportati quelli
più rilevanti in tab.\ref{tab:mkfs.xfs_options_keys}, per i dettagli si
rimanda alla pagina di manuale accessibile con \texttt{man mkfs.xfs}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-f} & da usare quando il filesystem è contenuto in un file e non
                  in un dispositivo.\\
    \texttt{-l} & stampa l'etichetta associata al filesystem.\\
    \texttt{-L \textsl{labl}} & imposta l'etichetta associata al filesystem.\\
    \texttt{-u} & stampa l'UUID associato al filesystem.\\
    \texttt{-U \textsl{uuid}} & imposta l'UUID associato al filesystem.\\
%    \texttt{} & .\\
    \hline
  \end{tabular}
  \caption{Principali opzioni di \texttt{xfs\_admin}.} 
  \label{tab:xfs_admin_options}
\end{table}

Una volta creato il filesystem si possono modificare alcune delle sue
proprietà con il comando \index{comando!\texttt{xfs\_admin}}
\texttt{xfs\_admin}, che è l'analogo di \texttt{tune2fs}, ma a differenza di
quest'ultimo richiede che il filesystem sia smontato se deve scriverci. Il
programma, che richiede come argomento il dispositivo su cui è mantenuto il
filesystem, consente sia di leggere che di impostare l'etichetta e l'UUID del
filesystem.\footnote{a differenza di \textit{ext4}, XFS considera l'UUID del
  filesystem una proprietà intrinseca dello stesso, e si rifiuta di montare un
  filesystem se un altro con lo stesso UUID è già montato, per questo motivo
  non è possibile modificarlo a filesystem montato.}  Buona parte delle altre
caratteristiche del filesystem possono essere modificate a caldo con
\texttt{xfs\_growfs}, che tratteremo in sez.~\ref{sec:filesystem_resize}. In
tab.~\ref{tab:xfs_admin_options} si sono riportate le principali opzioni di
\texttt{xfs\_admin}, per i dettagli e l'elenco completo si rimanda alla pagina
di manuale.


\subsection{Controllo e riparazione di un filesystem}
\label{sec:filesystem_check}

In generale il funzionamento dei filesystem in Linux è estremamente stabile,
ed una volta creati è praticamente impossibile danneggiarli nel corso delle
normali operazioni, a meno di non usare versioni sperimentali del kernel (ma
in questo caso si stanno cercando rogne, ed è possibile trovarle). Se però si
ha un black-out improvviso, qualcuno inciampa nel cavo di alimentazione del
vostro PC, o un addetto alle pulizie spegne il quadro elettrico, è normale che
il filesystem, dal momento in cui l'aggiornamento dei dati su disco è stato
interrotto brutalmente, si possa trovare in uno stato incoerente.

In questo caso si può avere un danneggiamento della struttura del filesystem,
che deve essere riparato. In genere ogni filesystem prevede l'esistenza di un
flag su disco, attivato quando viene montato, che indica che è in uso, e che
viene azzerato solo quando il filesystem viene smontato, nel qual caso si è
certi che tutte le operazioni sospese sono state completate e che lo stato è
coerente.  Se c'è stata un'interruzione della corrente, o un qualunque altro
problema che ha comportato un riavvio non pulito, questo flag resterà attivo
ed il sistema potrà rilevare, al successivo tentativo di montaggio, che
qualcosa è andato storto.

Quello che può succedere in questi casi dipende dal tipo di filesystem. Coi
filesystem tradizionali \texttt{mount} rileva l'errore e non monta il
filesystem o lo monta in sola lettura (a seconda delle opzioni scelte). A
questo punto occorre usare l'opportuno programma di controllo per verificare
lo stato del filesystem ed eventualmente riparare gli errori. Di norma, in
caso di rilevamento di un errore durante la procedura di avvio del sistema,
questo viene lanciato automaticamente secondo quanto specificato in
\texttt{/etc/fstab} (vedi sez.~\ref{sec:file_disk_management}).

Il programma generico per il controllo di un filesystem è
\index{comando!\texttt{fsck}} \texttt{fsck} (da \textit{\textbf{f}ile
  \textbf{s}ystem \textbf{c}hec\textbf{k}}) che come \texttt{mkfs} non è altro
che un front-end per i singoli programmi specifici di ciascun tipo di
filesystem. Questi vengono attivati attraverso l'opzione \texttt{-t} seguita
dal tipo del filesystem (quello di tab.\ref{tab:file_filesystem_types}). Il
programma prende come argomenti un elenco di filesystem da controllare
specificati per dispositivo, o anche per \textit{mount point}, se sono citati
in \texttt{/etc/fstab}.  Se si indica più di un filesystem la lista dei
relativi tipi, separata da virgole, deve essere specificata come parametro per
\texttt{-t}.

Quando viene invocato con l'opzione \texttt{-A} (di solito questo viene fatto
nella procedura di avvio) il comando esegue una scansione di
\texttt{/etc/fstab} e cerca di controllare ogni filesystem ivi elencato
(utilizzando il terzo campo per identificarne il tipo), a meno che il sesto
campo del file non sia impostato a zero (si ricordi quanto detto in
sez.~\ref{sec:file_disk_management}). Il comando prima proverà ad eseguire il
controllo per il filesystem della directory radice e passerà poi a tutti gli
altri in ordine di valore crescente del suddetto campo.

Come per \texttt{mkfs} le opzioni disponibili per \texttt{fsck} dipendono
dallo specifico filesystem, a parte quelle generiche relative alla gestione
della sequenza delle scansioni (per cui si rimanda alla pagina di manuale) il
comando passa tutte le opzioni che non riconosce al programma specifico del
filesystem selezionato. Una convenzione vorrebbe che i programmi di controllo
definiscano alcune opzioni generiche, indicando con \texttt{-a} di eseguire le
riparazioni in modo automatico, senza chiedere l'intervento
dell'amministratore, e con \texttt{-r} di eseguire le riparazioni in modalità
interattiva, ma non tutti i programmi che vedremo lo fanno.

Di norma l'esecuzione automatica del controllo prevede che il filesystem sia
riparato senza necessità di intervento da parte dell'utente. Ci sono casi
comunque in cui questo non è possibile, nel qual caso il programma si ferma
per chiedere lumi all'utente. Quando questo avviene durante la procedura di
avvio di norma il sistema viene portato in \textit{single user mode} (si veda
sez.~\ref{sec:struct_sysv_init}) e viene richiesto di rieseguire il programma
manualmente. In tal caso di norma il filesystem non è montato, a meno che il
filesystem danneggiato non sia la radice, nel qual caso esso deve essere
comunque montato, ma in sola lettura. Chiaramente se il filesystem radice è
danneggiato così gravemente da non poter neanche essere montato in sola
lettura, si avrà un \textit{kernel panic}.

\itindbeg{journaling}

La procedura di controllo e riparazione può essere molto lunga e complessa,
specie per filesystem di grandi dimensioni, in quanto prevede una serie di
verifiche dettagliate per identificare informazioni incoerenti e parziali, che
comportano varie scansioni dell'intero contenuto del filesystem stesso. Questo
può significare dei tempi che possono diventare ore o addirittura giorni per i
dischi più grandi. Per ovviare a questo inconveniente alcuni filesystem più
avanzati supportano il cosiddetto \textit{journaling}, un sistema che permette
di riportare il filesystem in uno stato coerente con grande velocità.

Il concetto fondamentale del \textit{journaling} è che le operazioni sul
filesystem vengono prima registrate su un \textsl{giornale}, un file speciale
a questo dedicato, in genere invisibile e mantenuto direttamente dal kernel, e
poi riportate sul filesystem. Così se si ha una interruzione improvvisa si
hanno due casi: se l'interruzione è avvenuta durante l'aggiornamento del
filesystem, il giornale sarà intatto e lo si potrà utilizzare per completare
l'aggiornamento interrotto. Se invece l'interruzione è avvenuta durante la
scrittura nel giornale sarà questo ad essere scartato, si perderanno così le
ultime modifiche, ma il filesystem resterà in uno stato coerente.

In questo modo quando si ha un \textit{filesystem journaled} si può evitare il
lungo procedimento di riparazione. In realtà non è che il procedimento non
avvenga, solo che grazie alla presenza del giornale questo viene eseguito con
grande rapidità, non dovendo effettuare il controllo completo del
filesystem. In generale però, anche se si usa il \textit{journaling}, è
opportuno mantenere un controllo periodico sul filesystem, in quanto errori
sul disco, cavi difettosi o bug del kernel potrebbero comunque aver corrotto
le informazioni.

\itindend{journaling}

Con Linux tutti i filesystem più recenti supportano nativamente il
\textit{journaling}, a parte il vecchio \textit{ext2} che ha ottenuto questa
funzionalità con la successiva versione \textit{ext3}. L'uso di un giornale ha
però un impatto significativo sulle prestazioni del filesystem, e non è detto
che sia sempre utilizzato, tanto che con il successivo \textit{ext4} è stata
prevista la possibilità di disabilitarlo, cosa che continua ad avere senso per
i filesystem che possono essere utilizzati in sola lettura e per quelli per
cui il recupero veloce all'avvio non è essenziale (ad esempio un disco su cui
si effettuano copie di backup).

Nel caso dei filesystem tradizionali della famiglia \textit{extN} l'uso del
giornale si realizza in maniera abbastanza semplice, per \textit{ext2} la
conversione ad \textit{ext3} è immediata, basta aggiungere il giornale al
filesystem con \texttt{tune2fs -j} e rimontarlo come \textit{ext3}. Il
passaggio da \textit{ext3} ad \textit{ext4} è ancora più semplice, basta
rimontare \textit{ext3} come \textit{ext4}, anche se questo abiliterà solo le
funzioni compatibili all'indietro e molte delle funzionalità più avanzate di
\textit{ext4} non saranno disponibili.

Una conversione più completa si può ottenere invece abilitando le funzionalità
avanzate che servono con \texttt{tune2fs} (ad esempio forzando le opzioni
\texttt{extent,uninit\_bg,dir\_index} con \texttt{-O}) ed effettuando appunto
un controllo forzato del filesystem, che provvederà ad effettuare tutte le
modifiche e correzioni necessarie, che in questo caso non dipendono da una
corruzione ma dall'aggiornamento. Questo però comporta che il filesystem sia
smontato cosa che rende le cose più problematiche per la radice, che non può
essere smontata, ma è comunque fattibile operando sul filesystem rimontato in
sola lettura.

Dato che si può sostanzialmente considerare la famiglia dei vari
\textit{ext2}, \textit{ext3} e \textit{ext4} come il filesystem più diffuso su
Linux, tratteremo in maniera più estesa i programmi di gestione specifici di
questa famiglia, che sono comuni a tutte le varie versioni.  Il programma di
controllo e riparazione del filesystem è \index{comando!\texttt{e2fsck}}
\texttt{e2fsck}, che prende come argomento il dispositivo da controllare.

Il comando supporta le opzioni generiche \texttt{-a} e \texttt{-r} illustrate
in precedenza, che sono state mantenute solo per compatibilità, in realtà
\texttt{-a} è deprecata in favore della più recente \texttt{-p} mentre
\texttt{-r} non fa niente dato che il comando viene sempre eseguito in
modalità interattiva. È comunque possibile usare l'opzione \texttt{-y} per far
rispondere ``\textit{yes}'' automaticamente a tutte le domande in modo da
poter eseguire il comando in modalità non interattiva (ad esempio da uno
script), mentre con \texttt{-n} si fa la stessa cosa aprendo il filesystem in
sola lettura\ifx\obsoletesection\undefined .\relax \else , eccetto il caso in
cui si siano specificate le opzioni \texttt{-c}, \texttt{-l} o \texttt{-L} nel
qual caso il filesystem viene aperto in scrittura per aggiornare la lista dei
settori difettosi, e dando una risposta di ``\textit{no}'' a tutte le domande.
\fi

In caso di filesystem pesantemente corrotto, o di cui si è cancellata la parte
iniziale, cosa che può capitare se ad esempio si è sbagliato il dispositivo di
uscita di un \texttt{dd}, si possono poi specificare il \textit{superblock} da
utilizzare con \texttt{-b} e la dimensione di un blocco con \texttt{-B}. Se si
è usato un giornale posto su un altro dispositivo questo deve essere
specificato con l'opzione \texttt{-j}. Quando si è usata l'opzione \texttt{-b}
e il filesystem non è stato aperto in sola lettura \texttt{e2fsck} si cura
anche di ripristinare il superblock al completamento del
controllo. \ifx\obsoletesection\undefined \relax \else

Usando l'opzione \texttt{-c} si può richiedere anche la scansione per il
rilevamento di settori difettosi, e specificandola due volte viene usato il
metodo approfondito di scansione con scrittura e rilettura.  Con l'opzione
\texttt{-l} si può specificare un file con una lista da aggiungere a quella
dei blocchi difettosi, mentre con \texttt{-L} il file indica la nuova lista di
blocchi difettosi. \fi Le altre opzioni principali del comando sono riportate in
tab.~\ref{tab:e2fsck_options}, per un elenco completo e la relativa
documentazione si può al solito fare riferimento alla pagina di manuale del
comando.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-b \textsl{N}}    & specifica un superblocco alternativo.\\
    \texttt{-B \textsl{size}} & specifica le dimensioni di un blocco.\\
    \texttt{-c}   & esegue il controllo del dispositivo per eventuali
                    settori difettosi.\\
    \texttt{-f}   & forza il controllo del filesystem.\\
    \texttt{-j \textsl{file}} & specifica il dispositivo di un giornale esterno.\\ 
    \texttt{-l \textsl{file}} & specifica il file con una lista di blocchi
                                difettosi da aggiungere a quelli già
                                presenti.\\
    \texttt{-L \textsl{file}} & specifica il file con la nuova lista dei
                                blocchi difettosi (sovrascrivendo quella
                                presente).\\
    \texttt{-n}   & esegue il controllo rispondendo automaticamente
                    ``\textit{no}'' a tutte le domande.\\
    \texttt{-t}   & stampa delle statistiche di esecuzione.\\
    \texttt{-y}   & esegue il controllo rispondendo automaticamente
                    ``\textit{yes}'' a tutte le domande.\\
    \hline
  \end{tabular}
  \caption{Principali opzioni per il comando \texttt{e2fsck}.} 
  \label{tab:e2fsck_options}
\end{table}

In genere non c'è necessità di eseguire direttamente \texttt{e2fsck}, in
quanto di norma questo viene eseguito dagli script di avvio. Nel caso lo si
voglia eseguire comunque occorre assicurarsi che il filesystem relativo non
sia montato, o sia montato in sola lettura, ed inoltre specificare l'opzione
\texttt{-f} senza la quale il comando non controlla un filesystem che per lui
risulta pulito.

Nel caso si usi \textit{ReiserFS} il programma che consente di eseguire
controllo e riparazione di un filesystem (quello invocato con
\texttt{fsck.reiserfs}) è \index{comando!\texttt{reiserfsck}}
\texttt{reiserfsck}. Il programma deve essere usato su un filesystem smontato,
anche se alcune opzioni, come \texttt{-{}-check}, possono essere usate su un
filesystem montato in sola lettura. Il comando richiede come argomento
obbligatorio il file di dispositivo contenente il filesystem da
controllare. Le opzioni principali sono riportate in
tab.~\ref{tab:reiserfsck_options}, per i dettagli si consulti al solito la
pagina di manuale.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-{}-check}       & esegue un controllo di consistenza e riporta i
                               risultati, senza eseguire nessuna riparazione.\\
    \texttt{-{}-fix-fixable} & esegue le riparazioni relative a problemi minori 
                               effettuabili senza dover effettuare una
                               ricostruzione completa dell'intero
                               filesystem.\\ 
    \texttt{-{}-rebuild-tree}& ricostruisce l'intero filesystem dai dati
                               presenti sul disco, da usare solo in caso di
                               danni gravi riportati da  \texttt{-{}-check} e
                               previo backup della partizione contenente il
                               filesystem in quanto potenzialmente
                               distruttiva.\\
    \texttt{-a, -p}          & opzioni usate nel controllo automatico
                               all'avvio, causano un controllo dello stato del
                               filesystem e la successiva esecuzione con
                               l'opzione \texttt{-{}-fix-fixable} se vengono
                               riportati danni minori.\\
    \texttt{-B}              & indica il file contenente la lista dei blocchi
                               difettosi.\\ 
    \texttt{-f}              & forza l'esecuzione del comando anche se il
                               filesystem risulta a posto.\\
%    \texttt{} & .\\
    \hline
  \end{tabular}
  \caption{Principali opzioni di \texttt{reiserfsck}.} 
  \label{tab:reiserfsck_options}
\end{table}


Nel caso di XFS il comportamento dei programmi di riparazione e controllo, a
causa delle diverse modalità di funzionamento di questo filesystem, è
piuttosto diverso rispetto ai precedenti. Ad esempio il comando
\index{comando!\texttt{fsck.xfs}} \texttt{fsck.xfs}, pur esistendo per
compatibilità con l'uso di \texttt{fsck}, non fa assolutamente niente ed ha
sempre successo.  Il controllo di consistenza del filesystem infatti non viene
effettuato all'avvio, ma direttamente quando il filesystem viene montato, ed
eventuali riparazioni relative a corruzioni minori vengono eseguite
automaticamente in quell'occasione senza dover utilizzare un comando
specifico.

Qualora si voglia effettuare una verifica manuale è comunque possibile
eseguire direttamente il comando \index{comando!\texttt{xfs\_repair}}
\texttt{xfs\_repair}, che prende come argomento il dispositivo contenente il
filesystem. Il comando richiede che questo sia smontato o al più montato in
sola lettura; in quest'ultimo caso, necessario se si tratta della radice, è
necessario indicare l'opzione \texttt{-d} ed è richiesto un immediato riavvio
dopo la terminazione del comando. A meno di eseguirlo in modalità prolissa con
l'opzione \texttt{-v}, il programma non scrive nulla se non in caso di
problemi. Le altre opzioni principali sono elencate in
tab.~\ref{tab:xfs_repair_options}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-d} & esegue la riparazione in modalità definita pericolosa a
                  filesystem montato in sola lettura, necessaria quando il
                  filesystem è quello della radice.\\
    \texttt{-f} & da usare quando il filesystem è contenuto in un file e non
                  in un dispositivo.\\
    \texttt{-l \textsl{dev}} & indica il dispositivo del giornale se questo è
                  esterno.\\ 
    \texttt{-n} & esegue la scansione senza eseguire nessuna modifica.\\
    \texttt{-v} & modalità prolissa, produce una quantità di informazioni
                  eccessiva ed è intesa ad uso di debug.\\
%    \texttt{} & .\\
    \hline
  \end{tabular}
  \caption{Principali opzioni di \texttt{xfs\_repair}.} 
  \label{tab:xfs_repair_options}
\end{table}

Benché il sistema sia molto stabile ed i principali problemi di corruzione
possano essere risolti con i vari comandi di controllo appena trattati, in
caso di danni veramente seri (le cui cause normalmente sono l'uso di un kernel
sperimentale o problemi hardware) questi possono fallire. Esistono pertanto
degli ulteriori comandi diagnostici che possono risultare utili per cercare di
risolvere la situazione; di nuovo tratteremo con maggior dettaglio quelli
disponibili per la famiglia dei filesystem \textit{extN}, anche se ne esistono
di analoghi anche per tutti gli altri.

Come già accennato in sez.~\ref{sec:filesystem_create} il comando
\texttt{dumpe2fs} può essere usato per recuperare una serie di informazioni
riguardo ad un filesystem \textit{extN}. Se invocato senza opzioni il comando
stampa una lunga lista di informazioni ricavate dal contenuto del
\textit{superblock} e dei \textit{group block}, come esempio riportiamo solo
la prima parte dell'output del comando, quella relativa alle sole informazioni
del \textit{superblock}, ottenibili specificando l'opzione \texttt{-h}:
\begin{Console}
anarres:~# \textbf{dumpe2fs -h /dev/sdd4}
dumpe2fs 1.35-WIP (07-Dec-2003)
Filesystem volume name:   <none>
Last mounted on:          <not available>
Filesystem UUID:          d0cb4773-dbf8-4898-94e8-bb2acc41df0d
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:      has_journal filetype needs_recovery sparse_super
Default mount options:    (none)
Filesystem state:         clean
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              4169760
Block count:              8324194
Reserved block count:     416209
Free blocks:              5365536
Free inodes:              3935324
First block:              0
Block size:               4096
Fragment size:            4096
Blocks per group:         32768
Fragments per group:      32768
Inodes per group:         16352
Inode blocks per group:   511
Last mount time:          Fri Jan 30 20:59:45 2004
Last write time:          Fri Jan 30 20:59:45 2004
Mount count:              16
Maximum mount count:      22
Last checked:             Sun Dec 21 14:45:22 2003
Check interval:           15552000 (6 months)
Next check after:         Fri Jun 18 15:45:22 2004
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:               128
Journal inode:            13
First orphan inode:       2421098
Journal backup:           inode blocks
\end{Console}

Le altre opzioni principali del comando sono \texttt{-b}, che restituisce
l'elenco dei blocchi marchiati come danneggiati in un filesystem, \texttt{-ob}
che permette di specificare il blocco (indicato per numero) da usare come
\textit{superblock} al posto di quello standard (in caso di corruzione di
quest'ultimo), \texttt{-oB} per indicare la dimensione dei blocchi (anche
questa è una informazione necessaria solo in caso di corruzione del
filesystem). Infine \texttt{-i} permette di leggere le informazioni invece che
dal filesystem da una immagine creata con il comando \texttt{e2image}. Per un
elenco completo e relative spiegazioni si faccia al solito riferimento alla
pagina di manuale.

Una delle misure di precauzione che si possono prendere per tentare un
recupero in caso di corruzione di un filesystem \textit{ext2} è quella di
crearne una immagine con il comando \index{comando!\texttt{e2image}}
\texttt{e2image}.  Questo comando permette di salvare su un file i dati
critici del filesystem in modo da poterli riutilizzare con programmi di
riparazione come \texttt{e2fsck} o \texttt{debugfs}. Il comando prende come
argomenti il dispositivo su cui si trova il filesystem ed il nome del file su
cui salvare l'immagine. L'unica opzione è \texttt{-r} che crea una immagine
binaria che può essere usata dai vari programmi di controllo come se fosse
l'intero filesystem.\footnote{per far questo viene creato uno \textit{sparse
    file} delle stesse dimensioni del filesystem; uno \textit{sparse file} è
  un file in cui non sono state scritte le parti vuote, pertanto anche se la
  sua dimensione può essere enorme, pari appunto ad un intero filesystem, in
  realtà viene occupato su disco solo lo spazio relativo alle parti non
  vuote.}

Qualora \texttt{e2fsck} fallisca in caso di un filesystem pesantemente
danneggiato un'ultima risorsa che si può tentare è quella di utilizzare
\index{comando!\texttt{debugfs}} \texttt{debugfs} per provare ad eseguire
manualmente la riparazione. Il comando permette di aprire anche un filesystem
danneggiato, e di eseguire su di esso delle operazioni. Non è detto che si
riesca a riparare completamente il filesystem, dato che per questo occorre una
conoscenza dettagliata della sua struttura interna, ma si possono tentare
delle operazioni di ripulitura che potrebbero portare lo stesso in uno stato
gestibile da \texttt{e2fsck}. In effetti il programma, come dice il suo nome,
non è uno strumento per il controllo quanto per il debugging, ed il suo uso è
in genere riservato ai cosiddetti \textit{filesystem guru}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-b \textsl{N}}   & specifica la dimensione dei blocchi.\\
    \texttt{-c}   & apre il filesystem in modalità \textsl{catastrofe}, in cui
                    non vengono letti neanche i dati generali dello stesso.\\
    \texttt{-f \textsl{file}}& legge i comandi dal file passato come
                               parametro.\\ 
    \texttt{-s \textsl{N}}   & specifica un superblocco alternativo.\\
    \texttt{-w}              & apre il filesystem in lettura/scrittura.\\
    \hline
  \end{tabular}
  \caption{Principali opzioni per il comando \texttt{debugfs}.} 
  \label{tab:debugfs_options}
\end{table}

Il comando prende come argomento il dispositivo contenente il filesystem da
esaminare; questo viene sempre aperto in sola lettura a meno che non si
specifichi l'opzione \texttt{-w}. In caso di filesystem pesantemente
danneggiato l'opzione \texttt{-b} permette di specificare una dimensione dei
blocchi, l'opzione \texttt{-s} permette di specificare il \textit{superblock}.
Le opzioni principali sono riportate in tab.~\ref{tab:debugfs_options}, per
l'elenco completo al solito si consulti la pagina di manuale.

Una volta aperto un filesystem con \texttt{debugfs} si viene portati su una
riga di comando da cui diventa possibile operare a basso livello con i dati
del filesystem, compiendo anche operazioni impossibili con i normali comandi
dei file, come cancellare o creare un \textit{hard link} senza aggiornare il
numero di riferimenti ad un \textit{inode}, recuperare un file cancellato ecc.
Molti dei comandi del programma riprendono i nomi degli ordinari comandi di
shell, eseguendo compiti analoghi, ma operano direttamente sui dati del
filesystem e possono usare come argomenti sia dei normali nomi di file che dei
numeri di \textit{inode}, questi ultimi però devono essere indicati
esplicitamente fra parentesi angolari (\texttt{<>}). Si è riportato un breve
riassunto dei comandi principali in tab.~\ref{tab:debugfs_commands}, per i
dettagli si consulti come sempre la pagina di manuale.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Comando} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{cat}   & mostra il contenuto di un file.\\
    \texttt{cd}    & cambia directory di lavoro.\\
    \texttt{dump}  & salva i dati del file/\textit{inode} su un altro file.\\
    \texttt{ln}    & crea un \textit{hard link} ma non aggiorna il numero di
                     collegamenti.\\ 
    \texttt{ls}    & mostra la lista dei file (con i dati degli
                     \textit{inode}).\\  
    \texttt{lsdel} & mostra la lista dei file cancellati.\\
    \texttt{rm}    & cancella un file.\\
    \texttt{rmdir} & cancella una directory.\\
    \texttt{stat}  & stampa i dati di un \textit{inode}.\\
    \texttt{undel} & ripristina un file cancellato.\\
    \texttt{unlink}& rimuove il collegamento ad un \textit{inode} 
                     ma non aggiorna il numero di collegamenti.\\
%    \texttt{} & .\\
    \hline
  \end{tabular}
  \caption{Principali comandi di \texttt{debugfs}.} 
  \label{tab:debugfs_commands}
\end{table}

Anche per XFS esistono ulteriori programmi diagnostici, ad esempio come
analogo di \texttt{dumpe2fs} si può usare il comando
\index{comando!\texttt{xfs\_info}} \texttt{xfs\_info} che stampa le
informazioni relative ad un filesystem e richiede che si indichi il file di
dispositivo.\footnote{in realtà questo è un alias per una opzione del comando
  di ridimensionamento (equivalente a \texttt{xfs\_growfs -n}), che vedremo in
  sez.~\ref{sec:filesystem_resize}. } Maggiori informazioni relative ai
metadati del filesystem possono essere ottenuto con
\index{comando!\texttt{xfs\_metadump}} \texttt{xfs\_metadump}, che scrive su
un file tutti i metadati, ma il programma viene utilizzato principalmente a
scopo di debug, per fornire agli sviluppatori i dati di un filesystem non
riparabile con \texttt{xfs\_repair} offuscando opportunamente i contenuti
(nomi dei file, directory ecc.).  Infine come analogo di \texttt{debugfs} è
disponibile \index{comando!\texttt{xfs\_db}} \texttt{xfs\_db}, anch'esso è
principalmente uno strumento di analisi di basso livello, che richiede una
approfondita conoscenza delle strutture del filesystem, da usare (leggendo la
documentazione) come ultima risorsa qualora \texttt{xfs\_repair} fallisse.

Infine si tenga presente che per Linux in genere non si usano programmi per la
\textsl{deframmentazione} del disco. Questa infatti è un problema solo per
quei filesystem la cui architettura è talmente inadeguata da renderlo
tale. Normalmente un filesystem ben progettato è in grado di gestire la
allocazione dello spazio disco in maniera da evitare il sorgere del problema
fin dall'inizio. Ci sono comunque alcuni programmi per eseguire questa
operazione o altre ottimizzazioni; ad esempio per XFS c'è
\index{comando!\texttt{xfs\_fsr}} \texttt{xfs\_fsr}, che agisce a filesystem
attivo ed esegue le operazioni in maniera parallela all'uso corrente dello
stesso, ma sia questo che gli altri non vengono usati quasi mai, proprio
perché di scarsa utilità.


\subsection{Il sistema dell'\textit{automounter}}
\label{sec:automounter}

Abbiamo visto in sez.~\ref{sec:file_disk_management} come sia possibile
impostare grazie a \texttt{/etc/fstab} il montaggio all'avvio di tutti i
filesystem necessari, e in quella occasione abbiamo anche accennato anche come
la gran parte dei sistemi desktop sia in grado di eseguire automaticamente il
montaggio di eventuali dispositivi estraibili quando il loro uso viene
rilevato dal kernel, funzionalità che oggi viene gestita da appositi programmi
che si appoggiano ad \textit{udev} (vedi sez.~\ref{sec:udev_hotplug}) e che
non ha nulla a che fare con quanto prenderemo in esame qui.

Esiste però un'altra esigenza relativa al montaggio automatico dei filesystem,
che non attiene a dispositivi estraibili o temporanei, ma piuttosto a
filesystem sempre disponibili, ma utilizzati solo sporadicamente, come
potrebbero essere filesystem di rete per accedere a informazioni condivise. In
questo caso può essere utile poter avere un montaggio ``a richiesta'',
soltanto in occasione del loro utilizzo. É a questa esigenza che risponde il
sistema dell'\textit{automounter} il cui scopo è proprio quello di montare
automaticamente un filesystem in reazione all'accesso alla directory in cui
questo deve comparire.

Il sistema consente in questo modo di rimandare al momento del loro uso
effettivo il montaggio di filesystem di rete senza la necessità di dover
eseguire un comando in maniera esplicita. Questo consente anche di evitare
intoppi nella procedura di avvio, quando in caso di malfunzionamento della
rete detti filesystem non potrebbero venire montati. Infine essendo stata
prevista la possibilità di mantenere le informazioni relative ai filesystem da
montare automaticamente su servizi di rete centralizzati (sono supportati NIS
e LDAP, ma trattare il loro uso va al di là degli obiettivi di questo testo)
si può semplificare la gestione in caso si debbano configurare allo stesso
modo molte macchine.

\itindbeg{autofs}

Il supporto per l'\textit{automounter}, denominato \textit{autofs}, viene
fornito direttamente da parte del kernel a partire dalla versione 2.2. Il
relativo supporto deve comunque essere stato compilato all'interno del kernel
(vedi sez.~\ref{sec:kernel_compile}) ed è inoltre necessario l'ausilio di
alcuni programmi in user-space.\footnote{esistono due versioni, la 4 e la 5,
  su Debian vengono fornite rispettivamente dai pacchetti \texttt{autofs} e
  \texttt{autofs5}.} In realtà esiste anche un supporto totalmente in
user-space, fornito da un apposito demone (\texttt{amd}, o \textit{auto mount
  daemon}) ripreso da quello usato su Solaris, che però non prenderemo in
considerazione.

L'intero sistema è controllato da un file di configurazione principale,
\index{configurazione!\texttt{/etc/auto.master}} \texttt{/etc/auto.master},
che contiene l'elenco dei \textit{mount-point} su cui verranno montati
automaticamente i filesystem. Il formato del file, con la solita convenzione
di ignorare righe vuote e tutto quello che segue il carattere ``\texttt{\#}''
prevede che ogni riga indichi un \textit{mount-point} a cui viene associata
una \textsl{mappa} che descrive quali filesystem vi devono essere montati e
delle eventuali opzioni; il tutto deve essere specificato da tre campi
separati da spazi.

Fino alla versione 4 di \textit{autofs} erano supportate soltanto le
cosiddette \textsl{mappe indirette}, in cui il campo del \textit{mount-point}
deve indicare una directory sul filesystem (ad esempio \texttt{/misc}) sotto
cui compariranno tutti i filesystem elencati nella mappa corrispondente. In
sostanza con una mappa indiretta l'accesso ad una sottodirectory (ad esempio
sotto \texttt{/misc/disk}) provoca una ricerca nella mappa associata con la
chiave espressa dal nome della sottodirectory (nel caso dell'esempio
\texttt{disk}) che se trovata provoca l'esecuzione della rispettiva operazione
di montaggio.

Con la versione 5 di \textit{autofs} è divenuto disponibile anche il supporto
per le cosiddette \textsl{mappe dirette}, in questo caso il
\texttt{mount-point} viene indicato come ``\texttt{/-}'' (che non corrisponde
alla directory ``\texttt{-}'' sotto la radice) mentre le chiavi usate nella
mappa diretta devono corrispondere ai pathname assoluti dove si vuole che i
rispettivi filesystem vengano montati. Si tenga presente che in entrambi i
casi se le directory indicate non esistono queste verranno create
automaticamente al montaggio del filesystem che devono ospitare, e rimosse al
suo smontaggio.

Il secondo campo di \texttt{/etc/auto.master} serve ad indicare la mappa
associata al rispettivo \textit{mount-point}. Nella sua forma più semplice
questa è espressa semplicemente come il pathname del file che la contiene. In
realtà come accennato le mappe possono essere mantenute anche tramite servizi
di rete, per cui la sintassi estesa di questo secondo campo è nella forma
\texttt{tipo:mappa},\footnote{ad essere pignoli la sintassi completa è
  \texttt{tipo,formato:mappa}, ma in tutti i casi pratici il default del
  formato è sempre quello corrispondente al tipo di mappa, quindi non viene
  mai indicato.} dove \texttt{tipo} indica di che mappa si tratta e
\texttt{nome} deve essere espresso in forma adeguata al relativo tipo, ma non
tratteremo queste forme più complesse, per le quali si rimanda alla lettura
della pagina di manuale con accessibile \texttt{man auto.master}.

% In tab.~\ref{tab:autofs_map_types} si sono riportati quelli più rilevanti, per
% un elenco completo si consulti la pagina di manuale con \texttt{man
%   auto.master}.

% \begin{table}[!htb]
%   \centering
%   \footnotesize
%   \begin{tabular}[c]{|l|p{10cm}|}
%     \hline
%     \textbf{Tipo} & \textbf{Significato} \\
%     \hline
%     \hline
%     \texttt{file} & la mappa è un file su disco, è il default e non viene mai
%                     specificato esplicitamente, si scrive pertanto solo il
%                     nome del file.\\
%     \texttt{program}& la mappa viene generata eseguendo il programma indicato
%                       dal nome file .\\
%     \texttt{yp}   & la mappa viene fornita via rete via NIS.\\
%     \texttt{ldap} & la mappa viene fornita via rete via LDAP.\\
% %    \texttt{} & .\\
%     \hline
%   \end{tabular}
%   \caption{Principali tipi delle mappe per \textit{autofs}.} 
%   \label{tab:autofs_map_types}
% \end{table}

% Il nome con cui si esprime la mappa dipende dal rispettivo tipo, ma nel caso
% di \texttt{file} (l'unico che prenderemo in esame)} questo deve essere il
% pathname di un file.

Il terzo campo di \texttt{auto.master} consente di specificare delle opzioni
facoltative. Qualora queste siano indicate senza un trattino iniziale verranno
semplicemente passate come opzioni per l'esecuzione del comando \texttt{mount}
per i filesystem della mappa, il trattino iniziale consente invece di passare
opzioni relative al funzionamento della mappa. Anche in questo caso per i
dettagli si consulti la pagina di manuale.

Si tenga presente inoltre che esiste, a partire dalla versione 5, una speciale
mappa interna, che non richiede riferimenti ad altre risorse, utilizzabile
specificando \texttt{-host} nel relativo campo. Questa mappa consente di
montare automaticamente un qualunque filesystem NFS disponibile sulla propria
rete; in tal caso la sottodirectory del \textit{mount-point} verrà
interpretata come un nome di una macchina sulla rete, ed al di sotto di detta
sottodirectory verranno montati tutti i filesystem esportati con NFS da quella
macchina. In questo modo non è più necessario mantenere una mappa con l'elenco
degli stessi.

Un possibile esempio del contenuto di \texttt{/etc/auto.master} è il seguente,
dove si è richiesto il montaggio automatico sotto \texttt{/misc} dei
filesystem elencati in \texttt{/etc/auto.misc} e in \texttt{/net} dei
filesystem NFS disponibili nella propria rete:
\begin{FileExample}[label=/etc/auto.master]
/misc  /etc/auto.misc
/net   -host
\end{FileExample}

L'avvio del sistema dell'\textit{automounter} è effettuato dallo script
\texttt{/etc/init.d/autofs} che esamina il contenuto di
\texttt{/etc/auto.master} e per ciascuna voce esegue il programma
\texttt{automount}, come singole istanze del programma nella versione 4, come
\textit{thread} aggiuntivo di una unica istanza nella versione 5.  Questo è il
programma che si incarica, all'accesso alle directory indicate in
\texttt{/etc/auto.master}, di eseguire la scansione delle relative mappe e di
effettuare il montaggio automatico. Ad ogni modifica di
\texttt{/etc/auto.master} occorre eseguire un reload del servizio per far
rieseguire \texttt{automount} sulle voci presenti, le istanze relative a voci
rimosse verranno eliminate e ne verranno fatte partire di nuove per le voci
aggiunte.

Invece una modifica di un file delle mappe (ad \texttt{/etc/auto.misc} nel
caso dell'esempio) viene vista immediatamente al primo utilizzo successivo
dello stesso. Inoltre è possibile modificare alcune delle impostazioni
generali del sistema che normalmente vengono mantenute nel file
\index{configurazione!\texttt{/etc/default/autofs}}
\texttt{/etc/default/autofs}, in cui queste sono espresse in forma di
assegnazione di variabili di shell. Si sono riportate in
tab.~\ref{tab:autofs_defaults} le più rilevanti, l'elenco completo si trova al
solito nella pagina di manuale di \texttt{auto.master}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Variabile} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{TIMEOUT} & tempo in secondi dopo il quale un filesystem
                       inutilizzato viene smontato automaticamente.\\
    \texttt{APPEND\_OPTIONS} & determina se le opzioni di montaggio inserite
                       nelle mappe vengono aggiunte (default \texttt{yes}) o
                       se rimpiazzano quelle
                       eventualmente specificate in \texttt{auto.master}.\\
    \texttt{LOGGING} & indica il livello di log.\\
%    \texttt{} & .\\
    \hline
  \end{tabular}
  \caption{Variabili di configurazione per i default di \textit{autofs}.} 
  \label{tab:autofs_defaults}
\end{table}

Il formato di un file di una mappa \textit{autofs} prevede di tre campi
separati da spazi, di cui il secondo è opzionale. Il primo campo è la stringa
che costituisce la chiave di ricerca sulla mappa, e che come detto corrisponde
alla sottodirectory della voce di \texttt{auto.master} corrispondente alla
mappa su cui verrà montato il filesystem indicato nell'ultimo campo.

Il secondo campo, che se presente deve iniziare con il carattere
``\texttt{-}'', indica le opzioni, espresse da una lista separata da virgole,
da usare nel montaggio del filesystem che devono corrispondere ai parametri
dell'opzione \texttt{-o} che si userebbero per montare il filesystem con il
comando \texttt{mount}, con l'eccezione dell'opzione speciale
\texttt{-fstype=tipo} che serve invece ad esprimere il tipo di filesystem, con
\texttt{tipo} che deve corrispondere al valore che si darebbe all'opzione
\texttt{-t} del comando \texttt{mount}. Se non si specifica \texttt{-fstype}
il default è usare \texttt{nfs}, e se non si devono specificare opzioni il
secondo campo si può omettere.

L'ultimo campo indica invece il filesystem da montare, nel caso di NFS questo
deve essere espresso nella forma \texttt{hostname:pathname} nello stesso
formato che si userebbe per il primo campo di \texttt{/etc/fstab}. Qualora si
voglia invece montare il contenuto di un dispositivo locale lo si dovrà
indicare tramite il corrispondente file di dispositivo preceduto dal carattere
``\texttt{:}'', qualora di tratti di una condivisione di rete con protocollo
SMB invece la si dovrà indicare, sempre preceduta dal carattere
``\texttt{:}'', con la convenzione per gli indirizzi usata dal comando
\texttt{smbclient} (per la quale si rimanda a sez.~\ref{sec:net_samba}). Sono
inoltre supportate alcune funzionalità avanzate, come l'uso di montaggi
multipli, e la sostituzione di alcune variabili per generare mappe dinamiche,
per la trattazione delle quali si rimanda alla pagina di manuale del formato
delle mappe, accessibile con \texttt{man 5 autofs}.

\itindend{autofs}



\subsection{La gestione della \textit{swap} e dei CDROM}
\label{sec:swap_CDROM_management}

\itindbeg{swap}

Tratteremo in questa ultima sezione due argomenti attinenti solo in modo
parziale alla gestione di dischi e filesystem. Il primo di questi è quello
relativo alla gestione dello spazio disco dedicato alla \textit{swap} ed al
funzionamento di quest'ultima. Questa costituisce un complemento alla gestione
della memoria virtuale, il meccanismo con cui il kernel controlla
l'allocazione della memoria fisica ai vari processi.

Come accennato in sez.~\ref{sec:struct_architecture} e poi approfondito in
sez.~\ref{sec:struct_proc_property} il kernel gestisce, con l'aiuto della MMU
(\textit{Memory Management Unit}) del processore, una rimappatura dello spazio
degli indirizzi dei processi sulla memoria fisica effettivamente disponibile.
In questo modo ciascun processo può usare un suo spazio di indirizzi virtuale
(usando un qualunque valore fra quelli possibili), e tramite la MMU accederà
ad un indirizzo reale della memoria effettivamente disponibile.

Una delle caratteristiche del meccanismo è che in questo modo ciascun processo
mantiene un suo spazio di indirizzi separato e se un processo usa un indirizzo
che non corrisponde a nessuna pagina di memoria si avrà quello che si chiama
un \textit{segmentation fault} ed il sistema si accorgerà immediatamente
dell'errore inviando al processo un segnale di \texttt{SIGSEGV}.  Ma la
potenza del meccanismo della memoria virtuale consiste nel fatto che esso
consente di utilizzare anche dello spazio disco come supporto aggiuntivo
rispetto alla memoria fisica, quando l'uso di questa diventa eccessivo.

È questo lo scopo della cosiddetta \textsl{area di swap}, una sezione di disco
(in genere una partizione, ma si può usare anche un file) su cui il kernel può
salvare le pagine di memoria meno utilizzate di un processo, ma anche i dati
mantenuti nei dischi in RAM generati con \texttt{tmpfs}, in modo che altri
possano utilizzare la memoria fisica che così viene liberata.  Chiaramente
quando si andrà a rieseguire il processo le cui pagine di memoria sono state
salvate sull'\textsl{area di swap} e questo cercherà di accedere a quelle, si
avrà quello che si chiama un \itindex{page~fault} \textit{page
  fault}\footnote{quello che succede è che quando la MMU si accorge che la
  pagina richiesta non è mappata su della memoria fisica invia un segnale al
  processore, così che questo possa eseguire la opportuna sezione del kernel,
  quest'ultimo si occuperà o di recuperare la pagina dalla \textit{swap} (se
  l'indirizzo era giusto) o di inviare un segnale di \texttt{SIGSEGV} (se
  l'accesso era sbagliato).} a questo punto il sistema della memoria virtuale
provvederà a recuperare la pagina dall'area di \textit{swap} e a rimetterla in
memoria, così che il processo possa proseguire la sua esecuzione come se
niente fosse. In realtà tutto questo richiede tempi che sono ordini di
grandezza superiori rispetto all'accesso diretto alla RAM, per cui il niente è
solo teorico ed in pratica il programma sarà infinitamente più lento.

Perché il kernel possa usare un'\textsl{area di swap} questa deve essere
opportunamente inizializzata, come si fa per un filesystem, ma si tenga
presente comunque che in questo caso non si ha a che fare con un filesystem,
dato che l'area deve essere solo utilizzata per copiarci pagine, per cui non
sono affatto necessarie tutte le infrastrutture mostrate in
sez.~\ref{sec:struct_filesystem_arch}. A questo provvede il comando
\index{comando!\texttt{mkswap}} \texttt{mkswap} che prende come argomento il
file da usare come area di \textit{swap}.  In genere si usa il comando
specificando come argomento un file di dispositivo indicante una partizione
appositamente riservata (vedi sez.~\ref{sec:partitioning}), in questo caso
infatti l'accesso al disco è diretto e più veloce rispetto al caso, comunque
possibile, in cui si usa un file normale, per il quale si dovrebbe prima
passare attraverso il relativo filesystem.

Dato che le prestazioni del sistema della memoria virtuale dipendono
direttamente, in caso di utilizzo dell'area di \textit{swap}, dai tempi di
accesso a quest'ultima e dalla velocità di trasferimento dei dati, è in genere
una pessima idea usare un disco vecchio e lento per questo scopo. È per questo
motivo inoltre che a volte si suggerisce di usare per l'area di \textit{swap}
l'ultima partizione disponibile, considerata come quella che contiene i
settori più esterni del disco, dove la velocità di trasferimento è maggiore.

Il comando prevede, per compatibilità con le vecchie versioni, un secondo
argomento che specifica la dimensione dell'area di \textit{swap} e se non lo
si specifica viene automaticamente utilizzato tutto lo spazio
disponibile. Come per \texttt{mkfs} l'opzione \texttt{-c} richiede un
controllo della partizione per la presenza di settori difettosi. L'opzione
\texttt{-p} permette di specificare come parametro la dimensione delle pagine
di memoria (in genere 4096 byte, ma dipende dall'architettura hardware),
l'elenco delle opzioni è riportato in tab.~\ref{tab:mkswap_options}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-c} & esegue un controllo per la presenza di settori difettosi.\\
%    \texttt{}   & .\\
    \texttt{-f} & forza l'esecuzione del comando anche se si sono dati
                  argomenti sbagliati (come un dimensione dell'area maggiore
                  di quella della partizione).\\
    \texttt{-p \textsl{size}} & specifica, con il valore passato come
                                parametro, la dimensione delle pagine di
                                memoria.\\
    \texttt{-v \textsl{N}}    & specifica la versione della formattazione
                                dell'area di \textit{swap}, con \texttt{-v0}
                                usa il vecchio stile (deprecato), con il
                                \texttt{-v1} usa il nuovo.\\
    \hline
  \end{tabular}
  \caption{Opzioni per il comando \texttt{mkswap}.} 
  \label{tab:mkswap_options}
\end{table}

Si tenga presente che per i kernel precedenti il 2.4.10 erano possibili fino
ad un massimo di 8 aree di \textit{swap}, a partire da esso sono state portate
a 32. Un elenco di quelle attive è visibile in \texttt{/proc/swaps}.
\index{filesystem~\texttt{/proc}!\texttt{/proc/swaps}} La dimensione massima
dell'area di \textit{swap} dipende sia dalla versione utilizzata che
dall'architettura hardware. Con la vecchia versione il massimo dipendeva solo
dalla dimensione delle pagine ed era di 128Mb con le pagine di 4096 byte della
architettura standard dei PC portati poi a 2Gb, oggi è di 64Gb.

Una volta creata un'area di \textit{swap} questa non verrà utilizzata dal
kernel fintanto che non la si attiva con il comando
\index{comando!\texttt{swapon}} \texttt{swapon}; questo prende come argomento
il file da usare coma area di \textit{swap}, che verrà immediatamente
attivata. In generale però il comando non viene mai invocato direttamente, ma
chiamato con l'opzione \texttt{-a} negli script di avvio, ed in questo caso
attiverà tutti i dispositivi che sono marcati con \texttt{swap} all'interno di
\texttt{/etc/fstab}.\footnote{si ricordi di nuovo che la \textit{swap} non è
  un filesystem, pertanto anche se la voce ad essa relativa compare in
  \texttt{/etc/fstab}, sintassi, come già visto in
  sez.~\ref{sec:file_disk_management}, è diversa, e che non si può usare il
  comando \texttt{mount} per montarne il contenuto in una directory.} Se
invece si vuole avere una lista dei dispositivi attualmente utilizzati si
potrà usare l'opzione \texttt{-s}, ottenendo qualcosa del tipo:
\begin{Console}
hain:/home/piccardi/truedoc/corso# \textbf{swapon -s}
Filename                        Type            Size    Used    Priority
/dev/hda2                       partition       498004  1936    -1
\end{Console}

Un'altra opzione importante è \texttt{-p}, che permette di impostare una
priorità (un parametro di valore fra 0 e 32767) per l'uso della partizione.
Quando si ha una sola area questo valore non è significativo in quanto il
kernel si limiterà ad usare la prima sezione libera che trova, se le aree sono
più di una l'algoritmo di utilizzo prevede che il kernel usi a turno quelle
della stessa priorità (realizzando così una forma di RAID-0, vedi
sez.~\ref{sec:RAID_intro}) e passi ad una di priorità inferiore solo quando
quelle di priorità superiore sono piene.

Se non si specifica nulla le priorità vengono assegnate automaticamente
andando a diminuire nell'ordine di attivazione (così che la prima area
attivata è quella a priorità maggiore), usando \texttt{-p} si può forzare la
stessa priorità ottenendo un uso più efficace e maggiore velocità. Si può
ottenere questo risultato anche per le aree di \textit{swap} attivate con
\texttt{swapon -a} specificando in \texttt{/etc/fstab} nel relativo campo
l'opzione \texttt{pri=\textsl{N}} dove \texttt{\textsl{N}}, è lo stesso valore
che si userebbe con \texttt{-p}.

Infine si può disattivare un'area di \textit{swap} usando il comando
\index{comando!\texttt{swapoff}} \texttt{swapoff}, anche in questo caso
occorre fornire come argomento il file di dispositivo indicante l'area da
disabilitare. Il comando consente anche l'uso dell'opzione \texttt{-a} nel
qual caso non sarà necessario passare argomenti e saranno disattivate tutte le
aree di \textit{swap} presenti, così come indicate in \texttt{/proc/swaps} e
\texttt{/etc/fstab}.

\itindend{swap}

Benché totalmente diversi dai dischi, anche i CDROM sono dispositivi a
blocchi, e come visto in sez.~\ref{sec:file_disk_management} per poter
accedere al loro contenuto occorre che questi vengano opportunamente
montati. Abbiamo anche accennato come in genere detto contenuto sia mantenuto
in uno specifico filesystem di tipo \texttt{iso9660}, definito nello standard
omonimo. Si tenga presente comunque che in questo caso stiamo parlando dei CD
di dati, i CD audio non contengono un filesystem e si utilizzano in maniera
totalmente diversa, che non approfondiremo qui.

Il problema che però non abbiamo affrontato in
sez.~\ref{sec:filesystem_create} è come creare un tale filesystem e come
registrarlo su un CDROM quando si vuole crearne uno. In questo caso infatti,
trattandosi di un dispositivo fisico diverso, non esiste il concetto delle
partizioni, e se l'accesso diretto in lettura può essere fatto, come per
dischi, tramite il file di dispositivo, non altrettanto accade per una
eventuale scrittura con un masterizzatore.  Questo vuol dire che anche se è
sempre possibile leggere l'immagine di un disco con un comando come \texttt{dd
  if=/dev/cdrom of=file.iso} non è possibile creare un CDROM con qualcosa del
tipo \texttt{dd if=file.iso of=/dev/cdrom}, anche se si ha un masterizzatore e
non un semplice lettore.

Il comando che consente la creazione di un filesystem \texttt{iso9660} è
\index{comando!\texttt{mkisofs}} \texttt{mkisofs}, anche se questo è il nome
del programma originale, sempre disponibile come link, ma la gran parte delle
distribuzioni oggi usa la versione sviluppata dopo un fork, che si chiama
\texttt{genisoimage}. \index{comando!\texttt{genisoimage}} Per quanto appena
detto a differenza dei vari \texttt{mkfs} questo non può essere usato
direttamente con un file di dispositivo,\footnote{a meno di non voler
  formattare una partizione o un disco con questo filesystem, cosa che non ha
  alcuna utilità pratica.} ma serve a creare una \textsl{immagine} dello
stesso su un file, che è quello che potrà essere usato in seguito con un
programma di masterizzazione.

La sintassi del comando prevede che si passino come argomenti le directory che
si vogliono includere nell'immagine, in genere si usa sempre l'opzione
\texttt{-o} per specificare il file dell'immagine ISO, altrimenti il comando
scrive sullo \textit{standard output}. Il comando prevede inoltre una
sterminata quantità di opzioni che consentono di controllare le modalità di
creazione dell'immagine e supportare le innumerevoli varianti delle estensioni
fatte allo standard originale, che essendo nato come minimo comun denominatore
delle caratteristiche dei filesystem dell'epoca, supporta funzionalità minime,
derivate per lo più dalle limitazioni dovuto al dover essere compatibile con
l'MSDOS del tempo, come ad esempio nomi dei file di al massimo otto caratteri
più tre di estensione, oltre ovviamente a non supportare nessuna forma di
permessi o proprietà dei file, link simbolici, ecc.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-b} \texttt{\textsl{image}}& crea una immagine con incluso il
                 disco di avvio \texttt{image} secondo le estensioni
                 \textit{El Torito}.\\
    \texttt{-hfs}&crea una immagine con le estensioni \textit{HFS} per
                 l'uso da parte di sistemi Macintosh.\\
    \texttt{-J}& crea una immagine con le estensioni \textit{Joliet} per
                 l'uso da parte di sistemi Windows.\\
    \texttt{-m} \texttt{\textsl{glob}}& esclude dai file inseriti
                nell'immagine quelli selezionati con l'espressione
                \texttt{glob} (indicata con la sintassi del \textit{filename
                  globbing} della shell).\\ 
    \texttt{-o} \texttt{\textsl{file}}& indica il file su cui scrivere
                 l'immagine ISO.\\
    \texttt{-R}& crea una immagine con le estensioni \textit{Rock Ridge} per
                 l'uso da parte di sistemi unix-like.\\
%    \texttt{}& .\\
    \hline
  \end{tabular}
  \caption{Opzioni per il comando \texttt{mkisofs}.} 
  \label{tab:mkisofs_options}
\end{table}

Dato che con filesystem più recenti questo costituirebbe un limite scarsamente
accettabile, sono state introdotte diverse estensioni, come le
\itindex{Rock~Ridge} \textit{Rock Ridge}, attivabili con l'opzione
\texttt{-R}, che consentono di crearvi un vero filesystem Unix (con permessi,
proprietari dei file, link simbolici, nomi estesi, ecc.)  o le
\itindex{Joliet} \textit{Joliet}, attivabili con l'opzione \texttt{-J}, ed
usate nei sistemi Windows per estendere i nomi dei file. Le due opzioni
possono essere combinate per aver il supporto di entrambe le funzionalità. Si
possono inoltre creare immagini adatte a sistemi Macintosh con le estensioni
HFS, abilitate con l'opzione \texttt{-hfs}.

Oltre ai semplici CD di dati il comando è anche in grado di creare CDROM
avviabili in diversi formati, e ad esempio si può usare l'opzione \texttt{-b}
per indicare come parametro il file contenente una immagine di disco di avvio
per PC secondo le estensioni \itindex{El Torito} \textit{El Torito}, che in
sostanza non è altro che l'immagine di un floppy di avvio, creata ad esempio
con SYSLINUX o ISOLINUX (vedi sez.~\ref{sec:struct_syslinux}), che può avere
dimensioni fisse di 1200, 1440, 2880 kb. Le altre opzioni più rilevanti si
sono riportate in tab.~\ref{tab:mkisofs_options}, ed al solito per i dettagli
e delle spiegazioni più approfondite si consulti la pagina di manuale.



\section{La gestione di kernel e moduli}
\label{sec:kernel}

Tratteremo in questa sezione la gestione del kernel, in tutti i suoi aspetti:
dalla scelta delle diverse versioni, al tipo di kernel da utilizzare, la sua
ricompilazione, l'installazione, la gestione dei moduli, l'utilizzo delle
\textit{patch} e tutto quanto attiene la manutenzione dello stesso.


\subsection{Le versioni del kernel}
\label{sec:kernel_version}

Uno dei primi problemi che ci si trova ad affrontare nella gestione del kernel
è quello della scelta di quale versione usare. Nella maggior parte dei casi il
kernel viene installato dalla propria distribuzione durante l'installazione, e
molti, non avendo necessità specifiche (ad esempio la mancanza di supporto per
un qualche dispositivo) evitano di installarne un altro. Le distribuzioni
inoltre forniscono ormai diverse versioni del kernel in modo che si possa
scegliere quella che meglio si adatta al proprio hardware.

Le principali esigenze che portano all'installazione di un kernel dai sorgenti
restano quella di ottimizzare il kernel per renderlo più adatto alla propria
configurazione hardware o quella di usare una versione più recente che ha una
nuova funzionalità che si vuole usare. Molti kernel di installazione infatti
sono compilati con un supporto generico (per tipo di processore o per il
chipset della piastra madre) per poter essere impiegati su qualunque PC e non
è detto siano l'ultima versione disponibile, perciò può essere utile
ricompilarli per eliminare il supporto di funzionalità superflue non
disponibili, attivare solo quello per la versione specifica del proprio
hardware o installare versioni più recenti.

Quando si vuole installare una propria versione del kernel si hanno due
scelte, si può ricompilare il kernel della propria distribuzione (in genere
tutte forniscono i relativi sorgenti), oppure si può utilizzare un kernel
\textsl{ufficiale}, vale ad dire il kernel pubblicato su
\url{http://www.kernel.org} a cura dal \textit{mantainer} ufficiale (lo stesso
Linus Torvalds o chi lui ha delegato al compito). Si tenga presente comunque
che le distribuzioni installano una propria versione del kernel, che anche se
può essere meno recente rispetto all'ultimo rilascio di quella ufficiale,
viene spesso modificata applicando vari \textit{patch} (vedi
sez.~\ref{sec:kernel_source}) per migliorare le prestazioni o la stabilità o
per aggiungere funzionalità reputate rilevanti o supporto per nuovi
dispositivi, che non è detto siano incluse nel kernel ufficiale.

Qualora si scelga il kernel della propria distribuzione c'è solo da procurarsi
i relativi sorgenti, i file di configurazione e provvedere alla ricompilazione
secondo le istruzioni di sez.~\ref{sec:kernel_compile}. Se invece si vuole
installare un kernel ufficiale, ad esempio per avere le funzionalità aggiunte
nello sviluppo effettuato nel frattempo, occorre scegliere una versione
adeguata. La scelta della versione di kernel da utilizzare è in linea generale
abbastanza semplice: occorre prendere l'ultima versione stabile. Le politiche
di rilascio sono però cambiate notevolmente, ed anche se per stabilire di
quale versione si tratta basta andare sul sito ufficiale del kernel, la logica
che sta dietro la numerazione delle versioni è stata modificata profondamente
varie volte.

Fino alla serie 2.6.x le versioni ufficiali erano caratterizzate da tre
numeri, separati da punti. Il primo numero esprimeva la \textit{major
  version}, che veniva cambiato solo in caso di modifiche strutturali
fondamentali, cosa avvenuta una sola volta, nel passaggio dei formati dei
binari dall'\textit{a.out} all'ELF. Il secondo numero esprimeva il cosiddetto
\textit{patchlevel}, e fino alla serie 2.4.x era quello che veniva cambiato in
base ai cicli di sviluppo: un numero pari indicava una versione
\textsl{stabile} da usare in produzione, mentre un numero dispari indicava una
versione di sviluppo su cui venivano introdotte tutte le novità che avrebbero
portato alla versione stabile successiva. Con questa convenzione si sono avute
le serie stabili 2.0.x, 2.2.x, 2,4.x, fino alla 2.6.x e le serie di sviluppo
2.1.x, 2.3.x e 2.5.x.  L'ultimo numero di versione, detto \textit{sublevel},
veniva utilizzato come numero progressivo per identificare i vari rilasci
successivi all'interno di una serie, nella direzione della stabilizzazione per
le serie pari, e delle nuove funzionalità per le serie dispari.

Con il rilascio della serie 2.6.x questo modello è stato totalmente cambiato;
in precedenza infatti dopo il rilascio tutti gli sforzi venivano concentrati
nella stabilizzazione della nuova versione stabile per un congruo periodo di
tempo, per poi dar vita ad una nuova versione di sviluppo. Ma le difficoltà ed
i ritardi incontrati nel rilascio della versione 2.6.0 aveva già fatto si che
molte distribuzioni, non volendo attendere i tempi lunghi di una nuova
versione stabile, introducessero nuove funzionalità o eseguissero il
\textit{backporting} di codice dalla versione di sviluppo a quella stabile,
introducendo delle differenze significative fra le loro versioni e quella
ufficiale.

Questo, insieme al fatto che diventava sempre meno sostenibile mantenere i
kernel stabili rinunciando ai miglioramenti introdotti in fase di sviluppo, è
stato uno dei motivi che ha spinto al cambiamento della gestione delle
versioni, diventato ufficiale con il rilascio del kernel 2.6.9 nel novembre
2004. La nuova politica, tuttora in vigore, non prevede più la creazione di
una serie di sviluppo (ed infatti la serie 2.7 non è mai nata), ma tante
versioni ``\textsl{stabili}'' successive nella stessa serie. Ogni volta che
una di queste viene rilasciata inizia un periodo di circa un paio di settimane
in cui si inseriscono tutte le funzionalità ed i cambiamenti che si ritengono
maturi per l'ingresso nella versione stabile successiva, cui segue un periodo
di stabilizzazione, che in genere dura qualche mese, prima del nuovo rilascio.

Questo ha reso molto più veloce l'introduzione di cambiamenti e l'evoluzione
del kernel, ma ha comportato anche la necessità di affrontare il problema
della correzione della versione stabile corrente per gli errori trovati nella
fase successiva al suo rilascio. Per questo motivo quasi subito vennero
introdotte delle ulteriori sotto-versioni di ``\textsl{manutenzione}'', in cui
inserire solo modifiche elementari o urgenti, come la chiusura di problemi di
sicurezza e piccole correzioni per malfunzionamenti ed errori, introducendo un
quarto livello di numerazione. Lo sviluppo di queste versioni terminava
normalmente in corrispondenza del rilascio della versione stabile successiva,
ma alcune versioni sono state mantenute per tempo maggiore, introducendo una
sorta di supporto esteso; ad esempio il kernel 2.6.32 è stato mantenuto in
questo modo per più di un anno, fornendo la base per molte distribuzioni.

In seguito, visto che con questo cambiamento del modello di sviluppo la
seconda cifra del numero di versione aveva completamente perso il significato
che aveva in precedenza (si è rimasti al 2.6 per lungo tempo), nel luglio 2011
venne deciso l'incremento della \textit{major version}, passando alla serie 3
(e cambiando anche il significato delle cifre successive) anche se il kernel
3.0 non aveva introdotto nessuna modifica particolarmente significativa
rispetto al 2.6.39.

Da allora la precedente terza cifra usata per il \textit{sublevel}, che
esprimeva le versioni rilasciate a cadenze regolari, è diventata la seconda
cifra (il \textit{patchlevel}) mentre i numeri progressivi delle ulteriori
correzioni di stabilizzazione che prima andavano sulla quarta cifra sono
diventati il nuovo \textit{sublevel}, tornando di fatto ad un numero di
versione ufficiale espresso con tre cifre separate da punti. Il modello di
rilascio è comunque rimasto lo stesso, ed anche in questo caso alcune versioni
specifiche, usate spesso come base per i kernel delle distribuzioni, sono
state mantenute per tempi più lunghi rispetto alla nascita di una versione
stabile successiva. Per concludere questa panoramica sulle versioni, nel
febbraio 2015 si è passati dal kernel 3.19 al 4.0, semplicemente per cambiare
la numerazione, e senza che ci fosse un motivo tecnico sottostante.

Si tenga comunque presente che l'indicazione iniziale di utilizzare l'ultimo
kernel della serie stabile non ha un valore assoluto. Esistono infatti anche
delle buone ragioni, come limiti sulle risorse, la ricerca di stabilità, il
supporto di vecchissime periferiche non più supportate che spingono a
mantenere l'utilizzo di kernel di serie precedenti, talvolta anche di quelli
ormai non più mantenuti.


\subsection{Sorgenti e \textit{patch}}
\label{sec:kernel_source}

Una volta scelta la versione del kernel da utilizzare, il passo successivo è
quello di scaricare i sorgenti e ricompilarli. Come accennato il sito per la
distribuzione delle versioni ufficiali è \url{http://www.kernel.org}, che in
genere ha molto carico, per cui si consiglia l'uso di uno dei vari mirror
italiani disponibili, la cui lista è segnalata sulla stessa pagina. 

I sorgenti del kernel vengono distribuiti via HTTP\footnote{in realtà è
  possibile il download anche tramite \texttt{rsync}, che permette di ridurre
  la quantità di dati da scaricare, o direttamente attraverso il programma di
  gestione dei sorgenti \texttt{git}, invece l'uso di FTP è cessato dal marzo
  2017.} sul sito citato nella directory \texttt{/pub/linux} e sono
disponibili sia come archivi completi in formato \texttt{tar} compressi o con
\texttt{gzip} o \texttt{xz} (con nomi come \texttt{linux-4.9.35.tar.gz} o
\texttt{linux-4.9.35.tar.xz}) oppure come \textit{patch} (sia dal rilascio
iniziale, che dalla versione precedente). Con questi ultimi si può passare da
una versione alla successiva, evitando così di scaricare l'archivio completo
tutte le volte. Per cui una volta che si abbiano i sorgenti del kernel 4.9.35,
si potrà passare al 4.9.36 scaricando soltanto il file
\texttt{patch-4.9.35-36.gz} (o \texttt{patch-4.9.35-36.xz}, anche i
\textit{patch} vengono compressi sia con \texttt{gzip} che con \texttt{xz}).

Una volta scaricati gli archivi si dovranno scompattare questi ultimi con
\texttt{tar} col procedimento lo stesso illustrato in
sez.~\ref{sec:install_tarball} per l'installazione dei sorgenti, ottenendo una
corrispondente directory \texttt{linux-4.9.35} nella directory corrente. In
genere si tende a mettere detti sorgenti in \texttt{/usr/src} ma nella
procedura di compilazione ed installazione niente obbliga a questa scelta, se
non il voler lasciare traccia delle versioni che si sono compilate in un posto
noto.

Un discorso diverso va fatto qualora si vogliano utilizzare i \textit{patch}
per eseguire un aggiornamento di una precedente installazione dei sorgenti.
Capire questa procedura è importante in quanto non riguarda soltanto il
passaggio da una versione di kernel alla successiva, ma anche l'applicazione
di \textit{patch} relativi all'installazione di funzionalità aggiuntive che
non sono ancora state incluse nei sorgenti del kernel ufficiale, ma delle
quali si voglia introdurre il supporto. Esistono infatti molte estensioni
rispetto al kernel cosiddetto ``\textit{vanilla}'', anche di grande interesse,
ma ancora sperimentali o molto specialistiche, che vengono mantenute al di
fuori dello sviluppo del kernel ufficiale.

Per questo occorre capire cos'è un ``\textit{patch}''. Il nome deriva proprio
dall'uso più comune, che è quello che li vedeva rilasciati per mettere delle
``\textsl{pezze}'' a programmi con errori o problemi di sicurezza. Si tratta
semplicemente di un file il cui contenuto è definito dalle differenze di due
file (in genere dei sorgenti di programmi, ma la cosa vale per qualunque file
di testo) che viene prodotto con il comando \index{comando!\texttt{diff}}
\texttt{diff}. In questo modo è possibile ottenere quali righe sono cambiate
da una versione all'altra e salvare su un file le sole differenze.  Si può
così passare da una versione di un programma alla successiva trasmettendo solo
le differenze nel relativo sorgente.

Il comando \texttt{diff} può inoltre essere eseguito ricorsivamente su due
intere directory, registrando le differenze sia per quanto riguarda i singoli
file che esse contengono, che per l'aggiunta o la rimozione di alcuni di essi.
Si può poi salvare il tutto su un unico file, ed è questo che ad esempio viene
distribuito come patch per passare da una versione stabile del kernel alla
successiva; un esempio del contenuto di un \textit{patch} è il seguente:
\begin{FileExample}
[...]
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 4
 PATCHLEVEL = 9
-SUBLEVEL = 35
+SUBLEVEL = 36
 EXTRAVERSION =
 NAME = Roaring Lionus 
[...]
\end{FileExample}
dove la prima riga indica qual'è file originale da cui si è partiti, mentre la
seconda la nuova versione. Si noti che si tratta di un pathname relativo, che
ha come origine la directory in cui si trovano i due diversi alberi (nel caso
denominati \texttt{a} e \texttt{b}) quando è stato eseguito il
\texttt{diff}. Le righe che iniziano per \verb|@@| indicano a quale riga nei
due file fanno riferimento i dati riportati di seguito, nel caso 7 righe del
primo file a partire dalla 12, che diventano 6 del secondo a partire sempre
dalla stessa riga. Le differenze sono mostrate apponendo un ``\texttt{+}''
alle righe aggiunte nel secondo file ed un ``\texttt{-}'' a quelle tolte.

% TODO trattare diff ed i vari formati

Con il comando \index{comando!\texttt{patch}} \texttt{patch} si può invece
compiere l'operazione inversa rispetto a \texttt{diff}, e cioè applicare ad un
certo file le differenze ottenute con il metodo precedente, in modo da
convertirlo nella nuova versione. La cosa può essere effettuata anche
ricorsivamente, su un intero albero di file e directory.  Così chi dispone sia
dei nuovi sorgenti del kernel 4.9.36 che di quelli della precedente versione
4.9.35 potrà generare un \textit{patch} con tutte le differenze.

Questo applicato da una persona ai sorgenti del kernel 4.9.35 li trasformerà
in quelli del 4.9.36.  L'utilità dei \textit{patch} è che in questo modo anche
chi cura la manutenzione di ulteriori funzionalità non presenti nei kernel
ufficiali potrà limitarsi a distribuire il \textit{patch} che contiene le
relative aggiunte e modifiche, così che un utente possa, se lo desidera,
applicarle senza dover scaricare tutto un nuovo albero dei sorgenti.

Il meccanismo è del tutto generale, ed inoltre il comando \texttt{patch} è
sufficientemente intelligente da essere in grado di applicare su uno stesso
albero anche più \textit{patch} distinti in successione, fintanto che questi
non vadano ad operare esattamente sulle stesse righe degli stessi file
eseguendo modifiche incompatibili fra di loro. Così diventa possibile,
applicando in successione più \textit{patch}, inserire nel kernel più
funzionalità aggiuntive, fintanto che queste non interferiscono fra loro. Allo
stesso modo è possibile passare da una versione di kernel ad un'altra che non
sia la successiva.

Come accennato il comando per applicare un \textit{patch} è appunto
\texttt{patch}. Nel caso più semplice, in cui si deve operare su un singolo
file, la sua sintassi è immediata, e si può eseguire il comando con un
qualcosa del tipo:
\begin{Example}
patch original patch.diff
\end{Example}
nel qual caso, a meno che non si sia specificata l'opzione \texttt{-b} (o
\texttt{-{}-backup}) per richiedere un backup, la nuova versione prenderà il
posto dell'originale.

Quando però si ha a che fare con un \textit{patch} che coinvolge più file
(come quelli che si applicano ad un albero di sorgenti) i nomi dei file cui
esso va applicato sono riportati nel file stesso, e non devono quindi essere
specificati; inoltre in questo caso il comando legge il contenuto del
\textit{patch} dallo \textit{standard input}, per cui occorre usare una
redirezione.

Per capire il funzionamento del comando conviene rifarsi all'esempio di
\textit{patch} mostrato in precedenza: il comando ricerca (a partire dalla
directory corrente) il file che considera la vecchia versione e cerca di
applicarvi le differenze. Il problema che ci si trova di fronte è che
normalmente si ha a disposizione solo la versione di partenza, che non è detto
si chiami \texttt{a}, e non quella di arrivo, ad esempio si potranno avere i
sorgenti del kernel 4.9.35 nella directory \texttt{linux-4.9.35} ma non ce ne
sarà una per quelli del 4.9.36.  Per questo motivo di solito bisogna dire al
comando da quale ``\textsl{livello}'' si vuole partire per applicare il
\textit{patch}, usando l'opzione \texttt{-p}.

Il livello 0 usa semplicemente l'uso dei pathname relativi specificati nel
\textit{patch} stesso, ma nel caso dell'esempio di \textit{patch} illustrato
in precedenza questo non può funzionare, in quanto il file di destinazione non
esiste e la directory di partenza è diversa. Se però, riprendendo il nostro
esempio, ci si pone direttamente dentro la directory \texttt{linux-4.9.35},
ignorando il primo livello di directory, tutti i pathname relativi verranno
risolti senza problemi. Per questo quello che si fa per applicare un
\textit{patch} sui sorgenti del kernel è qualcosa del tipo:
\begin{Example}
cd /usr/src/linux
patch -p1 < /path/to/patch/patch.diff
\end{Example}
e si otterrà la nuova versione del kernel nella directory corrente.

Si tenga presente che se non si specifica un livello, il default di
\texttt{patch} è di utilizzare solo il nome del file, ignorando le directory
presenti nei pathname relativi in esso contenuti, per cui in genere
l'applicazione fallirà. Se il comando non riesce ad applicare un
\textit{patch}, ad esempio perché se ne è già applicato uno incompatibile, o
si è sbagliato file, genererà automaticamente dei file terminanti in
\texttt{.rej} che contengono le modifiche che è stato impossibile
effettuare. Si può usare l'opzione \texttt{-{}-dry-run} per far eseguire una
prova senza modificare i file, facendosi stampare i risultati, in modo da
sapere se il \textit{patch} verrà applicato correttamente.

Inoltre \texttt{patch} è in grado di rilevare il caso in cui si è prodotto il
\textit{patch} invertendo le versioni, nel qual caso avvisa richiedendo il
permesso di applicare il \textit{patch} alla rovescia. Questo può essere
richiesto esplicitamente con l'opzione \texttt{-R} (o \texttt{-{}-reverse}).
Si tenga presente però che se si tenta di applicare uno stesso \textit{patch}
due volte ci si troverà proprio in questa situazione e proseguire
nell'applicazione non sarebbe corretto, per questo esiste l'opzione
\texttt{-N} (o \texttt{-{}-forward}) che indica di ignorare i \textit{patch}
che sembrano invertiti o già applicati.

Il comando \texttt{patch} prende molte altre opzioni ed è in grado di
utilizzare vari formati per i \textit{patch} ed anche di interagire
direttamente con vari programmi per il controllo di versione per identificare
quali sono i file su cui operare. Per tutti i dettagli sul funzionamento del
comando e sul significato delle opzioni si può al solito fare riferimento alla
pagina di manuale, accessibile con \texttt{man patch}.


\subsection{La ricompilazione del kernel}
\label{sec:kernel_compile}

Una volta scompattati i sorgenti ed applicati gli eventuali \textit{patch}
ritenuti opportuni, si può passare alla compilazione del kernel.  Questa, come
per la maggior parte dei pacchetti che si installano dai sorgenti, viene
eseguita tramite il comando \texttt{make}, ma non viene utilizzata la
procedura illustrata in sez.~\ref{sec:install_tarball} perché non vengono
usati gli \textit{autotools} e non esiste uno script di configurazione. Tutto
viene gestito con una procedura di costruzione specifica, controllata dal
\texttt{Makefile} principale presente nella base della directory dei sorgenti,
in cui le operazioni necessarie sono compiute invocando gli opportuni
\textit{target} del comando \texttt{make} (si ricordi quanto detto in
sez.~\ref{sec:install_tarball}).

Una delle caratteristiche di Linux (torneremo sull'argomento in dettaglio
anche in sez.~\ref{sec:kernel_modules}) è quella di essere
\textsl{modulare}. A differenza cioè di altri sistemi unix-like in cui il
kernel è un unico programma ``\textsl{monolitico}'', caricato in memoria
all'avvio del sistema ed in cui devono essere inserite tutte le funzionalità
che si vogliono usare, Linux può partire con un kernel contenente le sole
funzionalità di base e poi caricare da disco in maniera dinamica delle
ulteriori sezioni di codice, dette ``\textsl{moduli}'', per aggiungere
funzionalità aggiuntive o il supporto di dispositivi solo quando servono.

Questa è una delle caratteristiche più rilevanti di Linux, che gli permette
una flessibilità di utilizzo che i kernel monolitici tradizionali non hanno. É
possibile infatti modularizzare lo sviluppo del kernel separandone le
funzionalità, ed evitare mantenere permanentemente in memoria parti di codice
che sono utilizzate solo per limitati periodi di tempo (ad esempio il codice
per accedere a un CDROM occupa inutilmente memoria se non lo si sta
utilizzando). Inoltre si possono indicare opzioni specifiche per la gestione
di un dispositivo in fase di caricamento del modulo, e modificarle senza
bisogno di un riavvio (basta rimuoverlo e ricaricarlo con le nuove opzioni).

L'uso dei moduli ha pertanto una grande rilevanza e deve essere pianificato in
fase di compilazione e configurazione. Un primo aspetto dell'uso dei moduli è
che quando si usano diverse versioni del kernel devono essere usate le
corrispondenti versioni dei moduli. Ciò comporta che ogni kernel ha i suoi
moduli, che sono identificati come quest'ultimo dalla versione, quella che
viene mostrata dal comando \texttt{uname -r}.\footnote{in realtà come vedremo
  in sez.~\ref{sec:kernel_modules}, i moduli sono identificati soprattutto per
  la directory in cui sono mantenuti, che è \texttt{/lib/modules/`uname -r`}.}
Sorge allora un problema quando si vogliono ottenere due (o più) kernel
diversi a partire dagli stessi sorgenti, dato che in questo caso la versione
sarà la stessa.

Per risolvere questo problema è possibile definire una versione
``\textsl{personalizzata}''. La versione del kernel è indicata dai sorgenti,
ed è codificata nelle prime righe del \texttt{Makefile} principale, che per i
kernel ufficiali sono nella forma:
\begin{FileExample}[label=Makefile]
VERSION = 4
PATCHLEVEL = 9
SUBLEVEL = 36
EXTRAVERSION = 
\end{FileExample}
in cui si può notare la presenza della variabile \texttt{EXTRAVERSION}, che
serve appunto a specificare un ulteriore identificativo di versione, che
permetta di tenere separati kernel diversi (ad esempio per le opzioni di
compilazione che si sono scelte o per le \textit{patch} applicate) ottenuti a
partire dagli stessi sorgenti.

Nelle attuali versioni ufficiali \texttt{EXTRAVERSION} resta sempre non
definita,\footnote{questo non era vero per le release intermedie degli
  aggiornamenti delle serie 2.6.x.y, che hanno usato appunto questa variabile
  per marcare l'ultima cifra, e può non esserlo eventuali versioni mantenute
  indipendentemente da altri sviluppatori, che usano questa variabile per
  marcare le loro versioni.} è cura di chi esegue una ricompilazione definirla
adeguatamente, evitando di usare caratteri speciali, come lo spazio, che
possono essere interpretati negli script; il caso più comune è aggiungere un
``\texttt{-qualcosa}''. A partire dal kernel 2.6.x è prevista una opzione per
impostarla direttamente dall’interno del programma di configurazione e non è
più necessario modificare direttamente il \texttt{Makefile}.

\ifx\obsoletesection\undefined

\relax
\else
Le altre eventuali modifiche che si possono voler fare al \texttt{Makefile}
sono tutte molto specialistiche, ad esempio si potrebbe voler cambiare la
variabile \texttt{CROSS\_COMPILE}, che viene usata per compilare kernel per
una architettura diversa dalla propria (ad esempio un kernel per PowerPC su
una macchina Intel), oppure le opzioni per le ottimizzazioni del \texttt{gcc},
che è meglio lasciar stare al valore di default, che è sicuro, a meno di non
sapere esattamente quello che si sta facendo, o essere in vena di
sperimentazione.
\fi

Un secondo aspetto dell'uso dei moduli che occorre tener presente è che per
poterli utilizzare occorre anzitutto poter caricare in memoria il loro codice;
il che significa che si deve essere in grado di usare i relativi file
``\textsl{oggetto}'',\footnote{un file oggetto, in genere identificato
  dall'estensione \texttt{.o}, è un file che contiene il codice compilato di
  una o più funzioni in cui però gli indirizzi non sono stati assegnati; in
  questo modo, attraverso un procedimento successivo detto
  \textsl{collegamento} (in inglese \textit{linking}) si possono unire insieme
  più funzioni per dar luogo a quello che poi andrà a costituire un
  eseguibile; questo è anche quello che si fa quando si produce l'immagine del
  kernel, e l'uso dei moduli consente di ripetere il procedimento sul codice
  degli stessi per metterli in esecuzione nel kernel.}  dato che questi non
sono altro che codice come quello dei programmi ordinari, anche se un po'
particolare. A partire dalla serie 2.6.x, per distinguerli dai file oggetto
dei normali programmi, è stata adottata l'estensione \texttt{.ko} al posto di
\texttt{.o}, ma si ricordi che l'estensione in Unix è solo una convenzione,
nel caso conta solo il contenuto.

L'uso dei moduli comporta però che le funzionalità necessarie ad accedere al
supporto su cui si trovano questi file non possono essere ottenute in forma
modulare e dovranno essere inserite all'interno del kernel in maniera
\textsl{monolitica}.  Per capire quali sono queste funzionalità occorre
ricordare quali sono i due compiti di base eseguiti dal kernel all'avvio:
montare la directory radice ed eseguire il programma di inizializzazione di
sistema (in genere \texttt{/sbin/init}).

\itindbeg{kernel~panic}

Per il primo compito occorre il supporto per accedere al dispositivo su cui si
trova la radice e quello per il relativo filesystem, per il secondo il
supporto per l'uso del formato binario di esecuzione dei programmi. Quanto
necessario a svolgere questi due compiti, anche se modularizzabile, dovrà
comunque essere inserito permanentemente nel kernel, pena il fallimento
dell'avvio con un ``\textit{kernel panic}'', vale a dire con un crash fatale
del kernel, che comporta il blocco completo della macchina. Questo può
avvenire per errori fatali durante l'esecuzione dello stesso (in caso di bug
particolarmente gravi, molto rari, o di problemi hardware, assai meno rari),
oppure come nel caso in questione, se mancano delle componenti essenziali per
l'avvio del sistema.

\itindend{kernel~panic}

A parte le eventuali modifiche manuali della \texttt{EXTRAVERSION}, il primo
passo necessario per la compilazione del kernel è quello della configurazione,
in cui si scelgono quali funzionalità attivare e quali no, quali mettere
direttamente dentro il kernel, e quali utilizzare come moduli. Una volta che
si sia specificato quanto voluto, il kernel verrà costruito di conseguenza.

Tutto questo viene fatto, dal punto di vista della compilazione e della
costruzione del kernel, tramite il contenuto del file \texttt{.config}, sempre
mantenuto nella directory base dei sorgenti, dove sono memorizzate tutte le
opzioni di configurazione. Un estratto del contenuto di questo file è il
seguente:
\begin{FileExample}[label=.config]
#
# Automatically generated file; DO NOT EDIT.
# Linux/x86 4.9.36 Kernel Configuration
#
CONFIG_64BIT=y
CONFIG_X86_64=y
CONFIG_X86=y
...
CONFIG_INIT_ENV_ARG_LIMIT=32
CONFIG_CROSS_COMPILE=""
# CONFIG_COMPILE_TEST is not set
...
\end{FileExample}

Le opzioni di configurazione sono tutte dichiarate come variabili nella forma
\texttt{CONFIG\_\textsl{QUALCOSA}}; se non in uso sono commentate con un
\texttt{\#}, quelle attivate sono assegnate ad un valore. La gran parte delle
opzioni fa riferimento a funzionalità modularizzabili, ed in tal caso sono
possibili soltanto due valori, ``\texttt{y}'' che richiede l'inclusione
diretta del codice nel binario del kernel, ed o ``\texttt{m}'', che richiede
la compilazione come modulo esterno. Per le altre che attengono a proprietà
generali possono essere usati anche dei valori specifici (in forma di stringa
o numero) anche se molte prevedono soltanto il valore ``\texttt{y}'', che
indica semplicemente l'attivazione della funzionalità controllata.

Come scritto in testa all'estratto illustrato in precedenza, il file
\texttt{.config} non deve essere scritto a mano, ma opportunamente generato,
dato che, a meno di non sapere esattamente quello che si sta facendo, si
rischia di attivare opzioni incompatibili fra di loro o inconsistenti. Per
questo la generazione di questo file viene eseguita invocando \texttt{make}
con uno dei \textit{target} di configurazione. Senza la presenza di questo
file non è possibile passare alla compilazione del kernel.

Il primo \textit{target} di configurazione possibile è \texttt{config}; questo
avvia uno script di shell che effettua la configurazione chiedendo di
immettere sul terminale uno per uno i valori da assegnare alle varie opzioni
che si vogliono attivare. Ovviamente eviterà di eseguire ulteriori domande
qualora non si attivi una opzione che le prevede, ma il procedimento è
comunque molto scomodo in quanto non esiste un meccanismo per correggere una
impostazione una volta che si sia fatto un errore, per cui occorre
ricominciare da capo.

Pertanto è oggi praticamente in disuso, a parte per una sua versione
modificata, invocabile con il \textit{target} \texttt{oldconfig}, che si
limita a rileggere e riprocessare il file di configurazione precedente
ricavando da questo, invece che dalle nostre risposte sul terminale, le
risposte alle domande. Questo può risultare utile qualora si siano effettuate
modifiche a mano del file \texttt{.config} e si voglia essere sicuri di
ottenere un file di configurazione coerente.

Gli altri \textit{target} di configurazione più usati sono \texttt{menuconfig}
e \texttt{xconfig} che attivano invece due interfacce utente, testuale la
prima e grafica la seconda, con finestre e menu che permettono di selezionare
interattivamente le varie opzioni ed effettuare le relative scelte in maniera
casuale, senza serializzare le domande. Le due interfacce, a parte
l'apparenza, sono sostanzialmente equivalenti, per cui tratteremo solo la
prima. A partire dal kernel 2.6.x le interfacce grafiche sono diventate 2: la
prima, sempre accessibile con \texttt{make xconfig} è basata sulle librerie
QT, la seconda, accessibile con \texttt{make gconfig}, è basata sulle librerie
GTK; nelle versioni più recenti esiste anche una interfaccia testuale
alternativa, ottenibile con \texttt{make nconfig}.

Eseguendo \texttt{make menuconfig} nella directory dei sorgenti del kernel si
otterrà la pagina di avvio del programma di configurazione, mostrata in
fig.~\ref{fig:kernel_menuconfig1}. In genere il programma viene compilato la
prima volta che si esegue il comando, che si basa sulle librerie
\textit{ncurses}. Di norma queste vengono installate, ma non altrettanto
avviene per i file di dichiarazione necessari alla compilazione (si ricordi
quanto detto in sez.~\ref{sec:install_tarball}), nel qual caso per far
funzionare il comando andrà installato il relativo pacchetto di sviluppo e
tutte le sue dipendenze.\footnote{le librerie \textit{ncurses} sono presenti
  in tutte le distribuzioni, per cui è sempre il caso di usare i relativi
  pacchetti, per Debian sono \texttt{ncurses} e \texttt{libncurses-dev}.}

\begin{figure}[!htb]
\centering
\includegraphics[scale=0.5]{images/menuconfig1} 
\caption{Schermata di avvio della configurazione del kernel con \texttt{make
    menuconfig}.}
\label{fig:kernel_menuconfig1}
\end{figure}

La finestra di avvio riporta nella prima riga in alto la versione del kernel,
se si è modificata la \texttt{EXTRAVERSION} questa dovrà comparire. Subito
sotto c'è il titolo della sezione in cui ci si trova (nel caso è il menu
principale), seguito da un breve riassunto dei principali comandi disponibili.
Le frecce verticali permettono di spostarsi nella finestra centrale che
contiene le varie sezioni in cui sono state suddivise le opzioni di
configurazione. Nella parte bassa ci sono le opzioni principali che permettono
di selezionare una opzione, uscire dalla finestra corrente e ottenere una
finestra di aiuto (contestuale all'opzione selezionata), che possono essere
cambiate con le frecce orizzontali.

Dal menu principale è possibile selezionare una sezione premendo invio (a meno
di non aver cambiato l'opzione di selezione), e questo ci porterà nella
finestra di configurazione delle relative opzioni, un esempio della quale è
mostrato in fig.~\ref{fig:kernel_menuconfig2}. I valori delle opzioni sono
riportati all'inizio di ogni riga, quelli indicati fra parentesi tonde sono
per le opzioni che richiedono un valore generico, che può essere selezionato
da un menu a tendina o inserito da una finestra di immissione che si attiva
quando l'opzione viene selezionata.

\begin{figure}[!htb]
\centering
\includegraphics[scale=0.5]{images/menuconfig2}
\caption{Schermata di configurazione del kernel con \texttt{make menuconfig}.}
\label{fig:kernel_menuconfig2}
\end{figure} 

I valori fra parentesi quadre indicano le opzioni per le quali è possibile
solo scegliere fra l'attivazione o meno e la scelta può essere fatta premendo
il tasto ``\texttt{y}'' per attivare e ``\texttt{n}'' per disattivare,
premendo la barra si può ciclare fra le due opzioni. Un asterisco indica che
la funzionalità è attivata, uno spazio vuoto che non è attivata. Si tenga
presente che se si tratta del supporto per funzionalità specifiche del kernel
questo implica che il relativo codice sarà incluso monoliticamente, molte di
queste opzioni però servono anche per attivare ulteriori configurazioni o
specificare caratteristiche di un'altra opzione (che può anche essere
modulare), nel qual caso le successive descrizioni appariranno indentate.

I valori fra parentesi angolari indicano invece le opzioni relative a
funzionalità che possono essere anche modularizzate; rispetto alle precedenti
possono presentare anche il valore ``\texttt{M}'' (attivabile direttamente
premendo ``\texttt{m}'' o ciclando fra i valori possibili con la barra) che
indica che si è optato per la creazione del relativo modulo, se invece si ha
un ``\texttt{*}'' la funzionalità sarà inserita direttamente nel
kernel. Talvolta questi caratteri si trovano fra parentesi graffe o fra
trattini per indicare che le rispettive opzioni sono state attivate a causa di
una scelta effettuata altrove. 

Infine per alcune sezioni sono presenti delle ulteriori sottosezioni (sono
indicate dalla assenza del valore delle opzioni e dal fatto che terminano con
una freccia, come nel menu principale).  Una volta che si sono effettuate le
proprie scelte selezionando la voce di uscita si può tornare al menu
precedente, se si è già nel menu principale invece si uscirà direttamente dal
programma di configurazione, e comparirà una finestra che richiede se si vuole
che le nuove configurazioni siano salvate sovrascrivendo un nuovo
\texttt{.config}, o scartate.

Due opzioni specifiche per il menu principale sono poi quelle disponibili
separatamente in fondo allo stesso, che permettono di salvare i valori della
configurazione su, o caricarli da, un file specificabile dalla solita riga di
immissione dei dati. Questo può comunque essere ottenuto con delle semplici
copie del file \texttt{.config}.

Data la quantità (molte centinaia) di opzioni disponibili non è possibile
commentarle tutte, pertanto ci limiteremo ad una descrizione sommaria del
contenuto delle varie sezioni del menu principale. Queste sono state
completamente riorganizzate nel passaggio dal kernel 2.4.x al 2.6.x, ed
inoltre nel corso dello sviluppo ne state aggiunte delle altre; alla stesura
di questo testo\footnote{la revisione è dell'Agosto 2017, e fa riferimento al
  kernel 4.9.36.} erano disponibili:

\begin{basedescript}{\desclabelwidth{1.5cm}\desclabelstyle{\nextlinelabel}}
\item[General setup] Questa è la sezione dove si attivano le opzioni di
  configurazione generali; qui si può impostare la \textit{extraversion} del
  kernel (con ``\texttt{Local version - append to kernel release}''). %  e le
  % opzioni che consentono la visualizzazione di altre opzioni specialistiche
  % come ``\texttt{Prompt for development and/or incomplete code/drivers}'' che
  % permette di attivare tutte le opzioni che sono classificate come
  % sperimentali o ``\texttt{Configure standard kernel features (for small
  %   systems)}'' che permette di eseguire ulteriori configurazioni per i
  % sistemi con poche risorse. In particolare è sempre opportuno abilitare
  % ``\texttt{Prompt for development and/or incomplete code/drivers}'' prima di
  % iniziare una configurazione in quanto buona parte delle opzioni sperimentali
  % sono ampiamente utilizzate e perfettamente funzionanti; le opzioni
  % ``\textsl{pericolose}'' vengono adeguatamente segnalate nelle relative
  % descrizioni.
  Inoltre sono presenti in questa sezione le opzioni per il supporto per
  alcune funzionalità fornite dal kernel, come i meccanismi di
  intercomunicazione fra processi, il controllo e la suddivisione delle
  risorse,\footnote{come i \textit{control group} (\texttt{Control Group
      support}) e varie funzionalità (\texttt{Namespace support}) utilizzate
    per il supporto ai cosiddetti \textit{container}, una tecnologia che
    consente di eseguire macchine virtuali all'interno di \textsl{contenitori}
    forniti dal sistema, senza dover eseguire una virtualizzazione
    dell'hardware.} e vari supporti per tecnologie di debug, profilazione e
  controllo delle prestazioni. Infine vanno esplicitamente ricordate due
  opzioni molto importanti per il funzionamento del sistema: il supporto per
  il \textit{ramdisk} iniziale (vedi sez.~\ref{sec:kernel_install}) con
  l'opzione ``\texttt{Initial RAM filesystem and RAM disk (initramfs/initrd)
    support}'' e per la \textit{swap} (vedi
  sez.~\ref{sec:swap_CDROM_management}) con l'opzione ``\texttt{Support for
    paging of anonymous memory (swap)}''.

\item[Enable loadable module support] In questa sezione si attivano le opzioni
  per abilitare la gestione dei moduli ed il relativo supporto nel kernel. In
  generale si possono attivare tutte, mentre si possono disattivare quelle che
  introducono dei controlli di versione per i moduli, in particolare quella
  relativa ai sorgenti. In generale è utile mantenere attiva quella marcata
  ``\texttt{Module versioning support}'' per evitare che vengano caricati per
  errore moduli compilati per un'altra versione del kernel non compatibile;
  questo può comportare problemi qualora si vogliano utilizzare moduli
  compilati a parte o distribuiti in forma binaria. Nel 2.4 il meccanismo
  funzionava aggiungendo una \textit{checksum} a tutti i nomi dei simboli del
  kernel, cosicché le relative funzioni possono essere chiamate solo
  all'interno dello stesso kernel, nel 2.6 questa informazione viene mantenuta
  a parte e può essere ignorata.

\item[Enable the block layer] Questa sezione contiene le opzioni relative alla
  gestione generica dei dispositivi a blocchi che deve essere sempre inserita
  nel kernel perché il sistema possa funzionare (deve poter montare la
  radice). Qui si trovano in questa sezione anche le opzioni relative ai
  diversi \textit{scheduler} (\texttt{IO schedulers}) usabili per ottimizzare
  l'I/O su disco. Il kernel è in grado di utilizzare diverse strategie per
  organizzare l'accesso a disco in maniera ottimale da parte di diversi
  processi, queste possono essere stabilite in fase di avvio ed il default può
  essere impostato con l'opzione ``\texttt{Default I/O scheduler}'', presente
  in questa sezione.

\item[Processor type and features] Questa sezione contiene le opzioni relative
  alla scelta del tipo di CPU presente, con le opzioni per il supporto di vari
  insiemi di istruzioni estese (come ``\texttt{MTRR (Memory Type Range
    Register) support}''), ai vari tipi di timer usati dal sistema, la
  frequenza dello stesso (``\texttt{Timer frequency}''). Di particolare
  importanza è poi l'opzione per il ``\texttt{Symmetric multi-processing}''
  che consente l'uso di macchine multiprocessore, e quelle
  (``\texttt{Preemption Model}'') che controllano le modalità di gestione
  dello \textit{scheduler} dei processi a seconda del tipo di utilizzo.
  Sempre qui vanno attivate una serie di opzioni relative alla gestione della
  memoria, come quelle per l'uso di grandi quantità di memoria (``\texttt{High
    Memory Support}'') quando si ha più di 1Gb su macchine a 32 bit o il
  ``\texttt{Transparent Hugepage Support}'' per l'uso automatico di pagine di
  memoria di maggiori dimensioni che riducano la frammentazione della
  stessa.%  Si trovano qui anche alcune opzioni di supporto per essere eseguito
  % come ospite in una macchina virtualizzata (``\texttt{Paravirtualized guest
  %   support}'').

\item[Power management options and ACPI options] Questa sezione contiene tutte
  le opzioni relative al supporto delle funzionalità di risparmio energetico e
  di gestione dell'alimentazione, spegnimento, sospensione su disco ed in RAM
  ecc. È qui che si configura il supporto per l'ACPI (``\texttt{Advanced
    Configuration and Power Interface}'') e per tutte le opzioni di controllo
  delle modalità di risparmio energetico del processore o della memoria.

\item[Bus options (PCI etc.)] Questa sezione contiene tutte le opzioni di
  configurazione relative a vari bus hardware (vedi
  sez.~\ref{sec:interfaces_peripherals}) supportati da Linux, come PCI,
  PCMCIA, ecc. Sono di particolare importanza le opzioni relative al bus PCI
  che devono essere sempre inserite all'interno del kernel in quanto questo è
  il bus usato dalla quasi totalità dei computer odierni per accedere alle
  periferiche principali (dischi, scheda video, schede sonore, ecc.), ed è
  pertanto necessario per poter accedere ai dischi e montare la radice.

\item[Executable file formats] Questa sezione contiene le opzioni relative al
  supporto per i formati binari dei file che il kernel è in grado di eseguire
  come programmi. Il supporto per il formato ELF deve essere sempre abilitato
  nel kernel (altrimenti sarà impossibile eseguire \texttt{/sbin/init}), gli
  altri possono essere abilitati come moduli.

\item[Networking support] Questa sezione contiene le sottosezioni relative al
  supporto delle varie tecnologie di rete, wireless, infrarossi,
  \textit{bluetooth}, CAN, ecc. per ciascuna delle quali occorre abilitare
  (anche come moduli) le funzionalità necessarie. Di particolare importanza è
  poi, raccolto nella sottosezione ``\texttt{Networking options}'', il
  supporto per i vari protocolli di rete ed ai diversi tipi di socket e le
  funzionalità relative al filtraggio dei pacchetti (``\texttt{Network packet
    filtering}'') ed al routing avanzato; in questa sottosezione sono da
  attivare ``\texttt{TCP/IP networking}'', ``\texttt{Packet socket}'' e
  ``\texttt{Unix domain sockets}'', per gli ultimi due è possibile farlo anche
  in maniera modulare.  Oltre a questi si può poi abilitare il supporto per
  tutta una serie di altri protocolli di rete o estensioni dei protocolli
  standard come IPSEC.

\item[Device Drivers] Questa è la sezione più corposa e più importante in
  quanto contiene le opzioni di configurazione per tutti vari tipi di
  periferiche che si possono utilizzare con Linux; tratteremo separatamente in
  coda a questa panoramica sulle opzioni del menu principale le varie
  sottosezioni in cui essa è suddivisa.

\item[Firmware Drivers] Questa sezione, relativamente recente, contiene le
  opzioni per il supporto di alcune interfacce di comunicazione con il
  \textit{firmware} (il BIOS o alternative) della propria macchina.

\item[File systems] Questa sezione contiene le opzioni per il supporto di un
  gran numero di diversi filesystem. Si deve essere sicuri di inserire nel
  kernel il supporto per il filesystem della radice, qualunque esso sia (i più
  usati sono i vari \textit{extN}, \textit{reiserfs} e XFS). Qui si può anche
  abilitare, da altrettante sotto-sezioni, il supporto per i filesystem di
  CDROM e DVD, e per i vari filesystem di Windows. É sempre opportuno
  abilitare il supporto per il filesystem \texttt{/proc} (che è usato da
  moltissimi programmi) nella sotto-sezione ``\texttt{Pseudo
    filesystems}''. Una sotto-sezione a parte (``\texttt{Network File
    Systems}'') è dedicata ai filesystem di rete (NFS, SMB ed altri), dove può
  essere configurato il relativo supporto. Infine si trovano in questa sezione
  anche le opzioni relative alla gestione delle quote disco (vedi
  sez.~\ref{sec:disk_quota}), dell'\textit{automounter} (vedi
  sez.~\ref{sec:automounter}), dei vari meccanismi di notifica delle modifiche
  dei file principalmente ad uso dei programmi ad interfaccia grafica, ed il
  supporto per la realizzazione di filesystem in user-space (FUSE).

\item[Kernel hacking] Questa sezione contiene le opzioni per la configurazione
  del supporto di una lunga serie di funzionalità di controllo utilizzate
  principalmente dagli sviluppatori per il debug del kernel. Può essere utile
  abilitare l'opzione ``\texttt{Magic SysRq key}'' che permette l'uso di
  particolari combinazioni di tasti (a partire appunto da \textit{SysRq}) per
  tentare un recupero in estremo dei dati in caso di crash del kernel.

\item[Security options] Questa sezione contiene le opzioni relative alle
  infrastrutture di sicurezza (come \textit{SELinux}, \textit{Tomoyo},
  \textit{AppArmor} o eventuali altri moduli che consentono di supportare
  diverse politiche di sicurezza) che possono essere attivate all'interno del
  kernel. É qui che si sceglie quale di questi moduli deve essere usato di
  default.

\item[Cryptographic API] Questa sezione contiene le opzioni per il supporto di
  vari algoritmi crittografici all'interno del kernel, compreso l'eventuale
  supporto hardware per alcuni di questi. In genere viene utilizzato per
  supportare filesystem e protocolli di rete cifrati. Sono inserite in questa
  sezione anche le opzioni per abilitare gli algoritmi di compressione.

\item[Virtualization] Questa contiene le opzioni di configurazione per il
  supporto di varie tecnologie di virtualizzazione dell'hardware con cui
  diventa possibile fare eseguire dal kernel un altro sistema operativo a
  velocità nativa, creando opportunamente una \textsl{macchina virtuale} sia
  in termini di emulazione del processore che di alcuni dispositivi.

\item[Library routines] Questa sezione contiene le opzioni per la
  configurazioni di alcune funzioni di libreria usate dal kernel per lo più
  per calcoli di somme di controllo.
\end{basedescript}

Il precedente elenco riporta solo un breve sommario dei contenuti delle varie
sezioni in cui sono state suddivise le varie opzioni nel menu principale del
programma di configurazione del kernel. Come accennato però la sezione
``\texttt{Device Drivers}'' ha una rilevanza particolare in quanto è al suo
interno che si trovano la maggior parte delle opzioni di configurazione.

Detta sezione infatti è divisa in un gran numero di ulteriori sottosezioni,
relative alle varie tipologie di dispositivi che il kernel è in grado di
supportare, compresi molti ormai ormai obsoleti e non più disponibili su
hardware recente.  Data la rilevanza si è deciso di riportare di seguito anche
una breve descrizione delle principali sottosezioni in essa contenute:

\begin{basedescript}{\desclabelwidth{1.5cm}\desclabelstyle{\nextlinelabel}}

\item[Generic Driver Options] Contiene le opzioni generali relative alla
  gestione dei driver, in particolare il supporto per il caricamento dei
  firmware sulle periferiche e la creazione di un contenuto minimo per
  \texttt{/dev} ad uso di emergenza, disponibile anche senza la presenza di
  \textit{udev} (vedi sez.~\ref{sec:udev_hotplug}). Consentiva anche
  l'indicazione, ora deprecata, del programma da utilizzare per la gestione
  degli eventi generati dal kernel che nelle versioni recenti vengono gestiti
  da \textit{udev}.

\item[Memory Technology Devices (MTD) support] Questa sezione contiene le
  opzioni relative ai supporti di memoria opzionali come flash, memorie a
  stato solido ecc. Vengono utilizzate prevalentemente nei sistemi embedded,
  ancorché alcune di queste stanno trovando uso anche in sistemi ordinari
  dotati di dischi a stato solido.

\ifx\obsoletesection\undefined

\relax
\else
\item[Parallel port support] Questa sezione contiene le opzioni relative al
  supporto per la porta parallela, necessarie per poter utilizzare i
  dispositivi (ad esempio una stampante) ad essa collegati. Può essere
  completamente modulare ed è in disuso per la sempre minore diffusione di
  questa interfaccia.

\item[Plug and Play support] Questa sezione contiene le opzioni per abilitare
  il supporto all'uso del \textit{Plug and Play} per le schede che lo
  supportano (vedi sez.~\ref{sec:expansions_interface}). Riguarda hardware
  ormai praticamente scomparso e può essere completamente
  modulare.\label{sec:page_PnP}

\item[ATA/ATAPI/MFM/RLL support] Questa sezione contiene le opzioni per il
  supporto del bus IDE/ATA tradizionale (detto talvolta anche \textit{Parellel
    ATA}), e di tutti i relativi dispositivi (dischi, CDROM, ecc.). Questa
  sezione fa riferimento al supporto classico del bus IDE e non al nuovo
  supporto tramite \textit{libata}, la cui configurazione si effettua nella
  successiva sezione ``\texttt{Serial ATA and Parallel ATA drivers}'' e nei
  kernel più recenti è deprecata. Qualora si utilizzi questa modalità di
  supporto e la radice sia su un disco IDE occorrerà abilitarla ed inserirla
  direttamente nel kernel, inoltre al suo interno occorrerà abilitare le due
  opzioni ``\texttt{generic/default IDE chipset support}'' e ``\texttt{generic
    ATA/ATAPI disk support}'', oltre al supporto specifico per il proprio
  chipset; tutto il resto può essere modulare. Si può lasciare attivo
  ``\texttt{Generic PCI IDE Chipset Support}'' che permette l'avvio con un
  supporto generico. Questo supporto è però in dismissione e la sezione è
  deprecata, in quanto tutto quello che non è relativo ad hardware in disuso è
  già stato trasferito nella nuova sezione citata.
\fi

\item[Block devices] Questa sezione contiene le opzioni per abilitare il
  supporto di una serie di dispositivi a blocchi (i floppy, vari
  \textit{disk-array} e RAID hardware, i \textit{ramdisk} e il
  \textit{loopback}). A meno di non avere la radice su uno di questi
  dispositivi il supporto può essere modulare. A parte il supporto per i
  sempre meno comuni floppy (con ``\texttt{Normal floppy disk support}'') le
  funzionalità più usate sono quelle relative ai dischi in RAM (``\texttt{RAM
    block device support}'') e al dispositivo di \textit{loopback}
  (``\texttt{Loopback device support}'') già visto in
  sez.~\ref{sec:file_disk_management}), in particolare se si usa un meccanismo
  di avvio che utilizza un \textit{ramdisk} un occorrerà inserire
  ``\texttt{RAM block device support}'' all'interno del kernel. Si configurano
  qui anche il dispositivo a blocchi virtuale ad uso di macchine virtualizzate
  (``\texttt{Virtio block driver}'') ed il RAID via rete con DRBD
  (``\texttt{DRBD Distributed Replicated Block Device support}'').

\item[Misc devices] Questa sezione contiene le opzioni relative ad una
  miscellanea di dispositivi diversi, molti dei quali relativi al supporto di
  funzionalità presenti su specifiche macchine (in genere portatili); può
  essere completamente modulare.

\item[SCSI device support] Questa sezione contiene le opzioni per il supporto
  dei dispositivi SCSI (come dischi, CDROM, nastri), del relativo protocollo,
  e dei vari controller. L'opzione ``\texttt{SCSI support}'' deve essere
  abilitata anche se non si hanno dispositivi SCSI in quanto il protocollo
  viene usato da altri sistemi, come i programmi per la masterizzazione (che
  usano l'emulazione IDE-SCSI) e le chiavette e i dischi esterni USB o i
  dischi \textit{Serial ATA} (che usano il protocollo SCSI per accedere ai
  dati). Se si ha la radice su un disco SCSI tutto tranne ``\texttt{SCSI
    device support}'', ``\texttt{SCSI disk support}'' ed il supporto per il
  proprio controller può essere modulare.  Nella sottosezione ``\texttt{SCSI
    low-level drivers}'' si può poi selezionare il supporto per i vari tipi di
  controller.

\item[Serial ATA and Parallel ATA drivers] Questa sezione contiene le opzioni
  per il supporto dei nuovi dispositivi \textit{Serial ATA}, e, con le
  versioni più recenti del kernel, anche quello per alcuni dispositivi che
  usano l'interfaccia IDE/ATA tradizionale (il cosiddetto \textit{Parallel
    ATA}); in quest'ultimo caso questo supporto va a sostituire quello della
  sezione ``\texttt{ATA/ATAPI/MFM/RLL support}'' che è deprecata. Se si ha la
  radice su questo tipo di dispositivi, oltre a quello dello specifico chipset
  della propria scheda madre, occorre anche abilitare il supporto SCSI per i
  dischi (le due opzioni ``\texttt{SCSI device support}'', ``\texttt{SCSI disk
    support}'' della precedente sezione), dato che in questo caso i dischi
  vengono gestiti con il protocollo SCSI (si ricordi quanto illustrato in
  sez.~\ref{sec:disk_structure}). Se la radice è su uno di questi dispositivi
  occorrerà inserire nel kernel il relativo supporto.

\item[Multiple device driver support (RAID and LVM)] Questa sezione contiene
  le opzioni per abilitare il supporto del RAID software (vedi
  sez.~\ref{sec:disk_RAID}) e del \textit{Logical Volume Manager} (vedi
  sez.~\ref{sec:disk_LVM}) ed in generale del sistema del \textit{device
    mapper} che consente una serie di funzionalità avanzate (come l'uso di
  dischi cifrati). A meno di non avere la radice su uno di questi dispositivi
  il supporto può essere modulare. É presente in questa sezione anche il
  supporto per il \textit{multipath} che consente di accedere tramite diversi
  nomi agli stessi dispositivi (ad uso dei dispositivi SAN).

% \item[Fusion MPT device support] Questa sezione contiene le opzioni di
%   configurazione per una scheda \textit{LSI Logic Fusion}.

% \item[IEEE 1394 (Firewire) support] Questa sezione contiene le opzioni per il
%   supporto delle interfacce e dei protocolli per il bus IEEE 1394 (il
%   cosiddetto \textit{firewire}), un bus seriale veloce simile all'USB, usato
%   sia per utilizzare dischi rimuovibili esterni che per la trasmissione dati
%   da periferiche (viene usato principalmente per le telecamere).

% \item[I2O device support] Questa sezione contiene le opzioni per il supporto
%   del bus di comunicazione I2O usato per la comunicazione a basso livello fra
%   i vari dispositivi presenti sulla scheda madre.

% \item[Macintosh device drivers] Questa sezione contiene le opzioni per il
%   supporto di alcune funzionalità specifiche ad uso delle macchine
%   \textit{Macintosh} prodotte dalla \textit{Apple} (come l'emulazione dei
%   tasti mancanti sul mouse).

\item[Network device support] Questa sezione contiene le opzioni di
  configurazione per le varie schede di rete utilizzabili con Linux (sia
  Ethernet che di altro tipo), più il supporto per alcuni protocolli di
  comunicazione di basso livello (PPP, SLIP, ecc.) e dispositivi virtuali. Il
  supporto può anche essere modulare, a meno di non avere la radice su un
  filesystem di rete. Questa è una delle sezioni più ampie ed è suddivisa in
  una lunga serie di sottosezioni relative ai vari driver disponibili.

% \item[Amateur Radio support] Questa sezione contiene le opzioni per la
%   configurazione del protocollo AX.25, detto anche \textit{Packet radio},
%   usato dai radioamatori per la trasmissione dati via radio.

% \item[IrDA (infrared) support] Questa sezione contiene le opzioni per il
%   supporto dei dispositivi di comunicazione ad infrarossi (le porte IrDA). 

% \item[ISDN support] Questa sezione contiene le opzioni per il supporto dei
%   dispositivi ISDN e dei relativi protocolli.

% \item[Telephony support] Questa sezione contiene le opzioni relative al
%   supporto di schede telefoniche dedicate, che consentono di telefonare
%   direttamente dal computer, ed usare questo come ponte fra linea telefonica
%   normale e VoIP.

% \item[Old CD-ROM drivers] Questa sezione contiene le opzioni per il supporto
%   dei vecchi CDROM pilotati direttamente dalla schede audio. Ampiamente in
%   disuso.

\item[Input device support] Questa sezione contiene le opzioni per il supporto
  per mouse, tastiere, joystick ed altri dispositivi analoghi.

\item[Character devices] Questa sezione contiene le opzioni di configurazione
  per una lunga serie di dispositivi a caratteri. Qui è essenziale l'opzione
  per il supporto del terminale sullo schermo (``\texttt{Virtual terminal}'')
  che serve per poter disporre all'avvio della \textit{console} di
  sistema.\footnote{è il supporto per i terminali su \textit{console}, che
    consente di usare i dispositivi \texttt{/dev/tty1}, \texttt{/dev/tty2},
    ecc.} É sempre in questa sezione che si abilita il supporto per le porte
  seriali nella sottosezione ``\texttt{Serial drivers}'', e se si vuole la
  \textit{console} sulla porta seriale si deve abilitare all'interno di questa
  l'opzione ``\texttt{Console on 8250/16550 and compatible serial port}'', ed
  il supporto dei terminali virtuali (quelli usati da tutti i programmi che
  emulano un terminale) con l'opzione ``\texttt{Unix98 PTY support}''.

% Qui può essere abilitato il supporto per la stampante su
  % parallela (``\textbf{Parallel printer support}'') ed il supporto per
  % l'orologio in tempo reale (``\textbf{Enhanced Real Time Clock Support}'').

\item[Hardware Monitoring support] Questa sezione contiene le opzioni relative
  al supporto dei dispositivi di controllo di funzionamento dell'hardware
  presenti sulle schede madri moderne (ad esempio i sensori di temperatura).

\item[Multimedia support] Questa sezione contiene le opzioni di configurazione
  di \textit{Video For Linux}, l'infrastruttura del kernel per i dispositivi
  video, che comprende il supporto per l'utilizzo di schede TV, schede di
  acquisizione video, webcam ed anche quello delle schede di sintonizzazione
  radio.

\item[Graphics support] Questa sezione contiene le opzioni per il supporto di
  funzionalità relative alla grafica: l'uso del bus AGP
  (``\texttt{/dev/agpgart (AGP Support)}''), il supporto (``\texttt{Direct
    Rendering Manager}'') per il DRI (\textit{Direct Rendering
    Infrastructure}) di X11, l'interfaccia di accesso a basso livello alle
  funzionalità di accelerazione delle schede grafiche (vedi
  sez.~\ref{sec:cfg_Xserver}), il supporto per i framebuffer e per la
  \textit{console} sia su VGA che su framebuffer, come avviene per le macchine
  che non usano la VGA, come gli Apple, quello per i vari display montati
  sulle macchine e per il logo all'avvio.


% \item[Console drivers] Questa sezione contiene le opzioni per il supporto di
%   tutta una varietà di diversi dispositivi a caratteri. Di norma basta
%   configurare solo l'opzione \textbf{VGA text console}, a meno di non avere
%   necessità del framebuffer (come avviene per le macchine che non usano la
%   VGA, come gli Apple).

\item[Sound card support] Questa sezione contiene le opzioni relative al
  supporto delle schede audio per Linux, sono presenti due sottosezioni,
  relative alle due modalità alternative di supporto disponibili, il vecchio
  OSS (\textit{Open Sound System}), ormai deprecato ed in via di sostituzione
  il cui uso è da evitare, ed il nuovo ALSA (\textit{Advanced Linux Sound
    Architecture}), È all'interno di dette sottosezioni che poi si potrà
  abilitare il supporto per le varie schede sonore.

\item[HID Devices] Questa sezione contiene le opzioni per il supporto
  dell'interfaccia dei dispositivi di interazione ``\textsl{uomo-macchina}'',
  cioè tutto quello che attiene il cosiddetto HID (\textit{Human Interface
    Device}), una astrazione che permette di usare in maniera generica
  dispositivi come il mouse.

\item[USB support] Questa sezione contiene le opzioni relative al supporto dei
  vari chipset del bus USB (vedi sez.~\ref{sec:USB_interface}) e dei vari
  dispositivi che si possono inserire su di esso; è qui che si abilita il
  supporto per i dischi su USB che consente di usare le chiavette ed i dischi
  esterni.

\item[Staging drivers] Questa sezione contiene le opzioni relative ad una
  serie di dispositivi il cui supporto è considerato non ottimale,
  sperimentali, instabili e in sviluppo, inseriti solo per ampliare la platea
  di utilizzo. Sono considerati problematici per cui vanno utilizzati solo se
  strettamente necessari, o se interessati al loro sviluppo.

% \item[MMC/SD/SDIO card support] Questa sezione contiene le opzioni relative al
%   supporto delle varie carte \textit{Secure Digital} e \textit{MultiMediaCard}
%   e dei chipset che consentono di leggerle.

\end{basedescript}

Una volta completata la configurazione, qualunque sia il metodo con cui la si
è effettuata, questa viene salvata su un nuovo \texttt{.config}. A questo
punto si può passare alla compilazione del kernel e di tutti i moduli con il
comando \texttt{make}.\footnote{con i kernel recenti può essere necessario
  installare alcuni pacchetti di sviluppo aggiuntivi, come i plugin del
  \texttt{gcc} o le intestazioni della libreria \texttt{libssl}.} Si tenga
presente però che questa è la procedura adottata a partire dal kernel 2.6, in
precedenza erano necessari vari passi intermedi, che non tratteremo essendo
questi kernel ormai questi completamente obsoleti.


%%
%% ### OBSOLETE BEGIN ###
%% Materiale obsoleto per la compilazione del kernel 2.4
%%
\ifx\obsoletesection\undefined

\relax
\else
A questo punto la
procedura cambia a seconda che si stia utilizzando un kernel dalla serie 2.4.x
o precedenti o della serie 2.6.x. Infatti con la serie 2.6.x anche la
procedura di ricompilazione è stata profondamente modificata e semplificata.

Con i kernel della serie 2.4.x e precedenti se si effettua la compilazione per
la prima volta, il primo passo è creare le dipendenze con il comando
\texttt{make dep}. Il comando esegue due compiti, il primo è creare le
dipendenze\footnote{cioè determinare quali file di dichiarazione (i
  \texttt{.h}) sono necessari per produrre i relativi file binari (i
  \texttt{.o}) contenenti il codice di kernel e moduli.} per la compilazione,
il secondo, se si è abilitato il controllo della versione dei moduli, è
calcolare le informazioni per il versionamento nei simboli.\footnote{si
  chiamano così i nomi delle funzioni che vengono dichiarate all'interno di un
  modulo, ma possono essere usati da altri; per far questo si dice che il
  simbolo deve essere \textsl{esportato}, il versionamento funziona
  aggiungendo al nome di ciascun simbolo un hash unico che impedisce di
  chiamare da un kernel diverso le suddette funzioni.}  Pertanto quando se non
si è abilitato il versionamento è necessario eseguire questo comando soltanto
la prima volta che si effettua una compilazione, altrimenti deve essere
eseguito ogni volta che si cambia la configurazione, in quanto l'informazione
sulla versione dei simboli dipende da questa. Nei kernel della serie 2.6.x
tutto questo non è più necessario e pertanto questo comando è deprecato e non
deve essere utilizzato (qualora lo si usi viene semplicemente stampato un
avviso).

Il passo successivo, sempre per i kernel della serie 2.4.x, è quello di
compilare l'immagine del kernel. Sui normali PC compatibili a 32bit questo si
fa con il comando \texttt{make bzImage}, che crea l'omonima immagine compressa
nella directory \texttt{arch/i386/boot}, con i kernel 2.6 più recenti le
architettura a 32 e 64 bit sono state unificate, e l'immagine del kernel si
trova sempre in \texttt{arch/x86/boot}; su altre architetture si usa in genere
\texttt{make vmlinux} che crea una immagine non compressa nel file omonimo
nella directory dei sorgenti. Un altro possibile comando è \texttt{make
  zImage}, che crea una immagine compressa generica, valida anche per altre
architetture.

Quest'ultimo era il comando originale per la creazione delle immagini del
kernel, e può essere ancora usato fintanto che il kernel è di dimensione
inferiore a 512kb. Se la dimensione è superiore occorre invece usare
\texttt{make bzImage}, non tanto, come qualcuno ancora ritiene, perché così
l'immagine viene compressa di più,\footnote{la compressione è identica nei due
  casi e fino al kernel 2.6.30 è sempre stata effettuata con \texttt{gzip};
  nonostante il nome \texttt{bzImage} possa trarre in inganno \texttt{bzip2}
  non veniva mai usato; a partire da questo kernel è stato aggiunto il
  supporto per diversi algoritmi di compressione (\texttt{bzip} e
  \texttt{lzma}).} quanto perché nel primo caso il kernel viene caricato nella
cosiddetta \textit{low memory} (cioè sotto i primi 640k) e viene utilizzato un
meccanismo d'avvio diverso, mentre nel secondo caso viene caricato sopra 1M.

Al giorno d'oggi l'unica ragione per usare \texttt{zImage} potrebbe essere
quella della compatibilità con macchine obsolete (ormai praticamente
scomparse) su cui ci sono vecchie versioni di LILO e vecchi BIOS che non
supportano la procedura di avvio di \texttt{bzImage}, che non risente del
limite di 512k nella dimensione, ed è anche più veloce. Questo ovviamente vale
solo per l'architettura PC, se si usano altre architetture ci possono essere
altri \textit{target} o può non essere necessario l'uso di un kernel compresso
(è il caso dell'architettura PPC dei vecchi Macintosh).

Una volta compilata l'immagine del kernel il passo successivo è, se li si sono
abilitati, passare alla compilazione dei moduli. Questo viene fatto con il
comando \texttt{make modules}. I due passi della compilazione (compilazione
dell'immagine e dei moduli) ed i relativi \textit{target} per \texttt{make},
pur essendo disponibili anche con i kernel della serie 2.6.x, sono deprecati,
in quanto tutta la procedura di compilazione può essere eseguita in un colpo
solo invocando semplicemente il comando \texttt{make}, questo si cura anche di
compilare l'immagine del kernel nel giusto formato per la piattaforma hardware
che si sta usando. 

%%
%% ### OBSOLETE END ###
%% Materiale obsoleto per la compilazione del kernel 2.4
%%
\fi

La compilazione del kernel (e dei moduli) è in genere un processo piuttosto
lungo e che utilizza pesantemente le risorse (memoria e CPU) della macchina.
Pertanto viene spesso anche usato come test di carico. Il procedimento può
essere reso più veloce usando l'opzione \texttt{-j} del comando \texttt{make}
che consente di \textsl{parallelizzare} la compilazione. 

Questa è una funzionalità del tutto generale di \texttt{make} (per la
precisione della versione GNU) che consente di specificare come parametro
dell'opzione un numero di processi da eseguire in parallelo, ciascuno dei
quali compilerà parti indipendenti, così da avere in generale sempre qualche
processo in compilazione anche quando gli altri sono bloccati sull'I/O, cosa
che è particolarmente efficiente su macchine multiprocessore. Questo è
possibile sfruttando appunto le informazioni sulle dipendenze usate da
\texttt{make} per affidare a processi diversi la compilazioni di sorgenti
indipendenti.


\subsection{Installazione manuale del kernel e del \textit{ramdisk} iniziale}
\label{sec:kernel_install}

Una volta eseguita con successo la compilazione i passi successivi riguardano
l'installazione del nuovo kernel; il primo passo è quello di installare i
moduli e questo viene fatto, usando un ulteriore \textit{target}, con il
comando \texttt{make modules\_install}. I moduli vengono sempre installati
sotto \texttt{/lib/modules}, in una directory diversa per ciascuna versione
del kernel, con lo stesso nome della stessa, così come definita nel
\texttt{Makefile}; questo significa che se si installano i moduli del kernel
4.9.36 questi e tutti i relativi file saranno installati in
\texttt{/lib/modules/4.9.36/}.

I passi successivi sono l'installazione nel sistema della nuova immagine del
kernel e dei file ad essa associati. Per questo vengono anche forniti altri
\textit{target} specifici per \texttt{make} (come \texttt{make install},
\texttt{make rpm} o \texttt{make deb-pkg}) che consentono di automatizzare
l'installazione o generare dei pacchetti installabili, ma è sempre possibile
eseguire l'operazione manualmente, anche perché in questo caso le operazioni
sono indipendenti dal \textit{bootloader} (vedi sez.~\ref{sec:struct_boot})
che si intende usare.

In tab.~\ref{tab:kernel_make_target} si sono riportati i principali
\textit{target} di \texttt{make} usati per la compilazione e l'installazione
del kernel dai sorgenti; in questo caso la documentazione non è disponibile in
una pagina di manuale, ma si può trovare una lista completa dei vari
\textit{target} disponibili nel capitolo 10 di \cite{LinuxNutshell}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Target} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{config}    & interfaccia di configurazione a linea di comando.\\
    \texttt{oldconfig} & interfaccia di configurazione a linea di comando, 
                         che riutilizza i valori precedentemente immessi.\\ 
    \texttt{menuconfig}& interfaccia di configurazione a grafica testuale, 
                         basata sulle librerie \texttt{ncurses}. \\
    \texttt{nconfig}   & nuova interfaccia di configurazione testuale.\\
    \texttt{xconfig}   & interfaccia di configurazione grafica.\\
   % \texttt{checkconfig}& \\
   % \texttt{checkhelp} & \\
   % \texttt{dep}       & crea le dipendenze per la compilazione e le
   %                      informazioni per il versionamento dei moduli, inutile
   %                      per i kernel della serie 2.6.x.\\
   % \texttt{depend}    & identico a \texttt{dep}.\\
   % \texttt{zImage}    & crea una immagine compressa del kernel (valida su
   %                      tutte le architetture).\\
   % \texttt{bzImage}   & crea una immagine compressa del kernel (su
   %                      architettura PC) con una diversa procedura di avvio.\\
    \texttt{vmlinux}   & crea solo l'immagine del kernel.\\
    \texttt{modules}   & compila soltanto i moduli. \\
    \texttt{modules\_install} & installa i moduli nella relativa directory.\\
    \texttt{clean}     & cancella tutti i file oggetto (i \texttt{.ko})
                         presenti prodotti da una precedente compilazione.\\ 
    \texttt{mrproper}  & oltre a quanto esegue \texttt{clean}, cancella anche
                         le configurazioni prodotte da \texttt{menuconfig}.\\ 
    \texttt{distclean} & oltre a quanto esegue \texttt{mrproper} e cancella
                         ulteriori file prodotti cercando di riportare
                         l'albero dei sorgenti identico allo stato
                         immediatamente dopo la scompattazione.\\
    \texttt{install}   & esegue l'installazione del kernel.\\
    \texttt{rpm}       & crea un pacchetto RPM contenente
                         l'immagine del kernel.\\
    \texttt{deb-pkg}   & crea un pacchetto Debian contenente immagine del
                         kernel e moduli.\\ 
    \hline
  \end{tabular}
  \caption{Principali \textit{target} del comando \texttt{make} per la
    compilazione del kernel.}
  \label{tab:kernel_make_target}
\end{table}

Come spiegato in sez.~\ref{sec:file_FHS} i file usati dal \textit{bootloader}
per lanciare il sistema sono mantenuti in \texttt{/boot}, pertanto è qui che
deve essere copiata l'immagine del kernel. Questa viene sempre creata nel file
\texttt{vmlinux} nella directory dei sorgenti, ma per motivi storici nella
architettura dei PC ordinari deve essere usata una immagine compressa che si
trova, sia per le versioni a 32 che a 64 bit, sotto
\texttt{arch/x86/boot/bzImage}. Su architetture hardware diverse si possono
avere casi diversi a seconda del tipo di \textit{bootloader}, ma in genere
viene usato direttamente il file \texttt{vmlinux}.

La convezione adottata universalmente è quella di chiamare l'immagine del
kernel posta sotto \texttt{/boot} con il nome
\texttt{vmlinuz-\textsl{versione}}, dove la ``\textit{versione}'' è quella
impostata con le variabili del \texttt{Makefile} principale di cui si è
parlato all'inizio di sez.~\ref{sec:kernel_compile}, e che deve essere univoco
qualora si voglia dare la possibilità al \textit{bootloader} di utilizzare
kernel diversi per l'avvio del sistema (tratteremo l'argomento in
sez.~\ref{sec:struct_kernel_boot}).

Occorre inoltre copiare anche il file \texttt{System.map} che contiene le
informazioni che permettono di identificare per nome, e non tramite un
indirizzo in memoria, le varie funzioni interne del kernel. In questo file, la
cosiddetta \textsl{mappa dei simboli}, viene mantenuto l'elenco completo dei
nomi delle funzioni (i \textsl{simboli} appunto) che sono state
``\textsl{esportate}'', cioè rese visibili, alle altre funzioni del kernel. La
mappa contiene sia i simboli di quelle presenti nell'immagine di avvio che di
tutte quelle disponibili all'interno dei moduli.

Il contenuto del file viene utilizzato dal kernel nella stampa degli eventuali
errori riscontrati nell'esecuzione di una funzione interna.  Le funzioni
infatti sono accessibili al kernel solo con degli indirizzi binari, ma il file
può essere utilizzato per ottenere i nomi degli indirizzi. Questa funzionalità
di per sé non è essenziale, ma senza questa informazione diventa molto
complesso per chi sviluppa il kernel capire dove si è verificato l'errore, ed
anche più difficile per voi chiedere aiuto o cercare informazioni
relativamente all'errore stesso. La sua assenza perciò non comporta problemi
di funzionamento del sistema, ma solo una maggiore difficoltà per chi dovrà
andare ad analizzare gli errori.

Lo stesso file è utilizzato anche in sede di installazione dei moduli quando
vengono calcolate le dipendenze di un modulo da un altro, ed il comando
\texttt{depmod} (che vedremo in sez.~\ref{sec:kernel_modules}) darà degli
errori in caso di sua mancanza o di non corrispondenza con il kernel attivo.
Come per l'immagine del kernel anche \texttt{System.map} viene di norma
copiato su \texttt{/boot} aggiungendo un ``\texttt{-}'' e la versione; questo
fa sì che ogni kernel sia in grado di trovare ed utilizzare la propria mappa
dei simboli.

Infine è buona norma, tutte le volte che si installa un nuovo kernel,
mantenere traccia anche delle opzioni di configurazione con cui lo si è
prodotto, tanto che a partire dalla serie 2.6.x è possibile far generare
direttamente al kernel stesso il contenuto di detto file, posto che si sia
abilitato il relativo supporto durante la compilazione (opzione
``\texttt{Kernel .config support}'' in ``\texttt{General setup}''). Questo
comporta la necessità di salvare il contenuto del corrispondente file
\texttt{.config} e di norma lo si fa (questa ad esempio è la scelta di Debian)
copiandolo sempre sotto \texttt{/boot}, ed assegnandogli, usando la stessa
convenzione usata per la mappa dei simboli e l'immagine del kernel, un nome
nella forma \texttt{config-\textsl{versione}}.


Ricapitolando, l'insieme dei vari passi per ottenere un nuovo kernel ed
installare tutti i file relativi, dovrà essere qualcosa del tipo:
\ifx\obsoletesection\undefined

\relax
\else
\begin{Example}
make menuconfig
make dep
make bzImage
make modules
make modules_install
cp arch/i386/boot/bzImage /boot/vmlinuz-2.4.24-my
cp System.map /boot/System.map-2.4.24-my
cp .config /boot/config-2.4.24-my
\end{Example}
se si usa un kernel della serie 2.4.x o precedente, mentre se il kernel è
della serie 2.6.x o seguenti la procedura si potrà ridurre a: \fi
\begin{Example}
make menuconfig
make
make modules_install
cp arch/x86/boot/bzImage /boot/vmlinuz-4.9.36
cp System.map /boot/System.map-4.9.36
cp .config /boot/config-4.9.36
\end{Example}
dopo di che occorrerà configurare il proprio \textit{bootloader} (vedi
sez.~\ref{sec:struct_boot}) per l'uso del nuovo kernel.

Si tenga presente però che il procedimento appena illustrato può funzionare
soltanto se nel kernel si è inserito direttamente il supporto necessario a
montare la radice, vale a dire sia il supporto per la classe di dispositivi su
cui si trova il filesystem (ed eventualmente per lo specifico hardware che ne
consente l'accesso) che per il filesystem stesso. In caso contrario una volta
lanciato il kernel non sarà in grado di montare la radice, e ci si troverà di
fronte ad una brusca interruzione della procedura di avvio con un
\textit{kernel panic}.

Tutto questo, una volta che si conosca l'hardware specifico della propria
macchina, non è un problema, a parte ovviamente la necessità di individuare
quali sono le opzioni di configurazione che corrispondono al supporto per il
proprio hardware, cosa talvolta non banale: basterà inserire all'interno del
kernel il relativo supporto. Lo è però quando, come accade per i kernel
standard forniti dalle distribuzioni, il kernel deve poter funzionare con una
macchina generica. In tal caso infatti si dovrebbero inserire all'interno del
kernel tutti i possibili driver per tutti i possibili tipi di hardware, ad
esempio con le comuni macchine odierne sarebbe necessario il supporto per
tutti i possibili chipset \textit{Serial ATA}, la gran parte dei quali poi
sarebbe inutilizzato ed occuperebbe inutilmente una risorsa preziosa come la
RAM.

\itindbeg{ramdisk} 

Benché sia possibile seguire questo approccio, e rimandare ad una successiva
ricompilazione l'installazione di un kernel più adatto alla propria specifica
macchina, la gran parte delle distribuzioni utilizza un approccio diverso che
passa attraverso l'utilizzo di quello che in gergo viene chiamato un
\textit{ramdisk} iniziale, o \textit{initrd}. In questo caso quello che si fa
è inserire nel kernel soltanto il supporto per questo unico tipo di
dispositivo che viene montato come radice provvisoria durante l'avvio.

È all'interno del \textit{ramdisk} che viene installato un sistema minimale
che si incarica di caricare i moduli necessari e compiere le operazioni
necessarie ad accedere al dispositivo su cui si trova la radice. A questo
punto sarà possibile montare la radice ``\textsl{reale}'' del sistema, e,
tramite un apposito comando,\footnote{il comando si chiama
  \texttt{pivot\_root}, come la omonima \textit{system call}, ed è specifico
  di Linux; una volta che la radice ``\textsl{reale}'' sia stata montata in
  una directory all'interno di quella provvisoria il comando consente di
  rendere questa la nuova radice del sistema.} renderla la nuova radice, da
cui eseguire l'ordinario avvio descritto in sez.~\ref{sec:struct_sysv_init},
liberando al contempo la memoria utilizzata dal \textit{ramdisk} e non più
necessaria.

Perché questa procedura funzioni con un kernel generico occorre ovviamente
poter generare un \textit{ramdisk} appropriato. Nell'originario
\textit{initrd} questo veniva creato come immagine di un filesystem in cui si
era inserito tutto il necessario. In genere venivano usati filesystem minimali
come \texttt{cramfs} o \texttt{romfs} ed ovviamente doveva essere inserito
direttamente nel kernel il relativo supporto. A partire dai kernel della serie
2.6.x invece è presente un nuovo meccanismo, chiamato \textit{initramfs}, che
fornisce il supporto per creare un \textit{ramdisk} vuoto e popolarlo
automaticamente con il contenuto di un archivio \texttt{cpio} compresso con
\texttt{gzip}, non è pertanto necessario inserire nel kernel il supporto per
nessun filesystem specifico, ma solo quello per l'uso del \textit{ramdisk}
iniziale.  Questo è il meccanismo usato oggi da tutte le principali
distribuzioni.

Qualunque sia il metodo occorre comunque poter creare un appropriato
\textit{ramdisk} iniziale che contenga, oltre a tutti i moduli che possono
servire, anche tutti i programmi e le relative librerie che consentano di
caricarli per accedere al dispositivo, montare la radice reale, e eseguire da
questa la procedura di avvio ordinaria. Per questo motivo ogni distribuzione
mette a disposizione un suo programma che consente di creare, dopo aver
installato un nuovo kernel, un opportuno \textit{ramdisk} ad esso associato.

Il comando usato originariamente sia su sistemi RedHat che Debian era
\index{comando!\texttt{mkinitrd}} \texttt{mkinitrd}.\footnote{si tenga
  presente che nonostante il nome, la versione in uso nelle distribuzioni
  recenti utilizza il nuovo meccanismo di \textit{initramfs}, anche se quella
  usata da RedHat e CentOS è in grado di produrre \textit{ramdisk} anche con
  il vecchio meccanismo per kernel della serie 2.4.x.}  Si trattava comunque,
nonostante il nome fosse lo stesso, di programmi diversi funzionanti in
maniera diversa. Tratteremo solo la versione di \texttt{mkinitrd} usata da
RedHat e derivate dato che è la sola che sopravvive ancora oggi e che non è
altro che uno script di shell che si cura della generazione del
\textit{ramdisk}. Il comando prevede due argomenti, il primo è il nome del
file su cui verrà creato il \textit{ramdisk} ed il secondo la versione del
kernel per cui crearlo (per quella corrente è sufficiente usare il risultato
di \texttt{uname -r}).

Il comando supporta una serie di opzioni che consentono di omettere alcune
classi di moduli, per ridurre le dimensioni del \textit{ramdisk} qualora si
sappia per certo che queste non servano (ad esempio i moduli per i dischi
SCSI). Si può inoltre specificare una lista di moduli da aggiungere o
togliere, ed ulteriori opzioni per controllare il formato del \textit{ramdisk}
e le sue modalità di funzionamento, per le quali si può consultare la pagina
di manuale. L'unica opzione che vale la pena citare è \texttt{-f} che consente
di sovrascrivere un file esistente.

Nel caso di \texttt{mkinitrd} viene sempre generato un \textit{ramdisk} che
contiene i moduli strettamente necessari all'avvio della propria macchina,
così come sono stati determinati durante l'installazione della stessa. Lo
script di avvio del \textit{ramdisk} si limita a caricali, in modo da montare
la radice reale e poi far proseguire l'ordinaria procedura di avvio. Si deve
pertanto stare attenti qualora si sposti il disco del sistema su un'altra
macchina, perché non è detto che i moduli necessari siano gli stessi, nel qual
caso non si sarebbe più in grado di avviare la macchina. Lo stesso dicasi
qualora si volesse riutilizzare il kernel ed il relativo \textit{ramdisk} su
una macchina diversa.

Per superare questi problemi, e fornire un meccanismo che consenta l'avvio su
una macchina generica, Debian e derivate hanno sostituito \texttt{mkinitrd}
con \index{comando!\texttt{mkinitramfs}}
\index{comando!\texttt{update-initramfs}} \texttt{mkinitramfs},\footnote{nel
  caso di Debian è presente pure il programma \texttt{update-initramfs} che
  semplifica la creazione dei \textit{ramdisk} per i kernel installati sotto
  \texttt{/boot}; entrambi con i loro file di configurazione fanno parte del
  pacchetto \texttt{initramfs-tools}.} un programma che permette di creare un
\textit{ramdisk} in cui sono presenti tutti i moduli necessari ad effettuare
l'avvio da un dispositivo generico.  Questo significa che saranno presenti non
solo i moduli per il supporto delle diverse schede SCSI o dei vari chipset per
il \textit{Serial ATA}, ma anche quelli per l'uso di dispositivi
\textsl{virtuali} il RAID software (vedi sez.~\ref{sec:disk_RAID}) o LVM (vedi
sez.~\ref{sec:disk_LVM}) e quelli necessari per l'avvio via rete. Inoltre
saranno presenti anche i moduli per i vari filesystem utilizzabili per la
radice, ed infine un sistema minimale con tutto l'occorrente per determinare
quali sono i moduli da caricare per montare la radice reale ed eseguire
l'avvio definitivo.

Per creare un nuovo \textit{ramdisk} occorre invocare il programma
specificando con l'opzione \texttt{-o} il file sul quale si vuole
scriverlo. Se non si indica altro viene sottinteso l'uso del kernel corrente,
altrimenti occorrerà indicarne esplicitamente la versione come argomento. Per
le altre opzioni e la documentazione completa si consulti al solito la pagina
di manuale.

Lo svantaggio di \texttt{mkinitramfs} è che il \textit{ramdisk} iniziale
creato è in genere di dimensioni maggiori, anche se è possibile indicare al
programma di inserirvi soltanto lo stretto indispensabile o escludere alcune
classi di moduli se si sa che questi non serviranno. Il vantaggio, oltre alla
disponibilità dei vari moduli che consentono di avviare lo stesso kernel anche
con macchine diverse, è quello che nel \textit{ramdisk} è presente un sistema
minimale dotato di una sua shell ed un sottoinsieme di comandi a cui si viene
portati in caso di problemi, il che consente di operare manualmente e tentare
un recupero se qualcosa non funziona.

Il comportamento di \texttt{mkinitramfs} è controllato dal rispettivo file di
configurazione che è
\index{configurazione!\texttt{/etc/initramfs-tools/initramfs.conf}}
\texttt{/etc/initramfs-tools/initramfs.conf}, il formato del file è quello di
una serie di dichiarazioni di variabili di shell, che controllano il
comportamento di \texttt{mkinitramfs}, come è naturale dato che quest'ultimo è
uno script di shell. In generale non c'è da modificare nulla, il file è
comunque ben commentato ed anche per lui è disponibile una pagina di manuale.

Infine una ulteriore alternativa è costituita dal comando
\index{comando!\texttt{yaird}} \texttt{yaird}, che a differenza dei precedenti
nasce come progetto indipendente disponibile per qualunque distribuzione. La
filosofia del programma è simile a quella di \texttt{mkinitrd}, cioè mira a
creare un \textit{ramdisk} iniziale di dimensioni minime che contenga soltanto
lo stretto indispensabile. Contrariamente a \texttt{mkinitrd} il programma
esegue una serie di controlli estesi, svolti tramite i dati ottenuti dal
filesystem \texttt{/sys}, volti ad assicurarsi che il \textit{ramdisk}
prodotto sia adatto all'hardware effettivamente presente sulla propria
macchina ed assicuri un avvio senza problemi, senza i quali si rifiuta di
creare l'immagine.

Il comando deve essere invocato o con l'opzione \texttt{-{}-output} tramite la
quale si indica il file su cui produrre l'immagine, o con l'opzione
\texttt{-{}-test} che esegue soltanto un controllo sul sistema per verificare
la capacità di produrre il \textit{ramdisk}. Come argomento si deve
specificare la versione di kernel per cui creare il \textit{ramdisk} e come
per \texttt{mkinitramfs} se non si specifica nessun argomento verrà usata la
versione corrente. Per le altre opzioni ed i dettagli si rimanda di nuovo alla
relativa pagina di manuale.

Qualunque sia il programma utilizzato, se si è deciso di optare per un kernel
da avviare con l'ausilio di un \textit{ramdisk}, l'ultimo passo
dell'installazione manuale è sempre quello di copiare il file dell'immagine
del \textit{ramdisk} nella directory \texttt{/boot} con un nome adeguato (in
genere si usa qualcosa del tipo \texttt{initrd-\textsl{versione}}) per poi
essere in grado di farlo utilizzare al \textit{bootloader} (vedi
sez.~\ref{sec:struct_grub} e \ref{sec:struct_syslinux}).

\itindend{ramdisk} 



\subsection{La gestione dei moduli}
\label{sec:kernel_modules}

Abbiamo già sottolineato come una delle caratteristiche più significative del
kernel Linux sia il supporto modulare che consente di aggiungere funzionalità
e supporto di periferiche anche dopo l'avvio caricando gli opportuni
moduli. Ma oltre alla possibilità di effettuare questa operazione in maniera
manuale, fin dalla nascita del supporto modulare era anche il kernel stesso ad
essere in grado di effettuare autonomamente, ad esempio in corrispondenza
della richiesta di una funzionalità mancante, il caricamento degli eventuali
moduli ritenuti necessari.  A partire dalla serie 2.6.x il meccanismo prevede
che per il supporto ai dispositivi presenti i moduli siano caricati in
corrispondenza al riconoscimento degli stessi.

Nelle prime versioni del kernel questo era realizzato attraverso un apposito
demone, \texttt{kerneld}, che riceveva le richieste dal kernel ed eseguiva il
caricamento dei moduli. A partire dalla serie 2.4.x il meccanismo è stato
realizzato con un apposito sottosistema del kernel tramite il quale
all'interno del kernel è possibile invocare una apposita funzione che dato il
nome del modulo che si vuole caricare\footnote{la funzione si chiama
  \texttt{request\_module}, ed in realtà con essa si potevano richiedere non
  soltanto dei moduli specifici ma anche delle funzionalità generiche, sempre
  identificate da un nome, che poi potevano essere fatte corrispondere anche a
  moduli diversi.} si incarica di mettere in esecuzione un programma in user
space in grado di eseguire tutte le operazioni necessarie al caricamento dello
stesso.\footnote{il programma è \texttt{modprobe}, che tratteremo in dettaglio
  più avanti, ma si può utilizzare al suo posto un programma qualsiasi
  scrivendo il relativo pathname assoluto in
  \texttt{/proc/sys/kernel/modprobe}.}
\index{filesystem~\texttt{/proc}!\texttt{/proc/sys/kernel/modprobe}}

Per questo motivo, oltre a quanto illustrato nei paragrafi precedenti riguardo
configurazione, compilazione ed installazione del kernel per il supporto
modulare, per poter utilizzare a pieno quest'ultimo sono necessari anche tutti
quei programmi in user space che permettono di gestire i moduli stessi (ed in
particolare il loro caricamento) che sono raccolti in un apposito pacchetto
che viene distribuito coi sorgenti del kernel.

Inoltre a partire dai kernel della serie 2.6.x la gestione dei moduli è stata
completamente ristrutturata, e a quanto appena illustrato è stata affiancata
una ulteriore infrastruttura in user space (vedi sez.~\ref{sec:udev_hotplug})
che oltre alla creazione dinamica dei file di dispositivo sotto la directory
\texttt{/dev} sulla base dell'hardware effettivamente presente sulla propria
macchina, fosse in grado di gestire la rilevazione dei dispositivi presenti,
compresa quella occasionale dei dispositivi rimuovibili, ed il caricamento
contestuale dei moduli necessari per il relativo funzionamento.

% Nell'ambito di questa ristrutturazione l'interfaccia per il caricamento dei
% moduli è stata drasticamente semplificata, ed ora la gran parte del lavoro
% viene effettuata all'interno del kernel. Per questo i programmi per la
% gestione dei moduli sono stati completamente riscritti. I nuovi programmi
% garantiscono comunque la compatibilità all'indietro con i precedenti,
% chiamando quest'ultimi quando invocati con un kernel della serie
% 2.4.x.\footnote{questo viene fatto chiamando per ciascun programma viene
%   eseguito, in maniera del tutto trasparente per l'utente, un corrispondente
%   comando con estensione \texttt{.old} (o \texttt{.modutils} a seconda della
%   versione).}

Il programma di base che consente di caricare un modulo all'interno del
kernel, in modo da poterne usare le funzionalità, è
\index{comando!\texttt{insmod}} \texttt{insmod}. Fino alla serie 2.4.x era il
programma stesso che leggeva il codice dal disco, effettuava la risoluzione
dei simboli, controllando che questi fossero compatibili con la versione del
kernel in esecuzione, ed infine eseguiva il \textsl{collegamento} al codice
del kernel. Con la serie 2.6.x il lavoro di controllo dei simboli ed il
collegamento viene operato direttamente dal kernel stesso, per cui il comando
non è che un programma minimale che legge il file contenente il codice del
modulo che si vuole utilizzare e lo passa alla nuova versione della
\textit{system call} del kernel che gestisce il caricamento.\footnote{questa
  funzione si chiama \texttt{init\_module}, e si limita a prendere da un
  buffer il codice del modulo letto dal file, e gli eventuali parametri
  passati come stringa.}

Si tenga presente però che \texttt{insmod} consente di inserire nel kernel
solo un modulo alla volta e che per farlo ha bisogno di risolvere tutti i
simboli necessari al modulo stesso. Se alcuni di questi non sono presenti nel
kernel in esecuzione, ma disponibili soltanto attraverso altri moduli non
ancora caricati, il comando fallirà con un errore di ``\texttt{unresolved
  symbol}''. É per questo motivo che non si usa quasi mai \texttt{insmod}
direttamente per caricare un modulo, ma lo si fa attraverso \texttt{modprobe},
che vedremo a breve.

Con i kernel della serie 2.6 il programma richiede semplicemente il pathname
del file che deve essere caricato come modulo. % , con i kernel della serie 2.4.x
% il comportamento era più complesso perché il comando prendeva come argomento
% solo il \textsl{nome} del modulo,\footnote{che si ricordi è nella forma
%   \texttt{nome.o} (l'estensione \texttt{.ko} è stata introdotta con i kernel
%   2.6.x).} e cercava il corrispondente file oggetto al di sotto della
% directory \texttt{/lib/modules/`uname -r`}, a meno che non fosse stata
% definita la variabile di ambiente \texttt{MODPATH} o fosse stata specificata
% una apposita opzione nel file di configurazione \texttt{/etc/modules.conf} per
% indicare una directory diversa. 
Se un modulo li prevede, possono essere specificati come ulteriori argomenti
di \texttt{insmod} dei parametri di configurazione nella forma
\texttt{parametro=valore}. Si tenga presente che ogni argomento aggiuntivo
viene interpretato come parametro, per cui si abbia cura di non inserire spazi
prima e dopo l'assegnazione con ``\texttt{=}''. 

Il nome del ``\textit{parametro}'' dipende dal modulo stesso e la lista dei
parametri disponibili per ciascun modulo si può ottenere tramite il comando
\texttt{modinfo}, che tratteremo a breve, mentre il ``\textit{valore}'' può
essere a seconda dei casi una stringa, un numero intero, o una lista di numeri
interi separati da virgole. I numeri inoltre sono specificabili sia in forma
decimale scrivendoli normalmente (ad esempio \texttt{17}), che in forma ottale
apponendovi uno zero (ad esempio \texttt{021} equivale di nuovo a
\texttt{17}), che in forma esadecimale apponendovi uno \texttt{0x} (e ad
esempio in questo caso si potrebbe scrivere il solito \texttt{17} come
\texttt{0x11}).

% A differenza della versione elementare in uso per i kernel 2.6, la versione di
% \texttt{insmod} usata per i kernel della serie 2.4.x supporta anche una serie
% di opzioni che ne modificano il comportamento: ad esempio come norma di
% sicurezza non carica i moduli se i relativi file non appartengono
% all'amministratore, onde evitare che il contenuto di un modulo possa essere
% sovrascritto in caso di compromissione dell'utente cui appartiene, con la
% conseguente possibilità di far eseguire direttamente al kernel il codice che
% si vuole; questo comportamento può essere disabilitato con l'opzione
% \texttt{-r} (ad uso principalmente degli sviluppatori).

% Inoltre essendo \texttt{insmod} stesso a controllare che la versione del
% kernel corrente e quella del modulo combacino per evitare di caricare moduli
% che appartengano a kernel diversi, si poteva forzare il caricamento di un
% modulo non corrispondente con l'opzione \texttt{-f}. Con questa opzione però
% veniva evitato soltanto il controllo sulla versione del kernel, il controllo
% sull'uso dei nomi dei simboli non poteva essere evitato, questo significa che
% se si erano compilati i moduli con il supporto per il versionamento (che crea
% dei nomi di simboli contenenti una \textit{checksum}) non sarebbe stato
% comunque possibile utilizzarli.\footnote{questo meccanismo non esiste più nel
%   kernel 2.6, per il quale viene usata una \textit{checksum} interna che può
%   essere ignorata.}

% Per l'elenco completo di tutte le opzioni della versione di \texttt{insmod}
% per il kernel 2.4 (alcune sono comunque obsolete, facendo riferimento al
% vecchio \texttt{kerneld}) con le relative spiegazioni dettagliate si può
% consultare al solito la pagina di manuale; le principali si sono comunque
% riportate in tab.~\ref{tab:insmod_options} con una breve spiegazione.

% \begin{table}[!htb]
%   \centering
%   \footnotesize
%   \begin{tabular}[c]{|l|p{8cm}|}
%     \hline
%     \textbf{Opzione} & \textbf{Significato} \\
%     \hline
%     \hline
%     \texttt{-f}    & evita il controllo della corrispondenza fra versione del
%                      kernel e versione del modulo.\\
%     \texttt{-L}    & usa il file locking per prevenire tentativi simultanei di
%                      caricare lo stesso modulo.\\
%     \texttt{-h}    & stampa un sommario del comando e relative opzioni.\\
%     \texttt{-n}    & esegue tutta la procedura eccettuato il caricamento
%                      finale del modulo.\\ 
%     \texttt{-r}    & disabilita la condizione che il modulo da caricare sia di
%                      proprietà di \textit{root}.\\
%     \texttt{-v}    & abilita la stampa di un maggior numero di informazioni.\\
%     \texttt{-k}    & imposta il flag di \textit{auto-clean} per il modulo, che
%                      viene controllato da \texttt{kerneld} per rimuovere i
%                      moduli non più in uso.\\
%     \hline
%   \end{tabular}
%   \caption{Principali opzioni del comando \texttt{insmod.old}.} 
%   \label{tab:insmod_options}
% \end{table}

Dato che \texttt{insmod} consente di caricare un modulo solo quando tutti i
simboli di cui questo ha bisogno possono essere referenziati, se alcuni di
essi sono presenti in un altro modulo non ancora caricato come accennato il
comando fallirà. In casi come questo per poter andare avanti occorre
identificare quale è questo modulo e caricarlo preventivamente, e se anche lui
dipende da simboli presenti in altri moduli, ripetere la procedura risolvendo
tutte le dipendenze. Dato che tutto questo può risultare assai scomodo, per
automatizzare il caricamento dei moduli è stato creato un secondo comando,
\index{comando!\texttt{modprobe}} \texttt{modprobe}, che permette di risolvere
le dipendenze in maniera automatica, trovare quali sono gli altri moduli che
servono per poter utilizzare quello richiesto, e caricarli preventivamente.

Il meccanismo tramite cui \texttt{modprobe} è in grado di risolvere le
dipendenze si basa sul contenuto del file \texttt{modules.dep} posto nella
directory in cui sono installati i moduli. Questo file viene di norma prodotto
in fase di installazione degli stessi tramite il comando \texttt{depmod} (su
cui torneremo più avanti) ed è costituito da una serie di righe con un formato
del tipo:
\begin{FileExample}[label=modules.dep]
kernel/fs/fat/vfat.ko: kernel/fs/fat/fat.ko
\end{FileExample}
che ricalca esattamente quello del \textit{target} di un \texttt{Makefile}; per
ciascun modulo che ha delle dipendenze nel file è presente una riga contenente
la lista degli altri moduli da cui esso dipende. In questo modo
\texttt{modprobe} si incaricherà di caricarli preventivamente ed evitare il
problema dei simboli non definiti.

Per trovare i file \texttt{modprobe} effettua la ricerca dei moduli da
caricare fra quelli compilati per il kernel corrente, cercandoli nella
directory \texttt{/lib/modules/`uname -r`}, dove vengono installati
normalmente con l'esecuzione di \texttt{make modules\_install} insieme a tutte
le informazioni necessarie al loro utilizzo.

A partire dal kernel 2.4 tutti i moduli sono installati sotto la directory
\texttt{kernel}, e all'interno di questa suddivisi per categorie in ulteriori
directory:\footnote{le directory citate sono quelle presenti al momento della
  stesura di questo testo, con riferimento al kernel 4.9.36
  ``\textit{vanilla}''.}  \texttt{arch} per i moduli specifici per la propria
architettura hardware, \texttt{block} per la gestione dell'I/O sui dispositivi
a blocchi, \texttt{crypto} per gli algoritmi di crittografia, \texttt{drivers}
per il supporto delle periferiche, \texttt{fs} per il supporto dei filesystem,
\texttt{lib} per le funzioni di libreria, \texttt{mm} per la gestione della
memoria, \texttt{net} per il supporto dei protocolli di rete,
\texttt{security} per le estensioni di sicurezza, \texttt{sound} per
l'infrastruttura di gestione dell'audio, \texttt{virt} per la
virtualizzazione. A loro volta i moduli installati sotto \texttt{drivers} sono
suddivisi in altre sottodirectory per tipologia di hardware.

% Come avvenuto per \texttt{insmod} anche \texttt{modprobe} è stato modificato
% nella ristrutturazione della gestione dei moduli effettuata con il passaggio
% ai kernel della serie 2.6.x, e di nuovo se il comando rileva l'uso di un
% kernel della serie 2.4.x chiamerà in maniera automatica e trasparente all'utente
% la versione precedente. Nel seguito faremo riferimento alla versione di
% \texttt{modprobe} in uso con i kernel della serie 2.6.x, che ormai sono stati
% adottati da tutte le principali distribuzioni, ma in questo caso, a parte
% alcune opzioni, non si hanno differenze significative per quel che riguarda la
% sintassi ordinaria del comando.

L'utilizzo più comune di \texttt{modprobe} prevede che gli si passi come
argomento il nome del modulo da caricare, stavolta senza estensioni e senza
fare riferimento ad un pathname; per comodità inoltre il comando non distingue
fra i caratteri ``\texttt{-}'' e ``\texttt{\_}'' qualora essi siano presenti
nel nome del modulo. Se \texttt{modprobe} rileva la necessità di caricare
altri moduli come dipendenze del modulo indicato provvederà a farlo in maniera
automatica. Dato che il lavoro effettivo di caricamento del modulo è fatto dal
kernel stesso, \texttt{modprobe} non è in grado di riportare nessun errore
specifico sui motivi per i quali il caricamento fallisce; in questo caso sarà
necessario consultare i messaggi del kernel nei file di log o con
\texttt{dmesg}.

Come per \texttt{insmod} anche con \texttt{modprobe} si possono specificare
negli argomenti successivi gli eventuali parametri da passare al modulo che
viene caricato, il vantaggio di \texttt{modprobe} è che attraverso l'uso del
suo file di configurazione, come vedremo a breve, si possono impostare dei
valori di default da assegnare a questi argomenti, senza doverli più scrivere
esplicitamente.

Oltre a caricare un modulo \texttt{modprobe}, se invocato con l'opzione
\texttt{-r}, è anche in grado di rimuoverlo; in questo caso, se i moduli da
cui quello rimosso dipende non sono utilizzati, il comando cercherà di
rimuovere anche quelli. Inoltre a differenza dell'inserimento, se si richiede
la rimozione si possono specificare negli argomenti anche più di un modulo
alla volta. Si tenga presente però che se il modulo è utilizzato il comando
fallirà.

Una seconda opzione importante è \texttt{-f} che consente di forzare
l'inserimento di un modulo anche qualora questo non corrisponda alla versione
del kernel corrente. Nel caso del kernel 2.6 il controllo avviene sia
attraverso l'uso di apposite informazioni sulla versione salvate quando è
stato abilitato il relativo supporto nel kernel (vedi
sez.~\ref{sec:kernel_compile}), che tramite una stringa di informazioni (detta
\textit{vermagic}) che viene mantenuta comunque all'interno del
modulo.\footnote{sono disponibili anche due opzioni più specifiche,
  \texttt{-{}-force-modversion} e \texttt{-{}-force-vermagic}, per ignorare
  solo una delle due fonti di informazioni sulla versione.}  L'opzione
consente di eliminare tutte queste informazioni, consentendo il caricamento
del modulo. Dato che nel passaggio da una versione all'altra del kernel
possono essere state introdotte delle differenze non banali una operazione di
questo tipo è rischiosa, e può dar luogo anche ad un crash del sistema.

Le altre opzioni principali del comando sono riportate in
tab.~\ref{tab:modprobe_options}, l'elenco completo ed una descrizione
dettagliata delle stesse è come sempre disponibile nella pagina di manuale,
accessibile con \texttt{man modprobe}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-a} & consente di indicare come argomenti una lista di moduli da
                  caricare.\\ 
    \texttt{-C} & permette di usare un differente file di configurazione
                  (da passare come parametro per l'opzione).\\
    \texttt{-c} & stampa la configurazione di default.\\
    \texttt{-f} & forza il caricamento del modulo anche qualora la versione
                  non corrisponda a quella richiesta dal kernel corrente.\\
    \texttt{-i} & ignora le direttive \texttt{remove} e \texttt{install} del
                  file di configurazione.\\
    \texttt{-n} & esegue tutta la procedura eccettuato il caricamento
                  finale del modulo.\\ 
    \texttt{-r} & rimuove il modulo specificato e l'insieme di moduli da cui
                  esso dipende.\\
    \texttt{-v} & abilita la stampa di un maggior numero di informazioni.\\
    \hline
  \end{tabular}
  \caption{Principali opzioni del comando \texttt{modprobe}}
  \label{tab:modprobe_options}
\end{table}

Come accennato il comportamento di \texttt{modprobe} è controllato da un
opportuno file di configurazione. % Fino al kernel 2.4 detto file era
% \index{configurazione!\texttt{/etc/modules.conf}}
% \texttt{/etc/modules.conf},\footnote{in alcuni sistemi più vecchi può essere
%   usato invece il file \texttt{/etc/conf.modules}, che è deprecato e non deve
%   essere più utilizzato a meno di non stare usando kernel di solo interesse
%   storico.} e attraverso di esso si controllavano, oltre al comportamento di
% \texttt{modprobe}, anche le directory usate da \texttt{insmod} per cercare i
% moduli da caricare.
Con i kernel della serie 2.6.x inizialmente la configurazione era mantenuta
nel file \index{configurazione!\texttt{/etc/modprobe.conf}}
\texttt{/etc/modprobe.conf} usando alternativamente, se il file non esisteva,
il contenuto della directory \index{configurazione!\texttt{/etc/modprobe.d/}}
\texttt{/etc/modprobe.d/}, ottenendo la configurazione come concatenazione di
tutti i file \texttt{.conf} in essa contenuti. Oggi
\texttt{/etc/modprobe.conf} è deprecato, ed il funzionamento delle versioni
recenti di \texttt{modprobe} prevede che vengano lette nell'ordine
\texttt{/lib/modprobe.d/}, \texttt{/etc/modprobe.d/} e
\texttt{/run/modprobe.d/} con la convenzione che prevale la configurazione
letta per ultima. In generale comunque le configurazioni vengono mantenute
prevalentemente in \texttt{/etc/modprobe.d/}.\footnote{le due directory
  \texttt{/lib/modprobe.d/} e \texttt{/run/modprobe.d/} sono previste per
  poter essere usata da un programma di avvio sistema (al momento ne fa uso
  solo \texttt{systemd}) per poter eseguire la gestione dei moduli all'interno
  della configurazione dello stesso.}


% \footnote{con Debian veniva usata la directory
  % \texttt{/etc/modutils/} per ottenere lo stesso risultato anche con i kernel
  % della serie 2.4.x, solo che in questo caso il meccanismo prevedeva la
  % generazione di un opportuno \texttt{/etc/modules.conf} a partire dai
  % contenuti di questa directory tramite il comando \texttt{update-modules};
  % tutto questo è stato eliminato nelle versioni più recenti con il passaggio
  % al kernel 2.6.}  \index{configurazione!\texttt{/etc/modutils/}}

I singoli file di \texttt{/etc/modprobe.d/} (o delle altre directory citate)
hanno un formato molto semplice in cui si specifica una direttiva per riga
nella forma di una parola chiave seguita da eventuali argomenti. Al solito
righe vuote o che iniziano con il carattere ``\texttt{\#}'' vengono
ignorate. In tab.~\ref{tab:modprobe_conf} si sono riportate le principali direttive
disponibili.

% La differenza principale fra
% \texttt{/etc/modules.conf} e \texttt{/etc/modprobe.conf} è nelle direttive
% utilizzabili che per quest'ultimo (l'unico che tratteremo) sono quelle
% illustrate in tab.~\ref{tab:modprobe_conf}; esiste comunque uno script di
% conversione in caso si voglia riutilizzare il contenuto di un vecchio
% \texttt{modules.conf}. 

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Direttiva} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{alias}    & definisce un nome da associare a un modulo, da passare
                        rispettivamente come primo e secondo argomento;
                        eventuali ulteriori argomenti saranno utilizzati come
                        parametri per il modulo in fase di caricamento.\\ 
    \texttt{blacklist}& richiede che il modulo passato come argomento venga
                        ignorato dal sistema di caricamento automatico dei
                        moduli.\\ 
    \texttt{include}  & consente di includere le configurazioni presenti nel
                        file passato come argomento, questo può essere anche
                        una directory, nel qual caso includerà le
                        configurazioni definite nei file in essa contenuti.\\
    \texttt{install}  & consente a \texttt{modprobe} di eseguire il comando,
                        passato come secondo argomento quando si richiede il
                        caricamento del modulo indicato come primo
                        argomento.\\
    \texttt{options}  & definisce, per il modulo passato come primo argomento,
                        quali sono i parametri da utilizzare nel caricamento
                        dello stesso passati negli argomenti successivi.\\ 
    \texttt{remove}   & analogo ad \texttt{install} ma il comando viene
                        eseguito quando si richiede la rimozione di un modulo
                        con \texttt{modprobe -r}.\\
    \hline
  \end{tabular}
  \caption{Le direttive del file di configurazione \texttt{modprobe.conf}.}  
  \label{tab:modprobe_conf}
\end{table}



La direttiva \texttt{alias} permette di associare un nome arbitrario (un
\textit{alias} appunto) ad un modulo che deve essere indicato con il nome del
relativo file oggetto, senza estensione. In questo modo si può usare il nome
dell'\textit{alias} al posto di quello del modulo nella invocazione di
\texttt{modprobe}. \ifx\obsoletesection\undefined \relax \else La direttiva
svolgeva un ruolo fondamentale nella gestione dei moduli dei kernel della
serie 2.4.x dato che in tal caso buona parte della gestione automatica dei
dispositivi veniva realizzata richiedendo il supporto di una certa
funzionalità attraverso l'uso del sistema di \textit{kmod} che a sua volta
richiedeva il caricamento dei moduli necessari invocando \texttt{modprobe} con
un opportuno identificativo.\footnote{vale a dire che con
  \texttt{request\_module} veniva eseguita una richiesta con un identificativo
  generico associato alla funzionalità voluta, a cui poi occorreva associare
  il modulo che la realizzava tramite una direttiva \texttt{alias}.}

Questo identificativo però non era associato direttamente al modulo necessario
(anche quando questo era univoco) e quindi per ottenerne il caricamento
occorreva impostare un \textit{alias}. Inoltre c'era l'ulteriore problema di
sapere quali erano gli identificativi utilizzati dal kernel per funzionalità e
dispositivi, e a quali moduli farli corrispondere. A partire dai kernel della
serie 2.6.x tutto questo è diventato marginale in quanto tutte le volte che il
modulo necessario per una certa funzionalità è univoco questo viene caricato
direttamente, mentre buona parte del lavoro di identificazione dei dispositivi
presenti e caricamento dei moduli necessari al loro uso è stato trasferito
alla nuova infrastruttura per il rilevamento e la gestione dinamica
dell'hardware che vedremo in sez.~\ref{sec:udev_hotplug}.

Per questo la direttiva \texttt{alias} viene usata per lo più qualora si
voglia far caricare un modulo a \texttt{modprobe} usando un nome
diverso. Resta possibile utilizzarla per associare uno specifico modulo ad una
specifica richiesta effettuata dal kernel, solo che queste sono diventate
molto meno comuni.  \fi Si tenga presente che non si possono definire degli
\texttt{alias} a nomi definiti da un altro \texttt{alias}, % \footnote{questa
% è un'altra differenza rispetto a quanto avveniva per \texttt{/etc/modules.conf}.}
mentre invece si possono specificare ulteriori argomenti nella direttiva, che
verranno utilizzati come parametri da passare al modulo in fase di
caricamento.

Una seconda direttiva molto utilizzata è \texttt{options}, che prende come
argomenti il nome di un modulo seguito dai parametri da passare al suddetto
quando questo viene caricato. Si tenga presente che i parametri così definiti
verranno aggiunti a quelli eventualmente specificati con \texttt{modprobe}
sulla riga di comando e a quelli eventualmente definiti in una direttiva
\texttt{alias}. La direttiva è utile in quanto consente di impostare dei
default per i parametri di un modulo in modo da non doverli scrivere tutte le
volte che viene chiamato \texttt{modprobe}.

Una terza direttiva importante è \texttt{blacklist}, che qualora ci siano più
moduli che supportano la stessa periferica consente di evitare che uno di
essi, indicato come argomento, venga utilizzato per il supporto della stessa
nel caricamento automatico. Questa direttiva è nata con il kernel 2.6 a
partire dal quale fra le informazioni presenti all'interno di ciascun modulo
sono stati inseriti anche gli \textit{alias} dei dispositivi e delle
funzionalità che questo supporta (che possono essere visualizzati, come
vedremo a breve, con il comando \texttt{modinfo}) così che il sistema di
rilevamento e la gestione dinamica dell'hardware (vedi
sez.~\ref{sec:udev_hotplug}) possa caricarli in maniera automatica.

Ci sono comunque dei casi in cui una stessa periferica è supportata da moduli
diversi, ma si sa che uno di questi è preferibile agli altri, oppure casi in
cui non si vuole che una certa periferica, pur essendo presente, venga
attivata automaticamente.  L'effetto della direttiva \texttt{blacklist} è di
far ignorare i valori degli \textit{alias} interni al modulo passato come
argomento, così che questo non sia mai caricato automaticamente, pur essendovi
dell'hardware a cui esso è in grado di fornire supporto. % Il contenuto tipico
% del file \texttt{/etc/modprobe.d/blacklist.conf}, dove normalmente si inseriscono
% queste direttive, è infatti per lo più costituito da direttive riguardanti il
% supporto per le funzionalità di \textit{watchdog} che non si vuole siano
% attivate se non viene esplicitamente avviato anche un demone che le gestisce.
% Si tenga presente che indipendentemente dalla presenza di una tale direttiva,
% sarà sempre possibile caricare il modulo con l'uso esplicito di
% \texttt{modprobe}.

Infine le due direttive \texttt{install} e \texttt{remove} consentono di
sostituire rispettivamente il caricamento o la rimozione del modulo indicato
come primo argomento con l'esecuzione del comando indicato come secondo
argomento. In questo modo diventa possibile effettuare operazioni anche molto
complesse (il comando può essere anche uno script di shell) contestualmente al
caricamento o alla rimozione del modulo scelto. Occorrerà però, perché poi il
modulo alla fine venga caricato o rimosso davvero, rieseguire
\texttt{modprobe} all'interno del comando eseguito utilizzando l'opzione
\texttt{-i} per disabilitare l'effetto di queste direttive, ovviamente solo se
lo scopo del comando non è proprio quello di evitare il caricamento del
modulo.

Come accennato per il funzionamento di \texttt{modprobe} occorre che nella
directory dei moduli sia presente il file \texttt{modules.dep} che identifica
le dipendenze fra i vari moduli. È grazie a questo file che è possibile
determinare quali sono i moduli che contengono i simboli necessari ad un altro
modulo, così da poter effettuare il caricamento di tutti quelli che servono
nella giusta sequenza. Questo file viene creato tramite il comando
\index{comando!\texttt{depmod}} \texttt{depmod} che esegue una scansione di
tutti i moduli installati, identificando quali sono i simboli forniti ed
utilizzati da ciascuno, per costruire così le relative dipendenze. Oltre a
\texttt{modules.dep} il comando crea anche altri file, utilizzati
dall'infrastruttura di gestione dei dispositivi (vedi
sez.~\ref{sec:udev_hotplug}).

Se invocato senza argomenti \texttt{depmod} esamina i moduli relativi al
kernel corrente, operando sotto \texttt{/lib/modules/\$(uname -r)}, ma
passandogli come argomento un numero di versione il comando utilizzerà i
moduli relativi a tale versione, assumendo ovviamente che essi siano stati
installati nella corrispondente directory sotto \texttt{/lib/modules}. Si
possono passare come ulteriori argomenti una lista di file nel qual caso il
comando si limiterà ad esaminare il contenuto degli stessi. In genere viene
specificata anche l'opzione \texttt{-a}, che richiede il controllo di tutti i
moduli, che comunque è sottintesa fintanto che non si specifica una lista di
file.

In genere \texttt{depmod} viene invocato automaticamente quando si installano
i moduli con \texttt{make modules\_install} e non è necessario invocarlo di
nuovo a meno che non si sia installato un qualche altro modulo in maniera
indipendente, ad esempio se si sono installati in un secondo tempo dei moduli
non presenti nel kernel che si sta utilizzando per ottenere qualche
funzionalità aggiuntiva. Anche in tal caso comunque è molto probabile che
nello script di installazione degli stessi sia prevista l'invocazione del
comando.

Le due opzioni principali sono \texttt{-A} che prima di effettuare il calcolo
delle dipendenze controlla preventivamente i tempi dei file, aggiornando
\texttt{modules.dep} solo se qualcosa è cambiato e \texttt{-n} che consente
una simulazione dell'esecuzione del comando, scrivendo il risultato
dell'elaborazione dello stesso sullo \textit{standard output} invece che nel
file \texttt{modules.dep}. Per la descrizione dettagliata del comando e di
tutte le altre opzioni si può fare riferimento alla pagina di manuale
accessibile con \texttt{man depmod}. Il comando supporta inoltre l'uso di una
directory di configurazione \index{configurazione!\texttt{/etc/depmod.d/}}
\texttt{/etc/depmod.d} (che sostituisce il precedente
\texttt{/etc/depmod.conf}) in cui inserire altrettanti file \texttt{.conf} per
creare una configurazione. In genere viene usata dalle distribuzioni per
elencare (con la direttiva \texttt{search}) eventuali ulteriori directory da
esaminare; per i dettagli si può consultare \texttt{man depmod.d}.

Uno degli aspetti rilevanti della gestione dei moduli come accennato è la
possibilità di controllarne alcune caratteristiche di funzionamento tramite il
passaggio di opportuni parametri in fase di caricamento. In questo caso il
problema maggiore è identificare detti parametri ed impostarne un valore
appropriato.  Ma se riuscire a determinare il significato dei parametri e dei
rispettivi valori può richiedere ricerche più o meno complesse nella
documentazione del kernel, se non addirittura la consultazione diretta del
codice, per poter iniziare a cercare occorre quantomeno sapere quali sono i
parametri supportati.

A questo scopo diventa molto utile il comando \index{comando!\texttt{modinfo}}
\texttt{modinfo} che consente di esaminare il file oggetto del modulo passato
come argomento ed estrarne una serie di informazioni, la principale delle
quali è la lista dei parametri supportati dal modulo. Un esempio del comando è
il seguente:
\begin{Console}
anarres:~# \textbf{modinfo 8139cp}
filename:       /lib/modules/4.9.36/kernel/drivers/net/ethernet/realtek/8139cp.ko
license:        GPL
version:        1.3
description:    RealTek RTL-8139C+ series 10/100 PCI Ethernet driver
author:         Jeff Garzik <jgarzik@pobox.com>
srcversion:     4CE9007FFA8F7109419F480
alias:          pci:v00000357d0000000Asv*sd*bc*sc*i*
alias:          pci:v000010ECd00008139sv*sd*bc*sc*i*
depends:        mii
intree:         Y
vermagic:       4.9.36 SMP mod_unload modversions 
signat:         PKCS#7
signer:         
sig_key:        
sig_hashalgo:   md4
parm:           debug:8139cp: bitmapped message enable number (int)
parm:           multicast_filter_limit:8139cp: maximum number of filtered multicast addresses (int)
\end{Console}

L'output del comando riporta una serie di campi, identificati per nome e
seguiti da un valore. Nel caso dei parametri del modulo i campi di interesse
sono quelli di tipo \texttt{parm}; nell'esempio allora vediamo come il modulo
\texttt{8139cp} abbia due parametri con valore intero, \texttt{debug} e
\texttt{multicast\_filter\_limit}. Si noti anche come il comando riporti anche
le dipendenze del modulo (nel campo \texttt{depends}) ed una serie di campi
\texttt{alias} che dicono a quali classi di dispositivi o funzionalità il
modulo è in grado di fornire supporto.\footnote{il nome è dovuto al fatto che
  questi campi fanno riferimento proprio ai nomi usati nella direttiva
  \texttt{alias} di \texttt{modprobe.d} per associare un modulo ad una certa
  funzionalità o dispositivo, e vengono usati dal sistema di caricamento
  automatico dei moduli (vedi sez.~\ref{sec:udev_hotplug}) .}

Se invocato con l'opzione \texttt{-k}, seguita da un identificativo di
versione, il comando esaminerà il modulo disponibile per quella versione di
kernel, piuttosto che quello per il kernel corrente; la cosa può risultare
utile se si vogliono esaminare le informazioni di un kernel che si è
installato ma non si sta usando.  Oltre a questa il comando supporta una serie
di opzioni che gli permettono di stampare solo alcune delle informazioni
disponibili, al solito per la descrizione completa si può fare riferimento
alla pagina di manuale.

Una volta che un modulo non sia più utilizzato, se ne può richiedere la
rimozione. Abbiamo visto a come questo possa essere fatto in maniera
``\textsl{intelligente}'' con l'opzione \texttt{-r} del comando
\texttt{modprobe}, che rimuove anche le eventuali dipendenze. Questa
funzionalità però è presente in questa forma solo a partire dai kernel della
serie 2.6.x, in precedenza era previsto un comando apposito,
\index{comando!\texttt{rmmod}} \texttt{rmmod}, che resta ancora come comando
di basso livello per la rimozione dei moduli, nello stesso senso in cui lo è
\texttt{insmod} per l'inserimento.

Il comando prende come argomento il nome di un singolo modulo di cui esegue la
rimozione. Ovviamente perché questa avvenga con successo il modulo in
questione non deve essere in uso, né contenere simboli usati da un altro
modulo (cioè non devono esserci altri moduli che \textsl{dipendano} da esso).
È comunque possibile, a proprio rischio e pericolo, forzare la rimozione con
l'opzione \texttt{-f}, ma per poterla usare si deve avere abilitato in fase di
compilazione del kernel l'opzione \texttt{Forced module unloading}; una
rimozione forzata resta comunque una operazione estremamente pericolosa,
perché rimuovendo un modulo in uso il relativo codice sparisce dal kernel
nonostante vi siano riferimenti ad esso, e si può facilmente causare un crash
del sistema.

Alternativamente si può usare l'opzione \texttt{-w} che blocca ogni ulteriore
utilizzo del modulo indicato, ma prima di effettuarne la rimozione si ferma in
attesa che questo venga liberato da ogni uso residuo. Per l'elenco completo
delle opzioni si consulti al solito la pagina di manuale.

Infine per consultare la lista dei moduli caricati in memoria, e ottenere le
informazioni relative al loro stato si può utilizzare il comando
\index{comando!\texttt{lsmod}} \texttt{lsmod}. Il comando non prende opzioni
né argomenti e a partire dal kernel 2.6 non è altro che un semplice programma
che espone in maniera più leggibile il contenuto del file
\index{filesystem~\texttt{/proc}!\texttt{/proc/modules}}
\texttt{/proc/modules}. Un esempio del risultato di questo comando è il
seguente:
\begin{Console}
anarres:~# \textbf{lsmod}
Module                  Size  Used by
cp2101                 11428  0 
usbserial              26472  1 cp2101
i915                   25280  2 
drm                    65256  3 i915
binfmt_misc             7528  1 
tun                     8292  0 
ppdev                   6468  0 
parport_pc             22500  0 
lp                      8164  0 
parport                30988  3 ppdev,parport_pc,lp
autofs4                16420  0 
...
\end{Console}
% video                  16400  0 
% output                  2912  1 video
% ac                      4196  0 
% battery                10180  0 
% ipv6                  235204  33 
% bridge                 40024  0 
% fuse                   42908  1 
% sbp2                   18572  0 
% loop                   12748  0 
% snd_hda_intel         324248  3 
% pcspkr                  2432  0 
% snd_pcm_oss            32800  0 
% snd_pcm                62628  2 snd_hda_intel,snd_pcm_oss
% snd_mixer_oss          12320  1 snd_pcm_oss

La prima colonna indica il nome del modulo, mentre la seconda le sue
dimensioni in memoria. La terza colonna infine indica se il modulo è in uso ed
è divisa in due parti; all'inizio viene riportato il numero di riferimenti
presenti, che dice quante volte il modulo è utilizzato, a questo segue, se ve
ne sono, la lista dei nomi degli altri moduli che dipendono da esso. Un valore
nullo del numero di riferimenti indica che il modulo non è utilizzato e può
essere rimosso.

Il comando consente di verificare se un modulo è in uso, operazione che è
utile fare prima di richiedere una rimozione che altrimenti
fallirebbe. Inoltre con \texttt{lsmod} si può anche verificare se un modulo è
effettivamente utilizzato, o risulta occupato soltanto a causa della presenza
di dipendenze da esso da parte di altri moduli. In quest'ultimo caso, avendone
la lista, li si potranno rimuovere preventivamente liberando il modulo
originario, che a questo punto potrà essere rimosso a sua volta.

Infine un altro file utilizzato da varie distribuzioni nella gestione dei
moduli è \index{configurazione!\texttt{/etc/modules}} \texttt{/etc/modules},
in cui si può inserire la lista dei moduli che si vuole siano caricati
all'avvio del sistema.  Il formato del file è estremamente semplice, ogni
linea deve contenere il nome di un modulo, al solito le linee vuote o che
iniziano per ``\texttt{\#}'' vengono ignorate. % Un possibile esempio del
% contenuto di questo file, preso dalla versione installata su una Debian
% Stretch, è il seguente:
% \begin{FileExample}[label=/etc/modules]
% # /etc/modules: kernel modules to load at boot time.
% #
% # This file contains the names of kernel modules that should be loaded
% # at boot time, one per line. Lines beginning with "#" are ignored.

% \end{FileExample}

In genere si utilizza questo file per forzare il caricamento di un modulo
all'avvio senza aspettare che questo venga caricato automaticamente. Nelle
distribuzioni più recenti viene usata, per lo stesso scopo, anche la directory
\index{configurazione!\texttt{/etc/modules-load.d/}} con la solita convenzione
di ottenere la lista dei moduli da caricare unendo il contenuto di tutti i
file \texttt{.conf} presenti nella stessa.

%  Oltre al
% file \texttt{modules}, che viene usato per qualunque kernel, Debian supporta
% anche la configurazione dei moduli da caricare all'avvio di kernel specifici;
% ad esempio con il file \texttt{modules-major}, dove \texttt{major} indica il
% numero di versione principale (cioè \texttt{2.4} o \texttt{2.6}) si possono
% indicare i moduli da caricare con i kernel della serie 2.4.x o 2.6.x, mentre
% con il file \texttt{modules-version}, dove \texttt{version} indica una
% versione di kernel si indicano i moduli da caricare all'avvio di quella
% specifica versione.


\section{La gestione dell'avvio del sistema}
\label{sec:struct_boot}

In questa sezione prenderemo in esame la procedura di avvio del sistema,
dettagliando i vari passaggi che portano dall'accensione della macchina al
pieno funzionamento del sistema, e come si possa intervenire (trattando i vari
programmi coinvolti ed i relativi meccanismi di configurazione) a ciascuno
stadio di questa procedura.


\subsection{L'architettura dell'avvio del sistema}
\label{sec:struct_kernel_boot}

Una delle caratteristiche comuni di tutti i computer moderni è che questi
devono prevedere una apposita procedura di avvio che porti dalla macchina
spenta ad un sistema attivo o funzionante. Questo consiste in quel processo
che in inglese viene chiamato \textit{bootstrap}, usando un'espressione
gergale che fa riferimento al paradosso del ``\textsl{sollevarsi da terra
  tirandosi per i lacci degli stivali}'', che sembra analogo al fatto di
riuscire a far eseguire un programma ad un computer che quando parte non ne
contiene alcuno.

In realtà questo non è vero ed in tutte le piattaforme hardware è prevista la
presenza di un programma iniziale, che serve appunto a gestire il
\textit{bootstrap} della macchina. Il successo della procedura è dovuto ad una
caratteristica comune di tutti i processori, che prevede che quando questi
vengono accesi inizino ad eseguire il programma posto ad una specifica
locazione di memoria. È cura di chi assembla la macchina far corrispondere
questa posizione di memoria al suddetto programma di gestione dell'avvio, che
viene mantenuto nella memoria non volatile di cui ogni computer moderno è
dotato, la ROM, o più precisamente la EPROM (in quanto riscrivibile). In
genere si fa riferimento a questo programma con il nome di \textit{firmware},
come via di mezzo fra \textit{hardware} e \textit{software}.

In generale ogni piattaforma hardware ha un suo \textit{firmware} specifico
per quella stessa piattaforma, ed esiste anche una versione libera e
multi-piattaforma di \textit{firmware}, \textit{openfirmware}, creato dalla
Sun ed usato anche da Apple e IBM per piattaforme diverse da quelle degli
ordinari PC compatibili. Nei comuni PC il \textit{firmware} è più noto con il
nome di BIOS, acronimo di \textit{Basic Input/Output System}, che è il nome
dato al \textit{firmware} nei primi PC prodotti dalla IBM.

I \textit{firmware} comunque sono programmi, per cui è sempre possibile avere
delle versioni alternative, che, viste le crescenti capacità dell'hardware
moderno, possono essere molto più sofisticati del BIOS tradizionale. Ad
esempio per alcune piastre madri è disponibile un \textit{firmware}
alternativo, \textit{coreboot}, nato per far eseguire direttamente il kernel
invece del BIOS e velocizzare la procedura di avvio, poi trasformatosi in un
sostituto del BIOS in grado di lanciare altri \textit{firmware} o
\textit{bootloader} oltre che Linux stesso.

Oggi la quasi totalità dei PC nuovi viene fornita con UEFI (\textit{Unified
  Extensible Firmware Interface}), un altro \textit{firmware} alternativo
rispetto al BIOS, le cui specifiche sono state create inizialmente da Intel,
ma che oggi viene gestito dallo \textit{UEFI forum} che vede fra i promotori i
principali produttori di processori e di sistemi operativi proprietari. Un
\textit{firmware} UEFI fornisce a sua volta una interfaccia standardizzata che
permette di gestire tutta la procedura di avvio in maniera molto più
flessibile rispetto al vecchio BIOS. Tutti i \textit{firmware} che supportano
UEFI prevedono comunque anche la possibilità di partire nella cosiddetta
modalità classica, che utilizza le stesse modalità con cui un BIOS
tradizionale permette di lanciare un sistema operativo, per cui tratteremo per
prima queste.

Benché con il BIOS le modalità di avvio dipendano dalla versione disponibile
(in pratica ogni produttore ha realizzato una sua variante), una serie di
caratteristiche sono comuni, e tutti i BIOS più recenti permettono di avviare
il sistema da una varietà di dispositivi, come floppy (se ne trovate ancora di
funzionanti), disco e CDROM. Altre modalità di avvio supportate da tutte le
macchine recenti, ma che potrebbero essere assenti su quelle molto datate,
sono via rete o da chiavetta USB.

In genere il dispositivo da cui effettuare l'avvio si può selezionare tramite
l'apposito menu di configurazione del BIOS che permette di determinare la
sequenza in cui vengono controllati tutti i dispositivi da cui questo è
possibile. Il primo su cui si trovano dati opportuni verrà utilizzato, per cui
in genere si mettono in cima alla lista i dispositivi rimuovibili, così da non
dover cambiare la configurazione e poterli utilizzare semplicemente
inserendoli nella macchina.

La procedura con cui il BIOS può caricare in memoria il sistema operativo
dipende dal supporto da cui quest'ultimo viene prelevato, nel caso di un
floppy il meccanismo è molto semplice: il BIOS legge il primo settore ed
esegue il programma ivi contenuto, che è quello che deve incaricarsi di
eseguire l'avvio. Per i CDROM il meccanismo è lo stesso, solo che detto
settore deve essere letto dalla immagine di un floppy presente all'interno del
CD, in sostanza il BIOS vede solo l'immagine del floppy contenuta nel CD, che
tratta come tale, che è disponibile qualora questo sia stato masterizzato con
le opportune estensioni (le \textit{El Torito}, vedi 
sez.~\ref{sec:swap_CDROM_management}).

%%
%% ### OBSOLETE BEGIN ###
%% Materiale obsoleto sui floppy ed i relativi kernel
%%
\ifx\obsoletesection\undefined

\relax
\else

Il fatto che per lanciare il sistema di un floppy basti eseguirne il contenuto
del primo settore consente una modalità di creazione di un disco di avvio
molto semplice: quando si crea una immagine compressa del kernel (con la
procedura vista in sez.~\ref{sec:kernel_compile}) viene automaticamente
inserito nei primi 512 byte della stessa un programma di avvio che si limita a
caricare il resto dell'immagine in memoria, scompattarlo ed eseguirlo.
Pertanto basta l'uso di \texttt{dd} per copiare direttamente l'immagine del
kernel su un dischetto con un comando del tipo:
\begin{Verbatim}
dd if=bzImage of=/dev/fd0
\end{Verbatim}
per ottenere un floppy di avvio. 

Il problema con un disco d'avvio fatto in questo modo è che non si possono
fornire argomenti all'avvio. In particolare questo significa che il sistema
userà come radice quella in uso quando viene compilata l'immagine. In realtà
alcuni argomenti di avvio in questo caso possono essere modificati con il
comando \index{comando!\texttt{rdev}} \texttt{rdev}.

Se usato senza argomenti il comando si limita a stampare una riga in cui
riporta quale è la partizione impostata come directory radice per il sistema
corrente.  Se si specifica un solo argomento questo deve essere un file
contenente l'immagine di un kernel e allora stamperà la radice predisposta per
quel kernel; se si specifica un secondo argomento questo dovrà essere il
dispositivo contenente la nuova directory radice che andrà a sovrascrivere la
precedente.

Il comando permette anche di modificare anche altri due parametri che sono
mantenuti nell'immagine del kernel, la \textsl{modalità video} usando
l'opzione \texttt{-v}, o invocandolo come \index{comando!\texttt{vidmode}}
\texttt{vidmode}, e la dimensione del \textit{RAM disk} iniziale, usando
l'opzione \texttt{-r} o invocandolo come \texttt{ramsize}. Per i dettagli si
faccia riferimento alla pagina di manuale.

%%
%% ### OBSOLETE END ###
%% Materiale obsoleto sui floppy ed i relativi kernel
%%
\fi

Il caso più comune comunque è quello in cui l'avvio viene fatto dal disco
rigido, un tempo la cosa poteva dipendere dal tipo di disco, se IDE (ATA o
\textit{Serial ATA}) o SCSI e per questi ultimi dal supporto del relativo
controller, oggi tutti i BIOS trattano indifferentemente i vari tipi di disco,
comprese le chiavette USB che vengono viste come normali dischi, secondo una
modalità denominata \textit{USBHDD}.\footnote{esisteva anche una modalità
  alternativa denominata \textit{USBZIP}, usata per avviare da dischi
  estraibili ZIP su USB, ormai dismessa.} Qualora i dischi disponibili siano
più di uno è cura del BIOS fornire un menù di configurazione per impostare
quale usare.

In questo caso la procedura prevede che il BIOS legga il primo settore del
disco scelto per
l'avvio, % \footnote{per BIOS molto vecchi questo poteva essere
  % solo il primo disco IDE, tutti i BIOS più recenti permettono di usare anche
  % gli altri dischi.} 
che anche per questo motivo viene chiamato \textit{Master Boot Record}, ma a
differenza del caso del floppy/CDROM, in cui il primo settore contiene solo il
codice da eseguire, nell'MBR è presente anche la tabella delle partizioni, ed
il codice posto in esecuzione deve essere stato installato in una posizione
opportuna.

Infine nel caso sia disponibile l'avvio via rete questo viene eseguito tramite
il supporto PXE (\textit{Pre-boot eXecution Environment}) che consente di
ottenere l'immagine del \textit{bootloader} (che in questo caso viene chiamato
NBP, \textit{Network Bootstrap Program}) e del kernel da mettere in esecuzione
da un server di rete tramite gli opportuni protocolli. In questo caso occorre
aver installato su un'altra macchina i servizi TFTP e DHCP (tratteremo
quest'ultimo in sez.~\ref{sec:net_DHCP_server}) per mettere a disposizione
tutti i dati necessari.

\itindbeg{bootloader}

Indipendentemente dal supporto scelto, la caratteristica generale resta quella
che il BIOS non è in grado di lanciare direttamente il sistema operativo e
deve ricorrere ad un programma esterno, chiamato \textit{bootloader}, il quale
deve essere stato opportunamente installato sui dispositivi utilizzati per
l'avvio. Questa è una limitazione specifica del BIOS che da sempre ha previsto
l'uso di un \textit{bootloader} separato per effettuare l'avvio del sistema
operativo, limitazione che non è presente nei \textit{firmware} di altre
piattaforme hardware che sono in grado di lanciare direttamente il sistema
operativo, in genere caricandolo da una apposita partizione, con una gestione
che per questo risulta notevolmente semplificata.

In generale il \textit{bootloader} è un programma elementare il cui unico
compito è quello di trovare il sistema operativo, caricarlo in memoria ed
eseguirlo, passandogli eventuali parametri di avvio. Nel caso di Linux questo
significa trovare l'immagine del kernel e, se lo si usa, del \textit{ramdisk}.
Si tenga presente che un \textit{bootloader} oltre che nel \textit{Master Boot
  Record}, può essere installato anche nel settore iniziale di una
partizione. Questo permette allora di concatenare più \textit{bootloader} in
modo che il primo lanci il successivo, e così via, ed in particolare questa è
la tecnica usata normalmente per lanciare il \textit{bootloader} di Windows da
parte dei \textit{bootloader} usati per Linux.

\itindbeg{Unified Extensible Firmware Interface (UEFI)} 

L'introduzione di UEFI come sostituto del BIOS è servita principalmente a
superare l'ostacolo costituito dal limite di dover mantenere il codice di
partenza del \textit{bootloader} nel limitato spazio disponibile nel
\textit{Master Boot Record}, ed al contempo fornire una piattaforma di avvio
avanzata e generica che consentisse di supportare una serie di funzionalità
aggiuntive, come le partizioni GPT (viste in sez.~\ref{sec:partitioning}), il
cosiddetto \textit{secureboot}, ecc.

\itindend{bootloader}

Per superare i limiti dell'uso del \textit{Master Boot Record} è stata
utilizzata la più classica delle soluzioni: aggiungere un altro livello di
redirezione.  A differenza del BIOS classico infatti un \textit{firmware} UEFI
non esegue nessun codice dall'MBR, e benché in modalità di compatibilità la
maggior parte possano eseguire un avvio classico, l'avvio in modalità nativa
richiede la presenza di una partizione riservata, denominata ESP
(``\textit{EFI System Partition}'') in cui installare delle opportune
``\textit{EFI Application}''; sono queste che vengono eseguite dal
\textit{firmware} e che possono effettuare tutte le successive operazioni,
come caricare un \textit{bootloader} ed avviare il sistema.

Una ``\textit{EFI System Partition}'' deve contenere un filesystem di tipo FAT
(ufficialmente è richiesto FAT32, anche se nella gran parte dei casi va bene
anche FAT16) ed essere marcata come tale. Anche se è possibile usare una
partizione classica, che nel caso deve essere di tipo \texttt{EF}, è comunque
opportuno (obbligatorio nel caso si debba avere un dual boot con Windows)
usare le nuove partizioni GPT che sono state introdotte proprio con le
specifiche di EFI. Una ESP in tal caso viene identificata dal GUID
\texttt{C12A7328-F81F-11D2-BA4B-00A0C93EC93B}, e viene impostata da
\texttt{gdisk} con il tipo \texttt{EF00} (si ricordi quanto detto in
sez.~\ref{sec:partitioning}).

All'avvio un \textit{firmware} UEFI esegue le inizializzazioni, recupera i
dati che gli dicono quale applicazione lanciare per l'avvio (se li si sono
impostati dall'interfaccia di gestione interna) e poi la esegue. In assenza
dell'impostazione di una applicazione specifica (cosa che non tutti i
\textit{firmware} consentono) viene eseguita una scansione dei dispositivi
presenti (come CD, dischi, chiavette) cercando all'interno degli stessi
eventuali partizioni ESP, per eseguire il programma di avvio di default che è
sempre \texttt{/efi/boot/boot\textsl{arch}.efi} dove \texttt{\textsl{arch}}
indica l'architettura hardware ed in genere è una sigla breve come
\texttt{ia32}, \texttt{x64}, \texttt{arm} (rispettivamente per le più comuni
piattaforme come PC a 32 bit, a 64 bit e ARM).

L'utilizzo di una partizione dedicata consente di installare ulteriori
applicazioni in grado di fornire le funzionalità più varie. Se poi il proprio
\textit{firmware} UEFI fornisce una interfaccia nativa per farlo si potrà
scegliere quale di queste applicazioni lanciare direttamente all'avvio, oppure
si potrà installare direttamente (col nome di default citato prima) un
\textit{boot manager} come \textit{rEFInd}, che consente di scegliere lui
quale sistema operativo o altra applicazione EFI lanciare sulla base di quanto
installato. Inoltre è anche possibile installare direttamente delle
applicazioni specifiche come una ``\textit{UEFI shell}'' per effettuare
operazioni amministrative prima di lanciare il sistema operativo.

In questo modo ogni sistema operativo può installare un suo
\textit{bootloader}, ed una convenzione vuole che ciascuno utilizzi una sua
sotto-directory specifica; ad esempio Windows usa \texttt{/efi/Microsoft},
mentre le distribuzioni Linux usano \texttt{/efi/NomeDistribuzione/}. Nel caso
di Linux l'applicazione EFI inizialmente utilizzata per l'avvio era ELILO, ma
oggi è disponibile, ed usata praticamente da tutte le distribuzioni, una
versione EFI di GRUB (vedi sez.~\ref{sec:struct_grub}) che in questo caso sarà
lanciato come applicazione EFI invece che direttamente dal BIOS.

\itindend{Unified Extensible Firmware Interface (UEFI)} 
\itindbeg{bootloader}

Pertanto, sia che si usi un BIOS tradizionale, o che si usi UEFI,
nell'architettura dei PC l'avvio del sistema prevede comunque dopo
l'esecuzione del \textit{firmware} un secondo stadio in cui si passa
attraverso l'uso di un \textit{bootloader} il cui compito è quello di caricare
il kernel in memoria e di eseguirlo. Trattandosi di nuovo di un programma,
anche in questo caso esistono diverse alternative (tratteremo nel seguito le
più rilevanti), ma il compito da eseguire è sostanzialmente lo stesso, fornire
una interfaccia in cui si possa scegliere il kernel che si vuole utilizzare
(in genere Linux, ma potrebbe essere anche un kernel BSD, o un programma
diagnostico come \texttt{memtest}) e metterlo in esecuzione.

Oltre a questo i \textit{bootloader} consentono di passare eventuali argomenti
al kernel che mettono in esecuzione e di caricare l'immagine di un
\textit{ramdisk} per fornire un filesystem iniziale con gli strumenti minimi
necessari per individuare e montare il supporto su cui è stato effettivamente
installato tutto il sistema operativo (torneremo su questo in
sez.~\ref{sec:kernel_launch}). Solo a questo punto si passerà allo stadio
successivo, in cui il kernel viene effettivamente eseguito.

\itindend{bootloader}

Una volta messo in esecuzione Linux effettuerà una serie di operazioni
preliminari, come le inizializzazioni delle infrastrutture generiche e dei
dispositivi il cui supporto è stato compilato direttamente nel kernel. Una
volta completata l'inizializzazione dell'hardware tutto quello che resta da
fare è semplicemente montare il dispositivo su cui si trova la \ directory
radice e lanciare il programma di avvio del sistema, che di norma è
\texttt{/sbin/init}.

Nel caso si stia utilizzando un \textit{ramdisk} di avvio, verrà montato
questo come directory radice e lanciato lo \texttt{/sbin/init} del
\textit{ramdisk}, con un ulteriore stadio prima del lancio del programma di
avvio finale. Le operazioni comunque, per quanto riguarda il kernel, si
concludono con il lancio della prima istanza del programma di avvio, tutto il
resto verrà eseguito in \textit{user space}.


\subsection{Il \textit{bootloader} SYSLINUX}
\label{sec:struct_syslinux}


Il \textit{bootloader} SYSLINUX viene per lo più utilizzato per creare le
immagini di avvio usate per floppy, CDROM e chiavette USB. Per i CD è
disponibile anche la variante ISOLINUX, che supporta la stessa sintassi del
file di configurazione ma non necessita di una immagine di un filesystem FAT e
può usare direttamente il contenuto del CD. In genere è il \textit{bootloader}
usato nei dischi di installazione di molte distribuzioni (ad esempio
Debian). Per questo scopo viene utilizzato anche sulle chiavette USB.  Inoltre
la variante PXELINUX è molto diffusa come programma per gestire l'avvio via
rete. Tutte queste varianti condividono la stessa sintassi generale del file
di configurazione, e la stessa forma e funzionalità del prompt di avvio, per
questo buona parte di quanto illustrato in questa sezione può applicarsi anche
alle altre varianti.

Il programma deve la sua popolarità alla relativa semplicità con cui consente
di creare immagini di avvio, in una tipologia di utilizzo cioè in cui non è
molto importante avere una grande flessibilità nel cambiare la versione di
kernel da avviare, come avviene appunto nel caso di un CDROM o di una
chiavetta di installazione.

Uno dei suoi punti di forza è che i dati da cui creare l'immagine d'avvio
vengono mantenuti in un filesystem FAT, cosa che lo rende facilmente
utilizzabile anche per l'uso diretto su chiavette USB che in genere vengono
formattate in questo modo, che possono essere rese avviabili semplicemente
copiandoci i vari file. L'uso di un filesystem FAT rende inoltre molto
semplice modificare una precedente immagine di avvio, in quanto basterà
montarla (direttamente o in \textit{loopback} se la si è messa su un file) per
accedere ai relativi contenuti.

Per creare una immagine d'avvio basterà installare i file necessari sul
filesystem FAT con il comando \index{comando!\texttt{syslinux}}
\texttt{syslinux}, e nel caso di un floppy questo è quanto basta. Nel caso di
una chiavetta USB (o in generale di un disco) invece sarà necessario
sovrascrivere il \textit{Master Boot Record} con la versione fornita insieme
al programma (il file è \texttt{mbr.bin}, che nel caso di Debian viene
installato sotto \texttt{/usr/lib/SYSLINUX}). In tal caso viene richiesta la
sovrascrittura con l'uso di \texttt{dd}, in sostanza per installare il tutto
sul disco \texttt{/dev/sd\textsl{x}} si dovranno usare i comandi:

\begin{Console}
# \textbf{dd conv=notrunc bs=440 count=1 if=/usr/lib/SYSLINUX/mbr.bin of=/dev/sd\textsl{X}}
# \textbf{syslinux /dev/sd\textsl{X}1}
\end{Console}

L'unica opzione significativa è \texttt{-s} che installa una versione
``\textit{safe, slow and stupid}'' che funziona anche con alcuni BIOS
difettosi. Se ci si limita a seguire i passi precedenti all'avvio SYSLINUX
caricherà l'immagine del kernel dal file \texttt{linux}, che si suppone sia
stato copiato a sua volta sul disco (ovviamente per farlo occorrerà
semplicemente montarlo ed effettuare la copia); questo comportamento può
essere personalizzato usando il file \texttt{syslinux.cfg}, che deve essere
anch'esso copiato nella radice del filesystem FAT (è comunque supportata anche
la lettura dai file \texttt{/boot/syslinux/syslinux.cfg} e
\texttt{/syslinux/syslinux.cfg}).

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Direttiva} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{append}  & imposta l'elenco di argomenti da passare al kernel,
                       eventuali altri argomenti inseriti al prompt verranno
                       accodati a questi (consentendo una sovrascrittura), se
                       specificata prima della prima \texttt{label} si applica
                       globalmente.\\
    \texttt{default} & imposta il kernel da usare di default, indicato tramite
                       l'etichetta (fra quelle specificate in una 
                       successiva \texttt{label}) ad esso associata, se non
                       specificato viene usato il valore \texttt{linux}.\\ 
    \texttt{display} & pathname di un file di testo il cui contenuto
                       viene stampato sulla schermata del prompt di avvio.\\
    \texttt{f1},\ldots,\texttt{f12} & pathname di un file il cui contenuto
                       viene stampato al prompt di avvio in conseguenza della
                       pressione dei tasti F1, \ldots, F12.\\
    \texttt{initrd}  & imposta il pathname all'immagine del \textit{ramdisk} 
                       che verrà caricato all'avvio.\\
    \texttt{kernel}  & imposta il pathname all'immagine del kernel che verrà
                       caricata all'avvio.\\
    \texttt{label}   & imposta l'etichetta che identifica una immagine di 
                       kernel, richiede che si specifichi di seguito una
                       direttiva \texttt{kernel} per indicare l'immagine del
                       kernel ed ulteriori direttive che verranno usate
                       qualora si usi quell'etichetta come valore per
                       \texttt{default} o la si scriva sul prompt di avvio.\\
    \texttt{prompt}  & il valore $1$ richiede di mostrare sempre all'avvio 
                       il prompt della riga di comando \textit{syslinux},
                       in caso di valore nullo o in assenza della direttiva il
                       prompt viene mostrato solo premendo uno dei 
                       tasti di controllo (Alt, Shift, ecc.).\\
    \texttt{timeout} & imposta il tempo di attesa (in decimi di secondo) per
                       accedere al prompt di avvio che parta il caricamento del
                       kernel; un valore nullo (il default) inizia
                       immediatamente il caricamento.\\
%    \texttt{serial}  & .\\
%    \texttt{} & .\\
    \hline
  \end{tabular}
  \caption{Direttive di configurazione di \texttt{syslinux.cfg}.} 
  \label{tab:syslinux_config_keyword}
\end{table}

Il formato del file, che è identico anche per le varianti ISOLINUX e PXELINUX,
segue la convenzione di ignorare righe vuote e quanto segue un
``\texttt{\#}'', mentre le configurazioni devono essere indicate da righe
inizianti con una parola chiave seguita da uno o più parametri posti sulla
stessa riga separato da spazi.

La direttiva \texttt{label} seguita da un nome consente di etichettare diverse
immagini del kernel da avviare, queste devono essere specificate con la
direttiva \texttt{kernel} seguita dal pathname del file. Si tenga presente che
per i nomi delle etichette valgono alcune limitazioni presenti per i nomi dei
file MSDOS, ad esempio usare etichette con più di un ``\texttt{.}'' nel nome
farà ignorare quanto segue il secondo punto.  La direttiva \texttt{initrd}
consente di specificare un \textit{ramdisk}; eventuali argomenti del kernel
devono essere specificati con una direttiva \texttt{append}. Un riassunto
delle principali direttive è riportato in
tab.~\ref{tab:syslinux_config_keyword}.  Per i dettagli si può fare
riferimento alla pagina di manuale di \texttt{syslinux} al solito accessibile
con \texttt{man syslinux}.

All'avvio del sistema SYSLINUX mette a disposizione una riga di comando
(esplicitamente o con la pressione di uno dei tasti di controllo (Alt, Shift,
ecc.) con un prompt da cui è possibile scegliere quale immagine usare fra
quelle disponibili. Questa può essere scelta indicandola con il valore usato
nella corrispondente direttiva \texttt{label} della configurazione, altrimenti
si può usare il valore di default linux, ed eventualmente aggiungere ulteriori
parametri di avvio del kernel, che andranno ad aggiungersi a quelli
eventualmente impostati nella configurazione di \texttt{syslinux.cfg}. 

%%
%% ### OBSOLETE BEGIN ###
%% Materiale obsoleto sui floppy ed i relativi kernel
%%
\ifx\obsoletesection\undefined

\relax
\else

\subsection{Il \textit{bootloader} LILO}
\label{sec:struct_lilo}

Uno dei primi \textit{bootloader} creati per Linux è stato LILO, abbreviazione
di \textit{LInux LOader}, che a lungo è stato anche quello che veniva usato da
tutte le distribuzioni per l'avvio da disco rigido. Si tratta di un
\textit{bootloader} con una architettura elementare, che si affida al BIOS per
la lettura del disco, e pertanto risente di tutti i limiti che questo può
avere. Uno di questi problemi è che, a causa delle restrizioni ereditate dai
primi PC illustrate in sez.~\ref{sec:disk_structure}, alcuni vecchi BIOS non
sono capaci di leggere i dischi oltre il 1024-simo cilindro.

In genere LILO viene installato nell'MBR alla fine della procedura di
installazione di una distribuzione. In generale è possibile, come accennato in
precedenza, installarlo all'interno di una partizione, se si dispone di un
altro \textit{bootloader} in grado di eseguirlo.  Una volta eseguito (sia
direttamente dal BIOS, che da un altro \textit{bootloader}) LILO si incarica
di trovare l'immagine del kernel sul disco, caricarla in memoria, passare
tutti gli eventuali parametri di avvio specificati in fase di configurazione,
e poi eseguirla.\footnote{qualora lo si sia richiesto, si può caricare in
  memoria anche l'immagine di un \textit{ramdisk}, che serve come filesystem
  iniziale per il kernel.}  Da questo punto in poi il controllo passa al
kernel, che si incarica di tutto il resto.

La configurazione di LILO è gestita tramite il file
\index{configurazione!\texttt{/etc/lilo.conf}} \texttt{/etc/lilo.conf}, questo
contiene sia le opzioni passate al kernel in fase di avvio, che le direttive
che permettono di controllare direttamente il comportamento del
\textit{bootloader}. Si tenga presente però che, al contrario di quanto
avviene in genere per altri file di configurazione, non basta modificarlo
perché i cambiamenti diventino effettivi al riavvio successivo. Si deve invece
far girare il programma \index{comando!\texttt{lilo}} \texttt{lilo} che
reinstalla il \textit{bootloader} con le nuove opzioni.

In genere si ha a che fare con questo file tutte le volte che si vuole usare
un nuovo kernel. Infatti per poter lanciare un kernel occorre specificarne la
posizione su disco al \textit{bootloader} in modo che questo possa
caricarlo. La cosa va fatta anche se si è semplicemente sovrascritto un kernel
precedente con un altro e pertanto non si è neanche dovuto modificare
\texttt{/etc/lilo.conf}; si ricordi infatti che LILO (il \textit{bootloader},
quello che sta nell'MBR) conosce solo la posizione fisica del kernel nel
disco, non quella logica nel filesystem; pertanto se si sovrascrive un file
non è affatto detto che la posizione fisica del nuovo file sia la stessa (anzi
di norma non lo è affatto) per cui al successivo riavvio senz'altro LILO
potrebbe non essere più in grado di trovare il kernel, con la conseguente
impossibilità di lanciare il sistema.

Il formato di \texttt{/etc/lilo.conf} è simile a quello degli altri file di
configurazione, le linee vuote o che iniziano per ``\texttt{\#}'' vengono
ignorate.  Le altre linee indicano una opzione o una direttiva. Un esempio di
questo file è il seguente:
\begin{Verbatim}[fontsize=\footnotesize,xleftmargin=1cm,xrightmargin=1.5cm]
# Support LBA for large hard disks.
#
lba32
# Specifies the boot device.  This is where Lilo installs its boot
# block.  It can be either a partition, or the raw device, in which
# case it installs in the MBR, and will overwrite the current MBR.
#
boot=/dev/hda
# Specifies the device that should be mounted as root. (`/')
#
root=/dev/hdb5
# Installs the specified file as the new boot sector
#
install=/boot/boot.b
# Specifies the location of the map file
#
map=/boot/map
# Specifies the number of deciseconds (0.1 seconds) LILO should
# wait before booting the first image.
#
delay=30
# message=/boot/bootmess.txt
        prompt
#       single-key
#       delay=100
        timeout=30
# Kernel command line options that apply to all installed images go
# here.  See: The `boot-prompt-HOWTO' and `kernel-parameters.txt' in
# the Linux kernel `Documentation' directory.
#
# append=""
# Boot up Linux by default.
#
default=linux
image=/boot/vmlinuz-2.2.21
        label=linux
        read-only
        optional
image=/boot/vmlinuz-2.2.20
        label=linuxold
        read-only
        optional
# If you have another OS on this machine to boot, you can uncomment the
# following lines, changing the device name on the `other' line to
# where your other OS' partition is.
#
other=/dev/hda1
        label=dos
#       restricted
#       alias=3
\end{Verbatim}

Le direttive sono divise in tre classi principali: le direttive che
specificano opzioni globali, che si applicano al comportamento generale del
\textit{bootloader}, le direttive che specificano opzioni relative alle
singole immagini dei sistemi che si vogliono lanciare, e le direttive che
permettono di passare delle opzioni al kernel (Linux).

La maggior parte delle direttive ricade nella prima classe; di queste forse la
più importante è \texttt{boot}, che specifica il dispositivo su cui installare
il \textit{bootloader}, nel caso è il \textit{Master Boot Record} del primo
disco IDE, indicato tramite il suo file di dispositivo come
\texttt{/dev/hda}. Si può specificare allo stesso modo una partizione, ad
esempio se si volesse installare LILO sulla seconda partizione del primo disco
si sarebbe potuto usare \texttt{/dev/hda2}.

La direttiva \texttt{map} specifica il file (di norma \texttt{boot.map}) che
contiene la mappa della posizione su disco delle varie immagini del kernel;
questa viene definita automaticamente alla installazione del pacchetto e
ricostruita tutte le volte che si lancia il comando \texttt{lilo}.  La
direttiva \texttt{install} invece specifica qual'è il file che contiene il
programma del \textit{bootloader}, ne possono esistere varie versioni, che
presentano una interfaccia di avvio semplificata a menu o semplicemente
testuale.  In genere tutti questi i file referenziati da queste direttive
vengono tenuti, come illustrato in sez.~\ref{sec:file_FHS}, nella directory
\texttt{/boot}.

Le altre direttive globali più usate sono quelle che controllano le modalità
di avvio. Se si specifica \texttt{prompt} il \textit{bootloader} si ferma
all'avvio presentando una riga di comando da cui l'utente può immettere dei
comandi (si tratta in genere di scrivere il nome di uno dei kernel
predefiniti, seguito dalle eventuali opzioni che gli si vogliono
passare). Specificando un numero con \texttt{timeout} si introduce un tempo
massimo (in decimi di secondo) dopo il quale, pur avendo specificato
\texttt{prompt}, si procederà automaticamente all'avvio. Se non si specifica
\texttt{prompt} invece l'avvio verrà effettuato automaticamente, senza
possibilità di intervento dell'utente,\footnote{in realtà è comunque possibile
  ottenere la riga di comando se ti tiene premuto il tasto di shift.} dopo il
numero di decimi di secondo specificato con \texttt{delay}.

Direttive come \texttt{lba32} e \texttt{linear} servono ad indicare a LILO
quale metodo utilizzare per caricare il kernel. Per trovare l'immagine del
kernel sul disco infatti LILO utilizza la posizione dello stesso specificata
dalla \textit{boot map} che contiene la lista degli indirizzi sul disco da cui
leggere una immagine del kernel. Di default questi indirizzi sono indicati
nella notazione classica, specificando cilindro, testina e settore, ed il
caricamento del kernel viene utilizzando l'interfaccia classica illustrata in
sez.~\ref{sec:disk_structure}, questo comporta che si avranno problemi tutte
le volte che si installa un kernel al di là del limite del 1024-simo
cilindro. Con i BIOS (e le versioni di LILO) più recenti, si deve sempre
specificare la direttiva \texttt{lba32}, in tal caso gli indirizzi nella
\textit{boot map} saranno tenuti in forma lineare, e verrà usata la nuova
interfaccia di accesso del BIOS, e ci si potrà dimenticare di tutti i problemi
relativi alla geometria dei dischi.

Qualora il BIOS non supporti queste estensioni, la direttiva \texttt{linear}
mantiene sempre gli indirizzi nella \textit{boot map} in forma lineare, ma per
l'accesso al disco esegue una conversione al vecchio formato, usando la
funzione originale. Questo può essere utile in quanto non è detto che Linux ed
il BIOS concordino sempre sulla geometria del disco; se questo accade e non si
è usato \texttt{linear} all'avvio LILO userà dei valori per cilindro, testina
e settore relativi ad una geometria diversa a quella vista dal BIOS, con
relativo fallimento. Usando \texttt{linear} invece l'idea della geometria che
ha il kernel diventa irrilevante, e sarà LILO ad usare all'avvio la
conversione dell'indirizzo lineare usando la geometria che gli fornisce il
BIOS. L'uso di questa direttiva comunque ha senso solo per i vecchi BIOS che
non supportano LBA.

Con la direttiva \texttt{default} si può scegliere quale, fra le varie
immagini del kernel installate o gli altri sistemi operativi presenti su altre
partizioni, viene selezionato come default per l'avvio (e lanciato quando
scade il tempo specificato da \texttt{timeout}).  Per farlo basta fare
riferimento all'etichetta che si è associata con la direttiva \texttt{label} a
ciascuna immagine o altro sistema presente.

Un'altra direttiva fondamentale è \texttt{root} che definisce il dispositivo
da cui montare la directory radice, nel nostro esempio
\texttt{/dev/hdb5}.\footnote{si noti che non è assolutamente detto che questa
  debba stare sullo stesso disco da cui si lancia il kernel.} Di solito la si
specifica all'inizio del file per utilizzarla come valore di default per tutti
i kernel, ma può essere anche specificata per ciascuna immagine.

La direttiva che permette di identificare un kernel da lanciare è
\texttt{image}, che prende come parametro il file che contiene l'immagine del
kernel. Si ricordi che benché qui essa sia specificata tramite il pathname del
file che la contiene, LILO vi accederà direttamente usando la posizione di
quest'ultima nel disco. Questo significa che se si copia su una di queste
immagini un altro file (ad esempio per un aggiornamento), essendo questo
creato altrove (quando si sovrascrive con \texttt{cp} prima viene creata la
copia, poi cancellato il file preesistente e assegnato il suo nome al nuovo),
fintanto che non si ricrea la \textit{boot map} e la si reinstalla, LILO
continuerà ad accedere alla posizione del vecchio file. Questo significherà
nel migliore dei casi, se si è fortunati e nessuno ha sovrascritto i dati, che
si utilizzerà ancora la vecchia immagine, mentre in caso di sovrascrittura
l'avvio fallirà (in maniera più o meno spettacolare a seconda dei casi).

Per ciascuna direttiva \texttt{image} vanno poi fornite una serie di ulteriori
direttive specifiche da applicare all'avvio di quella immagine. Una sempre
necessaria è \texttt{label} che definisce l'etichetta che identifica
l'immagine, da usare nella fase di avvio e per la direttiva \texttt{default}. 

La direttiva \texttt{initrd} specifica il file da utilizzare come
\textit{ramdisk} per l'avvio, la direttiva \texttt{append} permette di
specificare dei parametri di avvio al kernel, analoghi a quelle che si possono
scrivere al prompt, la direttiva \texttt{read-only} fa montare la radice in
sola lettura (in genere è cura degli script di avvio di rimontarla anche in
scrittura).

Nel caso si voglia lanciare un altro sistema operativo (cosa che di norma si
fa tramite un altro \textit{bootloader}) si deve usare la direttiva
\texttt{other} specificando la partizione su cui si trova quest'ultimo. Anche
questa direttiva deve essere seguita da una \texttt{label}.  L'elenco completo
di tutte le direttive si trova al solito nella pagina di manuale, accessibile
con \texttt{man lilo.conf}.

Una direttiva utile per la sicurezza è \texttt{password} che permette di
proteggere con una password la procedura di avvio. Dato che la password è
scritta in chiaro nel file di configurazione, qualora si usi questa funzione
si abbia anche la cura di proteggerne l'accesso in lettura (il comando
\texttt{lilo} in ogni caso stampa un avviso se questa direttiva viene
utilizzata con un file accessibile in lettura). 

L'uso di questa direttiva permette di controllare le modalità con cui si fanno
partire le varie immagini (o i sistemi operativi alternativi), attraverso
ulteriori direttive da indicare nelle relative sezioni del file di
configurazione. Specificando \texttt{bypass} non viene applicata nessuna
restrizione; specificando \texttt{restricted} si impedisce all'utente di
passare dei parametri al kernel sul prompt, a meno di non fornire la password;
specificando \texttt{mandatory} è necessario fornire la password anche per
avviare la relativa immagine.

Una volta che si sono definite le impostazioni in \texttt{/etc/lilo.conf}, si
può attivarle con il comando \texttt{lilo}. Questo si limita a leggere il
suddetto file e a reinstallare il \textit{bootloader} con i nuovi valori. Il
comando prende varie opzioni che permettono di soprassedere i valori
specificati da \texttt{lilo.conf}, al solito si può fare riferimento alla
pagina di manuale, accessibile con \texttt{man lilo}, per l'elenco completo.

Vale la pena però di ricordarne due, la prima è \texttt{-r} che permette di
specificare una directory nella quale eseguire un \itindex{chroot}
\texttt{chroot} prima di eseguire il comando. Essa è molto utile quando si
avvia il sistema da un disco di recupero (ad esempio se si è fatto qualche
errore con LILO ed il sistema non parte più) perché permette di correggere i
valori nel \texttt{lilo.conf} del disco, e ripristinare il sistema
reinstallando il \textit{bootloader} come se lo si fosse fatto direttamente
dal disco originale; ovviamente in tal caso occorre montare il disco da
qualche parte nel sistema usato come recupero e poi usare \texttt{lilo -r}
sulla directory su cui lo si è montato.

La seconda opzione è \texttt{-R} che invece specifica una riga di comando da
passare a LILO al successivo riavvio, come se la si scrivesse direttamente dal
prompt. L'utilità dell'opzione è che questo avviene una \textsl{sola} volta,
per cui solo il riavvio successivo userà le nuove opzioni; così se qualcosa
non va, ed il riavvio fallisce, basterà far riavviare la macchina un'altra
volta per riavere i valori precedenti, che si presume siano funzionanti.

%%
%% ### OBSOLETE END ###
%% Materiale obsoleto sui floppy ed i relativi kernel
%%
\fi


\subsection{I \textit{bootloader} GRUB e GRUB2}
\label{sec:struct_grub}

\itindbeg{bootloader}

Uno dei più sofisticati \textit{bootloader} disponibili per Linux, è GRUB,
nome che sta per \textit{Grand Unified Bootloader}. GRUB è nato come
\textit{bootloader} per il sistema HURD\footnote{HURD è un sistema libero
  sperimentale realizzato dalla FSF, basato su una architettura microkernel,
  con funzionalità teoricamente molto avanzate; ma il cui sviluppo è ancora
  molto limitato.}  ma è in grado di avviare qualunque altro tipo di sistema
(compreso Linux e BSD). Benché sia ancora usato è stato sostituito in quasi
tutte le distribuzioni più recenti dalla sua evoluzione, GRUB2.

La caratteristica principale di GRUB è che è formato da diverse parti, dette
\textsl{stadi}, ciascuno dei quali, come gli omonimi dei razzi, viene usato
per lanciare il successivo. In sostanza poi gli stadi sono due, il primo viene
installato sull'MBR ed il suo unico compito è quello di lanciare lo stadio
successivo, che poi si incaricherà di effettuare tutte le operazioni
successive.  Il grande vantaggio di GRUB è che siccome il primo stadio deve
solo occuparsi di trovare il secondo ed è quest'ultimo che fa tutto il lavoro,
tutte le restrizioni che si applicano ad un programma che deve stare nell'MBR
scompaiono.

Per questo GRUB è in grado di leggere nativamente i principali filesystem,
cosicché non solo si può fare riferimento alle immagini del kernel attraverso
un pathname, ma si ha anche a disposizione una micro-shell che consente di
navigare attraverso un filesystem ed esplorarne il contenuto. Questo vuol dire
che basta cambiare il file di configurazione di GRUB o sovrascrivere una
immagine del kernel perché la nuova versione sia usata al successivo riavvio,
e non è necessario eseguire la reinstallazione nel \textit{Master Boot Record}
come per \textit{bootloader} primitivi come era LILO, evitando i guai che
nascono tutte le volte che ci si dimenticava di farlo.  Un altro grande
vantaggio è che GRUB può ricevere i comandi all'avvio non solo dalla
\textit{console}, ma anche via seriale e via rete, dato che non ha bisogno del
BIOS per gestire l'I/O, il che lo rende molto più
flessibile.  % Inoltre non è limitato, sui vecchi BIOS che non lo supportano, a
% lanciare il sistema dal primo canale IDE, ma, essendo di nuovo indipendente
% dal BIOS, può usare uno qualunque dei dischi presenti.

Tutti i file di GRUB sono mantenuti in \texttt{/boot/grub}, in questa
directory si trovano i file \texttt{stage1} e \texttt{stage2} che contengono i
due stadi standard usati nell'avvio, e una serie di file \texttt{*\_stage1\_5}
che contengono gli stadi intermedi che GRUB utilizza per accedere ai contenuti
di diversi filesystem (ne esiste uno per tipo di filesystem, e sono supportati
tutti i principali filesystem di Linux). Il file \texttt{device.map} contiene
invece la lista dei dispositivi riconosciuti da GRUB in fase di installazione,
e come questi vengono mappati nella notazione interna di GRUB, un esempio di
questo file è il seguente:
\begin{FileExample}[label=/boot/grub/device.map]
(fd0)   /dev/fd0
(hd0)   /dev/hda
\end{FileExample}
che ci mostra il caso di una macchina su cui sono presenti un floppy ed un
disco rigido.

I dispositivi vengono identificati da GRUB con un nome fra parentesi tonde, il
floppy viene sempre identificato con \texttt{fd0} (nel caso ci siano due
floppy ci sarebbe anche \texttt{fd1}) mentre i dischi vengono identificati, in
ordine di rilevazione, con \texttt{hd0}, \texttt{hd1}, ecc.  Si tenga presente
che GRUB non distingue i nomi per i dischi IDE o SCSI, quindi anche questi
ultimi verrebbero identificati con la sigla \texttt{hd\textsl{N}}, dove
\texttt{\textsl{N}} è semplicemente un numero progressivo che dipende
dall'ordine di rilevamento.

Il file \texttt{device.map} viene generato con il comando di installazione di
GRUB, \index{comando!\texttt{grub-install}} \texttt{grub-install}; questo
prende come argomento il dispositivo su cui si vuole installare GRUB come
\textit{bootloader} (si tenga presente che in tal caso si andrà a
sovrascrivere un eventuale altro \textit{bootloader} presente su tale
dispositivo). Il comando copia anche nella directory \texttt{/boot} tutti i
file di GRUB, e gli si può dire di usare una radice diversa con l'opzione
\texttt{-{}-root-directory=DIR}. Il comando esegue anche una scansione dei
dispositivi e crea \texttt{device.map}.

In teoria GRUB non ha un vero e proprio file di configurazione, infatti se
avviato come \textit{bootloader} mette a disposizione una shell da cui è
possibile eseguire tutti i suoi comandi interni. Questa stessa shell è
disponibile anche se lo si esegue come semplice programma in user space,
lanciandolo con il comando \index{comando!\texttt{grub}} \texttt{grub}. I
comandi di GRUB sono molteplici ed oltre a quelli usati per impostare l'avvio
dei vari kernel, ce ne sono altri da usare in modalità interattiva, come
\texttt{find} e \texttt{cat} che come gli analoghi della shell sono quelli che
forniscono rispettivamente la capacità di cercare i file e di visualizzarne il
contenuto. La shell di GRUB inoltre offre funzionalità avanzate come
l'auto-completamento di comandi e nomi dei file, ed anche un \textit{help on
  line} con il comando \texttt{help}.

Ma al di là della possibilità di uso interattivo la modalità principale con
cui viene usato GRUB è quella in cui si inseriscono tutti i comandi necessari
in un apposito file, \index{configurazione!\texttt{menu.lst}}
\texttt{menu.lst}, posto sempre sotto \texttt{/boot/grub}, così che questi
vengano eseguiti automaticamente all'avvio. In questo modo \texttt{menu.lst}
diventa una sorta di file di configurazione, tanto che alcune distribuzioni
installano sotto \texttt{/etc} il file \texttt{grub.conf} come link simbolico
a questo file, ed i vari comandi di GRUB assumono il significato di direttive
di configurazione.

Il vantaggio di usare \texttt{menu.lst} è che questo permette di creare anche
un menu semi-grafico in formato testo dal quale scegliere quale kernel o altro
sistema avviare, pertanto in genere all'installazione di GRUB come
\textit{bootloader} segue anche quella di un appropriato \texttt{menu.lst}.
Il contenuto tipico di questo file è qualcosa del tipo:
\begin{FileExample}[label=menu.lst]
## default num
# Set the default entry to the entry number NUM. Numbering starts from 0, and
# the entry number 0 is the default if the command is not used.
#
# You can specify 'saved' instead of a number. In this case, the default entry
# is the entry saved with the command 'savedefault'.
default         0

## timeout sec
# Set a timeout, in SEC seconds, before automatically booting the default entry
# (normally the first entry defined).
timeout         5

# Pretty colours
color cyan/blue white/blue

## password ['--md5'] passwd
# If used in the first section of a menu file, disable all interactive editing
# control (menu entry editor and command-line)  and entries protected by the
# command 'lock'
# e.g. password topsecret
#      password --md5 $1$gLhU0/$aW78kHK1QfV3P2b2znUoe/
# password topsecret

title           Debian GNU/Linux, kernel 2.6.18-4-686
root            (hd0,0)
kernel          /boot/vmlinuz-2.6.18-4-686 root=/dev/hda1 ro 
initrd          /boot/initrd.img-2.6.18-4-686
savedefault

title           Debian GNU/Linux, kernel 2.6.18-4-686 (recovery mode)
root            (hd0,0)
kernel          /boot/vmlinuz-2.6.18-4-686 root=/dev/hda1 ro single
initrd          /boot/initrd.img-2.6.18-4-686
savedefault
\end{FileExample}
%$
e su Debian si può anche usare il comando \index{comando!\texttt{update-grub}}
\texttt{update-grub}, che effettua una ricerca dei kernel presenti in
\texttt{/boot/} e crea automaticamente una lista con le relative voci in
\texttt{menu.lst}.\footnote{il comando di Debian usa anche alcuni dei commenti
  dentro \texttt{menu.lst} per generare parametri e valori usati nelle singole
  voci create automaticamente.}

Le varie voci che compariranno nel menu iniziale sono introdotte dal comando
\texttt{title}, che specifica la stringa con cui queste verranno mostrate, ad
esso si associa in genere il comando \texttt{root}, che specifica quale disco
e partizione usare come ``\textsl{radice}'' per cercare i file a cui si fa
riferimento nei comandi seguenti. Questa viene indicata con la notazione di
GRUB, in cui si indica fra parentesi tonde il dispositivo, seguito da una
virgola e dal numero progressivo della partizione a partire da zero. Nel caso
precedente allora si dice di cercare il kernel nella prima partizione del
primo disco, in sostanza \texttt{/dev/hda1}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Comando} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{chainloader}& indica di lanciare il \textit{bootloader} che si
                      trova all'inizio della partizione impostata come radice,
                      prende in genere un argomento (\texttt{+1} nel caso di
                      Windows) che indica a quanti settori dall'inizio della 
                      partizione stessa si trova il secondo
                      \textit{bootloader}.\\
    \texttt{default}& indica quale fra le voci del menu deve essere avviata di
                      default, prende come argomento un numero progressivo che
                      parte da 0.\\
    \texttt{initrd} & indica il file da cui caricare l'immagine di un
                      \textit{ramdisk}.\\ 
    \texttt{kernel} & indica il file da cui caricare in memoria il codice da
                      eseguire come kernel all'avvio.\\
    \texttt{makeactive} & marca come ``\textsl{attiva}'' la partizione
                      indicata come radice, necessario quando questa è la
                      partizione di avvio di Windows (usato in abbinamento con
                      \texttt{chainloader}).\\
    \texttt{password}&imposta una password che blocca l'accesso alla riga di
                      comando durante l'avvio.\\
    \texttt{root}   & imposta il dispositivo (disco e partizione) da usare
                      come radice per i nomi dei file usati dagli altri
                      comandi.\\
    \texttt{timeout}& indica quanto tempo, in secondi, deve passare prima
                      che venga avviata la voce di default.\\
    \texttt{title}  & imposta una voce nel menu di avvio, e usa l'argomento
                      seguente come titolo della stessa.\\ 
%    \texttt{serial} &  .\\
%    \texttt{}   & .\\
    \hline
  \end{tabular}
  \caption{Principali comandi usati nella configurazione di GRUB.} 
  \label{tab:grub_command_directives}
\end{table}

L'immagine del sistema operativo da caricare si specifica con la direttiva
\texttt{kernel}, seguita dal pathname del file. Si tenga presente che questo è
relativo alla partizione stessa (non esiste il concetto di radice in GRUB),
per cui se ad esempio si è posto \texttt{/boot} su un'altra partizione non è
più necessario specificarla nel nome del file.  Nel caso di Linux al nome del
file si devono far seguire le opzioni da passare al kernel all'avvio, fra cui
occorre comunque specificare il dispositivo da montare come radice
(nell'esempio precedente con \texttt{root=/dev/hda1}), se si usa un
\textit{ramdisk} si dovrà specificare anche il relativo file con il comando
\texttt{initrd}.

Il comando \texttt{default} permette di stabilire quale immagine, nella lista
di quelle dichiarate, deve essere lanciata se l'utente non interviene, dopo un
tempo di attesa specificato con \texttt{timeout}. Inoltre è possibile
proteggere l'accesso alla shell di GRUB, che di default è sempre accessibile,
con la direttiva \texttt{password}, che oltre alla password in chiaro accetta
come argomento anche la stessa in formato MD5, scritta nella stessa forma in
cui viene espressa in \texttt{/etc/shadow}.

I principali comandi usati come direttive di configurazione all'interno di
\texttt{menu.lst} sono riportati in tab.~\ref{tab:grub_command_directives},
una lista dei comandi interattivi come accennato può essere ottenuta con il
comando \texttt{help}, mentre l'elenco completo delle funzionalità di GRUB è
illustrato in dettaglio sia nel \textit{GRUB-HOWTO} che nelle pagine info del
programma, accessibili con \texttt{info grub}.

Benché GRUB sia ancora diffuso, il suo sviluppo è stato ormai completamente
abbandonato in favore della suo successore GRUB2, che lo sta progressivamente
soppiantando.  Questo però non è una evoluzione del precedente, ma una
completa riscrittura, cosa che ha consentito di superare alcuni dei limiti
originali, come quello di non saper gestire il RAID software, che richiedeva
la necessità di installare GRUB separatamente in maniera manuale su entrambi i
dischi.

Le principali nuove funzionalità fornite da GRUB2 sono quella di poter
accedere al contenuto dei volumi logici di LVM, quella di gestire meccanismi
di partizionamento diversi da quelli classici (con il supporto delle nuove
partizioni GPT usate da UEFI), la disponibilità di una versione usabile con
UEFI, la possibilità di essere utilizzato su piattaforme diverse da quella dei
PC e la capacità di identificare direttamente i filesystem con il loro UUID
(vedi sez.~\ref{sec:file_disk_management}) invece che attraverso un file di
dispositivo o l'indicazione di una partizione.

Il problema è che con la riscrittura le modalità di configurazione sono state
completamente rivoluzionate, basandole su un sistema di moduli che forniscono
le varie funzionalità e su un linguaggio di scripting (con tanto di istruzioni
condizionali) che viene eseguito dal \textit{bootloader} stesso. Se da una
parte questo ha aumentato la flessibilità e le capacità di GRUB2, dall'altra
ha reso il file di configurazione molto più complesso rispetto al precedente
\texttt{menu.lst}, portandolo al limite dell'illeggibilità, per cui diventa
molto più complicato fare delle correzioni alla configurazione durante
l'avvio.

Nell'uso comune però questa maggiore complessità viene mascherata in quanto il
file di configurazione non deve più essere modificato direttamente, ma
generato attraverso il comando \index{comando!\texttt{grub-mkconfig}}
\texttt{grub-mkconfig}. Di default il comando stampa la configurazione
generata sullo \textit{standard output}, e si deve usare l'opzione \texttt{-o}
per effettuare il salvataggio nella posizione standard in cui viene letto
all'avvio, che è \index{configurazione!\texttt{/boot/grub/grub.cfg}}
\texttt{/boot/grub/grub.cfg}.\footnote{su Debian si può continuare ad usare
  anche \texttt{update-grub}, che semplicemente chiama \texttt{grub-mkconfig}
  passandogli l'opzione ``\texttt{-o /boot/grub/grub.cfg''}.}

La configurazione viene costruita da \texttt{grub-mkconfig} in base alle
istruzioni contenute in una serie di script di shell, che fan parte del
pacchetto, installati sotto \texttt{/etc/grub.d}. Oltre a questi viene
utilizzato il contenuto del file
\index{configurazione!\texttt{/etc/default/grub}} \texttt{/etc/default/grub},
che così viene a costituire il file su cui si opera normalmente per le
principali modifiche che si possono apportare alla configurazione. Il file è
un segmento di codice shell che assegna dei valori ad alcune variabili, in
modo che questi vengano utilizzati dagli script di \texttt{/etc/grub.d}.

Di default \texttt{grub-mkconfig} crea per ogni immagine del kernel presente
in \texttt{/boot} due voci nel menù di avvio, una per l'avvio ordinario, ed
una per l'avvio in \textit{single user mode} (vedi
sez.~\ref{sec:struct_sysv_init}) o modalità di recupero equivalente. Le voci
sono ordinate sulla base al numero di versione dei kernel presenti, mettendo
in cima alla lista la versione più recente. Le opzioni di avvio da passare al
kernel vengono indicate con le variabili \texttt{GRUB\_CMDLINE\_LINUX} (per
tutte le voci) e \texttt{GRUB\_CMDLINE\_LINUX\_DEFAULT} (aggiunte alle voci
relative all'avvio ordinario). Se sulla macchina sono presenti anche altri
sistemi operativi vengono generate in coda alla lista ulteriori voci per
poterli lanciare.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Variabile} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{GRUB\_CMDLINE\_LINUX}& indica gli argomenti da inserire 
                            nella riga di comando di tutti i kernel, sia
                            quelli per l'avvio ordinario che per l'avvio in
                            \textit{single user mode}.\\
    \texttt{GRUB\_CMDLINE\_LINUX\_DEFAULT}& indica gli argomenti da inserire
                            nella riga di comando del kernel per un avvio
                            ordinario, da aggiungere a quelli di
                            \texttt{GRUB\_CMDLINE\_LINUX}.\\
    \texttt{GRUB\_DEFAULT}& indica quale fra le voci del menu deve essere
                            avviata di default, prende come argomento un
                            numero progressivo che parte da 0 (il default),
                            oppure l'etichetta che identifica una voce del
                            menu iniziale, o la parola chiave \texttt{saved}
                            per indicare quello salvato in un precedente avvio
                            (nel qual caso occorre anche definire
                            \texttt{GRUB\_SAVEDEFAULT=true}).\\  
    \texttt{GRUB\_DISABLE\_RECOVERY}& se impostata a \texttt{true} non genera
                            per ogni kernel la seconda voce usata per avviare
                            il sistema in \textit{single user mode}.\\ 
    \texttt{GRUB\_SERIAL\_COMMAND}& indica la direttiva di configurazione per
                            la seriale da usare se si è indicato
                            \texttt{serial} come valore di
                            \texttt{GRUB\_TERMINAL}, da specificare con una
                            linea contenente la direttiva \texttt{serial} ed i
                            rispettivi argomenti usati da \texttt{grub.cfg},
                            ad esempio:

                            \texttt{"serial -{}-speed=38400 -{}-unit=0 
                              -{}-word=8 -{}-parity=no -{}-stop=1"}\\ 
    \texttt{GRUB\_TERMINAL}&indica il terminale con cui interagire con GRUB2
                            all'avvio della macchina, con valori
                            come \texttt{console} (il default, che indica la
                            console nativa della macchina), \texttt{serial}
                            (per l'uso di una seriale da impostare con
                            \texttt{GRUB\_SERIAL\_COMMAND}) ed altri a seconda
                            dell'architettura hardware della macchina; si
                            possono specificare più valori separati da spazi
                            per utilizzare dispositivi multipli.\\ 
    \texttt{GRUB\_TIMEOUT}& indica quanto tempo, in secondi, deve passare
                            prima che venga avviata la voce di default.\\
%    \texttt{}   & .\\
    \hline
  \end{tabular}
  \caption{Principali variabili di \texttt{/etc/default/grub} usate nella
    configurazione di GRUB2.}
  \label{tab:grub2_config_variables}
\end{table}


Il kernel che viene avviato di default viene indicato assegnando un valore
alla variabile \texttt{DEFAULT}, che viene a costituire l'equivalente della
direttiva \texttt{default} di GRUB, il valore di default è 0, che indica la
prima voce, che nella generazione del file di configurazione viene associata
all'avvio ordinario del kernel con la versione più recente.  La variabile
consente, oltre all'indicazione numerica della voce da avviare (contando a
partire da zero), di specificare una stringa identificativa (quella che
compare nel menù di avvio, corrispondente alla direttiva \texttt{menuentry} di
\texttt{grub.cfg}) o il valore speciale \texttt{saved} per ripartire
dall'ultima voce usata.  Le altre variabili più rilevanti sono riportate in
tab.~\ref{tab:grub2_config_variables}, per i dettagli si consulti la
documentazione di GRUB2, accessibile con \texttt{info grub}, nella sezione
``\textit{Configuration}''.

Si tenga presente che \texttt{grub-mkconfig} genera semplicemente il file di
configurazione, per l'installazione è sempre disponibile il comando
\texttt{grub-install} che opera in maniera analoga al vecchio GRUB e richiede
come argomento il dispositivo su cui effettuare l'installazione, solo che in
questo caso è in grado di funzionare correttamente anche se lo si installa sui
dischi di un RAID1 software (vedi sez.~\ref{sec:RAID_mdadm}). Il comando
inoltre supporta anche l'installazione su sistemi che usano EFI al posto del
BIOS tradizionale, nel qual caso la partizione di sistema di EFI deve essere
montata sotto \texttt{/boot/efi} e non sono necessari ulteriori argomenti.

In realtà in questo caso \texttt{grub-install} può dipendere da una corretta
impostazione dei valori di \texttt{device.map}, e questo, se è cambiata la
versione del kernel (ad esempio perché si sta usando un sistema di recupero),
può contenere, essendo in genere basato su identificativi dei dischi generati
da \textit{udev}, dei nomi non corrispondenti a quelli del kernel corrente,
che farebbero fallire il comando.

Il contenuto di questo file può comunque essere rigenerato con il comando
\texttt{grub-mkdevicemap}, che lo aggiorna agli identificativi corretti
secondo il kernel corrente, così che i dischi su cui installare GRUB2 possano
essere identificati correttamente. Si può anche usare il comando con l'opzione
\texttt{-m} seguita da un pathname per ottenere il risultato su un file
diverso, o direttamente sullo \textit{standard input} con il nome
``\texttt{-}''. 

Benché grazie all'uso di \texttt{grub-mkconfig}, non sia più necessario
intervenire manualmente su \texttt{grub.cfg}, cosa da evitare sempre visto che
le modifiche verrebbero perse alla successiva invocazione del
comando,\footnote{qualora si vogliano introdurre delle direttive permanenti,
  ad esempio per eseguire una configurazione ad hoc non gestibile attraverso
  \texttt{/etc/default/grub}, queste devono essere generate con un opportuno
  script dentro \texttt{/etc/grub.d/}; ad esempio Debian fornisce il file
  \texttt{40\_custom} dove mettere le proprie personalizzazioni.} una
conoscenza di base di alcune direttive fondamentali utilizzate in questo file
resta comunque necessaria qualora ci si debba trovare nella condizione di
doverle modificare in fase di avvio dalla console di GRUB2. Non tratteremo
pertanto in maniera estesa la sintassi di questo file di configurazione (che
come accennato consente anche costrutti evoluti come condizionali e cicli)
limitandoci a prendere in esame il necessario per orientarsi in caso di
emergenza. 

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Direttiva} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{boot}     & esegue l'avvio del sistema operativo caricato; da usare
                        esplicitamente solo sulla riga di comando, è implicita
                        nella chiusura di una voce di menu.\\
    \texttt{initrd}   & carica l'immagine di un \textit{ram disk} e ne
                        predispone l'uso da parte del kernel; richiede come
                        argomento obbligatorio il pathname a partire
                        dalla radice indicata dalla variabile di ambiente
                        \texttt{root}.\\
    \texttt{insmod}   & carica un modulo, da indicare come argomento, a
                        partire dalla directory indicata dalla
                        variabile di ambiente \texttt{prefix} (in genere
                        \texttt{/boot/grub}).\\
    \texttt{linux}    & carica il file con l'immagine di un kernel Linux;
                        richiede come primo argomento obbligatorio il
                        pathname a partire dalla radice indicata dalla
                        variabile di ambiente \texttt{root}, cui possono
                        essere aggiunti eventuali argomenti successivi che
                        saranno passati al kernel (quelli di cui abbiamo
                        parlato in sez.~\ref{sec:struct_kernel_boot}).\\ 
    \texttt{menuentry}& crea una voce per il menu di avvio, deve essere
                        seguita da una stringa (delimitata dal carattere
                        ``\texttt{'}'') che ne indica il titolo, da eventuali
                        opzioni e dalla serie di direttive da eseguire per
                        quella voce, comprese fra parentesi graffe.\\ 
    \texttt{serial}   & attiva la console su seriale, richiede che si indichi
                        con \texttt{-{}-unit} l'interfaccia seriale da usare (se
                        più di una sono numerate progressivamente a partire da
                        zero), con \texttt{-{}-speed} la velocità, con
                        \texttt{-{}-word} per il numero di bit, con
                        \texttt{-{}-parity} l'uso della parità, con
                        \texttt{-{}-stop} gli \textit{stop bit} (per il
                        significato di questi parametri si rimanda a
                        sez.~\ref{sec:serial_interface}).\\
    \texttt{set}      & imposta una variabile di ambiente di GRUB2, nella forma
                        \texttt{variabile=valore}.\\ 
%    \texttt{}   & .\\
    \hline
  \end{tabular}
  \caption{Principali direttive di configurazione di GRUB2.}
  \label{tab:grub2_directives}
\end{table}

Dalla console di avvio infatti è sempre possibile, attraverso l'interfaccia
fornita da GRUB2, modificare sia la configurazione generale che le varie
direttive utilizzate all'interno di ciascuna voce di menu. Fra queste le due
più rilevanti sono \texttt{linux} che indica il pathname assoluto all'immagine
del kernel da avviare, seguita dagli argomenti della riga di comando con cui
lo si lancia (quelli di sez.~\ref{sec:struct_kernel_boot}), e \texttt{initrd}
che indica il pathname assoluto del \textit{ramdisk} usato nell'avvio. Qualora
si voglia far partire un kernel in una posizione diversa (ad esempio perché si
è perso il contenuto di \texttt{/boot}) si dovrà intervenire su queste
direttive. Come accennato una trattazione dettagliata di tutte le direttive va
al di la dello scopo di questo testo, si sono elencate più rilevanti in
tab.\ref{tab:grub2_directives}, per il resto si rimanda alla documentazione
accessibile con \texttt{info grub}.

Un'altra direttiva fondamentale molto usata nella configurazione è
\texttt{set}, che in generale consente di impostare una variabile di ambiente
nella forma \texttt{variabile=valore}. Si può definire e poi riutilizzare una
variabile qualunque, ma GRUB2 usa alcune variabili di ambiente speciali (il
cui nome è riservato) per modificare il proprio comportamento, ed è appunto
attraverso l'impostazione di dette variabili che viene effettuata una parte
essenziale della configurazione di \texttt{grub.cfg}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Variabile} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{default} & indica la voce di default da usare per l'avvio del
                       sistema, può essere indicato con il valore numerico
                       della stessa (contata da $0$) o con il valore della
                       stringa usata come argomento della direttiva
                       \texttt{menuentry} che la definisce.\\
    \texttt{prefix}  & indica il pathname della directory dei file di GRUB2
                       (\texttt{/boot/grub}) da cui vengono risolti i nomi dei
                       file usati da GRUB2 (ad esempio quelli dei moduli).\\ 
    \texttt{root}    & indica il filesystem da usare come radice per la
                       risoluzione 
                       dei nomi dei file, equivalente alla direttiva
                       \texttt{root} di GRUB1, il valore deve essere
                       specificato con la sintassi illustrata in seguito.\\ 
    \texttt{timeout} & indica il tempo da attendere (in secondi) prima di
                       avviare il sistema con la voce di default.\\ 
%    \texttt{}   & .\\
    \hline
  \end{tabular}
  \caption{Principali variabili di ambiente della configurazione di GRUB2.}
  \label{tab:grub2_environ_variables}
\end{table}

Fra queste variabili speciali sono di particolare rilevanza \texttt{root}, che
serve ad indicare il dispositivo ed il filesystem su cui cercare i file usati
da GRUB2, e \texttt{default}, che indica il kernel da avviare di default, e
che in sostanza svolgono il ruolo delle omonime direttive di GRUB1. Le altre
variabili di ambiente speciali più rilevanti sono illustrate in
tab.~\ref{tab:grub2_environ_variables}, per l'elenco completo si consulti la
sezione ''\textsf{Environment}'' della documentazione, accessibile con
\texttt{info grub}.

Si tenga presente però che con GRUB2, avendo ottenuto il supporto di
molteplici dispositivi, schemi di partizionamento e filesystem, è stata
modificata la modalità di identificazione dei dispositivi, pertanto i valori
da usare per la variabile di ambiente \texttt{root} non corrispondono
necessariamente a quelli usati per la omonima direttiva di GRUB, anche se per
compatibilità si possono usare gli stessi valori con lo stesso significato.

I dischi infatti vengono ancora identificati direttamente con la stessa
nomenclatura e numerati progressivamente a partire da zero, ma in genere le
partizioni sono identificate con una stringa che ne specifica il formato (che
per quelle ordinarie è \texttt{msdos}) e viene mantenuta la numerazione
ordinaria vista in sez.~\ref{sec:partitioning}, pertanto la prima partizione
del primo disco sarà identificata come \texttt{(hd0,msdos1)} e non come
\texttt{(hd0,0)}. Se invece si usa il nuovo di schema di partizionamento con
GPT si potrà indicare direttamente una partizione con il suffisso
\texttt{gpt}, utilizzando una indicazione come \texttt{(hd0,gpt1)}.

Ma oltre alla identificazione diretta in stile classico, grazie all'uso degli
opportuni moduli, GRUB2 è in grado di utilizzare direttamente i filesystem su
un RAID software o su un volume logico di LVM (che tratteremo rispettivamente
in sez.~\ref{sec:RAID_mdadm} e \ref{sec:disk_LVM}), ed è in grado di accedervi
sia identificandoli direttamente (per numero di array o con la sintassi
\texttt{nomegruppo-nomevolume}) che attraverso il relativo UUID (si rammenti
sez.~\ref{sec:file_disk_management}); pertanto si potranno avere indicazioni
come \texttt{(md/0)}, \texttt{(lvm/\textsl{vg-root})} o
\texttt{(mduuid/\textsl{2e405c525b920c94e725973a2a998466})}.

\itindend{bootloader}


\subsection{Lancio del kernel, \textit{ramdisk} ed avvio del sistema}
\label{sec:kernel_launch}


\itindbeg{kernel boot parameters}

Come accennato in sez.~\ref{sec:struct_kernel_boot} uno dei compiti del
\textit{bootloader} all'interno della procedura di avvio è quello di passare
degli argomenti al kernel all'atto del metterlo in esecuzione. Infatti in fin
dei conti anche il kernel un è programma per cui gli si possono passare degli
argomenti, solo che normalmente non esiste una riga di comando da cui
darglieli, se non quella che può eventualmente mettere a disposizione il
\textit{bootloader}, che in questo caso svolge il ruolo della shell, e deve
anche essere in grado, per alcuni argomenti, di fornire una opportuna
interpretazione.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Argomento} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{console=dev}& specifica un file di dispositivo da usare come
                          \textit{console} per i messaggi del kernel.\\ 
    \texttt{init=command}&specifica il programma da lanciare come primo
                           processo del sistema (di default è
                           \texttt{/sbin/init}).\\
    \texttt{initrd=file}& specifica un \textit{RAM disk}
                          iniziale che verrà usato come radice provvisoria; in
                          realtà questo parametro viene utilizzato solo dal
                          \textit{bootloader} che ha anche il compito di
                          interpretare il significato di \texttt{file} per
                          ottenere i dati del \textit{ramdisk}.\\
    \texttt{mem=size}   & imposta la dimensione della memoria da utilizzare,
                          veniva utilizzato per soprassedere il
                          malfunzionamento del sistema di auto-rilevamento del
                          kernel.\\
    \texttt{noacpi}     & non utilizza ACPI per l'instradamento degli
                          \textit{interrupt} di processore.\\ 
    \texttt{noapic}     & disabilita l'uso delle I/O APIC (vedi
                          sez.~\ref{sec:expansions_interface}).\\
    \texttt{nosmp}      & disabilita il funzionamento in modalità
                          multiprocessore.\footnotemark \\ 
    \texttt{quiet}      & disabilita la stampa sulla \textit{console} della
                          maggior parte dei messaggi del kernel.\\
    \texttt{ro}&          all'avvio monta la directory radice in sola
                          lettura.\\  
    \texttt{root=dev}   & specifica (in genere col nome del file di
                          dispositivo) il disco (o la partizione) da montare
                          come radice.\\
    \texttt{rootdelay}  & numero di secondi da attendere prima di tentare di
                          montare la radice (utile per dischi lenti a
                          partire).\\ 
    \texttt{single}&      indica ad \texttt{init} di andare in \textit{single
                           user mode} (vedi
                          sez.~\ref{sec:struct_sysv_init}).\\     
%    \texttt{vga=mode}   & dove \texttt{mode} è un valore intero che stabilisce
%                          la \textit{modalità video} in cui utilizzare la
%                          \textit{console}, o il valore \texttt{ask} per fare
%                          eseguire una scansione.\\
%    \texttt{}   & .\\
    \hline
  \end{tabular}
  \caption{Principali argomenti per la linea di comando del kernel.} 
  \label{tab:kernel_boot_options}
\end{table}

\footnotetext{opzione di compatibilità che disabilita le I/O APIC (vedi
  sez.~\ref{sec:expansions_interface}) oltre far funzionare il kernel in
  modalità mono-processore, è l'equivalente di \texttt{maxcpus=0}, valore
  particolare dell'opzione che a sua volta consente di specificare quanti
  processori usare su un sistema SMP; in genere, come \texttt{noapci} e
  \texttt{noapic} la si usa in caso di problemi di avvio dovuti a
  implementazioni difettose del kernel, del BIOS o della scheda madre.}

In genere gli argomenti passati al kernel servono ad impostare parametri per
alcuni sottosistemi o ad attivare o disabilitare funzionalità specifiche
all'avvio.  Essi vengono espressi nella stessa forma dei parametri per i
moduli illustrati in sez.~\ref{sec:kernel_modules}, anche perché i moduli che
supportano l'uso di parametri a cui assegnare un valore in fase di caricamento
(vedi sez.~\ref{sec:kernel_modules}), quando vengono compilati all'interno del
kernel possono ricevere il suddetto valore in questo modo.  Pertanto gli
argomenti possono essere espressi sia come singola parola chiave, che nella
forma \texttt{chiave=valore}, dove \texttt{valore} può essere un numero, una
stringa, o una lista separata da virgole.

In tab.~\ref{tab:kernel_boot_options} si è riportato un elenco degli argomenti
del kernel più rilevanti nell'uso comune, ed il relativo significato; si può
trovare una lista più completa nel file \texttt{kernel-parameters.txt} della
documentazione allegata ai sorgenti del kernel o nel
\textit{boot-prompt-HOWTO}. La lista è solo parziale, e riguarda solo i
parametri del kernel, quelli dei moduli e quelli relativi ad architetture
specifiche sono riportati in altri file sempre sotto la directory
\texttt{Documentation} allegata ai sorgenti, ma la documentazione talvolta è
incompleta e poco aggiornata. Si tenga presente che il kernel ignora gli
argomenti che non riconosce, e che questi vengono passati direttamente al
programma di avvio, in questo modo è possibile usarli anche per controllare il
comportamento di quest'ultimo.

In alcuni casi può essere necessario usare degli argomenti di avvio diversi da
quelli preimpostati; uno dei più comuni è quello in cui si deve usare
l'argomento \texttt{root} per cambiare il dispositivo da usare come radice, ad
esempio perché si è spostato il disco, o si vuole fare l'avvio da una
partizione diversa, oppure occorre usare l'argomento \texttt{init} per
specificare un programma di avvio diverso da \texttt{/sbin/init}, ad esempio
per sostituirlo con \texttt{/bin/sh} facendo partire direttamente una shell di
\textit{root}, così da essere in grado di accedere alla macchina con privilegi
amministrativi per ripristinare una password di \textit{root} persa o
dimenticata.

A parte questi due l'altro parametro più usato è \texttt{console} che consente
di specificare il dispositivo relativo ad una \textit{console} su cui dirigere
i messaggi del kernel, che viene usato in particolare sui sistemi embedded per
mandare i messaggi sulla linea seriale, a cui si potrà accedere con un modem.
Una volta avviato il sistema è possibile risalire alla linea di comando con la
quale è stato avviato il kernel, che viene riportata nel contenuto del file
\index{filesystem~\texttt{/proc}!\texttt{/proc/cmdline}}
\texttt{/proc/cmdline}.

Infine può capitare, in particolare con alcune schede madri e BIOS difettosi,
di dover disabilitare alcune funzionalità del kernel che altrimenti possono
causare un blocco dell'avvio dello stesso a causa di alcuni bug; per questo
motivo in certi casi può essere necessario far partire il kernel disabilitando
alcune funzionalità, ad esempio disabilitando il sistema \textit{APIC} (vedi
sez.~\ref{sec:expansions_interface}) per la gestione degli \textit{interrupt},
o farlo partire in modalità mono-processore.

\itindend{kernel boot parameters}

Come già detto fin da sez.~\ref{sec:struct_sys_arch}, una volta messo in
esecuzione, il kernel esegue due soli compiti: monta la directory radice e
lancia il programma di inizializzazione del sistema, che tradizionalmente è
\texttt{/sbin/init}, e tutto il resto viene demandato a
quest'ultimo. Ovviamente per poter far questo il kernel deve essere in grado
di accedere al dispositivo su cui si trova la radice, montare il relativo
filesystem ed eseguire detto programma.

\itindbeg{ramdisk}

Due degli errori più comuni, che comportano l'impossibilità di proseguire
nella procedura di avvio, sono proprio quelli relativi all'impossibilità di
montare la radice, ad esempio perché ci si è dimenticati di inserire nel
kernel il supporto per accedere al dispositivo su cui essa si trova o quello
per il suo filesystem, o all'impossibilità di lanciare \texttt{init} ad
esempio perché si è danneggiato il programma, o qualche libreria, o si è
indicata come radice una partizione sbagliata.

Dato che oggi la varietà di dispositivi su cui è possibile installare un
sistema è estremamente ampia, abbiamo visto in sez.~\ref{sec:kernel_install}
come nella gran parte dei casi (è una politica ormai adottata da tutte le
distribuzioni) sia previsto di appoggiarsi all'uso di un \textit{ramdisk} che
contenga l'immagine di un filesystem iniziale (creato in RAM) che sarà quello
effettivamente montato come radice. 

In questa modalità di avvio si ha un ulteriore stadio in cui è il programma di
avvio lanciato dal \textit{ramdisk} che individua il supporto di installazione
del sistema operativo; in tal caso infatti è possibile montare sia
\texttt{/sys} che \texttt{/proc} ed utilizzare comandi come \texttt{blkid} per
identificare i dispositivi con gli UUID, caricare tutti i moduli necessari,
avviare il RAID e riconoscere i dispositivi LVM qualora questi fossero
utilizzati. Alla fine si potrà utilizzare il valore dell'argomento
\texttt{root} passato al kernel (rilevabile dal contenuto di
\texttt{/proc/cmdline}) anche in forma diversa dell'indicazione di un file di
dispositivo, ed usare supporti rilevabili o disponibili solo in un secondo
tempo.

Una volta identificato il dispositivo che contiene la propria installazione
del sistema operativo, il programma di avvio del \textit{ramdisk} lo monta e
poi utilizza il comando \texttt{pivot\_root} per spostare su di esso la radice
ed infine esegue il programma di inizializzazione finale al di sotto di questa
al proprio posto con una \texttt{exec}; di nuovo qual'è questo programma potrà
essere scelto sulla base dell'argomento \texttt{init} passato al kernel,
sempre rilevabile dal contenuto di \texttt{/proc/cmdline}.

\itindend{ramdisk}

Dato il suo ruolo particolare, il primo processo lanciato dal kernel (che per
questo ha PID 1) è in sostanza il protagonista principale della procedura di
avvio e svolge un compito fondamentale per il funzionamento del sistema
operativo, dato che è suo compito mettere in esecuzione tutti i programmi che
lo rendono effettivamente utilizzabile;\footnote{e non solo per questo, si
  ricordi il ruoli che \texttt{init} che svolge nella gestione dei processi
  \textsl{orfani} (vedi sez.~\ref{sec:struct_proc_property}).} per questo è a
lui che si fa riferimento per la gestione dei servizi da avviare o fermare. E
come per le altre componenti interessate al processo di avvio anche in questo
caso esistono varie alternative (e diversi programmi) che possono svolgere
questo compito. 

Fino a qualche anno la principale differenza era quella originata negli anni
'70, con la scissione con le varianti di Unix derivate dalla versione
sviluppata alla AT/T, che poi diventerà \textit{System V}, o quella sviluppata
a Berkeley, che darà origine alla famiglia dei BSD. In questo caso la
differenza non era tanto nelle funzionalità di \texttt{init}, dato si che
tratta sempre di lanciare gli opportuni programmi, quanto nella modalità in
cui questi venivano avviati.

Nei sistemi derivati da BSD questo veniva fatto attraverso l'esecuzione di
alcuni script. Attivare o meno un servizio dipende dall'inserimento o meno (al
posto ``\textsl{giusto}'') delle opportune righe di avvio all'interno di
essi. I sistemi derivati da \textit{System V} usano una procedura più
complessa, con script suddivisi per servizio ed eseguiti in opportuna sequenza
(che tratteremo in dettaglio in sez.~\ref{sec:struct_sysv_init}) che offre
maggiore funzionalità e soprattutto è più ``\textsl{modulare}''.

Nel caso di Linux, che è stato sviluppato da zero e non deriva da nessuna
delle due famiglie di Unix, si è sempre cercato di prendere il meglio dei due
mondi, il risultato è che pochissime distribuzioni hanno adottato la modalità
di BSD, e la gran parte han preferito, per la sua maggiore flessibilità, lo
stile di avvio di \textit{System V}.

In realtà, anche se lanciato per primo, e con un ruolo particolare,
\texttt{init} resta comunque un programma eseguito in \textit{user space}, che
può essere tranquillamente sostituito da altri (ad esempio da una shell, come
accennato in precedenza), per cui negli anni sono state proposte varie
alternative, anche per cercare di superare le problematiche relative alla
intrinseca sequenzialità della procedura di avvio classica, che può portare a
tempi di partenza del sistema anche piuttosto lunghi.

Questo ha dato vita alla realizzazione di una serie di alternative, come
\textit{Upstart}, \textit{OpenRC}, \texttt{systemd}, ispirate a filosofie
progettuali completamente diverse, che esamineremo in
sez.~\ref{sec:systemd_upstart}, concentrandoci in particolare su
\texttt{systemd}, che sta ottenendo una adozione molto ampia, essendo stato
scelto come nuovo programma di avvio nelle versioni più recenti delle
principali distribuzioni come Debian, RedHat, SuSE e derivate.


\subsection{Il sistema di avvio alla \textit{System V}}
\label{sec:struct_sysv_init}

Come accennato in sez.~\ref{sec:kernel_launch} fino qualche anno fa la gran
parte delle distribuzioni GNU/Linux aveva adottato lo stile di avvio di
\textit{System V}, basato su un \texttt{init} tradizionale, che resta comunque
supportato, per compatibilità, anche da tutti i candidati alla sua
sostituzione. Per questo lo tratteremo per primo anche se oggi la sua
diffusione sembra essere destinata ad essere sempre meno rilevante.

\itindbeg{runlevel}

L'avvio ``\textsl{alla System V}'' (o \textit{SysV init}, come viene spesso
chiamato) avviene sulla base dei cosiddetti \textit{runlevel}, una sorta di
\textsl{modalità operative} del sistema in cui viene lanciato un particolare
insieme di programmi, che garantiscono la presenza di un certo gruppo di
servizi.  È possibile selezionare sia quali programmi lanciare (ed in che
ordine) in ciascun \textit{runlevel}, sia quale \textit{runlevel}
utilizzare. Inoltre è possibile passare da un \textit{runlevel} all'altro. È
compito di \texttt{init} portare il sistema in un certo \textit{runlevel},
secondo quanto specificato nella sua configurazione.

\itindbeg{single~user~mode}

I \textit{runlevel} validi sono 8, quelli effettivamente utilizzati sono
numerati da 0 a 6. A questi si aggiunge il runlevel ``S'', che riveste un
ruolo speciale e serve ad indicare quali sono i servizi che devono essere
attivati comunque. La standardizzazione di LSB prevede che tre runlevel siano
riservati; il \textit{runlevel} 0 viene usato per fermare il sistema, mentre
il \textit{runlevel} 6 per riavviarlo. Infine il \textit{runlevel} 1 serve per
andare nel cosiddetto \textit{single user mode}, la modalità di recupero in
cui può entrare nel sistema solo l'amministratore e solo dalla console, con
tutti i servizi disattivati e con la directory radice montata in sola lettura.

\itindend{single~user~mode}

Per gli altri \textit{runlevel} le caratteristiche possono variare da
distribuzione a distribuzione, con o senza servizi di rete, avvio terminante
con il login direttamente da X, etc.  Per Debian il default prevede che da 2 a
5 essi siano tutti equivalenti, mentre RedHat e SuSE usano il 2 per l'avvio in
console senza rete, il 3 per l'avvio in console con la rete ed il 5 per
l'avvio in modalità grafica.

Tutto il procedimento di avvio viene controllato dal file di configurazione di
\texttt{init} che è \index{configurazione!\texttt{/etc/inittab}}
\texttt{/etc/inittab}. Il formato di questo file è molto semplice, come per
molti altri le linee vuote o che iniziano per ``\texttt{\#}'' vengono
ignorate, le altre prevedono la presenza di quattro campi separati dal
carattere ``\texttt{:}'' nella forma:
\begin{FormattedExample}
\textsl{id}:\textsl{runlevels}:\textsl{action}:\textsl{process}
\end{FormattedExample}

Il primo campo, \texttt{\textsl{id}}, è una semplice etichetta composta da 1 a
4 caratteri che identifica la singola linea (anche se in certi casi fa
riferimento a delle azioni speciali). Il secondo campo,
\texttt{\textsl{runlevels}}, indica la lista dei \textit{runlevel} a cui si
applica la riga in questione. Il terzo campo, \texttt{\textsl{action}}, indica
la modalità con cui \texttt{init} eseguirà il comando indicato nel quarto
campo, \texttt{\textsl{process}}, quando il \textit{runlevel} corrente
corrisponde ad uno di quelli elencati nel secondo campo. In questo modo è
possibile utilizzare \texttt{inittab} per elencare ad \texttt{init} quali sono
i programmi da lanciare all'avvio e quali sono le operazioni da eseguire per
ciascun \textit{runlevel}. 

Per capire meglio il funzionamento della procedura di avvio di \textit{SysV}
conviene però fare riferimento ad un esempio del contenuto di
\texttt{inittab}. Riportiamo di seguito un estratto dalla versione del file
installata su una Debian Squeeze:
\begin{FileExample}[label=/etc/inittab]
# The default runlevel.
id:2:initdefault:
# Boot-time system configuration/initialization script.
# This is run first except when booting in emergency (-b) mode.
si::sysinit:/etc/init.d/rcS
# What to do in single-user mode.
~~:S:wait:/sbin/sulogin
# /etc/init.d executes the S and K scripts upon change
# of runlevel.
l0:0:wait:/etc/init.d/rc 0
l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2
l3:3:wait:/etc/init.d/rc 3
l4:4:wait:/etc/init.d/rc 4
l5:5:wait:/etc/init.d/rc 5
l6:6:wait:/etc/init.d/rc 6
...
# What to do when CTRL-ALT-DEL is pressed.
ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now
# What to do when the power fails/returns.
pf::powerwait:/etc/init.d/powerfail start
pn::powerfailnow:/etc/init.d/powerfail now
po::powerokwait:/etc/init.d/powerfail stop
# /sbin/getty invocations for the runlevels.
#
# The "id" field MUST be the same as the last
# characters of the device (after "tty").
1:2345:respawn:/sbin/getty 38400 tty1
2:23:respawn:/sbin/getty 38400 tty2
3:23:respawn:/sbin/getty 38400 tty3
4:23:respawn:/sbin/getty 38400 tty4
5:23:respawn:/sbin/getty 38400 tty5
6:23:respawn:/sbin/getty 38400 tty6
...
\end{FileExample}

Si tenga presente che questo file viene letto da \texttt{init} all'avvio
mentre le azioni in esso specificate vengono eseguite sia nella procedura di
avvio che ad ogni cambio di \textit{runlevel} (torneremo su questo argomento
più avanti).  Specificando come azione \texttt{wait} si richiede che il
programma sia eseguito una sola volta, attendendo che esso sia concluso prima
di passare all'azione successiva; nell'esempio è questo il caso con lo script
\texttt{/etc/init.d/rc} che, come vedremo fra poco, è quello che viene usato
per avviare e fermare i servizi. Se invece non è necessario attendere la
conclusione si può usare \texttt{once}.

Specificando \texttt{respawn} si chiede che il comando sia messo in esecuzione
immediatamente, senza attendere la sua conclusione, per proseguire coi
successivi; si richiede inoltre che esso sia rilanciato automaticamente ogni
volta che se ne termina l'esecuzione. Questo è quello che nell'esempio viene
fatto con \texttt{getty} per avere i terminali di login attivi sulle varie
console: ogni volta che ci si collega al sistema \texttt{getty} eseguirà
\texttt{login} per l'autenticazione e questo eseguirà la shell,\footnote{si
  ricordi che mettere in esecuzione un nuovo programma non comporta la
  creazione di un nuovo processo, nella catena di esecuzioni successive il
  processo resterà sempre lo stesso.} all'uscita dalla shell, \texttt{init},
accorgendosi della terminazione del processo, rilancerà di nuovo
\texttt{getty}.

Il problema che spesso si verifica nella interpretazione del contenuto di
\texttt{inittab} è che il significato di alcune azioni non è di immediata
comprensione, in quanto ve ne sono di indipendenti dal \textit{runlevel}
scelto, come \texttt{powerwait}, \texttt{powerfailnow}, \texttt{powerokwait},
mentre \texttt{initdefault} non esegue nulla ma serve invece ad impostare il
\textit{runlevel} di default, cioè quello che viene usato quando viene fatto
partire il sistema. Inoltre non contribuisce alla chiarezza il fatto che il
campo \texttt{id} può essere soggetto a delle restrizioni, come nel caso delle
righe di \texttt{getty} che richiedono vi si usi il numero della console.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Valore} & \textbf{Significato} \\
    \hline
    \hline
%    \texttt{}           & .\\
    \texttt{boot}        & il comando viene eseguito una sola volta all'avvio
                           del sistema; il valore del \textit{runlevel} viene
                           ignorato.\\  
    \texttt{bootwait}    & il comando viene eseguito una sola volta all'avvio
                           del sistema attendendo per il suo completamento; il
                           valore del \textit{runlevel} viene ignorato.\\  
    \texttt{ctrlaltdel}  & esegue il processo specificato quando \texttt{init}
                           riceve un segnale di \texttt{SIGINT} o se si
                           utilizza la combinazione di tasti
                           \texttt{ctrl-alt-del}, viene usato in genere per
                           invocare \texttt{shutdown} (vedi
                           sez.~\ref{sec:runlevel_control}).\\  
    \texttt{initdefault} & indica quale \textit{runlevel} deve essere
                           utilizzato all'avvio, il campo indicante il
                           programma da eseguire viene ignorato.\\ 
    \texttt{once}        & il comando viene eseguito una volta all'ingresso
                           nel \textit{runlevel} specificato senza aspettare
                           la sua terminazione prima di proseguire.\\ 
    \texttt{powerfailnow}& eseguito quando viene comunicato ad \texttt{init}
                           da parte del programma di gestione del gruppo di
                           continuità che le batterie si stanno esaurendo.\\
    \texttt{powerokwait} & eseguito quando viene notificato ad \texttt{init}
                           il ritorno della corrente sulla linea elettrica.\\ 
    \texttt{powerwait}   & eseguito quando viene notificata ad \texttt{init}
                           la caduta della linea elettrica da parte del
                           programma di gestione del gruppo di continuità.\\ 
    \texttt{respawn}     & il comando viene eseguito all'ingresso nel
                           \textit{runlevel} senza aspettare la sua
                           terminazione e viene rieseguito tutte le volte 
                           che termina.\\ 
    \texttt{sysinit}     & il comando viene eseguito all'inizio della
                           procedura di avvio, prima di qualunque voce
                           relativa alle azioni \texttt{boot} o
                           \texttt{bootwait}; il valore del \textit{runlevel}
                           viene ignorato.\\ 
    \texttt{wait}        & il comando viene eseguito una volta all'ingresso
                           nel \textit{runlevel} specificato e si aspetta la sua
                           terminazione prima di proseguire.\\ 
    \hline
  \end{tabular}
  \caption{Principali valori delle azioni indicabili nel terzo campo di
    \texttt{/etc/inittab}.}  
  \label{tab:inittab_actions}
\end{table}

In tab.~\ref{tab:inittab_actions} sono riportati i principali valori ed il
rispettivo significato delle parole chiave che possono essere usate per il
campo \texttt{action}; i dettagli e l'elenco completo si trovano al solito
nella pagina di manuale, accessibile con \texttt{man inittab}.

In genere non c'è molto da fare con questo file, l'unica cosa che può servire
è cambiare la linea dell'azione \texttt{initdefault} per cambiare il
\textit{runlevel} di default, e passare ad esempio dal login da
\textit{console} a quello grafico.\footnote{sempre che questo sia previsto
  come un \textit{runlevel} indipendente dalla distribuzione; per RedHat
  questo significa mettere un 5 al posto di 3, mentre in Debian questa
  differenza non esiste.} Una seconda azione che si può voler modificare (ad
esempio disabilitare) è quella che imposta la reazione alla combinazione di
tasti \texttt{ctrl-alt-del} che nell'estratto è specificata dall'azione
\texttt{ctrlaltdel}, ed invoca il programma \texttt{shutdown} (vedi
sez.~\ref{sec:runlevel_control}) per riavviare il computer.

Si noti come nell'esempio citato il primo comando eseguito sia quello
associato dall'azione \texttt{sysinit}. Questa è una delle azioni speciali
indipendente dal \textit{runlevel}, che viene eseguita soltanto all'avvio
della macchina e che nell'esempio prevede l'esecuzione dello script
\texttt{/etc/init.d/rcS}. Questa è la scelta di Debian in cui questo script non
fa altro che chiamare lo stesso \texttt{/etc/init.d/rc} invocato sul
\textit{runlevel} S, in modo che si possono inserire nella directory
\texttt{/etc/rcS.d} gli script che si vuole siano eseguiti all'avvio
indipendentemente da qualunque \textit{runlevel}. Su RedHat (e derivate) viene
invece usato al suo posto lo script \texttt{/etc/rc.d/rc.sysinit} in cui di
nuovo sono inserite tutte le operazioni di prima inizializzazione del sistema,
da eseguire qualunque sia il \textit{runlevel} scelto.

Come accennato il grosso della procedura di avvio viene gestito dallo script
\texttt{/etc/init.d/rc} che nell'esempio precedente viene invocato, sia pure
con un argomento diverso, per ciascun \textit{runlevel}, utilizzando l'azione
\texttt{wait} per attenderne il completamento. È compito infatti di questo
script fermare e avviare i servizi che sono richiesti per il \textit{runlevel}
specificato come argomento.

Per eseguire questo compito esso si basa sul fatto che le modalità con cui si
ferma ed avvia un servizio sono state a loro volta standardizzate. In
particolare secondo le specifiche LSB è previsto che ciascun programma e
servizio debba fornire un proprio script di avvio, da porsi, secondo quanto
specificato dal \textit{Filesystem Hierarchy Standard}, in
\texttt{/etc/init.d/}.\footnote{tradizionalmente gli script di avvio di RedHat
  erano posti invece sotto \texttt{/etc/rc.d}; questo non corrisponde alla
  standardizzazione di LSB, per cui nelle versioni più recenti di questa
  distribuzione le varie directory previste dallo standard sono state
  realizzate tramite dei link simbolici, alcuni pathname potrebbero comunque
  non corrispondere.} Questi script devono prevedere anche l'uso di alcuni
argomenti standard: \texttt{start}, che avvia il servizio, \texttt{stop} che
lo ferma, \texttt{restart} che prima lo ferma e poi lo riavvia,
\texttt{reload} che fa rileggere la configurazione.

Se allora si va ad analizzare il codice di \texttt{/etc/init.d/rc}, che può
essere un buon esercizio per studiare la sintassi avanzata della shell, ci si
accorgerà che a grandi linee quello che lo script fa è verificare la presenza
di una directory \texttt{/etc/rc\textsl{N}.d}, (alcune vecchie distribuzioni
potrebbero mantenerla ancora sotto \texttt{/etc/init.d/}) dove
\texttt{\textsl{N}} corrisponde al numero del \textit{runlevel} passato come
argomento, per ricavare la lista dei file in essa presenti. Osservando il
contenuto di queste directory vedremo che contengono tutte una serie di link
simbolici agli script di avvio dei servizi posti in \texttt{/etc/init.d/},
chiamati con lo stesso nome ma preceduto da una sigla composta da una
\texttt{S} od una \texttt{K} seguite da un numero di due cifre.

Dopo aver letto la lista dei file presenti \texttt{/etc/init.d/rc} si limita
ad eseguire tutti questi script in ordine alfabetico, passando l'argomento
\texttt{stop} a quelli che iniziano per ``\texttt{K}'' (che sta per
\textit{kill}) e l'argomento \texttt{start} a quelli che iniziano per
``\texttt{S}'' (che sta per \textit{start}).  In questo modo i servizi
indicati dai rispettivi script vengono fermati o avviati, e nell'ordine
stabilito dalle due cifre usate nella sigla.

In questo modo è possibile, per ogni servizio, avere uno script di avvio
personalizzato, da mettere in \texttt{/etc/init.d/}, e poi programmarne la
partenza o l'arresto in un certo \textit{runlevel} creando un semplice link
simbolico nella relativa directory. Si può anche, grazie alle due cifre
presenti nei nomi dei link, decidere in quale punto della sequenza di avvio
lanciare un certo servizio, ad esempio un server di rete dovrà essere lanciato
sempre dopo che questa è stata attivata.

Si noti inoltre come la presenza dei servizi attivi in un determinato
\textit{runlevel} possa dipendere da come si è arrivati ad esso; nel passaggio
da un \textit{runlevel} ad un altro infatti i servizi avviati dal primo
vengono fermati dal secondo solo in presenza di un corrispondente script
iniziante per \texttt{K}, altrimenti restano attivi, anche se non sono
previsti fra quelli che verrebbero avviati se si andasse direttamente in quel
\textit{runlevel}.

Benché sia possibile attivare o disattivare un servizio su un certo
\textit{runlevel} creando semplicemente un link simbolico con l'opportuna
sigla iniziale, sono comunque disponibili innumerevoli programmi in grado di
automatizzare il compito. Alcuni di questi consentono anche di generare la
corretta posizione nella sequenza di avvio, utilizzando le informazioni
presenti negli script stessi (in genere in forma di commento iniziale).

Nel caso di Debian e derivate gli script di avvio sono in genere gestiti con
\index{comando!\texttt{update-rc.d}} \texttt{update-rc.d}. Il comando prende
come primo argomento il nome dello script di avvio, e come secondo l'azione da
compiere su di esso. L'uso più comune del comando è con l'azione
\texttt{remove}, che consente di rimuovere da tutti i \textit{runlevel} ogni
riferimento (sia di avvio che di arresto) allo script indicato. In genere, a
meno che non si sia già cancellato lo script da \texttt{/etc/init.d/}, occorre
anche usare l'opzione \texttt{-f}, altrimenti il comando fallirà, pertanto se
si vuole rimuovere dalla procedura di avvio l'uso di \texttt{atd} si potrà
eseguire il comando:
\begin{Example}
update-rc.d -f atd remove
\end{Example}

Se invece si vuole installare uno script di avvio si potrà usare l'azione
\texttt{defaults}, che utilizzando le informazioni presenti nello script
stesso lo installerà (in avvio o in arresto a seconda di quanto richiesto) su
tutti i \textit{runlevel}. Se dette informazioni non sono presenti il comando
lo installa in avvio sui \textit{runlevel} 2, 3, 4 e 5, ed in arresto su 0, 1
e 6, con numero di sequenza pari a 20.  Il comando consente anche di
specificare singolarmente quale servizio avviare e fermare su quale
\textit{runlevel} ed a quale punto della sequenza, ma per i dettagli si
rimanda alla lettura della relativa pagina di manuale.

La gestione dei link simbolici è stata comunque anche standardizzata
all'interno di LSB, che prevede a questo scopo un altro comando,
\index{comando!\texttt{chkconfig}} \texttt{chkconfig}, che è quello usato su
RedHat e la maggior parte delle altre distribuzioni, ma presente anche su
Debian, dove è disponibile un pacchetto omonimo. Il comando consente di
elencare tutti i servizi disponibili con l'opzione \texttt{-{}-list},
aggiungerne uno con \texttt{-{}-add} o rimuoverlo con \texttt{-{}-del}. Ad
esempio su una RedHat si potrà rimuovere \texttt{atd} con:
\begin{Example}
chkconfig --del atd
\end{Example}

Una delle differenze fra distribuzioni è anche quella relativa alla
attivazione o meno di un servizio alla sua installazione, cosa che viene
eseguita per Debian e derivate, e non viene fatta da RedHat e derivate. Per
quest'ultima infatti è sempre richiesto che quando si vuole attivare un
servizio all'avvio dopo averlo installato, si esegua il comando:
\begin{FormattedExample}
chkconfig --add \textsl{service}
\end{FormattedExample}
e poi lo installi nei \textit{runlevel} necessari con:
\begin{FormattedExample}
chkconfig \textsl{service} on
\end{FormattedExample}


Anche in questo caso il comando fa riferimento alle informazioni contenute
negli script per determinare su quali \textit{runlevel} e con quale numero di
sequenza inserire gli script, si può comunque soprassedere il default
specificando una lista di \textit{runlevel} con l'opzione
\texttt{-{}-level}. Per i dettagli su tutte le opzioni anche in questo caso si
faccia riferimento alla pagina di manuale.

Benché con il tempo la procedura di avvio classico appena illustrata sia stata
standardizzata, e sia ormai possibile inserire una operazione specifica in un
qualunque punto della sequenza di avvio, esistono alcuni file che storicamente
venivano usati per effettuare delle configurazioni aggiuntive alla fine della
sequenza stessa. In particolare un file ancora utilizzato è
\index{configurazione!\texttt{/etc/rc.local}} \texttt{/etc/rc.local}. Esso
viene eseguito alla fine della procedura di avvio,\footnote{ad esempio nel
  caso di Debian esso viene eseguito alla fine di tutti i \textit{runlevel}
  tranne il \textit{single user mode}.}  ed assume un po' il significato di
quello che era l'\texttt{autoexec.bat} del DOS: contiene i comandi che si
vogliono eventualmente dare dopo che tutti i servizi sono partiti, senza
doversi preoccupare di doverli inserire opportunamente all'interno della
sequenza di avvio.

Una modalità alternativa, supportata ad esempio da Debian, è quella dell'uso
della directory \texttt{/etc/rc.boot} nella quale si possono mettere gli
script che si vuole siano eseguiti alla fine della procedura di
inizializzazione. In tal caso occorre tenere presente che i file dovranno
essere eseguibili, e il loro nome non dovrà contenere caratteri speciali;
Debian infatti esegue gli script usando lo speciale comando \texttt{run-parts}
che, come visto in sez.~\ref{sec:crontab}, lancia tutti gli script presenti in
una directory posto che il loro nome sia nel formato adatto.

Entrambi questi metodi di personalizzazione delle operazioni da compiere dopo
l'avvio sono comunque sempre meno utilizzati, la standardizzazione del sistema
di avvio prevede che si utilizzi direttamente un apposito script da inserire
nel \textit{runlevel} opportuno.

Infine occorre tenere presente che gli script di avvio usati dal sistema di
avvio possono essere usati anche direttamente quando si debba fermare, avviare
o riavviare un servizio, o anche richiedere la rilettura della
configurazione. In tal caso gli script possono essere invocati direttamente
lanciandoli per pathname con gli argomenti standard riassunti in
tab.~\ref{tab:init_script_args}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Argomento} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{start}       & avvia il servizio.\\
    \texttt{stop}        & ferma il servizio.\\
    \texttt{restart}     & riavvia (ferma e poi avvia) il servizio.\\
    \texttt{reload}      & ricarica la configurazione (senza fermare il
                           servizio).\\
    \texttt{force-stop}  & forza lo stop del servizio.\\
    \texttt{force-reload}& forza la rilettura della configurazione anche se
                           questo comporta il riavvio del servizio.\\
%    \texttt{}           & .\\
    \hline
  \end{tabular}
  \caption{Argomenti standard per gli script di avvio alla \textit{System V}.}  
  \label{tab:init_script_args}
\end{table}


Finora abbiamo parlato delle modalità in cui avviene l'avvio ed in cui il
sistema si porta in un certo \textit{runlevel}, vedremo ora come è possibile
cambiare \textit{runlevel} e istruire il sistema, anche una volta avviato, a
passare da un \textit{runlevel} ad un altro. 

Una delle modalità in cui si può modificare il \textit{runlevel} su cui una
macchina viene avviata è quella che prevede il passaggio tramite il
\textit{bootloader} delle opportune opzioni di avvio per il kernel (quelle
illustrate in sez.~\ref{sec:struct_kernel_boot}). Alcune di queste infatti
vengono passate direttamente ad \texttt{init}, in particolare l'indicazione di
un semplice valore numerico porta nel relativo \textit{runlevel}, ed è inoltre
possibile usare l'opzione \texttt{single} per avviarsi in \textit{single user
  mode}. Ovviamente questo tipo di indicazione, fintanto che non viene
impostata in maniera permanente nella configurazione del \textit{bootloader},
vale soltanto per il singolo avvio, ed è questo il motivo per cui nella
configurazione di GRUB vista in sez.~\ref{sec:struct_grub} è presente una voce
separata per l'avvio in \textit{single user mode}.

Nelle operazioni ordinarie, una volta arrivati sul \textit{runlevel} di
default, normalmente non c'è bisogno di passare dall'uno all'altro. Può
capitare però di essere partiti in \textit{single user mode}, o di esservi
arrivati a causa di problemi nella fase di avvio, e che una volta che si siano
completati i compiti amministrativi o risolto il problema, si voglia passare
ad un \textit{runlevel} ordinario. Oppure, in seguito all'insorgere di
problemi, ci si può voler portare in \textit{single user mode}.

In tal caso il comando usato per cambiare \textit{runlevel} è
\index{comando!\texttt{telinit}} \texttt{telinit} (che è un link allo stesso
\texttt{init}) per cui si può usare anche direttamente quest'ultimo per
compiere le stesse operazioni. Il comando prende come argomento il numero di
\textit{runlevel} su cui ci si vuole portare, e semplicemente notifica ad
\texttt{init} (inteso qui come il processo in esecuzione con PID 1) la
richiesta di cambiamento di \textit{runlevel} (allo scopo \texttt{init} usa la
pipe \texttt{/dev/initctl} come dispositivo di controllo). A questo punto sarà
compito di \texttt{init} registrare in \texttt{/var/log/wtmp} il cambiamento
di \textit{runlevel} (vedi sez.~\ref{sec:user_sys_info}) e far eseguire prima
gli script di arresto e poi quelli di avvio secondo quanto previsto per il
\textit{runlevel} scelto, a condizione ovviamente che i relativi servizi siano
presenti nel \textit{runlevel} di partenza: non verranno cioè fermati servizi
non attivi, ne fatti partire servizi già attivi.

Oltre al valore numerico del \textit{runlevel} di destinazione si possono
passare a \texttt{telinit} altri argomenti; ad esempio con ``\texttt{q}'' si
indica ad \texttt{init} di riesaminare \texttt{/etc/inittab} mentre con
``\texttt{s}'' si richiede di andare in \textit{single user mode} (le lettere
possono essere indifferentemente maiuscole o minuscole).  Il comando può
essere anche invocato, utilizzando le opportune opzioni, per modificare
semplicemente il comportamento di \texttt{init}; in particolare con l'opzione
\texttt{-t} si può indicare un tempo diverso, rispetto ai 5 secondi di
default, fra l'invio del segnale \texttt{SIGINT} e quello del segnale
\texttt{SIGKILL} quando viene eseguito l'arresto della macchina.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Variabile} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{CONSOLE}      & la \textit{console} di sistema, il default è
                            \texttt{/dev/console}.\\ 
    \texttt{INIT\_VERSION}& la versione di \texttt{init}.\\
    \texttt{PATH}         & le directory dei comandi, come illustrato in
                            sez.~\ref{sec:shell_sintax}, inizializzata a
                            \texttt{/bin:/usr/bin:/sbin:/usr/sbin}.\\ 
    \texttt{PREVLEVEL}    & il \textit{runlevel} precedente.\\
    \texttt{RUNLEVEL}     & il \textit{runlevel} corrente.\\
    \hline
  \end{tabular}
  \caption{Variabili di ambiente definite da \texttt{init} per i suoi figli.}  
  \label{tab:init_env_var}
\end{table}

È possibile inoltre cambiare i valori delle variabili di ambiente che
\texttt{init} definisce per i processi che lancia o definirne di nuove con
l'opzione \texttt{-e}, seguita dall'assegnazione delle variabili stesse. In
generale infatti quando \texttt{init} esegue una delle azioni specificate in
\texttt{inittab} definisce anche per il processo eseguito le variabili di
ambiente riportate in tab.~\ref{tab:init_env_var}.


\subsection{Sistemi di avvio alternativi e \texttt{systemd}}
\label{sec:systemd_upstart}

\else
\relax
%%
%% FINE: Parte generale da non includere in systemd
%%
\fi

Benché sia in uso da moltissimi anni, il sistema di avvio alla \textit{System
  V} presenta numerosi problemi. Quello che viene considerato più rilevante,
specialmente in materia di prestazioni, è che la partenza del sistema può
risultare anche molto lenta a causa della serializzazione del lancio degli
script di avvio. Cosa che ad esempio comporta si debba aspettare che siano
partiti tutti i demoni di rete per avere una console, dato che, come risulta
dall'esempio di \texttt{inittab} illustrato in
sez.~\ref{sec:struct_sysv_init}, \texttt{getty} viene lanciato per ultimo.

Inoltre, dato che il sistema fa partire comunque i servizi registrati su un
\textit{runlevel}, ne verrà tentato l'avvio comunque, anche quando potrebbe
essere già noto in una fase precedente che questo fallirà. Ad esempio se la
rete non funziona o non può essere configurata, verrà comunque tentato l'avvio
dei servizi di rete, anche se è chiaro che non potranno mai funzionare. E se
si fanno errori nel piazzare un servizio nella sequenza di avvio, perché
magari lo si lancia prima di un altro da cui dipende, verrà comunque avviato e
si dovranno subire le conseguenze dell'errore.

Infine l'utilizzo degli script di avvio, per quanto offra una grande
flessibilità, comporta anche, per lo stesso motivo, il fiorire di una varietà
di opzioni, scelte specifiche, default registrati nei file più vari, casi
particolari da gestire a seconda delle varie distribuzioni o delle varie
implementazioni di sistema su cui il servizio viene installato. Il tutto porta
a complessità degli script sempre crescenti, soprattutto in termini di
manutenzione degli stessi.

Per questo motivo negli ultimi anni si è iniziato a cercare una alternativa ad
\texttt{init} che cercasse di risolvere questi ed altri problemi. Un primo
passo è stato quello di inserire negli script stessi un meccanismo di
tracciamento delle dipendenze che quantomeno consentisse di creare una
generazione corretta della sequenza degli script e la possibilità di lanciare
in parallelo quelli per cui è possibile.

% TODO: trattare insserv e il dependency mode boot
% bassa priorità

Ma oltre a questo sono stati anche realizzati dei programmi in grado di
sostituire \texttt{init} e migliorare la qualità e la velocità del processo di
avvio. Il primo tentativo serio di sostituzione è quello effettuato con la
creazione di \textit{Upstart} introdotto da Ubuntu ed usato come default fino
alla versione 14.10, ed adottato anche per RedHat 6.0.

La caratteristica principale di \textit{Upstart} è quella di poter realizzare
l'avvio del sistema in maniera asincrona e parallela, e gestire in maniera
esplicita le dipendenze fra servizi. Il programma infatti ha una architettura
\textit{event driven} in cui cioè viene \textsl{guidato} dagli eventi che
avvengono nel sistema, il principale dei quali (denominato \texttt{startup}) è
associato all'avvio del sistema. A ciascun evento possono essere associati dei
compiti (\textit{job}) da eseguire in risposta allo stesso, che a loro volta
possono generare altri eventi che comporteranno ulteriori reazioni.

In questo modo si possono gestire le dipendenze avviando un servizio che
dipende da un altro con un \textit{job} attivato in risposta ad un evento
generato da quest'ultimo. Tutto quello che non è associato ad un evento
specifico potrà essere eseguito immediatamente, e tutti i \textit{job}
potranno comunque essere eseguiti in parallelo una volta innescati dai
relativi eventi.

Questo significa ad esempio che è possibile associare l'esecuzione degli
script di configurazione di una interfaccia di rete alla rilevazione della
presenza del link sulla stessa, ed in questo caso si può anche evitare di
lanciare i servizi di rete fintanto che questa non è disponibile, ed anche
definire le dipendenze fra diversi servizi di rete (ad esempio avviare la
posta dopo il DNS) in modo che questi partano nella giusta sequenza e solo
quando tutti i prerequisiti sono soddisfatti.

%%
%% ### OBSOLETE BEGIN ###
%% Materiale obsoleto su Upstart
%%
\ifx\obsoletesection\undefined
\relax
\else
Il risultato netto è la possibilità di avere un avvio più veloce, lanciando
solo i servizi che servono e quando servono. Inoltre il sistema è compatibile
con l'uso degli script di avvio tradizionali illustrati in
sez.~\ref{sec:struct_sysv_init}, che vengono comunque utilizzati qualora non
siano stati opportunamente sostituiti da \textit{job} specifici.

Il sistema di \textit{Upstart} prevede l'uso di una versione di \texttt{init}
alternativa, che invece di eseguire quanto indicato da \texttt{/etc/inittab}
processa il contenuto della directory \texttt{/etc/init/} per il contenuto dei
\textit{job} da eseguire, che vengono specificati da altrettanti file con
estensione \texttt{.conf} posti in detta directory. Questi descrivono, con una
serie di direttive per la spiegazione delle quali si rimanda alla lettura
della documentazione accessibile con \texttt{man 5 init}, cosa deve essere
fatto.

Per controllare il comportamento di \texttt{init} è inoltre disponibile il
comando \index{comando!\texttt{initctl}} \texttt{initctl}. Il comando prevede
che si specifichi come primo argomento una direttiva, seguita eventualmente da
parametri specificati negli argomenti successivi, ad esempio con la direttiva
\texttt{list} si stampa la lista corrente dei lavori, che vengono identificati
dal nome del file sotto \texttt{/etc/init/} (la parte prima dell'estensione
\texttt{.conf}).

Il comando può essere utilizzato anche per far partire, fermare o riavviare i
singoli servizi con le direttive \texttt{start}, \texttt{stop} e
\texttt{restart} seguite dal nome del servizio. Si possono usare anche
direttamente queste direttive come fossero comandi, dato che sono previsti
altrettanti link simbolici a \texttt{initctl}, che quando viene invocato con
questi nomi le applica automaticamente all'argomento successivo. Si può
inoltre usare la direttiva \texttt{emit} per generare l'evento specificato
nell'argomento seguente, che farà partire ogni \texttt{job} associato allo
stesso.

Come accennato il sistema prevede anche la possibilità di eseguire l'avvio
nella modalità classica alla \textit{System V} usando gli script di
\texttt{/etc/init.d/} dei quali però è prevista la trasformazione in
altrettanti \textit{job}, in tal caso in genere verrà stampato un messaggio,
con il consiglio di usare il comando \texttt{service} che come vedremo in
sez.~\ref{sec:runlevel_control} è la modalità generica con cui tutti i sistemi
di inizializzazione ed avvio del sistema consentono di riavviare un servizio.

%%
%% ### OBSOLETE END ###
%% Materiale obsoleto su IDE e affini
%%
\fi

Benché \textit{Upstart} consenta di gestire il lancio in parallelo dei
programmi e l'esecuzione degli stessi solo quando necessario, resta comunque
un problema generale di serializzazione nell'avvio dovuto alle dipendenze, per
cui alcuni programmi possono essere lanciati (vale a dire letti dal disco,
portati in memoria a poi eseguiti) solo dopo che è stato completato l'avvio di
quelli da cui dipendono.

Questo comporta un calo delle prestazioni in quanto se li si potessero
lanciare in contemporanea si potrebbe ottenere una maggiore velocità
concentrando gli accessi a disco ed il caricamento in memoria, ma per
l'esistenza delle dipendenze si è costretti a serializzare gli avvii. Se però
si vanno ad esaminare le ragioni per cui queste dipendenze esistono, ci si
rende conto che nella gran parte dei casi esse sono dovute al fatto che un
programma deve poter contattare un altro per uno scambio di dati, e che questo
avviene nella quasi totalità dei casi attraverso un socket (o locale o di
rete).

\itindbeg{socket~activation} 
La considerazione da cui nasce \texttt{systemd} è che se questi socket fossero
immediatamente disponibili non sarebbe necessario aspettare l'avvio del
programma che deve crearli perché un secondo programma, che deve contattare il
primo da cui dipende, possa essere lanciato. Se il socket che serve è già
disponibile infatti il secondo programma può comunque partire ed aprirlo (che
spesso è tutto quel che serve) per poi proseguire, se invece deve inviare dei
dati può scriverli sul socket, o tentare una lettura se deve riceverli.

In questo scenario però si possono sfruttare le caratteristiche
dell'interfaccia di programmazione dei socket. Questa prevede che le scritture
siano bufferizzate per cui se non si eccedono le dimensioni dei buffer l'invio
di dati ha successo immediato e l'esecuzione può proseguire. Se invece serve
leggere una risposta dal socket in assenza di dati disponibili l'esecuzione si
bloccherà, ma questo avverrà solo per quei programmi che devono eseguire una
lettura, solo dopo che sono partiti, senza generare errori e nell'esatto
momento in cui l'esigenza si presenta. E l'esecuzione ripartirà immediatamente
senza nessun intervento esterno non appena arriveranno i dati a cura di chi li
deve fornire, quando questi inizierà a scriverli sul socket.

Si noti come utilizzando questo meccanismo non serve più doversi preoccupare
di analizzare le dipendenze reciproche per definire una corretta sequenza di
avvio, si può lanciare tutto in parallelo e le eventuali dipendenze verranno
gestite automaticamente dall'interfaccia standard dei socket del kernel, che
provvederà a fermare i processi che necessitano di dati, il tutto senza
nessuna necessità di doverle identificare e gestire esplicitamente.

Questa modalità di avvio viene detta \textit{socket activation} ed è una delle
caratteristiche più importanti di \texttt{systemd}. In sostanza è
\texttt{systemd} che si incarica di creare, sulla base della sua
configurazione, tutti i socket necessari ai programmi che deve lanciare,
passando loro i relativi file descriptor una volta che questi si sono
avviati. In realtà il concetto è tutt'altro che nuovo: come vedremo in
sez.~\ref{sec:net_superdaemons} con i cosiddetti \textit{superdeamon} dei
servizi di rete, l'idea di un programma di supervisione che si pone in ascolto
passando poi, in caso di connessione, quest'ultima al programma appropriato,
esiste fin dagli albori di Unix. Lo stesso concetto è anche quello che viene
utilizzato dal programma di avvio (\texttt{launchd}) usato da MacOsX.

Ovviamente per far funzionare la \textit{socket activation} è necessario il
supporto da parte dei programmi che usano i socket, che devono prevedere la
possibilità di utilizzare quelli creati da altri invece di crearli in
proprio. Questo comunque non si è dimostrato un grosso ostacolo, specie per i
servizi di rete, dato che come accennato già esisteva un concetto affine con i
\textsl{super-demoni}, per cui il supporto fornito da \texttt{systemd} si è
rivelato abbastanza semplice da utilizzare, e laddove assente è stato
rapidamente introdotto. A lungo termine questo consente anche di rendere i
suddetti programmi indipendenti da tutta la logica relativa alla creazione di
detti socket, essendo questa demandata a \texttt{systemd}.

\itindend{socket~activation}

Ma oltre all'uso della \textit{socket activation} il concetto di mettere in
esecuzione i programmi da lanciare in maniera asincrona rispetto alle risorse
che devono utilizzare è stato esteso da \texttt{systemd} nella maniera più
ampia possibile, in tutti quei casi in cui fosse possibile realizzarlo. Ad
esempio è stato sfruttato l'\textit{automounter} (vedi
sez.~\ref{sec:automounter}) per eseguire immediatamente un programma anche
quando questo richiede un accesso a dati posti su un disco non ancora
montato. Invece di fermarsi ad aspettare che la scansione di
\texttt{/etc/fstab}, con eventuale relativo controllo del filesystem e
abilitazione delle quote, sia stata eseguita per tutti i filesystem, il
programma potrà partire immediatamente e si bloccherà in attesa del
completamento delle operazioni dell'\textit{automounter}, ma solo lui, senza
fermare una sequenza di avvio, e solo quando richiederà di accedere ad un file
su un filesystem non ancora montato.

Un secondo aspetto di \texttt{systemd} che consente di migliorare le
prestazioni di avvio è quello di evitare di lanciare tutto quello che non
serve fintanto che non ne viene richiesto l'uso. Ad esempio è inutile lanciare
\texttt{cupsd} fintanto che non viene richiesta una stampa, o avviare un
servizio di rete se ancora l'interfaccia non è stata configurata, per cui
\texttt{systemd} consente, appoggiandosi ad infrastrutture esistenti come
quella di \textit{udev} (vedi sez.~\ref{sec:udev_hotplug}), di lanciare
automaticamente i programmi che lo utilizzano solo alla comparsa di un certo
dispositivo, o come i \textsl{super-demoni}, fare partire i demoni di rete solo
alla ricezione di una connessione.

Inoltre \texttt{systemd} supporta anche la possibilità di indicare
esplicitamente dipendenze e conflitti, ottenendo un meccanismo simile a quello
di \textit{Upstart}, ed anche di forzare una eventuale serializzazione. Ed
ovviamente resta in grado di usare il classico \textit{SysV init}, trattando
\texttt{/etc/init.d/} come una ulteriore fonte di configurazione, cercando
comunque di ottimizzare le prestazioni usando le eventuali informazioni di
dipendenza contenute negli script di avvio e ricorrendo altrimenti alla
struttura dei link nelle varie directory \texttt{/etc/rc\textsl{N}.d}.

Infine è stato fatto un notevole sforzo per sostituire il più possibile l'uso
degli script di shell, ed al di là della possibilità di lanciare direttamente
i programmi, \texttt{systemd} è in grado di effettuare internamente una serie
di configurazioni di avvio, per cui ad esempio non è più necessario eseguire
esplicitamente comandi appositi per impostare l'\textit{hostname} della
macchina, o i parametri del kernel (quelli di sez.~\ref{sec:sysctl_conf}).

Ma le novità introdotte da \texttt{systemd} vanno oltre gli aspetti collegati
all'avvio dei processi. Il programma infatti si distingue anche per le sue
funzionalità relative alla gestione ed al tracciamento degli stessi. Un'altra
delle sue caratteristiche principali infatti è quella di un uso esteso dei
\textit{Control Group}, una funzionalità presente nei kernel più recenti, che
gli consente di raggruppare tutti i processi associati ad un servizio che
mette in esecuzione, sia per identificarli, che per tenerli sotto controllo o
terminarli, che per applicare eventuali limiti sulle risorse all'intero
gruppo, o impostarne priorità e privilegi.

Infine un'ulteriore importante funzionalità di \texttt{systemd}, cui abbiamo
accennato in sez.~\ref{sec:syslog.conf}, è quella di fornire anche un sistema
di registrazione degli eventi di sistema che si pone come alternativa al
\textit{syslog}, realizzato tramite un programma di ausilio
(\texttt{journald}) che a fianco di scelte molto discutibili (e discusse) come
quella di fare uso di file binari il cui formato non è definito in maniera
stabile, consente un notevole dettaglio e fornisce funzionalità di ricerca e
classificazione delle informazioni molto interessanti.

Il file di configurazione principale del programma è
\index{configurazione!\texttt{/etc/systemd/system.conf}}
\texttt{/etc/systemd/system.conf}, che però si applica solo al programma
quando questo viene eseguito con PID 1, qualora lo si esegua dalla riga di
comando a sistema avviato (quindi con un PID diverso da 1) viene invece usato
il file \index{configurazione!\texttt{/etc/systemd/user.conf}}
\texttt{/etc/systemd/user.conf}.  Per tutti i file di configurazione
\index{demone!\texttt{systemd}} \texttt{systemd} ha adottato una variante del
formato dei \textit{keyfile} (illustrati in sez.~\ref{sec:cfg_general}) la cui
principale estensione è che l'assegnazione multipla di valori diversi alla
stessa chiave non ne sovrascrive il valore ma lo trasforma in una lista,
mentre per cancellare un precedente valore e poi poterlo riassegnare occorre
effettuare prima una assegnazione vuota.

Il file di configurazione generale permette anzitutto di definire alcune
caratteristiche di funzionamento del programma; ad esempio con
\texttt{LogLevel} si indica il livello di registrazione e con
\texttt{LogTarget} la modalità di registrazione dei messaggi. Consente inoltre
di impostare valori per risorse, limiti o proprietà generali che verranno
assegnate a tutti programmi messi in esecuzione; ad esempio assegnando un
valore a \texttt{DefaultEnvironment} nella forma di una stringa che definisce
una lista di variabili di ambiente, queste verranno propagate a tutti i
programmi che vengono avviati. Normalmente non esiste nessun motivo per
modificare il default, e questi due file contengono soltanto direttive
commentate.

Dato che come accennato \texttt{systemd}, compie direttamente alcune
operazioni eseguite nell'avvio tradizionale di \textit{SysV init} tramite
l'uso di comandi esterni, i file che venivano utilizzati a tale scopo possono
essere considerati come file di configurazione ``\textsl{indiretti}'' per
\texttt{systemd}. Fra questi c'è \texttt{/etc/hostname}, usato per impostare
il nome della macchina (vedi sez.~\ref{sec:net_resolver_intro}) i file
\texttt{/etc/sysctl.d/*.conf} usati per impostare i parametri del kernel (vedi
sez.~\ref{sec:sysctl_conf}), \texttt{/etc/fstab}, usato per montare i
filesystem ed attivare la \textit{swap}, i file
\texttt{/etc/modules-load.d/*.conf} usati per caricare moduli di kernel
aggiuntivi all'avvio.

\itindbeg{unit~file} 

La gran parte della gestione dell'avvio con \texttt{systemd} fa riferimento al
concetto di ``\textsl{unità}'', che costituisce una generalizzazione di quello
che è il concetto di servizio nell'avvio tradizionale alla
\textit{SysV}. Tutte le operazioni effettuate da \texttt{systemd} per avviare
il sistema fanno riferimento alle unità che vengono gestite tramite i
cosiddetti \textit{unit file}. Sono questi file che controllano il
comportamento del programma e vanno a sostituire gli script di avvio,
estendendone il significato.  Ad esempio anche le operazioni di configurazione
legate ai file di configurazione di sistema elencati prima sono effettuate
convertendo internamente gli stessi in opportune ``\textsl{unità}''.

Ciascuna \textsl{unità} è sempre associata ad un \textsl{nome} e ad un
\textsl{tipo} e viene espressa nella forma
\texttt{\textsl{nome}.\textsl{tipo}} che è anche il nome del relativo
\textit{unit file}. Gli \textit{unit file} di sistema vengono installati (dai
pacchetti della propria distribuzione) in \texttt{/lib/systemd/system/}, ne
possono poi essere creati ulteriori in fase di esecuzione in
\texttt{/run/systemd/system/}, mentre l'amministratore di sistema può
effettuare le proprie configurazioni inserendole sotto
\index{configurazione!\texttt{/etc/systemd/system/}}
\texttt{/etc/systemd/system/}. Queste tre directory vengono esaminate
nell'ordine appena illustrato, caricando tutti gli \textit{unit file}
presenti; in caso siano presenti più \textit{unit file} relativi ad una stessa
unità viene utilizzata la configurazione presente nell'ultimo che viene letto.
Per quanto appena detto questo fa si che le configurazioni sotto
\texttt{/etc/systemd/system/} abbiano la precedenza sulle altre.

Infine se un \textit{unit file} è vuoto, o se è un link simbolico a
\texttt{/dev/null}, la relativa unità viene marcata come \textsl{mascherata}
rendendone impossibile l'attivazione anche per via manuale. Questo consente di
disabilitare permanentemente una unità semplicemente creando un link simbolico
a \texttt{/dev/null} dentro \texttt{/etc/systemd/system/}, il cui contenuto,
essendo letto per ultimo, ha la precedenza sulle altre configurazioni.

\itindend{unit~file} 

Quando \texttt{systemd} parte attiva l'unità \texttt{default.target} che
provoca l'avvio del sistema (come vedremo le unità di tipo \texttt{target}
servono a definire uno stato in cui si vuole portare il sistema). Questa a
seconda dell'installazione effettuata è un link simbolico a
\texttt{graphical.target}, se si è installata una stazione di lavoro con
l'interfaccia grafica, o a \texttt{multi-user.target} per una installazione
senza interfaccia grafica.

Questo default può essere modificato passando nella riga di comando del kernel
(si ricordi quanto visto in sez.~\ref{sec:kernel_launch}) l'argomento
\texttt{systemd.unit=\textsl{unit.type}} per indicarne un altra. Ad esempio
\texttt{rescue.target} è l'equivalente del \textit{single user mode} ed un
link simbolico a \texttt{runlevel1.target} (sono disponibili anche le unità
\texttt{runlevel\textsl{N}.target} che riproducono gli altri \textit{runlevel}
classici), mentre \texttt{emergency.target} si limita ad eseguire una shell
sulla console principale e si può usare al posto di \texttt{init=/bin/sh} (in
genere però viene chiesta la password), col vantaggio di poter proseguire con
la procedura di avvio.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Argomento} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{systemd.unit} & indica l'unità da attivare all'avvio (il default è
                            \texttt{default.target}).\\ 
    \texttt{systemd.crash\_chvt} & con un valore positivo in caso di crash
                                   attiva il terminale virtuale indicato, il
                                   default è $-1$.\\
    \texttt{systemd.crash\_shell} & impostato a \texttt{true} indica di
                            eseguire una shell in caso di crash di
                            \texttt{systemd} (il default è \texttt{false}).\\
    \texttt{systemd.confirm\_spawn} & impostato a \texttt{true} richiede una
                            conferma prima di avviare un qualunque
                            processo (il default è \texttt{false}).\\ 
    \hline
  \end{tabular}
  \caption{Principali argomenti specifici di \texttt{systemd} da usare nella
    riga di comando del kernel.} 
  \label{tab:systemd_kernel_parameters}
\end{table}

Si sono riportati in tab.~\ref{tab:systemd_kernel_parameters} i più
significativi degli argomenti della linea di comando del kernel specifici di
\texttt{systemd}, che sono sempre nella forma
\texttt{systemd.\textsl{nome}=\textsl{valore}}. Ad essi si aggiungono anche i
tradizionali valori usati per l'avvio classico, come \texttt{single} per il
\textit{single user mode} (equivalente a \texttt{rescue.target}) ed i vari
numeri \texttt{\textsl{N}} usati per indicare un \textit{runlevel},
equivalenti all'avvio con l'unità \texttt{runlevel\textsl{N}.target}.

Anche per gli \textit{unit file} viene usato il formato dei \textit{keyfile}
con le estensioni precedentemente citate, i dettagli sono comunque illustrati
nella documentazione accessibile con \texttt{man systemd.unit}. Dato che il
nome serve ad identificare il soggetto dell'unità in generale può assumere un
valore qualunque, anche se alcuni nomi, come \texttt{default.target} e gli
altri citati sopra, sono riservati (per l'elenco completo si consulti la
documentazione, accessibile con \texttt{man systemd.special}).

Il tipo invece serve a classificare le varie tipologie di operazioni che
\texttt{systemd} può compiere attivando l'unità, e può assumere solo dei
valori prestabiliti. I tipi più rilevanti, corrispondenti alle principali
funzionalità del programma (per l'elenco completo si consulti \texttt{man
  systemd}), sono i seguenti:
\begin{basedescript}{\desclabelwidth{1.3cm}\desclabelstyle{\nextlinelabel}}
\item[\texttt{device}] un dispositivo, da usare per eseguire delle operazioni
  in base alla disponibilità di un dispositivo;
\item[\texttt{mount}] un \textit{mount point}, per controllare il montaggio
  dei filesystem con \texttt{systemd};
\item[\texttt{service}] un servizio, per controllare l'avvio di demoni e la
  gestione dei relativi processi, sostanzialmente sostituisce uno script di
  avvio;
\item[\texttt{socket}] un socket, da usare per la \textit{socket activation},
  ogni unità di questo tipo deve avere una corrispondente unità di tipo
  \texttt{service} che viene fatta partire quando il socket riceve una
  connessione;
\item[\texttt{target}] un obiettivo, da usare per raggruppare altre unità e
  riottenere uno stato del sistema equivalente ad un \textit{runlevel}; con
  questo tipo di unità si controlla quali programmi lanciare nella procedura
  di avvio.
\end{basedescript}

La configurazione di una unità avviene definendo le opportune direttive in una
opportuna sezione all'interno del suo \textit{unit file}. Due sezioni
\texttt{[Unit]} e \texttt{[Install]}, sono generiche e disponibili per
qualunque tipo di \textit{unit file}, ciascun tipo prevede inoltre una sezione
omonima che contenga le sue direttive specifiche, ad esempio la sezione
\texttt{[Service]} per i \texttt{.service}, la sezione \texttt{[Socket]} per i
\texttt{.socket}, e così via.

La sezione \texttt{[Unit]} è la più rilevante nella gestione delle procedure
di avvio (per questo di solito la si inserisce in testa al file) e serve a
mantenere le informazioni relative all'unità, in particolare consente di
definirne le dipendenze da altre unità. Le due direttive principali per fare
ciò sono \texttt{Requires} e \texttt{Wants} che prendono come argomenti una
lista di altre unità, espressa con i nomi dei relativi \textit{unit file}
separati da spazi o con la ripetizione della direttiva.  Con \texttt{Requires}
si indicano quali sono le altre unità ``\textsl{richieste}'' per l'attivazione
di una unità; questo significa che quando si attiva l'unità anche quelle
indicate con \texttt{Requires} verranno attivate, e viceversa se una di quelle
indicate con \texttt{Requires} viene disattivata o la sua attivazione
fallisce, verrà disattivato o fallirà anche l'attivazione dell'unità stessa.

Con \texttt{Wants} si indica invece una dipendenza più debole, in cui
l'attivazione dell'unità comporta anche quella delle altre unità
``\textsl{volute}'', ma la disattivazione di una di queste, o il fallimento
nella loro attivazione, non comporterà anche la disattivazione o il fallimento
dell'unità stessa. Questo tipo di dipendenza viene in genere utilizzato quando
si vuole associare l'attivazione di una unità a quella di un altra, che è il
caso più comune, e lo si fa semplicemente inserendola fra quelle
``\textsl{volute}'' da quest'ultima.

Data la loro rilevanza queste due direttive possono essere anche espresse in
maniera diversa tramite l'uso di una eventuale directory nella forma
\texttt{\textsl{unita}.\textsl{tipo}.requires} o
\texttt{\textsl{unita}.\textsl{tipo}.wants} in cui inserire altrettanti link
simbolici agli \textit{unit file} richiesti. La presenza di un link siffatto
fa si che la corrispondente unità sia implicitamente aggiunta a quelle che si
sarebbero elencate con \texttt{Requires} o \texttt{Wants}, ed in genere questa
è anche una delle modalità più comuni per farlo, in quanto la creazione di
questi link può essere gestita direttamente all'interno delle unità che vi
vengono inserite attraverso l'uso delle direttive \texttt{RequiredBy} e
\texttt{WantedBy} della sezione \texttt{[Install]}, che tratteremo a breve.

Si tenga presente che le dipendenze indicate da \texttt{Requires} o
\texttt{Wants} sono puramente logiche e non vanno intese nel senso
tradizionale in cui un servizio deve partire prima di un altro; non hanno cioè
nessuna influenza nell'ordine in cui vengono lanciati i servizi, cosa che
\texttt{systemd} cerca sempre di fare in parallelo, usando le varie
metodologie illustrate in precedenza. Qualora sia necessario definire una
sequenza in cui un servizio deve essere avviato strettamente prima o dopo un
altro, occorre dichiararlo esplicitamente usando rispettivamente le direttive
\texttt{Before} o \texttt{After}. Nel primo caso \texttt{systemd} attenderà
che l'unità abbia completato l'avvio prima di avviare quelle elencate, nel
secondo caso la avvierà solo dopo che quelle elencate hanno completato il loro
avvio. Come logico, visto il requisito, questo comportamento viene rovesciato
in caso di stop.


\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Direttiva} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{After}        & richiede che l'unità sia attivata dopo il
                            completamento dell'avvio di quella/e indicate.\\  
    \texttt{AllowIsolate} & deve essere impostata a \texttt{true} per poter
                            utilizzare l'unità con il comando \texttt{isolate}
                            di \texttt{systemctl} (ad uso prevalente delle
                            unità \texttt{target}).\\ 
    \texttt{Before}       & richiede che l'avvio dell'unità si sia completato
                            prima di attivare la/e unità indicate.\\ 
    \texttt{Conflicts}    & indica un conflitto con la/e unità indicate,
                            l'attivazione di una di esse comporta la
                            disattivazione dell'unità e l'attivazione
                            dell'unità comporta la loro disattivazione.\\ 
    \texttt{Description}  & imposta una breve stringa descrittiva usata per
                            identificare l'unità.\\ 
    \texttt{Documentation}& imposta una serie di riferimenti alla
                            documentazione delle operazioni coperte
                            dall'unità.\\ 
    \texttt{Requires}     & richiede che all'attivazione dell'unità siano
                            attivate pure la/e unità indicate ed alla
                            disattivazione di una di esse sia disattivata
                            anche l'unità stessa.\\  
    \texttt{Wants}        & richiede che all'attivazione dell'unità siano
                            attivate pure la/e unità indicate, ma non comporta
                            la disattivazione dell'unità stessa se viene
                            disattivata una di quelle indicate.\\ 
%    \texttt{} & .\\
    \hline
  \end{tabular}
  \caption{Principali direttive della sezione \texttt{[Unit]}.} 
  \label{tab:systemctl_unit_directives}
\end{table}

Oltre alle varie forme di dipendenza appena illustrate, di cui esistono
diverse varianti (ad esempio con \texttt{Conflicts} si può indicare una
dipendenza negativa da altre unità), due direttive usate comunemente sono
\texttt{Description} che consente di indicare una breve stringa descrittiva
usata per identificare l'unità e \texttt{Documentation} per inserire
riferimenti alla sua documentazione. Si sono riportate le direttive più
significative in tab.~\ref{tab:systemctl_unit_directives}, ma ne esistono
molte altre (ad esempio la serie delle varie
\texttt{Condition\textsl{Qualcosa}} che richiedono la verifica di una serie di
condizioni preliminari all'attivazione di una unità) per cui per la
documentazione completa si rimanda al solito alla pagina di manuale citata.

La sezione \texttt{[Install]} di un \textit{unit file} (che di solito viene in
genere mantenuta in coda allo stesso) non viene mai utilizzata nell'esecuzione
di \texttt{systemd} e serve invece a mantenere informazioni sull'installazione
della stessa. In particolare vi si utilizzano le direttive \texttt{WantedBy} e
\texttt{RequiredBy}, che prendono come argomento una lista di altre unità, di
cui la presente dichiara di voler essere una dipendenza.  Queste sono le
direttive che consentono di gestire l'abilitazione e la disabilitazione
dell'unità stessa ad uso dei sotto-comandi \texttt{enable} e \texttt{disable}
di \texttt{systemctl} (su cui torneremo più avanti) che rispettivamente creano
o rimuovono i link simbolici che puntano all'unità in questione nelle
directory \texttt{.wants} e \texttt{.require} delle unità indicate con queste
direttive. Questo consente di gestire in maniera pulita le dipendenze di una
unità senza ricorrere direttamente a lunghe liste di direttive \texttt{Wants}
e \texttt{Require} da gestire direttamente dentro l'unità stessa.


\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Direttiva} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{Alias}      & indica una lista di nomi alternativi per l'unità,
                          creati o cancellati come altrettanti link simbolici.\\
    \texttt{Also}       & richiede di abilitare o disabilitare anche la/e unità
                          indicate quando l'unità viene
                          abilitata/disabilitata.\\  
    \texttt{RequiredBy} & richiede di inserire l'unità come \textsl{richiesta}
                          da quella/e indicate.\\ 
    \texttt{WantedBy}   & richiede di inserire l'unità come \textsl{voluta} da
                          quella/e indicate.\\ 
%    \texttt{} & .\\ 
    \hline
  \end{tabular}
  \caption{Principali direttive della sezione \texttt{[Install]}.} 
  \label{tab:systemctl_install_directives}
\end{table}

Un'altra direttiva utilizzata in questa sezione è \texttt{Alias} che consente
di indicare dei nomi alternativi per l'unità, in modo che quando la si abilita
vengano creati automaticamente con quei nomi altrettanti link simbolici al suo
\textit{unit file}. Le altre principali direttive usabili nella sezione
\texttt{[Install]} sono illustrate in
tab.~\ref{tab:systemctl_install_directives}, e di nuovo per la documentazione
completa si rimanda alla pagina di manuale citata in precedenza.

Le unità più semplici, che non prevedono nessuna sezione specifica oltre le
due appena illustrate, sono quelle di tipo \texttt{target}, il loro scopo è
quello di raggruppare altre unità tramite le relative dipendenze, per indicare
così lo stato in cui si vuole portare il sistema (e sostituire il concetto di
\textit{runlevel}), o quello di definire degli stati intermedi, da usare come
punti di sincronizzazione per le dipendenze fra le varie unità.  Esse non
prevedono nessuna sezione specifica oltre le due appena illustrate, ed in
genere sono gli obbiettivi delle direttive \texttt{WantedBy} e
\texttt{RequiredBy} usate nelle altre unità che avviano servizi o effettuano
operazioni nel sistema, dato che questa è la modalità più comune con cui si
definiscono i servizi che si vogliono lanciare per ottenere un certo
\texttt{target}, rovesciando la prospettiva e definendo nelle unità che si
vogliono attivare i \texttt{target} a cui esse ``\textsl{appartengono}''. Come
esempio prendiamo l'unità \texttt{graphical.target} installata di default in
una Debian Jessie:

\begin{FileExample}[label=/lib/systemd/system/graphical.target]
[Unit]
Description=Graphical Interface
Documentation=man:systemd.special(7)
Requires=multi-user.target
After=multi-user.target
Conflicts=rescue.target
Wants=display-manager.service
AllowIsolate=yes
\end{FileExample}


Le unità di tipo \texttt{service} sono quelle che vengono utilizzate per
lanciare i servizi, ed in sostanza costituiscono gli equivalenti degli script
di avvio. Le modalità con cui avviare un servizio devono essere configurate
nella sezione \texttt{[Service]} che è specifica di queste unità; le direttive
principali in questa sezione sono \texttt{Type} che indica il tipo di servizio
ed \texttt{ExecStart} che indica il comando usato per avviare il servizio.

In genere \texttt{Type} non viene indicata, in quanto viene assunto il valore
di default che è \texttt{simple} che indica che il comando lanciato con
\texttt{ExecStart} sarà il processo principale del servizio, che verrà
eseguito immediatamente per poi proseguire ad avviare le unità seguenti.  Un
altro caso comune è \texttt{forking} che indica che il comando eseguito con
\texttt{ExecStart}, seguendo il comportamento tradizionale dei demoni Unix,
eseguirà immediatamente una \texttt{fork} per lanciare il processo principale
e poi terminare, in questo caso dopo l'esecuzione del comando \texttt{systemd}
attenderà la sua terminazione per proseguire a lanciare le unità seguenti. In
questo caso è opportuno indicare con la direttiva \texttt{PIDFile} il file in
cui viene salvato il \textit{PID} del processo principale, in modo che
\texttt{systemd} possa identificarlo senza incertezze. Infine con
\texttt{oneshot} si indica un comando che deve essere eseguito e terminare
prima che \texttt{systemd} prosegua a lanciare le unità seguenti. 


\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Direttiva} & \textbf{Significato} \\
    \hline
    \hline
%    \texttt{BusName}     & .\\
    \texttt{ExecReload}  & indica il comando da utilizzare per richiedere una
                           rilettura della configurazione.\\
    \texttt{ExecStart}   & indica il comando da eseguire per avviare il
                           servizio.\\
    \texttt{ExecStop}    & indica un comando da eseguire prima di fermare il
                           servizio, si tenga conto che la terminazione degli
                           eventuali processi usati dal servizio viene
                           controllata dalla direttiva \texttt{KillMode}.\\
    \texttt{PIDFile}     & indica il file da cui leggere il \textit{PID} del
                           processo principale del servizio.\\
    \texttt{Restart}     & configura se e come riavviare il servizio una volta
                           che il processo principale esce o termina al di
                           fuori delle operazioni gestite da \texttt{systemd};
                           prende uno fra: \texttt{no}, \texttt{on-success},
                           \texttt{on-failure}, \texttt{on-abnormal},
                           \texttt{on-watchdog}, \texttt{on-abort}, o
                           \texttt{always}.\\ 
    \texttt{Type}        & indica il tipo di servizio, prende uno fra 
                           \texttt{simple}, \texttt{forking},
                           \texttt{oneshot}, \texttt{dbus}, \texttt{notify},
                           \texttt{idle}.\\
%    \texttt{} & .\\
    \hline
  \end{tabular}
  \caption{Principali direttive della sezione \texttt{[Service]}.} 
  \label{tab:systemctl_service_directives}
\end{table}

La direttiva \texttt{ExecStart} richiede che si scriva il programma da
eseguire, indicandone il pathname assoluto, seguito dai relativi argomenti
separati da spazi, e si possono proteggere argomenti contenenti spazi con
apici doppi o singoli, e spezzare una riga molto lunga andando a capo dopo una
``\texttt{\bslash}''. Inoltre si può far uso nel valore della direttiva del
contenuto di eventuali variabili di ambiente che possono essere impostate
direttamente con la direttiva \texttt{Environment} o fatte leggere da un file
con \texttt{EnvironmentFile}.  Il contenuto può essere indicato con la
sintassi \texttt{\$VAR} in cui il valore viene a sua volta trattato come lista
di argomenti separati da spazi, mentre con \texttt{\$\{VAR\}} viene
interpretato come argomento unico.  Non sono supportate redirezioni o altri
elementi della sintassi della shell.

La direttiva, a meno che non si sia impostato \texttt{Type} al valore
\texttt{oneshot}, può essere usata una sola volta e consente di eseguire un
solo comando. Nel caso di \texttt{oneshot}, che in genere viene usato per
lanciare comandi che eseguano azioni semplici terminando immediatamente, la
direttiva \texttt{ExecStart} può essere ripetuta più volte (ed i comandi
verranno eseguiti nella sequenza in cui li si sono scritti), oppure si possono
indicare più comandi in una singola direttiva, separati con un
``\texttt{;}'' e di nuovo verranno eseguiti in sequenza. 

% \begin{table}[!htb]
%   \centering
%   \footnotesize
%   \begin{tabular}[c]{|l|p{8cm}|}
%     \hline
%     \textbf{Valore} & \textbf{Significato} \\
%     \hline
%     \hline
%     \texttt{simple} & il processo lanciato .\\
%     \texttt{forking}& .\\
%     \texttt{oneshot}& .\\
%     \texttt{dbus}   & .\\
%     \texttt{notify} & .\\
%     \texttt{idle}   & .\\
% %    \texttt{} & .\\ 
%     \hline
%   \end{tabular}
%   \caption{Valori della direttiva \texttt{Type}.} 
%   \label{tab:service_type_directive}
% \end{table}


Si sono riportate le principali direttive utilizzabili in una sezione
\texttt{[Service]} in tab.~\ref{tab:systemctl_service_directives}, l'elenco
completo è riportato nella pagina di manuale accessibile con \texttt{man
  systemd.service}. A queste si aggiungono una serie di direttive comuni con
altri tipi di unità, relative alle modalità di esecuzione e terminazione dei
processi, elencate rispettivamente nelle due sezioni di
tab.~\ref{tab:systemctl_exec_kill_directives}, documentate in maniera completa
nelle pagine di manuale accessibili con \texttt{man systemd.exec} e
\texttt{man systemd.kill}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Direttiva} & \textbf{Significato} \\
    \hline
    \hline
%    \texttt{BusName}     & .\\
    \texttt{Environment} & definisce le variabili di ambiente da usare per
                           l'avvio del servizio e passate ai processi lanciati
                           dallo stesso.\\
    \texttt{EnvironmentFile}& indica il file da cui leggere la definizione
                              delle variabili di ambiente usate per lanciare
                              il programma, ad esempio per usare i file in
                              \texttt{/etc/defaults/} o in
                              \texttt{/etc/sysconfig/}.\\ 
    \texttt{User}        & indica l'utente per conto del quale eseguire i
                           processi.\\ 
    \texttt{UMask}       & imposta la \textit{umask} di processi.\\
    \hline
    \texttt{KillMode}    & indica le modalità con cui terminare i processi di
                           un servizio, prende uno fra 
                           \texttt{control-group,}, \texttt{process},
                           \texttt{mixed}, \texttt{none}.\\
    \texttt{KillSignal}  & indica quale segnale usare per terminare i
                           processi.\\
%    \texttt{} & .\\
    \hline
  \end{tabular}
  \caption{Principali direttive per l'esecuzione e la terminazione dei
    processi.} 
  \label{tab:systemctl_exec_kill_directives}
\end{table}



Un esempio del contenuto di unità di tipo \texttt{service}, presa
dall'\textit{unit file} usato per avviare il servizio \textit{cron} su una
Debian Jessie, è il seguente:

\begin{FileExample}[label=/lib/systemd/system/cron.service]
[Unit]
Description=Regular background program processing daemon
Documentation=man:cron(8)

[Service]
EnvironmentFile=-/etc/default/cron
ExecStart=/usr/sbin/cron -f $EXTRA_OPTS
IgnoreSIGPIPE=false
KillMode=process

[Install]
WantedBy=multi-user.target
\end{FileExample}
%$



Si tenga conto infine che sono supportate anche delle unità
\textit{template}, contraddistinte dal nome che deve terminare con il
carattere ``\texttt{@}''. Queste sono molto utili per creare degli
\textit{unit file} generici che contengano una configurazione comune da cui è
possibile creare delle istanze specifiche in fase di esecuzione, in cui i
parametri delle direttive vengono referenziati tramite degli opportuni
``\textsl{specificatori}'' avvalorati in fase di attivazione.  Ad esempio per
gestire i terminali virtuali viene usata l'unità \texttt{getty@.service} in
modo che quando viene richiesta una console sul primo terminale virtuale possa
essere possibile creare automaticamente l'istanza specifica
\texttt{getty@tty1.service}. In tal caso nel template si farà riferimento
all'istanza specifica con lo specificatore `` \texttt{\%I}'' che viene
automaticamente sostituito dal nome dell'istanza corrente (la stringa fra la
``\texttt{@}'' ed il ``\texttt{.}'', nel caso dell'esempio precedente
\texttt{tty1}).

Una volta che il sistema è partito \texttt{systemd} continua a supportare per
compatibilità anche le interfacce del sistema di avvio alla \textit{SysV}; in
particolare continua a supportare l'uso del socket \texttt{/dev/initctl}, su
cui gli si possono inviare i comandi in maniera analoga a quanto si fa con
l'\texttt{init} tradizionale, e se viene invocato come \texttt{init} sulla
riga di comando si limita ad eseguire \texttt{telinit} con la sintassi vista
in sez.~\ref{sec:struct_sysv_init}. A sua volta con una installazione completa
di \texttt{systemd} il comando \texttt{telinit} non è altro che un link
simbolico a \index{comando!\texttt{systemctl}} \texttt{systemctl}, che è il
programma di controllo nativo, che consente di gestire tutti gli aspetti
dell'avvio del sistema e non solo quelli relativi al cambiamento di
\textit{runlevel}, ma che invocato in questo modo si comporta come il
\texttt{telinit} tradizionale.

Quando viene invocato esplicitamente come \texttt{systemctl} il programma
prevede che si indichi come primo argomento un comando (i principali sono
elencati in tab.~\ref{tab:systemctl_commands}) seguito da eventuali parametri
per lo stesso negli argomenti successivi. Se lanciato senza argomenti il
programma stampa un elenco di tutte le unità riconosciute, ed è equivalente
all'uso del comando \texttt{list-units}. Per tutti i comandi che prevedono
come argomenti delle unità queste possono essere espresse per nome e non è
necessario indicarne il tipo se questo è desumibile dal comando, inoltre se le
unità possono essere più di una si possono usare anche dei pattern, usando la
sintassi del \textit{filename globbing} della shell.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Comando} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{enable}  & abilita una o più unità, indicate con i successivi
                       argomenti, creando gli eventuali link
                       simbolici dettati dalla sezione \texttt{[Install]},
                       equivalente dei vari \texttt{chkconfig},
                       \texttt{update-rc.d}, ecc.\\ 
    \texttt{disable} & disabilita una o più unità, rimuovendo gli eventuali link
                       simbolici dettati dalla sezione \texttt{[Install]}.\\ 
    \texttt{isolate} & attiva l'unità indicata nell'argomento successivo, e
                       tutte le sue dipendenze, e disattiva tutte le altre,
                       l'unità deve essere abilitata con la direttiva
                       \texttt{AllowIsolate}.\\  
    \texttt{mask}    & \textsl{maschera} una o più unità, indicate con i
                       successivi argomenti, rendendole non attivabili neanche
                       con l'uso esplicito di \texttt{start}.\\
    \texttt{reload}  & richiede la rilettura della configurazione dei servizi
                       delle unità indicate con i successivi argomenti.\\ 
    \texttt{restart} & riattiva (o attiva se non lo era) una o più unità,
                       indicate con i successivi argomenti.\\ 
    \texttt{start}   & attiva una o più unità, indicate con i successivi
                       argomenti.\\ 
    \texttt{stop}    & disattiva una o più unità, indicate con i successivi
                       argomenti.\\ 
%    \texttt{kill}    & invia un segnale (da precisare con l'opzione
%    \texttt{-{}-signal}) a tutti i processi lanciati dall'unità.\\ 
    \texttt{unmask}  & rimuove il mascheramento di una unità (annulla un
                       precedente \texttt{mask}).\\ 
    % \hline
    % \texttt{halt}     & .\\ 
    % \texttt{poweroff} & .\\ 
    % \texttt{reboot}   & .\\ 
    % \texttt{suspend}  & .\\ 
    % \texttt{hibernate}& .\\ 
    % \texttt{rescue}   & .\\ 
    % \texttt{emergency}& .\\    
    \hline
    \texttt{status}  & mostra lo stato di una unità, leggendo anche le eventuali
                       registrazioni relative alla stessa.\\ 
    \texttt{list-units} & elenca le unità presenti, limitandosi a quelle
                          eventualmente indicate negli argomenti successivi.\\ 
    \texttt{daemon-reload} & rilegge la configurazione (e ricarica tutti gli
                             \textit{unit file}).\\ 
%    \texttt{show} & mostra lo stato in formato adatto alla scansione automatizzata.\\ 
%    \texttt{} & .\\ 
    \hline
  \end{tabular}
  \caption{Principali comandi di \texttt{systemctl}.} 
  \label{tab:systemctl_commands}
\end{table}

I comandi più usati sono \texttt{start}, \texttt{stop} e \texttt{restart} che,
come con gli script di avvio, consentono di attivare, disattivare o riattivare
delle unità (e quindi anche di operare sui servizi). Analogamente si può
richiedere di ricaricare i file di configurazione di un servizio con il
comando \texttt{reload}, ma si tenga presente che questo comando, riproducendo
l'analogo degli script di avvio, opera solo per la configurazione del servizio
stesso. Questo significa che se si modifica un \textit{unit file} la rilettura
dello stesso (che è poi la rilettura della configurazione di \texttt{systemd})
non viene eseguita da \texttt{reload}, e si deve invece usare
\texttt{daemon-reload}.

Sempre in analogia con gli script di avvio con il comando \texttt{status} si
può verificare lo stato di una unità, in questo caso però si possono ottenere
informazioni molto dettagliate relative a tutti processi ad essa collegati e,
appoggiandosi al nuovo sistema di registrazione di \texttt{journald}, anche le
ultime righe delle registrazioni effettuate nei log dagli stessi.

Oltre alle classiche operazioni disponibili con gli script di avvio,
\texttt{systemctl} viene usato anche per controllare l'attivazione all'avvio
di una o più unità con i comandi \texttt{enable} e \texttt{disable}, che sono
sostanzialmente gli equivalenti di quello che con il sistema tradizionale alla
\textit{SysV} veniva fatto con programmi distinti come \texttt{chkconfig} o
\texttt{update-rc.d}.

Dato che con \texttt{systemd} non esistono i \textit{runlevel} e l'avvio viene
gestito tramite le opportune unità \texttt{target}, per richiedere che una
unità venga attivata la modalità più comune è quella di inserirle fra quelle
``\textsl{volute}'' dal \texttt{target} che si sta usando. Questo è quello che
normalmente viene fatto con il comando \texttt{enable}, che fa si che vengano
creati i link simbolici indicati nella sezione \texttt{[Install]} nelle
opportune directory \texttt{.wanted} o \texttt{.required} (a seconda di quanto
specificato) e poi ricarica la configurazione di
\texttt{systemd}. L'operazione inversa viene eseguita da \texttt{disable}, che
rimuove i suddetti link e disabilita quindi l'attivazione
all'avvio. Ovviamente per ottenere che tutto questo abbia un risultato analogo
a quello di \texttt{chkconfig} o \texttt{update-rc.d} è necessario che
l'\textit{unit file} sia opportunamente configurato.

Si tenga presente che questi due comandi sono del tutto ortogonali rispetto ai
precedenti \texttt{start} e \texttt{stop}, abilitare una unità non significa
attivarla e disabilitarla non significa disattivarla.  Si può attivare anche
una unità non abilitata o disattivare una unità abilitata esattamente come si
può lanciare un servizio con uno script di avvio senza che questo sia stato
inserito sul proprio \textit{runlevel} o fermarlo senza toglierlo dal
\textit{runlevel}.

Oltre ad abilitare o disabilitare una unità con \texttt{systemctl} si può
anche impedire totalmente di attivare una unità, anche rispetto all'uso
esplicito di \texttt{start}, utilizzando il comando \texttt{mask} che ne
effettua il cosiddetto ``\textsl{mascheramento}''. Sfruttando il comportamento
di \texttt{systemd} già citato in precedenza, il comando semplicemente crea
sotto \texttt{/etc/systemd/system} un link simbolico ad \texttt{/dev/null} con
il nome dell'unità indicata, che rende impossibile l'avvio del servizio anche
con una richiesta diretta. Si tenga presente però che se si sono installati
direttamente degli \textit{unit file} in detta directory questi non saranno
mascherabili (non potendo creare il link simbolico al posto di un file
esistente, il comando fallirà). Si può anche mascherare una unità fino al
riavvio successivo specificando l'opzione \texttt{-{}-runtime} (che crea il
link simbolico sotto \texttt{/run/systemd/system/}). L'operazione può essere
annullata con il comando \texttt{unmask}, che semplicemente cancella i link
simbolici.

Si tratta di una funzionalità sostanzialmente assente nell'avvio alla SysV,
ottenuta per alcuni servizi con l'uso di opportune variabili di ambiente lette
dagli script di avvio (quelle in genere mantenute sotto \texttt{/etc/defaults}
per Debian ed \texttt{/etc/sysconfig} per RedHat). Benché \texttt{systemd}
supporti l'uso di questi file (con l'use della direttiva
\texttt{EnvironmentFile} nelle unità di tipo \texttt{service}) per definire
delle variabili di ambiente, le eventuali variabili usate per marcare
l'effettivo lancio di un programma (come la definizione di \texttt{START=yes}
o affini) non avranno più questo effetto.


Altri comandi interessanti forniti da \texttt{systemctl} sono \texttt{kill},
che consente di terminare tutti i processi collegati ad una unità (che
essendo, come accennato, mantenuti all'interno dello stesso \textit{control
  group}, possono essere facilmente identificati) o \texttt{isolate} che
consente di simulare il cambiamento di \textit{runlevel}, attivando
esplicitamente una unità e tutte le sue dipendenze e fermando tutte le altre.
Oltre a questi sono supportati molti altri comandi, e per la documentazione
completa si rimanda alla pagina di manuale.

Come accennato in sez.~\ref{sec:syslog.conf} una delle funzionalità più
controverse di \texttt{systemd} è quella di aver realizzato un meccanismo
indipendente di registrazione degli eventi di sistema, realizzato attraverso
il demone ausiliario \index{demone!\texttt{journald}} \texttt{journald}. Il
comportamento di questo demone viene controllato dal file
\index{configurazione!\texttt{/etc/systemd/journald.conf}}
\texttt{/etc/systemd/journald.conf}, che di nuovo segue la sintassi dei
\textit{keyfile}, e che prevede una unica sezione \texttt{[Journal]}.

La configurazione di default prevede (tramite la direttiva
\texttt{ForwardToSyslog} preimpostata a \texttt{yes}) il reinoltro dei
messaggi ad un demone di \textit{syslog} e normalmente non c'è necessità di
modificarla. Al più si potrà cambiare la dimensione massima che possono
occupare i dati registrati (il demone esegue automaticamente la cancellazione
dei dati più vecchi) da effettuare con la direttiva \texttt{SystemMaxUse} (il
default è il 10\% del filesystem). Per maggiori dettagli si rimanda alla
pagina di manuale, accessibile con \texttt{man journald.conf}.

Il sistema prevede, oltre alla registrazione dei messaggi inviati al
\textit{syslog} dai programmi, anche la registrazione degli eventi generati da
\texttt{systemd} ed oltre alle informazioni dei messaggi di log standard
registra pure una serie di ulteriori informazioni (come utenti, PID dei
processi, contesti di sicurezza, ecc.), accentrando tutte le informazioni.

Dato che gli eventi vengono registrati, indicizzati e salvati usando un formato
binario, essi possono essere riletti solo tramite un programma apposito,
\index{comando!\texttt{journalctl}} \texttt{journalctl}, che consente di
effettuare le opportune interrogazioni. Se lanciato senza argomenti il comando
stamperà tutto il contenuto disponibile nel ``\textsl{giornale}'', partendo
dalle voci più vecchie, visualizzato tramite \texttt{less}. Dato che in genere
si è interessati agli eventi più recenti è possibile richiedere al comando di
portarsi automaticamente sulla coda dei dati se si aggiunge l'opzione
\texttt{-e}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-b \textsl{N}}& limita i risultati a partire dal riavvio indicato
                            da \texttt{\textsl{N}}, che può essere un numero
                            positivo (per contare i riavvii dall'inizio dei
                            dati disponibili), negativo (per contare i riavvii
                            dal momento corrente) o un identificativo (valore
                            numerico a 32 bit usato da \texttt{journald}).\\
    \texttt{-e} & si porta automaticamente alla fine dell'elenco delle voci.\\
    \texttt{-f} & resta agganciato al terminale continuando a stampare le
                  nuove voci registrate da \texttt{journald}.\\
    \texttt{-k} & stampa solo i messaggi del kernel.\\
    \texttt{-p \textsl{prio}} & stampa solo i messaggi a partire dalla
                                priorità di \textit{syslog} indicata con un
                                valore numerico, partendo da 0 per
                                \texttt{emerg} fino a 7 per \texttt{debug}).\\
    \texttt{-u \textsl{unit}}& mostra i messaggi relativi alle unità indicate
                               (come unità singola o come pattern secondo le
                               regole del \textit{filename globbing}).\\
    \texttt{-{}-since=\textsl{data}} & stampa solo i messaggi a partire
                               dall'instante 
                               indicato (da indicare con il formato di
                               \texttt{date}).\\ 
%    \texttt{}   & .\\
%    \texttt{}   & .\\
    \hline
  \end{tabular}
  \caption{Opzioni per il comando \texttt{journalctl}.} 
  \label{tab:journalctl_options}
\end{table}

Lo si può anche usare in modalità analoga al \texttt{tail} su un file di log
utilizzando l'opzione \texttt{-f}, nel qual caso il comando resterà attivo sul
terminale continuando a stampare le nuove voci.  Si può invece limitare la
stampa dei dati dall'ultimo (o $n$-simo) riavvio usando l'opzione \texttt{-b}
seguita dal numero dello stesso: se positivo viene contato dall'inizio dei
dati, se negativo dalla fine, quindi per i dati dall'ultimo riavvio occorre
usare \texttt{journalctl -b -1}. Un elenco delle altre opzioni principali è
riportato in tab.~\ref{tab:journalctl_options}, per tutti i dettagli si
rimanda al solito alla pagina di manuale.

Nell'uso generico il programma prevede che si passino come argomenti dei
filtri di ricerca nella forma \texttt{\textsl{CAMPO}=\textsl{valore}}, dove il
\texttt{\textsl{CAMPO}} indica su quale fra i vari dati registrati da
\texttt{journald} si vuole eseguire la ricerca.  Ad esempio per ottenere tutti
i dati registrati relativi ad una certa unità si dovrà indicare
\texttt{\_SYSTEMD\_UNIT=\textsl{nome.tipo}} mentre per ottenere i dati
relativi ad un utente si dovrà indicare \texttt{\_UID=\textsl{uid}}.

Dato che la registrazione dei dati viene effettuata direttamente da
\texttt{systemd} alcuni di questi sono considerati ``\textsl{fidati}'' in
quanto vengono registrati in maniera diretta e non possono essere modificati
da programmi esterni. Per convenzione i campi relativi a questi dati sono
identificati, come nei due casi appena citati, da un nome che inizia con un
``\texttt{\_}''.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Campo} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{PRIORITY}          & priorità sul \textit{syslog}, indicata con un
                                 valore numerico, partendo da 0 per
                                 \texttt{emerg} fino a 7 per \texttt{debug}.\\
    \texttt{SYSLOG\_FACILITY}  & la \textit{facility} del \textit{syslog}.\\
    \texttt{SYSLOG\_IDENTIFIER}& nome identificativo passato al
                                 \textit{syslog} (corrispondente in genere al
                                 nome del programma).\\
    \hline
    \texttt{\_CMDLINE}         & riga di comando con cui è stato lanciato il
                                 processo che ha generato la voce.\\
    \texttt{\_COMM}            & nome del programma eseguito dal processo che
                                 ha generato la voce.\\
    \texttt{\_EXE}             & \textit{pathname} dell'eseguibile del
                                 processo che ha 
                                 generato la voce.\\ 
    \texttt{\_SYSTEMD\_UNIT}   & unità di \texttt{systemd} che ha generato la
                                 voce.\\ 
    \texttt{\_UID}             & UID del processo che ha generato la voce.\\
    \texttt{\_PID}             & PID del processo che ha generato la voce.\\
%    \texttt{}   & .\\
    \hline
  \end{tabular}
  \caption{Campi di ricerca per \texttt{journalctl}.} 
  \label{tab:journalctl_fields}
\end{table}

In tab.~\ref{tab:journalctl_fields} si sono riportati alcuni fra i campi di
ricerca più rilevanti (per l'elenco completo si rimanda alla pagina di manuale
accessibile con \texttt{man systemd.journal-fields}), ma alcune delle ricerche
più comuni sono riassunte con una opzione (ad esempio \texttt{-u} e
\texttt{-p}).  La sintassi del programma prevede che se si indicano più filtri
di ricerca vengano mostrate solo le voci corrispondenti a tutti, ma si può
chiedere la corrispondenza ad uno qualunque separandoli con un ``\texttt{+}''.

Infine si tenga presente che il programma interpreta in maniera intelligente i
parametri, per cui se si passa come argomento un pathname questo viene
automaticamente trasformato in una ricerca sul campo \texttt{\_EXE} se
corrisponde ad un eseguibile o sul campo \texttt{\_KERNEL\_DEVICE} se
corrisponde ad un file di dispositivo. 

%%
%% INIZIO: Parte generale da non includere in systemd
%%
\ifx\systemdspecificsection\undefined

\subsection{Gestione generica di servizi, riavvio, spegnimento}
\label{sec:runlevel_control}

Dato che, come appena illustrato, molte distribuzioni stanno passando ad altri
sistemi di avvio, l'uso dei classici script di shell sotto
\texttt{/etc/init.d/} per fermare, avviare o riavviare un servizio potrebbe
non essere più possibile. Per consentire di effettuare questa operazione in
maniera generica, qualunque sia il sistema di avvio scelto, è allora
disponibile il comando \index{comando!\texttt{service}} \texttt{service}, che
si incarica di compierla utilizzando le modalità opportune a seconda di quello
che si è installato.

Nel caso di avvio alla \textit{System V} il comando si limiterà semplicemente
ad invocare lo script di avvio il cui nome sotto \texttt{/etc/init.d/}
corrisponde al primo argomento, passandogli come argomento il secondo. Se il
sistema di avvio è un altro il primo argomento indicherà comunque il nome del
servizio su cui agire, ed il secondo argomento l'operazione da eseguire, da
specificare usando uno dei valori di tab.~\ref{tab:init_script_args}, e sarà
cura del comando ottenere la corrispondente azione per il servizio indicato;
nel caso di \texttt{systemd} ad esempio il primo argomento sarà considerato il
nome di una unità di tipo \texttt{service} per cui sarà eseguito
\texttt{systemctl} passandogli come comando il secondo argomento.

Benché tradizionalmente con l'avvio alla \textit{System V} si possa arrestare
una macchina o riavviarla usando i \textit{runlevel} 0 e 6, è comunque invalso
l'uso di effettuare queste operazioni rispettivamente con i comandi dedicati
\index{comando!\texttt{halt}} \texttt{halt} e \index{comando!\texttt{reboot}}
\texttt{reboot}.  A questi si aggiunge, come sostanziale sinonimo di
\texttt{halt}, \index{comando!\texttt{poweroff}} \texttt{poweroff}, che
richiede esplicitamente anche lo spegnimento fisico della macchina e non solo
lo stop di tutti i servizi, ma perché questo avvenga è necessario che sia
disponibile l'opportuno supporto nel kernel.

Di nuovo questi comandi formano una interfaccia generica che fornisce la
stessa sintassi in maniera indipendente dal sistema di avvio, la cui effettiva
realizzazione però dipende da quest'ultimo. Nel caso dell'avvio alla
\textit{System V} tutti questi comandi corrispondono sempre allo stesso
programma, \texttt{halt}, che è quello che effettua la richiesta di arresto,
riavvio o spegnimento al kernel. Il comportamento di default prevede che venga
preventivamente invocato l'ulteriore comando \texttt{shutdown} per arrestare i
servizi prima di fermare (o riavviare) definitivamente la macchina.  I tre
comandi supportano l'opzione \texttt{-f} per disabilitare questo
comportamento, causando l'arresto o il riavvio immediato senza passare
dall'arresto dei servizi. Questo serve perché in alcuni casi l'operazione di
arresto dei servizi può fallire o non essere necessaria o voluta.

I tre comandi e questa opzione sono disponibili anche per la versione usata da
\texttt{systemd} ed ha lo stesso effetto di forzare uno spegnimento o un
riavvio immediato senza cercare di fermare i servizi, anche se questo viene
effettuato in maniera completamente diversa; in sostanza i tre comandi sono
link a \texttt{systemctl} che quando invocato con uno di quei nomi esegue il
suo corrispondente comando interno.  Per le altre opzioni (comuni per tutti e
tre i comandi) e per tutti i dettagli si consulti al solito la pagina di
manuale.

Benché sia possibile spegnere o riavviare immediatamente la macchina con i
comandi appena esaminati, in genere è sempre opportuno eseguire l'operazione
con un minimo di preparazione ed avvisare gli utenti eventualmente collegati,
ed è per questo motivo che in questo caso è preferibile fare ricorso al
comando \index{comando!\texttt{shutdown}} \texttt{shutdown}, che consente di
pianificare un'operazione di fermo macchina, e di notificare gli utenti della
stessa.

Il comando prende come primo argomento l'orario a cui deve essere eseguita
l'operazione, e come argomento successivo un messaggio da inviare a tutti gli
utenti collegati. L'orario può essere indicato in vari formati, a partire da
un tempo assoluto specificato nella forma \texttt{\textsl{hh:mm}} con ore e
minuti, ad un tempo relativo nella forma \texttt{+\textsl{m}} dando un numero
di minuti; l'esecuzione immediata si ottiene utilizzando \texttt{now},
sinonimo di \texttt{+0}.

Di nuovo il comando è generico e viene fornito da tutti i sistemi di avvio;
nel caso di avvio alla \textit{System V} il default è di portare il sistema in
\textit{single user mode} (cioè di porsi sul \textit{runlevel} 1), ma si può
richiedere l'arresto della macchina (\textit{runlevel} 0) con l'opzione
\texttt{-h} o il riavvio (\textit{runlevel} 6) con l'opzione
\texttt{-r}. Queste due opzioni sono generiche ed hanno lo stesso significato
anche con la versione usata da \texttt{systemd}, dove di nuovo vengono
realizzate tramite \texttt{systemctl}. Un'altra opzione generica è \texttt{-c}
che permette di interrompere uno \textit{shutdown} programmato che ancora non
è stato iniziato.

Una volta eseguito, il comando notificherà tutti gli utenti connessi ad un
terminale dell'imminenza delle operazioni di arresto, comunicando l'orario
programmato, così che questi possano salvare eventuali cambiamenti ai file e
scollegarsi, verrà inoltre automaticamente disabilitata la possibilità di
collegarsi. La notifica agli utenti viene normalmente fatta con l'ausilio del
comando \index{comando!\texttt{wall}} \texttt{wall}, che consente di scrivere
un messaggio, passato come argomento, su tutti i terminali a cui è collegato
un utente, e che può essere usato anche direttamente per inviare notifiche
agli utenti collegati, slegate dalla presenza di uno \textit{shutdown}; per i
dettagli si consulti al solito la pagina di manuale, con \texttt{man wall}.


\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-c} & annulla uno \textit{shutdown} in corso.\\
    \texttt{-h} & esegue lo spegnimento della macchina.\\
    \texttt{-k} & non esegue l'operazione ma invia soltanto il relativo
                  messaggio agli utenti.\\ 
    \texttt{-r} & esegue il riavvio della macchina.\\
    \hline
    \texttt{-F} & richiede che al riavvio venga eseguito forzatamente un
                  controllo dei filesystem.\\
    \texttt{-f} & richiede che al riavvio non venga eseguito il controllo dei
                  filesystem.\\
    \texttt{-t} & specifica il numero di secondi da attendere fra l'invio del
                  segnale \texttt{SIGINT} e quello del segnale
                  \texttt{SIGKILL} ai processi residui (come per
                  \texttt{telinit}).\\
    \hline
  \end{tabular}
  \caption{Principali opzioni del comando \texttt{shutdown}}
  \label{tab:shutdown_options}
\end{table}

Allo scadere del tempo specificato come argomento verrà effettuata
l'operazione richiesta dal comando. Si sono riportate le altre principali
opzioni di \texttt{shutdown} in tab.~\ref{tab:shutdown_options}, dove nella
prima parte si sono elencate le opzioni supportate in modo generale su tutti i
sistemi di avvio, e nella seconda quelle specifiche della versione classica
legata all'avvio in stile \textit{System V}. Per l'elenco completo e tutti i
dettagli della propria versione si faccia al solito riferimento alla pagina
di manuale.

Si tenga presente infine che quando è previsto uno spegnimento o una
manutenzione che renderà impossibile l'accesso al sistema, è buona norma
avvisare preventivamente gli utenti. Abbiamo visto che \texttt{shutdown} è in
grado di farlo al momento della sua invocazione, ma questo vale soltanto per
gli utenti che in quel momento sono effettivamente collegati alla macchina. Se
si conoscono le necessità con sufficiente anticipo è buona norma segnalare i
futuri momenti di fermo a chiunque si collegherà alla macchina tramite i
messaggi di benvenuto che vengono stampati all'accesso, controllati dai file
visti in sez.~\ref{sec:cfg_login}. Sarà cioè opportuno inserire un opportuno
avviso o in \texttt{/etc/motd} o all'interno di \texttt{/etc/issue} e
\texttt{/etc/issue.net}.

\itindend{runlevel}


\section{La gestione di interfacce e periferiche}
\label{sec:interfaces_peripherals}

Tratteremo in questa sezione gli argomenti relativi all'utilizzo di una serie
di tipiche interfacce hardware di cui sono dotati i moderni computer, e come,
con le versioni più recenti di Linux, il relativo supporto venga gestito in
maniera il più possibile automatica attraverso sistemi come \textit{hotplug} e
\textit{udev}.

\subsection{Gestione delle interfacce di espansione}
\label{sec:expansions_interface}

Una delle caratteristiche essenziali dell'architettura hardware dei computer
moderni è quella di disporre di opportune interfacce di espansione in cui
inserire delle schede dedicate che permettono l'uso di nuove periferiche; si
ha così la possibilità di ampliare le capacità di un computer utilizzando
degli appositi dispositivi in grado effettuare i più svariati compiti.

Una interfaccia di espansione in sostanza non fornisce direttamente delle
funzionalità finali, che sono specifiche del singolo dispositivo che si pone
su di essa, quanto una interfaccia hardware comune che consente una
comunicazione fra la CPU e la memoria e tutti i dispositivi che sono posti su
detta espansione. In questo modo il sistema operativo può inviare comandi e
scambiare dati con le singole periferiche, in modo da poterne utilizzare le
capacità specifiche.

In Linux il supporto per queste interfacce è ovviamente fornito direttamente
dal kernel, che predispone tutta l'infrastruttura software con cui è possibile
leggere i dati relativi a dette interfacce, e poi dialogare con i singoli
dispositivi su di esse presenti. Questi ultimi, seguendo il criterio
fondamentale dell'architettura di un sistema unix-like per cui \textsl{tutto è
  un file}, potranno poi essere acceduti attraverso l'interfaccia generica dei
file illustrata in sez.~\ref{sec:struct_file_vfs}, con l'eccezione delle
interfacce di rete, che non rientrando bene in questa astrazione, sono
utilizzate in modo diverso.

Le due interfacce di espansione tradizionalmente più utilizzate nel mondo dei
computer basati sulla architettura classica dei cosiddetti PC (in sostanza la
piattaforma basata su Intel o compatibili) sono la ormai superata ISA
(\textit{Industry Standard Architecture}) e la più recente ed ampiamente
utilizzata PCI (\textit{Peripheral Component Interconnect}).  Entrambe queste
interfacce definiscono uno standard sia hardware (consistente in piedinatura,
dimensioni, specifiche dei segnali elettrici ecc.) che software (i comandi che
la CPU deve dare per comunicare con l'interfaccia ed i dispositivi presenti
sulla stessa). Ad oggi ISA è completamente abbandonata, mentre lo standard PCI
ha subito diverse evoluzioni, ma i concetti di base restano comunque
sostanzialmente gli stessi.

La struttura di base di queste interfacce è quella di definire uno speciale
canale di comunicazione (il cosiddetto \textit{bus}) sul quale far passare sia
i dati che i comandi che vanno dal \textsl{sistema centrale} (CPU e memoria)
ai dispositivi inseriti nell'interfaccia stessa (le \textsl{periferiche}
appunto), e viceversa. Le interfacce forniscono inoltre un opportuno
meccanismo che permetta di comunicare in maniera indipendente (identificando
opportunamente i flussi di dati sul \textit{bus}) con ciascuna delle
periferiche presenti sull'interfaccia.

Una descrizione dettagliata del funzionamento di queste interfacce va ben
oltre lo scopo di questo testo, la loro gestione è infatti completamente
realizzata all'interno del kernel attraverso il codice relativo al loro
supporto. Quello che interessa dal punto di vista dell'amministrazione di
sistema è capire quali sono le risorse utilizzate e come allocarle e le
funzionalità messe a disposizione del kernel che consentono di accedere alle
informazioni relative a dette interfacce ed ai dispositivi su di esse presenti
a scopo di configurazione o di controllo.

\itindbeg{interrupt} 
Le risorse fondamentali usate da una interfaccia sono sostanzialmente due gli
\textit{interrupt} e i \textsl{canali DMA}. Un \textit{interrupt} è un
meccanismo con cui un dispositivo hardware può inviare un segnale al
processore\footnote{nei sistemi tradizionali questo viene fatto fisicamente
  alzando un livello su uno dei piedini del processore a questo dedicato.}
(usando quella che si chiama una \textsl{linea di interrupt}) così che questo
possa \textsl{interrompere} le operazioni e rispondere all'esigenza di
attenzione così manifestata dal dispositivo. In genere un processore ha un
numero limitato di linee di \textit{interrupt}; originariamente nei
PC erano 8 e poi sono state portate a 15, in altre architetture sono 32 o 64.

Nei computer più recenti, con il crescere del numero di dispositivi e la
presenza di sistemi multiprocessore la gestione degli \textit{interrupt} è
stata demandata ad un apposito sistema, denominato APIC, da \textit{Advanced
  Programmable Interrupt Controllers}, questo oltre a fornire un numero di
\textit{interrupt} molto più elevato, la definizione di priorità e
l'allocazione dinamica degli stessi, consente anche di risolvere i problemi
connessi alla presenza di più processori (in tal caso si tratta di decidere a
quale processore inviare l'\textit{interrupt} perché lo processi) realizzando
un meccanismo di smistamento fra gli stessi.

Il sistema prevede la presenza di due componenti, l'APIC locale (LAPIC),
presente nella misura di una unità per processore, che gestisce gli
\textit{interrupt} destinati al singolo processore e quelli creati fra
processori, e l'I/O APIC, presente nella misura di una unità per bus di
periferiche, che gestisce gli interrupt ricevuti dalle periferiche stesse e li
instrada verso gli APIC locali, per il trattamento da parte dei singoli
processori.  

\itindend{interrupt}

\index{canali DMA|(}

La seconda risorsa è quella dei \textsl{canali DMA}, questi sono un meccanismo
hardware che consente dei trasferimenti diretti di dati da una periferica alla
memoria senza che questi debbano essere letti direttamente con l'intervento
della CPU, che può essere utilizzata in altre operazioni. Con l'uso dei canali
DMA il sistema si limita a richiedere solo un intervento iniziale della CPU
per indicare al dispositivo in quale zona di memoria inviare i dati, che
saranno poi trasferiti in maniera asincrona.  In genere l'uso di un canale DMA
si abbina sempre a quello di un \textit{interrupt} che serve a segnalare la
conclusione del trasferimento, così che la CPU venga avvertita che è possibile
utilizzare i dati disponibili in memoria.

\index{canali DMA|)}

Uno dei problemi relativi alla gestione delle interfacce di espansione è
allora proprio quello della allocazione degli \textit{interrupt} e dei canali
DMA ai dispositivi esistenti,\footnote{in realtà questo è un problema che si
  aveva quasi esclusivamente sui vecchi PC intel-compatibili, che avevano
  pochi \textit{interrupt} e canali DMA e tutta una serie di limitazioni
  ereditate dall'architettura originaria che su altre piattaforme non
  esistono.} che di norma può essere eseguita a livello di BIOS. In
particolare alcuni \textit{interrupt} sono assegnati staticamente a
periferiche presenti sui PC da prima che fosse possibile una allocazione
dinamica, come l'interfaccia IDE per i dischi, le seriali e la parallela; gli
altri poi possono essere lasciati liberi per l'uso da parte delle interfacce
di espansione o di altre interfacce interne come USB (che vedremo in
sez.~\ref{sec:USB_interface}).

I problemi che possono sorgere sono allora quelli dell'allocazione di queste
risorse; il kernel permette di esaminare lo stato corrente di queste
allocazioni attraverso il file \texttt{/proc/interrupts}
\index{filesystem~\texttt{/proc}!\texttt{/proc/interrupts}} per gli interrupt
e \index{filesystem~\texttt{/proc}!\texttt{/proc/dma}} \texttt{/proc/dma} per
i canali DMA; un esempio potrebbe essere il seguente:
\begin{Console}
# \textbf{cat /proc/interrupts}
           CPU0
  0:     584706          XT-PIC  timer
  1:      15435          XT-PIC  keyboard
  2:          0          XT-PIC  cascade
  8:          4          XT-PIC  rtc
  9:          2          XT-PIC  usb-uhci, usb-uhci, btaudio, bttv
 10:     933383          XT-PIC  EMU10K1, eth0
 11:       2170          XT-PIC  ide2, ide3, aic7xxx
 12:     319229          XT-PIC  PS/2 Mouse
 14:         56          XT-PIC  ide0
 15:     162630          XT-PIC  ide1
NMI:          0
LOC:     584659
ERR:        848
MIS:          0
\end{Console}
che mostra l'allocazione degli \textit{interrupt}, il cui numero progressivo è
riportato in prima colonna, rispettivamente ai dispositivi ad essi associati
(riportati nell'ultima); nella seconda colonna sono riportati il numero di
\textit{interrupt} registrati al momento ed un sommario di questa statistica è
riportato nelle ultime quattro righe. Analogamente abbiamo:
\begin{Console}
# \textbf{cat /proc/dma}
 4: cascade
\end{Console}
che mostra l'allocazione dei canali DMA.

L'uso di APIC sulle macchine più moderne permette in genere di risolvere i
problemi di allocazione degli \textit{interrupt}, ma può accadere che ne
introduca a sua volta di altri. In particolar modo a causa di errori sia
nell'implementazione dell'hardware, che nel supporto da parte del kernel, ci
si può trovare con un sistema non funzionante. Per questo motivo su Linux è
disponibile fra le opzioni di avvio del kernel (vedi
sez.~\ref{sec:struct_kernel_boot}) \texttt{noapic} che disabilita l'uso di
questo sistema, o \texttt{nosmp} che inoltre disabilita anche l'uso in
modalità multiprocessore. Si tratta di soluzioni di emergenza a cui si può
provare a ricorrere in caso si manifestino problemi.

Una terza risorsa usata da alcune periferiche è quella delle \textit{porte di
  I/O}, una modalità di comunicazione diretta fra la CPU e le stesse
effettuata attraverso l'accesso ad alcune locazioni di memoria riservate
(chiamate appunto in questo modo) leggendo e scrivendo dalle quali si andava a
leggere e scrivere direttamente sui dispositivi. Anche in questo caso alcune
di queste porte sono allocate staticamente a periferiche standard come le
seriali, mentre altre possono dover essere allocate opportunamente quando si
inserisce il relativo dispositivo su una interfaccia di espansione; la
situazione corrente dell'allocazione è riportata dal kernel nel file
\index{filesystem~\texttt{/proc}!\texttt{/proc/ioports}}
\texttt{/proc/ioports}, un cui esempio è:
\begin{Console}
# \textbf{cat /proc/ioports}
0000-001f : dma1
0020-003f : pic1
0040-005f : timer
0060-006f : keyboard
0070-007f : rtc
0080-008f : dma page reg
00a0-00bf : pic2
00c0-00df : dma2
00f0-00ff : fpu
0170-0177 : ide1
01f0-01f7 : ide0
02e8-02fe : serial(set)
02f8-02ff : serial(set)
0376-0376 : ide1
03c0-03df : vga+
03f6-03f6 : ide0
03f8-03ff : serial(set)
0cf8-0cff : PCI conf1
5c20-5c3f : ALi Corporation M7101 PMU
...
\end{Console}

Di nuovo con tutto l'hardware recente questa allocazione viene gestita in
maniera dinamica e trasparente per l'utente, ci sono casi però, specie con
vecchie periferiche, in cui non è così e può essere necessario dover
effettuare una allocazione manuale (in genere tramite il BIOS).

Una delle prime interfacce di espansione realizzate nei PC tradizionali è
stata la ISA, che nacque come estensione dei bus dei vecchi PC, che
consentivano l'utilizzo di schede di espansione dedicate.  Originariamente
l'interfaccia prevedeva un bus a 8 bit, quasi subito portato a 16. Veniva
usata principalmente per modem interni e schede sonore ed al giorno d'oggi è
totalmente in disuso, e si trova soltanto su delle macchine molto vecchie.

%%
%% ### OBSOLETE BEGIN ###
%% Materiale obsoleto su ISA-PNP
%%
\ifx\obsoletesection\undefined
\relax
\else

Le prime versioni dell'interfaccia prevedevano la presenza di opportuni
interruttori sulle schede stesse (i cosiddetti \textit{jumper}) che
permettevano di selezionare in maniera manuale gli \textit{interrupt}, i
canali DMA o le porte di I/O da utilizzare. In questo caso era cura del
sistemista allocare queste risorse in maniera compatibile fra le varie schede
(con le opportune impostazioni sui \textit{jumper}); in particolare gli
\textit{interrupt} che a differenza del più recente bus PCI non possono essere
condivisi fra schede diverse.

Per evitare questo problema e facilitare l'uso delle schede di espansione da
parte degli utenti meno esperti venne creato uno standard per
l'autoconfigurazione delle schede chiamato \textit{Plug'n
  Play},\footnote{quasi immediatamente ribattezzato in \textit{Plug'n Pray}
  visto che spesso il meccanismo non funzionava e le risorse venivano allocate
  in maniera non compatibile con altre schede, con conseguente impossibilità
  di usare le espansioni.} in cui le precedenti risorse potevano essere
allocate dinamicamente dal sistema operativo o dal BIOS ed impostate sulle
schede. Il supporto per questa funzionalità prevede un meccanismo di
configurazione detto \textit{isolation},\footnote{una descrizione più
  dettagliata può essere trovata nel
  \href{http://www.tldp.org/HOWTO/Plug-and-Play-HOWTO.html}{Plug-and-Play
    HOWTO}.} in cui ad ogni scheda venga assegnato un \textit{Card Serial
  Number} (in breve CSN) che la identifica e ne vengono rilevate le
caratteristiche, dopo di che alle varie schede vengono assegnate le risorse da
utilizzare in modo che non ci sia conflitto.

In questo modo un driver può utilizzare la scheda conoscendo i parametri che
indicano quale risorsa utilizzare; nel caso di Linux buona parte dei moduli
delle schede ISA utilizzano i parametri \texttt{irq}, \texttt{ioport} e
\texttt{dma} che permettono di utilizzare la scheda sapendo quali sono le
risorse ad essa allocate. Il problema è che se un modulo viene caricato prima
che il PnP abbia eseguito l'allocazione la scheda non sarà utilizzabile,
inoltre se il meccanismo fallisce ci si può trovare con delle schede presenti
ma non utilizzabili, se poi si cerca di riallocare le risorse di una scheda in
uso gli effetti possono essere anche peggiori, con buona probabilità il blocco
completo del sistema.

Le modalità con cui le schede vengono configurate sono sostanzialmente due:
alcuni BIOS sono in grado di eseguire da soli il procedimento di allocazione
delle risorse, e presentare il risultato finale al sistema operativo; questo
nel caso di Linux significa solo che si dovranno individuare quali sono le
risorse assegnate, passando gli opportuni valori ai moduli che le
utilizzano. Altri non sono in grado di farlo\footnote{o si può dire al BIOS di
  non farlo specificando che si ha un sistema operativo \textit{PnP enabled}
  che si occuperà del compito nella apposita sezione di configurazione.} ed il
procedimento dovrà allora essere effettuato direttamente dal sistema operativo
prima di poter utilizzare i driver; questo, nel caso di Linux, significa che
la configurazione dovrà essere effettuata prima di caricare i moduli relativi
a dette schede.

In genere\footnote{alcuni BIOS meno evoluti non supportano questa
  funzionalità.} quando il BIOS esegue la configurazione delle schede PnP
questa viene salvata nella memoria non volatile (la cosiddetta ESCD,
\textit{Extended System Configuration Data}, dove vengono mantenute tutte le
configurazioni del BIOS) in modo da poter essere riutilizzata al riavvio
successivo; quando viene inserita una nuova scheda \textit{Plug'n Play} questa
verrà riconosciuta e configurata e la configurazione sarà aggiunta nella ESCD.
Sebbene in teoria questo permetta di evitare la riconfigurazione tutte le
volte che si riavvia la macchina, con Linux c'è il problema che quando la
configurazione viene eseguita in un secondo tempo i nuovi valori non vengono
salvati nella ESCD.

Per tutta questa serie di motivi il meccanismo del \textit{Plug'n Play}
finisce con il complicare notevolmente le cose, dato che molte delle
funzionalità vengono a dipendere dalla versione di BIOS disponibile e da come
questo e le relative schede supportano lo standard. Per questo motivo con
Linux è in genere preferibile usare le capacità di configurazione fornite
direttamente dal sistema.

Prima dei kernel della serie 2.4.x, l'unico modo di eseguire la configurazione
era grazie al programma \index{comando!\texttt{isapnp}} \texttt{isapnp}, a
partire da essi il supporto per la configurazione è stato introdotto nel
kernel grazie al modulo \texttt{isa-pnp} che viene chiamato dai vari driver
dei dispositivi per eseguire l'allocazione delle risorse. Il programma viene
comunque ancora utilizzato (e lo descriveremo a breve) anche se non è più
strettamente necessario, almeno fin quando i driver ed il supporto sulle
schede funzionano correttamente.

Il comando prende come unico argomento il nome di un file di configurazione
(che in genere è \index{configurazione!\texttt{/etc/isapnp.conf}}
\texttt{/etc/isapnp.conf}), ed esegue le impostazioni secondo le direttive in
esso contenute. Le uniche opzioni sono \texttt{-{}-help} e
\texttt{-{}-version} il cui significato è evidente; a partire dalla versione
1.18 si può usare anche \texttt{-} come nome di file, per indicare una lettura
dallo \textit{standard input}.

Eseguendo il comando si esegue la configurazione delle schede e l'assegnazione
delle risorse secondo quanto specificato nella configurazione. In genere
dovrebbe essere eseguito ad ogni riavvio, in quanto con Linux non c'è modo di
salvare le impostazioni precedenti. Se non si fa così si corre il rischio,
usando Windows (95 o 98) sulla stessa macchina che questo configuri le schede
in maniera differente, così che al successivo riavvio con Linux queste
diventino inutilizzabili.

Il formato di \texttt{isapnp.conf} è piuttosto complesso, e non staremo qui a
descriverlo (gli interessati possono fare riferimento alla pagina di manuale,
accessibile con \texttt{man isapnp.conf}) dato che in genere questo file viene
prodotto automaticamente grazie al comando \index{comando!\texttt{pnpdump}}
\texttt{pnpdump}. Questo comando permette infatti di ricavare i dati delle
schede presenti sulla macchina eseguendo una scansione del bus ISA alla
ricerca di schede che supportano il \textit{Plug'n Play} e leggendo da
ciascuna di esse l'elenco delle risorse necessarie (il PnP prevede che esse
siano memorizzate all'interno della scheda).

Il problema è che in certi casi le informazioni riportate non sono accurate;
questo perché fintanto che le schede non erano necessarie all'avvio alcuni
produttori sono stati piuttosto pigri nella specificazione delle risorse
necessarie all'interno della scheda, contando sull'uso del driver (ovviamente
fornito solo per DOS/Windows) per eseguire le impostazioni. Questo significa
che in certi casi le informazioni ricavate da \texttt{pnpdump} non sono
corrette, e potrebbe essere necessario controllare quali sono le risorse
utilizzate sotto Windows per ricavare dati esatti.

Il comando comunque esegue la scansione effettuando vari tentativi di
comunicazione con le eventuali schede, interrogando in fila tutte le porte di
I/O possibili (nell'intervallo fra \texttt{0x203} e \texttt{0x3ff}, riservato
alle schede ISA), per identificare quali di queste corrispondono ad un
dispositivo presente sul BUS, cui richiedere le informazioni. Si tenga
presente però che in certi casi si possono avere conflitti (l'interrogazione
cioè può interferire con altre schede non PnP o già configurate) con risultati
che vanno dalla successiva inutilizzabilità delle suddette schede al blocco
completo del sistema. Pertanto è sempre opportuno eseguire il comando in
\textit{single user mode} (vedi sez.~\ref{sec:struct_sysv_init}).

Se invocato senza argomenti il comando stampa sullo \textit{standard output} il
risultato della scansione, direttamente nel formato utilizzato per la
configurazione del programma \texttt{isapnp}; di default però tutte le
istruzioni sono commentate, pertanto è comune salvare il file e poi
modificarlo per togliere i commenti. Se però lo si invoca con l'opzione
\texttt{-c} il comando stesso cerca di determinare le impostazioni più sicure
e fornisce una versione pronta (cioè senza necessità di togliere i commenti)
del file stesso.  Si tenga presente però che se l'allocazione risulta
impossibile il comando può bloccarsi indefinitamente nel tentativo di trovare
una soluzione.

Se il comando viene invocato con un solo argomento questo viene interpretato
come il valore minimo della porta di I/O da cui iniziare la scansione sul bus
ISA, si può così limitare l'intervallo evitando di interrogare schede già
configurate o non PnP. L'argomento può essere specificato come valore
esadecimale (se inizia con le cifre \texttt{0x}), ottale (se inizia per
\texttt{0}) o decimale.
\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-c}& tenta di determinare delle impostazioni sicure per i
                 dispositivi, e produce un output direttamente utilizzabile
                 senza necessità di rimuovere i commenti.\\
    \texttt{-d}& scarica i valori dei registri interni per ogni scheda e li
                 stampa sullo \textit{standard output}, in questo modo è possibile
                 vedere le eventuali impostazioni fatte dal BIOS o mantenute
                 di default dalle schede stesse.\\
    \texttt{-h}& stampa un messaggio di aiuto.\\
    \texttt{-i}& ignora gli errori di \textit{checksum} nel riconoscimento
                 degli indirizzi delle porte di I/O; in alcuni casi questo non
                 è dovuto a conflitti e porta a classificare come non valide
                 tutte le porte, ignorandolo si potranno trovare lo stesso le
                 schede presenti. \\
    \texttt{-o}& scrive il risultato sul file passato come parametro invece
                 che sullo \textit{standard output}.\\
    \texttt{-v}& stampa la versione.\\
    \hline
  \end{tabular}
  \caption{Principali opzioni per il comando \texttt{pnpdump}.} 
  \label{tab:pnpdump_options}
\end{table}

Se si usano due argomenti in questo caso il primo dei due assume il
significato di numero di schede già identificate e configurate dal BIOS, nel
qual caso il programma non esegue la procedura di ricerca, e inizia la
scansione per nuove schede a partire dall'indirizzo passato come secondo
argomento. Le opzioni principali del comando sono riportate in
tab.~\ref{tab:pnpdump_options}.  Al solito per l'elenco completo ed i dettagli
si faccia riferimento alla pagina di manuale.

%%
%% ### OBSOLETE END ###
%% Materiale obsoleto sui floppy ed i relativi kernel
%%
\fi

Le interfacce di espansione più utilizzate nei computer odierni sono quelle
che utilizzano lo standard PCI \textit{Peripheral Connect Interface}, che
venne creato per fornire un bus di espansione generico che fosse adatto
all'evoluzione dei computer, ed in grado di supportare velocità di
trasferimento dei dati molto superiori al precedente ed ormai completamente
abbandonato ISA. Il bus nasce a 32 bit e prevede una frequenza per le
operazioni di 33.3MHz, per una banda passante teorica di circa 1Gbit/s. In
seguito sono state realizzate varie estensioni dello standard, fra cui il bus
AGP delle schede video (che è sostanzialmente un PCI con frequenze operative
più alte), ed ulteriori evoluzioni come il PCI-X ed il PCI Express, che
riguardano diversi formati per le schede, uso di bus a 64 bit e maggiori
velocità di trasferimento.

Nel caso di PCI la allocazione delle risorse è dinamica; in genere gli
\textit{interrupt} vengono associati sulla base dello slot su cui è inserita
la scheda di espansione, inoltre il bus supporta la condivisione degli
\textit{interrupt}. Un'altra caratteristica specifica del bus PCI è che ogni
scheda riporta al suo interno (nel \textit{firmware}) una serie di
informazioni fra cui una coppia di numeri che specificano sia il produttore
che il tipo della scheda, che possono essere confrontati con un database delle
schede prodotte (usualmente mantenuto nel file
\texttt{/usr/share/misc/pci.ids}).

In un bus PCI ciascuna periferica viene identificata univocamente grazie ad un
indirizzo che è composto da tre numeri: il \textsl{numero di bus}, il
\textsl{numero di dispositivo} ed il \textsl{numero di funzione}. Il
\textsl{numero di bus} identifica su quale bus si trova la scheda, infatti lo
standard supporta la possibilità di avere più bus (fisicamente distinti) sulla
stessa macchina, fino ad un massimo di 256.  Una caratteristica comune del PCI
è che i bus possono essere collegati fra di loro attraverso dei dispositivi
appositi detti \textit{PCI bridge}, per cui con una scheda apposita si può
controllare un altro bus PCI contenente altre schede. Per ciascun bus si
possono poi inserire fino a 32 schede diverse, identificate per \textsl{numero
  di dispositivo}, che possono supportare fino a 8 diverse periferiche cadauna
(in caso di schede \textsl{multifunzione}). Il tutto compone un numero a 16
bit che viene a costituire l'\textsl{indirizzo} hardware della periferica sul
bus PCI.

\begin{figure}[!htb]
\centering
\includegraphics[width=12cm]{images/bus-schema}
\caption{Schema della disposizione del bus PCI e delle varie interfacce di
  espansione.}
\label{fig:expansion_bus_schema}
\end{figure}

I computer più recenti in genere hanno sempre almeno due bus, la CPU è
collegata attraverso il cosiddetto \textit{host bridge} sul bus principale che
è sempre il bus 0, ulteriori bus sono agganciati su questo con un \textit{PCI
  bridge} e su di essi possono essere agganciati ulteriori bus in modo da
formare un albero. Uno schema della disposizione dei bus nelle architetture PC
è in fig.~\ref{fig:expansion_bus_schema}.

In generale il kernel riporta le informazioni relative a tutte le periferiche
disponibili sul bus PCI all'interno del filesystem \textit{proc} nella
directory \index{filesystem~\texttt{/proc}!\texttt{/proc/bus/pci}}
\texttt{/proc/bus/pci}. All'interno della directory è presente, per ogni bus
PCI presente nel sistema, una sottodirectory identificata con il numero
assegnato a ciascun bus che contiene un file per ciascuna periferica nella
forma \texttt{NumeroDispositivo.NumeroFunzione}, ed il file \texttt{devices} in
cui sono riportate le informazioni relative a tutte le schede presenti (ed
agli eventuali moduli cui sono associate).\footnote{nelle vecchie versioni del
  kernel esisteva solo il file \texttt{/proc/pci}, contenente una lista
  descrittiva delle schede presenti, eliminato nella serie 2.6.x, e presente
  per compatibilità nella serie 2.4.x.}

La lista dei dispositivi presenti sul bus può essere ottenuta anche con il
comando \index{comando!\texttt{lspci}} \texttt{lspci}; nei nuovi kernel questo
è il metodo canonico, e sarà l'unico supportato in futuro. Il comando non
prende argomenti e stampa sullo \textit{standard output} la lista delle schede
rilevate sul bus PCI, con qualcosa del tipo:
\begin{Console}
[root@gont corso]# \textbf{lspci}
00:00.0 Host bridge: VIA Technologies, Inc. VT8363/8365 [KT133/KM133] (rev 03)
00:01.0 PCI bridge: VIA Technologies, Inc. VT8363/8365 [KT133/KM133 AGP]
00:07.0 ISA bridge: VIA Technologies, Inc. VT82C686 [Apollo Super South] (rev 4
0)
00:07.1 IDE interface: VIA Technologies, Inc. VT82C586/B/686A/B PIPC Bus Master
IDE (rev 06)
00:07.2 USB Controller: VIA Technologies, Inc. USB (rev 16)
00:07.3 USB Controller: VIA Technologies, Inc. USB (rev 16)
00:07.4 Host bridge: VIA Technologies, Inc. VT82C686 [Apollo Super ACPI] (rev 4
0)
00:09.0 SCSI storage controller: Adaptec AHA-2940U/UW/D / AIC-7881U (rev 01)
00:0f.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL-8139/8139C/813
9C+ (rev 10)
01:00.0 VGA compatible controller: nVidia Corporation NV11 [GeForce2 MX/MX 400]
 (rev a1)
\end{Console}
\label{sec:page_lspci_output}

Il comando riporta nella prima colonna l'indirizzo di ciascun dispositivo
ordinato per numero di bus, numero di dispositivo e numero di funzione seguito
da una descrizione sommaria della periferica relativa; usando l'opzione
\texttt{-v} si può avere una descrizione più dettagliata comprensiva delle
risorse utilizzate dalla periferica stessa, con qualcosa del tipo di:
\begin{Console}
0000:00:12.0 Ethernet controller: VIA Technologies, Inc. VT6102 [Rhine-II] (rev 74)
        Subsystem: Micro-Star International Co., Ltd.: Unknown device 7120
        Flags: bus master, medium devsel, latency 32, IRQ 23
        I/O ports at dc00 [size=256]
        Memory at dffffe00 (32-bit, non-prefetchable) [size=256]
        Capabilities: <available only to root>
\end{Console}
e ripetendo una seconda volta l'opzione si possono avere ancora più dettagli. 

Con l'opzione \texttt{-t} si può invece avere una stampa della struttura ad
albero del bus, mentre con \texttt{-s} si può selezionare quali dispositivi
guardare, passando un parametro che esprime il relativo indirizzo nella forma
\texttt{bus:slot.func} (il formato della prima colonna del precedente esempio)
dove ciascun numero identificativo può essere sostituito dal carattere jolly
``\texttt{*}''. Le altre opzioni principali sono riportate in
tab.~\ref{tab:lspci_options}, per un elenco completo si faccia al solito
riferimento alla pagina di manuale del comando.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-b}& riporta la lista degli \textit{interrupt} per come li vede il
                 bus (con APIC nel kernel vengono rimappati). \\
    \texttt{-d}& mostra le informazioni relative ai dispositivi di un singolo
                 produttore (usando gli identificativi della scheda sulla base
                 del valore del parametro \texttt{vendorID:deviceID}) dove
                 entrambi gli identificativi sono espressi come numeri
                 esadecimali. \\
    \texttt{-i}& usa il file passato come parametro come database degli
                 identificativi delle schede PCI.\\
    \texttt{-n}& riporta il valore numerico degli identificatori delle schede
                 invece di usare la descrizione testuale riportata nel 
                 database. \\
    \texttt{-s}& mostra le informazioni relative ad uno o più dispositivi che
                 corrispondono ad un certo indirizzo sul bus espresso da un 
                 parametro nella forma \texttt{bus:slot.func}.\\
    \texttt{-t}& mostra una schematizzazione ad albero della disposizione dei
                 dispositivi.  \\
    \texttt{-v}& aumenta le informazioni stampate (può essere ripetuto due
                 volte). \\
    \hline
  \end{tabular}
  \caption{Principali opzioni per il comando \texttt{lspci}.} 
  \label{tab:lspci_options}
\end{table}

Un secondo comando utilizzabile per operare sul bus PCI è \texttt{setpci}, che
può essere utilizzato per interrogare e configurare i singoli dispositivi
presenti sul bus. Il comando necessita sempre di una opzione di selezione per
indicare su quale dispositivo operare, questa può essere sia \texttt{-s} per
usare l'indirizzo che \texttt{-d} per usare l'identificativo della scheda;
entrambe usano la stessa sintassi già vista in tab.~\ref{tab:lspci_options}
per \texttt{lspci}.

Il comando prende come argomento il nome del registro su cui si vuole operare.
Lo standard PCI prevede infatti che tutte le schede debbano avere una serie di
registri di configurazione, che contengono informazioni o controllano vari
aspetti del loro funzionamento, come il tempo massimo che un dispositivo può
tenere il bus.

Indicando solo il nome di un registro ne sarà stampato il valore corrente,
indicando una assegnazione nella forma \texttt{registro=valore} ne sarà invece
cambiato il contenuto (si tenga conto che il valore deve essere espresso in
esadecimale). Al nome del registro si possono aggiungere i suffissi
\texttt{.B}, \texttt{.W} e \texttt{.L} per indicare che si vuole eseguire
l'operazione su un registro di dimensione pari ad un byte, una parola (16 bit)
o una parola lunga (32 bit). Al posto del nome può anche essere usato un
valore esadecimale che ne indica la posizione nello spazio dei registri.

Un elenco sommario dei principali registri e del relativo significato è
riportato in tab.~\ref{tab:setpci_registers}, un elenco completo di tutti i
nomi definiti è riportato nella pagina di manuale di \texttt{setpci} (i nomi
sono riportati in maiuscolo, ma possono essere specificati anche in
minuscolo), per il relativo significato si può fare riferimento alla
dichiarazione delle costanti omonime in \texttt{/usr/include/linux/pci.h} o
alle specifiche dello standard PCI.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Registro} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{device\_id}& identificativo del dispositivo. \\
    \texttt{vendor\_id}& identificativo del produttore del dispositivo. \\
    \texttt{latency\_timer}& imposta un temporizzatore scaduto il quale il
                             dispositivo rilascia l'uso del bus (così si 
                             permette un uso più corretto del bus da parte di
                             altri dispositivi presenti). \\
    \texttt{min\_gnt}& valore (in sola lettura) del tempo minimo per il quale
                       deve essere garantito l'uso del bus al dispositivo (in
                       unità di quarti di microsecondo). \\
    \texttt{max\_lat}& valore (in sola lettura) che specifica quanto spesso il
                       dispositivo necessita di accedere al bus (in
                       unità di quarti di microsecondo). \\
    \hline
  \end{tabular}
  \caption{Costanti identificative di alcuni registri PCI usate dal comando
    \texttt{setpci}.}  
  \label{tab:setpci_registers}
\end{table}



\subsection{Gestione delle interfacce SCSI}
\label{sec:SCSI_interface}

L'interfaccia SCSI (\textit{Small Computer System Interface}) potrebbe essere
inserita fra le interfacce di espansione generiche trattate in
sez.~\ref{sec:expansions_interface} in quanto anche essa definisce una
struttura a \textit{bus} su cui vengono innestati dispositivi multipli. La
trattiamo a parte in quanto in realtà questa non è necessariamente una
interfaccia collegata ad un solo PC,\footnote{è infatti possibile, anche se
  ormai questa tecnologia è completamente superata, creare un sistema di
  dischi condivisi collegando più PC sullo stesso bus SCSI.} e di norma viene
realizzata tramite l'uso di apposite schede (i cosiddetti \textit{controller
  SCSI}) che si inseriscono in una delle interfacce precedentemente citate e
vengono utilizzati tramite esse.

Una seconda differenza con le interfacce generiche di
sez.~\ref{sec:expansions_interface} è che nonostante sia possibile inserire
dispositivi diversi su un bus SCSI, l'interfaccia è utilizzata quasi
esclusivamente per l'accesso a periferiche di stoccaggio di dati
(principalmente dischi e nastri, ma anche CD e masterizzatori) e non all'uso
di periferiche generiche, ed il protocollo stesso della trasmissione dei dati
sul bus è stato pensato per questo tipo di lavoro.

Unica eccezione significativa, restata in uso per qualche tempo, è quella dei
primi scanner che, non essendo all'epoca disponibile una interfaccia più
semplice con sufficienti capacità, venivano pilotati da una interfaccia
SCSI. Oggi probabilmente l'unico altro uso ``atipico'' è quello di controllo
per i dispositivi cambia-nastri delle cosiddette \textit{tape factory}. 

%%
%% ### OBSOLETE BEGIN ###
%% Materiale obsoleto sulla storia dello SCSI
%%
\ifx\obsoletesection\undefined

Essendo una delle interfacce più antiche (la prima definizione dello standard
SCSI-1, è del 1986) le interfacce SCSI han visto una notevole evoluzione in
termini di cablature, connettori, modalità di comunicazione e caratteristiche,
con velocità di trasferimento sempre maggiori, ed un passaggio da un bus che
originariamente era parallelo, al SAS (\textit{Serial Attached SCSI}) un
collegamento di tipo seriale ad alta velocità, come avvenuto con il
\textit{Serial ATA}.  Infine con iSCSI ci si è resi indipendenti dall'uso di
uno specifico controller, facendo passare i comandi del protocollo sulla rete
tramite schede Ethernet.

\else

% Infine una caratteristica del bus SCSI è che questo non è di solito cablato in
% soluzione unica su una piastra madre, ma può essere realizzato anche con un
% insieme di connettori che collegano fra loro le varie periferiche.

Uno dei problemi maggiori con le interfacce SCSI è che dalla prima definizione
dello standard (SCSI-1, del 1986) si sono susseguite molte modifiche: lo
SCSI-2, cui segue lo SCSI-3 che però non è mai stato rilasciato come tale ed è
stato suddiviso in parti distinte dell'interfaccia. Ma anche all'interno degli
stessi standard le modalità di realizzazione delle cablature, dei connettori e
dei segnali sono le più varie, il che ha portato ad una discreta confusione.

Lo standard originario (SCSI-1) prevedeva un bus basato su un connettore a 50
pin, di cui 8 (più uno di parità) erano riservati per la trasmissione dei
dati, la frequenza di trasmissione era di 5MHz, con una corrispondente
velocità massima di trasferimento di 5MB/s, erano poi previste 4 linee per
gli indirizzi, consentendo fino ad un massimo di 8 periferiche sul bus.

Una prima modifica, chiamata \textit{Fast SCSI} venne fatta aumentando la
frequenza del bus a 10MHz per raddoppiare la velocità di trasferimento. Altre
modifiche vennero fatte riguardo la modalità di gestione dei segnali sui cavi
ed il tipo di cablatura, questo portò allo sviluppo di un secondo standard (lo
SCSI-2). Questa seconda versione prevedeva una lunga serie di estensioni,
molte delle quali relative alla gestione dei segnali sui cavi ed alla
composizione della cablatura stessa (terminazione attiva, segnali
differenziali, nuovi connettori), oltre ad un aumento dei comandi disponibili
e all'introduzione del sistema del \textit{command queing} che permetteva ad
un singolo dispositivo di accettare più comandi, in modo da poterne
ottimizzare l'ordine di esecuzione.

Una delle modifiche principali (detta \textit{Wide SCSI}), che richiede un
connettore diverso a 68 pin, prevedeva la possibilità di usare un bus per il
trasferimento dati a 16 bit (detto \textit{wide}, in contrapposizione con il
precedente, detto \textit{narrow}) raddoppiando anche il numero di periferiche
inseribili nel bus.  In questo modo si otteneva a parità di frequenza (con il
cosiddetto \textit{Fast Wide SCSI}) un raddoppio della velocità di
trasferimento 20MB/s.

Passi successivi sono state l'introduzione di bus con frequenze sempre
maggiori consentendo velocità di trasferimento sempre maggiori: \textit{Ultra
  SCSI} a 40MB/s, \textit{Ultra2} a 80MB/s, \textit{Ultra160} a 160MB/s e
ultimamente pure \textit{Ultra 320} a 320MB/s e \textit{Ultra 640} a
640MB/s. Inoltre è stato introdotto pure il SAS, \textit{Serial Attached SCSI}
in cui si è abbandonato il bus parallelo per passare ad un collegamento di
tipo seriale ad alta velocità mantenendo il protocollo dei comandi SCSI, come
avvenuto con il \textit{Serial ATA}.  Infine con iSCSI ci si è resi
indipendenti dall'uso di uno specifico controller, facendo passare i comandi
del protocollo sulla rete tramite schede Ethernet.

%%
%% ### OBSOLETE END ###
%% Materiale obsoleto su /proc/scsi
%%
\fi


\begin{figure}[!htb]
\centering
\includegraphics[width=10cm]{images/SCSI-schema}
\caption{Schema della struttura delle interfacce SCSI.}
\label{fig:SCSI_schema}
\end{figure}

Lo schema classico di una interfaccia SCSI è riportato in
fig.~\ref{fig:SCSI_schema}, il bus prevede l'esistenza di almeno una
\textsl{unità di controllo}, la scheda, detta \textit{controller SCSI}, che in
genere si mette sul bus PCI del computer, e a cui si collegano le altre
periferiche utilizzando gli appositi connettori. Un singolo controller può
gestire anche più bus, nel qual caso sarà in grado di alloggiare più
connettori. Tutte le periferiche sul bus, compresa l'unità di controllo,
vengono identificate attraverso un indirizzo di identificazione, detto SCSI
ID.

\begin{figure}[!htb]
\centering
\includegraphics[width=10cm]{images/kernel-scsi-schema}
\caption{Strutturazione del supporto alle interfacce SCSI nel kernel.}
\label{fig:SCSI_kernel_schema}
\end{figure}

Nel caso di Linux il supporto SCSI è presente fin dalle prime versioni del
kernel, ma dato che lo standard prevede vari tipi di periferiche a partire dal
kernel 2.4 il sistema è stato organizzato su tre livelli, secondo lo schema
illustrato in fig.~\ref{fig:SCSI_kernel_schema}. Al livello più alto,
utilizzati direttamente dai programmi quando accedono ai relativi file di
dispositivo, stanno i driver per le periferiche che si trovano sul bus, come
CD, nastri o dischi, ciascuno dei quali richiede una modalità d'accesso
distinta; a questi si aggiunge il supporto generico che viene usato come
interfaccia per inviare direttamente comandi ad una periferica (che viene
usato per pilotare dispositivi particolari come gli scanner o i
masterizzatori).

Il livello intermedio costituisce il collante fra i driver dei dispositivi
finali ed i driver che invece si occupano di gestire i controller per
l'accesso al bus, che saranno diversi a seconda della scheda SCSI utilizzata.
Oltre a quest'ultimi però si situano a questo livello anche tutti i moduli che
consentono di utilizzare il protocollo SCSI per controllare dispositivi posti
su altre interfacce. Ad esempio il protocollo viene utilizzato per accedere ai
dischi sia sul bus USB (che siano memorie a stato solido o veri e propri hard
disk) che \textit{Serial ATA}, sia per utilizzare i masterizzatori IDE
attraverso un meccanismo di emulazione. In tal caso i comandi del protocollo
SCSI, invece di diventare segnali elettrici su connettore attaccato ad un
controller, saranno inviati su un bus virtuale fornito dal driver per il
supporto di dette funzionalità.

Le periferiche accedute tramite interfaccia SCSI sono identificate attraverso
quattro numeri: il primo è l'\textit{host adapter number} che identifica, come
il nome stesso indica, quale è l'interfaccia (in genere la scheda col
controller, ma può essere anche l'interfaccia di un bus virtuale) con cui si
accede ai dispositivi; il numero viene assegnato dal kernel all'avvio a
seconda dell'ordine in cui rileva le schede presenti o di quando viene
abilitato il supporto per bus virtuali che si utilizzeranno.  L'\textit{host
  adapter number} è un numero progressivo che parte da zero.

Il secondo numero è il cosiddetto \textit{channel number}, che identifica
ciascun bus (detto anche, in altra nomenclatura, \textsl{canale SCSI})
associato ad un \textit{host adapter}; alcuni controller infatti possono
gestire più di un bus, e questi saranno numerati progressivamente a partire da
zero, nell'ordine in cui l'adattatore stesso li presenta (che dipenderà
ovviamente da come è fatto quest'ultimo). Anche questo è un numero progressivo
che parte da zero.

All'interno di ciascun \textsl{canale} si avrà poi l'identificativo del
singolo dispositivo posto su di esso (lo SCSI ID di cui abbiamo già parlato).
In genere sui dispositivi questo viene stabilito dall'utente con degli
appositi interruttori; di norma sono presenti dei jumper che permettono di
impostare le linee corrispondenti, anche se in alcuni confezionamenti sono
disponibili dei selettori. Per i controller invece l'identificativo può essere
modificato dal BIOS di configurazione, ma è in genere preimpostato al valore
più alto (in genere 7) che è quello che ha maggiore priorità.

Infine alcuni dispositivi più sofisticati (come le unità a nastro dotate di
libreria, o i juke-box di CDROM) possono avere al loro interno diverse
funzionalità che vengono allora indirizzate da un quarto numero detto
\itindex{Logical Unit Name (LUN)} \textit{Logical Unit Name}, o LUN.  In
questo caso la periferica da usare (ad esempio l'unità a nastro o il
meccanismo di controllo della libreria) viene identificata completamente
usando anche il LUN; per la maggioranza dei dispositivi, che non hanno più
periferiche a bordo, questo è nullo.  Pertanto una modalità di indicare le
periferiche SCSI è quella di fornire una quadrupletta di numeri che indicano
interfaccia, canale, ID e LUN, del tipo di:
\begin{Example}
<scsi(_adapter_number), channel, id, lun>
\end{Example}
e quando esse vengono riconosciute dal kernel in fase di avvio si otterranno
nei log (o nell'uscita di \texttt{dmesg}) dei messaggi del tipo:
\begin{FileExample}[label=dmesg]
scsi0 : SCSI emulation for USB Mass Storage devices
  Vendor: IC35L120  Model: AVV207-0          Rev:  0 0
  Type:   Direct-Access                      ANSI SCSI revision: 02
USB Mass Storage device found at 2
...
SCSI device sda: 241254720 512-byte hdwr sectors (123522 MB)
sda: assuming drive cache: write through
 sda: sda1
Attached scsi disk sda at scsi0, channel 0, id 0, lun 0
\end{FileExample}
e si noti come in questo caso sia stato rilevato un disco su USB, in cui
l'interfaccia di emulazione viene vista come \texttt{scsi0}, ed il dispositivo
viene riconosciuto (non essendo qui disponibile un meccanismo di assegnazione
degli ID ogni dispositivo verrà associato ad una diversa interfaccia) con
valori del canale, ID e LUN nulli.

%%
%% ### OBSOLETE BEGIN ###
%% Materiale obsoleto su /proc/scsi/
%%
\ifx\obsoletesection\undefined
\relax
\else

Nei kernel fino al 2.4 le informazione relative alle interfacce SCSI erano
disponibili nella directory
\index{filesystem~\texttt{/proc}!\texttt{/proc/scsi}} \texttt{/proc/scsi}, ed
in particolare nel file \texttt{scsi}; un esempio del contenuto del file,
quando si ha una interfaccia cui sono agganciati più dispositivi è il
seguente:
\begin{Verbatim}[fontsize=\footnotesize,%frame=single,samepage=true,
  xleftmargin=1cm,xrightmargin=1.5cm]
root@ellington:~# cat /proc/scsi/scsi
Attached devices:
Host: scsi0 Channel: 00 Id: 00 Lun: 00
  Vendor: MATSHITA Model: CD-R   CW-7502   Rev: 4.10
  Type:   CD-ROM                           ANSI SCSI revision: 02
Host: scsi0 Channel: 00 Id: 01 Lun: 00
  Vendor: PIONEER  Model: CD-ROM DR-U16S   Rev: 1.01
  Type:   CD-ROM                           ANSI SCSI revision: 02
Host: scsi0 Channel: 00 Id: 02 Lun: 00
  Vendor: SEAGATE  Model: ST118202LW       Rev: 0004
  Type:   Direct-Access                    ANSI SCSI revision: 02
\end{Verbatim}
ed in questo caso si noti come ci siano tre diversi ID per tre diverse
periferiche. 

%%
%% ### OBSOLETE END ###
%% Materiale obsoleto su /proc/scsi
%%
\fi

Come mostrato nel precedente esempio sul contenuto dei messaggi di avvio
ogni volta che una periferica viene rilevata su una interfaccia SCSI gli viene
assegnato un file di dispositivo, quest'ultimo dipende dal tipo di
dispositivo, come visto in sez.~\ref{sec:disk_structure} nel caso di dischi
essi sono tutti nella forma \texttt{/dev/sd\textsl{X}} dove
\texttt{\textsl{X}} è una lettera progressiva a partire da \texttt{a}; le
eventuali partizioni saranno accedute per numeri crescenti a partire da 1,
esattamente come per i dischi IDE classici.

Qualora invece si abbia a che fare con dei CDROM si avranno dispositivi
diversi, in particolare nel caso del secondo esempio si avrà (andando a
controllare i messaggi di avvio) un risultato del tipo:
\begin{Verbatim}
Attached scsi CD-ROM sr0 at scsi0, channel 0, id 0, lun 0
Attached scsi CD-ROM sr1 at scsi0, channel 0, id 1, lun 0
\end{Verbatim}
i CD infatti vengono acceduti con i dispositivi \texttt{/dev/sr\textsl{N}}
dove \texttt{\textsl{N}} è un numero progressivo a partire da 0; un nome
equivalente, anch'esso utilizzato, è \texttt{/dev/scd\textsl{N}}. Gli altri
dispositivi utilizzati sono \texttt{/dev/sg\textsl{N}} per l'utilizzo del
driver generico (quello con cui si pilotano ad esempio masterizzatori e
scanner) e \texttt{/dev/st\textsl{N}} per i nastri (con l'alternativa di
\texttt{/dev/nst\textsl{N}}, in cui il nastro non viene riavvolto quando
arriva alla fine).

%%
%% ### OBSOLETE BEGIN ###
%% Materiale obsoleto su /proc/scsi/
%%
\ifx\obsoletesection\undefined
\relax
\else

Una caratteristica speciale del file \texttt{/proc/scsi/scsi} è che questo può
essere acceduto anche in scrittura, si possono così rimuovere e aggiungere
dispositivi, funzionalità che può essere utile qualora si disponga di
periferiche \textit{hot-swap} che possono essere estratte a caldo dal
bus\footnote{questo è possibile solo se il bus e le periferiche sono cablati
  con dei connettori appositi che supportino questa funzionalità.}; questo può
essere fatto con comandi come:
\begin{Verbatim}[frame=single,samepage=true,xleftmargin=1cm,xrightmargin=1.5cm]
echo "scsi remove-single-device H C I L" > /proc/scsi/scsi
echo "scsi add-single-device H C I L" > /proc/scsi/scsi
\end{Verbatim}
dove \texttt{H}, \texttt{C}, \texttt{I} ed \texttt{L} sono la solita
quadrupletta di numeri che identifica il dispositivo.  Ovviamente un
dispositivo potrà essere rimosso solo se non è al momento utilizzato.

Le altre informazioni presenti nella directory \texttt{/proc/scsi} sono una
directory per ciascuna interfaccia utilizzata, con il nome del relativo modulo
di kernel, contenente un file con nome corrispondente al numero di ciascun
\textit{host adapter number} presente con quella interfaccia, nella forma:
\begin{Verbatim}
/proc/scsi/<driver_name>/<scsi_adapter_number>
\end{Verbatim}
così nelle situazioni dei due esempi illustrati potremo trovare la directory
\texttt{aic7xxx} in caso e la directory \texttt{usb-storage} nell'altro, e in
quest'ultimo caso, quando utilizziamo oltre al disco fisso anche una penna
USB, otterremo al suo interno due file, corrispondenti alle due istanze della
stessa interfaccia viste come \textit{host adapter} diversi.\footnote{si
  avrebbe lo stesso risultato nel caso si installassero più schede con lo
  stesso controller.}

%%
%% ### OBSOLETE END ###
%% Materiale obsoleto su /proc/scsi
%%
\fi

Con il kernel 2.6 l'informazione relativa ai dispositivi SCSI è stata rimossa
dalla directory \texttt{/proc/scsi/} e viene mantenuta sotto \texttt{/sys}
grazie al filesystem \textit{sysfs}. Questo però la rende assai meno fruibile
e per questo è disponibile un comando specifico,
\index{comando!\texttt{lsscsi}} \texttt{lsscsi} che consente di ottenere un
elenco di tutti i dispositivi SCSI presenti nel sistema. Eseguendolo si
otterrà qualcosa del tipo:
\begin{Console}
root@selinor:~# \textbf{lsscsi}
[0:0:0:0]    disk    FUJITSU  ETERNUS_DXL      0000  /dev/sdb
[0:0:0:1]    disk    FUJITSU  ETERNUS_DXL      0000  /dev/sdc
[1:0:0:0]    disk    ATA      ST3250310AS      4.AA  /dev/sda
[5:0:0:0]    cd/dvd  TSSTcorp DVD-ROM TS-H353C FS02  /dev/sr0
\end{Console}
dove in prima colonna viene riportata la quadrupletta di numeri che
costituiscono l'identificativo del dispositivo sul bus SCSI, seguita dalla sua
tipologia (disco, CD o altro), e da alcuni dati relativi al produttore
ottenuti dal bus stesso. Infine in ultima colonna viene riportato il file di
dispositivo con cui vi si può accedere.

Rispetto agli equivalenti dispositivi IDE classici in genere dischi e CDROM
SCSI hanno prestazioni superiori per la capacità del bus di gestire l'invio di
comandi multipli, vista però la maggiore complessità del protocollo sono anche
in genere più costosi, per questo CD e masterizzatori sono ormai praticamente
inesistenti da anni, e rimangono sostanzialmente solo dischi e nastri per
l'uso professionale, anche se i primi subiscono sempre di più la concorrenza
da parte del \textit{Serial ATA} che ha prestazioni sostanzialmente
equivalenti e che comunque viene visto con la stessa interfaccia.

Un secondo aspetto da tenere presente nel caso di dispositivi SCSI classici è
che in genere il cablaggio degli stessi è piuttosto delicato, alcuni bus
infatti devono essere opportunamente \textsl{terminati} per consentire una
corretta trasmissione dei segnali, inoltre la presenza di diversi standard
sullo stesso bus può portare a degrado di prestazioni. Infine occorre tenere
sotto controllo l'allocazione degli ID, che è di norma a carico degli utenti,
la presenza di due dispositivi con lo stesso ID infatti li rende entrambi
inutilizzabili.

Nelle distribuzioni recenti i programmi di gestione dell'interfaccia SCSI sono
distribuiti con il pacchetto \texttt{scsitools}; il principale è
\index{comando!\texttt{scsiinfo}} \texttt{scsiinfo} che permette di
interrogare un dispositivo (passato come argomento) per ricavarne tutta una
serie di proprietà (per l'elenco completo e le relative spiegazioni si
consulti la pagina di manuale), è invece da segnalare l'uso dell'opzione
\texttt{-l}, da usare senza specificare un dispositivo, che riporta quelli
presenti.

%% OBSOLETO
% Infine sempre con questo pacchetto viene anche fornito lo script
% \texttt{rescan-scsi-bus.sh} che esegue una scansione del bus abilitando nuovi
% dispositivi eventualmente aggiunti dopo il boot, utilizzando i comandi da
% inviare sul file \texttt{/proc/scsi/scsi} illustrati in precedenza; con i
% kernel della serie 2.6 questo in genere non è necessario dato che la gestione
% dei dispositivi viene affidata al sistema di \textit{udev} che
% è in grado di riconoscere automaticamente l'aggiunta di nuovi dispositivi.


\subsection{Gestione delle interfacce seriali}
\label{sec:serial_interface}

Le interfacce seriali sono una delle prime interfacce create per la
comunicazione fra computer, e prevedono appunto una comunicazione via cavo
estremamente semplice (e di breve distanza) basata sull'invio dei dati lungo
una linea di trasmissione, in cui un dato viene trasmesso appunto come una
sequenza di singoli segnali che traducono direttamente il valore dello stesso
espresso come sequenza di bit.

Benché oggi stiano sparendo, le seriali sono una delle interfacce di
comunicazione più elementari, presenti fin dai primi PC. Fino a qualche tempo
fa tutti i PC montavano almeno due interfacce, ma oggi, data la lentezza della
comunicazione e la presenza di nuove interfacce più veloci (come l'USB) sono
praticamente scomparse, anche se resta la disponibilità di adattatori USB che
consentono comunque di utilizzare questo tipo di interfaccia. Ciò non di meno
esse restano le interfacce tipiche con cui vengono gestiti i modem
telefonici,\footnote{quelli esterni, ma pure alcuni di quelli interni, sia che
  siano modem reali che modem finti, come i winmodem.}  ed per la loro
semplicità realizzativa una delle interfacce più comuni usate per collegarsi
ad apparati esterni come router, switch programmabili o dispositivi
industriali.

A causa delle limitazioni dell'architettura originale dei PC, l'uso
contemporaneo di due porte seriali crea problemi se queste condividono la
stessa linea di \textit{interrupt}. Per questo quando era necessario un numero
maggiore di porte seriali occorreva utilizzare apposite schede di
estensione. Esistono ad esempio delle schede dedicate ad alta velocità, usate
per lo più dai provider per gestire i modem, per le quali il kernel è in grado
di supportare la condivisione degli \textit{interrupt}.  Un altro caso di
conflitto è quello in cui, come parte di una scheda ISDN o di un modem-fax
interno, diventa disponibile una nuova interfaccia seriale e bisogna
verificare che questa non sia sulla stessa linea di \textit{interrupt} di una
porta seriale che è già in uso.

Tutte queste problematiche oggi sono sostanzialmente scomparse, come le schede
seriali sulla scheda madre. Qualora si usi una porta seriale su adattatore USB
infatti questi problemi di conflitti non si pongono, dato che in tal caso
vengono usate le risorse associate a questo bus di comunicazione, mantenendo
per il resto inalterate le capacità di comunicazione.

Data la loro presenza fin dai primi PC compatibili, l'assegnazione delle
risorse delle porte seriali sulla scheda madre è predefinita, e sia le porte
di I/O che gli \textit{interrupt} utilizzati per le 4 porte previste
dall'architettura classica del PC sono riportati in
tab.~\ref{tab:serial_port_resources}, insieme ai file di dispositivo con cui
si può accedere ad essi.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|l|l|}
    \hline
    \textbf{Interrupt} & \textbf{Porta I/O} &\textbf{Dispositivo} \\
    \hline
    \hline
    4 & \texttt{0x3F8}&\texttt{/dev/ttyS0}\\
    3 & \texttt{0x2F8}&\texttt{/dev/ttyS1}\\
    4 & \texttt{0x3E8}&\texttt{/dev/ttyS2}\\
    3 & \texttt{0x2E8}&\texttt{/dev/ttyS3}\\
    \hline
  \end{tabular}
  \caption{Risorse e file di dispositivo usati dalle porte seriali.}
  \label{tab:serial_port_resources}
\end{table}

Benché le seriali siano praticamente scomparse dai PC ordinari, è comunque
utile tenere presente i file di dispositivo di
tab.~\ref{tab:serial_port_resources}, dato che queste interfacce restano
presenti su moltissimi dispositivi embedded su cui gira Linux. La lettura o la
scrittura dei dati di una seriale infatti avviene in maniera estremamente
semplice: basta leggere o scrivere sul suo file di dispositivo. 

Uno dei problemi più comuni che si possono avere utilizzando altre porte oltre
quelle standard è che queste possono non essere configurate correttamente. Per
ovviare a questo problema si può utilizzare il programma di configurazione
delle interfacce seriali \index{comando!\texttt{setserial}}
\texttt{setserial}.  Questo prende come primo argomento il file di dispositivo
da configurare (o controllare), se utilizzato senza opzioni viene stampato un
breve riassunto delle principali caratteristiche dello stesso:
\begin{Console}
hain:~# \textbf{setserial /dev/ttyS1}
/dev/ttyS1, UART: 16550A, Port: 0x02f8, IRQ: 3
\end{Console}
dove sono mostrate rispettivamente il tipo di chip della porta seriale (nel
caso un \texttt{16550A}) la porta di I/O e la linea di \textit{interrupt}
utilizzate.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-a}& stampa tutte le informazioni disponibili. \\
    \texttt{-b}& stampa un riassunto della configurazione. \\
    \texttt{-G}& stampa le informazioni nel formato in cui vengono prese sulla
                 riga di comando. \\
    \texttt{-z}& azzera tutti i valori prima di fare le impostazioni. \\
    \hline
  \end{tabular}
  \caption{Principali opzioni per il comando \texttt{setserial}.} 
  \label{tab:setserial_options}
\end{table}

Quando il comando viene utilizzato con l'opzione \texttt{-g} gli argomenti
vengono interpretati come una lista di dispositivi di cui stampare le
proprietà; l'output delle informazioni riportate dal comando è controllato
dalle ulteriori opzioni \texttt{-a}, che fa stampare tutte le informazioni
possibili, e \texttt{-b} che riporta solo un riassunto della configurazione
del dispositivo; l'elenco delle principali opzioni è riportato in
tab.~\ref{tab:setserial_options}.

Se invocato senza l'opzione \texttt{-g}, gli argomenti successivi al primo
permettono di indicare quale parametro del dispositivo deve essere impostato
dal comando; in generale soltanto l'amministratore può modificare i parametri
dell'interfaccia, ma alcuni di questi possono essere impostati anche da un
utente normale. 

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{autoconfig} & fa eseguire una auto-configurazione al kernel (la
                          porta di I/O deve essere già impostata) con cui
                          determinare la UART e se \texttt{auto\_irq} anche la
                          linea di \textit{interrupt}.\\
    \texttt{auto\_irq}  & richiede di auto-configurare anche la linea di
                          \textit{interrupt}. \\
    \texttt{baud\_base X}& imposta la frequenza delle operazioni di base, in
                           bit per secondo, in genere vale 115200, che è il
                           massimo raggiungibile da una seriale standard. \\
    \texttt{divisor N}  & imposta il divisore con cui calcolare una velocità
                          personalizzata.\\
    \texttt{irq N}      & imposta il numero della linea di \textit{interrupt}.\\
    \texttt{port 0xHHHH}& imposta la porta di I/O. \\
    \texttt{spd\_hi}    & richiede l'uso di una velocità di 57600bps (bit per
                          secondo). \\
    \texttt{spd\_vhi}   & richiede l'uso di una velocità di 115200bps (bit per
                          secondo). \\
    \texttt{spd\_shi}   & richiede l'uso di una velocità di 230400bps (bit per
                          secondo). \\
    \texttt{spd\_warp}  & richiede l'uso di una velocità di 460800bps (bit per
                          secondo). \\
    \texttt{spd\_normal}& richiede l'uso di una velocità di 38400bps (bit per
                          secondo). \\
    \texttt{spd\_cust}  & richiede una velocità personalizzata pari a valore di
                          \texttt{baud\_base} diviso per quello di
                          \texttt{divisor}.\\ 
    \texttt{uart type}  & imposta il tipo di chip, i principali valori sono
                          \texttt{8250}, \texttt{16450}, \texttt{16550},
                          \texttt{16550A}, ecc. (per la lista si faccia
                          riferimento alla pagina di manuale); con
                          \texttt{none} si disabilita la porta. \\ 
    \hline
  \end{tabular}
  \caption{Principali direttive di impostazione del comando
    \texttt{setserial}.}  
  \label{tab:setserial_command}
\end{table}

I due parametri principali impostabili dal comando sono \texttt{port} e
\texttt{irq}, il cui significato è ovvio e che prendono rispettivamente come
ulteriore argomento il numero di porta e di \textit{interrupt}.  Si può
inoltre impostare a mano (qualora non venisse riconosciuta correttamente) il
tipo di interfaccia (la UART, \textit{Universal Asynchronous
  Receiver/Transmitter}) con \texttt{uart}; infine si può controllare la
velocità della porta seriale con la serie di argomenti \texttt{spd\_*} il cui
significato, insieme a quello degli altri parametri principali, è riportato in
tab.~\ref{tab:setserial_command}; al solito per una descrizione dettagliata su
può fare riferimento alla pagina di manuale di \texttt{setserial}.

% TODO: trattare stty e le velocità.

Dato che spesso l'interfaccia viene usata per fornire una console di accesso
(si noti come il nome del file di dispositivo richiami quello generico
dell'interfaccia dei terminali \texttt{tty}) il modo più comune per usare
l'interfaccia è quella di fare ricorso ad un emulatore di terminale seriale da
usare interattivamente, come il programma \index{comando!\texttt{minicom}}
\texttt{minicom}. In tal caso il programma, lanciato all'interno di una
qualunque finestra di terminale, legge dalla seriale stampando sullo schermo e
scrive sulla stessa quanto immesso dalla tastiera.

Quando viene lanciato \texttt{minicom} si collega sulla porta seriale che si è
configurata come default. Questa si può cambiare lanciando il comando con
l'opzione \texttt{-s} che non effettua il collegamento e fa partire il comando
(che fornisce una interfaccia semigrafica) direttamente sul menu di
configurazione che consente di scegliere la porta seriale e le impostazioni.

%TODO completare minicom


\subsection{Gestione delle interfacce USB}
\label{sec:USB_interface}

L'interfaccia USB (\textit{Universal Serial Bus}) nasce sulla piattaforma PC
allo scopo di fornire una interfaccia di comunicazione semplificata e con
prestazioni ridotte, ma molto semplice da realizzare e poco costosa per la
realizzazione di dispositivi semplici (ed in genere portabili, è infatti
prevista anche la capacità di fornire alimentazione) che non necessitano di
tutte le risorse (in termini di velocità di accesso, potenza di alimentazione
e banda passante nella trasmissione dei dati) fornite dalle usuali interfacce
di espansione trattate in sez.~\ref{sec:expansions_interface}.

Un bus USB è costruito in maniera gerarchica ed è controllato da una
\textsl{unità di controllo} (o \textit{host}), a cui è direttamente collegato
un \textsl{concentratore} (o \textit{hub}) radice a cui tutti i dispositivi o
eventuali altri concentratori secondari vanno ad agganciarsi, secondo la
struttura mostrata in fig.~\ref{fig:USB_schema}. Il protocollo prevede che le
comunicazioni siano tutte controllate dall'unità di controllo, che è l'unica
che può iniziare una comunicazione, ed i dispositivi possono solo rispondere
all'unità di controllo; non è prevista nessuna possibilità di comunicazione
dei singoli dispositivi fra di loro. 

Altre architetture di bus non hanno queste limitazioni, ma USB è stato
progettato con un compromesso fra prestazione ed economicità, per cui si sono
evitate funzionalità avanzate come l'\textsl{arbitraggio} del bus che
comportano una maggiore complessità realizzativa per dispositivi che dovevano
essere estremamente semplici.

In genere su un computer è presente un solo \textit{host}, anche se, per la
diffusione di dispositivi, alcuni ne hanno più di uno, ed è comunque possibile
aggiungerne altri usando schede di espansione. A ciascun \textit{host} in
genere sono agganciate 2 o 4 porte. A ciascuna porta USB si può agganciare un
dispositivo o un \textit{hub}, il quale a sua volta avrà altre porte cui
agganciare altri dispositivi ed \textit{hub}.  

\begin{figure}[!htb]
\centering
\includegraphics[width=10cm]{images/USB-schema}
\caption{Schema della struttura di un bus USB.}
\label{fig:USB_schema}
\end{figure}

Il bus prevede fino ad un massimo di 127 unità per ciascuna unità di
controllo; la presenza di \textit{hub} secondari permette l'utilizzo di un
maggior numero di periferiche rispetto alle porte presenti sul PC, ma si tenga
conto che anche essi contano come unità sul bus, pertanto le unità disponibili
per le periferiche sono in realtà 127 meno il numero di \textit{hub}
aggiuntivi.

Come mostrato in fig.~\ref{fig:USB_schema} il bus prevede due direzioni per il
flusso dei dati, dall'\textit{host} alla periferica e viceversa, indicati con
\textit{downstream} e \textit{upstream}; inoltre vengono specificati quattro
\textsl{tipi} di trasferimento:
\begin{basedescript}{\desclabelwidth{1.5cm}\desclabelstyle{\nextlinelabel}}
\item[Control transfers] utilizzati per inviare pacchetti di controllo, che
  devono essere di dimensioni ridotte e trasportati con affidabilità; vengono
  usati per configurare i dispositivi e per supportare i comandi di controllo
  di base.
\item[Bulk transfers] usati per trasmettere dati alla massima velocità
  possibile in maniera affidabile; vengono usati per i trasferimenti di dati
  da e verso i dispositivi.
\item[Interrupt transfers] simili ai precedenti, ma ripetuti periodicamente;
  la richiesta cioè viene ripetuta periodicamente e vengono utilizzati come
  meccanismo di notifica dato che non esiste un vero e proprio
  \textit{interrupt}.
\item[Isochronous transfers] usati per inviare e riceve dati potendo contare
  su una quantità di banda garantita, ma senza affidabilità, usati per
  trasferimenti \textit{real-time} (ad esempio i trasferimenti per video e
  audio).
\end{basedescript}

La presenza di due direzioni nel flusso di dati si riflette anche sui
connettori, che in genere sono classificati in due tipi diversi, a seconda che
siano rivolti all'unità di controllo (di \textsl{tipo A}) o verso una
periferica (di \textsl{tipo B}). Inoltre i dispositivi si possono suddividere
in auto-alimentati, alimentati dal bus (che fornisce un massimo di 400 mA,
quindi attenzione a non sovraccaricare, pena il rischio di non far funzionare
nulla per mancanza di potenza) o entrambi. Un'altra distinzione fra i
dispositivi è fra quelli \textsl{lenti} (come mouse, tastiere, ecc.) che
comunicano al massimo ad 1.5MB/s e quelli \textsl{veloci} che possono usare
potenzialmente fino al 90\% della banda passante massima.

La prima versione del protocollo (USB 1.0) consentiva una banda passante
massima di 1.5 Mbit/s ma venne presto aumentata a 12Mbit/s con la versione
1.1. Tuttavia l'uso di dispositivi lenti, gli \textit{interrupt} e l'overhead
del protocollo non consentono velocità superiori a 8.5Mbit/s anche in
condizioni ideali, mentre prestazioni tipiche sono intorno ai 2Mbit/s. La
seconda versione del protocollo, la USB 2.0, permette invece di portare la
banda passante ad un massimo teorico 480Mbit/s, ampliando notevolmente
l'utilizzabilità del bus per l'utilizzo con dispositivi di stoccaggio esterni,
in particolare con dischi rimuovibili. Infine l'ultima versione del protocollo
(USB 3.0) porta la banda passante a 4.8 Gbit/s (anche se quella effettiva
viene stimata ad un massimo di 3.2 Gbit/s) con la modalità \textit{superspeed}
che richiede un diverso tipo di cavi, consente anche l'uso di interconnessioni
ottiche pur restando retro-compatibile con USB 2.0. L'ultima versione alla
scrittura di questa sezione, soltanto annunciata, è la 3.1 che arriva ad una
velocità teorica di 10 Gbit/s.

%%
%% ### OBSOLETE BEGIN ###
%% Materiale obsoleto su USB 1.0
%%
\ifx\obsoletesection\undefined
\relax
\else

Negli ultimi tempi praticamente qualunque PC compatibile viene fornito di
interfaccia USB, usualmente fornita direttamente dal \textit{chipset} della
piastra madre, anche se sono disponibili schede PCI con a bordo delle unità di
controllo. Per quanto riguarda USB 1.0 le unità di controllo sono
sostanzialmente di due tipi, quelle compatibili con le specifiche OHCI
(\textit{Open Host Controller Interface}) della Compaq, usata anche nel mondo
Mac o quelle compatibili con le specifiche UHCI (\textit{Universal Host
  Controller Interface}) della Intel. Le funzionalità sono le stesse, ma la
seconda specifica richiede hardware più semplice e quindi è meno costosa, ma
richiede un driver più complesso e quindi un maggior carico sulla CPU.

Il supporto per USB venne introdotto per la prima volta a partire dal kernel
2.2.7, ma nella serie 2.2.x il supporto era elementare, almeno fino al 2.2.18
in cui furono incluse parecchie funzionalità del 2.4. Per un supporto pieno
delle funzionalità del bus (ed in particolare per utilizzare dischi su USB)
occorre comunque usare un kernel della serie 2.4.x o successivo.  In ogni caso
Linux supporta entrambi i tipi di unità di controllo di USB 1 (UHCI o OHCI),
utilizzando rispettivamente i moduli \texttt{usb-uhci} e \texttt{usb-ohci} (da
selezionare nella relativa sezione di configurazione del kernel, vedi
sez.~\ref{sec:kernel_compile}). I kernel recenti supportano completamente
anche la successiva versione 2 del protocollo, presente su tutti i PC moderni,
e la più recente versione 3, che però ancora non ha avuto una grande
diffusione, in questo caso non esistono però varianti e le specifiche sono le
stesse per tutti i controller.

In genere, se si deve utilizzare USB 1, comunque supportati da tutti i
controller per compatibilità con i vecchi dispositivi, è estremamente facile
riconoscere quale delle due interfacce citate viene utilizzata, basta infatti
usare \texttt{lspci} per verificare il tipo di unità di controllo; avremo
allora, a seconda dei casi, per una macchina che ha una unità UHCI:
\begin{Console}
urras:~# \textbf{lspci -v}
...
00:04.2 USB Controller: VIA Technologies, Inc. VT82xxxxx UHCI USB 1.1 Controlle
r (rev 10) (prog-if 00 [UHCI])
        Subsystem: VIA Technologies, Inc. (Wrong ID) USB Controller
        Flags: bus master, medium devsel, latency 32, IRQ 9
        I/O ports at b400 [size=32]
        Capabilities: [80] Power Management version 2
...
\end{Console}
mentre per una unità OHCI si avrà:
\begin{Console}
anarres:~# \textbf{lspci -v}
...
00:0f.2 USB Controller: ServerWorks CSB6 OHCI USB Controller (rev 05) (prog-if 
10 [OHCI])
        Subsystem: ServerWorks: Unknown device 0220
        Flags: bus master, medium devsel, latency 32, IRQ 5
        Memory at fe120000 (32-bit, non-prefetchable) [size=4K]
...
\end{Console}

Invece se si dispone di una unità USB 2, le specifiche utilizzate sono quelle
della \textit{Extended Host Controller Interface}, identificata con la sigla
EHCI, mentre in questo caso il modulo da utilizzare è \texttt{ehci-hcd}. Un
tempo la scelta di quale modulo usare doveva essere fatta in sede di
installazione, e fissata con la configurazione dei moduli (vedi
sez.~\ref{sec:kernel_modules}), con i kernel recenti e l'uso di \textit{udev}
e \textit{hotplug} questa in genere avviene automaticamente, anche se in certi
casi, in caso di errori nel rilevamento, può risultare necessario effettuare
una configurazione manuale.

%%
%% ### OBSOLETE END ###
%% Materiale obsoleto su USB 1.0
%%
\fi

Una delle caratteristiche del bus USB è che, a differenza ad esempio di quanto
avveniva all'epoca per il bus SCSI, la numerazione delle periferiche presenti
non deve essere effettuata a mano, essendo eseguita dal bus stesso.  L'altra
caratteristica interessante del bus USB è che esso supporta sempre la
possibilità di disconnettere a caldo i dispositivi, anche se questo può avere
conseguenze poco piacevoli se fatto senza accortezza. Per questo motivo in
genere all'uso del bus è legato quello del sistema di \textit{udev} e
\textit{hotplug} (vedi sez.~\ref{sec:udev_hotplug}) che è in grado di rilevare
la connessione e la disconnessione di nuove periferiche caricando (e
rimuovendo) automaticamente i relativi moduli.

Il bus fornisce inoltre al kernel la possibilità di rilevare tutta una serie
di informazioni dai singoli dispositivi, il protocollo infatti prevede che
questi forniscano i dati relativi a loro stessi. Questa informazione era
inizialmente disponibile sotto la directory \texttt{/proc/bus/usb}
\index{filesystem~\texttt{/proc}!\texttt{/proc/bus/usb}} una volta che si
fosse montato il filesystem virtuale \textit{procbususb}.

In questo caso sotto la directory \texttt{/proc/bus/usb} compariranno tante
directory quanti sono i bus disponibili (numerate in ordine crescente),
ciascuna delle quali conterrà un file con nome il numero associato a ciascun
dispositivo presente su detto bus, contenente i relativi dati. Un sommario con
una presentazione più leggibile degli stessi dati è fornito invece dal file
\texttt{/proc/bus/usb/devices} che riporta l'elenco di tutti i dispositivi
presenti con un contenuto del tipo:
\begin{FileExample}[label=/proc/bus/usb/devices]
T:  Bus=01 Lev=00 Prnt=00 Port=00 Cnt=00 Dev#=  1 Spd=480 MxCh= 6
B:  Alloc=  0/800 us ( 0%), #Int=  0, #Iso=  0
D:  Ver= 2.00 Cls=09(hub  ) Sub=00 Prot=01 MxPS= 8 #Cfgs=  1
P:  Vendor=0000 ProdID=0000 Rev= 2.06
S:  Manufacturer=Linux 2.6.6 ehci_hcd
S:  Product=VIA Technologies, Inc. USB 2.0
S:  SerialNumber=0000:00:10.3
C:* #Ifs= 1 Cfg#= 1 Atr=40 MxPwr=  0mA
I:  If#= 0 Alt= 0 #EPs= 1 Cls=09(hub  ) Sub=00 Prot=00 Driver=hub
E:  Ad=81(I) Atr=03(Int.) MxPS=   2 Ivl=256ms

T:  Bus=01 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=480 MxCh= 0
D:  Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
P:  Vendor=04b4 ProdID=6830 Rev= 0.01
S:  Manufacturer=Cypress Semiconductor
S:  Product=USB2.0 Storage Device
S:  SerialNumber=600000001814
C:* #Ifs= 1 Cfg#= 1 Atr=c0 MxPwr=  0mA
I:  If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage
E:  Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=88(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
\end{FileExample}

Il principale utilizzo di questo file è per verificare se il riconoscimento di
una periferica e la relativa numerazione è stata eseguita correttamente,
infatti per ciascun dispositivo presente sul bus viene riportata nel file una
diversa sezione con tutti i dati ad esso relativi. Ogni sezione è introdotta
da una linea che inizia con la lettera \texttt{T} e che indica il
posizionamento del dispositivo all'interno del bus, dove \texttt{Bus} indica
il numero progressivo del bus, \texttt{Lev} il livello (in termini di passaggi
per eventuali \textit{hub} secondari) e \texttt{Dev} il numero progressivo
assegnato. 

Nelle righe successive sono poi riportate altre informazioni relative al
dispositivo, sono particolarmente importanti, come riportati nella riga
iniziante per \texttt{P}, gli identificatori del venditore e del prodotto che
vengono utilizzati per selezionare automaticamente il modulo da utilizzare per
il supporto del dispositivo, ma che in caso di fallimento possono essere
utilizzati per cercare informazioni su Internet; informazioni utili relative
al dispositivo sono quelle delle stringhe fornite dal produttore e mostrate
nelle righe inizianti per \texttt{S}.  Per il resto della sintassi si può fare
riferimento alla \textit{Linux USB Guide} disponibile su
\url{http://www.linux-usb.org/USB-guide/book1.html}.

Oggi la stessa informazione viene presentata direttamente sotto \texttt{/sys}
tramite l'uso di \textit{sysfs} ed in genere \texttt{/proc/bus/usb} non viene
più utilizzato. In tal caso però l'informazione risulta parcellizzata nelle
varie sottodirectory di \texttt{/sys/bus/usb}. Per avere una visualizzazione
più intelligibile delle informazioni, sono disponibili i programmi del
pacchetto \texttt{usbutils}, in particolare il programma
\index{comando!\texttt{lsusb}} \texttt{lsusb} permette di avere una lista
molto semplice dei dispositivi presenti nella forma:
\begin{Console}
root@hain:~# \textbf{lsusb}
Bus 001 Device 002: ID 04b4:6830 Cypress Semiconductor Corp.
Bus 001 Device 001: ID 0000:0000
\end{Console}

Il programma può comunque stampare la lista anche in forma gerarchica usando
l'opzione \texttt{-t}, mentre si possono ottenere informazioni molto più
dettagliate con l'opzione \texttt{-v}. Si possono poi usare le opzioni
\texttt{-s} e \texttt{-d} in maniera analoga a come si fa con \texttt{lspci}
per selezionare un singolo dispositivo sulla base rispettivamente del suo bus
e numero identificativo (con la sintassi \texttt{bus:num}) o del produttore
(usando i rispettivi identificatori cui abbiamo accennato in precedenza). Al
solito si faccia riferimento alla pagina di manuale per una descrizione
completa.



\subsection{La gestione dei dispositivi con \textit{udev} e \textit{hotplug}}
\label{sec:udev_hotplug}

Come accennato in sez.~\ref{sec:kernel_modules} nello sviluppo del kernel 2.6
è stata completamente ristrutturata la gestione dei moduli come conseguenza
della creazione di una rappresentazione generale dei dispositivi (il
cosiddetto \textit{device model}) da parte del kernel con l'uso del filesystem
\textit{sysfs} e della directory \texttt{/sys}. In concomitanza a questo è
stato poi sviluppato, in considerazione del sempre maggiore utilizzo di Linux
in ambienti di tipo desktop, un meccanismo di gestione il più trasparente e
semplificato possibile per automatizzare rilevamento e supporto dei vari
dispositivi, sia fissi che rimuovibili.

\itindbeg{hotplug}

In particolare uno dei problemi affrontati è stato quello dei dispositivi
rimuovibili a caldo, sempre più diffusi anche nelle macchine comuni anche
grazie a bus come l'USB o il Firewire. Per questo sono state realizzate
diverse infrastrutture, in particolare fin dal kernel 2.4 era stato introdotto
un meccanismo, denominato \textit{hotplug}, per cui in reazione alla avvenuta
presenza di dispositivi rimuovibili il kernel stesso provvedeva all'esecuzione
di un apposito programma in user space, \texttt{/sbin/hotplug},\footnote{o
  qualunque altro programma fosse stato indicato nel file
  \texttt{/proc/sys/kernel/hotplug}.}
\index{filesystem~\texttt{/proc}!\texttt{/proc/sys/kernel/hotplug}} che si
incaricava di caricare gli opportuni moduli ed effettuare tutte le operazioni
reputate necessarie alla gestione del dispositivo.

Il meccanismo classico di \textit{hotplug} prevedeva il passaggio delle
informazioni necessarie al programma tramite delle opportune variabili di
ambiente; queste poi venivano analizzate dal programma per identificare il
dispositivo che aveva generato l'evento, ed eseguire le azioni necessarie alla
sua gestione, fra cui ovviamente il caricamento dei moduli per il relativo
supporto. Tutte queste operazioni venivano realizzate tramite una serie di
script di shell mantenuti in \texttt{/etc/hotplug.d}, e suddivisi per i vari
tipi di bus.

Con lo sviluppo dei kernel della serie 2.6.x questo meccanismo ha cominciato a
mostrare i suoi limiti. Da una parte infatti si erano ampliate le richieste di
notifiche di eventi non più semplicemente legati alla disponibilità di un
nuovo dispositivo, ad esempio viene generato un evento anche in risposta
all'inserimento di un cavo in una scheda di rete, così da poterla configurare
automaticamente. Dall'altra lo sviluppo della rappresentazione generica dei
dispositivi richiedeva la generazione di eventi tutte le volte che si doveva
registrare una qualche nuova informazione. L'impatto dell'analisi di tutti
questi eventi iniziava ad essere pesante.

\itindbeg{udev}

Allo stesso tempo i kernel della serie 2.6.x avevano visto una completa
ristrutturazione della infrastruttura per la creazione dinamica dei file di
dispositivo (dinamica nel senso che prevedesse la presenza in \texttt{/dev}
soltanto dei file relativi ai dispositivi effettivamente presenti, e non di
tutti quelli possibili) con una realizzazione interamente in user space che
rimpiazzasse il precedente \textit{devfs},\footnote{questo era un filesystem
  virtuale che creava automaticamente il contenuto di \texttt{/dev}, ma oltre
  a non essere più mantenuto e presentare notevoli problemi nella
  realizzazione, costringeva ad inserire le politiche relative alla gestione
  dei dispositivi (i permessi ad esempio) all'interno del kernel; per questo è
  stato sostituito ed il relativo supporto è stato completamente rimosso a
  partire dal kernel 2.6.13.}  La nuova infrastruttura, denominata
\textit{udev}, prevedeva l'uso delle informazioni mantenute nell'apposito
filesystem \textit{sysfs} e degli eventi di \textit{hotplug} per la creazione
automatica dei file di dispositivo sotto \texttt{/dev}, ed un insieme di
``\textsl{regole}'' in grado di governare non solo i nomi, ma anche i permessi
e le altre caratteristiche da assegnare ai singoli dispositivi.

Per un certo periodo i due sistemi, \textit{udev} ed \textit{hotplug}, sono
stati sviluppati indipendentemente, ma nel corso della ristrutturazione di
\textit{hotplug} per far fronte al crescente numero di eventi gli sviluppatori
si sono resi conto che dato che \textit{udev} doveva comunque analizzare tutti
gli eventi per creare i file di dispositivo, non aveva senso usare un
programma a parte per caricare i moduli necessari, e che questo compito poteva
essere eseguito direttamente dal sistema di \textit{udev}.

Questo risultava possibile anche grazie alla ristrutturazione della gestione
dei moduli stessi. Come abbiamo visto in sez.~\ref{sec:kernel_modules} ogni
modulo porta con sé, fra i parametri ad esso associati, una lista degli
\textit{alias} che indicano a quale tipo di dispositivo esso può venire
associato; quando il kernel riconosce la presenza di un nuovo dispositivo è
suo compito generare un \textit{alias} per lo stesso,\footnote{il kernel lo
  ricava dalle informazioni ottenute dal dispositivo stesso, grazie agli
  identificativi previsti nei vari bus (si ricordi quanto appena visto per PCI
  e USB).} che sarà quello usato da \textit{udev} per caricare il relativo
modulo. Questo è quanto avviene oggi, a lungo, fino al 2.6.15, il meccanismo
prevedeva che il kernel creasse delle variabili di ambiente che poi dovevano
essere esaminate da \textit{hotplug} per identificare il modulo.

Per questo motivo tutte le distribuzioni recenti non prevedono più l'uso degli
script di \textit{hotplug} e la directory \texttt{/etc/hotplug.d} è
sostanzialmente vuota se non assente. Il caricamento dei moduli viene infatti
gestito direttamente dal sistema di \textit{udev} per qualunque dispositivo
venga rilevato dal kernel, mentre le eventuali operazioni da compiere per gli
eventi relativi a dispositivi rimuovibili vengono gestite in genere passando
tutti gli eventi ad un apposito demone.

Questo cambia anche le modalità con cui viene eseguito il caricamento dei
moduli, in precedenza infatti questo era associato al primo accesso ad un
dispositivo, adesso invece è associato alla sua rilevazione, pertanto se non
si vuole che certi moduli siano caricati se non si utilizza il dispositivo
sottostante, questo deve essere impedito esplicitamente: si riveda quanto
detto riguardo la direttiva \texttt{blacklist} di \texttt{modprobe.conf} in
sez.~\ref{sec:kernel_modules}.

\itindend{hotplug}

Ovviamente è possibile evitare l'uso di \textit{udev}, creando un contenuto
statico per \texttt{/dev} e mantenendo nel kernel il supporto per i
dispositivi essenziali (è quello che viene fatto per i \textit{ramdisk} di
avvio), ma l'infrastruttura si è dimostrata estremamente flessibile, ed è
stata adottata da tutte le distribuzioni. La flessibilità di \textit{udev}
deriva dal fatto che la creazione dei file di dispositivo sotto \texttt{/dev}
può essere controllata attraverso una serie di ``\textsl{regole}'', che
consentono non solo di specificarne le proprietà come nome, permessi,
proprietario, ecc. ma anche di associare alla creazione stessa azioni
ulteriori, come la creazione di più nomi o di link simbolici, e l'esecuzione
di ulteriori programmi.

\itindbeg{sysfs}

Come accennato \textit{udev} si appoggia al nuovo filesystem \textit{sysfs},
introdotto con i kernel della serie 2.6.x. Si tratta di un filesystem virtuale
analogo a \texttt{/proc}, il cui scopo principale è quello di rendere visibile
le informazioni presenti nel kernel riguardo dispositivi e relativi moduli (il
cosiddetto \textit{device model} del kernel) ai programmi in user-space. Come
richiesto dal \textit{Filesystem Hierarchy Standard} (vedi
sez.~\ref{sec:file_FHS}) deve essere montato sotto \texttt{/sys}. In questo
caso la richiesta è più stringente di una semplice esigenza di
standardizzazione: tutti i programmi e le utilità di basso livello fanno
l'assunzione che \textit{sysfs} sia montato sotto \texttt{/sys}, e non
funzionano se lo si sposta altrove.

In sostanza l'idea sottostante l'uso di \textit{sysfs} era quella di esporre
in questo filesystem caratteristiche e proprietà dei dispositivi e
sottosistemi gestiti dal kernel e di fornire qui la possibilità di effettuare
eventuali impostazioni, cercando di riportare \texttt{/proc} al suo scopo
originale di fornire informazioni relative ai processi.

Il vantaggio di \textit{sysfs} è che le informazioni sui dispositivi ed i
moduli vengono generate direttamente all'origine dal kernel stesso, e non sono
necessarie ulteriori intermediazioni; ogni volta che il kernel riconosce un
nuovo oggetto all'interno del suo \textit{device model} la relativa
informazione viene creata automaticamente dentro questo filesystem.

In particolare sotto \texttt{/sys/devices} viene creata automaticamente la
gerarchia generale di tutti i dispositivi rilevati dal kernel, espressa come
un albero di directory che rappresentano le dipendenze reciproche fra gli
stessi. Così ad esempio un dispositivo PCI (come un controller SATA) sarà
rappresentato da una directory inserita sotto la directory relativa al bus PCI
su cui esso si trova, ed un disco attaccato a un controller sarà inserito in
una directory sotto quella del suo controller.

Inoltre sotto \texttt{/sys/devices} vengono rappresentati anche quei
dispositivi che non corrispondono ad una periferica (ad esempio la CPU) ma che
sono parte integrante del sistema (sotto \texttt{/sys/devices/system}) e
quelli specifici di alcune piattaforme hardware che non rientrano in nessuna
gerarchia, come le porte di I/O usate per la seriale che si trovano solo sui
PC (sotto \texttt{/sys/devices/platform}).

Oltre a questo il sistema prevede la generazione di una serie di informazioni
aggiuntive. Ad esempio la directory \texttt{/sys/bus} viene automaticamente
popolata con link simbolici agli stessi dispositivi classificati secondo i bus
che sono stati registrati come tali nel kernel, mentre la directory
\texttt{/sys/class} conterrà invece la classificazione dei dispositivi secondo
le relative classi (di nuovo queste vengono definite direttamente dal kernel e
gestite al suo interno), e \texttt{/sys/block} l'elenco dei dispositivi a
blocchi. Inoltre la directory \texttt{/sys/modules} conterrà una directory per
ciascun modulo caricato dal kernel con le relative informazioni.

Un'altra delle caratteristiche distintive di \textit{sysfs} è che è possibile
associare in maniera molto semplice a ciascun dispositivo o modulo degli
``\textsl{attributi}'' che verranno visualizzati nel filesystem come file, su
cui è possibile leggere (e anche scrivere). In questo modo diventa semplice
rendere disponibili informazioni o caratteristiche (eventualmente modificabili
per effettuare impostazioni) relative agli stessi.

Con lo sviluppo del kernel il contenuto si \textit{sysfs} si è ampliato molto,
sono stati aggiunti contenuti e molte proprietà dei dispositivi ed altre
funzionalità del kernel possono essere impostate direttamente attraverso i
file presenti in \texttt{/sys}, con l'indicazione da parte dagli sviluppatori
del kernel di spostare al suo interno tutte quelle funzionalità che in
precedenza sarebbero state gestite tramite \texttt{/proc}, che dovrebbe invece
tornare ad essere un filesystem dedicato alla gestione dei processi. Questo
però non significa che \textit{sysfs} abbia completamente sostituito
\texttt{/proc} ed in particolare \texttt{/proc/sys} continua a mantenere lo
stesso significato illustrato in sez.~\ref{sec:sysctl_conf}.

\itindend{sysfs}

La creazione dinamica del contenuto di \texttt{/dev} viene realizzata tramite
il demone \index{demone!\texttt{udevd}} \texttt{udevd}, che viene lanciato
all'avvio e riceve dal kernel gli eventi di notifica per ciascun dispositivo
che viene aggiunto o rimosso dal sistema o che cambia stato. È compito di
\texttt{udevd} identificare il tipo di dispositivo utilizzando sia le
informazioni ricevute con l'evento che quelle presenti sotto \texttt{/sys}, e
creare di conseguenza i file di dispositivo sotto \texttt{/dev} che viene
creata come directory posta su un \index{filesystem~temporaneo} filesystem
temporaneo (la si può anche osservare nell'output di \texttt{df} mostrato in
sez.~\ref{sec:file_disk_management}).

Il comportamento di base del sistema di \textit{udev} è controllato dal
relativo file di configurazione
\index{configurazione!\texttt{/etc/udev/udev.conf}}
\texttt{/etc/udev/udev.conf}; questo usa la sintassi di un file di
assegnazioni di variabili di shell. In genere lo si usa per impostare alcune
delle variabili chiave che consentono di soprassedere i valori di default
usati dal sistema.  Le sole chiavi che può valer la pena di modificare sono
\texttt{udev\_log}, che controlla la priorità dei messaggi inviati al sistema
di \textit{syslog} (con i valori di tab.~\ref{tab:cfg_syslog_priority}) e
\texttt{tmpfs\_size} che controlla le dimensioni del filesystem temporaneo su
cui è creata \texttt{/dev}, un contenuto tipico è il seguente (estratto da una
Debian Lenny):
\begin{FileExample}[label=/etc/udev/udev.conf]
# The initial syslog(3) priority: "err", "info", "debug" or its
# numerical equivalent. For runtime debugging, the daemons internal
# state can be changed with: "udevadm control --log_priority=<value>".
udev_log="err"
# maximum size of the /dev tmpfs
tmpfs_size="10M"
\end{FileExample}

Oltre a detto file di configurazione generale le funzionalità di \textit{udev}
vengono controllate grazie all'uso di appropriate ``\textsl{regole}'' con cui
si esprimono le operazioni da effettuare in conseguenza ai vari eventi che
\texttt{udevd} riceve dal kernel. Alla ricezione di ciascun evento
\texttt{udevd} processa le regole ed esegue le operazioni in esse indicate,
inoltre tutta l'informazione viene comunque memorizzata in un database e può
essere acceduta da altri programmi.

Le regole devono essere inserite in appositi file con l'estensione
\texttt{.rules} (altre estensioni sono ignorate), mantenuti normalmente sotto
\texttt{/etc/udev/rules.d}, che è la directory riservata agli utenti per la
configurazione delle regole; è possibile, anche se non c'è nessun motivo per
farlo, cambiare questa directory con la direttiva \texttt{udev\_rules} in
\texttt{/etc/udev/udev.conf}. Se presenti però vengono utilizzate anche le
regole predefinite di sistema poste in \texttt{/lib/udev/rules.d}, ed
eventuali regole temporanee poste in \texttt{/dev/.udev/rules.d}.

Quando \texttt{udevd} parte tutti i file delle regole vengono letti e
processati in ordine alfabetico, indipendentemente dalle directory in cui si
trovano, ma in caso di uguaglianza dei nomi hanno la precedenza i file
presenti in \texttt{/etc/udev/rules.d}. Questo significa che se ci sono regole
da eseguire per prime queste devono essere inserite in file il cui nome abbia
la precedenza, questo è il motivo per cui i file di regole di
\texttt{/etc/udev/rules.d} hanno normalmente nomi che iniziano con dei codici
numerici, così da identificare in maniera più immediata la sequenza in cui
verranno utilizzati.

La sintassi con cui si esprimono le regole è abbastanza complessa; ogni riga
del file, a parte quelle vuote ed i commenti introdotti dal solito carattere
``\texttt{\#}'', deve contenere almeno una coppia chiave/valore; è poi
possibile specificarne anche più di una con una lista separata da virgole.
Esistono due tipi di chiavi, le chiavi di confronto (dette \textit{matching
  key}) usate per selezionare gli eventi a cui applicare la regola e quelle di
assegnazione (dette \textit{assign key}) con cui si controllano le operazioni
da eseguire.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|c|l|}
    \hline
    \textbf{Operatore} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{==}& confronta l'eguaglianza di una \textit{matching key}.\\ 
    \texttt{!=}& confronto la diseguaglianza di una \textit{matching key}.\\ 
    \hline
    \texttt{=} & assegna un valore a una \textit{assign key}.\\
    \texttt{+=}& aggiunge un valore a una \textit{assign key}.\\
    \texttt{:=}& assegna definitivamente un valore a una \textit{assign key}.\\
    \hline
  \end{tabular}
  \caption{Operatori delle regole di \textit{udev}.}
  \label{tab:udev_rules_operators}
\end{table}

Ciascun tipo di chiave prevede diversi operatori con cui essa viene associata
al proprio valore nella forma di una assegnazione in cui il valore viene
espresso come stringa fra apici doppi. Gli operatori utilizzabili sono
riportati in tab.~\ref{tab:udev_rules_operators}, nella parte superiore ci
sono gli operatori di confronto, il cui uso identifica una \textit{matching
  key}, nella parte inferiore quelli di assegnazione, il cui uso identifica
una \textit{assign key}. Si tenga presente inoltre che nelle espressioni dei
valori usati con le \textit{matching key} è generalmente supportato l'uso
degli operatori del \textit{filename globbing} (``\texttt{*}'', ``\texttt{?}''
e ``\texttt{[]}''), con lo stesso significato che hanno nella shell.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Chiave} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{ACTION}   & nome dell'azione riportato dell'evento.\\ 
    \texttt{ATTR\{name\}}& valore dell'attributo \texttt{name} associato su 
                         \textit{sysfs} al dispositivo dell'evento.\\  
    \texttt{KERNEL}   & nome del dispositivo secondo il kernel, come
                        riportato nell'evento.\\ 
    \texttt{NAME} & nome dell'interfaccia di rete o del file di
                    dispositivo sotto \texttt{/dev}, usabile se assegnato in
                    una regola precedente.\\   
    \texttt{SUBSYSTEM}& nome del sottosistema riportato dall'evento.\\ 
%    \texttt{}& .\\ 
    \hline
  \end{tabular}
  \caption{Chiavi di confronto per le regole di \textit{udev}.}
  \label{tab:udev_matching_key}
\end{table}

Si tenga presente inoltre che alcune chiavi, a seconda dell'operatore che vi
si applica, possono essere usate sia per confronto o per assegnazione; un
elenco delle chiavi di confronto più significative è riportato in
tab.~\ref{tab:udev_matching_key} mentre in tab.~\ref{tab:udev_assign_key} si
sono riportate quelle di assegnazione. Per l'elenco completo ed i dettagli si
consulti la pagina di manuale di \textit{udev} con \texttt{man udev}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|l|}
    \hline
    \textbf{Chiave} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{GROUP}& gruppo proprietario del file di dispositivo.\\ 
    \texttt{MODE} & permessi del file dispositivo.\\ 
    \texttt{NAME} & nome dell'interfaccia di rete o del file di
                    dispositivo sotto \texttt{/dev}.\\  
    \texttt{OWNER}& proprietario del file di dispositivo.\\ 
    \texttt{RUN}  & programma da eseguire.\\ 
    \hline
  \end{tabular}
  \caption{Chiavi di assegnazione per le regole di \textit{udev}.}
  \label{tab:udev_assign_key}
\end{table}

Se in corrispondenza ad un evento tutte le \textit{matching key} presenti in
una riga corrispondono, verranno assegnati i valori alle \textit{assign key}
presenti nella stessa; questo, a seconda di quali chiavi si sono usate, può
comportare l'esecuzione di varie operazioni, come la creazione di un file di
dispositivo, o di un link simbolico, fino anche alla esecuzione di un
programma ad hoc.

Come esempio di un file di regole possiamo prendere in esame il seguente
contenuto del file \texttt{z60\_hdparm.rules}, installato con il pacchetto
Debian del programma \texttt{hdparm} (vedi sez.~\ref{sec:hdparm_sdparm}):
\begin{FileExample}[label=z60\_hdparm.rules]
ACTION=="add", SUBSYSTEM=="block", KERNEL=="[sh]d[a-z]", RUN+="/etc/init.d/hdparm hotplug" 
\end{FileExample}

In questo caso nel caso che il kernel riporti l'aggiunta di un dispositivo a
blocchi il cui nome corrisponda a quelle di un disco, si richiede l'aggiunta
alla lista dei programmi da eseguire del lancio dello script di avvio di
\texttt{hdparm} così che questo possa tener conto del nuovo disco.

\itindend{udev}

Per controllare il comportamento di \textit{udev} erano stati forniti
inizialmente alcuni programmi singoli (\texttt{udevinfo}
\index{comando!\texttt{udevinfo}} e \index{comando!\texttt{udevmonitor}}
\texttt{udevmonitor}) le cui funzionalità sono state in seguito raccolte in un
unico programma, \index{comando!\texttt{udevadm}} \texttt{udevadm} che
consente di operare sul sistema. Il comando richiede che si specifichi come
argomento un sotto-comando indicante il tipo di operazioni che si vogliono
effettuare, che vengono specificate ulteriormente tramite le opportune
opzioni.

In particolare con \texttt{udevadm info}, che sostituisce \texttt{udevinfo},
si possono ottenere le informazioni presenti nel database di \textit{udev}
relative ad un qualunque dispositivo riconosciuto dal kernel.  Il comando
richiede che si indichi il dispositivo di cui si richiedono le informazioni e
questo può essere fatto in due modi; il primo è tramite l'opzione \texttt{-p}
(o \texttt{-{}-path}) che consente di specificarlo tramite il
\textit{pathname} con cui esso compare sotto \texttt{/sys/device}, ma in
genere, dato che detto pathname può risultare molto complesso per via della
gerarchia dei dispositivi, si utilizza molto più spesso l'opzione \texttt{-n}
(o \texttt{-{}-name}), che prende invece il nome del dispositivo come compare
sotto \texttt{/dev}. La prima opzione però, al costo di una identificazione
più complicata, consente di ottenere le informazioni anche quando per un
qualche malfunzionamento delle regole di \textit{udev} non viene creato un
file di dispositivo sotto \texttt{/dev}.

Le richieste di informazione vengono controllate dall'opzione \texttt{-q} (o
\texttt{-{}-query}) che prende un argomento e consente di specificare le
informazioni che si richiedono, il cui possibile valore è illustrato in
tab.~\ref{tab:udevadm_info_query}, in genere si usa \texttt{path} per ottenere
il pathname del dispositivo sotto \texttt{/sys/device}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Valore} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{name}    & file di dispositivo sotto \texttt{/dev}. \\
    \texttt{symlink} & link simbolici relativi al dispositivo. \\
    \texttt{path}    & \textit{pathname} sotto \texttt{/sys}. \\
    \texttt{property}& proprietà del dispositivo. \\
    \texttt{all}     & tutte le precedenti. \\
    \hline
  \end{tabular}
  \caption{Possibili valore per l'opzione \texttt{-q} di \texttt{udevadm
      info}.}
  \label{tab:udevadm_info_query}
\end{table}

Inoltre, se si usa l'opzione \texttt{-a} (o \texttt{-{}-attribute-walk})
invece di \texttt{-q} è possibile ottenere i valori di tutti gli attributi
associati al dispositivo (e ai bus o dispositivi di cui fa parte nella
gerarchia di \textit{sysfs}), vale a dire quelli controllabili con le
\textit{matching key} di tipo \texttt{ATTR\{name\}}.

Una altro sotto-comando molto utile, specie quando si deve effettuare una
diagnosi di funzionamento di \textit{udev}, è \texttt{udevadm monitor}, (che
sostituisce \texttt{udevmonitor}) che pone sotto osservazione il sistema e
stampa sulla console i dati relativi sia agli eventi inviati dal kernel che a
quelli generati dal sistema stesso. In questo caso esistono varie opzioni che
consentono di controllare e filtrare l'output del comando, ad esempio con
\texttt{-{}-kernel} si può richiedere la stampa degli eventi del kernel, con
\texttt{-{}-udev} di quelli interni ad \textit{udev}, o usare
\texttt{-{}-subsystem-match} per chiedere (tramite la stringa che lo
identifica passata come parametro) la stampa dei soli eventi relativi ad un
sottosistema (quelli di \texttt{/sys/subsystem}). 

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{10cm}|}
    \hline
    \textbf{Sotto-comando} & \textbf{Significato} \\
    \hline
    \hline
%    \texttt{trigger}& richiede un evento dal kernel. \\
%    \texttt{settle}&  attende che la coda di eventi sia smaltita. \\
    \texttt{control}& esegue operazioni di controllo su \texttt{udevd}. \\
    \texttt{help}   & stampa l'elenco dei sotto-comandi. \\
    \texttt{info}&    ricerca informazioni nei dati di \textit{sysfs} e
                      \textit{udev}. \\
    \texttt{monitor}& si pone in ascolto degli eventi e stampa informazioni a
                      video. \\
    \texttt{test}   & simula un evento. \\
    \hline
  \end{tabular}
  \caption{Sotto-comandi del comando \texttt{udevadm}.}  
  \label{tab:udevadm_command}
\end{table}

In tab.~\ref{tab:udevadm_command} si sono riportati i principali sotto-comandi
di \texttt{udevadm}. Un elenco completo si può ottenere con \texttt{udevadm
  help}, e per le informazioni dettagliate riguardo a tutte le opzioni
disponibili per ciascuno di essi si rimanda alla pagina di manuale,
accessibile al solito con \texttt{man udevadm}.

\else
\relax
%%
%% FINE: Parte generale da non includere in systemd
%%
\fi


% LocalWords:  kernel patch Linus diff sez major version mirror addressing ls
% LocalWords:  patchlevel backporting FTP rsync tar bzip gzip xvjf xvzf root is
% LocalWords:  home generated make config don't edit ISA SBUS not transparent
% LocalWords:  UID MPENTIUM MK MELAN MCRUSOE pathname original rej reverse like
% LocalWords:  forward Makefile CDROM uname SUBLEVEL EXTRAVERSION KERNELRELEASE
% LocalWords:  package kpkg COMPILE PowerPC Intel gcc linking ko init panic NLS
% LocalWords:  filesystem crash SPINLOCK ALGORITHM language iso guest xz virt
% LocalWords:  shell oldconfig menuconfig xconfig QT gconfig GTK fig ncurses 
% LocalWords:  libncurses dev glibc maturity level options loadable module type
% LocalWords:  support checksum and features MTRR memory register symmetric Gb
% LocalWords:  processing high general setup networking ELF for binaries system
% LocalWords:  IPC technology embedded parallel port plug rpc unmask staging
% LocalWords:  configuration devices array loopback Normal device TCP prio
% LocalWords:  socket packet filtering routing networking domain sockets VoIP
% LocalWords:  dhclient Telephony ATA IDE ATAPI enhanced DMA AX abort oppish
% LocalWords:  when available SCSI controller USB fusion MPT LSI logic IEEE rm
% LocalWords:  Firewire Ethernet PPP Amateur IrDA infrared subsystem Jessie
% LocalWords:  drivers joystick human character virtual Hugepage Virtio grp
% LocalWords:  ssh PTY generic printer AGP direct rendering DRI XFree clock ext
% LocalWords:  systems reiserfs system Windows proc NFS SMB VGA text apple key
% LocalWords:  framebuffer Bluetooth debug SysRq Cryptographic IPSEC dep
% LocalWords:  library routines hash bzImage arch vmlinux zImage kb low memory
% LocalWords:  LILO PPC Mac depend modules install clean mrproper map lsof lzma
% LocalWords:  distclean overclocking bootloader vmlinuz syslog depmod lsdel ln
% LocalWords:  cp modutils kerneld kmod request modprobe sysctl insmod MODPATH
% LocalWords:  modinfo unresolved symbol tab locking fs crypto autoclean conf
% LocalWords:  rmmod scsi hostadapter Adaptec aic usb interface char NN block
% LocalWords:  dmasound pmac service keywest eth sungem airport off null option
% LocalWords:  add path misc toplevel kernelversion keep pre remove to load at
% LocalWords:  should contain the names of that loaded one line comments UEFI
% LocalWords:  begin with everything after them ignored ide adapter isa eeprom
% LocalWords:  radeon filename description author license additional rights prm
% LocalWords:  parm string opts lsmod Size Used tainted unused agpgart yenta
% LocalWords:  soundcore pcmcia orinoco hermes ohci usbcore hid head sector CHS
% LocalWords:  cylinder INT Large HOWTO Linear LBA fdisk this journaled SAS fix
% LocalWords:  SPARC Alpha sull'MBR qtparted gparted parted cfdisk number There
% LocalWords:  cylinders nothing wrong but larger than could certain setups old
% LocalWords:  problems runs versions booting partitioning from other OSs DOS
% LocalWords:  OS action toggle bootable bsd disklabel dos delete list Secure
% LocalWords:  compatibility partition known types print menu new empty table
% LocalWords:  quit without saving changes Sun change partition's entry units
% LocalWords:  verify write exit functionality experts only heads sectors bytes
% LocalWords:  blocks swap fd var usr opt LVM mkreiserfs hashing msdos mkfs FAT
% LocalWords:  allocation name vfat inode fdformat Reiser JFS XFS mke WIP Dec
% LocalWords:  label size log Fragment inodes blocks First groups group backups
% LocalWords:  fragments Superblock stored Writing tables done superblocks will
% LocalWords:  accounting information automatically checked every mounts days
% LocalWords:  whichever comes first tune override superblock dumpe news index
% LocalWords:  largefile filetype has journal badblocks fsck remount Journaling
% LocalWords:  ro universally unique identifier UUID anarres Last mounted cb ob
% LocalWords:  magic revision dynamic needs recovery mount Errors behavior Fri
% LocalWords:  count reserved Jan interval months Next Jun uid gid orphan oB HP
% LocalWords:  image debugfs black ChecK point ReiserFS yes MMU pri journaling
% LocalWords:  superblocco Unit segmentation fault SIGSEGV sull' mkswap swapon
% LocalWords:  swapoff MBR parameters txt Documentation vga ask mem UX true ARM
% LocalWords:  initrd command Sparc MILO OpenFirmware dd if rdev vidmode SYS It
% LocalWords:  ramsize syslinux LDLINUX CFG LInux LOader nell'MBR lilo large it
% LocalWords:  disks lba specifies where installs its can either raw which as
% LocalWords:  overwrite current specified location deciseconds seconds wait hd
% LocalWords:  before delay message apply all installed images here see append
% LocalWords:  linux read linuxold you have another machine uncomment following
% LocalWords:  lines changing your restricted l'MBR shift linear mandatory GRUB
% LocalWords:  chroot unified HURD FSF microkernel cat hdN grub lst num starts
% LocalWords:  numbering used specify instead saved sec LSB undel rmdir unlink
% LocalWords:  normally defined pretty colours cyan blue white passwd section
% LocalWords:  disable interactive control entries protected topsecret rc stat
% LocalWords:  title savedefault update SysV sbin Slackware runlevel RedHat run
% LocalWords:  process respawn initdefault ctrlaltdel SIGINT ctrl shutdown upon
% LocalWords:  powerwait powerokwait powerfailnow inittab initialization except
% LocalWords:  emergency executes scripts What pressed now power fails returns
% LocalWords:  invocations runlevels field MUST same last characters tty getty
% LocalWords:  telinit FHS restart reload rcN kill chkconfig industry WORKS Cnt
% LocalWords:  architecture peripheral component interconnect interrupt intel
% LocalWords:  XT PIC timer keyboard cascade rtc uhci btaudio bttv PS NMI LOC
% LocalWords:  ERR MIS dma pic reg bf df ff fpu corporation jumper Plug'n Pray
% LocalWords:  l'autoconfigurazione isolation CSN irq ioport PnP Pnp enabled VT
% LocalWords:  ESCD isapnp pnp pnpdump Connect MHz Gbit l'AGP host lspci Inc NV
% LocalWords:  technologies rev storage Realtek Semiconductor RTL compatible IC
% LocalWords:  nVidia GeForce Rhine International Ltd Unknown Flags devsel APIC
% LocalWords:  latency ports prefetchable capabilities vendorID deviceID setpci
% LocalWords:  vendor min gnt lat pin queing wide narrow channel LUN Requires
% LocalWords:  lun emulation AVV Access found sda hdwr MB assuming cache sr hot
% LocalWords:  through attached MATSHITA PIONEER SEAGATE echo info cs FW rescan
% LocalWords:  scsitools scsiinfo sh l'USB winmodem router switch setserial spd
% LocalWords:  UART uart autoconfig hi bps vhi shi warp normal cust divisor hub
% LocalWords:  universal asynchronous receiver transmitter downstream upstream
% LocalWords:  transfers bulk isochronous mA l'overhead Compaq EHCI iSCSI files
% LocalWords:  holland ServerWorks ehci hcd hotplug usbmgr usbdevfs defaults ms
% LocalWords:  SerialNumber manufacturer Cypress product usbutils lsusb Corp fe
% LocalWords:  mantainer MWINCHIPC MWINCHIP MCYRIXIII MVIAC RWSEM XCHGADD LOCK
% LocalWords:  Gareth Hughes Keith Whitwell others drm semigrafica ALi PMU ACPI
% LocalWords:  AHA xxxxx prog davis CSB INVLPG CMPXCHG Ver Prot Lev speed ESP
% LocalWords:  nfs smbfs call adfs Acorn filing RiscOS cramfs compressed second
% LocalWords:  hfs hierarchy MacOS hpfs jfs IBM minix ntfs NT qnx QNX ufs EXE
% LocalWords:  romfs SunOS FreeBSD NetBSD OpenBSD vxfs Veritas VxFS UnixWare rw
% LocalWords:  Solaris xfs IRIX SGI befs BeOS dall'MSDOS shm sysfs devpts Sarge
% LocalWords:  nodev rootfs bdev sockfs tmpfs pipefs ramfs usbfs users async sw
% LocalWords:  atime suid exec nouser noatime noauto noexec nosuid sgid sync Mb
% LocalWords:  dirsync geomorphix encryption keybits mapper fstab static dump
% LocalWords:  pass errors cdrom umount lazy sfdisk hda save page git vanilla
% LocalWords:  tool micro local autoexec bat parts integrated electronics cable
% LocalWords:  advanced attachment digital Wikipedia select sd libATA Alan Cox
% LocalWords:  dell'UUID address losetup SL relatime client mutt udev parity hh
% LocalWords:  Ubuntu plugdev du kilobyte dell'MBR srv tmp l'UUID resize Etch
% LocalWords:  ramdisk versioning layer scheduler preemption l'ACPI APM track
% LocalWords:  executable formats wireless bluetooth dall' WP small lp simple
% LocalWords:  extraversion development configure initramfs paging MTD always
% LocalWords:  anonymous filesystems SELinux virtualization parellel prod ALSA
% LocalWords:  experimental firewire all'USB Macintosh monitoring webcam grand
% LocalWords:  graphics rpm deb pkg cpio mkinitrd CentOS mkinitramfs tools SATA
% LocalWords:  yaird sys NumeroDispositivo NumeroFunzione dmesg security force
% LocalWords:  modversion vermagic blacklist depends mod unload modversions int
% LocalWords:  bitmapped enable multicast filter limit filtered addresses tun
% LocalWords:  forced unloading usbserial binfmt parport ppdev autofs snd ATTR
% LocalWords:  battery pcm oss watchdog series Jeff Garzik srcversion pci SMP
% LocalWords:  bootstrap openfirmware basic EFI MacIntosh find chainloader
% LocalWords:  makeactive upstart bootwait sysinit atd PID SIGKILL PREVLEVEL
% LocalWords:  halt reboot poweroff programmable controllers noapic devfs vol
% LocalWords:  findfs ellington USAGE ENC SAFE RealTek udevd Lenny initial err
% LocalWords:  priority numerical equivalent runtime daemons changed udevadm
% LocalWords:  value rules matching assign wall procbususb hdparm gpart blkid
% LocalWords:  strictatime third fourth hfsplus udf format express globbing utf
% LocalWords:  OWNER udevinfo udevmonitor query symlink property attribute walk
% LocalWords:  reiserfsck fixable rebuild tree reiserfstune repair admin growfs
% LocalWords:  automounter mkisofs fork genisoimage LDAP amd daemon thread glob
% LocalWords:  automount LOGGING fstype hostname smbclient comun Ridge Joliet
% LocalWords:  Torito USBHDD USBZIP PXE eXecution environment TFTP DHCP quiet
% LocalWords:  rootdelay nosmp noacpi maxcpus noapci ISOLINUX PXELINUX ldlinux
% LocalWords:  safe stupid cfg btrfs mkdosfs uuid NIS frequency AppArmor  was
% LocalWords:  DRBD multipath lib SuSE Squeeze during installation width extN
% LocalWords:  extent sublevel schedulers coreboot scripting mkconfig CMDLINE
% LocalWords:  uninit systemd event driven startup job DNS factory initctl
% LocalWords:  lsscsi minicom emit activation unit systemctl GPT Leonard GUID
% LocalWords:  Poettering paravirtualized distributed replicated secureboot
% LocalWords:  MultiMediaCard menuentry custom prefix deprecated strongly efi
% LocalWords:  recommended total logical physical optimal primary header gpt
% LocalWords:  globally secondary gdisk scan protective valid using holds emerg
% LocalWords:  usable aligned boundaries cgdisk sgdisk snapshot ascii naming
% LocalWords:  realtime superdeamon logdev Tomoyo loader dual rEFInd labl
% LocalWords:  terabyte gigabyte memtest OpenRC cupsd journald keyfile spawn
% LocalWords:  rescue confirm require wants WantedBy metadump Also metadati
% LocalWords:  RequiredBy conflicts template mask descriptor Infrastructure
% LocalWords:  extensible program application condition wanted required less
% LocalWords:  journalctl since tail facility fields partitions stripe dbus
% LocalWords:  allocating enterprise namespace SystemMaxUse AllowIsolate idle
%  LocalWords:  DefaultEnvironment graphical ExecStart forking PIDFile notify
%  LocalWords:  oneshot ExecReload ExecStop KillMode success failure abnormal
%  LocalWords:  EnvironmentFile UMask umask mixed KillSignal cron COMM Mbit
%  LocalWords:  ForwardToSyslog specificatori specificatore superspeed plugin
%  LocalWords:  launchd LogLevel LogTarget requires libssl nconfig Regular

%%% Local Variables: 
%%% TeX-master: "corso"
%%% mode: latex
%%% End:
