miércoles, 13 de febrero de 2008

Ramdisk comprimido en Linux

Existen situaciones en las que se dispone de poco espacio de almacenamiento y, en cambio, de bastante memoria volátil. Un ejemplo de ésto es un sistema embarcado, en los que muchas veces el almacenamiento persistente está muy limitado en comparación con la cantidad de memoria volátil (no hablo de ROM, sino de algún tipo de Flash). Para estas situaciones es bastante interesante lo que voy a tratar en este pequeño texto: cómo crear un disco virtual en RAM (ramdisk) que se almacena en memoria persistente comprimido, por lo que se ahorra mucho espacio.

Entorno inicial

Todo lo que aquí voy a explicar ha sido reproducido durante la redacción del texto para asegurar su funcionamiento en un Fedora Core 3 y ha sido probado en un Debian 3.0 muy limitado. Debería funcionar de igual manera en cualquier distribución relativamente reciente.

Creación de la imagen del disco virtual

Lo primero es crear la imagen del disco virtual. ¿Qué es esto? Pues bien, se trata de un archivo cuyo contenido es un sistema de archivos completo de tamaño reducido. Puede parecer extraño, pero se verá más adelante con mayor claridad (de momento podemos imaginar que se trata de una nueva unidad de disco recién comprada). Lo primero es crearlo vacío, sin contenido. Para ello no hay más que teclear en la consola:
dd if=/dev/zero of=disco.img bs=1k count=4096

Con esta orden hemos volcado una cantidad de ceros a un nuevo archivo llamado disco.img. ¿Cuántos bytes? Pues si bs es el tamaño del bloque (1k) y count es el número de bloques (4096), hemos creado un fichero vacío de 4 MB.

Ahora hay que crear un sistema de archivos dentro del fichero. Para comprenderlo mejor es útil imaginar el archivo como un disco duro sin formato, de tamaño 4 MB. Para crear el sistema de archivos usaremos la siguiente orden:
mke2fs -m0 disco.img

Puede aparecer una pregunta indicando que no es un dispositivo real: habrá que responder que se desea continuar de todas formas. Esto creará un sistema de archivos del tipo ext2, soportado por la inmensa mayoría de kernels. El parámetro -m0 indica que no se ha de reservar espacio para el super usuario.

Montado y preparación de la imagen

De poco nos sirve la imagen si no alberga algún programa o datos en su interior. Por ello vamos a montarla antes de comprimirla y dejarla lista para ser usada sólo en memoria RAM. Para montarla hay que tener un directorio destinado a ello (en mi caso /mnt/ramdisk) y ejecutar la siguiente orden:
mount -o loop disco.img /mnt/ramdisk

Ahora hay que copiar las aplicaciones y datos que se quieran al directorio creado. Para comprobar que está bien montado se puede ejecutar el comando df. Un ejemplo de su resultado sería:
[root@MORDOR test]# df
S.ficheros Bloques de 1K Usado Dispon Uso% Montado en
/dev/mapper/VolGroup00-LogVol00
4386480 3185068 978592 77% /

/dev/hda2 101105 11613 84271 13% /boot
none 128000 0 128000 0% /dev/shm
/dev/hda1 24141872 23615776 526096 98% /mnt/win32
/root/test/disco.img 3963 29 3934 1% /mnt/ramdisk

Como se puede observar en la última línea todo ha marchado correctamente. Una vez que la imagen contenga todos los datos que queremos no hay más que desmontarla:
umount /mnt/ramdisk

Compresión de la imagen

Ahora vamos a comprimir la imagen, para lograr el objetivo de que ocupe muy poco espacio en disco. Para lograrlo ejecutaremos la siguiente orden:
gzip -9c disco.img > disco.img.gz

El nuevo archivo creado, llamado disco.img.gz, es el que habremos de distribuir si queremos que otra persona pueda usar la imagen comprimida, o cuando queramos llevarla a nuestro sistema embarcado.

Uso de la imagen del ramdisk

Con nuestra imagen lista sólo nos falta saber cómo utilizarla. El proceso que vamos a seguir es el siguiente:
  1. Descomprimir la imagen directamente en la memoria RAM.
  2. Montar el espacio de RAM con la imagen en el sistema de ficheros.
Como se puede observar en la descripción no se utiliza espacio de disco adicional, que es el objetivo principal. Para descomprimir en memoria la imagen utilizaremos gzip:
gzip -dc disco.img.gz > /dev/ram

Ahora que tenemos en la memoria la totalidad de nuestra imagen podemos montarla en el sistema de ficheros. Para ello vamos a utilizar el mismo directorio que utilizamos cuando creamos y dotamos de contenido inicialmente a la imagen:
mount /dev/ram /mnt/ramdisk

Con esto, ya se puede acceder a través del punto de montaje de la forma habitual. Su comportamiento será el esperado de cualquier sistema de ficheros normal, con posibilidad de lectura y escritura.

Consideraciones finales

Aunque con el método descrito se puede leer y escribir en el ramdisk, los cambios realizados se perderán cuando se desmonte (ya sea por acción del usuario o por apagado de la máquina). Existe la posibilidad de grabar en disco de nuevo la imagen comprimida cuando se termine de usar, pero conlleva el riesgo de que una interrupción de este proceso puede hacer perder todos los datos de la imagen. El script que presento permite grabar la imagen comprimida en otro archivo, y realizar el cambio cuando finalice. Sin embargo, choca contra el objetivo original de no gastar espacio adicional. Más convendría hacer que los datos que las aplicaciones puedan necesitar modificar se encontraran fuera de la imagen. Aún así el script es el siguiente:
umount /mnt/ramdisk gzip -9c < /dev/ram > tmp-disco.img.gz
mv tmp-disco.img.gz disco.img.gz

Para finalizar aquí hay un script que descomprime y monta la imagen una vez que ya está lista. De esta manera se hace mucho más ameno su uso, pues sólo se ha de ejecutar en el mismo directorio en donde se encuentre la imagen comprimida cada vez que se quiera utilizar.
gzip -dc disco.img.gz > /dev/ram
mount /dev/ram /mnt/ramdisk


Este texto lo escribí hace ya algunos años. Dado que su contenido aún es aplicable he considerado oportuno rescatarlo de mi antigua página y volver a publicarlo aquí, para que no se pierda en el tiempo.

1 comentario:

Tito HX dijo...

Entrada que por cierto apareció en Barrapunto hace ya un tiempo.