Sous Linux, un tube est un mécanisme de communication qui connecte directement la sortie d'un programme à l'entrée d'un autre programme. Essentiellement, un tube est aussi une sorte de fichier, mais il est différent d'un fichier général. Les tubes peuvent résoudre deux problèmes liés à l'utilisation de fichiers pour la communication. Les manifestations spécifiques sont : la limitation de la taille du tube et le processus de lecture peut fonctionner. plus rapide que Le processus d'écriture est rapide.
L'environnement d'exploitation de ce tutoriel : système linux7.3, ordinateur Dell G3.
Pipeline est une méthode de communication très importante sous Linux. Il connecte directement la sortie d'un programme à l'entrée d'un autre programme. Les canaux font souvent référence à des canaux sans nom. Les canaux sans nom ne peuvent être utilisés qu'entre des processus liés. C'est la plus grande différence entre eux et les canaux nommés.
Le fameux tube est appelé tube nommé ou FIFO (premier entré, premier sorti), qui peut être créé avec la fonction mkfifo().
Le mécanisme d'implémentation des pipes Linux
Sous Linux, les pipes sont un mécanisme de communication très fréquemment utilisé. Essentiellement, un tube est aussi une sorte de fichier, mais il est différent d'un fichier général. Les tubes peuvent résoudre deux problèmes liés à l'utilisation de fichiers pour la communication, notamment les suivants :
Limiter la taille du tube. En fait, un canal est un tampon de taille fixe. Sous Linux, la taille de ce tampon est de 1 page, soit 4 Ko, afin que sa taille n'augmente pas de manière incontrôlée comme un fichier. L'utilisation d'un seul tampon fixe peut également causer des problèmes, tels que le canal peut devenir plein lors de l'écriture. Lorsque cela se produit, les appels write() suivants au canal seront bloqués par défaut, en attendant que certaines données soient lues, afin de libérer suffisamment d'espace. pour que l'appel write() soit écrit.
Le processus de lecture peut également fonctionner plus rapidement que le processus d'écriture. Le tube devient vide lorsque toutes les données de processus actuelles ont été lues. Lorsque cela se produit, un appel read() ultérieur bloquera par défaut, en attendant que certaines données soient écrites, ce qui résout le problème des appels read() renvoyant la fin du fichier.
Remarque : La lecture des données du canal est une opération unique. Une fois les données lues, elles sont supprimées du canal, libérant ainsi de l'espace pour écrire davantage de données.
1. La structure du pipeline
Sous Linux, l'implémentation du pipeline n'utilise pas de structure de données particulière, mais s'appuie sur la structure de fichiers du système de fichiers et sur le nœud d'index inode du VFS. Ceci est réalisé en pointant deux structures de fichiers vers le même nœud d'index VFS temporaire, qui à son tour pointe vers une page physique.
2. Lecture et écriture de pipes
Le code source de l'implémentation du pipeline se trouve dans fs/pipe.c. Il existe de nombreuses fonctions dans pipe.c, parmi lesquelles deux fonctions sont plus importantes, à savoir la fonction de lecture de pipe pipe_read. () et la fonction d'écriture Pipe pipe_wrtie(). La fonction d'écriture pipe écrit les données en copiant les octets dans la mémoire physique pointée par le nœud d'index VFS, tandis que la fonction de lecture pipe lit les données en copiant les octets dans la mémoire physique. Bien entendu, le noyau doit utiliser un certain mécanisme pour synchroniser l'accès au canal. Pour ce faire, le noyau utilise des verrous, des files d'attente et des signaux.
Lorsque le processus d'écriture écrit dans le tube, il utilise la fonction de bibliothèque standard write(). Le système peut trouver la structure du fichier en fonction du descripteur de fichier transmis par la fonction de bibliothèque. La structure du fichier spécifie l'adresse de la fonction utilisée pour effectuer les opérations d'écriture (c'est-à-dire la fonction d'écriture), de sorte que le noyau appelle cette fonction pour terminer l'opération d'écriture. Avant que la fonction d'écriture n'écrive des données dans la mémoire, elle doit d'abord vérifier les informations dans le nœud d'index VFS, et le travail de copie de mémoire réel ne peut être effectué que lorsque les conditions suivantes sont remplies :
Il y a suffisamment d'espace dans la mémoire pour accueillir toutes les données requises Les données écrites
La mémoire n'est pas verrouillée par le programme de lecture.
Si les conditions ci-dessus sont remplies en même temps, la fonction d'écriture verrouille d'abord la mémoire, puis copie les données de l'espace d'adressage du processus d'écriture vers la mémoire. Sinon, le processus d'écriture dort dans la file d'attente du nœud d'index VFS. Ensuite, le noyau appellera le planificateur et le planificateur choisira d'autres processus à exécuter. Le processus d'écriture est en fait dans un état d'attente pouvant être interrompu. Lorsqu'il y a suffisamment d'espace dans la mémoire pour accueillir les données écrites, ou que la mémoire est déverrouillée, le processus de lecture réveillera le processus d'écriture. À ce moment-là, le processus d'écriture recevra. le signal. Une fois les données écrites dans la mémoire, la mémoire est déverrouillée et tous les processus de lecture dormant sur le nœud d'index sont réveillés.
Le processus de lecture de la pipe est similaire au processus d'écriture. Cependant, un processus peut renvoyer un message d'erreur immédiatement lorsqu'il n'y a pas de données ou lorsque la mémoire est verrouillée, plutôt que de bloquer le processus, selon le mode d'ouverture du fichier ou du canal. Au contraire, le processus peut dormir dans la file d'attente du nœud d'indexation et attendre que le processus d'écriture écrive les données. Lorsque tous les processus ont terminé l'opération du canal, l'inode du canal est supprimé et les pages de données partagées sont libérées.
Étant donné que la mise en œuvre de pipelines implique le fonctionnement de nombreux fichiers, lorsque les lecteurs auront fini de se familiariser avec le système de fichiers et liront ensuite le code dans pipe.c, vous ne trouverez pas difficile à comprendre.
Les pipes Linux sont plus simples à créer et à utiliser, simplement parce qu'elles nécessitent moins de paramètres. Pour atteindre le même objectif de création de tuyaux que sous Windows, Linux et UNIX, utilisez l'extrait de code suivant :
Création d'un tuyau nommé Linux
int fd1[2]; if(pipe(fd1)) { printf("pipe() FAILED: errno=%d",errno); return 1; }
Les tuyaux Linux ont une limite sur la taille d'une opération d'écriture avant le blocage. Le tampon au niveau du noyau utilisé spécifiquement pour chaque canal est exactement de 4 096 octets. Une opération d'écriture supérieure à 4K sera bloquée à moins que le lecteur efface le canal. En pratique, ce n'est pas une limitation, puisque les opérations de lecture et d'écriture sont implémentées dans des threads différents.
Linux prend également en charge les canaux nommés. Un des premiers commentateurs de ces chiffres a suggéré que je devrais, par souci d'équité, comparer les canaux nommés de Linux aux canaux nommés de Windows. J'ai écrit un autre programme qui utilise des canaux nommés sous Linux. J'ai trouvé qu'il n'y avait aucune différence dans les résultats pour les canaux nommés et sans nom sous Linux.
Les canaux nommés Linux sont beaucoup plus rapides que les canaux nommés Windows 2000, et les canaux nommés Windows 2000 sont beaucoup plus rapides que les canaux nommés Windows XP.
Exemple :
#include<stdio.h> #include<unistd.h> int main() { int n,fd[2]; // 这里的fd是文件描述符的数组,用于创建管道做准备的 pid_t pid; char line[100]; if(pipe(fd)<0) // 创建管道 printf("pipe create error/n"); if((pid=fork())<0) //利用fork()创建新进程 printf("fork error/n"); else if(pid>0){ //这里是父进程,先关闭管道的读出端,然后在管道的写端写入“hello world" close(fd[0]); write(fd[1],"hello word/n",11); } else{ close(fd[1]); //这里是子进程,先关闭管道的写入端,然后在管道的读出端读出数据 n= read(fd[0],line,100); write(STDOUT_FILENO,line,n); } exit(0); }
Apprentissage recommandé : Tutoriel vidéo Linux
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!