Grandi pulizie di primavera... dimmi te se uno deve sprecare le ferie cosi`
authorSimone Piccardi <piccardi@gnulinux.it>
Mon, 30 Apr 2001 20:18:29 +0000 (20:18 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Mon, 30 Apr 2001 20:18:29 +0000 (20:18 +0000)
Tolto files.tex e inseriti i nuovi quattro capitoli sui files, c'e`
poco piu` dei titoli delle sezioni, ma la ristrutturazione e` stata fatta.

Aggiunte le appendici (vuote, per ora sono solo segnaposti) dove
dovrebbero andare le cose riguardanti i vari protocolli.

Finito il three way handshake e la chiusura della connessione, rimane
irrisolto il problema di tradurre acknoweledgment ...

13 files changed:
app_a.tex [new file with mode: 0644]
app_b.tex [new file with mode: 0644]
elemtcp.tex
filedir.tex [new file with mode: 0644]
fileintro.tex [new file with mode: 0644]
files.tex [deleted file]
filestd.tex [new file with mode: 0644]
fileunix.tex [new file with mode: 0644]
intro.tex
main.tex
network.tex
process.tex
socket.tex

diff --git a/app_a.tex b/app_a.tex
new file mode 100644 (file)
index 0000000..fd56b3f
--- /dev/null
+++ b/app_a.tex
@@ -0,0 +1,3 @@
+\chapter{Il protocollo IP}
+\label{cha:ip_protocol}
+
diff --git a/app_b.tex b/app_b.tex
new file mode 100644 (file)
index 0000000..48d2dd8
--- /dev/null
+++ b/app_b.tex
@@ -0,0 +1,3 @@
+\chapter{Il protocollo TCP}
+\label{cha:tcp_protocol}
+
index 37745f2ac447edfed010194d17c4f748abc3c718..7929fcca6c6e400e0606c5e75a0f1cfc0f7728db 100644 (file)
@@ -4,7 +4,7 @@
 In questo capitolo inizieremo ad approndire la conoscenza dei socket TCP,
 tratteremo qui dunque il funzionamento delle varie funzioni che si sono usate
 nei due esempi elementari forniti in precedenza (vedi \ref{sec:net_cli_sample}
-e \ref{sec:net_cli_server}), previa una descrizione delle principali
+e \ref{sec:net_serv_sample}), previa una descrizione delle principali
 caratteristiche del funzionamento di una connessione TCP.
 
 La seconda parte del capitolo sarà poi dedicata ad una riscrittura
@@ -20,28 +20,219 @@ Prima di entrare nei dettagli di come si usano le varie funzioni dei socket
 che operano con TCP, è fondamentale capire alcune basi del funzionamento del
 protocollo, ed in particolare su come si stabilisce una connessione, come la
 si conclude e qual'è il significato dei vari stati del protocollo ad essa
-connessi; in particolare questo ci permetterà di capire ed usare con profitto
-il programma \texttt{netstat}, che è in grado di mostrare lo stato in cui si
-trova ciascuna connessione attiva.
+connessi.
 
-\subsection{Creazione: il \textit{three way handshake}}
+La conoscenza del funzionamento del protocollo è infatti essenziale per capire
+il modello di programmazione ed il funzionamento delle API. In tutto questo è
+di grande aiuto il programma \texttt{netstat}, che useremo per mostrare lo
+stato in cui si trova ciascuna connessione attiva.
+
+\subsection{La creazione della connessione: il \textit{three way handushake}}
 \label{sec:TCPel_conn_cre}
 
+Lo scenario tipico che si verifica quando si deve stabilire una connessione
+TCP (lo stesso usato negli esempi elementari \ref{fig:net_cli_code} e
+\ref{fig:net_serv_code}) la successione degli eventi è la
+seguente:
+
+\begin{itemize}
+\item Il server deve essere preparato per accettare le connessioni in arrivo;
+  il procedimento si chiama \textsl{apertura passiva} del socket (da
+  \textit{passive open}); questo viene fatto chiamando la sequenza di funzioni
+  \texttt{socket}, \texttt{bind} e \texttt{listen}. Infine il server chiama la
+  funzione \texttt{accept} e il processo si blocca in attesa di connessioni.
+  
+\item Il client richiede l'inizio della connessione usando la funzione
+  \texttt{connect}, attraverso un procedimento che viene chiamato
+  \textsl{apertura attiva}, dall'inglese \textit{active open}. La chiamata di
+  \texttt{connect} blocca il processo e causa l'invio da parte del client di
+  un segmento \texttt{SYN}\footnote{Si ricordi che il segmento è l'unità
+    elementare di dati trasmessa dal protocollo TCP al livello superiore;
+    tutti i segmenti hanno un header che contiene le informazioni che servono
+    allo \textit{stack TCP} (così viene di solito chiamata la parte del kernel
+    che implementa il protocollo) per realizzare la comunicazione, fra questi
+    dati ci sono una serie di flag usati per gestire la connessione, come
+    \texttt{SYN}, \texttt{ACK}, \texttt{URG}, \texttt{FIN}, alcuni di essi,
+    come \texttt{SYN} (che sta per \textit{sincronize}) corrispondono a
+    funzioni particolari del protocollo e danno il nome al segmento, (per
+    maggiori dettagli vedere \ref{cha:tcp_protocol})}, in sostanza viene
+  inviato al server un pacchetto IP che contiene solo gli header IP e TCP (con
+  un numero di sequenza) e le opzioni di TCP.
+  
+\item il server deve dare ricevuto (l'\textit{acknowledge}) del \texttt{SYN}
+  del client, inoltre anche il server deve inviare il suo \texttt{SYN} al
+  client (e trasmettere il numero di sequenza iniziale) questo viene fatto
+  ritrasmettendo un singolo segmento in cui entrambi i flag \texttt{SYN}
+  \texttt{ACK} e sono settati.
+  
+\item una volta che il client ha ricevuto l'acknowledge dal server la funzione
+  \texttt{connect} ritorna, l'ultimo passo è dare dare il ricevuto del
+  \texttt{SYN} del server inviando un \texttt{ACK}. Alla ricezione di
+  quest'ultimo la funzione \texttt{accept} del server ritorna e la connessione
+  è stabilita.
+\end{itemize} 
+
+Dato che per compiere tutto questo procedimento devono essere scambiati tre
+pacchetti esso viene generalmente chiamato \textit{three way handshake}. In
+\nfig\ si è rappresentato graficamente lo sequenza di scambio dei segmenti che
+stabilisce la connessione.
+
+% Una analogia citata da R. Stevens per la connessione TCP è quella con il
+% sistema del telefono. La funzione \texttt{socket} può essere considerata
+% l'equivalente di avere un telefono. La funzione \texttt{bind} è analoga al
+% dire alle altre persone qual'è il proprio numero di telefono perché possano
+% chiamare. La funzione \texttt{listen} è accendere il campanello del telefono
+% per sentire le chiamate in arrivo.  La funzione \texttt{connect} richiede di
+% conoscere il numero di chi si vuole chiamare. La funzione \texttt{accept} è
+% quando si risponde al telefono.
 
+\begin{figure}[htb]
+  \centering
+  
+  \caption{Il \textit{three way handshake} del TCP}
+  \label{fig:TCPel_TWH}
+\end{figure}
 
-\subsection{Il significato delle opzioni del TCP}
+Si noti che figura si sono riportati anche i \textsl{numeri di sequenza}
+associati ai vari pacchetti; per gestire una connessione affidabile infatti il
+protocollo TCP prevede nell'header la presenza di un \textit{sequence number}
+a 32 bit che identifica a quale byte nella sequenza dello stream corrisponde
+il primo byte dei dati contenuti nel segmento.
+
+Il numero di sequenza di ciascun segmento viene calcolato a partire da un
+numero di sequenza iniziale generato in maniera casuale del kernel all'inizio
+della connessione e trasmesso con il SYN; l'acknowledgement di ciascun
+segmento viene effettuato dall'altro capo della connessione settando il flag
+\texttt{ACK} e restituendo nell'apposito campo dell'header un
+\textit{acknowledge number}) pari al numero di sequenza che il ricevente si
+aspetta di ricevere con il pacchetto successivo; dato che il primo pacchetto
+SYN consuma un byte, nel \textit{three way handshake} il numero di acknowledge
+è sempre pari al numero di sequenza iniziale incrementato di uno; lo stesso
+varrà anche (vedi \nfig) per l'acknowledgement di un FIN.
+
+\subsection{Le opzioni TCP.}
 \label{sec:TCPel_TCP_opt}
 
