De nombreux IPC sont proposés par Unix/Linux: tuyaux, sockets, mémoire partagée, dbus, files d'attente de messages ...
Quelles sont les applications les plus adaptées à chacune et comment fonctionnent-elles?
Voici les sept grands:
Utile uniquement parmi les processus liés en tant que parent/enfant. Appelez pipe(2)
et fork(2)
. Unidirectionnel.
FIFO , ou pipe nommée
Deux processus indépendants peuvent utiliser FIFO contrairement au canal ordinaire. Appelez mkfifo(3)
. Unidirectionnel.
Socket et Socket de domaine Unix
Bidirectionnel. Destiné à la communication réseau, mais peut également être utilisé localement. Peut être utilisé pour différents protocoles. Il n'y a pas de limite de message pour TCP. Appelez socket(2)
.
Le système d'exploitation maintient un message discret. Voir sys/msg.h .
Le signal envoie un entier à un autre processus. Ne s'adapte pas bien aux multi-threads. Appelez kill(2)
.
Un mécanisme de synchronisation pour plusieurs processus ou threads, semblable à une file d'attente de personnes attendant la salle de bain. Voir sys/sem.h .
Faites votre propre contrôle d'accès concurrentiel. Appelez shmget(2)
.
Un facteur déterminant lors du choix d'une méthode par rapport à l'autre est le problème de limite de message. Vous pouvez vous attendre à ce que les "messages" soient discrets les uns des autres, mais ce n'est pas pour les flux d'octets comme TCP ou Pipe.
Considérez une paire d'écho client et serveur. Le client envoie une chaîne, le serveur la reçoit et la renvoie immédiatement. Supposons que le client envoie "Bonjour", "Bonjour" et "Que diriez-vous d'une réponse?".
Avec les protocoles de flux d'octets, le serveur peut recevoir comme "Hell", "oHelloHow" et "about an answer?"; ou plus réaliste "HelloHelloHow sur une réponse?". Le serveur n'a aucune idée de la limite du message.
Une astuce séculaire consiste à limiter la longueur du message à CHAR_MAX
ou UINT_MAX
et acceptez d'envoyer d'abord la longueur du message dans char
ou uint
. Donc, si vous êtes du côté de la réception, vous devez d'abord lire la longueur du message. Cela implique également qu'un seul thread doit lire le message à la fois.
Avec des protocoles discrets comme UDP ou des files d'attente de messages, vous n'avez pas à vous soucier de ce problème, mais les flux d'octets programmés sont plus faciles à gérer car ils se comportent comme des fichiers et stdin/out.
La mémoire partagée peut être la plus efficace car vous créez votre propre schéma de communication par-dessus, mais elle nécessite beaucoup de soin et de synchronisation. Des solutions sont également disponibles pour distribuer la mémoire partagée à d'autres machines.
Les prises sont les plus portables de nos jours, mais nécessitent plus de frais généraux que les tuyaux. La possibilité d'utiliser de manière transparente des sockets localement ou sur un réseau est un grand avantage.
Les files d'attente de messages et les signaux peuvent être parfaits pour les applications difficiles en temps réel, mais ils ne sont pas aussi flexibles.
Ces méthodes ont été naturellement créées pour la communication entre les processus, et l'utilisation de plusieurs threads dans un processus peut compliquer les choses - en particulier avec les signaux.
Voici une page Web avec une référence simple: https://sites.google.com/site/rikkus/sysv-ipc-vs-unix-pipes-vs-unix-sockets
Autant que je sache, chacun a ses avantages:
Il convient de noter que de nombreuses bibliothèques implémentent un type de chose au-dessus d'un autre.
La mémoire partagée n'a pas besoin d'utiliser les horribles fonctions de mémoire partagée sysv - il est beaucoup plus élégant d'utiliser mmap () (mmapez un fichier sur un tmpfs/dev/shm si vous voulez le nommer; mmap/dev/zero si vous voulez forked processus non exécutés pour en hériter anonymement). Cela dit, cela laisse toujours à vos processus un certain besoin de synchronisation pour éviter les problèmes - généralement en utilisant certains des autres mécanismes IPC pour effectuer la synchronisation de l'accès à une zone de mémoire partagée.