¿Por qué los enlaces duros a directorios no están permitidos en UNIX / Linux?

130

Leí en libros de texto que Unix / Linux no permite enlaces duros a directorios, pero sí permite enlaces blandos. ¿Es porque, cuando tenemos ciclos y si creamos enlaces duros, y después de un tiempo eliminamos el archivo original, señalará algún valor basura?

Si los ciclos fueron la única razón detrás de no permitir enlaces duros, entonces ¿por qué se permiten enlaces blandos a directorios?

usuario3539
fuente
2
¿A dónde debe ..apuntar? Especialmente después de eliminar el enlace duro a este directorio, en el directorio señalado por ..? Necesita apuntar a alguna parte.
Thorbjørn Ravn Andersen
2
..no necesita existir físicamente en ninguna unidad. De todos modos, el trabajo del sistema operativo es realizar un seguimiento del directorio de trabajo actual, por lo que debería ser relativamente simple también mantener una lista de inodos asociados con cada proceso 'cwd y referirse a eso cuando vea un uso de ... Por supuesto, eso significaría que los enlaces simbólicos deberían crearse con eso en mente, pero ya debes tener cuidado de no romper los enlaces simbólicos, y no creo que una regla adicional los haga inútiles.
Parthian Shot
Me gusta esta explicación . Conciso y fácil de leer y / o descremado.
Trevor Boyd Smith

Respuestas:

143

Esta es solo una mala idea, ya que no hay forma de distinguir entre un enlace duro y un nombre original.

Permitir enlaces duros a directorios rompería la estructura gráfica gráfica acíclica del sistema de archivos, posiblemente creando bucles de directorio y colgando subárboles de directorio, lo que haría que fsckcualquier otro caminante de árbol de archivos sea propenso a errores.

Primero, para entender esto, hablemos de inodes. Los datos en el sistema de archivos se mantienen en bloques en el disco, y esos bloques se recopilan juntos por un inodo. Puedes pensar en el inodo como EL archivo. Sin embargo, los Inodes carecen de nombres de archivo. Ahí es donde entran los enlaces.

Un enlace es solo un puntero a un inodo. Un directorio es un inodo que contiene enlaces. Cada nombre de archivo en un directorio es solo un enlace a un inodo. Abrir un archivo en Unix también crea un enlace, pero es un tipo diferente de enlace (no es un enlace con nombre).

Un enlace duro es solo una entrada de directorio adicional que apunta a ese inodo. Cuando usted ls -l, el número después de los permisos es el número de enlaces con nombre. La mayoría de los archivos regulares tendrán un enlace. Crear un nuevo enlace duro a un archivo hará que ambos nombres de archivo apunten al mismo inodo. Nota:

% ls -l test
ls: test: No such file or directory
% touch test
% ls -l test
-rw-r--r--  1 danny  staff  0 Oct 13 17:58 test
% ln test test2
% ls -l test*
-rw-r--r--  2 danny  staff  0 Oct 13 17:58 test
-rw-r--r--  2 danny  staff  0 Oct 13 17:58 test2
% touch test3
% ls -l test*
-rw-r--r--  2 danny  staff  0 Oct 13 17:58 test
-rw-r--r--  2 danny  staff  0 Oct 13 17:58 test2
-rw-r--r--  1 danny  staff  0 Oct 13 17:59 test3
            ^
            ^ this is the link count

Ahora, puede ver claramente que no existe un enlace duro. Un enlace duro es lo mismo que un nombre normal. En el ejemplo anterior, testo test2, ¿cuál es el archivo original y cuál es el enlace duro? Al final, realmente no se puede saber (incluso por marcas de tiempo) porque ambos nombres apuntan al mismo contenido, el mismo inodo:

% ls -li test*  
14445750 -rw-r--r--  2 danny  staff  0 Oct 13 17:58 test
14445750 -rw-r--r--  2 danny  staff  0 Oct 13 17:58 test2
14445892 -rw-r--r--  1 danny  staff  0 Oct 13 17:59 test3

