¿Son FIFO, pipe y socket de dominio Unix lo mismo en el kernel de Linux?


30

Escuché que los FIFO se llaman tubos. Y tienen exactamente la misma semántica. Por otro lado, creo que el socket de dominio Unix es bastante similar a pipe (aunque nunca lo he usado). Así que me pregunto si todos se refieren a la misma implementación en el kernel de Linux. ¿Alguna idea?


De la respuesta a continuación me di cuenta de que mi pregunta es algo ambigua y es difícil de responder. Es probable que nadie pueda conocer tantos detalles de cosas de implementación en el núcleo (incluso para los desarrolladores del núcleo). Si alguien puede confirmar que el socket, la tubería y el FIFO del dominio Unix almacenan los datos que se envían en la memoria compartida bajo Linux, mi pregunta está resuelta Bueno ... en parte resuelto.
Justin

FIFO = tuberías con nombre! = Tuberías. Los FIFO pueden ser bidireccionales como un par de enchufes. Las tuberías regulares son unidireccionales. Todos tienen la interfaz de archivo y la semántica de archivo. ¿Por qué te importa la implementación?
PSkocik

Sé que las tuberías son memorias intermedias circulares, y que con el sistema STREAMS, estas pueden tener una implementación compartida, sin embargo, Linux no usa STREAMS de manera predeterminada. Creo que Linux codifica estos canales IPC. Sin embargo, no tengo ganas de comprobar. : D ¿Por qué no? El código está disponible públicamente.
PSkocik

Si todos comparten la misma implementación, su eficiencia debería ser cercana entre sí. Y, para mí, el código del núcleo es demasiado difícil de entender.
Justin

Respuestas:


35

Los sockets de dominio UNIX y FIFO pueden compartir parte de su implementación, pero conceptualmente son muy diferentes. FIFO funciona a un nivel muy bajo. Un proceso escribe bytes en la tubería y otro lee de él. Un socket de dominio UNIX tiene el mismo comportamiento que un socket TCP / IP.

Un socket es bidireccional y puede ser utilizado por muchos procesos simultáneamente. Un proceso puede aceptar muchas conexiones en el mismo socket y atender a varios clientes simultáneamente. El núcleo entrega un nuevo descriptor de archivo cada vez connect(2)o accept(2)se llama en el socket. Los paquetes siempre irán al proceso correcto.
En un FIFO, esto sería imposible. Para la comunicación bidireccional, necesita dos FIFO y un par de FIFO para cada uno de sus clientes. No hay forma de escribir o leer de forma selectiva, porque son una forma mucho más primitiva de comunicarse.

Las tuberías anónimas y los FIFO son muy similares. La diferencia es que las tuberías anónimas no existen como archivos en el sistema de archivos, por lo que ningún proceso puede open(2)hacerlo. Son utilizados por procesos que los comparten por otro método. Si un proceso abre un FIFO y luego realiza, por ejemplo, a fork(2), su hijo heredará sus descriptores de archivo y, entre ellos, la tubería.

Los sockets de dominio UNIX, las canalizaciones anónimas y los FIFO son similares en el hecho de que usan segmentos de memoria compartida. Los detalles de la implementación pueden variar de un sistema a otro, pero la idea es siempre la misma: adjuntar la misma porción de memoria en dos procesos distintos de mapeo de memoria para que compartan datos
( editar: esa sería una forma obvia de implementarlo, pero eso es no cómo se hace realmente en Linux, que simplemente usa la memoria del núcleo para las memorias intermedias, consulte la respuesta de @ tjb63 a continuación).
El núcleo luego maneja las llamadas del sistema y abstrae el mecanismo.


"Los sockets de dominio UNIX y FIFO pueden compartir una parte de su implementación" ... el punto es "alguna parte de" ... Me acabo de dar cuenta de que mi pregunta es un tanto ambigua y es difícil de responder. Es probable que nadie pueda conocer tantos detalles de qué partes comparten en el núcleo (incluso para los desarrolladores del núcleo). Sin embargo ... ¿alguien podría confirmar que el socket de dominio Unix, la tubería y FIFO almacenan todos los datos que se envían en la memoria compartida en Linux? Si se confirma, mi pregunta está resuelta. Bueno ... en parte resuelto.
Justin

