\begin{figure}[htb]
\centering
- \includegraphics[width=10cm]{img/struct_sys}
+ \includegraphics[width=11cm]{img/struct_sys}
% \begin{tikzpicture}
% \filldraw[fill=black!20] (0,0) rectangle (7.5,1);
% \draw (3.75,0.5) node {\textsl{System Call Interface}};
ad una funzione con lo stesso nome definita all'interno della libreria
fondamentale del sistema, quella che viene chiamata \textsl{Libreria Standard
del C} (\textit{C Standard Library}) in ragione del fatto che il primo
-kernel Unix e tutti i programmi eseguiti su di esso vennero scritti in C,
-usando le librerie di questo linguaggio. In seguito faremo riferimento alle
+kernel Unix e tutti i programmi eseguiti su di esso vennero scritti in questo
+linguaggio, usando le sue librerie. In seguito faremo riferimento alle
funzioni di questa libreria che si interfacciano alle \textit{system call}
come ``\textsl{funzioni di sistema}''.
-Questa libreria infatti, oltre alle interfacce delle \textit{system call},
+Questa libreria infatti, oltre alle chiamate alle \textit{system call},
contiene anche tutta una serie di ulteriori funzioni di utilità che vengono
comunemente usate nella programmazione e sono definite nei vari standard che
documentano le interfacce di programmazione di un sistema unix-like. Questo
concetto è importante da tener presente perché programmare in Linux significa
-anche essere in grado di usare le funzioni fornite dalla \textsl{Libreria
- Standard del C}, in quanto né il kernel, né il linguaggio C implementano
-direttamente operazioni ordinarie come l'allocazione dinamica della memoria,
-l'input/output bufferizzato sui file o la manipolazione delle stringhe, la
-matematica in virgola mobile, che sono comunemente usate da qualunque
-programma.
+anche essere in grado di usare le funzioni fornite dalla libreria Standard del
+C, in quanto né il kernel né il linguaggio C implementano direttamente
+operazioni ordinarie come l'allocazione dinamica della memoria, l'input/output
+bufferizzato sui file, la manipolazione delle stringhe, la matematica in
+virgola mobile, che sono comunemente usate da qualunque programma.
Tutto ciò mette nuovamente in evidenza il fatto che nella stragrande
maggioranza dei casi si dovrebbe usare il nome GNU/Linux in quanto una parte
essenziale del sistema, senza la quale niente funzionerebbe, è appunto la
\textit{GNU Standard C Library} (a cui faremo da qui in avanti riferimento
-come \acr{glibc}), ovvero la Libreria Standard del C realizzata dalla Free
-Software Foundation, nella quale sono state implementate tutte le funzioni
-essenziali definite negli standard POSIX e ANSI C (e molte altre), che vengono
-utilizzate da qualunque programma.
+come \acr{glibc}), la libreria standard del C realizzata dalla Free Software
+Foundation nella quale sono state implementate tutte le funzioni essenziali
+definite negli standard POSIX e ANSI C (e molte altre), che vengono utilizzate
+da qualunque programma.
Si tenga comunque presente che questo non è sempre vero, dato che esistono
-implementazioni alternative della Libreria Standard del C, come la
+implementazioni alternative della libreria standard del C, come la
\textit{libc5} o la \textit{uClib}, che non derivano dal progetto GNU. La
\textit{libc5}, che era usata con le prime versioni del kernel Linux, è oggi
ormai completamente soppiantata dalla \acr{glibc}. La \textit{uClib} invece,
e soprattutto per la possibilità di togliere le parti non necessarie. Pertanto
costituisce un valido rimpiazzo della \acr{glibc} in tutti quei sistemi
specializzati che richiedono una minima occupazione di memoria. Infine per lo
-sviluppo del sistema Android è stata realizzata da Google un'altra Libreria
-Standard del C, utilizzata principalmente per evitare l'uso della \acr{glibc}.
+sviluppo del sistema Android è stata realizzata da Google un'altra libreria
+standard del C, utilizzata principalmente per evitare l'uso della \acr{glibc}.
-Tradizionalmente le funzioni specifiche della Libreria Standard del C sono
+Tradizionalmente le funzioni specifiche della libreria standard del C sono
riportate nella terza sezione del \textsl{Manuale di Programmazione di Unix}
(cioè accessibili con il comando \cmd{man 3 <nome>}) e come accennato non sono
direttamente associate ad una \textit{system call} anche se, ad esempio per la
estensioni.
Il concetto base è quello di utente (\textit{user}) del sistema, le cui
-capacità rispetto a quello che può fare sono sottoposte a ben precisi limiti.
-Sono così previsti una serie di meccanismi per identificare i singoli utenti
-ed una serie di permessi e protezioni per impedire che utenti diversi possano
-danneggiarsi a vicenda o danneggiare il sistema. Questi meccanismi sono
-realizzati dal kernel stesso ed attengono alle operazioni più varie, e
-torneremo su di essi in dettaglio più avanti.
+capacità sono sottoposte a limiti precisi. Sono così previsti una serie di
+meccanismi per identificare i singoli utenti ed una serie di permessi e
+protezioni per impedire che utenti diversi possano danneggiarsi a vicenda o
+danneggiare il sistema. Questi meccanismi sono realizzati dal kernel stesso ed
+attengono alle operazioni più varie, e torneremo su di essi in dettaglio più
+avanti.
Normalmente l'utente è identificato da un nome (il cosiddetto
\textit{username}), che ad esempio è quello che viene richiesto all'ingresso
l'identità dell'utente, in genere attraverso la richiesta di una parola
d'ordine (la \textit{password}), anche se sono possibili meccanismi
diversi.\footnote{ad esempio usando la libreria PAM (\textit{Pluggable
- Autentication Methods}) è possibile astrarre completamente dai meccanismi
- di autenticazione e sostituire ad esempio l'uso delle password con
- meccanismi di identificazione biometrica, per un approfondimento
- dell'argomento si rimanda alla sez.~4.3 di \cite{AGL}.} Eseguita la
-procedura di riconoscimento in genere il sistema manda in esecuzione un
-programma di interfaccia (che può essere la \textit{shell} su terminale o
-un'interfaccia grafica) che mette a disposizione dell'utente un meccanismo con
-cui questo può impartire comandi o eseguire altri programmi.
+ Autentication Methods}) è possibile generalizzare i meccanismi di
+ autenticazione e sostituire ad esempio l'uso delle password con meccanismi
+ di identificazione biometrica; per un approfondimento dell'argomento si
+ rimanda alla sez.~4.3.7 di \cite{AGL}.} Eseguita la procedura di
+riconoscimento in genere il sistema manda in esecuzione un programma di
+interfaccia (che può essere la \textit{shell} su terminale o un'interfaccia
+grafica) che mette a disposizione dell'utente un meccanismo con cui questo può
+impartire comandi o eseguire altri programmi.
Ogni utente appartiene anche ad almeno un gruppo (il cosiddetto
\textit{default group}), ma può essere associato ad altri gruppi (i
del tipo: ``\code{if (uid) \{ \textellipsis\ \}}''.}
-%Rimosse
-% \section{L'architettura della gestione dei file}
-% \label{sec:file_arch_func}
-
\section{L'architettura di file e directory}
\label{sec:intro_file_dir}
\itindbeg{Virtual~File~System~(VFS)}
In Linux il concetto di \textit{everything is a file} è stato implementato
-attraverso il \textit{Virtual File System} (che da qui in poi abbrevieremo in
-VFS) che è uno strato intermedio che il kernel usa per accedere ai più
-svariati filesystem mantenendo la stessa interfaccia per i programmi in
-\textit{user space}.
-
-Il VFS fornisce cioè quel livello di astrazione che permette di collegare le
-operazioni interne del kernel per la manipolazione sui file con le
-\textit{system call} relative alle operazioni di I/O, e gestisce poi
+attraverso il cosiddetto \textit{Virtual File System} (da qui in avanti VFS)
+che è uno strato intermedio che il kernel usa per accedere ai più svariati
+filesystem mantenendo la stessa interfaccia per i programmi in \textit{user
+ space}. Il VFS fornisce quel livello di astrazione che permette di
+collegare le operazioni interne del kernel per la manipolazione sui file con
+le \textit{system call} relative alle operazioni di I/O, e gestisce poi
l'organizzazione di dette operazioni nei vari modi in cui i diversi filesystem
le effettuano, permettendo la coesistenza di filesystem differenti all'interno
dello stesso albero delle directory. Approfondiremo il funzionamento di
In sostanza quello che accade è che quando un processo esegue una
\textit{system call} che opera su un file, il kernel chiama sempre una
funzione implementata nel VFS. La funzione eseguirà le manipolazioni sulle
-strutture generiche e utilizzerà poi la chiamata alle opportune funzioni del
-filesystem specifico a cui si fa riferimento. Saranno queste a chiamare le
-funzioni di più basso livello che eseguono le operazioni di I/O sul
-dispositivo fisico, secondo lo schema riportato in
+strutture generiche e utilizzerà poi delle chiamate alle opportune funzioni
+del filesystem specifico a cui si fa riferimento. Saranno queste infine a
+chiamare le funzioni di più basso livello che eseguono le operazioni di I/O
+sul dispositivo fisico, secondo lo schema riportato in
fig.~\ref{fig:file_VFS_scheme}.
\begin{figure}[!htb]
\centering
- \includegraphics[width=7cm]{img/vfs}
+ \includegraphics[width=8cm]{img/vfs}
\caption{Schema delle operazioni del VFS.}
\label{fig:file_VFS_scheme}
\end{figure}
insieme al lancio di \cmd{init},\footnote{l'operazione è ovviamente anche
preliminare al lancio di \cmd{init}, dato il kernel deve poter accedere al
file che contiene detto programma.} l'unica operazione che viene effettuata
-direttamente dal kernel in fase di avvio quando, completata la fase di
-inizializzazione, esso riceve dal bootloader l'indicazione di quale
-dispositivo contiene il filesystem da usare come punto di partenza e questo
-viene posto alla radice dell'albero dei file.
+direttamente dal kernel in fase di avvio. Il kernel infatti, completata la
+fase di inizializzazione, utilizza l'indicazione passatagli dal
+\textit{bootloader} su quale sia il dispositivo che contiene il filesystem da
+usare come punto di partenza, lo monta come radice dell'albero dei file.
Tutti gli ulteriori filesystem che possono essere disponibili su altri
-dispositivi dovranno a loro volta essere inseriti nell'albero, montandoli su
+dispositivi dovranno a loro volta essere inseriti nell'albero, montandoli in
altrettante directory del filesystem radice, su quelli che vengono chiamati
-\textit{mount point}. Questo comunque avverrà sempre in un secondo tempo, in
-genere a cura dei programmi eseguiti nella procedura di inizializzazione del
-sistema, grazie alle funzioni che tratteremo in
-sez.~\ref{sec:filesystem_mounting}.
+\textit{mount point}. Questo comunque avverrà sempre in un secondo tempo, a
+cura dei programmi eseguiti nella procedura di inizializzazione del sistema,
+grazie alle funzioni che tratteremo in sez.~\ref{sec:filesystem_mounting}.
\subsection{La risoluzione del nome di file e directory}
\itindbeg{pathname}
-Come illustrato sez.~\ref{sec:file_arch_overview} una delle caratteristiche
-distintive di un sistema unix-like è quella di avere un unico albero dei
-file. Un file deve essere identificato dall'utente usando quello che viene
-chiamato il suo \textit{pathname},\footnote{il manuale della \acr{glibc}
- depreca questa nomenclatura, che genererebbe confusione poiché \textit{path}
- indica anche un insieme di directory su cui effettuare una ricerca (come
- quello in cui la shell cerca i comandi). Al suo posto viene proposto l'uso
- di \textit{filename} e di componente per il nome del file all'interno della
- directory. Non seguiremo questa scelta dato che l'uso della parola
- \textit{pathname} è ormai così comune che mantenerne l'uso è senz'altro più
- chiaro dell'alternativa proposta.} vale a dire tramite il
+Come appena illustrato sez.~\ref{sec:file_arch_overview} una delle
+caratteristiche distintive di un sistema unix-like è quella di avere un unico
+albero dei file. Un file deve essere identificato dall'utente usando quello
+che viene chiamato il suo \textit{pathname},\footnote{il manuale della
+ \acr{glibc} depreca questa nomenclatura, che genererebbe confusione poiché
+ \textit{path} indica anche un insieme di directory su cui effettuare una
+ ricerca (come quello in cui la shell cerca i comandi). Al suo posto viene
+ proposto l'uso di \textit{filename} e di componente per il nome del file
+ all'interno della directory. Non seguiremo questa scelta dato che l'uso
+ della parola \textit{pathname} è ormai così comune che mantenerne l'uso è
+ senz'altro più chiaro dell'alternativa proposta.} vale a dire tramite il
``\textsl{percorso}'' (nome che talvolta viene usato come traduzione di
\textit{pathname}) che si deve fare per accedere al file a partire da una
certa ``\textit{directory}''.
dei file è quella di usare il carattere ``\texttt{/}'' come separatore fra i
nomi che indicano le directory che lo compongono. Dato che la directory radice
sta in cima all'albero, essa viene indicata semplicemente con il
-\textit{pathname} \file{/}.
+\textit{pathname} ``\file{/}''.
\itindbeg{pathname~resolution}
diversi fra loro. Oltre ai normali file di dati abbiamo già accennato ad altri
due di questi oggetti, i file di dispositivo e le directory, ma ne esistono
altri. In genere quando si parla di tipo di file su Linux si fa riferimento a
-questi, di cui si riportato l'elenco completo in
+questi diversi tipi, di cui si riportato l'elenco completo in
tab.~\ref{tab:file_file_types}.
\begin{table}[htb]
\textit{block device}& \textsl{dispositivo a blocchi}
& Un file \textsl{speciale} che identifica una
periferica ad accesso a blocchi.\\
- \textit{fifo} & ``\textsl{coda}''
+ \textit{fifo} & ``\textsl{coda}''
& Un file \textsl{speciale} che identifica una
linea di comunicazione unidirezionale (vedi
sez.~\ref{sec:ipc_named_pipe}).\\
- \textit{socket} & ``\textsl{presa}''
+ \textit{socket} & ``\textsl{presa}''
& Un file \textsl{speciale} che identifica una
linea di comunicazione bidirezionale (vedi
cap.~\ref{cha:socket_intro}).\\
\end{table}
Si tenga ben presente che questa classificazione non ha nulla a che fare con
-una classificazione dei file in base al tipo loro del contenuto, dato che in
-tal caso si avrebbe a che fare sempre e solo con dei file di dati. E non ha
-niente a che fare neanche con le eventuali diverse modalità con cui si
-potrebbe accedere al contenuto dei file di dati. La classificazione di
+una classificazione dei file in base al loro contenuto, dato che in tal caso
+si avrebbe a che fare sempre e solo con dei file di dati. E non ha niente a
+che fare neanche con le eventuali diverse modalità con cui si possa accedere
+al contenuto dei file di dati. La classificazione di
tab.~\ref{tab:file_file_types} riguarda il tipo di oggetti gestiti dal
\textit{Virtual File System}, ed è da notare la presenza dei cosiddetti file
``\textsl{speciali}''.
proprio quei \textsl{file di dispositivo} che costituiscono una interfaccia
diretta per leggere e scrivere sui dispositivi fisici. Anche se finora li
abbiamo chiamati genericamente così, essi sono tradizionalmente suddivisi in
-due grandi categorie, \textsl{a blocchi} e \textsl{a caratteri} a seconda
+due grandi categorie, \textsl{a blocchi} e \textsl{a caratteri}, a seconda
delle modalità in cui il dispositivo sottostante effettua le operazioni di
I/O.
dell'I/O in blocchi di dimensione fissa avviene solo all'interno del kernel,
ed è completamente trasparente all'utente; inoltre talvolta si parla di
\textsl{accesso diretto} riferendosi alla capacità, che non ha niente a che
- fare con tutto ciò, di effettuare, attraverso degli appositi file di
- dispositivo, operazioni di I/O direttamente sui dischi senza passare
+ fare con tutto ciò, di effettuare attraverso degli appositi file di
+ dispositivo delle operazioni di I/O direttamente sui dischi senza passare
attraverso un filesystem, il cosiddetto \textit{raw access}, introdotto coi
kernel della serie 2.4.x ma ormai in sostanziale disuso.}
questo tipo avviene sempre in \textit{user-space}. Gli unici file di cui il
kernel deve essere in grado di capire il contenuto sono i binari dei
programmi, per i quali sono supportati solo alcuni formati, anche se oggi
-viene usato quasi esclusivamente l'ELF.\footnote{il nome è l'acronimo di
- \textit{Executable and Linkable Format}, un formato per eseguibili binari
- molto flessibile ed estendibile definito nel 1995 dal \textit{Tool Interface
- Standard} che per le sue caratteristiche di non essere legato a nessun
- tipo di processore o architettura è stato adottato da molti sistemi
- unix-like e non solo.}
+viene usato quasi esclusivamente
+\itindex{Executable~and~Linkable~Format~(ELF)} l'ELF.\footnote{il nome è
+ l'acronimo di \textit{Executable and Linkable Format}, un formato per
+ eseguibili binari molto flessibile ed estendibile definito nel 1995 dal
+ \textit{Tool Interface Standard} che per le sue caratteristiche di non
+ essere legato a nessun tipo di processore o architettura è stato adottato da
+ molti sistemi unix-like e non solo.}
\itindbeg{magic~number}
Nonostante l'assenza di supporto da parte del kernel per la classificazione
del contenuto dei file di dati, molti programmi adottano comunque delle
convenzioni per i nomi dei file, ad esempio il codice C normalmente si mette
-in file con l'estensione \file{.c}. Inoltre una tecnica molto usata per
+in file con l'estensione ``\file{.c}''. Inoltre una tecnica molto usata per
classificare i contenuti da parte dei programmi è quella di utilizzare i primi
byte del file per memorizzare un ``\textit{magic number}'' che ne classifichi
il contenuto. Il concetto è quello di un numero intero, solitamente fra 2 e 10
successo, non esiste, per cui facendo riferimento agli \textit{stream}
useremo il significato adottato dal manuale delle \acr{glibc}.} Essa
fornisce funzioni più evolute e un accesso bufferizzato, controllato dalla
-implementazione fatta nella \acr{glibc}. Questa è l'interfaccia standard
-specificata dall'ANSI C e perciò si trova anche su tutti i sistemi non
-Unix. Gli \textit{stream} sono oggetti complessi e sono rappresentati da
-puntatori ad un opportuna struttura definita dalle librerie del C, ad essi si
-accede sempre in maniera indiretta utilizzando il tipo \code{FILE *}.
-L'interfaccia è definita nell'\textit{header file} \headfile{stdio.h} e la
-tratteremo in dettaglio in sez.~\ref{sec:files_std_interface}.
+implementazione fatta nella \acr{glibc}. Questa è l'interfaccia specificata
+dallo standard ANSI C e perciò si trova anche su tutti i sistemi non Unix. Gli
+\textit{stream} sono oggetti complessi e sono rappresentati da puntatori ad un
+opportuna struttura definita dalle librerie del C, a cui si accede sempre in
+maniera indiretta utilizzando il tipo \code{FILE *}; l'interfaccia è definita
+nell'\textit{header file} \headfile{stdio.h} e la tratteremo in dettaglio in
+sez.~\ref{sec:files_std_interface}.
Entrambe le interfacce possono essere usate per l'accesso ai file come agli
altri oggetti del VFS, ma per poter accedere alle operazioni di controllo
interfacce di programmazione e le altre caratteristiche di un sistema
unix-like (alcuni standardizzano pure i comandi base del sistema e la shell)
ed in particolare ci concentreremo sul come ed in che modo essi sono
-supportati sia per quanto riguarda il kernel che la Libreria Standard del C,
+supportati sia per quanto riguarda il kernel che la libreria standard del C,
con una particolare attenzione alla \acr{glibc}.
\subsection{Lo standard ANSI C}
\label{sec:intro_ansiC}
+\itindbeg{ANSI~C}
Lo standard ANSI C è stato definito nel 1989 dall'\textit{American National
Standard Institute} come prima standardizzazione del linguaggio C e per
questo si fa riferimento ad esso anche come C89. L'anno successivo è stato
vari \textit{header file} soltanto le funzionalità previste dallo standard
ANSI C e a non usare le varie estensioni al linguaggio e al preprocessore da
esso supportate.
+\itindend{ANSI~C}
\subsection{I tipi di dati primitivi}
Unix System V, e si fa rifermento a questa implementazione con la sigla SysV o
SV.
-Negli anni successivi l'AT\&T proseguì lo sviluppo rilasciando varie versioni
-con aggiunte e integrazioni, ed in particolare la \textit{release 2} nel 1985,
-a cui si fa riferimento con SVr2 e la \textit{release 3} nel 1986 (denominata
-SVr3). Le interfacce di programmazione di queste due versioni vennero
-descritte formalmente in due documenti denominati \textit{System V Interface
- Definition} (o SVID), pertanto nel 1995 venne rilasciata la specifica SVID 1
-e nel 1986 la specifica SVID 2.
+Negli anni successivi l'AT\&T proseguì lo sviluppo del sistema rilasciando
+varie versioni con aggiunte e integrazioni, ed in particolare la
+\textit{release 2} nel 1985, a cui si fa riferimento con il nome SVr2 e la
+\textit{release 3} nel 1986 (denominata SVr3). Le interfacce di programmazione
+di queste due versioni vennero descritte formalmente in due documenti
+denominati \itindex{System~V~Interface~Definition~(SVID)} \textit{System V
+ Interface Definition} (o SVID), pertanto nel 1985 venne rilasciata la
+specifica SVID 1 e nel 1986 la specifica SVID 2.
Nel 1989 un accordo fra vari venditori (AT\&T, Sun, HP, ed altri) portò ad una
versione di System V che provvedeva un'unificazione delle interfacce
successivo la divisione della AT\&T (già a suo tempo rinominata in Unix System
Laboratories) venne acquistata dalla Novell, che poi trasferì il marchio Unix
al consorzio X/Open. L'ultima versione di System V fu la SVr4.2MP rilasciata
-nel Dicembre 93. Infine nel 1995 è stata rilasciata da SCO, che aveva
+nel dicembre 1993. Infine nel 1995 è stata rilasciata da SCO, che aveva
acquisito alcuni diritti sul codice di System V, una ulteriore versione delle
\textit{System V Interface Description}, che va sotto la denominazione di SVID
4.
Si tenga presente inoltre che nuove specifiche e proposte di standardizzazione
si aggiungono continuamente, mentre le versioni precedenti vengono riviste;
talvolta poi i riferimenti cambiano nome, per cui anche solo seguire le
-denominazioni usate diventa particolarmente faticoso; una pagina dove si
-possono recuperare varie (e di norma piuttosto intricate) informazioni è
-\url{http://www.pasc.org/standing/sd11.html}.
+denominazioni usate diventa particolarmente faticoso.
\begin{table}[htb]
\footnotesize
interfacce, la obsolescenza di altre, la trasformazione da opzionali a
richieste di alcune specifiche di base, oltre alle solite precisazioni ed
aggiornamenti. Anche in questo caso è prevista la suddivisione in una
-conformità di base, e delle interfacce aggiuntive.
+conformità di base, e delle interfacce aggiuntive. Una ulteriore revisione è
+stata pubblicata nel 2017 come POSIX.1-2017.
Le procedure di aggiornamento dello standard POSIX prevedono comunque un
percorso continuo, che prevede la possibilità di introduzione di nuove
interfacce e la definizione di precisazioni ed aggiornamenti, per questo in
futuro verranno rilasciate nuove versioni. Alla stesura di queste note
-l'ultima revisione approvata resta POSIX.1-2008, uno stato della situazione
+l'ultima revisione approvata resta POSIX.1-2017, uno stato della situazione
corrente del supporto degli standard è allegato alla documentazione della
\acr{glibc} e si può ottenere con il comando \texttt{man standards}.
Unix, che venne presa come riferimento da vari produttori. Questo standard,
detto anche XPG3 dal nome della suddetta guida, è sempre basato sullo standard
POSIX.1, ma prevede una serie di funzionalità aggiuntive fra cui le specifiche
-delle API\footnote{le \textit{Application Programmable Interface}, in sostanze
- le interfacce di programmazione.} per l'interfaccia grafica (X11).
+delle API (sigla che sta per \textit{Application Programmable Interface}, in
+italiano interfaccia di programmazione) per l'interfaccia grafica (X11).
Nel 1992 lo standard venne rivisto con una nuova versione della guida, la
Issue 4, da cui la sigla XPG4, che aggiungeva l'interfaccia XTI (\textit{X
\label{sec:intro_gcc_glibc_std}
In Linux, se si usa la \acr{glibc}, la conformità agli standard appena
-descritti può essere richiesta sia attraverso l'uso di opportune opzioni del
-compilatore (il \texttt{gcc}) che definendo delle specifiche costanti prima
-dell'inclusione dei file di intestazione (gli \textit{header file}, vedi
-sez.~\ref{sec:proc_syscall}) che definiscono le funzioni di libreria.
+descritti può essere richiesta sia attraverso l'uso di alcune opzioni del
+compilatore (il \texttt{gcc}) che con la definizione di opportune costanti
+prima dell'inclusione dei file di intestazione (gli \textit{header file}, vedi
+sez.~\ref{sec:proc_syscall}) in cui le varie funzioni di libreria vengono
+definite.
Ad esempio se si vuole che i programmi seguano una stretta attinenza allo
standard ANSI C si può usare l'opzione \texttt{-ansi} del compilatore, e non
per richiedere la conformità ad uno standard, nella forma \texttt{-std=nome},
dove \texttt{nome} può essere \texttt{c89} per indicare lo standard ANSI C
(vedi sez.~\ref{sec:intro_ansiC}) o \texttt{c99} per indicare la conformità
-allo standard C99.\footnote{che non è al momento completa, esistono anche le
- possibilità di usare i valori \texttt{gnu89}, l'attuale default, che indica
- l'uso delle estensioni GNU al C89, riprese poi dal C99, o \texttt{gnu89} che
- indica il dialetto GNU del C99, che diventerà il default quando la
- conformità a quest'ultimo sarà completa.}
+allo standard C99 o \texttt{c11} per indicare la conformità allo standard C11
+(revisione del 2011).\footnote{esistono anche le possibilità di usare i valori
+ \texttt{gnu89}, che indica l'uso delle estensioni GNU al C89, riprese poi
+ dal C99, \texttt{gnu99} che indica il dialetto GNU del C99, o \texttt{gnu11}
+ che indica le estensioni GNU al C11, lo standard adottato di default dipende
+ dalla versione del \texttt{gcc}, ed all'agosto 2018 con la versione 8.2 è
+ \texttt{gnu11}.}
Per attivare le varie opzioni di controllo di aderenza agli standard è poi
possibile definire delle macro di preprocessore che controllano le
\item[\macrod{\_DEFAULT\_SOURCE}] questa macro abilita le definizioni
considerate il \textit{default}, comprese quelle richieste dallo standard
- POSIX.1-2008, ed è sostanzialente equivalente all'insieme di
+ POSIX.1-2008, ed è sostanzialmente equivalente all'insieme di
\macro{\_SVID\_SOURCE}, \macro{\_BSD\_SOURCE} e
\macro{\_POSIX\_C\_SOURCE}. Essendo predefinita non è necessario usarla a
meno di non aver richiesto delle definizioni più restrittive sia con altre
le estensioni delle funzioni di creazione, accesso e modifica di file e
directory che risolvono i problemi di sicurezza insiti nell'uso di
\textit{pathname} relativi con programmi \textit{multi-thread} illustrate in
- sez.~\ref{sec:file_openat}.
+ sez.~\ref{sec:file_openat}. Dalle \acr{glibc} 2.10 questa macro viene
+ definita implicitamente se si definisce \macro{\_POSIX\_C\_SOURCE} ad un
+ valore maggiore o uguale di ``\texttt{200809L}''.
\item[\macrod{\_REENTRANT}] definendo questa macro, o la equivalente
- \macrod{\_THREAD\_SAFE} (fornita per compatibilità) si rendono disponibili le
- versioni rientranti (vedi sez.~\ref{sec:proc_reentrant}) di alcune funzioni,
- necessarie quando si usano i \textit{thread}. Alcune di queste funzioni
- sono anche previste nello standard POSIX.1c, ma ve ne sono altre che sono
- disponibili soltanto su alcuni sistemi, o specifiche della \acr{glibc}, e
- possono essere utilizzate una volta definita la macro.
+ \macrod{\_THREAD\_SAFE} (fornita per compatibilità) si rendono disponibili
+ le versioni rientranti (vedi sez.~\ref{sec:proc_reentrant}) di alcune
+ funzioni, necessarie quando si usano i \textit{thread}. Alcune di queste
+ funzioni sono anche previste nello standard POSIX.1c, ma ve ne sono altre
+ che sono disponibili soltanto su alcuni sistemi, o specifiche della
+ \acr{glibc}, e possono essere utilizzate una volta definita la macro. Oggi
+ la macro è obsoleta, già dalle \acr{glibc} 2.3 le librerie erano già
+ completamente rientranti e dalle \acr{glibc} 2.25 la macro è equivalente ad
+ definire \macro{\_POSIX\_C\_SOURCE} con un valore di ``\texttt{199606L}''
+ mentre se una qualunque delle altre macro che richiede un valore di
+ conformità più alto è definita, la sua definizione non ha alcun effetto.
\item[\macrod{\_FORTIFY\_SOURCE}] definendo questa macro viene abilitata
l'inserimento di alcuni controlli per alcune funzioni di allocazione e
% LocalWords: filename fifo name components resolution chroot parent symbolic
% LocalWords: char block VMS raw access MacOS LF CR dos HFS Mac attributes
% LocalWords: Executable Linkable Format Tool magic descriptor stream locking
-% LocalWords: process
+% LocalWords: process mount point ELF
%%% Local Variables:
%%% mode: latex
variabili proprie e sarà eseguito in maniera completamente indipendente da
tutti gli altri. Questo non è del tutto vero nel caso di un programma
\textit{multi-thread}, ma la gestione dei \textit{thread} in Linux sarà
-trattata a parte in cap.~\ref{cha:threads}.
+trattata a parte\unavref{in cap.~\ref{cha:threads}}.
\subsection{L'avvio e l'esecuzione di un programma}
\itindbeg{link-loader}
\itindbeg{shared~objects}
-Quando un programma viene messo in esecuzione cosa che può essere fatta solo
-con una funzione della famiglia \func{exec} (vedi sez.~\ref{sec:proc_exec}) il
-kernel esegue un opportuno codice di avvio, il cosiddetto
+Quando un programma viene messo in esecuzione, cosa che può essere fatta solo
+con una funzione della famiglia \func{exec} (vedi sez.~\ref{sec:proc_exec}),
+il kernel esegue un opportuno codice di avvio, il cosiddetto
\textit{link-loader}, costituito dal programma \cmd{ld-linux.so}. Questo
programma è una parte fondamentale del sistema il cui compito è quello della
gestione delle cosiddette \textsl{librerie condivise}, quelle che nel mondo
Questo significa però che normalmente il codice di un programma è incompleto,
contenendo solo i riferimenti alle funzioni di libreria che vuole utilizzare e
non il relativo codice. Per questo motivo all'avvio del programma è necessario
-l'intervento del \textit{link-loader} il cui compito è
-caricare in memoria le librerie condivise eventualmente assenti, ed effettuare
-poi il collegamento dinamico del codice del programma alle funzioni di
-libreria da esso utilizzate prima di metterlo in esecuzione.
+l'intervento del \textit{link-loader} il cui compito è caricare in memoria le
+librerie condivise eventualmente assenti, ed effettuare poi il collegamento
+dinamico del codice del programma alle funzioni di libreria da esso utilizzate
+prima di metterlo in esecuzione.
Il funzionamento di \cmd{ld-linux.so} è controllato da alcune variabili di
-ambiente e dal contenuto del file \conffile{/etc/ld.so.conf}, che consentono
-di elencare le directory un cui cercare le librerie e determinare quali
-verranno utilizzate. In particolare con la variabile di ambiente
+ambiente e dal contenuto del file \conffile{/etc/ld.so.conf} che consentono di
+elencare le directory un cui cercare le librerie e determinare quali verranno
+utilizzate. In particolare con la variabile di ambiente
\envvar{LD\_LIBRARY\_PATH} si possono indicare ulteriori directory rispetto a
quelle di sistema in cui inserire versioni personali delle librerie che hanno
la precedenza su quelle di sistema, mentre con la variabile di ambiente
nell'esecuzione del programma. Una funzione ordinaria infatti viene eseguita,
esattamente come il codice che si è scritto nel corpo del programma, in
\textit{user space}. Quando invece si esegue una \textit{system call}
-l'esecuzione ordinaria del programma viene interrotta, i dati forniti (come
-argomenti della chiamata) vengono trasferiti al kernel che esegue il codice
-della \textit{system call} (che è codice del kernel) in \textit{kernel space}.
+l'esecuzione ordinaria del programma viene interrotta con quello che viene
+usualmente chiamato un \itindex{context~switch} \textit{context
+ switch};\footnote{in realtà si parla più comunemente di \textit{context
+ switch} quando l'esecuzione di un processo viene interrotta dal kernel
+ (tramite lo \textit{scheduler}) per metterne in esecuzione un altro, ma il
+ concetto generale resta lo stesso: l'esecuzione del proprio codice in
+ \textit{user space} viene interrotta e lo stato del processo deve essere
+ salvato per poterne riprendere l'esecuzione in un secondo tempo.} il
+contesto di esecuzione del processo viene salvato in modo da poterne
+riprendere in seguito l'esecuzione ed i dati forniti (come argomenti della
+chiamata) vengono trasferiti al kernel che esegue il codice della
+\textit{system call} (che è codice del kernel) in \textit{kernel space}; al
+completamento della \textit{system call} i dati salvati nel \textit{context
+ switch} saranno usati per riprendere l'esecuzione ordinaria del programma.
Dato che il passaggio dei dati ed il salvataggio del contesto di esecuzione
-del programma che consentirà di riprenderne l'esecuzione ordinaria al
-completamento della \textit{system call} sono operazioni critiche per le
-prestazioni del sistema, per rendere il più veloce possibile questa
-operazione, usualmente chiamata \textit{context switch} sono state sviluppate
-una serie di ottimizzazioni che richiedono alcune preparazioni abbastanza
-complesse dei dati, che in genere dipendono dall'architettura del processore
-sono scritte direttamente in \textit{assembler}.
+sono operazioni critiche per le prestazioni del sistema, per rendere il più
+veloce possibile questa operazione sono state sviluppate una serie di
+ottimizzazioni che richiedono alcune preparazioni abbastanza complesse dei
+dati, che in genere dipendono dall'architettura del processore e sono scritte
+direttamente in \textit{assembler}.
+
%
% TODO:trattare qui, quando sarà il momento vsyscall e vDSO, vedi:
può voler utilizzare una \textit{system call} che non è stata ancora associata
ad una funzione di libreria. In tal caso, per evitare di dover effettuare
esplicitamente le operazioni di preparazione citate, all'interno della
-\textsl{glibc} è fornita una specifica funzione, \funcd{syscall}, che consente
-eseguire direttamente una \textit{system call}; il suo prototipo, accessibile
-se si è definita la macro \macro{\_GNU\_SOURCE}, è:
+\textsl{glibc} è fornita una specifica funzione,
+\funcd{syscall},\footnote{fino a prima del kernel 2.6.18 per l'esecuzione
+ diretta delle \textit{system call} erano disponibili anche una serie di
+ macro \texttt{\_syscall\textsl{N}} (con $N$ pari al numero di argomenti
+ della \textit{system call}); queste sono deprecate e pertanto non ne
+ parleremo ulteriormente.} che consente eseguire direttamente una
+\textit{system call}; il suo prototipo, accessibile se si è definita la macro
+\macro{\_GNU\_SOURCE}, è:
\begin{funcproto}{
\fhead{unistd.h}
\fhead{sys/syscall.h}
- \fdecl{int syscall(int number, ...)}
+ \fdecl{long syscall(int number, ...)}
\fdesc{Esegue la \textit{system call} indicata da \param{number}.}
}
{La funzione ritorna un intero dipendente dalla \textit{system call} invocata,
chiusura invocando direttamente la funzione \func{exit}. Queste due modalità
sono assolutamente equivalenti, dato che \func{exit} viene chiamata in maniera
trasparente anche quando \code{main} ritorna, passandogli come argomento il
-valore di ritorno (che essendo .
+valore di ritorno.
La funzione \funcd{exit}, che è completamente generale, essendo definita dallo
standard ANSI C, è quella che deve essere invocata per una terminazione
Una forma alternativa per effettuare una terminazione esplicita di un
programma è quella di chiamare direttamente la \textit{system call}
\funcd{\_exit},\footnote{la stessa è definita anche come \funcd{\_Exit} in
- \headfile{stdlib.h}.} che restituisce il controllo direttamente al kernel,
-concludendo immediatamente il processo, il suo prototipo è:
+ \headfile{stdlib.h}, inoltre a partire dalle \acr{glibc} 2.3 usando questa
+ funzione viene invocata \func{exit\_group} che termina tutti i
+ \textit{thread} del processo e non solo quello corrente (fintanto che non si
+ usano i \textit{thread}\unavref{, vedi sez.~\ref{cha:threads},} questo non
+ fa nessuna differenza).} che restituisce il controllo direttamente al
+kernel, concludendo immediatamente il processo, il suo prototipo è:
\begin{funcproto}{ \fhead{unistd.h} \fdecl{void \_exit(int status)}
\fdesc{Causa la conclusione immediata del programma.} } {La funzione non