Hay archivos especiales en Linux que no son realmente archivos.
Los ejemplos más notables y claros de estos están en la dev
carpeta, "archivos" como:
/dev/null
- Ignora todo lo que escribes en el archivo/dev/random
- Emite datos aleatorios en lugar del contenido de un archivo/dev/tcp
- Envía cualquier información que escriba a este archivo a través de la red
En primer lugar, ¿cuál es el nombre de este tipo de "archivos" que realmente son algún tipo de script o binario disfrazado?
Segundo, ¿cómo se crean? ¿Están estos archivos integrados en el sistema a nivel del núcleo, o hay una manera de crear un "archivo mágico" usted mismo (qué tal a /dev/rickroll
)?
man 2 mknod
open()
,read()
,close()
, etc. Después de eso, le toca al softwareRespuestas:
/dev/zero
es un ejemplo de un "archivo especial", en particular, un "nodo de dispositivo". Normalmente, estos se crean por el proceso de instalación de distribución, pero se puede totalmente las crea usted mismo si quieres.Si preguntas
ls
sobre/dev/zero
:La "c" al principio le dice que este es un "dispositivo de caracteres"; el otro tipo es "dispositivo de bloque" (impreso
ls
como "b"). En términos generales, los dispositivos de acceso aleatorio como los discos duros tienden a ser dispositivos de bloque, mientras que las cosas secuenciales como las unidades de cinta o la tarjeta de sonido tienden a ser dispositivos de caracteres.La parte "1, 5" es el "número de dispositivo principal" y el "número de dispositivo secundario".
Con esta información, podemos usar el
mknod
comando para crear nuestro propio nodo de dispositivo:Esto crea un nuevo archivo llamado
foobar
, en la carpeta actual, que hace exactamente lo mismo que/dev/zero
. (Por supuesto, puede establecer diferentes permisos si lo desea). Todo este "archivo" realmente contiene los tres elementos anteriores: tipo de dispositivo, número mayor, número menor. Puede usarls
para buscar los códigos de otros dispositivos y recrearlos también. Cuando te aburras, solo usarm
para eliminar los nodos del dispositivo que acabas de crear.Básicamente, el número principal le dice al kernel de Linux con qué controlador de dispositivo debe hablar, y el número menor le dice al controlador de dispositivo de qué dispositivo está hablando. (Por ejemplo, probablemente tenga un controlador SATA, pero tal vez haya varios discos duros conectados).
Si desea inventar nuevos dispositivos que hagan algo nuevo ... bueno, deberá editar el código fuente del kernel de Linux y compilar su propio kernel personalizado. ¡Entonces no hagamos eso! :-) Pero puedes agregar archivos de dispositivo que duplican los que ya tienes. Un sistema automatizado como udev básicamente solo está buscando eventos del dispositivo y llamando
mknod
/rm
por usted automáticamente. Nada más mágico que eso.Todavía hay otros tipos de archivos especiales:
Linux considera que un directorio es un tipo especial de archivo. (Por lo general, no puede abrir directamente un directorio, pero si pudiera, encontraría que es un archivo normal que contiene datos en un formato especial y le dice al núcleo dónde encontrar todos los archivos en ese directorio).
Un enlace simbólico es un archivo especial. (Pero un enlace rígido no lo es). Puede crear enlaces simbólicos con el
ln -s
comando. (Busque la página del manual).También hay una cosa llamada "canalización con nombre" o "FIFO" (cola de primero en entrar, primero en salir). Puedes crear uno con
mkfifo
. Un FIFO es un archivo mágico que puede abrirse con dos programas a la vez: una lectura y una escritura. Cuando esto sucede, funciona como un tubo de cubierta normal. Pero puede iniciar cada programa por separado ...Un archivo que no es "especial" de ninguna manera se denomina "archivo normal". De vez en cuando verá mención de esto en la documentación de Unix. Eso es lo que significa; un archivo que no es un nodo de dispositivo o un enlace simbólico o lo que sea. Solo un archivo normal, todos los días, sin propiedades mágicas.
fuente
mknod
, correcat /proc/devices
para ver los números principales de todos los pilotos. Lo que nos lleva a otro tipo de archivo especial, el/proc
sistema de archivos ( esta respuesta habla de ello).La mayoría de las
/dev
entradas son inodos de dispositivo de bloque o inodos de dispositivo de caracteres. Wikipedia tiene muchos detalles sobre eso, que no voy a repetir.Pero lo
/dev/tcp
que se menciona en su pregunta no se explica por ninguna de las respuestas existentes./dev/tcp
y/dev/udp
son diferentes de la mayoría de las otras/dev
entradas. Los dispositivos de bloque y de carácter son implementadas por el kernel, pero/dev/tcp
y/dev/udp
se implementan en el modo de usuario.El shell bash es un programa que tiene una implementación de
/dev/tcp
y/dev/udp
(copiado deksh93
). Cuando intentas abrir una ruta debajo de las que tienen operadores de redireccionamiento bash, no realizará unaopen
llamada normal al sistema. En cambio, bash creará un socket TCP y lo conectará al puerto especificado.Esto se implementa en modo de usuario y solo en algunos programas, como se puede ver en el siguiente ejemplo, que demuestra la diferencia entre dejar
bash
ecat
intentar abrir/dev/tcp/::1/22
Una diferencia con esto
ksh93
es quebash
solo hará esas conexiones TCP con operadores de redireccionamiento, no en los otros lugares donde puede abrir archivos como elsource
o.
incorporado.fuente
gawk
casos especiales similares/inet{,4,6}/{tcp,udp}/$port/$remote/$rport
, desde algún lugar alrededor de 2010 (no recuerdo exactamente y no puedo encontrar notas de la versión)./dev/tcp
es que NO es un archivo. Nunca hay un archivo llamado esto. La sintaxis de Bash para abrir sockets usa la cadena/dev/tcp/address
como un nombre de archivo, pero llamarlo "archivo implementado en el espacio del usuario" suena extraño. Sinksh
embargo, es interesante que enganche esos nombres de archivo para todo, no solo para los redireccionamientos. Eso está más cerca de "implementar un archivo".bash
solo copió este comportamiento, pero se origina en otro lugar.Además de los nodos de dispositivos explicados en otras respuestas (creadas con mknod (2) o suministradas por algunos devfs ), Linux tiene otros archivos "mágicos" proporcionados por sistemas de archivos virtuales especiales , en particular en
/proc/
(ver proc (5) , leer sobre procfs ) y en/sys/
(leer sobre sysfs ).Estos pseudo archivos (que aparecen -eg a stat (2) - como archivos normales, no como dispositivos) son una vista virtual proporcionada por el núcleo; en particular, leer desde
/proc/
(p. ej.cat /proc/$$/maps
, con open (2) -ing/proc/self/status
en su programa) generalmente no implica ninguna E / S física desde el disco o la red, por lo que es bastante rápido.Para crear un pseudo-archivo adicional
/proc/
, generalmente debe escribir su propio módulo de kernel y cargarlo (ver, por ejemplo, esto ).fuente
Se llaman nodos de dispositivo y se crean de forma manual
mknod
o automática conudev
. Por lo general, son interfaces en forma de archivos para dispositivos de caracteres o bloques con controladores en el núcleo; por ejemplo, los discos son dispositivos de bloque, ttys y puertos seriales, etc., son dispositivos de caracteres.También hay otros tipos de archivos "especiales", que incluyen canalizaciones con nombre y fifos y sockets.
fuente
Como otros usuarios ya han explicado con gran detalle, los archivos especiales requieren código para realizar una copia de seguridad. Sin embargo, nadie parece haber mencionado que Linux proporciona varias formas de escribir ese código en el espacio de usuario:
A. FUSE (Sistema de archivos en USErspace) le permite escribir algo como
/proc
sin riesgo de bloquear el núcleo y hacerlo en el idioma / tiempo de ejecución de su elección, como Go , Node.js , Perl , PHP , Python , Ruby , Rust , etc .También tiene la ventaja de que los sistemas de archivos FUSE se pueden montar sin
sudo
ellos porque se ejecutan como el usuario que realiza el montaje.Aquí hay algunos ejemplos de cosas que la gente ha escrito usando FUSE:
B. Si desea crear un dispositivo de entrada virtual como un teclado, mouse, joystick, etc. (por ejemplo, para escribir un controlador de espacio de usuario para un dispositivo USB con el que está hablando
libusb
), hay una entrada .Los enlaces son más difíciles de encontrar, pero sé que existen para Go (solo con teclado), Python y Ruby (2) .
Los ejemplos de uso de entrada real en el mundo real incluyen:
C. Para dispositivos de caracteres genéricos, hay CUSE (dispositivos de caracteres en USErspace). Sin embargo, es mucho menos popular.
El único usuario de la API CUSE que estoy personalmente en cuenta es el mismo programa que impulsó su creación: osspd , que implementa
/dev/dsp
,/dev/adsp
y/dev/mixer
(la API de audio OSS) en el espacio de usuario para que puedan ser enrutados a través de PulseAudio o dmix.El único enlace de CUSE que pude encontrar es cusepy , que no se ha actualizado desde 2010.
D. Es posible que no necesite un nuevo archivo especial en absoluto.
Por ejemplo, puede abrir la comunicación en bruto con cualquier dispositivo USB usando libusb (Lista de enlaces en la página) y luego comunicarse con otros programas a través de algún otro mecanismo (sockets TCP / UDP, lectura / escritura de stdin / stdout o archivos regulares en el disco , etc.)
fuente
poll
, pero dado que cusepy usa ctypes y los enlaces se generan automáticamente en función de los archivos de encabezado C, corregir las funciones que faltan es solo cuestión de agregar el nombre de la función deseada a la lista de funciones exportadas en elsetup.py
.El libro Linux Device Drivers (altamente recomendado) explica esto en detalle, e incluso le hace crear un módulo de kernel que lo hace como un ejemplo, pero en pocas palabras, cada controlador de dispositivo tiene funciones específicas que se llaman cuando se abre, cierra un archivo , leer, escribir, etc. Los archivos "especiales" simplemente hacen algo especial dentro de esas funciones, en lugar de acceder al hardware de almacenamiento en un disco.
Por ejemplo, la función de escritura
/dev/null
simplemente no hace nada, ignorando los bytes. La función de lectura para/dev/random
devuelve un número aleatorio.fuente
mount -t devtmpfs
También es interesante ver que en los sistemas modernos,
/dev
normalmente es un tipo de sistema de archivos que se puede montar donde lo desee. Ubuntu 16.04:Esto está habilitado por
CONFIG_DEVTMPFS=y
y permite que el núcleo mismo cree y destruya los archivos del dispositivo según sea necesario.CONFIG_DEVTMPFS_MOUNT=y
Esta opción hace que el núcleo monte automáticamente devtmpfs
/dev
.drivers/base/Kconfig
documentos:file_operations
Finalmente, debe crear su propio módulo de kernel de dispositivo de caracteres para ver exactamente lo que está sucediendo.
Aquí hay un ejemplo ejecutable mínimo: Comprensión de los archivos de dispositivos de caracteres (o caracteres especiales)
El paso más importante es configurar la
file_operations
estructura, por ejemplo:que contiene punteros de función que se llaman para cada llamada al sistema relacionada con el archivo.
Entonces resulta obvio que anula esas llamadas al sistema relacionadas con archivos para hacer lo que quiera, y así es como el núcleo implementa los dispositivos
/dev/zero
.Crear
/dev
entradas automáticamente sinmknod
El misterio final es cómo el núcleo crea
/dev
entradas automáticamente .El mecanismo se puede observar haciendo un módulo de kernel que lo haga usted mismo como se muestra en: https://stackoverflow.com/questions/5970595/how-to-create-a-device-node-from-the-init-module- code-of-a-linux-kernel-module / 45531867 # 45531867 y se reduce a una
device_create
llamada.fuente