Por que es '.' Un enlace duro en Unix?

51

He visto muchas explicaciones de por qué el recuento de enlaces para un directorio vacío en sistemas operativos basados ​​en Unix es 2 en lugar de 1. Todos dicen que se debe a '.' directorio, que cada directorio tiene apuntando a sí mismo. Entiendo por qué tener algún concepto de '.' es útil para especificar rutas relativas, pero ¿qué se gana al implementarlo a nivel de sistema de archivos? ¿Por qué no solo tener shells o las llamadas al sistema que toman caminos saben cómo interpretarlo?

Ese '...' es un enlace real que tiene mucho más sentido para mí: el sistema de archivos necesita almacenar un puntero de regreso al directorio padre para poder navegar hacia él. Pero no veo por qué '. Ser un enlace real es necesario. También parece que lleva a un caso especial feo en la implementación: pensaría que solo podría liberar el espacio utilizado por los inodos que tienen un recuento de enlaces inferior a 1, pero si son directorios, en realidad necesita verificar un enlace cuenta menos de 2. ¿Por qué la inconsistencia?

Joseph Garvin
fuente
1
Una vez que tenga los ..enlaces duros, su software para caminar por el árbol ya debe tener una excepción de "no seguir ciclos en el enlace del directorio principal" , por lo que se agrega poca complejidad a excepto el .enlace.
dmckee

Respuestas:

37

Una pregunta interesante, de hecho. A primera vista veo las siguientes ventajas:

En primer lugar, declara que la interpretación " ." como el directorio actual puede ser realizada por el Shell o por llamadas del sistema. Pero tener la entrada de punto en el directorio en realidad elimina esta necesidad y fuerza la consistencia incluso en un nivel inferior.

Pero no creo que esta fuera la idea básica detrás de esta decisión de diseño.

Cuando se crea o elimina un archivo de un directorio, también se debe actualizar la marca de tiempo de modificación del directorio. Esta marca de tiempo se almacena en su inodo. El número de inodo se almacena en la entrada del directorio correspondiente.

SI la entrada de puntos no estuviera allí, las rutinas tendrían que buscar el número de inodo en la entrada de este directorio en el directorio padre, lo que provocaría una búsqueda de directorio nuevamente.

PERO afortunadamente hay una entrada de punto en el directorio actual. La rutina que agrega o elimina un archivo en el directorio actual solo tiene que volver a la primera entrada (donde generalmente reside la entrada de puntos) e inmediatamente ha encontrado el número de inodo para el directorio actual.

Hay una tercera cosa buena sobre la entrada de puntos:

Cuando fsckverifica un sistema de archivos podrido y tiene que lidiar con bloques no conectados que tampoco están en la lista libre, es fácil para él verificar si un bloque de datos (cuando se interpreta como una lista de directorio) tiene una entrada de punto que apunta a un inodo que a su vez apunta a este bloque de datos. Si es así, este bloque de datos puede considerarse como un directorio perdido que debe volver a conectarse.

ktf
fuente
Muy útil respuesta.
Navaneeth KN
66
El comentario sobre las rutinas que buscan el inodo del directorio es falso. Las rutinas del kernel no necesitan buscar .en el directorio actual. A menos que pueda encontrar un núcleo donde realmente funcione de esta manera (lo dudo ...)
Dietrich Epp
1
Estoy de acuerdo con @DietrichEpp; para que el sistema esté mirando las entradas del directorio en primer lugar , ya debe saber sobre el inodo, porque así es como llega a los bloques de datos que contienen las entradas del directorio.
Lqueryvg
10

(Hmm: lo siguiente ahora es un poco épico ...)

El diseño del directorio en los sistemas de archivos de Unix (que, para ser pedantes, están típicamente pero no necesariamente unidos a sistemas operativos de Unix) representa una visión maravillosa, que en realidad reduce el número de casos especiales requeridos.

Un 'directorio' es realmente solo un archivo en el sistema de archivos. Todo el contenido real de los archivos en el sistema de archivos está en inodes (de su pregunta, puedo ver que ya está al tanto de algunas de estas cosas). Los inodos en el disco no tienen estructura: son solo un gran grupo de gotas numeradas de bytes, esparcidas como mantequilla de maní sobre el disco. Esto no es útil, y de hecho es repelente para cualquier persona con una pizca de mentalidad ordenada.

La única inode especial es inode número 2 (no 0 o 1, por razones de tradición); inode 2 es un archivo de directorio: el directorio raíz . Cuando el sistema monta el sistema de archivos, "sabe" que tiene que leer el inodo 2 para comenzar.

