[Langage C] Faites attention à la combinaison de l'API de mise en mémoire tampon et de l'appel système sans mise en mémoire tampon

【Aperçu】

Vérifiez le résultat de sortie de l'appel de l'API qui met en mémoire tampon la chaîne dans le programme qui l'écrit d'abord dans le fichier, puis l'appel système qui ne met pas en mémoire tampon. Depuis les tampons API, la chaîne de caractères sortie par l'appel système est sortie en premier.

【environnement】

[root@vagrant-centos65 buff]# cat /etc/centos-release 
CentOS release 6.5 (Final)

【code】

Il s'agit d'un processus consistant à transmettre un fichier en tant que paramètre et à écrire une chaîne de caractères dans ce fichier.

① Avec mise en mémoire tampon

buffer.c


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
	FILE *f;
	char *apiStr = "Hello, API\n";
	char *systemCallStr = "Hello, system call\n";

	if((f = fopen(argv[1], "w")) == NULL) {
		puts("fopen error");
		exit(1);
	}

	//les fputs sont tamponnés
	fputs(apiStr, f);
	//L'écriture d'appel système n'est pas mise en mémoire tampon, elle est donc sortie immédiatement.
	if (write(fileno(f), systemCallStr, strlen(systemCallStr)) < 0) exit(1);
	fclose(f);
	exit(0);
}
Résultat d'exécution
[root@vagrant-centos65 buff]# gcc -o buffer buffer.c 
[root@vagrant-centos65 buff]# ./buffer buffer.txt
[root@vagrant-centos65 buff]# cat buffer.txt
Hello, system call
Hello, API

② Lorsqu'il n'y a pas de tampon

no_buffer1.c


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
	FILE *f;
	char *apiStr = "Hello, API\n";
	char *systemCallStr = "Hello, system call\n";

	if((f = fopen(argv[1], "w")) == NULL) {
		puts("fopen error");
		exit(1);
	}

	//Ne pas mettre en tampon
	//Alternativement, fflush est OK après les fputs
	setbuf(f, NULL);

	//Sortie immédiate
	fputs(apiStr, f);
	//Sortie immédiate
	if (write(fileno(f), systemCallStr, strlen(systemCallStr)) < 0) exit(1);
	fclose(f);
	exit(0);
}
Résultat d'exécution
[root@vagrant-centos65 buff]# gcc -o no_buffer1 no_buffer1.c 
[root@vagrant-centos65 buff]# ./no_buffer1 no_buffer1.txt
[root@vagrant-centos65 buff]# cat no_buffer1.txt 
Hello, API
Hello, system call

[Résumé]

Le descripteur de fichier et FILE peuvent être déplacés librement d'avant en arrière, mais il semble que vous ne devriez pas facilement mélanger les deux car l'ordre d'entrée / sortie peut être dans le désordre en fonction du tampon.

【prime】

Le printf doit être mis en mémoire tampon, mais l'API est imprimée avant l'appel système. [Ajout] D'après le commentaire de angel_p_57

Les flux de sortie qui référencent les terminaux sont toujours mis en mémoire tampon ligne par ligne par défaut

no_buffer2.c


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
	char *apiStr = "Hello, API\n";
	char *systemCallStr = "Hello, system call\n";

	printf("%s", apiStr);
	if (write(STDOUT_FILENO, systemCallStr, strlen(systemCallStr)) < 0) exit(1);
	exit(0);
}

Résultat d'exécution

[root@vagrant-centos65 buff]# gcc -o no_buffer2 no_buffer2.c 
[root@vagrant-centos65 buff]# ./no_buffer2
Hello, API
Hello, system call

【Livre de référence】

[Programmation Linux normale 2ème édition: La voie royale de la programmation gcc qui peut être apprise du mécanisme de Linux](https://www.amazon.co.jp/%E3%81%B5%E3%81%A4%E3%81%86% E3% 81% AELinux% E3% 83% 97% E3% 83% AD% E3% 82% B0% E3% 83% A9% E3% 83% 9F% E3% 83% B3% E3% 82% B0-% E7 % AC% AC2% E7% 89% 88-Linux% E3% 81% AE% E4% BB% 95% E7% B5% 84% E3% 81% BF% E3% 81% 8B% E3% 82% 89% E5 % AD% A6% E3% 81% B9% E3% 82% 8Bgcc% E3% 83% 97% E3% 83% AD% E3% 82% B0% E3% 83% A9% E3% 83% 9F% E3% 83 % B3% E3% 82% B0% E3% 81% AE% E7% 8E% 8B% E9% 81% 93-% E9% 9D% 92% E6% 9C% A8-% E5% B3% B0% E9% 83 % 8E-ebook / dp / B075ST51Y5)

Recommended Posts

[Langage C] Faites attention à la combinaison de l'API de mise en mémoire tampon et de l'appel système sans mise en mémoire tampon
Comment limiter la publication de l'API dans la bibliothèque partagée en langage C de Linux
L'histoire du portage du code de C vers Go (et vers la spécification du langage)
Soyez prudent lors de la différenciation des vecteurs propres d'une matrice
[Langage C] [Linux] Récupère la valeur de la variable d'environnement
Appelez la fonction C avec dart: ffi et rappelez la fonction Dart
Appelez l'API Hatena Blog depuis Python et enregistrez vos articles de blog individuellement sur votre PC
Traversons le mur du système de coordonnées gauche et du système de coordonnées droitier.
J'ai essayé d'illustrer le temps et le temps du langage C
100 traitement de la langue knock-42: Affichage de la phrase de la personne concernée et de la personne concernée