Perché è '.' un collegamento reale in Unix?


51

Ho visto molte spiegazioni sul perché il conteggio dei collegamenti per una directory vuota nei sistemi operativi basati su Unix sia 2 anziché 1. Dicono tutti che è a causa del '.' directory, che ogni directory ha ricondotto a se stessa. Capisco perché avere un concetto di "." è utile per specificare percorsi relativi, ma cosa si ottiene implementandolo a livello di filesystem? Perché non solo le shell o le chiamate di sistema che prendono i percorsi sanno come interpretarlo?

Quel '..' è un vero collegamento per me ha molto più senso: il file system deve memorizzare un puntatore nella directory principale per poterlo accedere. Ma non vedo perché '.' essere un vero collegamento è necessario. Sembra anche che porti a un brutto caso speciale nell'implementazione: potresti pensare di poter liberare solo lo spazio utilizzato dagli inode con un numero di collegamenti inferiore a 1, ma se si tratta di directory, devi effettivamente verificare un collegamento conta meno di 2. Perché l'incoerenza?


1
Una volta che hai i ..collegamenti fissi, il tuo software tree walking deve già avere delle eccezioni "non seguire i cicli sul collegamento della directory principale" , quindi è una piccola complessità aggiunta ad eccezione del .collegamento.
dmckee,

Risposte:


37

Una domanda interessante, davvero. A prima vista vedo i seguenti vantaggi:

Prima di tutto dichiari che l'interpretazione " ." come directory corrente può essere fatta dalla Shell o dalle chiamate di sistema. Ma avere la voce dot nella directory rimuove effettivamente questa necessità e forza la coerenza anche a un livello inferiore.

Ma non penso che questa sia stata l'idea alla base di questa decisione progettuale.

Quando un file viene creato o rimosso da una directory, anche il timestamp di modifica della directory deve essere aggiornato. Questo timestamp è memorizzato nel suo inode. Il numero di inode è memorizzato nella corrispondente voce della directory.

SE la voce punto non ci fosse, le routine dovrebbero cercare il numero di inode nella voce per questa directory nella directory padre, che causerebbe nuovamente una ricerca nella directory.

MA per fortuna c'è la voce punto nella directory corrente. La routine che aggiunge o rimuove un file nella directory corrente deve solo tornare alla prima voce (dove di solito risiede la voce punto) e ha immediatamente trovato il numero di inode per la directory corrente.

C'è una terza cosa carina sulla voce punto:

Quando fsckcontrolla un filesystem marcio e deve occuparsi di blocchi non connessi che non sono anche nella lista libera, è facile per lui verificare se un blocco di dati (quando interpretato come un elenco di directory) ha una voce punto che punta a un inode che a sua volta rimanda a questo blocco di dati. In tal caso, questo blocco di dati può essere considerato come una directory persa che deve essere ricollegata.


Risposta molto utile
Navaneeth KN,

6
Il commento sulle routine che cercano l'inode della directory è falso. Le routine del kernel non hanno bisogno di cercare .nella directory corrente. A meno che tu non riesca a trovare un kernel in cui funzioni effettivamente in questo modo (ne dubito ...)
Dietrich Epp

1
Sono d'accordo con @DietrichEpp; affinché il sistema guardi le voci della directory in primo luogo , deve già conoscere l'inode, perché è così che arriva ai blocchi di dati contenenti le voci della directory.
Lqueryvg,

10

