Flush stdout Flux de sortie en C

Jinku Hu 12 octobre 2023
  1. Utilisez la fonction fflush pour purger le flux de sortie stdout en C
  2. Démonstration du comportement de fflush en utilisant la fonction printf en C
Flush stdout Flux de sortie en C

Cet article présente plusieurs méthodes pour purger le flux de sortie stdout en C.

Utilisez la fonction fflush pour purger le flux de sortie stdout en C

La bibliothèque standard C fournit une bibliothèque I/O, stdio, qui représente essentiellement une version tampon des opérations d’E/S effectuées dans l’espace utilisateur, améliorant ainsi les performances pour les cas d’utilisation courants. En général, l’accès aux fichiers et les opérations sur ceux-ci sont fournis par les services du système d’exploitation ; ainsi, l’utilisateur a éventuellement besoin d’un appel système, par exemple pour ouvrir un fichier. Un appel système fréquent rend le programme plus lent car il implique l’accès aux structures de données du noyau du système d’exploitation et le transfert de contrôle dans les deux sens. En conséquence, il y a des tampons maintenus par la bibliothèque C pour gérer les opérations d’entrée/sortie lors de l’utilisation des appels de fonction stdio.

Si l’utilisateur doit forcer l’écriture dans les tampons du noyau, il doit vider le flux fourni par la fonction fflush. fflush prend un seul argument du pointeur FILE vers le flux donné. Notez que fflush force la fonction d’écriture pour les flux de sortie tout en rejetant les données mises en mémoire tampon pour les flux d’entrée (avec les fichiers recherchables). Si l’argument est NULL, il vide tous les flux de sortie ouverts.

Attention cependant, fflush ne garantit pas que les données écrites soient physiquement stockées car cela nécessite de vider les tampons du noyau (ce qui peut être fait en utilisant l’appel fsync vu ici).

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

int main(int argc, char *argv[]) {
  char *username;
  size_t len;
  int lnmax = 256;

  username = malloc(lnmax);
  if (username == NULL) perror("malloc");

  printf("Username: ");
  fflush(stdout);
  if (fgets(username, lnmax, stdin) == NULL) exit(EXIT_FAILURE);

  printf("Your username is set to - %s", username);

  exit(EXIT_SUCCESS);
}

Production :

Username: tmp
Your username is set to - tmp

Démonstration du comportement de fflush en utilisant la fonction printf en C

Notez que certains flux (par exemple stderr) ne sont pas mis en mémoire tampon. En revanche, la fonction printf qui écrit implicitement dans le flux stdout est mise en mémoire tampon, et si nous exécutons la boucle infinie en imprimant un seul caractère à chaque itération sous le capot, elle ne sortira pas le contenu du flux avant que la mémoire tampon interne ne soit pleine. Ainsi, l’exemple de code suivant entraîne l’impression en rafale des caractères de la puce. Remarquez que nous appelons la fonction usleep chaque itération pour ralentir l’exécution de l’oeil humain afin d’être clairement observable.

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

int main(int argc, char *argv[]) {
  while (1) {
    printf(".");
    usleep(1e3);
  }

  exit(EXIT_SUCCESS);
}

Alternativement, si nous remplaçons l’appel printf par fprintf, qui imprime vers le flux stderr, cela donnera le comportement d’impression itératif caractère par caractère à chaque seconde. Encore une fois, le délai d’une seconde à chaque itération est mis pour assurer seulement une bonne démonstration.

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

int main(int argc, char *argv[]) {
  while (1) {
    fprintf(stderr, ".");
    sleep(1);
  }

  exit(EXIT_SUCCESS);
}

Enfin, si nous avons besoin d’imiter le même comportement sur le flux stdout que celui vu dans l’exemple de code précédent, nous pouvons ajouter l’appel fflushaprès la fonction printf. Cela forcera les tampons de la bibliothèque C à être écrits dans les tampons du noyau à chaque itération, ce qui donnera un comportement similaire.

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

int main(int argc, char *argv[]) {
  while (1) {
    printf(".");
    fflush(stdout);
    sleep(1);
  }

  exit(EXIT_SUCCESS);
}
Auteur: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook

Article connexe - C IO