TP 06 - Communication Entre Processus
Resources
Pipe
Une pipe
est une forme de redirection (transfert de la sortie standard vers une autre destination) qui est utilisée dans Linux et d'autres systèmes d'exploitation de type Unix pour envoyer la sortie d'une commande/programme/processus à une autre commande/programme/processus pour un traitement ultérieur .
Le canal est un mécanisme de communication à sens unique entre deux processus. Dans la plupart des implémentations UNIX, un canal apparaît comme une zone mémoire d'une certaine taille dans l'espace du noyau. Les processus qui communiquent via un canal anonyme doivent avoir un certain degré de parenté; généralement, un processus qui crée un pipe sera alors appelé une fork
, et le pipe sera utilisé pour la communication parent-enfant. Dans tous les cas, les processus qui communiquent via des canaux anonymes ne peuvent pas être créés par différents utilisateurs du système.
Pipe est utilisé pour combiner deux commandes ou plus, et dans ce cas, la sortie d'une commande agit comme entrée d'une autre commande, et la sortie de cette commande peut servir d'entrée pour la commande suivante et ainsi de suite. Il peut également être visualisé comme une connexion temporaire entre deux ou plusieurs commandes/programmes/processus.
Exemple d'utilisation de pipes en Rust: pipe.
use nix::unistd::pipe;
fn main() {
let (fdw0, fdw1) = pipe().unwrap();
}
Le tuple (fdw0, fdw1)
contient après l'exécution de la fonction 2 descripteurs de fichiers:
fdw0
ouvert à la lecturefdw1
ouvert pour l'écriture
La sortie de fdw1
est considérée comme une entrée pour fdw0
.
- la lecture / écriture depuis / vers les canaux est atomique si vous ne lisez / écrivez pas plus de
PIPE_BUF
octets. - la lecture / écriture depuis / vers les pipes se fait à l'aide des fonctions
stdin().read_line()
/stdout().write()
La plupart des applications qui utilisent des pipes ferment dans chacun des processus l'extrémité du pipe inutilisé en communication unidirectionnelle. Si l'un des descripteurs est fermé, les règles s'appliquent:
-
une lecture à partir d'un canal pour lequel le descripteur d'écriture a été fermé, après que toutes les données ont été lues, renverra
0
, indiquant la fin du fichier. Le descripteur d'écriture peut être dupliqué afin que plusieurs processus puissent écrire dans le canal. Habituellement, dans le cas des canaux anonymes, il n'y a que deux processus, l'un qui écrit et l'autre qui lit, tandis que dans le cas des fichiers de canal nommé (FIFO), il peut y avoir plusieurs processus qui écrivent des données. -
une écriture dans un pipe pour lequel le descripteur read a été fermé provoque la génération du signal
SIGPIPE
. Si le signal est capturé et revient de la routine de traitement, la fonction système écriture renvoie une erreur et la variableerrno
a la valeur EPIPE .
L'erreur la plus courante , lorsque vous travaillez avec des pipes, vient de la négligence du fait que EOF
n'est pas envoyé à travers les pipes (la lecture des pipes ne se termine pas) à moins que toutes les extrémités ne soient fermées. TOUS les processus qui ont ouvert le descripteur de pipe (dans le cas d'une fork, assurez-vous de fermer les extrémités du pipe dans le processus parent).
Suggestions
Transformer un String en &[u8] peut être fait en utilisant
s.as_bytes()
Transformer un descripteur de fichier en File
peut être fait en utilisant
let mut f = unsafe { fs::File::from_raw_fd(fd) };
Exercises
- Écrivez un programme qui crée un pipe et un processus (processus enfant en utlisant fork). Du parent, lisez à partir du clavier un message et envoyez-le par le canal à l'enfant. Apres ca, inversez le message dans l'enfant et envoyez-le au parent.
- Écrivez un programme qui crée un pipe et un processus (un processus enfant en utlisant fork). Le processus enfant redirige son ecran vers le pipe et exécute ls -l. Le processus parent lit la sortie de l'enfant à partir du pipe et l'affiche.
- Écrivez un programme qui crée un pipe et 2 processus (deux processus enfant en utlisant fork doix fois). Le premier enfant exécute
ls -l
et le deuxième enfant exécutegrep src
. Le parent connecte l'affichage du premier enfant au clavier du deuxième enfant avec un pipe.