In GNU/Linux possono essere utilizzati vari tipi di file, ognuno identificato da uno specifico codice che filesystem ext2 memorizza nei metadati relativi al file considerato (i primi 4 bit del campo i_mode).
![]()
|
A tale categoria appartiene la maggior parte dei file presenti sui filesystem. Tale tipo rappresenta il file nella sua accezione di base, ovvero un contenitore di informazioni senza caratteristiche particolari. I file di questo tipo sono anche detti regular file.
Una directory è un file particolare che contiene un elenco di elementi detti dentry (directory entry), ognuno dei quali è costituito da (v. fig. 4.7)
I numeri degli inode presenti in tale elenco, costituiscono i riferimenti univoci agli inode relativi ai file (o directory) accessibili da tale directory, cioè i file (o directory) contenuti all’interno della directory. Più in dettaglio, le dentry hanno la struttura riportata di seguito (sintassi C)
struct ext2_dir_entry_2 { __u32 inode; /* Inode number */ __u16 rec_len; /* Directory entry length */ __u8 name_len; /* File name length */ __u8 file_type; /* File type */ char name[EXT2_NAME_LEN]; /* File name */ }
Il campo name_len contiene la lunghezza effettiva del nome del file, ovvero il numero di caratteri dai quali esso è effettivamente costituito, mentre il campo rec_len indica la lunghezza dell’intera dentry. Il campo file_type contiene un numero che indica il tipo del file secondo quanto riportato nella tab. 4.6.
![]()
|
Di seguito è riportato il contenuto di una directory.
00000000 dc b9 03 00 0c 00 01 02 2e 00 00 00 fd 05 00 00 |................| 00000010 0c 00 02 02 2e 2e 00 00 f4 b9 03 00 10 00 05 02 |................| 00000020 6d 79 64 69 72 00 00 00 f9 b9 03 00 10 00 07 02 |mydir...........| 00000030 74 65 73 74 64 69 72 00 0d ba 03 00 10 00 08 01 |testdir.........| 00000040 74 65 73 74 66 69 6c 65 fe b9 03 00 14 00 09 01 |testfile........| 00000050 6f 74 68 65 72 2e 6f 67 67 00 00 00 fa b9 03 00 |other.ogg.......| 00000060 a4 0f 0a 01 6d 79 66 69 6c 65 2e 6a 70 67 00 00 |....myfile.jpg..| 00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| [...]
Quando viene specificato il percorso di un file (path), il kernel ricerca nelle dentry delle varie directory che costituiscono il path del file, il nome indicato, per trovare di volta in volta il relativo numero di inode e per poter così accedere alle informazioni in esso contenute. Una volta raggiunto l’inode relativo al file indicato, il sistema ha i riferimenti per poter accedere alle informazioni contenute nel file stesso (si ricordi che la root directory è sempre contenuta nell’inode 2). Un esempio di accesso ad un file è riportato nella fig. 4.8).
Nei sistemi Unix-like dunque un file (o directory) è rappresentato da un inode, all’interno del quale sono memorizzati i sui metadati, ovvero i suoi dati caratteristici ed in esso vi sono i riferimenti ai blocchi che contengono il contenuto vero e proprio del file. Come si può notare dalla struttura, negli inode non viene memorizzato il nome del file, poiché esso non è una caratteristica intrinseca del file stesso (il file è individuato univocamente dal numero di inode), ma è semplicemente un’etichetta memorizzata nelle dentry che serve come riferimento per poter accedere all’inode relativo al file. Quindi, sebbene un nome di file individui un solo inode, lo stesso inode può essere individuato da più nomi di file. L’associazione tra il nome del file e l’inode a cui si riferisce, memorizzato nelle dentry, è detta hard link (physical link, collegamento fisico o collegamento diretto). Dunque, un file (inode) può avere più hard link (più nomi) che si riferiscono ad esso.
Quando viene creato un hard link, viene incrementato il contatore dei riferimenti nell’inode relativo (i_links_count). In questo modo il sistema tiene traccia di quanti hard link sono riferiti ad ogni inode. L’eliminazione di un hard link non implica l’eliminazione di un file, ovvero dell’inode relativo, ma un file viene effettivamente eliminato dal filesystem soltanto quando l’ultimo degli hard link ad esso relativi viene eliminato e nessun processo sta utilizzando il file (inode) in questione.19
Alla creazione di un file viene sempre creato un hard link ad esso relativo, cioè il primo riferimento a se stesso che è una dentry all’interno della directory che lo contiene. In tale dentry sarà memorizzato il nome associato a tale hard link (il nome del file).
È possibile creare hard link soltanto sui filesystem che li supportano e, comunque, sia l’inode che il relativo hard link devono trovarsi sullo stesso filesystem;
|
In GNU/Linux è possibile creare hard link relativi soltanto a file, non a directory, poiché sarebbe altrimenti possibile creare dei riferimenti circolari (catene di collegamenti chiuse su se stesse), complessi da gestire e soprattutto da rimuovere. |
È importante sottolineare il fatto che il sistema non tiene conto, all’interno degli inode, dei symbolic link che si riferiscono ad essi, come invece avviene per gli hard link: quindi è possibile ottenere dei dangling link (collegamenti penzolanti) ovvero dei symbolic link che non sono collegati ad un file o ad una directory esistente. Infatti, alla creazione di un symbolic link il sistema non attua nessun controllo relativo al fatto che il file o la directory a cui esso si riferisce esista e neanche alla cancellazione di un file (rimozione dell’ultimo hard link) il sistema tiene conto di eventuali symbolic link che si riferiscono ad esso.
Per contro, i symbolic link non hanno le restrizioni degli hard link, quindi è possibile anche creare symbolic link relativi a file o directory situati in filesystem diversi da quello in cui viene creato il link.
I link vengono creati per mezzo del comando ln (man page ln(1)).
____________________________________________________________________
SINTASSI
$ ln [option] target [link_name]
DESCRIZIONE
Ad esempio, è possibile creare un hard link al file ~/.bashrc20 (cioè una dentry in una directory, non un file) con il comando
$ ln ~/.bashrc myhlink
e così i nomi myhlink (nella working directory) e .bashrc (nella home directory) si
riferiranno in seguito allo stesso identico file, che sarà fisicamente rimosso dal sistema soltanto
quando lo saranno entrambi i link ad esso relativi.
È possibile creare un symbolic link al file ~/.bashrc (cioè un file vero e proprio) con il comando
$ ln -s ~/.bashrc myslink
anche nel caso in cui il file ~/.bashrc non esista. In tal caso myslink sarebbe
un dangling link poiché non si riferirebbe ad un file (o directory) effettivamente
esitente.
Con i symbolic link possono essere creati dei riferimenti circolari (catene di collegamenti chiuse su se stesse) che potrebbero essere problematici per certi comandi. Si supponga infatti di creare un symbolic link /boot/myboot alla directory /boot e di visualizzare il contenuto della directory /boot in modo da scendere ricorsivamente in tutte le sottodirectory in essa contenute, impartendo il comando
$ ls -r /boot
Così facendo il comando ls esaminerebbe la directory /boot, quindi la directory
/boot/myboot, ovvero la directory /boot stessa che ovviamente contiene /boot/myboot e
quindi esaminerebbe /boot/myboot/myboot, e così via, entrando in un loop infinito. In
pratica ciò non genera un loop infinito poiché il sistema è limitato ad effettuare un
determinato numero massimo di dereferenziazioni (seguimenti) di symbolic link
quando viene effettuata un’operazione di risoluzione del nome di un oggetto del
filesystem.
La creazione di un link, sia hard che symbolic, non occupa molto spazio sul disco, poiché non effettua la copia del contenuto del file al quale il link si riferisce.
Il filesystem ext2 gestisce anche i cosiddetti fast link, cioè speciali symbolic link che si riferiscono ad un oggetto del filesystem il cui path ha una lunghezza inferiore a 60 caratteri. In tal caso infatti non vengono utilizzati dei blocchi di dati per memorizzare il path dell’oggetto del filesystem al quale il symbolic (fast) link si riferisce, ma questo viene memorizzato direttamente nell’inode, nello spazio usualmente riservato per memorizzare i riferimenti ai blocchi contenenti i dati del file (lo spazio a disposizione è proprio 15 × 4 = 60 byte - v. il campo i_block della struttura dell’inode riportata a pag. 383). I fast link sono quindi caratterizzati dal fatto che non utilizzano alcun blocco dati per la memorizzazione del loro contenuto (utilizzano soltanto un inode). Un fast link viene creato automaticamente con il comando ln, quando si crea un symbolic link che si riferisce ad un oggetto del filesystem il cui path è inferiore a 60 caratteri.
Il contenuto di un symbolic link (o fast link) può essere visualizzato con il comando readlink (man page readlink(1)).
____________________________________________________________________
Comando: readlink
Path: /usr/bin/readlink
SINTASSI
$ readlink [option] filename
DESCRIZIONE
Alcuni file in GNU/Linux hanno caratteristiche particolari e per questo sono detti file speciali e si dividono in FIFO (o named pipe), file di dispositivo e socket (Unix domain socket). Le FIFO ed i file di dispositivo possono essere creati con il comando mknod (man page mknod(1)) (make inode).
__________________________________________________________________________________________________________
Comando: mknod
Path: /bin/mknod
SINTASSI
$ mknod [option] name type [major minor]
DESCRIZIONE
mentre i socket possono essere creati con il comando socket (man page socket(2)).
Una FIFO, detta anche named pipe, è un file il cui funzionamento è simile a quello di una pipe, cioè come memoria di appoggio per lo scambio di informazioni tra processi. Quando i processi comunicano tra loro attraverso una FIFO, il sistema non utilizza il filesystem, ma il transito delle informazioni avviene direttamente in memoria centrale. Il file serve soltanto come riferimento univoco alla FIFO per i processi che la vogliono utilizzare per comunicare tra loro.22
Il nome FIFO deriva dal fatto che essa opera come una coda, ovvero è gestita in maniera tale che il primo dato in essa inserito è anche quello che viene estratto per primo (First In, First Out).
... immagine ...
Una FIFO può essere creata utilizzando il comando mkfifo (man page mkfifo(1)) (make fifo).
_________________________________________________________________________________________________
Comando: mkfifo
Path: /bin/mkfifo
SINTASSI
$ mkfifo [option] name
DESCRIZIONE
Un processo può accedere in lettura e/o scrittura ad una FIFO, ovvero all’inode (file) presente sul filesystem, soltanto se ha i diritti per poterlo fare, come avviene per tutti gli altri file.
I file di dispositivo o device file sono particolari file che i sistemi Unix-like associano ai dispositivi fisici. Ad esempio, ad un terminale (monitor) è associato un file di dispositivo che rappresenta per il sistema il buffer di output del terminale stesso, ovvero i caratteri scritti in quel file verranno visualizzati sullo schermo; allo stesso modo la tastiera è associata ad un file, ovvero tutto ciò che viene digitato dalla tastiera finisce in tale file ed il sistema operativo leggerà i comandi impartiti da tale file.
Per poter funzionare correttamente con il sistema, ogni dispositivo necessita di un apposito software denominato driver. Tale software ha il compito di far “vedere” il dispositivo al sistema, nel senso che si preoccupa di gestire i meccanismi per la comunicazione con il particolare dispositivo considerato. Quindi è ncessario creare anche un file di dispositivo, con le opportune caratteristiche, da associare al dispositivo stesso.
Un file di dispositivo è caratterizzato da
brw-rw---- 1 root disk 8, 0 May 5 1998 sda
Un file di dispositivo può essere creato con il comando mknod. Ad esempio, se si vuol creare un file di dispositivo relativo ad un controller RAID23, questo deve essere di tipo a blocchi e relativo ad uno specifico major number (es. 72). Se si desidera specificare l’intero RAID deve essere indicato il minor number 0. Il nome del file di dispositivo potrebbe essere scelto convenzionalmente come “c0d0” (controller 0, disco 0). Quindi esso potrebbe essere creato con il comando
# mknod /dev/c0d0 b 72 0
I file di dispositivo sono generalmente contenuti nella directory /dev (v. sez. 4.13.1).
I socket24 costituiscono un’interfaccia di comunicazione tra processi. I socket locali, o Unix domain socket (il nome deriva dal fatto che tale meccanismo di comunicazione è nato in ambiente Unix nel 1983) presi in considerazione in questo contesto, costituiscono il meccanismo di comunicazione tra processi esistenti su una stessa macchina. L’interfaccia dei socket viene attualmente utilizzata per la comunicazione tra processi esistenti anche su macchine diverse, ovvero per realizzare la comunicazione di rete (v. parte II).
Un socket rappresenta un canale di comunicazione tra due processi, nel quale si possono scrivere informazioni e dal quale si possono leggerle. L’interfaccia dei socket è caratterizzata da un’elevata genericità e flessibilità, tanto che si è diffusa in tutti gli ambienti di programmazione, anche in quelli non legati al mondo Unix.
È possibile creare dei socket locali che siano visibili sul filesystem, come per le FIFO. L’accesso a tali socket deve tener conto dei permessi relativi al file che li rappresenta. Ad esempio la creazione di un socket viene rifiutata dal sistema all’interno di una directory nella quale il processo che tenta di creare il socket non ha i diritti di lettura ed esecuzione. Allo stesso modo, per connettersi ad un socket, il processo deve avere i diritti di lettura e scrittura sullo stesso.
[da completare ...]