La -ibandera a lsmuestra números de inodo al comienzo de la línea. Observe cómo testy test2tiene el mismo número de inodo, pero test3tiene uno diferente.

Ahora, si se le permitiera hacer esto para los directorios, dos directorios diferentes en diferentes puntos del sistema de archivos podrían apuntar a lo mismo. De hecho, un subdirectorio podría señalar a su abuelo, creando un bucle.

¿Por qué es este bucle una preocupación? Porque cuando está atravesando, no hay forma de detectar que está haciendo un bucle (sin hacer un seguimiento de los números de inodo mientras atraviesa). Imagine que está escribiendo el ducomando, que debe repetirse a través de subdirectorios para obtener información sobre el uso del disco. ¿Cómo dusabría cuando golpeó un bucle? Es propenso a errores y una gran cantidad de contabilidad que dutendría que hacer, solo para llevar a cabo esta sencilla tarea.

Los enlaces simbólicos son una bestia completamente diferente, ya que son un tipo especial de "archivo" que muchas API del sistema de archivos tienden a seguir automáticamente. Tenga en cuenta que un enlace simbólico puede apuntar a un destino inexistente, porque apuntan por su nombre y no directamente a un inodo. Ese concepto no tiene sentido con los enlaces duros, porque la mera existencia de un "enlace duro" significa que el archivo existe.

Entonces, ¿por qué puede dulidiar con enlaces simbólicos fácilmente y no con enlaces duros? Pudimos ver arriba que los enlaces duros no se pueden distinguir de las entradas normales del directorio. Sin embargo, los enlaces simbólicos son especiales, detectables y omitibles.  duse da cuenta de que el enlace simbólico es un enlace simbólico y lo omite por completo.

% ls -l 
total 4
drwxr-xr-x  3 danny  staff  102 Oct 13 18:14 test1/
lrwxr-xr-x  1 danny  staff    5 Oct 13 18:13 test2@ -> test1
% du -ah
242M    ./test1/bigfile
242M    ./test1
4.0K    ./test2
242M    .
Danny Dulai
fuente
77
Allowing hard links to directories would break the directed acyclic graph structure of the filesystem. ¿Puede explicar más sobre el problema con los ciclos que usan enlaces duros? ¿Por qué está bien con enlaces simbólicos
User3539
33
Parecen haberlo permitido en Mac al agregar detección de ciclo a la llamada al sistema link () y al negarse a permitirle crear un enlace rígido de directorio si crearía un ciclo. Parece ser una solución razonable.
psusi
10
@psusi mkdir -pa / b; nocheckln ca; mv ca / ​​b; - La nocheckln hay un ln teórico que no comprueba los argumentos del directorio, y simplemente pasa al enlace, y como no se realiza ningún ciclo, todos somos buenos para crear 'c'. luego movemos 'c' a 'a / b', y se crea un ciclo a partir de a / b / c -> a / - verificar el enlace () no es lo suficientemente bueno
Danny Dulai
3
Los ciclos son muy malos. Windows tiene este problema con las "uniones", que son directorios de enlaces duros. Si accidentalmente aplica permisos a todo su perfil, descubre una serie de uniones que crean un ciclo infinito. La recurrencia a través de los directorios se repite hasta que las limitaciones de longitud de ruta lo detengan.
doug65536
44
@WhiteWinterWolf, de acuerdo con este enlace, se añadió específicamente apoyo a la misma para la máquina del tiempo, pero se le permite hacerlo sólo root: superuser.com/questions/360926/...
psusi
14

Con la excepción de los puntos de montaje, cada directorio tiene una y sólo los padres: ...

