Puedo cat /dev
, puedo ls /dev
, no puedo less /dev
. ¿Por qué cat
me deja cat
este directorio pero no otros directorios?
Puedo cat /dev
, puedo ls /dev
, no puedo less /dev
. ¿Por qué cat
me deja cat
este directorio pero no otros directorios?
Respuestas:
Históricamente (hasta V7 UNIX, o alrededor de 1979) la read
llamada al sistema funcionó tanto en archivos como en directorios. read
en un directorio devolvería una estructura de datos simple que un programa de usuario analizaría para obtener las entradas del directorio. De hecho, la ls
herramienta V7 hizo exactamente esto: read
en un directorio, analiza la estructura de datos resultante, la salida en un formato de lista estructurada.
A medida que los sistemas de archivos se volvieron más complejos, esta estructura de datos "simple" se volvió más complicada, hasta el punto en que readdir
se agregó una función de biblioteca para ayudar a los programas a analizar la salida de read(directory)
. Los diferentes sistemas y sistemas de archivos pueden tener diferentes formatos en disco, lo que se estaba volviendo complicado.
Cuando Sun presentó el Sistema de archivos de red (NFS), querían abstraer completamente la estructura de directorios en el disco. read(directory)
Sin embargo, en lugar de hacer que su devolución sea una representación del directorio independiente de la plataforma, agregaron una nueva llamada al sistema getdirents
- y prohibieron read
los directorios montados en la red. Esta llamada al sistema se adaptó rápidamente para trabajar en todos los directorios en varios tipos de UNIX, por lo que es la forma predeterminada de obtener el contenido de los directorios. (Historia resumida de https://utcc.utoronto.ca/~cks/space/blog/unix/ReaddirHistory )
Debido a readdir
que ahora es la forma predeterminada de leer directorios, read(directory)
generalmente no se implementa (devolviendo -EISDIR) en la mayoría de los sistemas operativos modernos (QNX, por ejemplo, es una notable excepción que se implementa readdir
como read(directory)
). Sin embargo, con el diseño del "sistema de archivos virtual" en la mayoría de los núcleos modernos, en realidad depende del sistema de archivos individual si la lectura de un directorio funciona o no.
Y, de hecho, en macOS, el devfs
sistema de archivos subyacente al punto de /dev
montaje realmente admite la lectura ( https://github.com/apple/darwin-xnu/blob/xnu-4570.1.46/bsd/miscfs/devfs/devfs_vnops.c#L629 ) :
static int
devfs_read(struct vnop_read_args *ap)
{
devnode_t * dn_p = VTODN(ap->a_vp);
switch (ap->a_vp->v_type) {
case VDIR: {
dn_p->dn_access = 1;
return VNOP_READDIR(ap->a_vp, ap->a_uio, 0, NULL, NULL, ap->a_context);
Esto llama explícitamente READDIR
si intenta leer /dev
(la lectura de archivos bajo /dev
se maneja mediante una función separada - devfsspec_read
). Entonces, si un programa llama a la read
llamada del sistema /dev
, ¡tendrá éxito y obtendrá una lista de directorio!
Esta es efectivamente una característica que es remanente desde los primeros días de UNIX, y que no se ha tocado en mucho tiempo. Una parte de mí sospecha que esto se mantiene por alguna razón de compatibilidad con versiones anteriores, pero podría ser el hecho de que a nadie le importa lo suficiente como para eliminar la función, ya que realmente no está dañando nada.
Less es un visor de archivos de texto, cat es una herramienta para copiar datos arbitrarios. Por lo tanto, menos realiza su propia verificación para asegurarse de que no está abriendo algo que tendrá grandes cantidades de datos o se comportará de manera muy extraña. Por otro lado, cat no tiene tal verificación en absoluto: si el núcleo le permite abrir algo (incluso si es una tubería o un dispositivo o algo peor), cat lo leerá.
Entonces, ¿por qué el sistema operativo permite que cat abra directorios? Tradicionalmente, en los sistemas de estilo BSD, todos los directorios podían leerse como archivos, y así era como los programas enumerarían un directorio en primer lugar: simplemente interpretando las estructuras directas almacenadas en el disco.
Más tarde, esas estructuras en el disco comenzaron a divergir de la dirección utilizada por el núcleo: donde anteriormente un directorio era una lista lineal, los sistemas de archivos posteriores comenzaron a usar tablas hash, árboles B, etc. Así que leer directorios directamente ya no era sencillo: el núcleo creció funciones dedicadas para esto. (No estoy seguro de si esa fue la razón principal, o si se agregaron principalmente por otras razones, como el almacenamiento en caché).
Algunos sistemas BSD continúan permitiéndole abrir todos los directorios para leer; No sé si le dan los datos sin procesar del disco, o si en su lugar devuelven una lista directa emulada, o si dejan que el controlador del sistema de archivos decida.
Entonces, quizás macOS es uno de esos sistemas operativos donde el núcleo lo permite siempre que el sistema de archivos proporcione los datos. Y la diferencia es que /dev
está en un devfs
sistema de archivos que fue escrito para permitir esto en los primeros días, mientras que /
está en un sistema de archivos APFS que omitió esta característica como innecesaria en los tiempos modernos.
Descargo de responsabilidad: en realidad no he realizado ninguna investigación sobre BSD o macOS. Solo lo estoy volando.
/etc
sí, así que lo usé como mi punto de referencia.
mount
o /sbin/mount
ver qué está montado actualmente en dónde.
/dev
es un sistema de archivos virtual que usa el devfs
controlador, mientras que /etc
es parte del /
sistema de archivos que usa el apfs
controlador. Entonces, la razón cat
leerá uno y no el otro es una diferencia entre los controladores apfs
y devfs
.
neofetch
para su información :) i.imgur.com/3azpnDt.png