Su Unix, in genere, un file è una voce in una tabella di file. Esistono diversi tipi di file: file regolari, dispositivi, collegamenti symbolik, porte, pipe, socket, directory ...
Il numero di inode (che puoi vedere nell'output di ls -i
) è l'indice in quella tabella.
Ora, non accedi ai file per inode ma per percorso . Un percorso è una catena di voci della directory . Noterai che non stiamo parlando di cartella ma di directory qui. Perché è quello che è una directory (pensa a una rubrica telefonica).
Una directory è un tipo speciale di file che dà nomi a un numero di inode. Una voce di directory è una mappatura da un nome a un inode.
Un determinato file (un inode) può avere più di un nome in una directory (proprio come può esserci più di un nome in un numero di telefono) e può anche avere nomi (voci) in più di una directory. Questi sono chiamati collegamenti noti anche come collegamenti reali per distinguere con collegamenti software (un tipo speciale di file che è un puntatore a un percorso).
Un file (inode) tiene traccia del numero di collegamenti (di voci in qualsiasi directory) che ha, in modo che quando il numero raggiunge 0 (quando viene scollegato dall'ultima directory in cui è stato fatto riferimento), viene deallocato.
Questo è quel numero (il numero di collegamenti) che viene visualizzato ls -l
nell'output.
Quando un file non di directory viene creato per la prima volta (con le chiamate di sistema open
o creat
(o bind
o mknod
per alcuni tipi di file)), viene eseguito fornendo un percorso al nuovo file (come "/a/b"
). Quello che succede allora è un nuovo file e l'inode viene allocato e una nuova voce viene aggiunta alla directory associata al "a"
nome nella "/"
directory principale. Questo è il collegamento iniziale, quindi il conteggio dei collegamenti è uno.
Più collegamenti possono essere aggiunti in seguito con la link()
chiamata di sistema (il ln
comando). E i collegamenti possono essere rimossi con la unlink()
chiamata di sistema (il rm
comando).
Noterai che i file di tipo directory hanno generalmente un numero di collegamenti maggiore o uguale a 2.
Ora, quando crei una directory, stai chiamando la mkdir()
chiamata di sistema. Qualcosa del genere mkdir("/a/b")
. Ciò che fa quindi è allocare un nuovo file di tipo directory. In quella nuova directory, crea automaticamente due voci:
"."
( punto per directory ). Quale è un collegamento a se stesso. Quindi il conteggio dei collegamenti è ora 1.
".."
(per la directory della directory ). Che è un collegamento a "/a"
. Quindi il conteggio dei collegamenti di "/a"
viene incrementato di uno
Quindi quella nuova directory viene collegata "/a"
(viene aggiunta una voce "/a"
per essa), quindi il suo conteggio dei collegamenti è ora 2. Se "/a/b/c"
viene creata una directory, a causa della ".."
voce in "/a/b/c"
, il conteggio dei collegamenti "/a/b"
diventerà 3.
La maggior parte degli Unices limita la creazione di ulteriori collegamenti a una directory perché possono causare loop problematici. Quando consentono a link()
su una directory, generalmente solo il superutente può farlo.
Alcuni filesystem come si btrfs
allontanano da quella struttura di directory tradizionale. Noterai che i conteggi dei collegamenti nelle directory nei btrfs
file system sono sempre uno anche se tali directory contengono una "."
voce con lo stesso numero di inode di loro stessi.
Il fatto che il conteggio dei collegamenti sia tradizionalmente 2 più il numero di sottodiretti è utile. Ad esempio, in:
find . -name '*.c' -print
Se .
non contiene sottodirectory ma contiene milioni di file. Controllando il conteggio dei collegamenti di .
, è find
possibile sapere che non esiste un sottodir. Quindi tutto ciò che find
deve fare è leggere il contenuto della directory e riportare le voci che finiscono .c
(come un grep '\.c$'
file da pochi megabyte, nessun grosso problema). Altrimenti, find
dovrebbe controllare il tipo di ogni singolo file per vedere se ci sono delle directory in cui scendere (risultando in altrettante lstat()
chiamate di sistema). Ovviamente, questo tipo di ottimizzazione non funziona btrfs
(sebbene nelle versioni moderne di Linux, il tipo di file sia anche memorizzato nella voce della directory per alcuni filesystem (incluso btrfs
) e restituito dalla getdents(2)
chiamata di sistema utilizzata per recuperare l'elenco delle voci in una directory, quindilstat
non è ancora necessario).