Una forma de hacerlo pwdes verificar el dispositivo: inodo para '.' y '..'. Si son iguales, ha llegado a la raíz del sistema de archivos. De lo contrario, busque el nombre del directorio actual en el padre, insértelo en una pila y comience a comparar '../.' con '../ ..', luego '../../.' con '../../ ..', etc. Una vez que haya alcanzado la raíz, comience a aparecer e imprimir los nombres de la pila. Este algoritmo se basa en el hecho de que cada directorio tiene uno y solo un padre.

Si se permitieran enlaces duros a directorios, ¿a cuál de los padres múltiples debería ..apuntar? Esa es una razón convincente por la cual los enlaces duros a directorios no están permitidos.

Los enlaces simbólicos a directorios no causan ese problema. Si un programa lo desea, podría hacer un lstat()en cada parte del nombre de ruta y detectar cuándo se encuentra un enlace simbólico. El pwdalgoritmo devolverá el verdadero nombre de ruta absoluto para un directorio de destino. El hecho de que haya un fragmento de texto en alguna parte (el enlace simbólico) que apunta al directorio de destino es prácticamente irrelevante. La existencia de tal enlace simbólico no crea un bucle en el gráfico.

Joe Inwap
fuente
3
No estoy tan seguro de esto. Si consideramos que ..se trata de una especie de enlace rígido virtual con el padre, no hay ninguna razón técnica para que el objetivo del enlace solo pueda tener otro enlace. pwdsolo tendría que usar un algoritmo diferente para resolver el camino.
Benubird
13

Puede usar bind mount para simular directorios de enlaces duros

sudo mount --bind /some/existing_real_contents /else/dummy_but_existing_directory
sudo umount /else/dummy_but_existing_directory
zainengineer
fuente
7

Me gustaría agregar algunos puntos más sobre esta pregunta. Los enlaces duros para directorios están permitidos en Linux, pero de forma restringida.

Una forma de probar esto es cuando enumeramos el contenido de un directorio y encontramos dos directorios especiales "". y "..". Tal como lo conocemos "." apunta al mismo directorio y ".." apunta al directorio padre.

