Maison > Article > Opération et maintenance > Explication détaillée d'exemples de gestion du tampon IO
Le prototype d'écriture dans le système Linux IO est ssize_t write(int filees, const void * buff, size_t nbytes);
Lors de l'appel d'écriture Lors de la lecture des données, l'écriture revient directement une fois l'appel terminé, mais le disque est un périphérique lent. Le système d'exploitation enregistrera les données dans le tampon du noyau et sera responsable de l'écriture des données sur le disque de manière asynchrone. Bien entendu, si le système tombe en panne à ce moment-là, les données seront perdues. Write est un appel système, et chaque appel piègera le noyau, donc choisir une taille de tampon de longueur de bloc appropriée et minimiser ses appels peut optimiser l'efficacité. Dans les IO standard d'ANSI C, lorsque nous appelons printf/fprintf/fputs, etc., ils seront traités dans un flux. Nous avons seulement besoin d'écrire dans le flux au lieu de sélectionner une taille de buff comme write, car la bibliothèque IO standard gère. de nombreux détails pour nous, tels que l'allocation de tampon, l'exécution d'E/S avec une longueur optimisée, etc. Cela réduira le nombre d’appels système d’écriture/lecture et améliorera l’efficacité. Mais en même temps, un autre problème sera introduit : la copie des données. Par exemple, lors de l'utilisation des fonctions fgets et fputs, elle doit généralement passer par deux tampons : l'un est le tampon IO standard et l'autre est le tampon du noyau qui est utilisé. appels en lecture et en écriture. Mais en général, l’utilisation des E/S standard a une interface plus simple que celle du système et est tout aussi efficace.
Standard IO fournit trois types de tampons : cache complet, cache de ligne et aucun cache. Le cache complet ne sera activement vidé que lorsque le tampon est plein. Il est généralement utilisé pour un fichier disque IO. . Le cache de ligne sera vidé lorsqu'il rencontrera un caractère de nouvelle ligne dans le tampon. Dans un autre cas, le tampon sera vidé lorsque les données d'entrée doivent être obtenues à partir de l'entrée et de la sortie standard. Le cache de ligne est généralement utilisé dans les terminaux interactifs. Sans mise en cache, cela équivaut à écrire directement la sortie de l'appel système. Le flux d'erreur standard stderr n'est généralement pas mis en cache, ce qui permet d'afficher le message d'erreur le plus rapidement possible. En plus des conditions de vidage par défaut, le tampon sera également vidé lorsque la fonction fflush est explicitement appelée et que le programme se termine normalement. Nous pouvons utiliser setbuf/setvbuf pour modifier la longueur du tampon par défaut, voir APUE Section 5.4.
Dans un programme qui utilise les E/S standard, lorsque nous redirigeons une sortie standard vers un fichier, le cache de ligne deviendra un cache complet, ce qui peut provoquer des erreurs inattendues, comme lors de l'appel printf("*****n"), sera affiché normalement lorsque le programme est exécuté en mode interactif. Mais lorsque la sortie standard est redirigée vers un fichier, la zone tampon est entièrement mise en cache, printf ne produira pas normalement et la ligne de données est toujours dans le tampon. Si vous créez un processus enfant à ce moment-là, lorsque l'espace de données est copié dans le processus enfant, les données du tampon seront également copiées dans le processus enfant. Ensuite, si la sortie est effectuée dans le processus enfant, le contenu précédent du tampon sera actualisé, ce qui entraînera une sortie inattendue.
Dans la programmation réseau, les IO système doivent être utilisées directement. Le mécanisme de mise en mémoire tampon introduit par les IO standard pour améliorer les performances augmente la complexité des applications réseau. De plus, dans un certain sens, le flux IO standard est en duplex intégral et peut effectuer des entrées et des sorties en même temps. Cependant, les restrictions sur les flux et les restrictions sur les sockets entrent parfois en conflit. (Voir CSAPP P611)
Certaines bibliothèques réseau avancées (telles que la bibliothèque muduo) créeront leurs propres tampons basés sur l'utilisation des E/S du système pour aider les utilisateurs à protéger les E/S du système. Certains inconvénients, tels comme lors de l'appel d'écriture pour envoyer une grande quantité de données, la couche application doit attendre lorsque le tampon d'envoi est plein, et lorsque la lecture reçoit des données, les paquets sont collants et les données sont reçues lentement. Lorsque le tampon de la couche application est ajouté, la bibliothèque réseau gère ces détails d'implémentation pour simplifier les opérations de l'utilisateur.
Linux propose également une technologie zéro copie pour réduire les copies de mémoire et ainsi améliorer l'efficacité. Nous savons que l'utilisation de la lecture/écriture pour envoyer des données du disque vers la carte réseau nécessitera quatre opérations de copie : lorsqu'une application en a besoin. pour accéder à une certaine donnée À ce moment, le noyau du système d'exploitation vérifiera d'abord si les données ont été stockées dans le tampon de l'espace d'adressage du noyau du système d'exploitation en raison d'un accès précédent au même fichier. Si les données ne sont pas trouvées. dans le tampon du noyau, Linux Le noyau du système d'exploitation lira d'abord ces données à partir du disque et les placera dans le tampon du noyau du système d'exploitation. Si cette opération de lecture de données est effectuée par DMA, alors pendant le processus de lecture de données par DMA, le CPU n'a besoin que d'effectuer la gestion du tampon, et de créer et traiter le DMA. De plus, le CPU n'a pas besoin d'effectuer de nombreuses autres modifications. choses, une fois que DMA a effectué l'opération de lecture des données, il informera le système d'exploitation pour un traitement ultérieur. Le système d'exploitation Linux stockera cette donnée dans l'espace d'adressage de l'application qui a demandé cette donnée en fonction de l'adresse de l'espace d'adressage de l'application spécifiée par l'appel système de lecture. Le système d'exploitation doit restaurer les données. Une copie est effectuée à partir du tampon dans l'espace d'adressage de l'application utilisateur vers le tampon du noyau lié à la pile réseau. Ce processus nécessite également l'utilisation du processeur. Une fois l'opération de copie des données terminée, les données seront regroupées puis envoyées à la carte d'interface réseau. Comme le montre la description ci-dessus, au cours de ce processus de transfert de données traditionnel, les données sont copiées au moins quatre fois. Même si DMA est utilisé pour communiquer avec le matériel, le processeur doit toujours accéder aux données deux fois.
(ps : je me souviens avoir lu une question d'entretien auparavant qui disait que le processus de sortie printf passe par plusieurs tampons, maintenant tout le monde comprend !)
L'utilisation de la technologie zéro copie peut éviter la copie des données dans le tampon de l'espace d'adressage du noyau du système et dans le tampon de l'espace d'adressage de l'application utilisateur. Parfois, l'application n'a pas besoin d'accéder aux données pendant le processus de transmission des données. Les données transmises n'ont pas besoin d'être copiées dans la zone d'application utilisateur, mais peuvent être envoyées directement à la carte réseau via le noyau. et aucune copie n’est requise à l’heure actuelle. Sous Linux, vous pouvez utiliser mmap, sendfile et splice pour obtenir une copie nulle.
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!