(Hmm: il seguente è un po 'epico ...)

Il design della directory su filesystem unix (che, per essere pedanti, sono tipicamente ma non necessariamente collegati ai sistemi operativi unix) rappresenta una visione meravigliosa, che in realtà riduce il numero di casi speciali richiesti.

Una 'directory' è in realtà solo un file nel filesystem. Tutto il contenuto effettivo dei file nel filesystem è inode (dalla tua domanda, posso vedere che sei già a conoscenza di alcune di queste cose). Non c'è struttura per gli inode sul disco: sono solo un grosso mucchio di BLOB numerati di byte, sparsi come burro di arachidi sul disco. Questo non è utile e in effetti è repellente per chiunque abbia un briciolo di ordine mentale.

L' unico inode speciale è l'inode numero 2 (non 0 o 1, per motivi di Tradizione); l'inode 2 è un file di directory: la directory principale . Quando il sistema monta il filesystem, "sa" che deve leggere inode 2 per avviarsi.

Un file di directory è solo un file, con una struttura interna che deve essere letta da opendir (3) e dagli amici. Puoi vedere la sua struttura interna documentata in dir (5) (a seconda del tuo sistema operativo); se lo guardi, vedrai che la voce del file di directory non contiene quasi alcuna informazione sul file, tutto è nell'inode del file. Una delle poche cose speciali di questo file è che la funzione open (2) genererà un errore se si tenta di aprire un file di directory con una modalità che consente la scrittura. Vari altri comandi (per scegliere solo un esempio hexdump) si rifiuteranno di agire normalmente con i file di directory, solo perché probabilmente non è quello che vuoi fare (ma quello è il loro caso speciale, non quello del filesystem).

Un hard link non è altro che una voce nella mappa di un file di directory. Puoi avere due (o più) voci in tale mappa che entrambe mappano allo stesso numero di inode: quell'inode quindi ha due (o più) hard link. Questo spiega anche perché ogni file ha almeno un 'hard link'. L'inode ha un conteggio di riferimento, che registra quante volte l'inode è menzionato in un file di directory da qualche parte nel filesystem (questo è il numero che vedi quando lo fai ls -l).

OK: stiamo arrivando al punto ora.

Il file di directory è una mappa di stringhe ('nomi file') in numeri (numeri di inode). Quei numeri di inode sono i numeri degli inode dei file che sono "in" quella directory. I file che si trovano in quella directory potrebbero includere altri file di directory, quindi i loro numeri di inode saranno tra quelli elencati nella directory. Pertanto, se si dispone di un file /tmp/foo/bar, il file di directory fooinclude una voce per bar, associando quella stringa all'inode per quel file. C'è anche una voce nel file di directory /tmp, per il file di directory fooche è 'nella' directory /tmp.

Quando si crea una directory con mkdir (2), quella funzione

  1. crea un file di directory (con un certo numero di inode) con la struttura interna corretta,
  2. aggiunge una voce alla directory principale, mappando il nome della nuova directory su questo nuovo inode (che rappresenta uno dei collegamenti),
  3. aggiunge una voce alla nuova directory, mappando la stringa '.' allo stesso inode (questo rappresenta l'altro collegamento) e
  4. aggiunge un'altra voce alla nuova directory, mappando la stringa '..' sull'inode del file di directory modificato nel passaggio (2) (questo spiega il maggior numero di hard link che vedrai sui file di directory che contengono sottodirectory ).

Il risultato finale è che (quasi) gli unici casi speciali sono:

  • La funzione open (2) cerca di rendere più difficile spararti ai piedi, impedendoti di aprire i file della directory per la scrittura.
  • La funzione mkdir (2) rende le cose piacevoli e facili aggiungendo un paio di voci extra ('.' E '..') al nuovo file di directory, puramente per rendere conveniente lo spostamento nel filesystem. Ho il sospetto che il filesystem funzionerebbe perfettamente bene senza "." e '..', ma sarebbe un dolore da usare.
  • Il file di directory è uno dei pochi tipi di file che sono contrassegnati come "speciali" - questo è ciò che dice cose come open (2) a comportarsi in modo leggermente diverso. Vedi st_modein stat (2).

(copiato dalla domanda originale di StackOverflow, 20-10-2011)


1
Stai confondendo i blocchi con gli inode. Come caso speciale, per i file brevi, il contenuto del file potrebbe essere all'interno dell'inode, ma è falso affermare che gli inode non sono strutturati. Sono altamente strutturati e contengono quasi tutti i metadati del file tranne i nomi dei file con i quali è possibile trovare il file. L'inode contiene puntatori (diretti, indiretti, doppiamente indiretti, ecc.) Ai blocchi sul disco, dove si trova il contenuto del file.
Phil P

1
No, non confondo i blocchi con gli inode. Gli inode sono un'astrazione situata sopra i blocchi, e lo scopo di questo post era descrivere la relazione tra i file e le directory e il loro contenuto: tutta la struttura del filesystem proviene dai file di directory. Era già abbastanza a lungo senza impantanarsi nelle implementazioni dell'inode! (detto ciò, potrei eventualmente scrivere il primo paio di paragrafi più chiaramente). Inoltre, come vedi, dichiaro esplicitamente che tutte le informazioni sul file (tranne il suo nome) sono nell'inode e non nel file di directory.
Norman Gray,

@NormanGray: anche mentre ti difendi, ti spari in un piede. Hai detto: "Tutto il contenuto effettivo dei file nel filesystem è inode ...." È sbagliato.  Le proprietà / attributi di un file (ad es. Proprietario, permessi, tempo di modifica, ecc.) Sono memorizzati nell'inode. Il contenuto di un normale file è archiviato in blocchi di dati. Se non vuoi impantanarti nelle implementazioni degli inode, allora non farlo, ma per favore non fare anche semplificazioni eccessive fuorvianti.
G-Man dice "Ripristina Monica" il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.