La Gaceta de Linux ...¡ haciendo a Linux un poco más divertido !

Q & A: La diferencia entre enlaces duros y suaves

Por Lew Pitcher

Traducción al español por Fernando Frias
el día 1 de Febrero de 2005, para La Gaceta de Linux

Participe en cera de 30 grupos de noticias, y en un LUG virtual, las preguntas continuaban llegando. He respondido un par de esas preguntas lo sufuciente como para tener 'caliente' una respuesta, la cual modifico, dependiendo de las circunstancias.

Aqui esta una, ahora...

Q: Puede alguien darme una explicación simple de la diferencia entre un enlace duro y un enlace suave? La documentación que he leido menciona estos enlaces pero no explica suficientemente su significado ni como/cuando usarlos. Gracias!

A: Bien, Lo Intentare...

Los archivos en Unix constan de dos partes: la parte de datos y la parte del nombre de archivo.

La parte de datos esta asociada con algo llamado un 'inode'. El inode carga el mapa de donde estan ubicados los datos, los permisos del archivo, etc. para los datos.


                               .---------------> ! dato ! ! dato ! etc
                              /                  +------+ !------+
        ! permbits, etc ! direcciones de datos !
        +------------inode---------------------+

La parte del nombre de archivo carga el nombre y el número de inode asociado.

                               .--------------> ! permbits, etc ! direcciones!
                              /                    +---------inode--------------+
        ! nombre archivo ! inode # !
        +--------------------------+

Mas de un archvio puede hacer referencia el mismo número de inode; esos archivos son llamados a ser 'hard linked' juntos.

        ! nombre archivo! inode # !
        +-------------------------+
                        \
                         >--------------> ! permbits, etc ! direcciones!
                        /                       +----------inode-------------+
        ! otro nombre ! inode # !
        +-----------------------+