Bueno, sí, hay un buffer administrado por el núcleo. Por ejemplo, con FIFOs, puedes matar al escritor y el lector aún puede enviar lo que se envió a la tubería antes de la muerte del escritor. Con los sockets, es un poco más complicado porque funcionan con un protocolo conectado. Pero si envía, digamos, un int al socket y luego se sale del alcance para que el int se borre de la pila del remitente, el receptor aún puede leerlo. Entonces, claramente hay un búfer en alguna parte.
lgeorget

Vuelva a leer el comentario, no estoy seguro de que esté claro aquí ... Avíseme si todavía hay algo que no está claro.
lgeorget

Tu comentario es claro para mí.
Justin

7

Aquí hay una buena discusión sobre esto: http://www.slideshare.net/divyekapoor/linux-kernel-implementation-of-pipes-and-fifos

Hasta donde puedo ver, tanto de las diapositivas de la presentación como de la fuente @ http://lxr.free-electrons.com/source/fs/pipe.c : los quince se implementan como una envoltura alrededor de las tuberías, y las tuberías mismas son implementado a través del sistema de archivos virtual pipefs.

@lgeorget: las canalizaciones parecen utilizar la memoria del núcleo para memorias intermedias entre los lectores y los escritores; no utilizan 'memoria compartida' como tal, y copian memoria entre los espacios de direcciones del usuario y del núcleo (por ejemplo, pipe_readllamadas pipe_iov_copy_to_user, qué llamadas __copy_to_user_inatomic(o copy_to_user) . __copy_to_user_inatomicllamadas copy_user_generic, que se encuentra en varias implementaciones de ASM.


4

Un "FIFO" y una " tubería con nombre " es lo mismo, aunque es bastante diferente de cómo un shell maneja una "tubería" (|) entre dos comandos en la línea de comandos.

Una canalización con nombre (FIFO) es un único "archivo" compartido por dos programas, donde uno escribe en él y el otro lee de él ... Un socket, por otro lado, es una "conexión" entre dos "archivos", que puede usar una red y estar en computadoras separadas, donde un programa lee / escribe en un "archivo" y otro programa lee / escribe en el otro ... No creo que sean tan similares ... Por otro lado, ambos sockets y canalizaciones con nombre, así como archivos, dispositivos, enlaces simbólicos, todos usan inodes, y todos implementan algunas características comunes (como leer y escribir).


1
Sí, el socket de dominio de Unix es un tipo de socket, por lo que su API es similar a otras API de socket como TCP o UDP, etc. Sin embargo, el socket de dominio de Unix solo puede usarse como IPC "local". Y la forma en que transfiere datos es de primero a primero, de manera muy similar a FIFO & pipe. Entonces, creo que es posible que la API de socket de dominio de Unix sea solo otra encapsulación de implementación idéntica, por lo que la usamos como si fuera un socket. Creo que es posible que todos compartan el mismo interno en el núcleo ... Quiero confirmar si es cierto o no.
Justin

1

No lo creo, Justin. Si no me equivoco, y posiblemente lo estoy, creo que los FIFO usan un archivo en el disco, y los zócalos de dominio Unix usan la memoria del núcleo.

Además, como una adición al póster anterior que mencionó que los sockets de dominio Unix son bidireccionales, ese es solo el caso cuando se usa un socket SOCK_STREAM. SOCK_DGRAM Los sockets de dominio Unix son, de hecho, unidireccionales, y solo pueden enviar () desde el código que llamó a connect (), al código que llamó a bind ().

Por supuesto, el código que llamó a connect () también debe llamar a bind () para crear su propio punto final, pero eso no tiene nada que ver con su pregunta.


3
Bienvenido a StackExchange y gracias por publicar. Algunas observaciones ... 1) Si está "muy posiblemente" equivocado, debe verificar dos veces antes de responder; Este sitio no es un foro ni un chat. 2) Gracias por su precisión en los sockets orientados a datagramas 3) No es necesario publicar algo que no tenga "nada que ver" con la pregunta. :)
lgeorget

1

Mis 2 centavos ... El socket FIFO y UNIX son bidireccionales (similares) pero el socket tiene una topología en estrella, mientras que un FIFO es solo una cola (y, por lo tanto, no puede reemplazarse entre sí), sí, su implementación puede compartir código internamente.

** **

char * myfifo = "/tmp/myfifo";
mkfifo(myfifo, 0666);
fd = open(myfifo, O_RDWR);   //so that you can read/write to it
 ...
write(fd, buff1, sizeof(buff1));  
getchar();//wait till some one reds this and writes something else
int sz=read(fd, buff1, sizeof(buff1));  //read that something**

FIFO es bidireccional?
jhfrontz
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.