Estaba investigando la otra pregunta , cuando me di cuenta de que no entiendo lo que sucede debajo del capó, qué son esos /dev/fd/*archivos y cómo es que los procesos secundarios pueden abrirlos.
bash
process-substitution
x-yuri
fuente
fuente

Respuestas:
Bueno, hay muchos aspectos.
Descriptores de archivo
Para cada proceso, el kernel mantiene una tabla de archivos abiertos (bueno, podría implementarse de manera diferente, pero como no puede verlo de todos modos, puede asumir que es una tabla simple). Esa tabla contiene información sobre qué archivo es / dónde se puede encontrar, en qué modo lo abrió, en qué posición está leyendo / escribiendo actualmente, y cualquier otra cosa necesaria para realizar operaciones de E / S en ese archivo. Ahora el proceso nunca llega a leer (o incluso escribir) esa tabla. Cuando el proceso abre un archivo, recupera el llamado descriptor de archivo. Que es simplemente un índice en la tabla.
El directorio
/dev/fdy su contenido.En Linux
dev/fdes en realidad un enlace simbólico a/proc/self/fd./proces un pseudo sistema de archivos en el que el kernel mapea varias estructuras de datos internas para acceder con la API de archivos (por lo que solo parecen archivos / directorios / enlaces simbólicos normales a los programas). Especialmente hay información sobre todos los procesos (que es lo que le dio el nombre). El enlace simbólico/proc/selfsiempre se refiere al directorio asociado con el proceso que se está ejecutando actualmente (es decir, el proceso que lo solicita; por lo tanto, diferentes procesos verán diferentes valores). En el directorio del proceso, hay un subdirectoriofdque para cada archivo abierto contiene un enlace simbólico cuyo nombre es solo la representación decimal del descriptor de archivo (el índice en la tabla de archivos del proceso, consulte la sección anterior), y cuyo objetivo es el archivo al que corresponde.Descriptores de archivo al crear procesos secundarios
Un proceso hijo es creado por a
fork. Aforkhace una copia de los descriptores de archivo, lo que significa que el proceso hijo creado tiene la misma lista de archivos abiertos que el proceso padre. Por lo tanto, a menos que el niño cierre uno de los archivos abiertos, el acceso a un descriptor de archivo heredado en el niño accederá al mismo archivo que el acceso al descriptor de archivo original en el proceso padre.Tenga en cuenta que después de una bifurcación, inicialmente tiene dos copias del mismo proceso que difieren solo en el valor de retorno de la llamada de la bifurcación (el padre obtiene el PID del niño, el niño obtiene 0). Normalmente, un tenedor es seguido por un
execpara reemplazar una de las copias por otro ejecutable. Los descriptores de archivos abiertos sobreviven a ese ejecutivo. Tenga en cuenta también que antes del ejecutivo, el proceso puede hacer otras manipulaciones (como cerrar archivos que el nuevo proceso no debería obtener o abrir otros archivos).Tubos sin nombre
Una tubería sin nombre es solo un par de descriptores de archivo creados a pedido por el núcleo, de modo que todo lo escrito en el primer descriptor de archivo se pasa al segundo. El uso más común es para la construcción
foo | barde tuberías debash, donde la salida estándar defoose reemplaza por la parte de escritura de la tubería, y la entrada estándar se reemplaza por la parte de lectura. La entrada estándar y la salida estándar son solo las dos primeras entradas en la tabla de archivos (la entrada 0 y 1; 2 es un error estándar), y por lo tanto reemplazarla significa simplemente reescribir esa entrada de la tabla con los datos correspondientes al otro descriptor de archivo (nuevamente, el La implementación real puede diferir). Como el proceso no puede acceder a la tabla directamente, hay una función del núcleo para hacerlo.Proceso de sustitución
Ahora tenemos todo junto para comprender cómo funciona la sustitución del proceso:
echoproceso. El proceso secundario (que es una copia exacta delbashproceso original ) cierra el extremo de lectura de la tubería y reemplaza su propia salida estándar con el final de escritura de la tubería. Dado queechoes un shell integrado,bashpuede ahorrarse laexecllamada, pero no importa de todos modos (el shell incorporado también puede estar deshabilitado, en cuyo caso se ejecuta/bin/echo).<(echo 1)por el enlace del pseudo archivo al/dev/fdreferirse al final de la lectura de la tubería sin nombre./dev/fd/. Dado que el descriptor de archivo correspondiente todavía está abierto, todavía corresponde al final de la lectura de la tubería. Por lo tanto, si el programa PHP abre el archivo dado para leer, lo que realmente hace es crear unseconddescriptor de archivo para el final de la lectura de la tubería sin nombre. Pero eso no es problema, podría leer de cualquiera.echocomando que va al final de la escritura de la misma tubería.fuente
phpescenario, perophpno maneja bien las tuberías . Además, considerando el comandocat <(echo test), lo extraño aquí es que sebashbifurca una vezcat, pero dos vecesecho test.Tomando prestado de
celtschkla respuesta de,/dev/fdes un enlace simbólico a/proc/self/fd. Y/proces un pseudo sistema de archivos, que presenta información sobre procesos y otra información del sistema en una estructura jerárquica similar a un archivo. Los archivos en/dev/fdcorresponden a archivos, abiertos por un proceso y tienen un descriptor de archivo como sus nombres y los archivos mismos como sus objetivos. Abrir el archivo/dev/fd/Nes equivalente a duplicar el descriptorN(suponiendo que el descriptorNesté abierto).Y aquí están los resultados de mi investigación de cómo funciona (la
stracesalida se deshace de detalles innecesarios y se modifica para expresar mejor lo que está sucediendo):Básicamente,
bashcrea una tubería y pasa sus extremos a sus elementos secundarios como descriptores de archivo (lectura de fin1.outy escritura de fin2.out). Y pasa el fin de lectura como un parámetro de línea de comando a1.out(/dev/fd/63). De esta manera1.outse puede abrir/dev/fd/63.fuente