Por el otro lado, hay un tipo de archivo especial cuya parte de datos carga una ruta a otro archivo. Debido a que es un archivo especial, el OS reconoce los datos como uan ruta, y redirecciona aperturas, lecturas, y escrituras que, en lugar de accesar a los datos con el archivo especial, accesan los datos usando en el archivo named por los datos en el archivo especial. Este archivo especial es llamado un 'enlace suave' o un 'enlace simbolico' (aka a 'symlink').

        ! nombre de arachivo! inode # !
        +-----------------------------+
                                \
                                 .-------> ! permbits, etc ! addresses !
                                           +---------inode-------------+
                                                      /
                                                     /
                                                    /
    .----------------------------------------------'
   ( 
    '-->  !"/ruta/a/algun/otror/archivo"! 
          +---------data-------------------+
                  /                      }
    .~ ~ ~ ~ ~ ~ ~                       }-- (redireccionado en tiempo open())
   (                                     }
    '~~> ! nombre de archivo ! inode # !
         +--------------------------------+
                                     \
                                      '------------> ! permbits, etc ! direcciones !
                                                        +---------inode---------------+
                                                                            /
                                                                           /
     .--------------------------------------------------------------------'
    (
     '->  ! dato !  ! dato ! etc.
          +------+  +------+ 

Ahora, la parte del nombre de archivo esta ubicada en un archivo especial de su propiedad junto con la parte de nombre de archivo de otros archivos; este archivo especial es llamado un directorio. El directorio, como un archivo, es solo un arreglo de partes de nombre de archivo de otros archivos.

Cuando un directorio esta construido, esta inicialmente cargado con la parte de nombres de archivo de dos archivos especiales : los archivos '.' y '..'. La parte de nombres de archivo de del archivo '.' esta cargado con el inode# del archivo directorio cuya entrada ha sido hecha; '.' es un enlace duro al archvio que implementa el directorio actual.

La parte de nombre de archivo del archivo '..' esta cargada con el inode# del archivo directorio que contiene la parte de nombre de archivo del directorio actual . '..' es un enalce duro al archivo que implementa el padre inmediato del directorio actual. A

El comando 'ln' sabe como contruir enalces duros y enlaces suaves; el comando 'mkdir' sabe como construir directorios (el OS tiene cuidad de los enlaces duros de arriba).

Hay restricciones sobre como pueden ser enlazados (ambos enalces deben residir sobre el mismo sistema de archvios, el archivo fuente debe existir, etc.) no hay aplicalbe a enalces suaves (fuente y destino pueden estar sobre sistemas de arvhivo separados, los fuentes no tienen que existir, etc.). OTOH, los enlaces suaves tienen otras restricciones no compartidas por los enlaces duros (adicionales I/O son necesarios para completar el acceso de archivo, almacenamiento adicional es tomado por los enlaces suaves de archivos de datos, etc.)

En otras palabras, hay diferencias entre ambos.

Ahora, demostremos algo de esto...

ln en acción

Empecemos con un directorio vacio, creando un archivo en el

~/directory $ ls -lia 
total 3
  73477 drwxr-xr-x   2 lpitcher users        1024 Mar 11 20:16 .
  91804 drwxr-xr-x  29 lpitcher users        2048 Mar 11 20:16 ..

~/directory $ echo "Esto es un archivo" >basic.file

~/directory $ ls -lia 
total 4
  73477 drwxr-xr-x   2 lpitcher users        1024 Mar 11 20:17 .
  91804 drwxr-xr-x  29 lpitcher users        2048 Mar 11 20:16 ..
  73478 -rw-r--r--   1 lpitcher users          15 Mar 11 20:17 basic.file

~/directory $ cat basic.file
Esto es un archivo
Ahora, hagamos un enlace duro al archivo
   
~/directory $ ln basic.file hardlink.file

~/directory $ ls -lia 
total 5
  73477 drwxr-xr-x   2 lpitcher users        1024 Mar 11 20:20 .
  91804 drwxr-xr-x  29 lpitcher users        2048 Mar 11 20:18 ..
  73478 -rw-r--r--   2 lpitcher users          15 Mar 11 20:17 basic.file
  73478 -rw-r--r--   2 lpitcher users          15 Mar 11 20:17 hardlink.file

~/directory $ cat hardlink.file
Esto es un archivo

Vemos que:

  1. hardlink.file comparte el mismo (73478) como basic.file
  2. hardlink.file comparte los mismos datos como basic.file

Si cambiamos los permisos sobre basic.file:

~/directory $ chmod a+w basic.file

~/directory $ ls -lia 
total 5
  73477 drwxr-xr-x   2 lpitcher users        1024 Mar 11 20:20 .
  91804 drwxr-xr-x  29 lpitcher users        2048 Mar 11 20:18 ..
  73478 -rw-rw-rw-   2 lpitcher users          15 Mar 11 20:17 basic.file
  73478 -rw-rw-rw-   2 lpitcher users          15 Mar 11 20:17 hardlink.file

entonces los mismos permisos cambian sobre hardlink.file.

Los dos archivos (basic.file y hardlink.file) comparten el mismo inode y datos, pero tienen diferentes nombres de archivo.

Ahora hagamos un enlace suave a el archivo original:

~/directory $ ln -s basic.file softlink.file

~/directory $ ls -lia 
total 5
  73477 drwxr-xr-x   2 lpitcher users        1024 Mar 11 20:24 .
  91804 drwxr-xr-x  29 lpitcher users        2048 Mar 11 20:18 ..
  73478 -rw-rw-rw-   2 lpitcher users          15 Mar 11 20:17 basic.file
  73478 -rw-rw-rw-   2 lpitcher users          15 Mar 11 20:17 hardlink.file
  73479 lrwxrwxrwx   1 lpitcher users          10 Mar 11 20:24 softlink.file -> basic.file

~/directory $ cat softlink.file
This is a file

Aqui, vemos que aunque softlink.file accesa los mismos datos como basic.file y hardlink.file, no comparte el mismo (73479 contra 73478), tampoco exhibe los mismos permisos de archivo. Muestra un nuevo bit de permisos: el bit 'l' (enlace suave).

Si borramos basic.file:

~/directory $ rm basic.file

~/directory $ ls -lia 
total 4
  73477 drwxr-xr-x   2 lpitcher users        1024 Mar 11 20:27 .
  91804 drwxr-xr-x  29 lpitcher users        2048 Mar 11 20:18 ..
  73478 -rw-rw-rw-   1 lpitcher users          15 Mar 11 20:17 hardlink.file
  73479 lrwxrwxrwx   1 lpitcher users          10 Mar 11 20:24 softlink.file -> basic.file

entonces perdemos la habilidad de accesar los datos ligados a travez de el enlace suave:

~/directory $ cat softlink.file
cat: softlink.file: No such file or directory

Sin embargo, aun tenemos acceso a los datos originales a travez del enlace duro:

~/directory $ cat hardlink.file
Esto es un archivo

Notarás que cuando borramos el archivo original, el enlace duro no desaparecio . Similarmente, si hubieramos borrado el enlace suave, el archivo original no se hubiera borrado .

Nota ulterior con respecto a archivos de enlace duro

Al borrar archivos, la parte de datos no esta dispuesta hasta que todas las partes del archivo han sido borradas. Hay un contador en el inodo que indica como muchos archvios apuntan a este archivo, y este contador es decrementado en 1 cada vez de esos archivos borrados. Cuando el contador se hace cero, el inodo y sus datos relacionados son borrados.

A propósito, el contador tambien refleja cuantas veces el archivo ha sido abierto sin haber sido cerrado (en otras palabras, cuantas referencias al archivo están aún activas). Esto tiene algunas ramificaciones las cuales no son obvias a primera vista: puedes borrar una archivo de modo que la parte no de nombre de archivo apunta al inode, sin liberar espacio para la parte de datos del archivo, debido a que el archivo aun esta abierto.

Alguna vez te has encontrado en esta posición: notas que /var/log/messages (o algun otro archivo syslog-owned) ha crecido demasiado grande, y tu

     rm /var/log/messages
     touch /var/log/messages

para reclamar el espacio, pero el espacio usado no reaparece? Esto es porque, aunque has borrado la parte del nombre de archivo, hay un proceso que toma la parte de datos abierta aun (syslogd), y el OS no liberara el espacio para los datos hasta que el proceso lo cierre. Para completar tu reclamo de espacio , tienes que

     kill -SIGHUP `cat /var/run/syslogd.pid`

para conseguir cerrar syslogd ty reabrir el archivo.

Puedes usar esto para tu ventaja en programas: alguna vez te has preguntado como podrías esconder un archivo temporal? Bueno, podrías hacer lo siguiente:

     {
        FILE *fp;

        fp = fopen("some.hidden.file","w");
        unlink("some.hidden.file"); /* borra la parte de nombre de archvio */

        /* some.hidden.file no tiene mas una parte de nombre de archvio y esta de verdad oculto */
        fprintf(fp,"This data won't be found\n"); /* accesa a la parte de datos */
        /*etc*/
        fclose(fp); /* finalmente libera la parte de datos */
     }

 


[BIO] Canadiense por nacimiento, viviendo en Brampton, Ontario, Soy profesor de carrera trabajando en el principal banco Canadiense. Por cerca de 25 anios, He programado sobre todo tipo de sistemas, desde Z80 CP/M hasta OS/390. Primeramente, desarrollo aplicaciones OS/390 MVS para servicios bancarios, y he incorporado Linux dentro de mi ambiente de desarrollo.

Copyright © 2004, Lew Pitcher. Editado bajo la Open Publication License

Publicado en el numero 105 de la gaceta de Linux, Agosto 2004