Un archivo de directorio es solo un archivo, con una estructura interna que debe ser leída por opendir (3) y sus amigos. Puede ver su estructura interna documentada en dir (5) (dependiendo de su sistema operativo); si observa eso, verá que la entrada del archivo de directorio casi no contiene información sobre el archivo, todo eso está en el inodo del archivo. Una de las pocas cosas que tiene de especial este archivo es que la función open (2) generará un error si intenta abrir un archivo de directorio con un modo que permita la escritura. Varios otros comandos (para elegir solo un ejemplo hexdump) se negarán a actuar de la manera normal con los archivos de directorio, solo porque eso probablemente no sea lo que desea hacer (pero ese es su caso especial, no el del sistema de archivos).

Un enlace duro no es más ni menos que una entrada en el mapa de un archivo de directorio. Puede tener dos (o más) entradas en dicho mapa que se mapean al mismo número de inodo: ese inodo, por lo tanto, tiene dos (o más) enlaces duros. Esto también explica por qué cada archivo tiene al menos un 'enlace duro'. El inodo tiene un recuento de referencia, que registra cuántas veces ese inodo se menciona en un archivo de directorio en algún lugar del sistema de archivos (este es el número que ve cuando lo hace ls -l).

OK: estamos llegando al punto ahora.

El archivo de directorio es un mapa de cadenas ('nombres de archivo') a números (números de inodo). Esos números de inodo son los números de los inodes de los archivos que están 'en' ese directorio. Los archivos que están 'en' ese directorio pueden incluir otros archivos de directorio, por lo que sus números de inodo estarán entre los enumerados en el directorio. Por lo tanto, si tiene un archivo /tmp/foo/bar, el archivo de directorio fooincluye una entrada para barasignar esa cadena al inodo para ese archivo. También hay una entrada en el archivo de directorio /tmp, para el archivo de directorio fooque está 'en' el directorio /tmp.

Cuando crea un directorio con mkdir (2), esa función

  1. crea un archivo de directorio (con algún número de inodo) con la estructura interna correcta,
  2. agrega una entrada al directorio principal, asignando el nombre del nuevo directorio a este nuevo inodo (que representa uno de los enlaces),
  3. agrega una entrada al nuevo directorio, asignando la cadena '.' al mismo inodo (esto explica el otro enlace), y
  4. agrega otra entrada al nuevo directorio, asignando la cadena '..' al inodo del archivo de directorio que modificó en el paso (2) (esto explica la mayor cantidad de enlaces duros que verá en los archivos de directorio que contienen subdirectorios )

El resultado final es que (casi) los únicos casos especiales son:

  • La función open (2) intenta dificultar que te dispares en el pie, evitando que abras archivos de directorio para escribir.
  • La función mkdir (2) hace que las cosas sean agradables y fáciles al agregar un par de entradas adicionales ('.' Y '..') al nuevo archivo de directorio, simplemente para que sea conveniente moverse por el sistema de archivos. Sospecho que el sistema de archivos funcionaría perfectamente bien sin '.' y '...', pero sería un dolor de usar.
  • El archivo de directorio es uno de los pocos tipos de archivos que están marcados como 'especiales'; esto es realmente lo que le dice a cosas como open (2) que se comporten de manera ligeramente diferente. Ver st_modeen stat (2).

(copiado de la pregunta original de stackoverflow, 2011-10-20)

Gris normando
fuente
1
Estás confundiendo bloques con inodos. Como caso especial, para archivos cortos, el contenido del archivo puede estar dentro del inodo, pero es falso afirmar que los inodos no están estructurados. Están altamente estructurados y contienen casi todos los metadatos del archivo, excepto los nombres de archivo mediante los cuales se puede encontrar el archivo. El inodo contiene punteros (directos, indirectos, doblemente indirectos, etc.) a los bloques en el disco, donde se encuentra el contenido del archivo.
Phil P
1
No, no estoy confundiendo bloques con inodes. Los inodos son una abstracción situada sobre bloques, y el objetivo de esta publicación fue describir la relación entre los archivos y directorios, y su contenido: toda la estructura del sistema de archivos proviene de los archivos de directorio. ¡Ya fue lo suficientemente largo como para no quedar empantanado en implementaciones de inodo! (Dicho esto, posiblemente podría escribir los primeros párrafos más claramente). Además, como puede ver, declaro explícitamente que toda la información sobre el archivo (excepto su nombre) está en el inodo y no en el archivo de directorio.
Norman Gray el
@ NormanGray: incluso mientras te defiendes, te disparas en el pie. Usted dijo: "Todo el contenido real de los archivos en el sistema de archivos está en inodes ..." Eso está mal.  Las propiedades / atributos de un archivo (por ejemplo, propietario, permisos, tiempo de modificación, etc.) se almacenan en el inodo. El contenido de un archivo ordinario se almacena en bloques de datos. Si no desea atascarse en implementaciones de inodo, entonces no lo haga, pero tampoco haga simplificaciones excesivas engañosas.
G-Man dice 'Reincorporar a Monica' el