From 8e2e384f75e8ea30c3ea290d736af1077f20117b Mon Sep 17 00:00:00 2001 From: Simone Piccardi Date: Sat, 29 Dec 2001 12:40:44 +0000 Subject: [PATCH] Nuova figura sui processi e rifiniture varie --- filedir.tex | 52 +++++----- fileintro.tex | 229 ++++++++++++++++++++++---------------------- img/task_struct.dia | Bin 0 -> 4918 bytes 3 files changed, 140 insertions(+), 141 deletions(-) create mode 100644 img/task_struct.dia diff --git a/filedir.tex b/filedir.tex index 6bbdb18..835e350 100644 --- a/filedir.tex +++ b/filedir.tex @@ -32,15 +32,15 @@ dei nomi fittizi (come gli alias del MacOS o i collegamenti di Windows) che permettono di fare riferimento allo stesso file chiamandolo con nomi diversi o accedendovi da directory diverse. -Questo è possibile anche in ambiente unix, dove tali collegamenti sono +Questo è possibile anche in ambiente Unix, dove tali collegamenti sono usualmente chiamati \textit{link}; ma data la struttura del sistema di gestione dei file (ed in particolare quanto trattato in -\secref{sec:file_architecture}) ci sono due metodi sostanzialmente diversi per +\secref{sec:file_arch_func}) ci sono due metodi sostanzialmente diversi per fare questa operazione. -Come spiegato in \secref{sec:file_filesystem} 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 che fa +Come spiegato in \secref{sec:file_filesystem} l'accesso al contenuto di un +file su disco avviene attraverso il suo inode\index{inode}, e il nome che si +trova in una directory è solo una etichetta associata ad un puntatore a che fa riferimento al suddetto inode. Questo significa che la realizzazione di un link è immediata in quanto uno @@ -282,8 +282,8 @@ specificato. La funzione che permette di creare un nuovo link simbolico \bodydesc{La funzione restituisce zero in caso di successo e -1 per un errore, nel qual caso la variabile \var{errno} restituisce i valori: \begin{errlist} - \item[\macro{EPERM}] il filesystem che contiene \param{newpath} non supporta i - link simbolici. + \item[\macro{EPERM}] il filesystem che contiene \param{newpath} non supporta + i link simbolici. \item[\macro{ENOENT}] una componente di \param{newpath} non esiste o \param{oldpath} è una stringa vuota. \item[\macro{EEXIST}] esiste già un file \param{newpath}. @@ -1846,7 +1846,7 @@ sono tre e i loro prototipi sono i seguenti: specificati dalle variabili \var{owner} e \var{group}. \bodydesc{Le funzioni restituiscono zero in caso di successo e -1 per - un errore, in caso di errore \texttt{errno} viene settato ai valori: + un errore, in caso di errore \var{errno} viene settato ai valori: \begin{errlist} \item[\macro{EPERM}] L'\textit{effective user id} non corrisponde a quello del proprietario del file o non è zero, o utente e gruppo non sono validi @@ -1898,25 +1898,22 @@ Come accennato in \secref{sec:proc_fork} ogni processo oltre ad una directory di lavoro corrente, ha anche una directory radice, che è la directory che per il processo costituisce la radice dell'albero dei file e rispetto alla quale vengono risolti i pathname assoluti (si ricordi quanto detto in -\secref{sec:file_file_struct}) - +\secref{sec:file_organization}). La radice viene eredidata dal padre per ogni processo figlio; come si può vedere da \figref{fig:proc_task_struct} è tenuta nella struttura \type{fs\_struct} insieme alla directory di lavoro corrente e alla \var{umask}, e quindi di norma coincide con la \file{/} del sistema. - - In certe situazioni però per motivi di sicurezza non si vuole che un processo possa accedere a tutto il filesystem; per questo si può cambiare la directory radice con la funzione \func{chroot}, il cui prototipo è: \begin{prototype}{unistd.h}{int chroot(const char *path)} Cambia la directory radice del processo a quella specificata da - \param{path}.. + \param{path}. \bodydesc{La funzione restituisce zero in caso di successo e -1 per - un errore, in caso di errore \texttt{errno} viene settato ai valori: + un errore, in caso di errore \var{errno} viene settato ai valori: \begin{errlist} \item[\macro{EPERM}] L'\textit{effective user id} non è zero. \end{errlist} @@ -1924,17 +1921,22 @@ radice con la funzione \func{chroot}, il cui prototipo \macro{ENOMEM}, \macro{ENOTDIR}, \macro{EACCES}, \macro{ELOOP}; \macro{EROFS} e \macro{EIO}.} \end{prototype} - - - - - -un caso tipico è quello di un server -ftp che dovrebbe limitarsi - - -Il sistema però consente di cambiare questa directory con la funzione -\func{chroot} +\noindent in questo modo la directory radice del processo diventerà +\param{path} (che ovviamente deve esistere) ed ogni pathname assoluto sarà +risolto a partire da essa, rendendo impossibile accedere alla parte di albero +sovrastante; si ha cioè quella che viene chiamata una \textit{chroot jail}. + +Solo l'amministratore può usare questa funzione, e la nuova radice, per quanto +detto in \secref{sec:proc_fork}, sarà ereditata da tutti i processi figli. Si +tenga presente che la funzione non cambia la directory di lavoro corrente, che +potrebbe restare fuori dalla \textit{chroot jail}. + +Un caso tipico di uso di \func{chroot} è quello di un server ftp, in questo +caso infatti si vuole che il server veda solo i file che deve trasferire, per +cui in genere si una \textit{chroot jail} alla directory che contiene i file. +Si tenga presente però che in questo caso occorrerà replicare all'interno +della \textit{chroot jail} tutti i file (in genere programmi e librerie) di +cui il server potrebbe avere bisogno. %%% Local Variables: diff --git a/fileintro.tex b/fileintro.tex index c69acba..927dc4d 100644 --- a/fileintro.tex +++ b/fileintro.tex @@ -14,13 +14,15 @@ 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 una panoramica dell'architettura dei file, sia -nelle sue caratteristiche generali, comuni a tutti gli Unix, che nelle -particolarità che ha la specifica implementazione usata da Linux. +In questo capitolo forniremo una descrizione dell'architettura dei file in +Linux, iniziando da una panoramica sulle caratteristiche principali delle +interfacce con cui i processi accedono ai file (che tratteremo in dettaglio +nei capitoli seguenti), per poi passare ad una descrizione più dettagliata +delle modalità con cui detto accesso viene realizzato dal sistema. -\section{L'architettura dell'accesso ai file} +\section{L'architettura dell'accesso} \label{sec:file_access_arch} Per poter accedere ai file il kernel deve mettere a disposizione dei programmi @@ -28,91 +30,84 @@ le opportune interfacce che consentano di leggerne il contenuto; il sistema cioè deve provvedere ad organizzare e rendere accessibile in maniera opportuna l'informazione tenuta sullo spazio grezzo disponibile sui dischi. Questo viene fatto strutturando l'informazione sul disco attraverso quello che si chiama un -\textit{filesystem}, essa poi viene resa disponibile attraverso quello che -viene chiamato il \textsl{montaggio} del filesystem. +\textit{filesystem}, essa poi viene resa disponibile ai processi attraverso +quello che viene chiamato il \textsl{montaggio} del filesystem. % (approfondiremo tutto ciò in \secref{sec:file_arch_func}). In questa sezione faremo una panormamica generica su come il sistema presenta i file ai processi, trattando l'organizzazione di file e directory, i tipi di -file ed introducendo le interfacce disponibili, che saranno approfondite nei -capitoli seguenti. +file ed introducendo le interfacce disponibili e le loro caratteristiche. \subsection{L'organizzazione di file e directory} -\label{sec:file_file_struct} +\label{sec:file_organization} 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 (quella che -viene chiamata \textit{root directory}) 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. +viene chiamata \textit{root directory}) viene montata all'avvio. Un file +viene identificato dall'utente usando quello che viene chiamato +\textit{pathname}\footnote{anche se il manuale della \acr{glibc} depreca + questa nomenclatura, 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) non seguiremo questa + scelta dato che l'uso della parola \textit{pathname} è ormai così comune che + mantenerne l'uso è senz'altro più chiaro dell'alternativa proposta.}, cioè +il percorso che si deve fare per accedere al file, che è composto da una serie +di nomi separati da una \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 \file{/}); tutti gli ulteriori filesystem che possono essere su -altri dispositivi devono poi essere inseriti nell'albero utilizzando opportune -subdirectory. +altri dispositivi devono poi essere inseriti nell'albero montandoli su +opportune directory del filesystem montato come radice. Alcuni filesystem speciali (come \file{/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 file come le fifo, i -link, i socket e gli stessi i file di dispositivo (questi ultimi, per -convenzione, sono inseriti nella directory \file{/dev}). - -L'organizzazione dei nomi dei file deriva direttamente dall'organizzazione dei -medesimi nell'albero descritto in precedenza; una directory comunque, come -vedremo in \secref{sec:file_vfs_work}, è 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 \acr{glibc} chiama i nomi contenuti nelle directory -\textsl{componenti} (in inglese \textit{file name components}), noi li -chiameremo più semplicemente \textit{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 nomi separati da -una \file{/} (in Linux più \file{/} consecutive sono considerate equivalenti -ad una sola). Il nome completo di un file viene usualmente chiamato -\textit{pathname}, e anche se il manuale della \acr{glibc} depreca questa -nomenclatura\footnote{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}; non seguiremo questa -scelta dato che l'uso della parola \textit{pathname} è ormai così comune che è -senz'altro più chiaro dell'alternativa proposta. - -Il procedimento 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 \file{/} la ricerca parte dalla directory radice -del processo; questa, a meno di un \textit{chroot} (su cui torneremo in -seguito, vedi \secref{sec:file_chroot}) è la stessa per tutti i processi ed -equivale alla directory radice dell'albero (come descritto in -\secref{sec:file_organization}): 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:file_work_dir}) ed il pathname è -detto \textsl{relativo}. +stesso, ma anche essi devono essere montati all'interno dell'albero dei file. + +Una directory, come vedremo in maggior dettaglio in +\secref{sec:file_vfs_work}, è anch'essa un file, solo che è un file +particolare che il kernel riconosce come tale. Il suo scopo è quello di +contenere una lista di nomi di file e le informazioni che associano ciascun +nome al contenuto. Dato che questi nomi possono corrispondere ad un qualunque +oggetto del filesystem, compresa un'altra directory, si ottiene naturalmente +un'organizzazione ad albero inserendo directory in altre directory. + +Un file può essere indicato rispetto alla directory corrente semplicemente +specificandone il nome\footnote{Il manuale delle \acr{glibc} chiama i nomi + contenuti nelle directory \textsl{componenti} (in inglese \textit{file name + components}), noi li chiameremo più semplicemente \textit{nomi}.} da essa +contenuto. All'interno dello stesso albero si potranno poi inserire anche +tutti gli altri oggetti visti attraverso l'interfaccia che manipola i file +come le fifo, i link, i socket e gli stessi i file di dispositivo (questi +ultimi, per convenzione, sono inseriti nella directory \file{/dev}). + +Il nome completo di un file viene chiamato \textit{pathname} ed il +procedimento con cui si individua il file a cui esso fa riferimento è chiamato +risoluzione del nome (\textit{file name resolution} o \textit{pathname + resolution}). La risoluzione viene fatta esaminando il \textit{pathname} da +destra a sinistra e localizzando ogni nome nella directory indicata dal nome +precedente usando \file{/} come separatore\footnote{nel caso di nome vuoto, il + costrutto \file{//} viene considerato equivalente a \file{/}.}: ovviamente +perché il procedimento funzioni occorre che i nomi indicati come directory +esistano e siano effettivamente directory, inoltre i permessi (si veda +\secref{sec:file_access_control}) devono consentire l'accesso. + +Se il \textit{pathname} comincia per \file{/} la ricerca parte dalla directory +radice del processo; questa, a meno di un \func{chroot} (su cui torneremo in +\secref{sec:file_chroot}) è la stessa per tutti i processi ed equivale alla +directory radice dell'albero dei file: in questo caso si parla di un +\textsl{pathname assoluto}\index{pathname assoluto}. Altrimenti la ricerca +parte dalla directory corrente (su cui torneremo in +\secref{sec:file_work_dir}) ed il pathname è detto \textsl{pathname + relativo}\index{pathname relativo}. I nomi \file{.} e \file{..} hanno un significato speciale e vengono inseriti in ogni directory, il primo fa riferimento alla directory corrente e il -secondo alla directory \textsl{genitrice} (\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. +secondo alla directory \textsl{genitrice} (o \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{I tipi di file} @@ -121,8 +116,8 @@ sia la directory radice allora il riferimento Come detto in precedenza in unix esistono vari tipi di file, in Linux questi sono implementati come oggetti del \textit{Virtual File System} (vedi \secref{sec:file_vfs_work}) e sono presenti in tutti i filesystem unix-like -utilizzabili con Linux. L'elenco dei vari tipi di file definiti dal Virtual -File System è riportato in \ntab. +utilizzabili con Linux. L'elenco dei vari tipi di file definiti dal +\textit{Virtual File System}\index{Virtual File System} è riportato in \ntab. Si tenga ben presente che questa classificazione non ha nulla a che fare con la classificazione sui tipi di file (che in questo caso sono sempre file di @@ -184,61 +179,62 @@ In unix le modalit 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 descrittori di file (o \textit{file descriptor}). È -un'interfaccia specifica di unix e provvede un accesso non bufferizzato, la -tratteremo in dettaglio in \capref{cha:file_unix_interface}. +La prima è l'interfaccia standard di unix, quella che il manuale delle +\acr{glibc} chiama interfaccia dei descrittori di file (o \textit{file + descriptor}). È un'interfaccia specifica di unix e provvede un accesso non +bufferizzato, la tratteremo in dettaglio in \capref{cha:file_unix_interface}. 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 descriptor sono rappresentati da numeri interi (cioè -semplici variabili di tipo \type{int}). L'interfaccia è definita -nell'header \file{unistd.h}. +dispositivi); i \textit{file descriptor}\index{file descriptor} sono +rappresentati da numeri interi (cioè semplici variabili di tipo \type{int}). +L'interfaccia è definita nell'header \file{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), la tratteremo -in dettaglio in \capref{cha:files_std_interface}. +La seconda interfaccia è quella che il manuale della \acr{glibc} chiama degli +\textit{stream}\index{stream}, essa provvede funzioni più evolute e un accesso +bufferizzato (controllato dalla implementazione fatta dalle librerie del C), +la tratteremo in dettaglio in \capref{cha:files_std_interface}. Questa è l'interfaccia standard specificata dall'ANSI 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 -\type{FILE *}. L'interfaccia è definita nell'header \type{stdio.h}. +anche su tutti i sistemi non Unix. Gli \textit{stream} sono oggetti complessi +e sono rappresentati da puntatori ad un opportuna struttura definita dalle +librerie del C, si accede ad essi sempre in maniera indiretta utilizzando il +tipo \type{FILE *}. L'interfaccia è definita nell'header \type{stdio.h}. Entrambe le interfacce possono essere usate per l'accesso ai file come agli altri oggetti del VFS (pipe, socket, device, sui quali torneremo in dettaglio a tempo opportuno), 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 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 \secref{sec:file_noblocking}). - -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 byte. 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. +standard di Unix coi \textit{file descriptor}. Allo stesso modo devono essere +usati i \textit{file descriptor} se si vuole ricorrere a modalità speciali di +I/O come il polling o il non-bloccante (vedi \capref{cha:file_advanced}). + +Gli \textit{stream} forniscono un'interfaccia di alto livello costruita sopra +quella dei \textit{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 \textit{stream} è che l'interfaccia per le +operazioni di input/output è enormemente più ricca di quella dei \textit{file + descriptor}, che provvedono solo funzioni elementari per la +lettura/scrittura diretta di blocchi di byte. In particolare gli +\textit{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. +standard di Unix, è sempre possibile estrarre il \textit{file descriptor} da +uno stream ed eseguirvi operazioni di basso livello, o associare in un secondo +tempo uno \textit{stream} ad un \textit{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 definiti nello standard ANSI C; l'interfaccia con i file -descriptor invece segue solo lo standard POSIX.1 dei sistemi unix ed è -pertanto di portabilità più limitata. +livello, è opportuno usare sempre gli \textit{stream} per la loro maggiore +portabilità essendo questi ultimi definiti nello standard ANSI C; +l'interfaccia con i \textit{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} +\subsection{Caratteristiche specifiche dei file in Unix} \label{sec:fileint_unix_spec} Essendo un sistema multitasking e multiutente esistono alcune caratteristiche @@ -281,8 +277,9 @@ 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. +Ritorneremo su questo più avanti in \secref{sec:file_fd}, quando tratteremo +l'input/output sui file, esaminando in dettaglio come tutto ciò viene +realizzato. Si ricordi infine che in ambiente unix non esistono i tipi di file e che non c'è nessun supporto per le estensioni come parte del filesystem. Ciò non @@ -291,20 +288,20 @@ 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} +\section{L'architettura di funzionamento} \label{sec:file_arch_func} Per capire fino in fondo le proprietà di file e directory in un sistema -unix-like ed il funzionamento delle relative funzioni di manipolazione occorre -una breve introduzione sulla gestione dei medesimo e sugli oggetti su cui è -basato un filesystem di tipo unix. 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}. +unix-like ed il comportamento delle relative funzioni di manipolazione occorre +una breve introduzione al funzionamento gestione dei file da parte del kernel +e sugli oggetti su cui è basato un filesystem di tipo unix. 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}. In questa sezione esamineremo come viene implementato l'accesso ai file in Linux, come il kernel può gestire diversi tipi di filesystem, descrivendo -poi in maniera un po' più dettagliata il filesystem standard di Linux, -l'\acr{ext2}, come esempio di un filesystem unix-like. +prima le caratteristiche generali di un filesystem Unix, per poi trattare in +maniera un po' più dettagliata il filesystem standard di Linux, l'\acr{ext2}. % in particolare si riprenderà, approfondendolo sul piano diff --git a/img/task_struct.dia b/img/task_struct.dia new file mode 100644 index 0000000000000000000000000000000000000000..b9f28f6d6b715c8fd863a2124a92417fa21a311f GIT binary patch literal 4918 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 literal 0 HcmV?d00001 -- 2.30.2