Le socket de domaine FIFO, pipe et Unix est-il la même chose dans le noyau Linux?

30

J'ai entendu dire que les FIFO s'appelaient des pipes. Et ils ont exactement la même sémantique. D'un autre côté, je pense que le socket de domaine Unix est assez similaire au pipe (bien que je ne m'en sois jamais servi). Je me demande donc s'ils font tous référence à la même implémentation dans le noyau Linux. Une idée?

Justin
la source
À partir de la réponse ci-dessous, j'ai réalisé que ma question était assez ambiguë et qu'il était difficile d'y répondre. Il est probable que personne ne pourrait connaître autant de détails sur les éléments d'implémentation dans le noyau (même pour les développeurs du noyau). Si quelqu'un peut confirmer que le socket de domaine Unix, le canal et le FIFO tamponnent tous les données envoyées dans la mémoire partagée sous Linux, ma question est résolue. Eh bien ... en partie résolu.
Justin
FIFO = tuyaux nommés! = Tuyaux. Les FIFO peuvent être bidirectionnels comme une paire de sockets. Les tuyaux réguliers sont unidirectionnels. Tous ont l'interface de fichier et la sémantique des fichiers. Pourquoi la mise en œuvre est-elle importante pour vous?
PSkocik
Je sais que les canaux sont des tampons circulaires, et qu'avec le système STREAMS, ceux-ci peuvent avoir une implémentation partagée, mais Linux n'utilise pas STREAMS par défaut. Je crois que Linux code dur ces canaux IPC. Mais je n'ai pas envie de vérifier. : D Pourquoi pas toi? Le code est accessible au public.
PSkocik
S'ils partagent tous la même mise en œuvre, leur efficacité devrait être proche les uns des autres. Et, pour moi, le code du noyau est trop difficile à comprendre.
Justin

Réponses:

35

Les sockets de domaine UNIX et FIFO peuvent partager une partie de leur implémentation mais ils sont conceptuellement très différents. FIFO fonctionne à un niveau très bas. Un processus écrit des octets dans le canal et un autre le lit. Un socket de domaine UNIX a le même comportement qu'un socket TCP / IP.

Un socket est bidirectionnel et peut être utilisé par de nombreux processus simultanément. Un processus peut accepter plusieurs connexions sur le même socket et assister simultanément plusieurs clients. Le noyau délivre un nouveau descripteur de fichier à chaque fois connect(2)ou accept(2)est appelé sur le socket. Les paquets iront toujours au bon processus.
Sur un FIFO, ce serait impossible. Pour la communication bidirectionnelle, vous avez besoin de deux FIFO et vous avez besoin d'une paire de FIFO pour chacun de vos clients. Il n'y a aucun moyen d'écrire ou de lire de manière sélective, car ils sont une manière beaucoup plus primitive de communiquer.

Les canaux anonymes et les FIFO sont très similaires. La différence est que les canaux anonymes n'existent pas en tant que fichiers sur le système de fichiers, donc aucun processus ne peut le open(2)faire. Ils sont utilisés par des processus qui les partagent par une autre méthode. Si un processus ouvre un FIFO puis exécute, par exemple, un fork(2), son enfant héritera de ses descripteurs de fichier et, parmi eux, du canal.

Les sockets de domaine UNIX, les canaux anonymes et les FIFO sont similaires dans la mesure où ils utilisent des segments de mémoire partagée. Les détails de l'implémentation peuvent varier d'un système à l'autre mais l'idée est toujours la même: attachez la même portion de mémoire dans deux processus de mappage de mémoire distincts pour les faire partager des données
( modifier: ce serait une façon évidente de l'implémenter mais c'est pas comment cela se fait réellement sous Linux, qui utilise simplement la mémoire du noyau pour les tampons, voir la réponse de @ tjb63 ci-dessous).
Le noyau gère ensuite les appels système et résume le mécanisme.

lgeorget
la source
"Les sockets de domaine UNIX et FIFO peuvent partager une partie de leur implémentation" ... le point est "une partie de" ... Je viens de réaliser que ma question est en quelque sorte ambiguë et il est difficile d'y répondre. Il est probable que personne ne pourrait connaître autant de détails sur les parties qu'ils partagent dans le noyau (même pour les développeurs du noyau). Néanmoins ... quelqu'un pourrait-il confirmer que le socket de domaine Unix, le canal et le FIFO tamponnent tous les données envoyées dans la mémoire partagée sous Linux? Si c'est confirmé, ma question est résolue. Eh bien ... en partie résolu.
Justin
Eh bien, oui, il y a un tampon géré par le noyau. Par exemple, avec les FIFO, vous pouvez tuer l'écrivain et le lecteur peut encore ce qui a été envoyé dans la pipe avant la mort de l'écrivain. Avec les sockets, c'est un peu plus compliqué car ils fonctionnent avec un protocole connecté. Mais si vous envoyez, disons, un int à la socket, puis sortez de la portée pour que l'int soit effacé de la pile des expéditeurs, le récepteur peut toujours le lire. Donc, il y a clairement un tampon quelque part.
lgeorget
En relisant le commentaire, je ne suis pas sûr d'être clair ici ... Faites-moi savoir s'il y a encore quelque chose de peu clair.
lgeorget
Votre commentaire est clair pour moi.
Justin
7