Entonces, creemos un árbol de directorios donde "a" es el directorio padre que tiene el directorio "b" como hijo.

 a
 `-- b

Anote el inodo del directorio "a". Y cuando hacemos un ls -ladirectorio desde "a" podemos ver eso "." El directorio también apunta al mismo inodo.

797358 drwxr-xr-x 3 mkannan mkannan 4096 Sep 17 19:13 a

Y aquí podemos encontrar que el directorio "a" tiene tres enlaces duros. Esto se debe a que el inodo 797358 tiene tres enlaces duros en el nombre de "." dentro del directorio "a" y nombre como ".." dentro del directorio "b" y uno con el nombre "a" itslef.

$ ls -ali a/
797358 drwxr-xr-x 3 mkannan mkannan 4096 Sep 17 19:13 .

$ ls -ali a/b/
797358 drwxr-xr-x 3 mkannan mkannan 4096 Sep 17 19:13 ..

Entonces, aquí podemos entender que los enlaces rígidos están allí para que los directorios solo se conecten con sus directorios padre e hijo. Y así, un directorio sin un hijo solo tendrá 2 enlaces duros, y así el directorio "b" tendrá solo dos enlaces duros.

Una razón por la cual se impidió la vinculación de directorios libremente sería evitar bucles de referencia infinitos que confundirán los programas que atraviesan el sistema de archivos.

Como el sistema de archivos está organizado como árbol y el árbol no puede tener una referencia cíclica, esto debería haberse evitado.

Kannan Mohan
fuente
1
Buen ejemplo. Se aclaró mi duda. Por lo tanto, estos casos se manejan de una manera especial para evitar bucles infinitos. ¿derecho?
G Gill
1
Como tenemos una forma limitada de permitir enlaces duros para directorios, es decir, ".." y "." no alcanzaremos un bucle infinito, por lo que no necesitaríamos ninguna forma especial de evitarlos, ya que no sucederán :)
Kannan Mohan
6

Ninguno de los siguientes es la verdadera razón para no permitir enlaces duros a directorios; Cada problema es bastante fácil de resolver:

  • los ciclos en la estructura del árbol causan un recorrido difícil
  • padres múltiples, entonces, ¿cuál es el "real"?
  • sistema de archivos de recolección de basura

La verdadera razón (como lo insinuó @ Thorbjørn Ravn Andersen) se produce cuando elimina un directorio que tiene varios padres, del directorio señalado por ..:

¿Qué debería ..señalar ahora?

Si el directorio se elimina de su padre pero su recuento de enlaces sigue siendo mayor que 0entonces, debe haber algo, en algún lugar que todavía lo apunte. No puedes dejar de ..apuntar a nada; muchos programas dependen .., por lo que el sistema tendría que recorrer todo el sistema de archivos hasta que encuentre lo primero que apunta al directorio eliminado, solo para actualizar ... O eso, o el sistema de archivos tendría que mantener una lista de todos los directorios que apuntan a un directorio vinculado.

De cualquier manera, esto sería una sobrecarga de rendimiento y una complicación adicional para los metadatos y / o el código del sistema de archivos, por lo que los diseñadores decidieron no permitirlo.

Lqueryvg
fuente
3
Eso también es fácil de resolver: mantenga una lista de los padres de un directorio secundario, que actualiza cuando agrega o elimina un enlace al elemento secundario. Cuando elimine el padre canónico (el objetivo del niño ..), actualice ..para señalar a uno de los otros padres en la lista.
jathd
2
Estoy de acuerdo. No es ciencia espacial para resolver. Pero, no obstante, una sobrecarga de rendimiento, y ocuparía un poco más de espacio en los metadatos del sistema de archivos y agregaría complicaciones. Y los diseñadores optaron por un enfoque simple y rápido: no permitir enlaces a directorios rígidos.
Lqueryvg
1
Los enlaces Sym a directorios "violan la semántica y los comportamientos establecidos", pero aún están permitidos. Por lo tanto, algunos comandos necesitan opciones para controlar si se siguen los enlaces sym (por ejemplo, -L en find y cp). Cuando un programa sigue a '...' hay más confusión, de ahí la diferencia en la salida de pwd y / bin / pwd después de atravesar un enlace simétrico. No hay "respuestas Unix"; solo decisiones de diseño. Éste gira en torno a lo que se convierte en ".." como dije en mi respuesta. Desafortunadamente, '...' ni siquiera se menciona en la respuesta que todos los demás votan tan tímidamente.
Lqueryvg
Por cierto, no estoy diciendo que estoy a favor de los enlaces duros a directorios. De ningún modo. No quiero que mi trabajo diario sea más difícil de lo que ya es.
Lqueryvg
No es lo que dice POSIX, pero IMO '...' nunca debería haber sido un concepto de sistema de archivos, sino que se resolvió sintácticamente en las rutas, por lo que eso a/..siempre significaría .. Así es como funcionan las URL, por cierto. Es el navegador que está resolviendo '...' incluso antes de que llegue al servidor. Y funciona muy bien.
ybungalobill
3

La creación de enlaces en los directorios sería irrevertable. Supongamos que tenemos:

/dir1
├──this.txt
├──directory
│  └──subfiles
└──etc

Me HardLink a /dir2.

Así que /dir2ahora también contiene todos estos archivos y directorios

¿Qué pasa si cambio de opinión? No puedo simplemente rmdir /dir2(porque no está vacío)

Y si elimino recursivamente en /dir2... ¡también se eliminará /dir1!

En mi humilde opinión es una razón en gran medida suficiente para evitar esto!

Editar:

Los comentarios sugieren eliminar el directorio haciendo rmen él. Pero rmen un directorio no vacío falla, y este comportamiento debe permanecer, ya sea que el directorio esté vinculado o no. Entonces no puedes simplemente rmdesvincularlo. Requeriría un nuevo argumento rm, solo para decir "si el inodo del directorio tiene un recuento de referencias> 1, entonces solo desvincula el directorio".

Lo que, a su vez, rompe otro principio de menor sorpresa: significa que la eliminación de un enlace de directorio que acabo de crear no es lo mismo que la eliminación de un enlace de archivo normal ...

Reformularé mi oración: sin un mayor desarrollo, la creación del enlace rígido sería irrevertable (ya que ningún comando actual podría manejar la eliminación sin ser incoherente con el comportamiento actual)

Si permitimos que más desarrollo maneje el caso, la cantidad de trampas y el riesgo de pérdida de datos si no está lo suficientemente consciente de cómo funciona el sistema, tal desarrollo implica, en mi humilde opinión, es una razón suficiente para restringir el hardlinking en los directorios.

Pierre-Olivier Vares
fuente
Eso no debería ser un problema. Con su caso, cuando creamos un enlace rígido a dir2, tenemos que hacer un enlace rígido a todos los contenidos en dir1 y, por lo tanto, si cambiamos el nombre o eliminamos dir2, solo se eliminará un enlace adicional al inodo. Y eso no debería afectar a dir1 y su contenido, ya que hay al menos un enlace (dir1) al inodo.
Kannan Mohan
3
Tu argumento es incorrecto. Simplemente lo desvincularías, no harías rm -rf. Y si el recuento de enlaces llega a 0, entonces el sistema sabría que también puede eliminar todos los contenidos.
LtWorf
Eso es más o menos todo rmlo que hay debajo de todos modos (desvincular). Ver: unix.stackexchange.com/questions/151951/… Esto realmente no es un problema, como tampoco lo es con los archivos enlazados. Desvincular solo elimina la referencia nombrada y disminuye el recuento de enlaces. El hecho de que rmdirno elimine directorios no vacíos es irrelevante; tampoco lo haría para dir1 ninguno. Los enlaces duros no son copias de datos, son el mismo archivo real, por lo tanto, "borrar" el archivo dir2 borrará la lista de directorios de dir1. Siempre necesitarías desvincularte.
BryKKan
No puede simplemente desvincularlo como un archivo normal, porque rmen un directorio no lo desvincula si no está vacío. Ver Editar.
Pierre-Olivier Vares
1

Esta es una buena explicación. Con respecto a "¿Cuál de los padres múltiples debería ... señalar?" Una solución sería que un proceso mantenga su ruta wd completa, ya sea como inodes o como una cadena. los inodes serían más robustos ya que los nombres pueden cambiarse. Al menos en los viejos tiempos, había un inodo en el núcleo para cada archivo abierto que se incrementaba cada vez que se abría un archivo, que disminuía cuando se cerraba. Cuando llegara a cero, se liberaría el almacenamiento al que apuntaba. Cuando el archivo ya no esté abierto por nadie, se abandonará (la copia interna). Esto mantendría la ruta como válida si algún otro proceso moviera un directorio a otro directorio mientras el subdirectorio estaba en la ruta de otro proceso. Similar a cómo puede eliminar un archivo abierto, pero simplemente se elimina del directorio,

Los directorios de conexión dura solían permitirse libremente en Bell Labs UNIX, al menos V6 y V7, No sé sobre Berkeley o posterior. No se requiere bandera. ¿Podrías hacer bucles? Sí, no hagas eso. Está muy claro lo que estás haciendo si haces un bucle. Nether deberías practicar un nudo alrededor de tu cuello mientras esperas tu turno para saltar en paracaídas de un avión si tienes el otro extremo convenientemente colgado de un gancho en el mamparo.

Lo que esperaba hacer con él hoy era vincular de forma permanente lhome a home para poder tener / home / administ disponible, ya sea que / home estuviera cubierto con un automout sobre home, ese automount con un enlace simbólico llamado administ to / lhome / administ. Esto me permite tener una cuenta administrativa que funciona independientemente del estado de mi sistema de archivos de inicio principal. Este ES un experimento para Linux, pero creo que aprendí una vez para SunOS basado en UCB que los montajes automáticos se realizan a nivel de cadena ASCII. Es difícil ver cómo se podrían hacer de otra manera como una capa encima de cualquier FS arbitrario.

Leí en otro lado eso. y ... tampoco son archivos en el directorio. Estoy seguro de que hay buenas razones para todo esto, y que gran parte de lo que disfrutamos (como poder montar NTFS) es posible debido a tales cosas, pero parte de la elegancia de UNIX estaba en la implementación. Son los beneficios, como la generalidad y la maleabilidad que proporciona esta elegancia, lo que le ha permitido ser tan robusto y duradero durante cuatro décadas. A medida que perdamos las elegantes implementaciones, eventualmente se volverá como Windows (¡espero estar equivocado!). Entonces, alguien crearía un nuevo sistema operativo que se basa en principios elegantes. Algo sobre lo que pensar. Quizás estoy equivocado, no estoy (obviamente) familiarizado con la implementación actual. que es aunque increíble lo aplicable que es la comprensión de 30 años para Linux ... ¡la mayoría de las veces!

user57607
fuente
Creo, aunque puedo estar equivocado, eso .y ..no son enlaces duros en el sistema de archivos, para los sistemas de archivos modernos. Sin embargo, el controlador del sistema de archivos los falsifica. Son estos sistemas de archivos los que detienen los directorios de enlace duro. Para sistemas de archivos antiguos era posible (pero peligroso). Para hacer lo que está intentando, mire mount --bind, vea también mount --make…y tal vez contenedores.
ctrl-alt-delor
0

Por lo que deduzco, la razón principal es que es útil poder cambiar los nombres de directorio sin alterar los programas en ejecución que usan su directorio de trabajo para hacer referencia a otros archivos. Suponga que está utilizando Wine para ejecutar ~/.newwineprefix/drive_c/Program Files/Firefox/Firefox.exe, y desea mover todo el prefijo en su ~/.winelugar. Si por alguna extraña razón a la que Firefox accedía drive_c/windowsal hacer referencia ../../windows, el cambio de nombre ~/.newwineprefixinterrumpe las implementaciones de ..ese seguimiento del directorio principal como una cadena de texto en lugar de un inodo.

Almacenar el inodo de un solo directorio padre debe ser más simple que tratar de hacer un seguimiento de cada ruta como una cadena de texto y una serie de inodes.

Otra razón es que las aplicaciones que se comportan mal pueden crear bucles. Las aplicaciones de comportamiento deberían poder verificar si el inodo del directorio que se está moviendo es el mismo que el inodo de cualquiera de los directorios anidados al que se está moviendo, al igual que no se puede mover un directorio en sí mismo, pero es posible que esto no se aplique a nivel del sistema de archivos.

Otra razón más podría ser que si pudieras vincular directorios, querrás evitar vincular un directorio que no puedas modificar. findtiene consideraciones de seguridad porque se usa para borrar archivos creados por otros usuarios de directorios temporales, lo que puede causar problemas si un usuario cambia un directorio real para un enlace simbólico mientras findinvoca otro comando. Ser capaz de enlazar directorios importantes obligaría a un administrador a agregar pruebas adicionales findpara evitar afectarlos. (Ok, ya no puede hacer esto para los archivos, por lo que este motivo no es válido).

Otra razón más es que almacenar el inodo del directorio principal puede proporcionar redundancia adicional en caso de corrupción o daño del sistema de archivos. Si desea ..enumerar todos los directorios principales que se enlazan con este, por lo que se podría encontrar fácilmente un padre diferente y arbitrario si el actual está desvinculado, no solo está violando la idea de que los enlaces duros son iguales, sino que debe cambiar la forma en que El sistema de archivos almacena y utiliza inodes. Hacer que los programas traten las rutas como una serie (única para cada enlace duro) de inodos de directorio evitaría esto, pero no obtendría la redundancia en caso de daños en el sistema de archivos.

Misaki
fuente