From: Simone Piccardi Date: Sat, 30 Jun 2001 14:44:39 +0000 (+0000) Subject: Ristrutturati capitoli sui file X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=commitdiff_plain;h=7f82a673d95054cd295c8743606cfa8aa249e731 Ristrutturati capitoli sui file --- diff --git a/filedir.tex b/filedir.tex index cf928fc..daf947a 100644 --- a/filedir.tex +++ b/filedir.tex @@ -1,464 +1,14 @@ \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 come è strutturato il +In questo capitolo tratteremo in dettaglio le modalità con cui si gestiscono +files e directories, ed in particolare esamineremo 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 è lasciato ai capitoli successivi. -\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 \secref{sec:fileintr_overview}; -una directory comunque, come già specificato in \secref{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 delle etichette per fare -riferimento ai file stessi. - -I manuale delle librerie del C chiama i nomi contenuti nelle directory -\textsl{componenti} (in inglese \textit{file name components}), noi li -chiameremo più semplicemente nomi. Un file può essere indicato rispetto alla -directory corrente semplicemente specificando il nome da essa contenuto. Una -directory contiene semplicemente un elenco di questi nomi, 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 completo di file generico è composto da una serie di questi -\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 è 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 nome nella directory indicata dal nome -precedente: ovviamente perché il procedimento funzioni occorre che i nomi -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 \secref{sec:xxx_chroot}) è la stessa per tutti i processi ed -equivale alla directory radice dell'albero (come descritto in -\secref{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 \secref{sec:filedir_work_dir}) ed il pathname è -detto \textsl{relativo}. - -I nomi \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{L'architettura della gestione dei file} -\label{sec:filedir_file_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 sulla gestione dei medesimo e sugli oggetti su cui è basato -un filesystem unix; in particolare si riprenderà, approfondendolo sul piano -dell'uso nelle funzioni di libreria, il concetto di \textit{inode} di cui -abbiamo brevemente accennato le caratteristiche (dal lato dell'implementazione -nel kernel) in \secref{sec:fileintr_vfs}. - - -\subsection{Il funzionamento di un filesystem unix} -\label{sec:filedir_filesystem} - -Come già accennato in \secref{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 a -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 di un -singolo filesystem (tralasciando le parti connesse alla strutturazione e al -funzionamento del filesystem stesso 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} -da questa figura si evidenziano alcune caratteristiche 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{enumerate} - -\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'\textit{inode}; dentro una directory - si troverà solo il nome del file e il numero dell'\textit{inode} ad esso - associato, cioè quella che da qui in poi chiameremo una \textsl{voce} - (traduzione approssimata dell'inglese \textit{directory entry}, che non - useremo anche per evitare confusione con le \textit{dentries} del kernel di - cui si parlava in \secref{sec:fileintr_vfs}). - -\item Come mostrato in \curfig si possono avere più voci che puntano allo - stesso \textit{inode}. Ogni \textit{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 i dati del file vengono - effettivamente rimossi dal disco. Per questo la funzione per cancellare un - file si chiama \texttt{unlink}, ed in realtà non cancella affatto i dati del - file, ma si limita a eliminare la relativa voce da una directory e - decrementare il numero di riferimenti nell'\textit{inode}. - -\item Il numero di \textit{inode} nella voce si riferisce ad un \textit{inode} - nello stesso filesystem e non ci può essere una directory che contiene - riferimenti ad \textit{inodes} relativi ad altri filesystem. Questo limita - l'uso del comando \texttt{ln} (che crea una nuova voce 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, viene semplicemente creata una nuova voce - per l'\textit{inode} in questione e rimossa la vecchia (questa è la modalità - in cui opera normalmente il comando \texttt{mv} attraverso la funzione - \texttt{rename}). - -\end{enumerate} - -Infine è bene avere presente che essendo file pure loro, esiste un numero di -riferimenti anche per le directories; per cui se ad esempio a partire dalla -situazione mostrata in \curfig\ creiamo una nuova directory \texttt{textdir} -nella directory corrente 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 voce che fa riferimento a \texttt{textdir}) e dalla voce \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 voce \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 detto l'accesso al contenuto di un file su disco avviene -attraverso il suo 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}). Il prototipo della funzione e le sue caratteristiche -principali, come risultano dalla man page, sono le seguenti: -\begin{prototype}{unistd.h} -{int link(const char * oldpath, const char * newpath)} - Crea un nuovo collegamento diretto al file indicato da \texttt{oldpath} - dandogli nome \texttt{newpath}. - - 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 seguenti - codici di errore: - \begin{errlist} - \item \texttt{EXDEV} \texttt{oldpath} e \texttt{newpath} non sono sullo - stesso filesystem. - \item \texttt{EPERM} il filesystem che contiene \texttt{oldpath} e - \texttt{newpath} non supporta i link diretti o è una directory. - \item \texttt{EFAULT} una delle stringhe passate come parametri è fuori - dello spazio di indirizzi del processo. - \item \texttt{EACCESS} errore di accesso (mancano i permessi per scrivere o - per attraversare le directories), vedi \secref{sec:filedir_access_control} - per i dettagli. - \item \texttt{ENAMETOOLONG} una dei due pathname è troppo lungo. - \item \texttt{ENOENT} un componente di \texttt{oldpath} o \texttt{newpath} - non esiste o è un link simbolico spezzato. - \item \texttt{ENOTDIR} un componente di \texttt{oldpath} o \texttt{newpath} - non è una directory. - \item \texttt{ENOMEM} il kernel non ha a disposizione memoria sufficiente a - completare l'operazione. - \item \texttt{EROFS} la directory su cui si vuole inserire il nuovo link è - su un filesystem montato readonly. - \item \texttt{EEXIST} un file (o una directory) con quel nome esiste di - già. - \item \texttt{EMLINK} ci sono troppi link al file \texttt{oldpath} (il - numero massimo è specificato dalla variabile \texttt{LINK\_MAX}, vedi - \secref{sec:xxx_limits}). - \item \texttt{ELOOP} si incontrati troppi link simbolici nella risoluzione - di \texttt{oldpath} o \texttt{newpath}. - \item \texttt{ENOSPC} la directory in cui si vuole creare il link non ha - spazio per ulteriori voci. - \item \texttt{EIO} c'è stato un errore di input/output. - \end{errlist} -\end{prototype} - -La creazione di un nuovo collegamento 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. - -Per quanto dicevamo in \secref{sec:filedir_filesystem} la creazione del -collegamento diretto è possibile solo se entrambi i pathname sono nello stesso -filesystem; inoltre il filesystem deve supportare i collegamenti diretti (non è -il caso ad esempio del filesystem \texttt{vfat} di windows). - -La funzione opera sui file ordinari, come sugli altri oggetti del filesystem, -ma solo l'amministratore è in grado di creare un collegamento diretto ad -un'altra directory, questo lo si fa perché in questo caso è possibile creare -dei circoli nel filesystem (vedi \secref{sec:filedir_symlink}) che molti -programmi non sono in grado di gestire e la cui rimozione diventa estremamente -complicata (in genere occorre far girare il programma \texttt{fsck} per -riparare il filesystem); data la sua pericolosità in Linux questa -caratteristica è stata disabilitata, e la funzione restituisce l'errore -\texttt{EPERM}. - -La rimozione di un file (o più precisamente della voce che lo referenzia) si -effettua con la funzione \texttt{unlink}; il suo prototipo è il seguente: - -\begin{prototype}{unistd.h}{int unlink(const char * pathname)} - Cancella il nome specificato dal pathname nella relativa directory e - decrementa il numero di riferimenti nel relativo inode. Nel caso di link - simbolico cancella il link simbolico; nel caso di socket, fifo o file di - dispositivo rimuove il nome, ma come per i file i processi che hanno aperto - uno di questi oggetti possono continuare ad utilizzarlo. - - La funzione restituisce zero in caso di successo e -1 per un errore, nel - qual caso il file non viene toccato. La variabile \texttt{errno} viene - settata secondo i seguenti codici di errore: - \begin{errlist} - \item \texttt{EACCESS} errore di accesso (mancano i permessi per scrivere o - per attraversare le directories), vedi \secref{sec:filedir_access_control} - per i dettagli. - \item \texttt{EISDIR} \texttt{pathname} si riferisce ad una directory - (valore specifico ritornato da linux che non consente l'uso di - \texttt{unlink} con le directory, e non conforme allo standard POSIX, che - prescrive invece l'uso di \texttt{EPERM} in caso l'operazione non sia - consnetita o il processo non abbia privilegi sufficienti). - \item \texttt{EFAULT} la stringa - passata come parametro è fuori dello spazio di indirizzi del processo. - \item \texttt{ENAMETOOLONG} il pathname troppo lungo. - \item \texttt{ENOENT} uno dei componenti del pathname non esiste o è un link - simbolico spezzato. - \item \texttt{ENOTDIR} uno dei componenti del pathname non è una directory. - \item \texttt{EISDIR} \texttt{pathname} fa riferimento a una directory. - \item \texttt{ENOMEM} il kernel non ha a disposizione memoria sufficiente a - completare l'operazione. - \item \texttt{EROFS} \texttt{pathname} è su un filesystem montato in sola - lettura. - \item \texttt{ELOOP} ci sono troppi link simbolici nella risoluzione del - pathname. - \item \texttt{EIO} errore di input/output. - \end{errlist} -\end{prototype} - -Per cancellare una voce in una directory è necessario avere il permesso di -scrittura su di essa (dato che si va a rimuovere una voce dal suo contenuto) e -il diritto di esecuzione sulla directory che la contiene (torneremo in -dettaglio sui permessi e gli attributi fra poco), se inoltre lo -\textit{sticky} bit è settato occorrerà anche essere proprietari del file o -proprietari della directory (o root, per cui nessuna delle restrizioni è -applicata). - -Una delle caratteristiche di queste funzioni è che la creazione/rimozione -della nome dalla directory e l'incremento/decremento del numero di riferimenti -nell'inode deve essere una operazione atomica (cioè non interrompibile da -altri) processi, per questo entrambe queste funzioni sono realizzate tramite -una singola system call. - -Si ricordi infine che il file non viene eliminato dal disco fintanto che tutti -i riferimenti ad esso sono stati cancellati, solo quando il \textit{link - count} mantenuto nell'inode diventa zero lo spazio occupato viene rimosso. A -questo però si aggiunge una altra condizione, e cioè che non ci siano processi -che abbiano detto file aperto. Come accennato questa proprietà viene spesso -usata per essere sicuri di non lasciare file temporanei su disco in caso di -crash dei programmi; la tecnica è quella di aprire il file e chiamare -\texttt{unlink} subito dopo. - -\subsection{Le funzioni \texttt{remove} e \texttt{rename}} -\label{sec:filedir_cre_canc} - -Al contrario di quanto avviene con altri unix in Linux non è possibile usare -\texttt{unlink} sulle directory, per cancellare una directory si può usare la -funzione \texttt{rmdir} (vedi \secref{sec:filedir_dir_creat_rem}), oppure la -funzione \texttt{remove}. Questa è la funzione prevista dallo standard ANSI C -per cancellare un file o una directory (e funziona anche per i sistemi che non -supportano i link diretti), che per i file è identica alla \texttt{unlink} e -per le directory è identica alla \texttt{rmdir}: - -\begin{prototype}{stdio.h}{int remove(const char *pathname)} - Cancella un nome dal filesystem. Usa \texttt{unlink} per i file e - \texttt{rmdir} per le directory. - - La funzione restituisce zero in caso di successo e -1 per un errore, nel - qual caso il file non viene toccato. Per i codici di errori vedi quanto - riportato nella descrizione di \texttt{unlink} e \texttt{rmdir}. -\end{prototype} - -Per cambiare nome ad un file si usa invece la funzione \texttt{rename}, il -vantaggio nell'uso di questa funzione al posto della chiamata successiva di -\texttt{unlink} e \texttt{link} è che l'operazione è eseguita atomicamente, in -questo modo non c'è la possibilità che un processo che cerchi di accedere al -nuovo nome dopo che il vecchio è stato cambiato lo trovi mancante. - -\begin{prototype}{stdio.h} -{int rename(const char *oldpath, const char *newpath)} - Rinomina un file, spostandolo fra directory diverse quando richiesto. - - La funzione restituisce zero in caso di successo e -1 per un errore, nel - qual caso il file non viene toccato. La variabile \texttt{errno} viene - settata secondo i seguenti codici di errore: - \begin{errlist} - \item \texttt{EISDIR} \texttt{newpath} è una directory già esistente mentre - \texttt{oldpath} non è una directory. - \item \texttt{EXDEV} \texttt{oldpath} e \texttt{newpath} non sono sullo - stesso filesystem. - \item \texttt{ENOTEMPTY} \texttt{newpath} è una directory già esistente e - non vuota. - \item \texttt{EBUSY} o \texttt{oldpath} o \texttt{newpath} sono in uso da - parte di qualche processo (come directory di lavoro o come root) o del - sistema (come mount point). - \item \texttt{EINVAL} \texttt{newpath} contiene un prefisso di - \texttt{oldpath} o più in generale si è cercato di creare una directory - come sottodirectory di se stessa. - \item \texttt{EMLINK} \texttt{oldpath} ha già il massimo numero di link - consentiti o è una directory e la directory che contiene \texttt{newpath} - ha già il massimo numero di link. - \item \texttt{ENOTDIR} Uno dei componenti dei pathname non è una directory - o\texttt{oldpath} è una directory e \texttt{newpath} esiste e non è una - directory. - \item \texttt{EFAULT} o \texttt{oldpath} o \texttt{newpath} è fuori dello - spazio di indirizzi del processo. - \item \texttt{EACCESS} Non c'è il permesso di scrittura per la directory in - cui si vuole creare il nuovo link o una delle directory del pathname non - consente la ricerca (permesso di esecuzione). - \item \texttt{EPERM} le directory contenenti \texttt{oldpath} o - \texttt{newpath} hanno lo sticky bit attivo e i permessi del processo non - consentono rispettivamente la cancellazione e la creazione del file, o il - filesystem non supporta i link. - \item \texttt{ENAMETOOLONG} uno dei pathname è troppo lungo. - \item \texttt{ENOENT} Uno dei componenti del pathname non esiste o è un link - simbolico spezzato. - \item \texttt{ENOMEM} il kernel non ha a disposizione memoria sufficiente a - completare l'operazione. - \item \texttt{EROFS} I file sono su un filesystem montato in sola lettura. - \item \texttt{ELOOP} Ci sono troppi link simbolici nella risoluzione del - pathname. - \item \texttt{ENOSPC} Il device di destinazione non ha più spazio per la - nuova voce. - \end{errlist} -\end{prototype} - -\subsection{I link simbolici} -\label{sec:filedir_sym_link} - -Siccome la funzione \texttt{link} crea riferimenti agli inodes, essa può -funzionare soltanto per file che risiedono sullo stesso filesystem, dato che -in questo caso è garantita l'unicità dell'inode, e solo per un 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 simbolici sono le seguenti, esse sono tutte -dichiarate nell'header file \texttt{unistd.h}. - -\begin{prototype}{unistd.h} -{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 - \secref{sec:filedir_access_control}) ai quali si aggiungono i seguenti: - \begin{errlist} - \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{errlist} -\end{prototype} - -Dato che la funzione \texttt{open} segue i link simbolici, è necessaria usare -un'altra funzione quando si vuole leggere il contenuto di un link simbolico, -questa funzione è la: - -\begin{prototype}{unistd.h} -{int readlink(const char * path, char * buff, size\_t size)} - Legge il contenuto del link simbolico indicato da \texttt{path} nel buffer - \texttt{buff} di dimensione \texttt{size}. Non chiude la stringa con un - carattere nullo e la tronca a \texttt{size} nel caso il buffer sia troppo - piccolo per contenerla. - - La funzione restituisce il numero di caratteri letti dentro \texttt{buff} o - -1 per un errore, in caso di errore. La variabile \texttt{errno} viene - settata secondo i codici di errore: - \begin{errlist} - \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{errlist} -\end{prototype} - - \section{La manipolazione delle caratteristiche dei files} \label{sec:filedir_infos} @@ -501,9 +51,11 @@ in \nfig, cos effettivamente usata nel kernel dipende dall'archietettura e ha altri campi riservati per estensioni come tempo più precisi, o per il padding dei campi). -\begin{figure}[!htbp] +\begin{figure}[!htb] \footnotesize - \begin{lstlisting}{} + \centering + \begin{minipage}[c]{15cm} + \begin{lstlisting}[]{} struct stat { dev_t st_dev; /* device */ ino_t st_ino; /* inode */ @@ -519,7 +71,9 @@ struct stat { time_t st_mtime; /* time of last modification */ time_t st_ctime; /* time of last change */ }; - \end{lstlisting} + \end{lstlisting} + \end{minipage} + \normalsize \caption{La struttura \texttt{stat} per la lettura delle informazioni dei file} \label{fig:sock_sa_gen_struct} @@ -531,6 +85,7 @@ del sistema (di quelli definiti in \tabref{tab:xxx_sys_types}, e dichiarati in + \subsection{I tipi di file} \label{sec:filedir_file_types} @@ -556,6 +111,49 @@ dato che il valore numerico pu \label{sec:filedir_access_control} +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 (vedi +\secref{sec:filedir_access_control}), 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 accennato in \secref{sec:intro_multiuser}, 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 \secref{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 \secref{sec:filedir_suid_sgid} e \secref{sec:filedir_sticky}). + +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 \secref{sec:proc_perms}. + + + \subsection{I flag \texttt{suid} e \texttt{sgid}} \label{sec:filedir_suid_sgid} diff --git a/fileintro.tex b/fileintro.tex index c03e360..4f52826 100644 --- a/fileintro.tex +++ b/fileintro.tex @@ -1,11 +1,10 @@ -\chapter{I files: introduzione} +\chapter{I files: l'architettura} \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. +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 attraverso i @@ -14,32 +13,37 @@ speciali agendo sui quali i programmi possono leggere, scrivere e compiere operazioni direttamente sulle periferiche, 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. +In questo capitolo forniremo un'introduzione all'architettura della gestione +dei file, sia nelle sue caratteristiche generiche comuni a tutti gli unix, che +nelle particolarità che ha la specifica implementazione usata da Linux. Al +comtempo tratteremo l'organizzazione dei file in un sistema unix-like, e le +varie caratteristiche distintive. -\section{I file in un sistema unix-like} -\label{sec:fileintr_overview} + +\section{L'organizzazione di files e directories} +\label{sec:filedir_org} 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 \capref{cha:intro_unix}. +unix-like, è anzitutto opportuno fornire un'introduzione dettagliata su come +essi vengono organizzati all'interno del sistema. + + +\subsection{Una breve introduzione} +\label{sec:fileintr_org_intro} 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} (useremo per brevità -questo nome al posto della più prolissa traduzione italiana sistema di file). +dischi, cioè quello che si chiama un \textit{filesystem}\footnote{useremo per + brevità questo nome al posto della più prolissa traduzione italiana sistema + di file}, che descriviremo in dettaglio in \secref{sec:fileintr_vfs}. 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 (su questo aspetto torneremo con maggiori dettagli in -\secref{sec:filedir_filesystem}). 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). +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 @@ -66,179 +70,76 @@ 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. -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}. +\subsection{La struttura di file e directories} +\label{sec:fileintr_filedir_struct} + +L'organizzazione dei nomi dei file deriva direttamente dall'organizzazione dei +medesimi nell'albero descritto brevemente in \secref{sec:fileintr_org_intro}; +una directory comunque, come già specificato in \secref{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 delle etichette per fare +riferimento ai file stessi. + +I manuale delle glibc chiama i nomi contenuti nelle directory +\textsl{componenti} (in inglese \textit{file name components}), noi li +chiameremo più semplicemente nomi. Un file può essere indicato rispetto alla +directory corrente semplicemente specificando il nome da essa contenuto. Una +directory contiene semplicemente un elenco di questi nomi, 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 completo di file generico è composto da una serie di questi +\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 è 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 nome nella directory indicata dal nome +precedente: ovviamente perché il procedimento funzioni occorre che i nomi +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 \secref{sec:xxx_chroot}) è la stessa per tutti i processi ed +equivale alla directory radice dell'albero (come descritto in +\secref{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 \secref{sec:filedir_work_dir}) ed il pathname è +detto \textsl{relativo}. + +I nomi \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. + + +% \subsection{Il controllo di accesso} +% \label{sec:fileintr_access_ctrl} -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 che il kernel rende disponibile ai programmi in user space -attraverso la quale vengono manipolati i files; esso provvede un livello di -indirezione che permette di collegare le operazioni di manipolazione sui files -alle operazioni di I/O e gestisce l'organizzazione di questi ultimi nei vari -modi in cui diversi filesystem la effettuano, permettendo la coesistenza -di filesystem differenti all'interno dello stesso albero delle directory - -Quando un processo esegue una system call che opera su un file il kernel -chiama sempre una funzione implementata nel VFS; la funzione eseguirà le -manipolazioni sulle strutture generiche e ridirigendo la chiamata alla -opportune routine del filesystem specifico a cui si fa riferimento, saranno -queste a chiamare le funzioni di piu basso livello che eseguono le operazioni -di I/O sul dispositivo fisico, secondo lo schema riportato in \nfig. - -\begin{figure}[htb] - \centering - - \caption{Schema delle operazioni del VFS} - \label{fig:fileintro_VFS_scheme} -\end{figure} - -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 (su questo -torneremo in dettaglio in \secref{sec:fileunix_fd}). Un elenco delle operazioni -previste dal kernel è 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 (vedi -\secref{sec:filedir_access_control}), 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 accennato in \secref{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 \secref{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 \secref{sec:filedir_suid_sgid} e \secref{sec:filedir_sticky}). - -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 \secref{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 definiti nel VFS è il seguente: +Come detto in precedenza in unix esistono vari tipi di file, in Linux questi +sono implementati come oggetti del \textit{Virtual File System} e sono +presenti in tutti i filesystem unix-like utilizzabili con Linux. L'elenco dei +vari tipi di file definiti dal Virtual File System è il seguente: \begin{table}[htb] \begin{center} \begin{tabular}[c]{l l p{7cm}} - \multicolumn{2}{c}{\textbf{Nome}} & \textbf{Descrizione} \\ + \multicolumn{2}{c}{\textbf{Tipo di file}} & \textbf{Descrizione} \\ \hline \textit{regular file} & \textsl{file normale} & un file che contiene dei dati (l'accezione normale di file) \\ @@ -263,11 +164,13 @@ dei vari tipi di file definiti nel VFS \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 +Si tenga ben presente che tutto ciò non ha nulla a che fare con la +classificazione sui tipi di file (che in questo caso sono sempre 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. @@ -283,24 +186,17 @@ problemi qualora nei programmi 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. +programmazione sono due, basate su due diversi meccanismi con cui è possibile +accedere al loro contenuto. 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 @@ -399,3 +295,524 @@ 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'architettura della gestione dei file} +\label{sec:filedir_file_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 sulla gestione dei medesimo e sugli oggetti su cui è basato +un filesystem unix; in particolare si riprenderà, approfondendolo sul piano +dell'uso nelle funzioni di libreria, il concetto di \textit{inode} di cui +abbiamo brevemente accennato le caratteristiche (dal lato dell'implementazione +nel kernel) in \secref{sec:fileintr_vfs}. + +In particolare occorre tenere presente dov'è che si situa la divisione +fondamentale fra kernel space e user space che tracciavamo al +\capref{cha:intro_unix}. + + +\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. +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 che il kernel rende disponibile ai programmi in user space +attraverso la quale vengono manipolati i files; esso provvede un livello di +indirezione che permette di collegare le operazioni di manipolazione sui files +alle operazioni di I/O e gestisce l'organizzazione di questi ultimi nei vari +modi in cui diversi filesystem la effettuano, permettendo la coesistenza +di filesystem differenti all'interno dello stesso albero delle directory + +Quando un processo esegue una system call che opera su un file il kernel +chiama sempre una funzione implementata nel VFS; la funzione eseguirà le +manipolazioni sulle strutture generiche e ridirigendo la chiamata alla +opportune routine del filesystem specifico a cui si fa riferimento, saranno +queste a chiamare le funzioni di piu basso livello che eseguono le operazioni +di I/O sul dispositivo fisico, secondo lo schema riportato in \nfig. + +\begin{figure}[htb] + \centering + + \caption{Schema delle operazioni del VFS} + \label{fig:fileintro_VFS_scheme} +\end{figure} + +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 (su questo +torneremo in dettaglio in \secref{sec:fileunix_fd}). Un elenco delle operazioni +previste dal kernel è 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 funzionamento di un filesystem unix} +\label{sec:filedir_filesystem} + +Come già accennato in \secref{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 a +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 di un +singolo filesystem (tralasciando le parti connesse alla strutturazione e al +funzionamento del filesystem stesso 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} +da questa figura si evidenziano alcune caratteristiche 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{enumerate} + +\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'\textit{inode}; dentro una directory + si troverà solo il nome del file e il numero dell'\textit{inode} ad esso + associato, cioè quella che da qui in poi chiameremo una \textsl{voce} + (traduzione approssimata dell'inglese \textit{directory entry}, che non + useremo anche per evitare confusione con le \textit{dentries} del kernel di + cui si parlava in \secref{sec:fileintr_vfs}). + +\item Come mostrato in \curfig si possono avere più voci che puntano allo + stesso \textit{inode}. Ogni \textit{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 i dati del file vengono + effettivamente rimossi dal disco. Per questo la funzione per cancellare un + file si chiama \texttt{unlink}, ed in realtà non cancella affatto i dati del + file, ma si limita a eliminare la relativa voce da una directory e + decrementare il numero di riferimenti nell'\textit{inode}. + +\item Il numero di \textit{inode} nella voce si riferisce ad un \textit{inode} + nello stesso filesystem e non ci può essere una directory che contiene + riferimenti ad \textit{inodes} relativi ad altri filesystem. Questo limita + l'uso del comando \texttt{ln} (che crea una nuova voce 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, viene semplicemente creata una nuova voce + per l'\textit{inode} in questione e rimossa la vecchia (questa è la modalità + in cui opera normalmente il comando \texttt{mv} attraverso la funzione + \texttt{rename}). + +\end{enumerate} + +Infine è bene avere presente che essendo file pure loro, esiste un numero di +riferimenti anche per le directories; per cui se ad esempio a partire dalla +situazione mostrata in \curfig\ creiamo una nuova directory \texttt{textdir} +nella directory corrente 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 voce che fa riferimento a \texttt{textdir}) e dalla voce \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 voce \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 detto l'accesso al contenuto di un file su disco avviene +attraverso il suo 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}). Il prototipo della funzione e le sue caratteristiche +principali, come risultano dalla man page, sono le seguenti: +\begin{prototype}{unistd.h} +{int link(const char * oldpath, const char * newpath)} + Crea un nuovo collegamento diretto al file indicato da \texttt{oldpath} + dandogli nome \texttt{newpath}. + + 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 seguenti + codici di errore: + \begin{errlist} + \item \texttt{EXDEV} \texttt{oldpath} e \texttt{newpath} non sono sullo + stesso filesystem. + \item \texttt{EPERM} il filesystem che contiene \texttt{oldpath} e + \texttt{newpath} non supporta i link diretti o è una directory. + \item \texttt{EFAULT} una delle stringhe passate come parametri è fuori + dello spazio di indirizzi del processo. + \item \texttt{EACCESS} errore di accesso (mancano i permessi per scrivere o + per attraversare le directories), vedi \secref{sec:filedir_access_control} + per i dettagli. + \item \texttt{ENAMETOOLONG} una dei due pathname è troppo lungo. + \item \texttt{ENOENT} un componente di \texttt{oldpath} o \texttt{newpath} + non esiste o è un link simbolico spezzato. + \item \texttt{ENOTDIR} un componente di \texttt{oldpath} o \texttt{newpath} + non è una directory. + \item \texttt{ENOMEM} il kernel non ha a disposizione memoria sufficiente a + completare l'operazione. + \item \texttt{EROFS} la directory su cui si vuole inserire il nuovo link è + su un filesystem montato readonly. + \item \texttt{EEXIST} un file (o una directory) con quel nome esiste di + già. + \item \texttt{EMLINK} ci sono troppi link al file \texttt{oldpath} (il + numero massimo è specificato dalla variabile \texttt{LINK\_MAX}, vedi + \secref{sec:xxx_limits}). + \item \texttt{ELOOP} si incontrati troppi link simbolici nella risoluzione + di \texttt{oldpath} o \texttt{newpath}. + \item \texttt{ENOSPC} la directory in cui si vuole creare il link non ha + spazio per ulteriori voci. + \item \texttt{EIO} c'è stato un errore di input/output. + \end{errlist} +\end{prototype} + +La creazione di un nuovo collegamento 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. + +Per quanto dicevamo in \secref{sec:filedir_filesystem} la creazione del +collegamento diretto è possibile solo se entrambi i pathname sono nello stesso +filesystem; inoltre il filesystem deve supportare i collegamenti diretti (non è +il caso ad esempio del filesystem \texttt{vfat} di windows). + +La funzione opera sui file ordinari, come sugli altri oggetti del filesystem, +ma solo l'amministratore è in grado di creare un collegamento diretto ad +un'altra directory, questo lo si fa perché in questo caso è possibile creare +dei circoli nel filesystem (vedi \secref{sec:filedir_symlink}) che molti +programmi non sono in grado di gestire e la cui rimozione diventa estremamente +complicata (in genere occorre far girare il programma \texttt{fsck} per +riparare il filesystem); data la sua pericolosità in Linux questa +caratteristica è stata disabilitata, e la funzione restituisce l'errore +\texttt{EPERM}. + +La rimozione di un file (o più precisamente della voce che lo referenzia) si +effettua con la funzione \texttt{unlink}; il suo prototipo è il seguente: + +\begin{prototype}{unistd.h}{int unlink(const char * pathname)} + Cancella il nome specificato dal pathname nella relativa directory e + decrementa il numero di riferimenti nel relativo inode. Nel caso di link + simbolico cancella il link simbolico; nel caso di socket, fifo o file di + dispositivo rimuove il nome, ma come per i file i processi che hanno aperto + uno di questi oggetti possono continuare ad utilizzarlo. + + La funzione restituisce zero in caso di successo e -1 per un errore, nel + qual caso il file non viene toccato. La variabile \texttt{errno} viene + settata secondo i seguenti codici di errore: + \begin{errlist} + \item \texttt{EACCESS} errore di accesso (mancano i permessi per scrivere o + per attraversare le directories), vedi \secref{sec:filedir_access_control} + per i dettagli. + \item \texttt{EISDIR} \texttt{pathname} si riferisce ad una directory + (valore specifico ritornato da linux che non consente l'uso di + \texttt{unlink} con le directory, e non conforme allo standard POSIX, che + prescrive invece l'uso di \texttt{EPERM} in caso l'operazione non sia + consnetita o il processo non abbia privilegi sufficienti). + \item \texttt{EFAULT} la stringa + passata come parametro è fuori dello spazio di indirizzi del processo. + \item \texttt{ENAMETOOLONG} il pathname troppo lungo. + \item \texttt{ENOENT} uno dei componenti del pathname non esiste o è un link + simbolico spezzato. + \item \texttt{ENOTDIR} uno dei componenti del pathname non è una directory. + \item \texttt{EISDIR} \texttt{pathname} fa riferimento a una directory. + \item \texttt{ENOMEM} il kernel non ha a disposizione memoria sufficiente a + completare l'operazione. + \item \texttt{EROFS} \texttt{pathname} è su un filesystem montato in sola + lettura. + \item \texttt{ELOOP} ci sono troppi link simbolici nella risoluzione del + pathname. + \item \texttt{EIO} errore di input/output. + \end{errlist} +\end{prototype} + +Per cancellare una voce in una directory è necessario avere il permesso di +scrittura su di essa (dato che si va a rimuovere una voce dal suo contenuto) e +il diritto di esecuzione sulla directory che la contiene (torneremo in +dettaglio sui permessi e gli attributi fra poco), se inoltre lo +\textit{sticky} bit è settato occorrerà anche essere proprietari del file o +proprietari della directory (o root, per cui nessuna delle restrizioni è +applicata). + +Una delle caratteristiche di queste funzioni è che la creazione/rimozione +della nome dalla directory e l'incremento/decremento del numero di riferimenti +nell'inode deve essere una operazione atomica (cioè non interrompibile da +altri) processi, per questo entrambe queste funzioni sono realizzate tramite +una singola system call. + +Si ricordi infine che il file non viene eliminato dal disco fintanto che tutti +i riferimenti ad esso sono stati cancellati, solo quando il \textit{link + count} mantenuto nell'inode diventa zero lo spazio occupato viene rimosso. A +questo però si aggiunge una altra condizione, e cioè che non ci siano processi +che abbiano detto file aperto. Come accennato questa proprietà viene spesso +usata per essere sicuri di non lasciare file temporanei su disco in caso di +crash dei programmi; la tecnica è quella di aprire il file e chiamare +\texttt{unlink} subito dopo. + +\subsection{Le funzioni \texttt{remove} e \texttt{rename}} +\label{sec:filedir_cre_canc} + +Al contrario di quanto avviene con altri unix in Linux non è possibile usare +\texttt{unlink} sulle directory, per cancellare una directory si può usare la +funzione \texttt{rmdir} (vedi \secref{sec:filedir_dir_creat_rem}), oppure la +funzione \texttt{remove}. Questa è la funzione prevista dallo standard ANSI C +per cancellare un file o una directory (e funziona anche per i sistemi che non +supportano i link diretti), che per i file è identica alla \texttt{unlink} e +per le directory è identica alla \texttt{rmdir}: + +\begin{prototype}{stdio.h}{int remove(const char *pathname)} + Cancella un nome dal filesystem. Usa \texttt{unlink} per i file e + \texttt{rmdir} per le directory. + + La funzione restituisce zero in caso di successo e -1 per un errore, nel + qual caso il file non viene toccato. Per i codici di errori vedi quanto + riportato nella descrizione di \texttt{unlink} e \texttt{rmdir}. +\end{prototype} + +Per cambiare nome ad un file si usa invece la funzione \texttt{rename}, il +vantaggio nell'uso di questa funzione al posto della chiamata successiva di +\texttt{unlink} e \texttt{link} è che l'operazione è eseguita atomicamente, in +questo modo non c'è la possibilità che un processo che cerchi di accedere al +nuovo nome dopo che il vecchio è stato cambiato lo trovi mancante. + +\begin{prototype}{stdio.h} +{int rename(const char *oldpath, const char *newpath)} + Rinomina un file, spostandolo fra directory diverse quando richiesto. + + La funzione restituisce zero in caso di successo e -1 per un errore, nel + qual caso il file non viene toccato. La variabile \texttt{errno} viene + settata secondo i seguenti codici di errore: + \begin{errlist} + \item \texttt{EISDIR} \texttt{newpath} è una directory già esistente mentre + \texttt{oldpath} non è una directory. + \item \texttt{EXDEV} \texttt{oldpath} e \texttt{newpath} non sono sullo + stesso filesystem. + \item \texttt{ENOTEMPTY} \texttt{newpath} è una directory già esistente e + non vuota. + \item \texttt{EBUSY} o \texttt{oldpath} o \texttt{newpath} sono in uso da + parte di qualche processo (come directory di lavoro o come root) o del + sistema (come mount point). + \item \texttt{EINVAL} \texttt{newpath} contiene un prefisso di + \texttt{oldpath} o più in generale si è cercato di creare una directory + come sottodirectory di se stessa. + \item \texttt{EMLINK} \texttt{oldpath} ha già il massimo numero di link + consentiti o è una directory e la directory che contiene \texttt{newpath} + ha già il massimo numero di link. + \item \texttt{ENOTDIR} Uno dei componenti dei pathname non è una directory + o\texttt{oldpath} è una directory e \texttt{newpath} esiste e non è una + directory. + \item \texttt{EFAULT} o \texttt{oldpath} o \texttt{newpath} è fuori dello + spazio di indirizzi del processo. + \item \texttt{EACCESS} Non c'è il permesso di scrittura per la directory in + cui si vuole creare il nuovo link o una delle directory del pathname non + consente la ricerca (permesso di esecuzione). + \item \texttt{EPERM} le directory contenenti \texttt{oldpath} o + \texttt{newpath} hanno lo sticky bit attivo e i permessi del processo non + consentono rispettivamente la cancellazione e la creazione del file, o il + filesystem non supporta i link. + \item \texttt{ENAMETOOLONG} uno dei pathname è troppo lungo. + \item \texttt{ENOENT} Uno dei componenti del pathname non esiste o è un link + simbolico spezzato. + \item \texttt{ENOMEM} il kernel non ha a disposizione memoria sufficiente a + completare l'operazione. + \item \texttt{EROFS} I file sono su un filesystem montato in sola lettura. + \item \texttt{ELOOP} Ci sono troppi link simbolici nella risoluzione del + pathname. + \item \texttt{ENOSPC} Il device di destinazione non ha più spazio per la + nuova voce. + \end{errlist} +\end{prototype} + +\subsection{I link simbolici} +\label{sec:filedir_sym_link} + +Siccome la funzione \texttt{link} crea riferimenti agli inodes, essa può +funzionare soltanto per file che risiedono sullo stesso filesystem, dato che +in questo caso è garantita l'unicità dell'inode, e solo per un 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 simbolici sono le seguenti, esse sono tutte +dichiarate nell'header file \texttt{unistd.h}. + +\begin{prototype}{unistd.h} +{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 + \secref{sec:filedir_access_control}) ai quali si aggiungono i seguenti: + \begin{errlist} + \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{errlist} +\end{prototype} + +Dato che la funzione \texttt{open} segue i link simbolici, è necessaria usare +un'altra funzione quando si vuole leggere il contenuto di un link simbolico, +questa funzione è la: + +\begin{prototype}{unistd.h} +{int readlink(const char * path, char * buff, size\_t size)} + Legge il contenuto del link simbolico indicato da \texttt{path} nel buffer + \texttt{buff} di dimensione \texttt{size}. Non chiude la stringa con un + carattere nullo e la tronca a \texttt{size} nel caso il buffer sia troppo + piccolo per contenerla. + + La funzione restituisce il numero di caratteri letti dentro \texttt{buff} o + -1 per un errore, in caso di errore. La variabile \texttt{errno} viene + settata secondo i codici di errore: + \begin{errlist} + \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{errlist} +\end{prototype} + + diff --git a/fileunix.tex b/fileunix.tex index 2aeda78..a4fb479 100644 --- a/fileunix.tex +++ b/fileunix.tex @@ -1,6 +1,12 @@ \chapter{I files: l'interfaccia I/O di unix} \label{cha:file_unix_interface} +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. + \section{I file descriptors} diff --git a/intro.tex b/intro.tex index 4c871ac..0913f58 100644 --- a/intro.tex +++ b/intro.tex @@ -206,13 +206,13 @@ essere associato a pi accesso ai file e quindi anche alle periferiche, in maniera più flessibile, definendo gruppi di lavoro, di accesso a determinate risorse, etc. -% L'utente e il gruppo sono identificati da due numeri (la cui corrispondenza ad -% un nome in espresso in caratteri \`e inserita nei due files -% \texttt{/etc/passwd} e \texttt{/etc/groups}). Questi numeri sono -% l'\textit{user identifier}, detto in breve \textit{uid} e il \textit{group -% identifier}, detto in breve \textit{gid} che sono quelli che identificano -% l'utente di fronte al sistema. - +L'utente e il gruppo sono identificati da due numeri (la cui corrispondenza ad +un nome in espresso in caratteri \`e inserita nei due files +\texttt{/etc/passwd} e \texttt{/etc/groups}). Questi numeri sono +l'\textit{user identifier}, detto in breve \textit{uid} e il \textit{group + identifier}, detto in breve \textit{gid} che sono quelli che identificano +l'utente di fronte al sistema. + In questo modo il sistema è in grado di tenere traccia per ogni processo 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 @@ -226,7 +226,7 @@ qualunque operazione; pertanto per l'utente root i meccanismi di controllo descritti in precedenza sono disattivati. -\section{Gli standard di unix e Linux} +\section{Gli standard di unix e GNU/Linux} \label{sec:intro_standard} diff --git a/macro.tex b/macro.tex index e20120d..8f3092d 100644 --- a/macro.tex +++ b/macro.tex @@ -98,7 +98,7 @@ tab.~\thechapter.\theusercount} \newenvironment{functions} {% defining what is done by \begin \center - \footnotesize + \footnotesize \begin{minipage}[c]{14cm} \begin{description}{}{} @@ -123,4 +123,3 @@ tab.~\thechapter.\theusercount} \newcommand{\link}[1]{\texttt{#1}} % html link \newcommand{\type}[1]{\texttt{#1}} % variable type \newcommand{\param}[1]{\texttt{#1}} % function parameter - diff --git a/prochand.tex b/prochand.tex index 9a59964..721b899 100644 --- a/prochand.tex +++ b/prochand.tex @@ -50,12 +50,12 @@ 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{functions} -\incldecl{sys/types.h} -\incldecl{unistd.h} +\headdecl{sys/types.h} +\headdecl{unistd.h} \funcdecl{pid\_t getpid(void)} restituisce il pid del processo corrente. \funcdecl{pid\_t getppid(void)} restituisce il pid del padre del processo corrente. -\end{} +\end{functions} \section{Il controllo dei processi}