+Ciascun SYN può contenere delle opzioni per il TCP (le cosiddette \textit{TCP
+  options}, che vengono inserite fra l'header e i dati) che servono a regolare
+la connessione. Normalmente vengono usate le seguenti opzioni:
+
+\begin{itemize}
+\item \textit{MSS option} Sta per \textit{maximum segment size}, con questa
+  opzione ciascun capo della connessione annuncia all'altro il massimo
+  ammontare di dati che vorrebbe accettare per ciascun segmento nella
+  connesione corrente. È possibile leggere e scrivere questo valore attraverso
+  l'opzione del socket \texttt{TCP\_MAXSEG}.
+  
+\item \textit{window scale option} come spiegato in \ref{cha:tcp_protocol} il
+  protocollo TCP implementa il controllo di flusso attraverso una
+  \textsl{finestra annunciata} (\textit{advertized window}) con la quale
+  ciascun capo della comunicazione dichiara quanto spazio disponibile ha in
+  memoria per i dati. Questo è un numero a 16 bit dell'haeader, che così può
+  indicare un massimo di 65535 bytes; ma alcuni tipi di connessione come
+  quelle ad alta velocità (sopra i 45Mbits/sec) e quelle che hanno grandi
+  ritardi nel cammino dei pacchetti (come i satelliti) richiedono una finestra
+  più grande per poter ottenere il massimo dalla trasmissione, per questo
+  esiste questa opzione che indica un fattore di scala da applicare al valore
+  della finestra annunciata\footnote{essendo una nuova opzione per garantire
+    la compatibilità con delle vecchie implementazioni del protocollo la
+    procedura che la attiva prevede come negoziazione che l'altro capo della
+    connessione riconosca esplicitamente l'opzione inserendola anche lui nel
+    suo SYN di risposta dell'apertura della connessione} per la connessione
+  corrente (espresso come numero di bit cui shiftare a sinistra il valore
+  della finestra annunciata).
+
+\item \textit{timestamp option} è anche questa una nuova opzione necessaria
+  per le connessioni ad alta velocità per evitare possibili corruzioni di dati
+  dovute a pacchetti perduti che riappaiono; anche questa viene negoziata come
+  la precedente.
+
+\end{itemize}
+
+La MSS è generalmente supportata da quasi tutte le implementazioni del
+protocollo, le ultime due opzioni (trattate nell'RFC 1323) sono meno comuni;
+vengono anche dette \textit{long fat pipe options} dato che questo è il nome
+che viene dato alle connessioni caratterizzate da alta velocità o da ritardi
+elevati.
+
+
 \subsection{La terminazione della connessione}
 \label{sec:TCPel_conn_term}
 
-\subsection{Il diagramma delle transizioni di stato}
-\label{sec:TCPel_trans_dia}
+Mentre per creare una connessione occorre un interscambio di tre segmenti, la
+procedura di chiusura ne richede ben quattro; in questo caso la successione
+degli eventi è la seguente:
+
+\begin{enumerate}
+\item Un processo ad uno dei due capi chiama la funzione \texttt{close}, dando
+  l'avvio a quella che viene chiamata \textsl{chiusura attiva} (da
+  \textit{active close}). Questo comporta l'emissione di un segmento FIN, che
+  significa che si è finito con l'invio dei dati sulla connessione.
+  
+\item L'altro capo della connessione riceve il FIN ed esegue la
+  \textit{chiusura passiva} (da \textit{passive close}); al FIN, come per
+  tutti i pacchetti, viene risposto con un ACK. Inoltre il ricevimento del FIN
+  viene passato al processo che ha aperto il socket come un end of file sulla
+  lettura (dopo che ogni altro eventuale dato rimasto in coda è stato
+  ricevuto), dato che il ricevimento di un FIN significa che non si
+  riceveranno altri dati sulla connessione.
+
+\item Dopo un certo tempo anche il secondo processo chiamerà la funzione
+  \texttt{close} sul proprio socket, causando l'emissione di un altro segmento
+  FIN. 
+  
+\item L'altro capo della connessione riceverà il FIN conclusivo e risponderà
+  con un ACK.
+\end{enumerate}
+
+
+Dato che in questo caso sono richiesti un FIN ed un ACK per ciascuna direzione
+normalmente i segmenti scambiati sono quattro; normalmente giacché in alcune
+sitazioni il FIN del passo 1) è inviato insieme a dei dati. Comunque non è
+detto, anche se è possibile, che i segmenti inviati nei passi 2 e 3, siano
+accorpati in un singolo segmento. In \nfig\ si è rappresentato graficamente lo
+sequenza di scambio dei segmenti che stabilisce la connessione.
+
+\begin{figure}[htb]
+  \centering
+  
+  \caption{Il \textit{three way handshake} del TCP}
+  \label{fig:TCPel_TWH}
+\end{figure}
+
+Come per il SYN anche il FIN occupa un byte nel numero di sequenza, per cui
+l'ACK riporterà un \textit{acknowledge number} incrementato di uno. 
+
+Si noti che nella sequenza di chiusura fra i passi 2 e 3 è in teoria possibile
+che si mantenga un flusso di dati dal capo della connessione che sta eseguendo
+la chiusura passiva a quello che sta eseguendo la chiusura attiva. Nella
+sequenza indicata i dati verrebbero persi, dato che si è chiuso il socket, ma
+esistono situazione in cui si vuole che avvenga proprio questo, che è chiamato
+\texit{half-close}, per cui torneremo su questo aspetto e su come utilizzarlo
+più avanti, quando parleremo della funzione \texttt{shutdown}.
+
+La emissione del FIN avviene quando il socket viene chiuso, questo però non
+avviene solo per la chiamata della funzione \texttt{close}, ma anche alla
+terminazione di un processo, il che vuol dire che se un processo viene
+terminato da un segnale tutte le connessioni aperte verranno chiuse.
+
+
+\subsection{Un esempio di connessione}
+\label{sec:TCPel_conn_dia}
+
+Le operazioni del TCP nella creazione e conclusione di una connessione sono
+specificate attraverso il diagramma di transizione degli stati riportato in
+\nfig. TCP prevede l'esistenza di 11 diversi stati per una connessione ed un
+insieme di regole per le transizioni da uno stato all'altro basate sullo stato
+corrente e sul tipo di segmetno ricevuto.
+
+
 
 \subsection{Lo stato \texttt{TIME\_WAIT}}
 \label{sec:TCPel_time_wait}
 
 
+
 \section{I numeri di porta}
 \label{sec:TCPel_ports}
 
@@ -57,9 +248,6 @@ trova ciascuna connessione attiva.
 \subsection{La funzione \texttt{listen}}
 \label{sec:TCPel_func_listen}
 
-\subsection{La funzione \texttt{connect}}
-\label{sec:TCPel_func_connect}
-
 \subsection{La funzione \texttt{accept}}
 \label{sec:TCPel_func_accept}
 
diff --git a/filedir.tex b/filedir.tex
new file mode 100644 (file)
index 0000000..f68576f
--- /dev/null
@@ -0,0 +1,482 @@
+\chapter{Files e directories}
+\label{cha:files_and_dirs}
+
+In questo capitolo tratteremo in dettaglio le varie caratteristiche di files e
+directories, ed in particolare approfondiremo i dettagli su come è organizzata
+la struttura dei files in un sistema unix; esamineremo poi come è strutturato
+il sistema base di protezioni e controllo di accesso ai files, e tutta
+l'interfaccia che permette la manipolazione dei vari attributi di files e
+directories. Tutto quello che riguarda invece la manipolazione dei contenuti e
+lasciato ai capitoli successivi.
+
+Le funzioni che esamineremo in questo capitolo pertanto sono quelle che
+permettono di creare e cancellare o leggere le directories, rinominare o
+cancellare i files ed esaminare o cambiare i loro attributi.
+
+
+\section{L'organizzazione di files e directories}
+\label{sec:filedir_org}
+
+L'organizzazione dei nomi dei file deriva direttamente dall'organizzazione dei
+medesimi nell'albero descritto brevemente in \ref{sec:fileintr_overview}; una
+directory comunque, come già specificato in \ref{sec:fileintr_vfs}, è solo un
+particolare tipo di file che contiene le informazioni che associano un nome al
+contenuto. Per questo, anche se è usuale parlare di ``file in una directory''
+in realtà una directory contiene solo dei riferimenti ai file, non i file
+stessi.
+
+I nomi contenuti nelle directory sono chiamati componenti (\textit{file name
+  components}), un file può essere indicato rispetto alla directory corrente
+semplicemente specificando il nome da essa contenuto. Una directory contiene
+semplicemente un elenco di questi componenti, che possono corrispondere a un
+qualunque oggetto del filesystem, compresa un'altra directory; l'albero viene
+appunto creato inserendo directory in altre directory.
+
+Il nome di file generico è composto da una serie di \textsl{componenti}
+separati da una \texttt{/} (in linux più \texttt{/} consecutive sono
+considerate equivalenti ad una sola). Il nome completo di un file viene
+usualmente chiamato \textit{pathname}, e anche se il manuale della glibc
+depreca questo nome (poichè genererebbe confusione, dato che con \textit{path}
+si indica anche un insieme di directory su cui effettuare una ricerca, come
+quello in cui si cercano i comandi) l'uso è ormai così comune che è senz'altro
+più chiaro dell'alternativa proposta.
+
+Il processo con cui si associa ad un pathname uno specifico file (cioè si
+identifica l'inode a cui fare riferimento) è chiamato risoluzione del nome
+(\textit{file name resolution} o \textit{pathname resolution}).
+La risoluzione viene fatta esaminando il pathname da destra a sinistra e
+localizzando ogni componente nella directory indicata dal componente
+precedente: ovviamente perché il procedimento funzioni occorre che i
+componenti indicati come directory esistano e siano effettivamente directory,
+inoltre i permessi devono consentire l'accesso.
+
+Se il pathname comincia per \texttt{/} la ricerca parte dalla directory radice
+del processo; questa, a meno di un \textit{chroot} (su cui torneremo in
+seguito, vedi \ref{sec:proc_chroot}) è la stessa per tutti i processi ed
+equivale alla directory radice dell'albero (come descritto in
+\ref{sec:fileintr_overview}): in questo caso si parla di un pathname
+\textsl{assoluto}. Altrimenti la ricerca parte dalla directory corrente (su
+cui torneremo più avanti in \ref{sec:filedir_work_dir}) ed il pathname è detto
+\textsl{relativo}.
+
+I componenti \texttt{.} e \texttt{..} hanno un significato speciale e vengono
+inseriti in ogni directory, il primo fa riferimento alla directory corrente e
+il secondo alla directory \textsl{genitore} (\textit{parent directory}) cioè
+la directory che contiene il riferimento alla directory corrente; nel caso
+questa sia la directory radice allora il riferimento è a se stessa.
+
+
+\section{La manipolazione di files e directories}
+\label{sec:filedir_handling}
+
+Per capire fino in fondo le proprietà di files e directories in un sistema
+unix ed il funzionamento delle relative funzioni di manipolazione occorre una
+breve introduzione agli oggetti su cui è basato un filesystem unix; in
+particolare si riprenderanno, approfondendoli, i concetti di \textit{inode} e
+\textit{dentry} brevemente introdotti in \ref{sec:fileintr_vfs}.
+
+
+\subsection{Il funzionamento di un filesystem}
+\label{sec:filedir_filesystem}
+
+Come già accennato in \ref{sec:fileintr_overview} linux (ed ogni unix in
+generale) organizza i dati che tiene su disco attraverso l'uso di un
+filesystem. Una delle caratteristiche di linux rispetto agli altri unix è
+quella di poter supportare grazie al VFS una enorme quantità di filesystem
+diversi, ognuno dei quali ha una sua particolare struttura e funzionalità
+proprie; per questo non entreremo nei dettagli di un filesystem specifico, ma
+daremo una descrizione a grandi linee che si adatta alle caratteristiche
+comuni di un qualunque filesystem standard unix.
+
+Dato un disco lo spazio fisico viene usualmente diviso in partizioni; ogni
+partizione può contenere un filesystem; quest'ultimo è in genere strutturato
+secondo \nfig, con una lista di inodes all'inizio e il resto dello spazio aa
+disposizione per i dati e le directory.
+
+\begin{figure}[htb]
+  \centering
+  
+  \caption{Organizzazione dello spazio su un disco in partizioni e filesystem}
+  \label{fig:filedir_disk_filesys}
+\end{figure}
+
+Se si va ad esaminare come è strutturata l'informazione all'interno del
+filesystem (tralasciando le parti che non riguardano direttamente la gestione
+di file e directory come il super-block) avremo una situazione del tipo di
+quella esposta in \nfig.
+
+\begin{figure}[htb]
+  \centering
+  
+  \caption{Organizzazione di un filesystem}
+  \label{fig:filedir_filesys_detail}
+\end{figure}
+
+
+Quanto mostrato in \curfig\ mette in evidenza alcune caratteristiche di un 
+filesystem unix su cui è bene porre attenzione in quanto sono fondamentali per
+capire il funzionamento delle funzioni che manipolano i file e le directory su
+cui torneremo fra poco; in particolare è opportuno ricordare sempre che:
+
+\begin{itemize}
+  
+\item L'\textit{inode} contiene tutte le informazioni riguardanti il file: il
+  tipo di file, i permessi di accesso, le dimensioni, i puntatori ai blocchi
+  fisici che contengono i dati e così via; le informazioni che la funzione
+  \texttt{stat} fornisce provengono dall'inode; dentro una directory si
+  troverà solo il nome del file e il numero dell'inode ad esso associato, cioè
+  una \textit{dentry}.
+  
+\item Come mostrato in \curfig si possono avere più dentries che puntano allo
+  stesso inode. Ogni inode ha un contatore che contiene il numero di
+  riferimenti (\textit{link count}) che sono stati fatti ad esso, solo quando
+  questo contatore si annulla il file può essere cancellato. Per questo in
+  generale non esiste una funzione che cancelli un file, ma solo la funzione
+  \texttt{unlink} che si chiama così proprio perché che toglie un riferimento
+  da una directory (cancellando la dentry), il che non comporta
+  automaticamente pure la eliminazione dei blocchi sul disco.
+  
+\item Siccome il numero di inode nella dentry si riferisce ad un inode nello
+  stesso filesystem non ci può essere una directory che contiene riferimenti
+  ad inodes relativi ad altri filesystem, questo limita l'uso del comando
+  \texttt{ln} (che crea una nuova dentry per un file esistente, con la
+  funzione \texttt{link}) al filesystem corrente.
+
+\item Quando si cambia nome ad un file senza cambiare filesystem il contenuto
+  del file non deve essere spostato, ma basta creare una nuova dentry per
+  l'inode in questione rimuovendo la vecchia (che è la modalità in cui opera
+  normalmente il comando \texttt{mv} attraveso la funzione \texttt{rename}).
+
+\end{itemize}
+
+Infine è bene avere presente che esiste un numero di riferimenti anche per le
+directories, se a partire dalla situazione mostrata in \curfig\ creiamo una
+nuova directory \texttt{textdir} avremo una situazione come quella in \nfig,
+dove per chiarezza abbiamo aggiunto dei numeri di inode.
+
+La nuova directory avrà allora un numero di riferimenti pari a due, in quanto
+è referenziata dalla directory da cui si era partiti (in cui è inserita la
+nuova dentry che fa riferiemto a \texttt{textdir}) e dalla dentry \texttt{.}
+che è sempre inserita in ogni directory; questo vale sempre per ogni directory
+che non contenga a sua volta altre directories. Al contempo la directory da
+cui si era partiti avrà un numero di riferiementi di almeno tre, in quanto
+adesso sarà referenziata anche dalla dentry \texttt{..} di \texttt{textdir}.
+
+
+\subsection{Le funzioni \texttt{link} e \texttt{unlink}}
+\label{sec:filedir_link}
+
+Una delle caratteristiche usate quando si opera con i file è quella di poter
+creare dei nomi fittizi (alias o collegamenti) per potersi riferire allo
+stesso file accedendovi da directory diverse. Questo è possibile anche in
+ambiente unix, dove tali collegamenti sono usualmente chiamati \textit{link},
+ma data la struttura del sistema ci sono due metodi sostanzialmente diversi
+per fare questa operazione.
+
+Come si è appena visto l'accesso al contenuto di un file su disco avviene
+attraverso il suo \textit{inode}, e il nome che si trova in una directory è
+solo una etichetta associata ad un puntatore a detto inode.  Questo significa
+che la realizzazione di un link è immediata in quanto uno stesso file può
+avere tanti nomi diversi allo stesso tempo, dati da altrettante diverse
+associazioni allo stesso inode; si noti poi che nessuno di questi nomi viene
+ad assumere una particolare preferenza rispetto agli altri.
+
+Per aggiungere un nome ad un inode si utilizza la funzione \texttt{link}; si
+suole chiamare questo tipo di associazione un collegamento diretto (o
+\textit{hard link}).  La creazione di un nuovo link diretto non copia il
+contenuto del file, ma si limita ad aumentare di uno il numero di referenze al
+file aggiungendo il nuovo nome ai precedenti. Si noti che uno stesso file può
+essere così richiamato in diverse directory.
+
+\begin{itemize}
+\item \texttt{int link(const char * oldname, const char * newname)}
+  
+  Crea un nuovo link diretto al file indicato da \texttt{oldname} dandogli
+  nome \texttt{newname}.
+  
+  La funzione restituisce zero in caso di successo e -1 per un errore, in caso
+  di errore. La variabile \texttt{errno} viene settata secondo i codici di
+  errore standard di accesso ai files (trattati in dettaglio in
+  \ref{sec:filedir_access_control}) ai quali si aggiungono i seguenti:
+
+  \begin{itemize}
+  \item \texttt{EXDEV} \texttt{oldname} e \texttt{newname} non sono sullo
+    stesso filesystem.
+  \item \texttt{EPERM} il filesystem che contiene \texttt{oldname} e
+    \texttt{newname} non supporta i link diretti.
+  \item \texttt{EACCESS} 
+    Non c'è il permesso di scrittura per la directory in cui si vuole creare
+    il nuovo link.
+  \item \texttt{EEXIST} Un file (o una directory) con quel nome esiste di
+    già.
+  \item \texttt{EMLINK} Ci sono troppi link al file \texttt{oldname} (il
+    numero massimo è specificato dalla variabile \texttt{LINK\_MAX}, vedi
+    \ref{sec:xxx_limits}.
+  \item \texttt{ENOSPC} La directory in cui si vuole creare il link è piena e
+    non può essere ampliata.
+  \item \texttt{EROFS} La directory su cui si vuole inserire il nuovo link è
+    su un filesystem montato readonly.
+  \end{itemize}
+\end{itemize}
+
+
+
+\subsection{Le funzioni \texttt{remove} e \texttt{rename}}
+\label{sec:filedir_cre_canc}
+
+
+\subsection{I link simbolici}
+\label{sec:filedir_sym_link}
+
+Siccome tutto ciò funziona facendo riferimento ad un inode, questa funzione
+può essere applicata soltanto per file che risiedono sullo stesso filesystem,
+(dato che solo in questo caso è garantita l'unicità dell'inode) e solo per
+filesystem di tipo unix. Inoltre in linux non è consentito eseguire un link
+diretto ad una directory.
+
+Per ovviare a queste limitazioni i sistemi unix supportano un'altra forma di
+link (i cosiddetti \textit{soft link} o \textit{symbolic link}), che sono,
+come avviene in altri sistemi operativi, dei file che contengono il
+semplicemente il riferimento ad un altro file (o directory). In questo modo è
+possibile effettuare link anche attraverso filesystem diversi e a directory, e
+pure a file che non esistono ancora.
+
+Il sistema funziona in quanto i link simbolici sono contrassegnati come tali
+al kernel (analogamente a quanto avviene per le directory) per cui la chiamata
+ad una \texttt{open} o una \texttt{stat} su un link simbolico comporta la
+lettura del contenuto del medesimo e l'applicazione della funzione al file
+specificato da quest'ultimo. Invece altre funzioni come quelle per cancellare
+o rinominare i file operano direttamente sul link simbolico. Inoltre esistono
+funzioni apposite, come la \texttt{readlink} e la \texttt{lstat} per accedere
+alle informazioni del link invece che a quelle del file a cui esso fa
+riferimento.
+
+Le funzioni per operare sui link sono le seguenti, esse sono tutte dichiarate
+nell'header file \texttt{unistd.h}.
+
+\begin{itemize}
+\item \texttt{int symlink(const char * oldname, const char * newname)}
+  
+  Crea un nuovo link simbolico al file indicato da \texttt{oldname} dandogli
+  nome \texttt{newname}.
+  
+  La funzione restituisce zero in caso di successo e -1 per un errore, in caso
+  di errore. La variabile \texttt{errno} viene settata secondo i codici di
+  errore standard di accesso ai files (trattati in dettaglio in
+  \ref{sec:filedir_access_control}) ai quali si aggiungono i seguenti:
+
+  \begin{itemize}
+  \item \texttt{EEXIST} Un file (o una directory) con quel nome esiste di
+    già.
+  \item \texttt{EROFS} La directory su cui si vuole inserire il nuovo link è
+    su un filesystem montato readonly.
+  \item \texttt{ENOSPC} La directory o il filesystem in cui si vuole creare il
+    link è piena e non c'è ulteriore spazio disponibile.
+  \item \texttt{ELOOP} Ci sono troppi link simbolici nella risoluzione di
+    \texttt{oldname} o di \texttt{newname}.
+  \end{itemize}
+\end{itemize}
+
+
+\subsection{Le funzioni \texttt{mkdir} e \texttt{rmdir}} 
+\label{sec:filedir_dir_creat_rem}
+
+Per creare una nuova directory si può usare la seguente funzione, omonima
+dell'analogo comando di shell \texttt{mkdir}; per accedere alla funzioni il
+programma deve includere il file \texttt{sys/stat.h}.
+
+\begin{itemize}
+\item \texttt{char * mkdir (const char * dirname, mode\_t mode)}
+  
+  Questa funzione crea una nuova directory vuota con il nome indicato da
+  \texttt{dirname}, assegnandole i permessi indicati da \texttt{mode}. Il nome
+  può essere indicato con il pathname assoluto o relativo.
+  
+  La funzione restituisce zero in caso di successo e -1 per un errore, in caso
+  di errore \texttt{errno} viene settata secondo i codici di errore standard
+  di accesso ai files (trattati in dettaglio in
+  \ref{sec:filedir_access_control}) ai quali si aggiungono i seguenti:
+  \begin{itemize}
+  \item \texttt{EACCESS} 
+    Non c'è il permesso di scrittura per la directory in cui si vuole inserire
+    la nuova directory.
+  \item \texttt{EEXIST} Un file (o una directory) con quel nome essite di già. 
+  \item \texttt{EMLINK} La directory in cui si vuole creare la nuova directory
+    contiene troppi file. Sotto linux questo normalmente non avviene perchè il
+    filesystem standard consente la creazione di un numero di file maggiore di
+    quelli che possono essere contenuti nell'hard-disk, ma potendo avere a che
+    fare anche con filesystem di altri sistemi questo errore può presentarsi.
+  \item \texttt{ENOSPC} Non c'è abbastanza spazio sul file system per creare
+    la nuova directory.
+  \item \texttt{EROFS} La directory su cui si vuole inserire la nuova
+    directory è su un filesystem montato readonly.
+  \end{itemize}
+\end{itemize}
+
+\subsection{Accesso alle directory}
+\label{sec:filedir_dir_read}
+
+Benchè le directory siano oggetti del filesystem come tutti gli altri non ha
+ovviamente senso aprirle come fossero dei file di dati. Può però essere utile
+poterne leggere il contenuto ad esempio per fare la lista dei file che esse
+contengono o ricerche sui medesimi.
+
+Per accedere al contenuto delle directory si usano i cosiddetti
+\textit{directory streams} (chiamati così per l'analogia con i file stream);
+la funzione \texttt{opendir} apre uno di questi stream e la funzione
+\texttt{readdir} legge il contenuto della directory, i cui elementi sono le
+\textit{directory entries} (da distinguersi da quelle della cache di cui
+parlavamo in \ref{sec:fileintr_vfs}) in una opportuna struttura
+\texttt{struct dirent}.
+
+
+\subsection{La directory di lavoro}
+\label{sec:filedir_work_dir}
+
+A ciascun processo è associato ad una directory nel filesystem che è chiamata
+directory corrente o directory di lavoro (\textit{current working directory})
+che è quella a cui si fa riferimento quando un filename è espresso in forma
+relativa (relativa appunto a questa directory).
+
+Quando un utente effettua il login questa directory viene settata alla
+cosiddetta \textit{home directory} del suo account, il comando \texttt{cd}
+della shell consente di cambiarla a piacere, spostandosi da una directory ad
+un'altra.  Siccome la directory corrente resta la stessa quando viene creato
+un processo figlio, la directory corrente della shell diventa anche la
+directory corrente di qualunque comando da essa lanciato.
+
+Le funzioni qui descritte servono esaminare e cambiare la directory di lavoro
+corrente. I prototipi di queste funzioni sono dichiarati in \texttt{unistd.h}. 
+
+\begin{itemize}
+\item \texttt{char * getcwd (char * buffer, size\_t size)}
+  
+  Restituisce il filename completo della directory di lavoro corrente nella
+  stringa puntata da \texttt{buffer}, che deve essere precedentemente
+  allocata, per una dimensione massima di \texttt{size}. Si può anche
+  specificare un puntatore nullo come \textit{buffer}, nel qual caso la
+  stringa sarà allocata automaticamente per una dimensione pari a
+  \texttt{size} qualora questa sia diversa da zero, o della lunghezza esatta
+  del pathname altrimenti. In questo caso si deve ricordare di disallocara la
+  stringa una volta cessato il suo utilizzo.
+  
+  La funzione restituisce il puntatore \texttt{buffer} se riesce,
+  \texttt{NULL} se fallisce, in quest'ultimo caso la variabile
+  \texttt{errno} è settata con i seguenti codici di errore:
+
+  \begin{itemize}
+  \item \texttt{EINVAL} L'argomento \texttt{size} è zero e \texttt{buffer} non
+    è nullo.
+  \item \texttt{ERANGE} L'argomento \texttt{size} è più piccolo della
+    lunghezza del pathname. 
+  \item \texttt{EACCES} Manca il permesso di lettura o di ricerca su uno dei
+    componenti del pathname (cioè su una delle directory superiori alla
+    corrente).
+  \end{itemize}
+\end{itemize}
+
+Di questa funzione esiste una versione \texttt{char * getwd(char * buffer)}
+fatta per compatibilità all'indietro con BSD, che non consente di specificare
+la dimensione del buffer; esso deve essere allocato in precedenza ed avere una
+dimensione superiore a \texttt{PATH\_MAX} (di solito 256 byters, vedi
+\ref{sec:xxx_limits}; il problema è che in linux non esiste una dimensione
+superiore per un pathname, per cui non è detto che il buffer sia sufficiente a
+contenere il nome del file, e questa è la ragione principale per cui questa
+funzione è deprecata.
+
+Una seconda funzione simile è \texttt{char * get\_current\_dir\_name(void)}
+che è sostanzialmente equivalente ad una \texttt{getcwd(NULL, 0)}, con la sola
+differenza che essa ritorna il valore della variabile di ambiente
+\texttt{PWD}, che essendo costruita dalla shell può contenere anche dei
+riferimenti simbolici.
+
+Come già detto in unix anche le directory sono file, è possibile pertanto
+riferirsi ad esse tramite il file descriptor dell'interfaccia a basso livello,
+e non solo tramite il filename; per questo motivo ci sono due diverse funzioni
+per cambiare directory di lavoro.
+
+\begin{itemize}
+\item \texttt{int chdir (const char * pathname)}
+  
+  Come dice il nome (che significa \textit{change directory}) questa funzione
+  serve a cambiare la directory di lavoro a quella speficata dal pathname
+  contenuto nella stringa \texttt{pathname}.
+  
+\item \texttt{int fchdir (int filedes)} analoga alla precedente, ma usa un
+  file descriptor invece del pathname.
+
+  
+  Entrambe le funzioni restituiscono zero in caso di successo e -1 per un
+  errore, in caso di errore \texttt{errno} viene settata secondo i codici di
+  errore standard di accesso ai files (trattati in dettaglio in
+  \ref{sec:filedir_access_control}) ai quali si aggiunge il codice
+  \texttt{ENOTDIR} nel caso il \texttt{filename} indichi un file che non sia
+  una directory.
+\end{itemize}
+
+
+
+
+
+\section{La manipolazione delle caratteristiche dei files}
+\label{sec:filedir_infos}
+
+
+Si ricordi che in unix non esistono i tipi di file e che non c'è nessun
+supporto per le estensioni come parte del filesystem. Ciò non ostante molti
+programmi adottano delle convenzioni per i nomi dei file, ad esempio il codice
+C normalmente si mette in file con l'estensione .c, ma questa è, appunto, solo
+una convenzione.
+
+
+\subsection{Le funzioni \texttt{stat}, \texttt{fstat} e \texttt{lstat}}
+\label{sec:filedir_stat}
+
+\subsection{I tipi di file}
+\label{sec:filedir_file_types}
+
+\subsection{La dimensione dei file}
+\label{sec:filedir_file_size}
+
+\subsection{I tempi dei file}
+\label{sec:filedir_file_times}
+
+\subsection{La funzione \texttt{utime}}
+\label{sec:filedir_utime}
+
+
+
+\section{Il controllo di accesso ai file}
+\label{sec:filedir_access_control}
+
+
+\subsection{I flag \texttt{suid} e \texttt{sgid}}
+\label{sec:filedir_suid_sgid}
+
+\subsection{La titolarità di nuovi files e directory}
+\label{sec:filedir_ownership}
+
+\subsection{La funzione \texttt{access}}
+\label{sec:filedir_access}
+
+\subsection{La funzione \texttt{umask}}
+\label{sec:filedir_umask}
+
+\subsection{Le funzioni \texttt{chmod} e \texttt{fchmod}}
+\label{sec:filedir_chmod}
+
+\subsection{Il flag \texttt{stiky}}
+\label{sec:filedir_stiky}
+
+\subsection{Le funzioni \texttt{chown}, \texttt{fchown} e \texttt{lchown}}
+\label{sec:filedir_chown}
+
+
+
+%La struttura fondamentale che contiene i dati essenziali relativi ai file è il
+%cosiddetto \textit{inode}; questo conterrà informazioni come il
+%tipo di file (file di dispositivo, directory, file di dati, per un elenco
+%completo vedi \ntab), i permessi (vedi \ref{sec:file_perms}), le date (vedi
+%\ref{sec:file_times}).
+
diff --git a/fileintro.tex b/fileintro.tex
new file mode 100644 (file)
index 0000000..b0779a5
--- /dev/null
@@ -0,0 +1,375 @@
+\chapter{I files: introduzione}
+\label{cha:files_intro}
+Uno dei concetti fondamentali della architettura di unix è il cosiddetto
+\textit{everything is a file}, cioè il fatto che l'accesso ai vari dispositivi
+di input/output del computer viene effettuato attraverso un'interfaccia
+astratta che tratta le periferiche allo stesso modo degli usuali file di
+dati.
+
+Questo significa che si può accedere cioè a qualunque periferica del computer,
+dalla seriale, alla parallela, alla console, e agli stessi dischi, (unica
+eccezione le interfacce di rete, che che non rientrano bene nell'astrazione)
+attraverso i cosiddetti file di dispositivo (i \textit{device files}). Questi
+sono dei file speciali agendo sui quali i programmi possono leggere, scrivere
+e compiere operazioni direttamente sulle perferiche, usando le stesse funzioni
+che si usano per i normali file di dati.
+
+In questo capitolo forniremo un'introduzione alle principali caratteristiche
+di questa interfaccia, su come essa viene implementata in linux e su come sono
+organizzati i file nel sistema.
+
+
+\section{I file in un sistema unix-like}
+\label{sec:fileintr_overview}
+
+Visto il ruolo fondamentale che i files vengono ad assumere in un sistema
+unix, è anzitutto opportuno fornire un'introduzione dettagliata su come essi
+vengono trattati dal sistema. In particolare occorre tenere presente dov'è che
+si situa il limite fondamentale fra kernel space e user space che tracciavamo
+al Cap.~\ref{cha:intro_unix}.
+
+Partiamo allora da come viene strutturata nel sistema la disposizione dei
+file: per potervi accedere il kernel usa una apposita interfaccia che permetta
+di strutturare l'informazione tenuta sullo spazio grezzo disponibile sui
+dischi, cioè quello che si chiama un \textit{filesystem}. 
+
+Sarà attraverso quest'ultimo che il kernel andrà a gestire l'accesso ai dati
+memorizzati all'interno del disco stesso, strutturando l'informazione in files
+e directory.  Per poter accedere ai file contenuti in un disco occorrerà
+perciò attivare il filesystem, questo viene fatto \textsl{montando} il disco
+(o la partizione del disco).
+
+%In generale un filesystem piazzerà opportunamente sul disco dei blocchi di
+%informazioni riservate che tengono conto degli inodes allocati, di quelli
+%liberi, e delle posizioni fisiche su disco dei dati contenuti nei files, per
+
+In unix, a differenza di quanto avviene in altri sistemi operativi, tutti i
+file vengono tenuti all'interno di un unico albero la cui radice (la directory
+di \textit{root}) viene montata all'avvio. Pertanto un file viene identificato
+dall'utente usando quello che viene chiamato \textit{pathname}, cioè il
+percorso che si deve fare per accedere al file.
+
+Dopo la fase di inizializzazione il kernel riceve dal boot loader
+l'indicazione di quale dispositivo contiene il filesystem da usare come punto
+di partenza e questo viene montato come radice dell'albero (cioè nella
+directory \texttt{/}); tutti gli ulteriori dischi devono poi essere inseriti
+nell'albero utilizzando opportune subdirectory.
+
+Alcuni filesystem speciali (come \texttt{/proc} che contiene un'interfaccia ad
+alcune strutture interne del kernel) sono generati automaticamente dal kernel
+stesso, ma anche essi devono essere montati all'interno dell'albero.
+
+All'interno dello stesso albero si potranno poi inserire anche gli altri
+oggetti visti attraverso l'interfaccia che manipola i files come le FIFO, i
+link, i socket e gli stessi i file di dispositivo (questi ultimi, per
+convenzione, sono inseriti nella directory \texttt{/dev}).
+
+\subsection{Il \textit{virtual filesystem} di linux}
+\label{sec:fileintr_vfs}
+
+Esamineremo adesso come viene implementato l'accesso ai files in linux. Questa
+sezione riporta informazioni sui dettagli di come il kernel gestisce i files,
+ed è basata sul documento di Richard Goochs distribuito coi sorgenti del
+kernel (\texttt{linux/Documentation/vfs.txt}).
+
+L'argomento è abbastanza ``esoterico'' e questa sezione può essere saltata ad
+una prima lettura; è bene però tenere presente che vengono introdotti qui
+alcuni termini che potranno comparire in seguito, come \textit{inode},
+\textit{dentry}, \textit{dcache}.
+
+In linux il concetto di \textit{everything is a file} è stato implementato
+attraverso il \textit{virtual filesystem} (da qui in avanti VFS) che è
+l'interfaccia astratta che il kernel rende disponibile ai programmi in user
+space attraverso la quale vengono manipolati i files; esso provvede anche
+un'astrazione delle operazioni di manipolazione sui files che permette la
+coesistenza di diversi filesystem all'interno dello stesso albero.
+
+La funzione più importante implementata dal VFS è la system call \texttt{open}
+che permette di aprire un file. Dato un pathname viene eseguita una ricerca
+dentro la \textit{directory entry cache} (in breve \textit{dcache}),
+una tabella di hash che contiene tutte le \textit{directory entry} (in breve
+\textit{dentry}) che permette di associare in maniera rapida ed efficiente il
+pathname a una specifica dentry.
+
+Una singola dentry contiene in genere il puntatore ad un \textit{inode};
+quest'ultimo è la struttura base che sta sul disco e che identifica un singolo
+oggetto del VFS sia esso un file ordinario, una directory, una FIFO, un file
+di dispositivo, o una qualsiasi altra cosa che possa essere rappresentata dal
+VFS (sui tipi di ``files'' possibili torneremo in seguito). A ciascuno di essi
+è associata pure una struttura che sta in memoria, e che oltre alle
+informazioni sullo specifico file contiene pure il riferimento alle funzioni
+(i \textsl{metodi}) da usare per poterlo manipolare.
+
+Le dentries ``vivono'' in memoria e non vengono mai salvate su disco, vengono
+usate per motivi di velocità, gli inodes invece stanno su disco e vengono
+copiati in memoria quando serve, ed ogni cambiamento viene copiato
+all'indietro sul disco, gli inodes che stanno in memoria sono inodes del VFS
+ed è ad essi che puntano le singole dentry.
+
+La dcache costituisce perciò una sorta di vista completa di tutto l'albero dei
+files, ovviamente per non riempire tutta la memoria questa vista è parziale
+(la dcache cioè contiene solo le dentry per i file per i quali è stato
+richiesto l'accesso), quando si vuole risolvere un nuovo pathname il VFS deve
+creare una nuova dentry e caricare l'inode corrispondente in memoria. 
+
+Questo procedimento viene eseguito dal metodo \texttt{lookup()} dell'inode
+della directory che contiene il file; questo viene installato nelle relative
+strutture in memoria quando si effettua il montaggio lo specifico filesystem
+su cui l'inode va a vivere.
+
+Una volta che il VFS ha a disposizione la dentry (ed il relativo inode)
+diventa possibile accedere alle varie operazioni sul file come la
+\texttt{open} per aprire il file o la \texttt{stat} per leggere i dati
+dell'inode e passarli in user space.
+
+L'apertura di un file richiede comunque un'altra operazione, l'allocazione di
+una struttura di tipo \texttt{file} in cui viene inserito un puntatore alla
+dentry e una struttura \verb|f_ops| che contiene i puntatori ai metodi che
+implementano le operazioni disponibili sul file. In questo modo i processi in
+user space possono accedere alle operazioni attraverso detti metodi, che
+saranno diversi a seconda del tipo di file (o dispositivo) aperto. Un elenco
+delle operazioni disponibili è riportato in \ntab.
+
+\begin{table}[htb]
+  \centering
+  \begin{tabular}[c]{c p{7cm}}
+    \textbf{funzione} & \textbf{operazione} \\
+    \hline
+    \textit{open}    & apre il file \\
+    \textit{read}    & legge dal file \\
+    \textit{write}   & scrive sul file \\ 
+    \textit{llseek}  & sposta la posizione corrente sul file \\
+    \textit{ioctl}   & accede alle operazioni di controllo 
+                       (tramite la \texttt{ioctl})\\
+    \textit{readdir} & per leggere il contenuto di una directory \\
+    \textit{poll}    & \\
+    \textit{mmap}    & chiamata dalla system call \texttt{mmap}. 
+                       mappa il file in memoria\\
+    \textit{release} & chiamata quando l'ultima referenza a un file 
+                       aperto è chiusa\\
+    \textit{fsync}   & chiamata dalla system call \texttt{fsync} \\
+    \textit{fasync}  & chiamate da \texttt{fcntl} quando è abilitato 
+                       il modo asincrono per l'I/O su file. \\
+    \hline
+  \end{tabular}
+  \caption{Operazioni sui file definite nel VFS.}
+  \label{tab:fileintr_file_operations}
+\end{table}
+
+In questo modo per ciascun file diventano utilizzabili una serie di operazioni
+(non è dette che tutte siano disponibili), che costituiscono l'interfaccia
+astratta del VFS, e qualora se ne voglia eseguire una il kernel andrà ad
+utilizzare la opportuna routine dichiarata in \verb|f_ops| appropriata al tipo
+di file in questione. 
+
+Così sarà possibile scrivere sulla porta seriale come su un file di dati
+normale; ovviamente certe operazioni (nel caso della seriale ad esempio la
+\textit{seek}) non saranno disponibili, però con questo sistema l'utilizzo di
+diversi filesystem (come quelli usati da Windows o MacOs) è immediato e
+(relativamente) trasparente per l'utente ed il programmatore.
+
+\subsection{Il controllo di accesso}
+\label{sec:fileintr_access_ctrl}
+
+In unix è implementata da qualunque filesystem standard una forma elementare
+(ma adatta alla maggior parte delle esigenze) di controllo di accesso ai
+files. Torneremo sull'argomento in dettaglio più avanti, qui ci limitiamo ad
+una introduzione dei concetti essenziali.
+
+Si tenga conto poi che quanto diremo è vero solo per filesystem di tipo Unix,
+e non è detto che sia applicabile (ed infatti non è vero per il filesystem di
+Windows) a un filesystem qualunque. Esistono inoltre estensioni che permettono
+di implementare le ACL (\textit{Access Control List}) che sono un meccanismo
+di controllo di accesso molto più sofisticato.
+
+Ad ogni file Unix associa sempre l'utente che ne è proprietario (il cosiddetto
+\textit{owner}) e il gruppo di appartenenza, secondo il meccanismo degli uid e
+gid spiegato in \ref{sec:intro_usergroup}, e un insieme di permessi che sono
+divisi in tre classi, e cioè attribuiti rispettivamente al proprietario, a
+qualunque utente faccia parte del gruppo cui appartiene il file, e a tutti gli
+altri utenti.
+
+I permessi sono espressi da un insieme di 12 bit: di questi i nove meno
+significativi sono usati a gruppi di tre per indicare i permessi base di
+lettura, scrittura ed esecuzione (indicati rispettivamente con le lettere
+\textit{w}, \textit{r} \textit{x}) applicabili rispettivamente al
+proprietario, al gruppo, a tutti (una descrizione più dettagliata dei vari
+permessi associati ai file è riportata in \ref{sec:filedir_suid_sgid}).  I
+restanti tre bit sono usati per indicare alcune caratteristiche più complesse
+(\textit{suid}, \textit{sgid}, e \textit{sticky}) su cui pure torneremo in
+seguito (vedi \ref{sec:filedir_suid_sgid} e \ref{sec:filedir_stiky}).
+
+Tutte queste informazioni sono tenute per ciascun file nell'inode. Quando un
+processo cerca l'accesso al file esso controlla i propri uid e gid
+confrontandoli con quelli del file e se l'operazione richiesta è compatibile
+con i permessi associati al file essa viene eseguita, altrimenti viene
+bloccata ed è restituito un errore di \texttt{EPERM}. Questo procedimento non
+viene eseguito per l'amministratore di sistema (il cui uid è zero) il quale ha
+pertanto accesso senza restrizione a qualunque file del sistema.
+
+In realtà il procedimento è più complesso di quanto descritto in maniera
+elementare qui; inoltre ad un processo sono associati diversi identificatori,
+torneremo su questo in maggiori dettagli in seguito in \ref{sec:proc_perms}.
+
+\subsection{I tipi di files}
+\label{sec:fileintr_file_types}
+
+Come detto in precedenza esistono vari tipi di oggetti implementati del VFS
+per i quali è disponibile l'interfaccia astratta da esso provveduta. Un elenco
+dei vari tipi di file è il seguente:
+\begin{table}[htb]
+  \begin{center}
+    \begin{tabular}[c]{l l p{7cm}}
+    \multicolumn{2}{c}{\textbf{Nome}} & \textbf{Descrizione} \\
+    \hline
+      \textit{regular file} & \textsl{file normale} &
+      un file che contiene dei dati (l'accezione normale di file) \\
+      \textit{directory} & \textsl{cartella o direttorio} &
+      un file che contiene una lista di nomi associati a degli inodes \\
+      \textit{symbolic link} & \textsl{collegamento simbolico} &
+      un file che contiene un riferimento ad un altro file/directory \\
+      \textit{char device} & \textsl{dispositivo a caratteri} &
+      un file che identifica una periferica ad accesso sequenziale \\
+      \textit{block device} & \textsl{dispositivo a blocchi} &
+      un file che identifica una periferica ad accesso diretto \\
+      \textit{fifo} & \textsl{tubo} &
+      un file speciale che identifica una linea di comunicazione software
+      (unidirezionale) \\
+      \textit{socket} & \textsl{manicotto} &
+      un file speciale che identifica una linea di comunicazione software
+      (bidirezionale) \\
+    \hline
+    \end{tabular}
+    \caption{Tipologia dei file definiti nel VFS}
+    \label{tab:fileintr_file_types}
+  \end{center}
+\end{table}
+
+Tutto ciò non ha ovviamente nulla a che fare con la classificazione sui tipi
+di file (in questo caso file di dati) in base al loro contenuto, o tipo di
+accesso.  Una delle differenze principali con altri sistemi operativi (come il
+VMS o Windows) è che per Unix tutti i file di dati sono identici e contengono
+un flusso continuo di bytes; non esiste cioè differenza per come vengono visti
+dal sistema file di diverso contenuto o formato (come nel caso di quella fra
+file di testo e binari che c'è in windows) né c'è una strutturazione a record
+per il cosiddetto ``accesso diretto'' come nel caso del VMS.
+
+Una seconda differenza è nel formato dei file ascii; in Unix la fine riga è
+codificata in maniera diversa da Windows o MacIntosh, in particolare il fine
+riga è il carattere \texttt{LF} (o \verb|\n|) al posto del \texttt{CR}
+(\verb|\r|) del mac e del \texttt{CR LF} di windows. Questo può causare alcuni
+problemi qualora si facciano assunzioni sul terminatore della riga.
+
+
+\section{Una panoramica sull'uso dei file}
+\label{sec:fileintr_io_overview}
+
+Per poter accedere al contenuto dei file occorre anzitutto aprirlo. Questo
+crea un canale di comunicazione che permette di eseguire una serie di
+operazioni. Una volta terminate le operazioni, il file dovrà essere chiuso, e
+questo chiuderà il canale di comunicazione impedendo ogni ulteriore
+operazione.
+
+\subsection{Le due interfacce ai file}
+\label{sec:fileintr_io_api}
+
+In unix le modalità di accesso ai file e le relative interfacce di
+programmazione sono due, basate su due diversi meccanismi di connessione. 
+
+La prima è l'interfaccia standard di unix, quella che il manuale delle glibc
+chiama interfaccia dei descrittore di file (o \textit{file descriptor}).  È
+un'interfaccia specifica di unix e provvede un accesso non bufferizzato.
+L'interfaccia è primitiva ed essenziale, l'accesso viene detto non
+bufferizzato in quanto la lettura e la scrittura vengono eseguite chiamando
+direttamente le system call del kernel (in realtà il kernel effettua al suo
+interno alcune bufferizzazioni per aumentare l'efficienza nell'accesso ai
+dispositivi); i file descriptors sono rappresentati da numeri interi (cioè
+semplici variabili di tipo \texttt{int}).  L'interfaccia è definita
+nell'header \texttt{unistd.h}.
+
+La seconda interfaccia è quella che il manuale della glibc chiama degli
+\textit{stream}, essa provvede funzioni più evolute e un accesso bufferizzato
+(controllato dalla implementazione fatta dalle librerie del C).  Questa è
+l'interfaccia standard usata dal linguaggio C e perciò si trova anche su tutti
+i sistemi non Unix. Gli stream sono oggetti complessi e sono rappresentati da
+puntatori ad un opportuna struttura definita dalle librerie del C, si accede
+ad essi sempre in maniera indiretta utilizzando il tipo \texttt{FILE *}.
+L'interfaccia è definita nell'header \texttt{stdio.h}.
+
+Entrambe le interfacce possono essere usate per l'accesso ai file come agli
+altri oggetti del VFS (pipes, socket, device), ma per poter accedere alle
+operazioni di controllo sul particolare tipo di oggetto del VFS scelto occorre
+usare l'interfaccia standard di unix coi file descriptors. Allo stesso modo
+devono essere usati i file descriptor se si vuole ricorrere a modalità
+speciali di I/O come il polling o il non-bloccante (vedi
+\ref{sec:file_bohhhhh}).
+
+Gli stream forniscono un'interfaccia di alto livello costruita sopra quella
+dei file descriptor, che tratta tutti i file nello stesso modo, con
+l'eccezione di poter scegliere tra diversi stili di bufferizzazione.  Il
+maggior vantaggio degli stream è che l'interfaccia per le operazioni di
+input/output è enormemente più ricca di quella dei file descriptor, che
+provvedono solo funzioni elementari per la lettura/scrittura diretta di
+blocchi di bytes.  In particolare gli stream dispongono di tutte le funzioni
+di formattazione per l'input e l'output adatte per manipolare anche i dati in
+forma di linee o singoli caratteri.
+
+In ogni caso, dato che gli stream sono implementati sopra l'interfaccia
+standard di unix, è sempre possibile estrarre il file descriptor da uno stream
+ed eseguirvi operazioni di basso livello, o associare in un secondo tempo uno
+stream ad un file descriptor.
+
+In generale, se non necessitano specificatamente le funzionalità di basso
+livello, è opportuno usare sempre gli stream per la loro maggiore portabilità
+essendo questi ultimi definito nello standard ISO C; l'interfaccia con i file
+descriptor invece segue solo lo standard POSIX.1 dei sistemi unix ed è
+pertanto di portabilità più limitata.
+
+\subsection{Caratteristiche specifiche dei file in unix}
+\label{sec:fileint_unix_spec}
+
+Essendo un sistema multitasking e multiutente esistono alcune caratteristiche
+specifiche di Unix che devono essere tenute in conto nell'accesso ai file. È
+infatti normale che più processi o programmi possano accedere
+contemporaneamente allo stesso file e devono poter eseguire le loro operazioni
+indipendentemente da quello che fanno gli altri processi.
+
+Per questo motivo le strutture usate per all'accesso ai file sono relative al
+processo che effettua l'accesso.  All'apertura di ogni file infatti viene
+creata all'interno del processo una apposita struttura in cui sono memorizzati
+tutti gli attributi del medesimo, che viene utilizzata per tutte le
+operazioni. Questa è una struttura che resta locale al processo stesso; in
+questo modo processi diversi possono usare le proprie strutture locali per
+accedere ai file (che può essere sempre lo stesso) in maniera assolutamente
+indipendente.
+
+Questo ha delle conseguenze di cui è bene tenere conto; ad esempio in tutti i
+sistemi POSIX uno degli attributi di un file aperto è la posizione corrente nel
+file, cioè il punto nel file in cui verrebbe letto o scritto alla operazione
+successiva. Essa è rappresentata da un numero intero che indica il numero di
+bytes dall'inizio del file, che viene (a meno che non si apra il file in
+append) inizializzato a zero all'apertura del medesimo.
+
+Questo è uno dei dati che viene mantenuto nella suddetta struttura, per cui
+ogni processo avrà la sua posizione corrente nel file, che non sarà
+influenzata da quello che altri processi possono fare. Anzi, aprire un file
+significa appunto creare ed inizializzare una tale struttura, per cui se si
+apre due volte lo stesso file all'interno dello stesso processo, si otterrano
+due file descriptor o due stream che avranno ancora una posizione corrente nel
+file assolutamente indipendente.
+
+Si tenga conto inoltre che un'altro dei dati contenuti nella struttura di
+accesso è un riferimento all'inode del file, pertanto anche se il file viene
+cancellato da un altro processo, sarà sempre possibile mantenere l'accesso ai
+dati, e lo spazio su disco non verrà rilasciato fintanto che il file non sarà
+chiuso e l'ultimo riferimento cancellato. È pertanto possibile (e pratica
+comune) aprire un file provvisorio per cancellarlo immediatamente dopo; in
+questo modo all'uscita del programma il file scomparirà definitivamente dal
+disco, ma il file ed il suo contenuto saranno disponibili per tutto il tempo
+in cui il processo è attivo.
+
+Ritorneremo su questo più avanti, quando tratteremo l'input/output sui file,
+esaminando in dettaglio come tutto ciò viene realizzato.
+
diff --git a/files.tex b/files.tex
deleted file mode 100644 (file)
index e3c994d..0000000
--- a/files.tex
+++ /dev/null
@@ -1,718 +0,0 @@
-\chapter{I files: introduzione}
-\label{cha:files}
-Uno dei concetti fondamentali del design di unix è il cosiddetto
-\textit{everything is a file}, cioè il fatto che l'accesso ai vari dispositivi
-di I/O del computer viene effettuato attraverso un'interfaccia astratta che
-tratta le periferiche allo stesso modo degli usuali file di dati.
-
-Si può accedere cioè a qualunque periferica del computer, dalla seriale, alla
-parallela, alla console, e agli stessi dischi, (unica eccezione le interfacce
-di rete, che che non rientrano bene nell'astrazione) attraverso i cosiddetti
-file di dispositivo (i \textit{device files}). Questi sono dei file speciali
-agendo sui quali i programmi possono leggere, scrivere e compiere operazioni
-sulle perferiche, usando le stesse funzioni che si usano per i normali file di
-dati.
-
-\section{Concetti generali riguardanti i files}
-\label{sec:file_gen}
-
-Visto il ruolo fondamentale che i files vengono ad assumere in un sistema
-unix, è anzitutto opportuno fornire un'introduzione dettagliata su come essi
-vengono trattati dal sistema. In particolare occorre tenere presente dov'è che
-si situa il limite fondamentale fra kernel space e user space che tracciavamo
-al Cap.~\ref{cha:intro_unix}.
-
-Partiamo allora da come viene strutturata nel sistema la disposizione dei
-file: per potervi accedere il kernel usa una apposita interfaccia che permetta
-di strutturare l'informazione tenuta sullo spazio grezzo disponibile sui
-dischi, cioè quello che si chiama un \textit{filesystem}. 
-
-Sarà attraverso quest'ultimo che il kernel andrà a gestire l'accesso ai dati
-memorizzati all'interno del disco stesso, strutturando l'informazione in files
-e directory.  Per poter accedere ai file contenuti in un disco occorrerà
-perciò attivare il filesystem, questo viene fatto \textsl{montando} il disco
-(o la partizione del disco).
-
-%In generale un filesystem piazzerà opportunamente sul disco dei blocchi di
-%informazioni riservate che tengono conto degli inodes allocati, di quelli
-%liberi, e delle posizioni fisiche su disco dei dati contenuti nei files, per
-
-In Unix, a differenza di quanto avviene in altri sistemi operativi, tutti i
-file vengono tenuti all'interno di un unico albero la cui radice (la directory
-di \textit{root}) viene montata all'avvio. Pertanto un file viene identificato
-dall'utente usando quello che viene chiamato \textit{pathname}, cioè il
-percorso completo che si deve fare a partire dalla radice, per accedere al
-file.
-
-Dopo la fase di inizializzazione il kernel riceve dal boot loader
-l'indicazione di quale dispositivo contiene il filesystem da usare come punto
-di partenza e questo viene montato come radice dell'albero (cioè nella
-directory \texttt{/}); tutti gli ulteriori dischi devono poi essere inseriti
-nell'albero utilizzando opportune subdirectory.
-
-Alcuni filesystem speciali (come \texttt{/proc} che contiene un'interfaccia ad
-alcune strutture interne del kernel) sono generati automaticamente dal kernel
-stesso, ma anche essi devono essere montati all'interno dell'albero.
-
-All'interno dello stesso albero si potranno poi inserire anche gli altri
-oggetti visti attraverso l'interfaccia che manipola i files come le FIFO, i
-link, i socket e gli stessi i file di dispositivo (questi ultimi, per
-convenzione, sono inseriti nella directory \texttt{/dev}).
-
-\subsection{Il \textit{virtual filesystem} di linux}
-\label{sec:file_vfs}
-
-Esamineremo adesso come viene implementato l'accesso ai files in linux. Questa
-sezione riporta informazioni sui dettagli di come il kernel gestisce i files,
-ed è basata sul documento di Richard Goochs distribuito coi sorgenti del
-kernel (\texttt{linux/Documentation/vfs.txt}).
-
-L'argomento è abbastanza ``esoterico'' e questa sezione può essere saltata ad
-una prima lettura; è bene però tenere presente che vengono introdotti qui
-alcuni termini che potranno comparire in seguito, come \textit{inode},
-\textit{dentry}, \textit{dcache}.
-
-In linux il concetto di \textit{everything is a file} è stato implementato
-attraverso il \textit{virtual filesystem} (da qui in avanti VFS) che è
-l'interfaccia astratta che il kernel rende disponibile ai programmi in user
-space attraverso la quale vengono manipolati i files, esso provvede anche
-un'astrazione delle operazioni di manipolazione sui files che permette la
-coesistenza di diversi filesystem all'interno dello stesso kernel.
-
-La funzione più importante implementata dal VFS è la system call \texttt{open}
-che permette di aprire un file. Dato un pathname viene eseguita una ricerca
-dentro la \textit{directory entry cache} (in breve \textit{dcache}) che è
-una tabella di hash che contiene tutte le \textit{directory entry} (in breve
-\textit{dentry}) che permette di associare in maniera rapida ed efficiente il
-pathname a una specifica dentry.
-
-Una singola dentry contiene in genere il puntatore ad un \textit{inode};
-quest'ultimo è la struttura base che sta sul disco e che identifica un singolo
-oggetto del VFS sia esso un file ordinario, una directory, una FIFO, un file
-di dispositivo, o una qualsiasi altra cosa che possa essere rappresentata dal
-VFS (sui tipi di ``files'' possibili torneremo in seguito).
-
-Le dentries ``vivono'' in memoria e non vengono mai salvate su disco, vengono
-usate per motivi di velocità, gli inodes invece stanno su disco e vengono
-copiati in memoria quando serve, ed ogni cambiamento viene copiato
-all'indietro sul disco, gli inodes che stanno in memoria sono inodes del VFS
-ed è ad essi che puntano le singole dentry.
-
-La dcache costituisce perciò una sorta di vista completa di tutto l'albero dei
-files, ovviamente per non riempire tutta la memoria questa vista è parziale
-(la dcache cioè contiene solo le dentry per i file per i quali è stato
-richiesto l'accesso), quando si vuole risolvere un nuovo pathname il VFS deve
-creare una nuova dentry e caricare l'inode corrispondente in memoria. 
-
-Questo procedimento viene eseguito dalla metodo \texttt{lookup()} dell'inode
-della directory che contiene il file; esso viene installato dallo specifico
-filesystem su cui l'inode va a vivere.
-
-Una volta che il VFS ha a disposizione la dentry (ed il relativo inode)
-diventa possibile accedere a operazioni sul file come la \texttt{open} per
-aprire il file o la \texttt{stat} per leggere i dati dell'inode e passarli in
-user space.
-
-L'apertura di un file richiede comunque un'altra operazione, l'allocazione di
-una struttura di tipo \texttt{file} in cui viene inserito un puntatore alla
-dentry e una struttura \verb|f_ops| che contiene i puntatori ai metodi che
-implementano le operazioni disponibili sul file. In questo modo i processi in
-user space possono accedere alle operazioni attraverso detti metodi, che
-saranno diversi a seconda del tipo di file (o dispositivo) aperto. Un elenco
-delle operazioni disponibili è riportato in \ntab.
-
-\begin{table}[htb]
-  \centering
-  \begin{tabular}[c]{c p{7cm}}
-    \textbf{funzione} & \textbf{operazione} \\
-    \hline
-    \textit{open}    & apre il file \\
-    \textit{read}    & legge dal file \\
-    \textit{write}   & scrive sul file \\ 
-    \textit{llseek}  & sposta la posizione corrente sul file \\
-    \textit{ioctl}   & accede alle operazioni di controllo 
-                       (tramite la \texttt{ioctl})\\
-    \textit{readdir} & per leggere il contenuto di una directory \\
-    \textit{poll}    & \\
-    \textit{mmap}    & chiamata dalla system call \texttt{mmap}. 
-                       mappa il file in memoria\\
-    \textit{release} & chiamata quando l'ultima referenza a un file 
-                       aperto è chiusa\\
-    \textit{fsync}   & chiamata dalla system call \texttt{fsync} \\
-    \textit{fasync}  & chiamate da \texttt{fcntl} quando è abilitato 
-                       il modo asincrono per l'I/O su file. \\
-    \hline
-  \end{tabular}
-  \caption{Operazioni sui file definite nel VFS.}
-  \label{tab:file_operations}
-\end{table}
-
-In questo modo per ciascun file diventano utilizzabili una serie di operazioni
-(non è dette che tutte siano disponibili), che costituiscono l'interfaccia
-astratta del VFS, e qualora se ne voglia eseguire una il kernel andrà ad
-utilizzare la opportuna routine dichiarata in \verb|f_ops| appropriata al tipo
-di file in questione. 
-
-Così sarà possibile scrivere sulla porta seriale come su un file di dati
-normale; ovviamente certe operazioni (nel caso della seriale ad esempio la
-\textit{seek}) non saranno disponibili, però con questo sistema l'utilizzo di
-diversi filesystem (come quelli usati da Windows o MacOs) è immediato e
-(relativamente) trasparente per l'utente ed il programmatore.
-
-\subsection{Proprietari e permessi}
-\label{sec:file_perms}
-
-In Unix è implementata da qualunque filesystem standard una forma elementare
-(ma adatta alla maggior parte delle esigenze) di controllo di accesso ai
-files. Torneremo sull'argomento in dettaglio più avanti, qui ci limitiamo ad
-una introduzione dei concetti essenziali.
-
-Si tenga conto poi che quanto diremo è vero solo per filesystem di tipo Unix,
-e non è detto che sia applicabile (ed infatti non è vero per il filesystem di
-Windows) a un filesystem qualunque. Esistono inoltre estensioni che permettono
-di implementare le ACL (\textit{Access Control List}) che sono un meccanismo
-di controllo di accesso molto più sofisticato.
-
-Ad ogni file Unix associa sempre l'utente che ne è proprietario (il cosiddetto
-\textit{owner}) e il gruppo di appartenenza, secondo il meccanismo degli uid e
-gid spiegato in \ref{sec:intro_usergroup}, e un insieme di permessi che sono
-divisi in tre classi, e cioè attribuiti rispettivamente al proprietario, a
-qualunque utente faccia parte del gruppo cui appartiene il file, e a tutti gli
-altri utenti.
-
-I permessi sono espressi da un insieme di 12 bit: di questi i nove meno
-significativi sono usati a gruppi di tre per indicare i permessi base di
-lettura, scrittura ed esecuzione (indicati rispettivamente con le lettere
-\textit{w}, \textit{r} \textit{x}) applicabili rispettivamente al
-proprietario, al gruppo, a tutti. I restanti tre bit sono usati per indicare
-alcune caratteristiche più complesse (\textit{suid}, \textit{sgid}, e
-\textit{sticky}) su cui torneremo in seguito.
-
-Tutte queste informazioni sono tenute per ciascun file nell'inode. Quando un
-processo cerca l'accesso al file esso controlla i propri uid e gid
-confrontandoli con quelli del file e se l'operazione richiesta è compatibile
-con i permessi associati al file essa viene eseguita, altrimenti viene
-bloccata ed è restituito un errore di \texttt{EPERM}. Questo procedimento non
-viene eseguito per l'amministratore di sistema (il cui uid è zero) il quale ha
-pertanto accesso senza restrizione a qualunque file del sistema.
-
-In realtà il procedimento è più complesso di quanto descritto in maniera
-elementare qui, in quanto ad un processo sono associati diversi
-identificatori, torneremo su questo in maggiori dettagli in seguito in
-\ref{sec:proc_perms}.
-
-\subsection{I tipi di files}
-\label{sec:file_types}
-
-Come detto in precedenza esistono vari tipi di oggetti implementati del VFS
-per i quali è disponibile l'interfaccia astratta da esso provveduta. Un elenco
-dei vari tipi di file è il seguente:
-\begin{table}[htb]
-  \begin{center}
-    \begin{tabular}[c]{l l p{7cm}}
-    \multicolumn{2}{c}{\textbf{Nome}} & \textbf{Descrizione} \\
-    \hline
-      \textit{regular file} & \textsl{file normale} &
-      un file che contiene dei dati (l'accezione normale di file) \\
-      \textit{directory} & \textsl{cartella o direttorio} &
-      un file che contiene una lista di nomi associati a degli inodes \\
-      \textit{symbolic link} & \textsl{collegamento simbolico} &
-      un file che contiene un riferimento ad un altro file/directory \\
-      \textit{char device} & \textsl{dispositivo a caratteri} &
-      un file che identifica una periferica ad accesso sequenziale \\
-      \textit{block device} & \textsl{dispositivo a blocchi} &
-      un file che identifica una periferica ad accesso diretto \\
-      \textit{fifo} & \textsl{tubo} &
-      un file speciale che identifica una linea di comunicazione software
-      (unidirezionale) \\
-      \textit{socket} & \textsl{manicotto} &
-      un file speciale che identifica una linea di comunicazione software
-      (bidirezionale) \\
-    \hline
-    \end{tabular}
-    \caption{Tipologia dei file definiti nel VFS}
-    \label{tab:file_types}
-  \end{center}
-\end{table}
-
-Tutto ciò non ha ovviamente nulla a che fare con la classificazione sui tipi
-di file (in questo caso file di dati) in base al loro contenuto, o tipo di
-accesso.  Una delle differenze principali con altri sistemi operativi (come il
-VMS o Windows) è che per Unix tutti i file di dati sono identici e contengono
-un flusso continuo di bytes; non esiste cioè differenza per come vengono visti
-dal sistema file di diverso contenuto o formato (come nel caso di quella fra
-file di testo e binari che c'è in windows) né c'è una strutturazione a record
-per il cosiddetto ``accesso diretto'' come nel caso del VMS.
-
-Una seconda differenza è nel formato dei file ascii; in Unix la fine riga è
-codificata in maniera diversa da Windows o MacIntosh, in particolare il fine
-riga è il carattere \texttt{LF} (o \verb|\n|) al posto del \texttt{CR}
-(\verb|\r|) del mac e del \texttt{CR LF} di windows. Questo può causare alcuni
-problemi qualora si facciano assunzioni sul terminatore della riga.
-
-
-\section{Una panoramica sull'uso dei file}
-\label{sec:file_io_base}
-
-Per poter accedere al contenuto dei file occorre anzitutto aprirlo. Questo
-crea un canale di comunicazione che permette di eseguire una serie di
-operazioni. Una volta terminate le operazioni, il file dovrà essere chiuso, e
-questo chiuderà il canale di comunicazione impedendo ogni ulteriore
-operazione.
-
-
-\subsection{Le due interfacce ai file}
-\label{sec:file_base_api}
-
-In unix le modalità di accesso ai file e le relative interfacce di
-programmazione sono due, basate su due diversi meccanismi di connessione. 
-
-La prima è quella dei cosiddetti \textit{file descriptor} (descrittore di
-file), che è specifica di Unix e che provvede un accesso diretto a basso
-livello non bufferizzato, con un'interfaccia primitiva ed essenziale; i file
-descriptors sono rappresentati da numeri interi (cioè semplici variabili di
-tipo \texttt{int}). L'interfaccia è definita nell'header \texttt{unistd.h}.
-
-La seconda è quella degli \textit{stream}, che provvede un'interfaccia più
-evoluta e un accesso bufferizzato. Questa è anche l'interfaccia standard usata
-dal linguaggio C e perciò si trova anche su tutti i sistemi non Unix. Gli
-stream sono oggetti complessi e sono rappresentati da puntatori ad un
-opportuna struttura definita dalle librerie del C, si accede ad essi sempre in
-maniera indiretta utilizzando il tipo \texttt{FILE *}. L'interfaccia è
-definita nell'header \texttt{stdio.h}.
-
-Entrambe le interfacce possono essere usate per l'accesso ai file come agli
-altri oggetti del VFS (pipes, socket, device), ma per poter accedere alle
-operazioni di controllo sul particolare tipo di oggetto del VFS scelto occorre
-usare l'interfaccia a basso livello dei file descriptor. Allo stesso modo
-devono essere usati i file descriptor se si vuole ricorrere a modalità
-speciali di I/O come il polling o il non-bloccante (vedi
-\ref{sec:file_bohhhhh}).
-
-Gli stream forniscono un'interfaccia di alto livello costruita sopra quella
-dei file descriptor, che tratta tutti i file nello stesso modo, con
-l'eccezione di poter scegliere tre diversi stili di bufferizzazione.  Il
-maggior vantaggio degli stream è che l'interfaccia per le operazioni di
-input/output è enormemente più ricca di quella dei file descriptor, che
-provvedono solo funzioni elementari per la lettura/scrittura diretta di
-blocchi di bytes.  In particolare gli stream dispongono di tutte le funzioni
-di formattazione per l'input e l'output adatte per manipolare anche i dati in
-forma di linee o singoli caratteri.
-
-In ogni caso, dato che gli stream sono implementati sopra l'interfaccia a
-basso livello dei file descriptor, è sempre possibile estrarre il file
-descriptor da uno stream ed eseguirvi operazioni di basso livello, o associare
-in un secondo tempo uno stream ad un file descriptor.
-
-In generale, se non necessitano specificatamente le funzionalità di basso
-livello, è opportuno usare sempre gli stream per la loro maggiore portabilità
-essendo questi ultimi definito nello standard ISO C; l'interfaccia con i file
-descriptor invece segue solo lo standard POSIX.1 dei sistemi unix ed è
-pertanto di portabilità più limitata.
-
-\subsection{Caratteristiche specifiche dei file in unix}
-\label{sec:files_spec_unix}
-
-Essendo un sistema multitasking e multiutente esistono alcune caratteristiche
-specifiche di Unix che devono essere tenute in conto nell'accesso ai file. È
-infatti normale che più processi o programmi possano accedere
-contemporaneamente allo stesso file e devono poter eseguire le loro operazioni
-indipendentemente da quello che fanno gli altri processi.
-
-Per questo motivo le strutture usate per all'accesso ai file sono relative al
-processo che effettua l'accesso.  All'apertura di ogni file infatti viene
-creata all'interno del processo una apposita struttura in cui sono memorizzati
-tutti gli attributi del medesimo, che viene utilizzata per tutte le
-operazioni. Questa è una struttura che resta locale al processo stesso; in
-questo modo processi diversi possono usare le proprie strutture locali per
-accedere ai file (che può essere sempre lo stesso) in maniera assolutamente
-indipendente.
-
-Questo ha delle conseguenze di cui è bene tenere conto; ad esempio in tutti i
-sistemi POSIX uno degli attributi di un file aperto è la posizione corrente nel
-file, cioè il punto nel file in cui verrebbe letto o scritto alla operazione
-successiva. Essa è rappresentata da un numero intero che indica il numero di
-bytes dall'inizio del file, che viene (a meno che non si apra il file in
-append) inizializzato a zero all'apertura del medesimo.
-
-Questo è uno dei dati che viene mantenuto nella suddetta struttura, per cui
-ogni processo avrà la sua posizione corrente nel file, che non sarà
-influenzata da quello che altri processi possono fare. Anzi, aprire un file
-significa appunto creare ed inizializzare una tale struttura, per cui se si
-apre due volte lo stesso file all'interno dello stesso processo, si otterrano
-due file descriptor o due stream che avranno ancora una posizione corrente nel
-file assolutamente indipendente.
-
-Si tenga conto inoltre che un'altro dei dati contenuti nella struttura di
-accesso è un riferimento all'inode del file, pertanto anche se il file viene
-cancellato da un altro processo, sarà sempre possibile mantenere l'accesso ai
-dati, e lo spazio su disco non verrà rilasciato fintanto che il file non sarà
-chiuso e l'ultimo riferimento cancellato. È pertanto possibile (e pratica
-comune) aprire un file provvisorio per cancellarlo immediatamente dopo; in
-questo modo all'uscita del programma il file scomparirà definitivamente dal
-disco, ma il file ed il suo contenuto saranno disponibili per tutto il tempo
-in cui il processo è attivo.
-
-
-\subsection{L'accesso ai files: nomi e directory}
-\label{sec:file_names}
-
-L'organizzazione dei nomi dei file deriva direttamente dall'organizzazione dei
-medesimi nella gerarchia di directory descritta in \ref{sec:file_base}; una
-directory comunque, come già specificato in \ref{sec:file_vfs}, è solo un
-particolare tipo di file che il sistema riconosce come tale, che contiene le
-informazioni che associano un inode ad un nome. Per questo, anche se è usuale
-parlare di ``file in una directory'' in realtà una directory contiene solo dei
-riferimenti ai file, non i file stessi.
-
-I nomi contenuti nelle directory sono chiamati componenti (\textit{file name
-  components}), un file può essere indicato rispetto alla directory corrente
-semplicemente specificando il nome da essa contenuto. Una directory contiene
-semplicemente un elenco di questi componenti, che possono corrispondere a un
-qualunque oggetto del filesystem, compresa un'altra directory.
-
-Un nome di file è composto da una serie di \textsl{componenti} separati da una
-\texttt{/} (in linux più \texttt{/} consecutive sono considerate equivalenti
-ad una sola). Il nome completo di un file viene usualmente chiamato
-\textit{filename} o \textit{pathname}, anche se quest'ultimo può generare
-confusione, dato che con \textit{path} si indica anche un insieme di directory
-su cui effettuare una ricerca (ad esempio quello in cui si cercano i comandi).
-
-Il processo con cui si associa ad un pathname uno specifico file (cioè si
-identifica l'inode a cui fare riferimento) è chiamato risoluzione del nome
-(\textit{file name resolution} o \textit{pathname resolution}).
-La risoluzione viene fatta esaminando il pathname da destra a sinistra e
-localizzando ogni componente nella directory indicata dal componente
-precedente: ovviamente perché il procedimento funzioni occorre che i
-componenti indicati come directory esistano e siano effettivamente directory,
-inoltre i permessi devono consentire l'accesso.
-
-Se il pathname comincia per \texttt{/} la ricerca parte dalla directory radice
-del processo che (a meno di un \textit{chroot} su cui torneremo in seguito,
-vedi \ref{sec:file_chroot}) è la stessa per tutti i processi ed equivale alla
-radice dell'albero (\ref{sec:file_gen}): in questo caso si parla di un
-pathname \textsl{assoluto}. Altrimenti la ricerca parte dalla directory
-corrente (su cui pure torneremo più avanti in \ref{sec:file_dir_working}) ed
-il pathname è detto \textsl{relativo}.
-
-I componenti \texttt{.} e \texttt{..} hanno un significato speciale e vengono
-inseriti in ogni directory, il primo fa riferimento alla directory corrente e
-il secondo alla directory \textsl{genitore} (\textit{parent directory}) cioè
-la directory che contiene il riferimento alla directory corrente; nel caso
-questa sia la directory radice allora il riferimento è a se stessa.
-
-Infine si ricordi che in Unix non esistono i tipi di file e che non c'è nessun
-supporto per le estensioni come parte del filesystem. Ciò non ostante molti
-programmi adottano delle convenzioni per i nomi dei file, ad esempio il codice
-C normalmente si mette in file con l'estensione .c, ma questa è, appunto, solo
-una convenzione.
-
-
-\section{L'interfaccia al filesystem}
-\label{sec:file_filesys_interf}
-
-Prima di entrare nei dettagli della manipolazione del contenuto dei file
-esamineremo le funzioni utilizzate per operare sui file piuttosto che sul loro
-contenuto. Le funzioni che esamineremo in questa sezione pertanto sono quelle
-che permettono di esaminare e modificare le directory, rinominare o cancellare
-i file, esaminare o settare i loro attributi.
-
-\subsection{La directory di lavoro}
-\label{sec:file_dir_working}
-
-Come accennato ciascun processo è associato ad una directory nel filesystem
-che è chiamata directory corrente o directory di lavoro (\textit{current
-  working directory}) che è quella a cui si fa riferimento quando un filename
-è espresso in forma relativa (relativa appunto a questa directory).
-
-Quando un utente effettua il login questa directory viene settata alla
-cosiddetta \textit{home directory} del suo account, il comando \texttt{cd}
-della shell consente di cambiarla a piacere, spostandosi da una directory ad
-un'altra.  Siccome la directory corrente resta la stessa quando viene creato
-un processo figlio, la directory corrente della shell diventa anche la
-directory corrente di qualunque comando da essa lanciato.
-
-Le funzioni qui descritte servono esaminare e cambiare la directory di lavoro
-corrente. I prototipi di queste funzioni sono dichiarati in \texttt{unistd.h}. 
-
-\begin{itemize}
-\item \texttt{char * getcwd (char * buffer, size\_t size)}
-  
-  Restituisce il filename completo della directory di lavoro corrente nella
-  stringa puntata da \texttt{buffer}, che deve essere precedentemente
-  allocata, per una dimensione massima di \texttt{size}. Si può anche
-  specificare un puntatore nullo come \textit{buffer}, nel qual caso la
-  stringa sarà allocata automaticamente per una dimensione pari a
-  \texttt{size} qualora questa sia diversa da zero, o della lunghezza esatta
-  del pathname altrimenti. In questo caso si deve ricordare di disallocara la
-  stringa una volta cessato il suo utilizzo.
-  
-  La funzione restituisce il puntatore \texttt{buffer} se riesce,
-  \texttt{NULL} se fallisce, in quest'ultimo caso la variabile
-  \texttt{errno} è settata con i seguenti codici di errore:
-
-  \begin{itemize}
-  \item \texttt{EINVAL} L'argomento \texttt{size} è zero e \texttt{buffer} non
-    è nullo.
-  \item \texttt{ERANGE} L'argomento \texttt{size} è più piccolo della
-    lunghezza del pathname. 
-  \item \texttt{EACCES} Manca il permesso di lettura o di ricerca su uno dei
-    componenti del pathname (cioè su una delle directory superiori alla
-    corrente).
-  \end{itemize}
-\end{itemize}
-
-Di questa funzione esiste una versione \texttt{char * getwd(char * buffer)}
-fatta per compatibilità all'indietro con BSD, che non consente di specificare
-la dimensione del buffer; esso deve essere allocato in precedenza ed avere una
-dimensione superiore a \texttt{PATH\_MAX} (di solito 256 byters, vedi
-\ref{sec:xxxx_limits}; il problema è che in linux non esiste una dimensione
-superiore per un pathname, per cui non è detto che il buffer sia sufficiente a
-contenere il nome del file, e questa è la ragione principale per cui questa
-funzione è deprecata.
-
-Una seconda funzione simile è \texttt{char * get\_current\_dir\_name(void)}
-che è sostanzialmente equivalente ad una \texttt{getcwd(NULL, 0)}, con la sola
-differenza che essa ritorna il valore della variabile di ambiente
-\texttt{PWD}, che essendo costruita dalla shell può contenere anche dei
-riferimenti simbolici.
-
-Come già detto in unix anche le directory sono file, è possibile pertanto
-(come vedremo in \ref{sec:file_dir_access}) riferirsi ad esse tramite il file
-descriptor dell'interfaccia a basso livello, e non solo tramite il filename;
-per questo motivo ci sono due diverse funzioni per cambiare directory di
-lavoro.
-
-\begin{itemize}
-\item \texttt{int chdir (const char * pathname)}
-  
-  Come dice il nome (che significa \textit{change directory}) questa funzione
-  serve a cambiare la directory di lavoro a quella speficata dal pathname
-  contenuto nella stringa \texttt{pathname}.
-  
-\item \texttt{int fchdir (int filedes)} analoga alla precedente, ma usa un
-  file descriptor invece del pathname.
-
-
-  Entrambe le funzioni restituiscono zero in caso di successo e -1 per un
-  errore, in caso di errore \texttt{errno} viene settata secondo i codici di
-  errore standard di accesso ai files (trattati in dettaglio in
-  \ref{sec:file_err_acc}) ai quali si aggiunge il codice \texttt{ENOTDIR} nel
-  caso il \texttt{filename} indichi un file che non sia una directory.
-\end{itemize}
-
-\subsection{Creazione di una directory} 
-\label{sec:file_dir_creat}
-
-Per creare una nuova directory si può usare la seguente funzione, omonima
-dell'analogo comando di shell \texttt{mkdir}; per accedere alla funzioni il
-programma deve includere il file \texttt{sys/stat.h}.
-
-\begin{itemize}
-\item \texttt{char * mkdir (const char * dirname, mode\_t mode)}
-  
-  Questa funzione crea una nuova directory vuota con il nome indicato da
-  \texttt{dirname}, assegnandole i permessi indicati da \texttt{mode}. Il nome
-  può essere indicato con il pathname assoluto o relativo.
-
-  La funzione restituisce zero in caso di successo e -1 per un errore, in caso
-  di errore \texttt{errno} viene settata secondo i codici di errore standard
-  di accesso ai files (trattati in dettaglio in \ref{sec:file_err_acc}) ai
-  quali si aggiungono i seguenti:
-  \begin{itemize}
-  \item \texttt{EACCESS} 
-    Non c'è il permesso di scrittura per la directory in cui si vuole inserire
-    la nuova directory.
-  \item \texttt{EEXIST} Un file (o una directory) con quel nome essite di già. 
-  \item \texttt{EMLINK} La directory in cui si vuole creare la nuova directory
-    contiene troppi file. Sotto linux questo normalmente non avviene perchè il
-    filesystem standard consente la creazione di un numero di file maggiore di
-    quelli che possono essere contenuti nell'hard-disk, ma potendo avere a che
-    fare anche con filesystem di altri sistemi questo errore può presentarsi.
-  \item \texttt{ENOSPC} Non c'è abbastanza spazio sul file system per creare
-    la nuova directory.
-  \item \texttt{EROFS} La directory su cui si vuole inserire la nuova
-    directory è su un filesystem montato readonly.
-  \end{itemize}
-\end{itemize}
-
-\subsection{Accesso alle directory}
-\label{sec:file_dir_access}
-
-Benchè le directory siano oggetti del filesystem come tutti gli altri non ha
-ovviamente senso aprirle come fossero dei file di dati. Può però essere utile
-poterne leggere il contenuto ad esempio per fare la lista dei file che esse
-contengono o ricerche sui medesimi..
-
-Per accedere al contenuto delle directory si usano i cosiddetti
-\textit{directory streams} (chiamati così per l'analogia con i file stream);
-la funzione \texttt{opendir} apre uno di questi stream e la funzione
-\texttt{readdir} legge il contenuto della directory, i cui elementi sono le
-\textit{directory entries} (da distinguersi da quelle della cache di cui
-parlavamo in \ref{sec:file_vfs}) in una opportuna struttura \texttt{struct
-dirent}.
-
-\subsection{I link simbolici e i link diretti}
-\label{sec:file_link}
-
-Una delle caratteristiche più usate quando si opera con i file è quella di
-poter creare dei nomi fittizi (alias o collegamenti) per potersi riferire allo
-stesso file accedendovi da directory diverse. Questo è possibile anche in
-ambiente unix, dove tali collegamenti sono usualmente chiamati \textit{link},
-ma data la struttura del sistema ci sono due metodi sostanzialmente diversi
-per fare questa operazione.
-
-Come si è già accennato nell'introduzione in un sistema unix l'accesso al
-contenuto di un file su disco avviene attraverso il suo \textit{inode}, e il
-nome che si trova in una directory è solo una etichetta associata ad un
-puntatore a detto inode.  Questo significa che la realizzazione di un links è
-immediata in quanto uno stesso file può avere tanti nomi diversi allo stesso
-tempo, dati da altrettante diverse associazioni allo stesso inode; si noti poi
-che nessuno di questi nomi viene ad assumere una particolare preferenza
-rispetto agli altri.
-
-Per aggiungere un nome ad un inode si utilizza la funzione \texttt{link}, e si
-suole chiamare questa associazione un collegamento diretto (o \textit{hard
-  link}).  La creazione di un nuovo link diretto non copia il contenuto del
-file, ma si limita ad aumentare di uno il numero di referenze al file (uno dei
-dati contenuti nell'inode) aggiungendo il nuovo nome ai precedenti. Si noti
-che uno stesso file può essere così richiamato in diverse directory.
-
-Siccome tutto ciò funziona facendo riferimento ad un inode, questa funzione
-può essere applicata soltanto per file che risiedono sullo stesso filesystem,
-(dato che solo in questo caso è garantita l'unicità dell'inode) e solo per
-filesystem di tipo unix. Inoltre in linux non è consentito eseguire un link
-diretto ad una directory.
-
-Per ovviare a queste limitazioni i sistemi unix supportano un'altra forma di
-link (i cosiddetti \textit{soft link} o \textit{symbolic link}), che sono,
-come avviene in altri sistemi operativi, dei file che contengono il
-semplicemente il riferimento ad un altro file (o directory). In questo modo è
-possibile effettuare link anche attraverso filesystem diversi e a directory, e
-pure a file che non esistono ancora.
-
-Il sistema funziona in quanto i link simbolici sono contrassegnati come tali
-al kernel (analogamente a quanto avviene per le directory) per cui la chiamata
-ad una \texttt{open} o una \texttt{stat} su un link simbolico comporta la
-lettura del contenuto del medesimo e l'applicazione della funzione al file
-specificato da quest'ultimo. Invece altre funzioni come quelle per cancellare
-o rinominare i file operano direttamente sul link simbolico. Inoltre esistono
-funzioni apposite, come la \texttt{readlink} e la \texttt{lstat} per accedere
-alle informazioni del link invece che a quelle del file a cui esso fa
-riferimento.
-
-Le funzioni per operare sui link sono le seguenti, esse sono tutte dichiarate
-nell'header file \texttt{unistd.h}.
-
-\begin{itemize}
-\item \texttt{int link(const char * oldname, const char * newname)}
-  
-  Crea un nuovo link diretto al file indicato da \texttt{oldname} dandogli
-  nome \texttt{newname}.
-  
-  La funzione restituisce zero in caso di successo e -1 per un errore, in caso
-  di errore. La variabile \texttt{errno} viene settata secondo i codici di
-  errore standard di accesso ai files (trattati in dettaglio in
-  \ref{sec:file_err_acc}) ai quali si aggiungono i seguenti:
-
-  \begin{itemize}
-  \item \texttt{EXDEV} \texttt{oldname} e \texttt{newname} non sono sullo
-    stesso filesystem.
-  \item \texttt{EPERM} il filesystem che contiene \texttt{oldname} e
-    \texttt{newname} non supporta i link diretti.
-  \item \texttt{EACCESS} 
-    Non c'è il permesso di scrittura per la directory in cui si vuole creare
-    il nuovo link.
-  \item \texttt{EEXIST} Un file (o una directory) con quel nome esiste di
-    già.
-  \item \texttt{EMLINK} Ci sono troppi link al file \texttt{oldname} (il
-    numero massimo è specificato dalla variabile \texttt{LINK\_MAX}, vedi
-    \ref{sec:sys_limits}.
-  \item \texttt{ENOSPC} La directory in cui si vuole creare il link è piena e
-    non può essere ampliata.
-  \item \texttt{EROFS} La directory su cui si vuole inserire il nuovo link è
-    su un filesystem montato readonly.
-  \end{itemize}
-\end{itemize}
-
-
-\begin{itemize}
-\item \texttt{int symlink(const char * oldname, const char * newname)}
-  
-  Crea un nuovo link simbolico al file indicato da \texttt{oldname} dandogli
-  nome \texttt{newname}.
-  
-  La funzione restituisce zero in caso di successo e -1 per un errore, in caso
-  di errore. La variabile \texttt{errno} viene settata secondo i codici di
-  errore standard di accesso ai files (trattati in dettaglio in
-  \ref{sec:file_err_acc}) ai quali si aggiungono i seguenti:
-
-  \begin{itemize}
-  \item \texttt{EEXIST} Un file (o una directory) con quel nome esiste di
-    già.
-  \item \texttt{EROFS} La directory su cui si vuole inserire il nuovo link è
-    su un filesystem montato readonly.
-  \item \texttt{ENOSPC} La directory o il filesystem in cui si vuole creare il
-    link è piena e non c'è ulteriore spazio disponibile.
-  \item \texttt{ELOOP} Ci sono troppi link simbolici nella risoluzione di
-    \texttt{oldname} o di \texttt{newname}.
-  \end{itemize}
-\end{itemize}
-
-
-
-
-\section{L'input/output di basso livello}
-\label{sec:file_lowlev_io}
-%
-% Questa va per ultima. Va bene che e` la più usata, ma è basata sulle altre
-%
-\section{I file stream}
-\label{sec:file_stream}
-
-Esamineremo in questa sezione l'interfaccia per i file stream, le modalità per
-crearli, e le funzioni disponibili per leggere, scrivere e compiere le varie
-operazioni connesse all'uso dei file. L'interfaccia è accessibile includendo
-l'header file \texttt{stdio.h}.
-
-Per ragioni storiche la struttura di dati che rappresenta un stream è stata
-chiamata \texttt{FILE}, questi oggetti sono creati dalle funzioni di libreria
-e contengono tutte le informazioni necessarie a gestire le operazioni sugli
-stream, come la posizione corrente, lo stato del buffer e degli indicatori di
-stato e di fine del file. Per questo motivo gli utenti non devono mai
-utilizzare direttamente o allocare queste strutture, ma usare sempre puntatori
-del tipo \texttt{FILE *} (tanto che in certi caso il termine di puntatore a
-file è diventato sinonimo di stream). 
-
-\subsection{Gli stream standard}
-\label{sec:file_stream_std}
-
-Quando un programma viene lanciato il processo ha sempre tre stream
-predefiniti aperti, che rappresentano i canali standard di input/output
-prestabiliti per il processo; anche questi tre stream sono definiti
-nell'header \texttt{stdio.h} e sono:
-
-\begin{itemize}
-\item \texttt{FILE * stdin} Lo \textit{standard input} cioè lo stream da cui
-  il processo riceve ordinariamente i dati in ingresso. Normalmente è associato
-  dalla shell all'input del terminale e prende i caratteri dalla tastiera.
-\item \texttt{FILE * stdout} Lo \textit{standard input} cioè lo stream su cui
-  il processo invia ordinariamente i dati in uscita. Normalmente è associato
-  dalla shell all'output del terminale e scrive sullo schermo.
-\item \texttt{FILE * stderr} Lo \textit{standard input} cioè lo stream su cui
-  il processo è supposto inviare i messaaggi di errore. Normalmente anch'esso
-  è associato dalla shell all'output del terminale e scrive sullo schermo.
-\end{itemize}
-
-In linux 
-
-
-%La struttura fondamentale che contiene i dati essenziali relativi ai file è il
-%cosiddetto \textit{inode}; questo conterrà informazioni come il
-%tipo di file (file di dispositivo, directory, file di dati, per un elenco
-%completo vedi \ntab), i permessi (vedi \ref{sec:file_perms}), le date (vedi
-%\ref{sec:file_times}).
-
diff --git a/filestd.tex b/filestd.tex
new file mode 100644 (file)
index 0000000..58126b4
--- /dev/null
@@ -0,0 +1,89 @@
+\chapter{I files: l'interfaccia standard C}
+\label{cha:files_std_interface}
+
+%
+% Questa va per ultima. Va bene che e` la più usata, ma è basata sulle altre
+%
+\section{I file stream e gli oggetti \texttt{FILE}}
+\label{sec:filestd_stream}
+
+Esamineremo in questa sezione l'interfaccia per i file stream, le modalità per
+crearli, e le funzioni disponibili per leggere, scrivere e compiere le varie
+operazioni connesse all'uso dei file. L'interfaccia è accessibile includendo
+l'header file \texttt{stdio.h}.
+
+Per ragioni storiche la struttura di dati che rappresenta un stream è stata
+chiamata \texttt{FILE}, questi oggetti sono creati dalle funzioni di libreria
+e contengono tutte le informazioni necessarie a gestire le operazioni sugli
+stream, come la posizione corrente, lo stato del buffer e degli indicatori di
+stato e di fine del file. Per questo motivo gli utenti non devono mai
+utilizzare direttamente o allocare queste strutture, ma usare sempre puntatori
+del tipo \texttt{FILE *} (tanto che in certi caso il termine di puntatore a
+file è diventato sinonimo di stream). 
+
+\subsection{Gli stream standard}
+\label{sec:filestd_stdfiles}
+
+Quando un programma viene lanciato il processo ha sempre tre stream
+predefiniti aperti, che rappresentano i canali standard di input/output
+prestabiliti per il processo; anche questi tre stream sono definiti
+nell'header \texttt{stdio.h} e sono:
+
+\begin{itemize}
+\item \texttt{FILE * stdin} Lo \textit{standard input} cioè lo stream da cui
+  il processo riceve ordinariamente i dati in ingresso. Normalmente è associato
+  dalla shell all'input del terminale e prende i caratteri dalla tastiera.
+\item \texttt{FILE * stdout} Lo \textit{standard input} cioè lo stream su cui
+  il processo invia ordinariamente i dati in uscita. Normalmente è associato
+  dalla shell all'output del terminale e scrive sullo schermo.
+\item \texttt{FILE * stderr} Lo \textit{standard input} cioè lo stream su cui
+  il processo è supposto inviare i messaaggi di errore. Normalmente anch'esso
+  è associato dalla shell all'output del terminale e scrive sullo schermo.
+\end{itemize}
+
+
+\subsection{La bufferizzazione}
+\label{sec:filestd_buffering}
+
+\section{Funzioni base}
+\label{sec:filestd_base_func}
+
+\subsection{Apertura di uno stream}
+\label{sec:filestd_open}
+
+\subsection{Lettura e scrittura su uno stream}
+\label{sec:filestd_io}
+
+\subsection{Posizionamento su uno stream}
+\label{sec:filestd_seek}
+
+\subsection{Input/output binario}
+\label{sec:filestd_binary_io}
+
+\subsection{Input/output di linea}
+\label{sec:filestd_line_io}
+
+\subsection{Input/output formattato}
+\label{sec:filestd_formatted_io}
+
+
+\section{Funzioni avanzate}
+\label{sec:filestd_adv_func}
+
+
+\subsection{Dettagli dell'implementazione}
+\label{sec:filestd_details}
+
+\subsection{File temporanei}
+\label{sec:filestd_details}
+
+\subsection{Efficienza}
+\label{sec:filestd_details}
+
+
+
+
+
+
+
+
diff --git a/fileunix.tex b/fileunix.tex
new file mode 100644 (file)
index 0000000..de5d17d
--- /dev/null
@@ -0,0 +1,53 @@
+\chapter{I files: l'interfaccia I/O di unix}
+\label{cha:file_unix_interface}
+
+
+
+\section{I file descriptors}
+\label{sec:fileunix_fd}
+
+
+\section{Le funzioni base}
+\label{sec:fileunix_base_func}
+
+L'interfaccia standard unix per l'input/output sui file è su cinque funzioni
+\texttt{open}, \texttt{read}, \texttt{write}, \texttt{lseek}, \texttt{close}
+
+
+\subsection{La funzione \texttt{open}}
+\label{sec:fileunix_open}
+
+\subsection{La funzione \texttt{creat}}
+\label{sec:fileunix_creat}
+
+\subsection{La funzione \texttt{lseek}}
+\label{sec:fileunix_lseek}
+
+\subsection{La funzione \texttt{read}}
+\label{sec:fileunix_read}
+
+\subsection{La funzione \texttt{write}}
+\label{sec:fileunix_write}
+
+\section{La condivisione dei files}
+\label{sec:fileunix_sharing}
+
+
+\subsection{Operazioni atomiche}
+\label{sec:fileunix_atomic}
+
+\section{Funzioni avanzate}
+\label{sec:fileunix_adv_func}
+
+\subsection{La funzioni \texttt{dup} e \texttt{dup2}}
+\label{sec:fileunix_dup}
+
+\subsection{La funzione \texttt{fcntl}}
+\label{sec:fileunix_fcntl}
+
+\subsection{La funzione \texttt{fcntl}}
+\label{sec:fileunix_ioctl}
+
+
+
+
index 9dfed96e4beee262b8afccdcbe3d64de6605ead6..deef466b52c9ff4c8076bd18ed93dd0887d4ea86 100644 (file)
--- a/intro.tex
+++ b/intro.tex
@@ -60,12 +60,12 @@ necessario le pagine di memoria in eccedenza.
 
 Le periferiche infine vengono viste in genere attraverso un'interfaccia
 astratta che permette di trattarle come fossero file. secondo il concetto per
-cui \textit{everything is a file}, vedi \ref{sec:file_gen}, (questo non è vero
-per le interfacce di rete, ma resta valido il concetto generale che tutto il
-lavoro di accesso e gestione a basso livello è effettuato dal kernel), mentre
-ai programmi vengono fornite solo delle routine di interfacciamento; essendo
-l'argomento principale di cui tratteremo, di esse parleremo in abbondanza nei
-capitoli successivi.
+cui \textit{everything is a file}, vedi \ref{cha:files_intro}, (questo non è
+vero per le interfacce di rete, ma resta valido il concetto generale che tutto
+il lavoro di accesso e gestione a basso livello è effettuato dal kernel),
+mentre ai programmi vengono fornite solo delle routine di interfacciamento;
+essendo l'argomento principale di cui tratteremo, di esse parleremo in
+abbondanza nei capitoli successivi.
 
 
 \section{User space e kernel space}
@@ -193,7 +193,8 @@ In questo modo il sistema 
 dell'utente a cui appartiene ed impedire ad altri utenti di interferire con
 esso. Inoltre con questo sistema viene anche garantita una forma base di
 sicurezza interna in quanto anche l'accesso ai file (vedi
-\ref{sec:file_perms}) è regolato da questo meccanismo di identificazione.
+\ref{sec:fileintr_access_ctrl}) è regolato da questo meccanismo di
+identificazione.
 
 Un utente speciale del sistema è \textit{root}, il cui uid è zero. Esso
 identifica l'amministratore del sistema, che deve essere in grado di fare
index 1ec26d1f6fca9e1876483a130ab031180beaa7c0..11234560a84e8503818e5056372d50475413ce23 100644 (file)
--- a/main.tex
+++ b/main.tex
@@ -1,6 +1,10 @@
-%
-% File principale: gli altri vanno inclusi da questo.
-% 
+%%
+%% GaPiL : Guida alla Programmazione in Linux
+%%
+%% S. Piccardi Feb. 2001
+%%
+%% main.tex: file principale, gli altri vanno inclusi da questo.
+%% 
 \documentclass[a4paper,11pt,twoside,italian]{book}
 \usepackage[latin1]{inputenc}
 \usepackage{graphicx}
 }
 
 \include{intro}
-\include{files}
+\include{fileintro}
+\include{filedir}
+\include{fileunix}
+\include{filestf}
 \include{process}
 \include{option}
 \include{signal}
 \include{network}
 \include{socket}
 \include{elemtcp}
+\include{app_a}
+\include{app_b}
 \include{fdl}
+
  
 % at the end put the bibliography
 
index 7d1d053d6c8c1e66f039f7b8e2e0f41cbaa8ecd9..fc54b79aadf6ef4b4a1159387c9ec67da4ae315f 100644 (file)
@@ -635,8 +635,8 @@ grandi linee nei seguenti punti:
   multimediali e/o ``real-time'')
 \end{itemize}
 
-Per maggiori dettagli riguardo al protocollo si può consultare
-\ref{sec:appA_ip}.
+Maggiori dettagli riguardo a caratteristiche, notazioni e funzionamento del
+protocollo IP sono forniti nell'appendice \ref{cha:ip_protocol}.
 
  
 \subsection{UDP: User Datagram Protocol)}
@@ -745,3 +745,5 @@ stesso tempo, il che poi comporta che quanto dicevamo a proposito del
 controllo di flusso e della gestione della sequenzialità dei dati viene
 effettuato per entrambe le direzioni di comunicazione.
 
+Una descrizione più accurata del protocollo è fornita in appendice
+\ref{cha:tcp_protocol}.
\ No newline at end of file
index 09e67032993948e4907a973ea79df3e9ceb82f9d..c1fc583863e811e50ac271fe79d68ce145338e32 100644 (file)
@@ -7,6 +7,14 @@ viene posto in esecuzione, viene fatto partire un processo che si incarica di
 eseguirne il codice. In sostanza i processi costituiscono l'unità base per
 l'allocazione e l'uso delle risorse del sistema.
 
+In questo capitolo affronteremo i dettagli della creazione e della distruzione
+dei processi, della gestione dei loro attributi e privilegi, e di tutte le
+funzioni a questo connesse.
+
+
+\section{Una panoramica sui concetti base}
+\label{sec:proc_gen}
+
 Una delle caratteristiche essenziali di unix (che esamineremo in dettaglio più
 avanti) è che ogni processo può a sua volta generare altri processi figli
 (\textit{child}): questo è ad esempio quello che fa la shell quando mette in
@@ -23,8 +31,8 @@ gerarchicamente dalla relazione fra genitori e figli; alla base dell'albero in
 questo caso c'è init che è progenitore di ogni altro processo.
 
 
-\section{Una panoramica sui concetti base}
-\label{sec:proc_gen}
+\section{Gli identificatori dei processi}
+\label{sec:proc_id}
 
 Ogni processo viene identificato dal sistema da un numero identificativo
 unico, il \textit{process id} o \textit{pid}. Questo viene assegnato in forma
@@ -34,25 +42,43 @@ arriva a 32767) oltre il quale si riparte dal numero pi
 (FIXME: verificare, non sono sicuro).  Per questo motivo processo il processo
 di avvio (init) ha sempre il pid uguale a uno.
 
-Quando un processo ha concluso il suo compito o ha incontrato un errore non
-risolvibile esso può essere terminato con la funzione \texttt{exit} (la
-questione è più complessa ma ci torneremo più avanti). La vita del processo
-però termina solo quando viene chiamata la quando la sua conclusione viene
-ricevuta dal processo padre, a quel punto tutte le risorse allocate nel
-sistema ad esso associate vengono rilasciate.
+Ogni processo è identificato univocamente dal sistema per il suo
+pid; quest'ultimo è un apposito tipo di dato, il \texttt{pid\_t} che in
+genere è un intero con segno (nel caso di Linux e delle glibc il tipo usato è
+\texttt{int}.
+
+Tutti i processi inoltre portano traccia del pid del genitore, chiamato in
+genere \textit{ppid} (da \textit{Parente Process Id}). Questi identificativi
+possono essere ottenuti da un programma usando le funzioni:
+\begin{itemize} 
+  \item \texttt{pid\_t getpid(void)} restituisce il pid del processo corrente.
+    
+  \item \texttt{pid\_t getppid(void)} restituisce il pid del padre del processo
+    corrente.
+
+\end{itemize}
+(per l'accesso a queste funzioni e ai relativi tipi di dati occorre includere
+gli header files \texttt{unistd.h} e \texttt{sys/types.h}). 
+
+
+
+\section{Il controllo dei processi}
+\label{sec:proc_control}
+
+Esamineremo in questa sezione le varie funzioni per il controllo dei processi:
+la lore creazione, la terminazione, l'esecuzione di altri programmi. Prima di
+trattare in dettaglio le singole funzioni, faremo un'introduzione generale ai
+contetti che stanno alla base della gestione dei processi in unix.
+
+\subsection{Una panoramica}
+\label{sec:proc_control_overview}
 
 I processi vengono creati dalla funzione \texttt{fork}; in genere questa è una
-system call, Linux però usa un'altra nomenclatura, e la funzione fork è basata
-a sua volta sulla system call \texttt{clone}, che viene usata anche per
+system call, ma linux però usa un'altra nomenclatura, e la funzione fork è
+basata a sua volta sulla system call \texttt{clone}, che viene usata anche per
 generare i \textit{thread}.  Il processo figlio creato dalla \textit{fork} è
-una copia identica del processo processo padre, solo che ha un suo pid proprio.
-
-Dopo l'esecuzione di una fork sia il processo padre che il processo figlio
-continuano ad essere eseguiti normalmente, ed il processo figlio esegue
-esattamente lo stesso codice del padre. La sola differenza è che nel processo
-padre il valore di ritorno della funzione fork è il pid del processo figlio,
-mentre nel figlio è zero; in questo modo il programma può identificare se
-viene eseguito dal padre o dal figlio. 
+una copia identica del processo processo padre, solo che ha un suo pid
+proprio.
 
 Se si vuole che il processo padre si fermi fino alla conclusione del processo
 figlio questo deve essere specificato subito dopo la fork chiamando la
@@ -60,6 +86,13 @@ funzione \texttt{wait} o la funzione \texttt{waitpid}, che restituiscono anche
 una informazione abbastanza limitata (il codice di uscita) sulle cause della
 terminazione del processo.
 
+Quando un processo ha concluso il suo compito o ha incontrato un errore non
+risolvibile esso può essere terminato con la funzione \texttt{exit} (la
+questione è più complessa ma ci torneremo più avanti). La vita del processo
+però termina solo quando viene chiamata la quando la sua conclusione viene
+ricevuta dal processo padre, a quel punto tutte le risorse allocate nel
+sistema ad esso associate vengono rilasciate.
+
 Avere due processi che eseguono esattamente lo stesso codice non è molto
 utile, mormalmente si genera un secondo processo per affidagli l'esecuzione di
 un compito specifico (ad esempio gestire una connessione dopo che questa è
@@ -68,8 +101,8 @@ questo si usa la seconda funzione fondamentale per programmazione coi processi
 che è la \texttt{exec}.
 
 Il programma che un processo sta eseguendo si chiama immagine del processo
-(\textit{process image}), le funzioni della famiglia \textit{exec} permette di
-caricare un'altro programma da disco sostituendo quest'ultimo alla process
+(\textit{process image}), le funzioni della famiglia \textit{exec} permettono
+di caricare un'altro programma da disco sostituendo quest'ultimo alla process
 image corrente, questo fa si che la precedente immagine venga completamente
 cancellata e quando il nuovo programma esce anche il processo termina, senza
 ritornare alla precedente immagine.
@@ -77,38 +110,41 @@ ritornare alla precedente immagine.
 Per questo motivo la \texttt{fork} e la \texttt{exec} sono funzioni molto
 particolari con caratteristiche uniche rispetto a tutte le altre, infatti la
 prima ritorna due volte (nel processo padre e nel figlio) mentre la seconda
-non ritorna mai (in quanto viene eseguito un altro programma).
+non ritorna mai (in quanto con essa viene eseguito un altro programma).
 
 
-\section{Identificazione}
-\label{sec:proc_id}
+\subsection{La funzione \texttt{fork}}
+\label{sec:proc_fork}
 
-Come detto ogni processo è identificato univocamente dal sistema per il suo
-pid; quest'ultimo è un apposito tipo di dato, il \texttt{pid\_t} che in
-genere è un intero con segno (nel caso di Linux e delle glibc il tipo usato è
-\texttt{int}.
 
-Tutti i processi inoltre portano traccia del pid del genitore, chiamato in
-genere \textit{ppid} (da \textit{Parente Process Id}). Questi identificativi
-possono essere ottenuti da un programma usando le funzioni:
-\begin{itemize} 
-  \item \texttt{pid\_t getpid(void)} restituisce il pid del processo corrente.
-    
-  \item \texttt{pid\_t getppid(void)} restituisce il pid del padre del processo
-    corrente.
+Dopo l'esecuzione di una fork sia il processo padre che il processo figlio
+continuano ad essere eseguiti normalmente, ed il processo figlio esegue
+esattamente lo stesso codice del padre. La sola differenza è che nel processo
+padre il valore di ritorno della funzione fork è il pid del processo figlio,
+mentre nel figlio è zero; in questo modo il programma può identificare se
+viene eseguito dal padre o dal figlio. 
+
 
-\end{itemize}
-(per l'accesso a queste funzioni e ai relativi tipi di dati occorre includere
-gli header files \texttt{unistd.h} e \texttt{sys/types.h}. 
 
 
-\section{Provilegi e permessi}
+\subsection{La funzione \texttt{exit}}
+\label{sec:proc_exit}
+
+\subsection{Le funzioni \texttt{wait} e  \texttt{waitpid}}
+\label{sec:proc_wait}
+
+\subsection{Le funzioni \texttt{exec}}
+\label{sec:proc_exec}
+
+
+
+
+
+
+\section{Il controllo di accesso}
 \label{sec:process_perms}
 
 Va messo qui tutta la storia su effective, real, saved uid, e pure le cose di
 linux come il filesystem uid.
 
 
-
-\section{Creazione dei processi}
-\label{sec:proc_fork}
index 420913fdbe5e266bdf4415d5ad107980f1df1510..05b1af6bf0f21bea7fd7d297744e4c002972e072 100644 (file)
@@ -175,11 +175,10 @@ glibc chiama \textit{styles}) definiti come \texttt{int} in \texttt{socket.h}:
 \item \texttt{SOCK\_STREAM} Provvede un canale di trasmissione dati
   bidirezionale, sequenziale e affidabile. Opera su una connessione con un
   altro socket. I dati vengono ricevuti e trasmessi come un flusso continuo di
-  byte (da cui il nome \textit{stream}). Vedi \ref{sec:sock_stream}.
+  byte (da cui il nome \textit{stream}). 
 \item \texttt{SOCK\_DGRAM} Viene usato per mandare pacchetti di lunghezza
   massima fissata (\textit{datagram}) indirizzati singolarmente, senza
-  connessione e in maniera non affidabile. È l'opposto del precedente. Vedi
-  \ref{sec:sock_dgram}.
+  connessione e in maniera non affidabile. È l'opposto del precedente. 
 \item \texttt{SOCK\_SEQPACKET} Provvede un canale di trasmissione di dati
   bidirezionale, sequenziale e affidabile. Opera su una connessione con un
   altro socket. I dati possono solo essere trasmessi e letti per pacchetti (di
@@ -277,7 +276,7 @@ struct sockaddr {
 };
   \end{lstlisting}
   \caption{La struttura generica degli indirizzi dei socket \texttt{sockaddr}}
-  \label{fig:sock_sa_struct}
+  \label{fig:sock_sa_gen_struct}
 \end{figure}
 
 Tutte le funzioni dei socket che usano gli indirizzi sono definite usando nel
@@ -361,7 +360,7 @@ struct in_addr {
   \end{lstlisting}
   \caption{La struttura degli indirizzi dei socket internet (IPv4)
     \texttt{sockaddr\_in}.}
-  \label{fig:sock_sa_struct}
+  \label{fig:sock_sa_ipv4_struct}
 \end{figure}
 
 L'indirizzo di un socket internet (secondo IPv4) comprende l'indirizzo
@@ -415,7 +414,7 @@ struct in6_addr {
   \end{lstlisting}
   \caption{La struttura degli indirizzi dei socket IPv6 
     \texttt{sockaddr\_in6}.}
-  \label{fig:sock_sa_struct}
+  \label{fig:sock_sa_ipv6_struct}
 \end{figure}
 
 Il campo \texttt{sin6\_family} deve essere sempre settato ad
@@ -456,7 +455,7 @@ struct sockaddr_un {
   \end{lstlisting}
   \caption{La struttura degli indirizzi dei socket locali 
     \texttt{sockaddr\_un}.}
-  \label{fig:sock_sa_struct}
+  \label{fig:sock_sa_local_struct}
 \end{figure}
 
 In questo caso il campo \texttt{sun\_family} deve essere \texttt{AF\_UNIX},