En Unix, normalmente, un archivo es una entrada en una tabla de archivos. Hay diferentes tipos de archivos: archivos normales, dispositivos, enlaces simbólicos, puertas, tuberías, enchufes, directorios ...
El número de inodo (que puede ver en la salida de ls -i
) es el índice en esa tabla.
Ahora, no accede a los archivos por inodo sino por ruta . Una ruta es una cadena de entradas de directorio . Notarás que no estamos hablando de carpeta sino de directorio aquí. Porque es lo que es un directorio (piense en un directorio telefónico).
Un directorio es un tipo especial de archivo que da nombres a una serie de inodos. Una entrada de directorio es una asignación de un nombre a un inodo.
Un archivo dado (un inodo) puede tener más de un nombre en un directorio (al igual que puede haber más de un nombre en un número de teléfono), y también puede tener nombres (entradas) en más de un directorio. Esos se llaman enlaces también conocidos como enlaces duros para distinguirlos con enlaces blandos (un tipo especial de archivo que es un puntero a una ruta).
Un archivo (inodo) realiza un seguimiento del número de enlaces (de entradas en cualquier directorio) que tiene, de modo que cuando el número llega a 0 (cuando se desvincula del último directorio al que se hizo referencia), se desasigna.
Ese es el número (el número de enlaces) que se muestra en la ls -l
salida.
Cuando se crea un archivo que no directorio de la primera vez (con la open
o creat
(o bind
, o mknod
para algunos tipos de archivos) llamadas al sistema), se realiza proporcionando una ruta de acceso al archivo nuevo (como "/a/b"
). Lo que sucede entonces es que se asigna un nuevo archivo y un inodo y se agrega una nueva entrada al directorio asociado con el "a"
nombre en el "/"
directorio raíz. Ese es el enlace inicial, por lo que el recuento de enlaces es uno.
Se pueden agregar más enlaces más adelante con la link()
llamada al sistema (el ln
comando). Y los enlaces se pueden eliminar con la unlink()
llamada al sistema (el rm
comando).
Notarás que los archivos de tipo directorio generalmente tienen una cantidad de enlaces mayor o igual a 2.
Ahora, cuando crea un directorio, está llamando a la llamada del mkdir()
sistema. Algo así como mkdir("/a/b")
. Lo que hace entonces es asignar un nuevo archivo de tipo directorio. En ese nuevo directorio, crea automáticamente dos entradas:
"."
( punto para el directorio ). Que es un enlace a sí mismo. Entonces el recuento de enlaces ahora es 1.
".."
(para el directorio del directorio ). Que es un enlace a "/a"
. Por lo tanto, el recuento de enlaces "/a"
se incrementa en uno
Luego, se vincula ese nuevo directorio "/a"
(se agrega una entrada "/a"
), por lo que su recuento de enlaces ahora es 2. Si "/a/b/c"
se crea un directorio, debido a la ".."
entrada "/a/b/c"
, el recuento de enlaces "/a/b"
será 3.
La mayoría de los Unices restringen la creación de más enlaces a un directorio porque pueden causar bucles problemáticos. Cuando permiten un link()
en un directorio, generalmente solo el superusuario puede hacerlo.
Algunos sistemas de archivos como btrfs
partir de esa estructura de directorio tradicional. Notará que los recuentos de enlaces en los directorios en btrfs
los sistemas de archivos son siempre uno, aunque esos directorios contienen una "."
entrada con el mismo número de inodo que ellos mismos.
El hecho de que el recuento de enlaces sea tradicionalmente 2 más el número de subdirecciones tiene su uso. Por ejemplo, en:
find . -name '*.c' -print
Si .
no contiene subdires pero contiene millones de archivos. Al verificar el recuento de enlaces de .
, find
puede saber que no hay subdirección. Entonces, todo lo que find
tiene que hacer es leer el contenido del directorio e informar las entradas que terminan en .c
(como grep '\.c$'
en un archivo de pocos megabytes, no es gran cosa). De find
lo contrario, tendría que verificar el tipo de cada archivo para ver si hay directorios para descender allí (lo que da como resultado tantas lstat()
llamadas al sistema). Por supuesto, este tipo de optimización no funciona btrfs
(aunque en las versiones modernas de Linux, el tipo de archivos también se almacena en la entrada del directorio para algunos sistemas de archivos (incluidos btrfs
) y se devuelve mediante la getdents(2)
llamada al sistema utilizada para recuperar la lista de entradas en un directorio, entonceslstat
todavía no es necesario).