Il y a une assez bonne discussion à ce sujet ici: http://www.slideshare.net/divyekapoor/linux-kernel-implementation-of-pipes-and-fifos

Pour autant que je puisse voir, à la fois à partir des diapositives de présentation et de la source @ http://lxr.free-electrons.com/source/fs/pipe.c - les fifo sont implémentés comme un wrapper autour des tuyaux, et les tuyaux eux-mêmes sont implémenté via le système de fichiers virtuel pipefs.

@lgeorget - Les canaux semblent utiliser la mémoire du noyau pour les tampons entre les lecteurs et les écrivains - ils n'utilisent pas la «mémoire partagée» en tant que telle, et copient la mémoire entre les espaces d'adressage utilisateur et noyau (par exemple, les pipe_readappels pipe_iov_copy_to_user, qui appelle __copy_to_user_inatomic(ou copy_to_user) . __copy_to_user_inatomiccalls copy_user_generic, qui fait partie de plusieurs implémentations ASM.

tjb63
la source
4

Un "FIFO" et un " pipe nommé " sont la même chose - bien que ce soit très différent de la façon dont un shell gère un "pipe" (|) entre deux commandes sur la ligne de commande.

Un canal nommé (FIFO) est un seul "fichier" partagé par deux programmes, où l'un y écrit et l'autre le lit ... Un socket d'autre part est une "connexion" entre deux "fichiers" - qui peut utiliser un réseau et être sur des ordinateurs séparés - où un programme lit / écrit dans un "fichier" et un autre programme lit / écrit dans l'autre ... Je ne pense pas qu'ils soient aussi similaires ... D'un autre côté, les deux les sockets et les canaux nommés - ainsi que les fichiers, les périphériques, les liens symboliques - utilisent tous des inodes et implémentent tous des fonctionnalités communes (comme la lecture et l'écriture).

Baard Kopperud
la source
1
Oui, la socket de domaine Unix est une sorte de socket, donc son API est similaire à d'autres API de socket telles que TCP ou UDP, etc. Cependant, la socket de domaine Unix ne peut être utilisée que comme IPC "local". Et la façon dont il transfère les données est du premier entré, premier sorti, un peu comme FIFO et pipe. Je pense donc qu'il est possible que l'API du socket de domaine Unix soit juste une autre encapsulation d'une implémentation identique, nous l'utilisons donc comme s'il s'agissait d'un socket. Je pense qu'il est possible qu'ils partagent tous le même interne dans le noyau ... Je veux confirmer si c'est vrai ou non.
Justin
1

Je ne pense pas, Justin. Si je ne me trompe pas, et je le suis très probablement, je pense que les FIFO utilisent un fichier sur le disque, et les sockets de domaine Unix utilisent la mémoire du noyau.

En outre, en plus de l'affiche ci-dessus qui a mentionné que les sockets de domaine Unix sont bidirectionnelles, ce n'est le cas que lors de l'utilisation d'un socket SOCK_STREAM. SOCK_DGRAM Les sockets de domaine Unix sont en fait unidirectionnels et ne peuvent envoyer () qu'à partir du code qui a appelé connect (), vers le code qui a appelé bind ().

Bien sûr, le code qui a appelé connect () doit également appeler bind () pour créer son propre point de terminaison, mais cela n'a rien à voir avec votre question.

Anonyme
la source
3
Bienvenue sur StackExchange et merci d'avoir posté. Quelques remarques ... 1) Si vous vous trompez "très probablement", vous devriez revérifier avant de répondre; ce site n'est ni un forum ni un chat. 2) Merci pour votre précision sur les sockets orientées datagramme 3) Il n'est pas nécessaire de poster quelque chose qui n'a "rien à voir" avec la question. :)
lgeorget
1

Mes 2 cents ... FIFO et socket UNIX sont tous les deux bidirectionnels (similaires) mais le socket a une topologie en étoile tandis qu'un FIFO n'est qu'une file d'attente (et ne peut donc pas se remplacer), oui, leur implémentation peut partager du code en interne.

**

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**
Asif Bahrainwala
la source
FIFO est bidirectionnel?
jhfrontz