1. Una interfaz común no implica datos iguales
En el tema 30 conectamos un ext4 al árbol mediante un montaje. Ahora veremos por qué un programa también puede abrir una ruta bajo /proc o /sys sin cambiar todas sus llamadas. El kernel ofrece una interfaz común y cada implementación define cómo atiende las operaciones.
VFS: capa del kernel que organiza la interfaz de sistemas de archivos y permite que implementaciones diferentes convivan en el mismo espacio de rutas. Compartir open y read no obliga a compartir almacenamiento, persistencia ni todas las operaciones posibles.
open("nota.txt", O_RDONLY) → contenido de un regular
open("/proc/uptime", O_RDONLY) → información generada por el kernel
open("/sys/class/net/lo/mtu", ...) → atributo de un objeto del kernel
open("/dev/null", O_RDONLY) → dispositivo de caracteres
Cada apertura devuelve un descriptor o un error.
Lo que hace read depende del objeto y de su implementación.La idea de «todo es un archivo» resulta útil como orientación, pero no significa que cualquier recurso sea un archivo de disco ni que admita búsqueda, truncado, mapeo o escritura arbitraria.
2. Del descriptor a las operaciones de la implementación
Al abrir una ruta, el VFS participa en la resolución de nombres, atraviesa los montajes que correspondan y aplica las comprobaciones pertinentes. La implementación concreta aporta operaciones para localizar y manejar sus objetos.
Después de abrir, read(fd, ...) utiliza la referencia guardada para esa apertura, no empieza de nuevo por la ruta original. Las operaciones concretas pueden producir bytes a partir de un estado interno, recuperar páginas de memoria o consultar un almacenamiento.
La documentación del VFS del kernel describe esta organización. Los nombres internos sirven para comprender responsabilidades; sus estructuras no son una API estable para programas de usuario.
3. Superbloque, inodo, dentry y archivo abierto
| Objeto conceptual | Responsabilidad | No confundir con |
|---|---|---|
| Superbloque | Representa una instancia de sistema de archivos y sus operaciones generales. | Una sola carpeta o un descriptor de proceso. |
| Inodo | Representa un objeto y sus atributos y operaciones. | El nombre de la ruta. |
| Dentry | Relaciona un nombre dentro de un directorio con el resultado de su búsqueda. | Una copia permanente de todos los bytes del archivo. |
| Archivo abierto | Estado asociado a una apertura, como posición y opciones pertinentes. | El inodo compartido por varias aperturas. |
| Montaje | Conexión de una raíz de sistema de archivos al árbol visible. | Una instancia necesariamente distinta para cada conexión. |
Dos enlaces duros pueden conducir al mismo inodo. Dos aperturas independientes de un archivo pueden tener posiciones independientes; un descriptor duplicado comparte la descripción abierta correspondiente. La caché de nombres también puede recordar búsquedas negativas.
Un inodo de procfs no tiene que tener una representación persistente equivalente en un disco. La abstracción de objeto es más amplia que el caso de un formato de bloques. Tampoco un bind mount exige crear otro sistema de archivos de almacenamiento.
4. Qué distingue a estos sistemas de archivos
| Tipo | Qué presenta | Relación con persistencia |
|---|---|---|
| procfs | Información de procesos, kernel y algunas interfaces de control. | Consultar no equivale a recuperar un documento guardado. |
| sysfs | Objetos del kernel, sus relaciones y atributos. | Los atributos reflejan el objeto y su controlador. |
| tmpfs | Archivos normales almacenados en memoria virtual. | Su contenido no sobrevive a la destrucción de la instancia. |
| devtmpfs | Nodos de dispositivos administrados por el kernel. | El nodo no contiene una copia de los datos del dispositivo. |
| OverlayFS | Una vista combinada de capas de otros sistemas. | Depende del almacenamiento que respalda sus capas. |
«Virtual», «en memoria» y «especial» no son sinónimos perfectos. tmpfs sí guarda los bytes que escribes; procfs suele generarlos al consultar; OverlayFS puede apoyarse en sistemas persistentes o temporales.
5. procfs: procesos e información del kernel
/proc es el punto de montaje habitual de procfs. Hay rutas generales, como /proc/uptime, y directorios asociados a procesos. /proc/self identifica al proceso que realiza el acceso: si usas cat, corresponde a cat, no automáticamente al shell que lo lanzó.
$ findmnt --target /proc --output TARGET,SOURCE,FSTYPE,OPTIONS
$ cat /proc/uptime
$ sed -n '1,12p' /proc/self/status
$ head -n 5 /proc/self/mountinfoLos datos visibles dependen del proceso, los espacios de nombres y las políticas de acceso. Un PID puede desaparecer entre una enumeración y la consulta siguiente. Algunas entradas permiten escritura para modificar parámetros; no son documentos de configuración que deban editarse indiscriminadamente. Véase proc(5).
Status presenta campos como identidad y estado; los detalles se describen en proc_pid_status(5). Una aplicación debe interpretar los campos que necesita y tolerar los que no conoce.
6. Un tamaño aparente no determina los bytes disponibles
Algunas entradas de procfs tienen st_size igual a cero y aun así devuelven contenido. En sysfs el tamaño informado de un atributo también puede ser una cota o convención diferente de la cantidad de texto actual. Asignar un buffer de st_size bytes y decidir que cero significa «no leer» es un error.
unsigned char buffer[64];
ssize_t n = read(fd, buffer, sizeof buffer);
/* n > 0: usar exactamente n bytes; n == 0: fin para esa lectura. */
/* n == -1: interpretar errno; EINTR puede requerir reintento. */Leer hasta EOF sin límite tampoco es adecuado para todo recurso: /dev/zero puede seguir entregando bytes. Para información de tamaño variable se decide un límite, se leen los bloques necesarios y se maneja el truncado deliberadamente.
La posibilidad de seek y el significado de releer dependen de la interfaz concreta. Varias lecturas de un recurso generado no constituyen necesariamente una instantánea coherente del sistema. El descriptor conserva la referencia, como en el tema 29, pero no congela el estado consultado.
7. sysfs: objetos, relaciones y atributos
sysfs suele estar montado en /sys. Exporta objetos del kernel, sus atributos y enlaces que permiten ver relaciones entre subsistemas. No es un listado de todos los procesos ni un almacén de documentos ordinarios.
$ findmnt --target /sys --output TARGET,SOURCE,FSTYPE,OPTIONS
$ ls /sys/class/net
$ readlink -f /sys/class/net/lo
$ cat /sys/class/net/lo/mtuEl ejemplo depende de que la interfaz lo y ese atributo estén disponibles en el entorno. Muchos atributos textuales se diseñan para expresar un valor simple por archivo, aunque existen interfaces binarias y excepciones. Escribir un atributo habilitado invoca el comportamiento del controlador; una escritura parcial o un formato incorrecto puede ser rechazado.
El laboratorio solo consulta atributos conocidos. Las convenciones de atributos y su relación con objetos se describen en la documentación de sysfs; para una interfaz concreta debe consultarse además su ABI.
8. devtmpfs, udev y nodos de dispositivo
devtmpfs mantiene nodos para dispositivos registrados con números major/minor. Es habitual que respalde /dev, pero algunos entornos usan otro montaje y nodos proporcionados de otra forma. Se comprueba con findmnt en vez de inferirlo por el nombre del directorio.
El kernel mantiene los nodos básicos; la gestión en espacio de usuario puede aplicar permisos y crear enlaces descriptivos. La opción DEVTMPFS del kernel describe el mecanismo básico, y udev(7) explica reglas y eventos.
$ findmnt --target /dev --output TARGET,SOURCE,FSTYPE,OPTIONS
$ ls -l /dev/null /dev/zero
$ stat -c 'nombre=%n tipo=%F major=%t minor=%T' /dev/null /dev/zero/dev/null devuelve EOF al leer; /dev/zero entrega bytes cero. Se estudian en null(4). El almacenamiento del nodo no determina el almacenamiento de los datos: un nodo de bloques puede dar acceso a un disco persistente, aunque el nodo viva en devtmpfs.
Abrir un dispositivo arbitrario puede tener efectos propios. Los ejemplos se limitan a null y zero en modo lectura; no trasladan su comportamiento a discos, terminales u otros controladores.
9. tmpfs: bytes almacenados en memoria virtual
tmpfs permite crear directorios y archivos, escribir bytes y volver a leerlos. Su capacidad se asigna según el uso y las restricciones del sistema; un límite size no reserva de inmediato toda esa memoria.
Las páginas pueden usar swap cuando está disponible y permitida. Por tanto, «tmpfs» no equivale a prometer que ningún byte llegará a un medio de intercambio. La instancia es temporal: al destruirla se pierde su contenido. Un desmontaje normal de la última vista de una instancia aislada como la del laboratorio no convierte sus archivos en persistentes.
$ findmnt --target /dev/shm --output TARGET,SOURCE,FSTYPE,OPTIONS
$ findmnt --target /tmp --output TARGET,SOURCE,FSTYPE,OPTIONS/tmp no tiene que ser tmpfs, y /dev/shm debe verificarse en el entorno. Además del límite de bytes pueden intervenir límites de inodos y la presión de memoria. Los permisos siguen siendo relevantes. Véase tmpfs(5).
tmpfs no necesita formatear un archivo ni asociar un loop: su implementación administra directamente los archivos. La documentación del kernel sobre tmpfs contrasta ese diseño con un disco RAM de bloques y con ramfs.
10. OverlayFS: una vista de varias capas
OverlayFS combina un árbol inferior, lowerdir, con una capa superior escribible, upperdir, y presenta una vista merged. Si un nombre está en la capa superior, su objeto puede ocultar el inferior. Los directorios pueden combinar entradas de ambas capas.
lower/nota.txt = "base"
upper/ = vacío
merged/nota.txt → "base"
Escritura mediante merged:
puede requerir copy-up del objeto a upper
lower/nota.txt sigue con "base"
merged/nota.txt usa la versión superior
Borrar una entrada inferior desde merged puede crear una marca de ocultación.
Esa marca evita que reaparezca la entrada de lower en la vista combinada.Un whiteout es una marca con semántica del overlay, no un archivo de usuario que deba crearse o copiarse manualmente. Los directorios opacos permiten ocultar contenido inferior de un directorio. La representación y las optimizaciones dependen de configuración y soporte.
workdir debe estar en el mismo sistema de archivos que upperdir y prepararse vacío para un montaje nuevo. Se accede a los cambios mediante merged; no se alteran las capas por detrás mientras están en uso. Véase la documentación de OverlayFS.
La persistencia depende de las capas: un upperdir en tmpfs es temporal. Un descriptor que ya estaba abierto puede seguir conectado a un objeto anterior durante cambios de capa; no debe suponerse que toda referencia cambia automáticamente a la versión nueva.
11. Consultar el proveedor real y acotar el contrato
| Consulta | Qué informa | Qué no demuestra |
|---|---|---|
| findmnt -T ruta | Montaje que contiene la ruta en la vista actual. | Todos los efectos que admite el objeto final. |
| fstat(fd) | Tipo y atributos del objeto abierto. | Que st_size sea la cantidad total de texto generado. |
| fstatfs(fd) | Datos del sistema de archivos, incluido f_type en Linux. | Que cualquier objeto de ese sistema tenga idéntica semántica. |
| read(fd, buffer, límite) | Bytes de esa lectura o su error. | Una instantánea de todo el kernel ni persistencia futura. |
Un nodo de dispositivo encontrado dentro de un montaje tmpfs sigue siendo un dispositivo. Conviene distinguir el tipo del contenedor del tipo de objeto y su proveedor de operaciones.
El siguiente programa de creación usa fstatfs únicamente para reconocer tmpfs en Linux. El tema 32 utilizará statvfs para estadísticas de volumen con una interfaz más portable. Véase statfs(2).
12. Programa en C: una lectura acotada sobre proveedores distintos
Guarda muestra-vfs.c. El programa consulta metadatos y pide hasta 64 bytes sin calcular el buffer a partir de st_size. Muestra los bytes en hexadecimal para no confundir un cero binario con el terminador de una cadena.
#define _POSIX_C_SOURCE 200809L
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <inttypes.h>
#include <errno.h>
#include <stdio.h>
int main(int argc, char **argv)
{
if (argc != 2) {
fprintf(stderr, "Uso: %s ruta-de-lectura-conocida\n", argv[0]); return 2;
}
int fd = open(argv[1], O_RDONLY | O_CLOEXEC | O_NONBLOCK);
if (fd == -1) { perror("open"); return 1; }
int resultado = 1;
struct stat st;
if (fstat(fd, &st) == -1) { perror("fstat"); goto fin; }
const char *tipo = S_ISREG(st.st_mode) ? "regular" :
S_ISCHR(st.st_mode) ? "caracter" : "otro";
if (!S_ISREG(st.st_mode) && !S_ISCHR(st.st_mode)) {
fprintf(stderr, "El ejemplo acepta regulares o dispositivos de caracteres conocidos\n");
goto fin;
}
printf("TIPO=%s\nST_SIZE=%jd\n", tipo, (intmax_t)st.st_size);
unsigned char datos[64];
ssize_t n;
do { n = read(fd, datos, sizeof datos); } while (n == -1 && errno == EINTR);
if (n == -1) { perror("read"); goto fin; }
printf("LEIDOS=%zd\nHEX=", n);
for (ssize_t i = 0; i < n; ++i) printf("%02x", (unsigned int)datos[i]);
putchar('\n');
resultado = 0;
fin:
if (close(fd) == -1) { perror("close"); resultado = 1; }
return resultado;
}Esta es una muestra de una sola lectura, no un copiador completo. read puede devolver menos de 64 bytes sin error. O_NONBLOCK no garantiza que todos los proveedores respondan instantáneamente; EAGAIN, EIO y otros errores se tratan como fallos del ensayo, no como EOF.
El programa sigue enlaces y permite dispositivos de caracteres conocidos. La comprobación posterior de tipo no evita efectos que una apertura de otro dispositivo pudiera producir. Por eso el contrato de uso limita las rutas y no propone leer indiscriminadamente todo /dev.
13. Programa en C: crear un archivo solo si la base es tmpfs
Guarda crear-en-tmpfs.c. Abre una base propia, identifica su sistema con fstatfs y crea un nombre nuevo mediante openat con O_EXCL. Si la base no es tmpfs, termina sin crear ese archivo. El programa conserva un eventual archivo parcial si una escritura falla.
#define _POSIX_C_SOURCE 200809L
#include <sys/stat.h>
#include <sys/vfs.h>
#include <linux/magic.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
int main(int argc, char **argv)
{
if (argc != 2) {
fprintf(stderr, "Uso: %s directorio-propio-en-tmpfs\n", argv[0]); return 2;
}
int base = open(argv[1], O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
if (base == -1) { perror("open directorio"); return 1; }
int fd = -1, resultado = 1;
struct statfs sistema;
if (fstatfs(base, &sistema) == -1) { perror("fstatfs"); goto fin; }
if ((unsigned long)sistema.f_type != (unsigned long)TMPFS_MAGIC) {
fprintf(stderr, "Se requiere tmpfs; no se creó ningún archivo\n"); goto fin;
}
fd = openat(base, "nota-c.txt", O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0600);
if (fd == -1) { perror("openat nuevo"); goto fin; }
const char texto[] = "datos en tmpfs\n";
size_t escritos = 0, total = sizeof texto - 1;
while (escritos < total) {
ssize_t n = write(fd, texto + escritos, total - escritos);
if (n == -1 && errno == EINTR) continue;
if (n <= 0) {
if (n == -1) perror("write");
else fprintf(stderr, "write no avanzó\n");
goto fin;
}
escritos += (size_t)n;
}
printf("ESCRITOS=%zu\n", escritos);
resultado = 0;
fin:
if (fd != -1 && close(fd) == -1) { perror("close archivo"); resultado = 1; }
if (close(base) == -1) { perror("close directorio"); resultado = 1; }
return resultado;
}La comprobación se hace sobre el descriptor de la base. Los componentes previos de la ruta para obtenerla deben ser de confianza. El nombre de salida es fijo, de un solo componente y debe ser nuevo: repetir la ejecución no sobrescribe el resultado anterior.
Una escritura satisfactoria y close no prometen persistencia tras destruir tmpfs. Incluso añadir una sincronización no convertiría esa instancia temporal en un sistema de archivos persistente.
14. Laboratorio sin modificar interfaces del kernel
Usa Bash en Linux con una cuenta ordinaria, compilador C y Python 3. Guarda los programas anteriores en un directorio nuevo. Estas primeras consultas no necesitan montar nada ni escribir en /proc, /sys o dispositivos.
$ LAB31=$(mktemp -d "$HOME/tema31.XXXXXX")
$ cd -- "$LAB31"
$ cc -std=c11 -Wall -Wextra -Wpedantic -O2 muestra-vfs.c -o muestra-vfs
$ cc -std=c11 -Wall -Wextra -Wpedantic -O2 crear-en-tmpfs.c -o crear-en-tmpfs
$ ./muestra-vfs /proc/uptime
$ ./muestra-vfs /proc/self/status
$ ./muestra-vfs /dev/null
$ ./muestra-vfs /dev/zeroEn uptime se espera ST_SIZE=0 y una lectura no vacía. Null devuelve LEIDOS=0; zero devuelve 64 bytes cero. En self/status la consulta corresponde a muestra-vfs, porque es el proceso que abre la ruta. No se comparan entre sí valores dinámicos de uptime o PID.
$ if test -r /sys/class/net/lo/mtu; then ./muestra-vfs /sys/class/net/lo/mtu; fi
$ findmnt --target /dev/shm --output TARGET,SOURCE,FSTYPE,OPTIONS
# Continuar aquí solo si /dev/shm es tmpfs y permite crear el directorio propio.
$ TMP31=$(mktemp -d /dev/shm/curso31.XXXXXX)
$ (umask 077; ./crear-en-tmpfs "$TMP31")
$ cat -- "$TMP31/nota-c.txt"Si /dev/shm no es utilizable, puedes realizar la sección siguiente de montaje propio y usar su directorio como TMP31. No debes elegir un destino de otro tipo para eludir la comprobación del programa.
Guarda verificar-tema31.py y ejecútalo una vez sobre ese TMP31 después de crear nota-c.txt. El verificador crea otro nombre exclusivo, por lo que repetirlo requiere un directorio de casos nuevo.
from pathlib import Path
import os
import subprocess
import sys
if len(sys.argv) != 2:
raise SystemExit("Uso: python3 verificar-tema31.py directorio-propio-en-tmpfs")
tmp = Path(sys.argv[1]).resolve(strict=True)
lector = Path("muestra-vfs").resolve(strict=True)
creador = Path("crear-en-tmpfs").resolve(strict=True)
def muestra(ruta):
p = subprocess.run([str(lector), str(ruta)], capture_output=True,
text=True, timeout=5, check=True)
campos = dict(linea.split("=", 1) for linea in p.stdout.splitlines())
datos = bytes.fromhex(campos["HEX"])
assert len(datos) == int(campos["LEIDOS"]) <= 64
return campos, datos
regular = tmp / "regular-verificador.txt"
fd = os.open(regular, os.O_CREAT | os.O_EXCL | os.O_WRONLY, 0o600)
with os.fdopen(fd, "wb") as f:
f.write(b"abc\n")
c, b = muestra(regular)
assert c["TIPO"] == "regular" and int(c["ST_SIZE"]) == 4 and b == b"abc\n"
c, b = muestra("/proc/uptime")
assert c["TIPO"] == "regular" and int(c["ST_SIZE"]) == 0 and len(b) > 0
c, b = muestra("/dev/null")
assert c["TIPO"] == "caracter" and b == b""
c, b = muestra("/dev/zero")
assert c["TIPO"] == "caracter" and b == bytes(64)
sysfs = Path("/sys/class/net/lo/mtu")
if sysfs.is_file() and os.access(sysfs, os.R_OK):
_, b = muestra(sysfs)
assert b.strip().isdigit()
else:
print("Omitida consulta opcional: atributo sysfs no disponible")
nota = tmp / "nota-c.txt"
assert nota.read_bytes() == b"datos en tmpfs\n"
p = subprocess.run([str(creador), str(tmp)], capture_output=True, text=True, timeout=5)
assert p.returncode == 1, "O_EXCL debe rechazar repetir el nombre"
assert nota.read_bytes() == b"datos en tmpfs\n"
print("Correctos: regular, proc con tamaño cero, dispositivos y creación exclusiva en tmpfs")
print("Directorio temporal conservado:", tmp)$ python3 verificar-tema31.py "$TMP31"
$ printf 'Laboratorio: %s\nDirectorio en tmpfs: %s\n' "$LAB31" "$TMP31"La prueba no exige un valor concreto de MTU ni un PID estable. Si procfs, null o zero no están disponibles por la configuración del entorno, el fallo se interpreta como una precondición no satisfecha; no se inventa una salida equivalente.
15. Prácticas opcionales con montajes propios
Estas etapas requieren autorización de montaje y soporte del kernel, como en el tema 30. Utilizan destinos nuevos del laboratorio; no reemplazan los montajes del sistema en /proc, /sys o /dev. Se comprueba cada retorno antes de continuar.
Instancia tmpfs pequeña y vacía al recrearla
$ mkdir -- "$LAB31/memoria"
$ TMP31="$LAB31/memoria"
$ sudo mount -t tmpfs -o "size=8M,mode=0700,uid=$(id -u),gid=$(id -g),nodev,nosuid,noexec" tmpfs "$TMP31"
$ findmnt --mountpoint "$TMP31" --output TARGET,SOURCE,FSTYPE,OPTIONS
$ (umask 077; ./crear-en-tmpfs "$TMP31")
$ cat -- "$TMP31/nota-c.txt"
$ cd -- "$LAB31"
$ sudo umount "$TMP31"
$ sudo mount -t tmpfs -o "size=8M,mode=0700,uid=$(id -u),gid=$(id -g),nodev,nosuid,noexec" tmpfs "$TMP31"
$ ls -la -- "$TMP31"
$ sudo umount "$TMP31"El segundo montaje crea una instancia nueva: nota-c.txt no debe estar. Esta prueba presupone que no se conservan otras vistas o referencias que mantengan viva la instancia anterior. Si umount indica ocupado, primero se cierran los recursos y se repite el desmontaje normal.
Vista OverlayFS de archivos del propio ensayo
$ LOWER31="$LAB31/lower"
$ UPPER31="$LAB31/upper"
$ WORK31="$LAB31/work"
$ MERGED31="$LAB31/merged"
$ mkdir -- "$LOWER31" "$UPPER31" "$WORK31" "$MERGED31"
$ printf 'base original\n' > "$LOWER31/base.txt"
$ printf 'conservar\n' > "$LOWER31/conservar.txt"
$ printf 'inferior\n' > "$LOWER31/borrar.txt"
$ sudo mount -t overlay overlay -o "lowerdir=$LOWER31,upperdir=$UPPER31,workdir=$WORK31,nodev,nosuid,noexec" "$MERGED31"
$ findmnt --mountpoint "$MERGED31" --output TARGET,SOURCE,FSTYPE,OPTIONSPara esta sintaxis simple, las rutas de las capas no deben contener comas, dos puntos ni barras inversas, que tienen significado en las opciones de OverlayFS. Si el directorio del usuario los contiene, prepara el laboratorio en una ruta de práctica adecuada. La implementación superior debe soportar los requisitos de OverlayFS; que ext4 o tmpfs exista no prueba por sí solo que overlay esté autorizado en el entorno.
$ cat -- "$MERGED31/base.txt"
$ printf 'version superior\n' > "$MERGED31/base.txt"
$ cat -- "$LOWER31/base.txt" "$UPPER31/base.txt" "$MERGED31/base.txt"
$ rm -- "$MERGED31/borrar.txt"
$ test -f "$LOWER31/borrar.txt" && test ! -e "$MERGED31/borrar.txt"
$ ls -la -- "$UPPER31"
$ cd -- "$LAB31"
$ sudo umount "$MERGED31"Lower conserva base original y borrar.txt; la vista muestra la versión superior y oculta el nombre borrado. No se exige una representación textual concreta del whiteout. Tampoco se modifican directamente las capas mientras están montadas.
$ sudo mount -t overlay overlay -o "lowerdir=$LOWER31,upperdir=$UPPER31,workdir=$WORK31,nodev,nosuid,noexec" "$MERGED31"
$ cat -- "$MERGED31/base.txt" "$MERGED31/conservar.txt"
$ test ! -e "$MERGED31/borrar.txt"
$ sudo umount "$MERGED31"Las capas se conservan para inspección. Antes de limpiar, comprueba que no quedan montajes propios activos. No se borra un destino suponiendo que umount tuvo éxito.
16. Simuladores de lectura y capas
La misma petición read sobre fuentes diferentes
Estos son datos ilustrativos, fijos para una apertura del modelo; no son consultas a tu kernel. El tamaño mostrado no se usa para decidir el buffer. Cada lectura pide entre 1 y 128 bytes. Reabrir reinicia la muestra; no representa una garantía de instantánea en procfs o sysfs reales.
Misma interfaz, distinto proveedor
Copy-up, prioridad superior y ocultación
Modelo de regulares con nombres fijos, una capa inferior que no cambia, una superior y marcas de ocultación. Omite directorios, metadatos, enlaces, descriptores abiertos y optimizaciones como metacopy. La marca se representa conceptualmente, no como una instrucción para editar whiteouts reales.
Vista combinada de dos capas
| Nombre | Lower | Upper | Ocultación | Vista merged |
|---|
Prueba escribir config.txt: lower debe conservar su texto. Después bórralo y observa la marca. Escribir de nuevo ese nombre debe hacer visible la nueva versión superior. Para nuevo.txt, que nunca existió en lower, borrar su única versión no necesita ocultar un objeto inferior.
17. Diagnóstico y resumen
| Observación | Interpretación a comprobar |
|---|---|
| st_size es cero, pero cat muestra datos. | Puede tratarse de una interfaz que genera contenido; usar lecturas acotadas y su retorno. |
| Una ruta de /proc desapareció. | El proceso pudo terminar o cambiar la visibilidad; no es un documento estable. |
| Un atributo de /sys rechaza un formato. | Su ABI y controlador definen valores, permisos y escritura admitida. |
| /dev no figura como devtmpfs. | El entorno puede presentar otro montaje; inspeccionar origen y tipos de nodo. |
| tmpfs indica falta de espacio. | Revisar límites de bytes, inodos y restricciones del entorno. |
| Un archivo inferior existe, pero merged no lo muestra. | Puede haber prioridad superior, whiteout o un directorio opaco. |
| OverlayFS no monta. | Revisar autorización, soporte, rutas de capas, requisitos de upper y ubicación de work. |
- VFS permite una interfaz común para implementaciones distintas.
- Objeto, nombre, apertura y montaje son responsabilidades separadas.
- procfs y sysfs suelen presentar interfaces del kernel; una escritura puede ser una operación de control.
- st_size no es una receta universal para dimensionar una lectura.
- devtmpfs contiene nodos; el controlador define el comportamiento del dispositivo.
- tmpfs almacena bytes en memoria virtual, puede usar swap y tiene límites.
- OverlayFS combina capas y puede copiar a upper u ocultar nombres de lower.
- Las garantías de persistencia dependen del proveedor y del almacenamiento subyacente.
- Se comprueban retornos y límites sin asumir semántica de archivo de disco para todo recurso.
18. Preguntas de repaso y práctica
1. ¿Qué aporta el VFS?
Una capa común que organiza la interfaz y permite coexistir a diferentes implementaciones de sistemas de archivos.
2. ¿open exitoso garantiza que el recurso proviene de un disco?
No. Puede abrir una interfaz generada, memoria virtual o un dispositivo, entre otros casos.
3. ¿Inodo y dentry son lo mismo?
No. El inodo representa un objeto; la dentry participa en la relación entre nombres y resultados de búsqueda.
4. ¿Dos aperturas siempre comparten posición?
No. Dos aperturas independientes pueden tener posiciones independientes; los descriptores duplicados comparten la descripción abierta correspondiente.
5. ¿Todo lo que está bajo /proc es de solo lectura?
No. Existen interfaces de control escribibles con reglas concretas. El laboratorio no las modifica.
6. ¿A qué proceso se refiere /proc/self/status al usar muestra-vfs?
Al proceso muestra-vfs que abre esa ruta, no al shell padre.
7. ¿st_size cero prueba que read devolverá cero?
No. Una entrada como /proc/uptime puede informar tamaño cero y producir bytes.
8. ¿Leer hasta EOF siempre termina?
No. Un proveedor como /dev/zero puede seguir produciendo bytes; hay que establecer límites.
9. ¿sysfs es una base de archivos de configuración ordinarios?
No. Expone objetos y atributos del kernel, cuyos controladores definen los efectos de acceso.
10. ¿Qué diferencia hay entre devtmpfs y udev?
El kernel mantiene nodos básicos en devtmpfs; udev recibe eventos y puede gestionar permisos y enlaces en espacio de usuario.
11. ¿El nodo /dev/null contiene una copia de lo escrito?
No. Ese dispositivo descarta escrituras y devuelve EOF al leer.
12. ¿Todos los bytes de tmpfs permanecen obligatoriamente en RAM?
No. Las páginas pueden usar swap si está disponible y permitido.
13. ¿size=8M reserva inmediatamente 8 MiB?
No. Expresa un límite de la instancia; el consumo se produce según el uso.
14. ¿/tmp siempre es tmpfs?
No. Se consulta el montaje real del entorno.
15. ¿Sincronizar tmpfs garantiza persistencia al destruirlo?
No. La sincronización no cambia su naturaleza temporal.
16. ¿Escribir por merged modifica necesariamente lower?
No. El diseño del ensayo conserva lower y lleva la versión modificada a upper.
17. ¿Por qué borrar un nombre de lower puede necesitar una marca?
Porque, sin ocultación, la entrada inferior volvería a ser visible al desaparecer la versión superior.
18. ¿workdir puede estar en cualquier volumen?
No. En este montaje debe estar en el mismo sistema de archivos que upperdir y prepararse vacío para el montaje nuevo.
19. ¿OverlayFS es siempre persistente?
Depende de sus capas. Una capa superior en tmpfs se pierde al destruir esa instancia.
20. ¿Por qué crear-en-tmpfs conserva un descriptor de la base?
Para consultar y crear respecto del mismo directorio abierto, sin resolver otra vez su ruta para cada operación.
Para practicar
- Identifica el tipo de montaje de /proc, /sys, /dev, /dev/shm y /tmp en tu entorno.
- Relaciona el VFS con los descriptores estables que estudiaste en el tema 29.
- Ejecuta muestra-vfs sobre un regular vacío y sobre /proc/uptime; compara ST_SIZE y LEIDOS.
- Explica por qué una lectura de /dev/zero debe tener límite.
- Busca en la documentación la ABI de un atributo que puedas consultar sin modificarlo.
- Comprueba que crear-en-tmpfs rechaza una base de otro tipo antes de crear nota-c.txt.
- Observa en el simulador que varias lecturas consumen la muestra finita y zero sigue generando bytes.
- Completa el ciclo de una instancia tmpfs propia y verifica que la nueva está vacía.
- Escribe, borra y recrea un nombre inferior en el simulador de overlay.
- Comprueba que los archivos lower del laboratorio no cambian tras escribir por merged.
- Distingue permanencia de las capas y permanencia de una conexión de montaje.
- Diseña una función de lectura con límite que trate lectura corta, EOF y error como resultados distintos.
En el tema 32 estudiaremos estadísticas del volumen en C con statvfs, construiremos un df propio y analizaremos qué significa consultar espacio disponible antes de escribir.