Flush stdout Output Stream in C

Jinku Hu 12 ottobre 2023
  1. Usa la funzione fflush per scaricare lo stream di output stdout in C
  2. Dimostrare il comportamento di fflush usando la funzione printf in C
Flush stdout Output Stream in C

Questo articolo mostrerà diversi metodi su come svuotare il flusso di output stdout in C.

Usa la funzione fflush per scaricare lo stream di output stdout in C

La libreria standard C fornisce una libreria I/O, stdio, che essenzialmente rappresenta una versione bufferizzata delle operazioni di I/O eseguite nello spazio utente, migliorando così le prestazioni per i casi d’uso comuni. In generale, l’accesso ai file e l’esecuzione di operazioni su di essi è fornito dai servizi del sistema operativo; quindi, l’utente alla fine necessita di una chiamata di sistema, ad es. per aprire un file. Una frequente invocazione di chiamate di sistema rende il programma più lento poiché implica l’accesso alle strutture dati del kernel del sistema operativo e il trasferimento del controllo avanti e indietro. Di conseguenza, ci sono buffer mantenuti dalla libreria C per gestire le operazioni di input/output quando si usano le chiamate alla funzione stdio.

Se l’utente deve forzare la scrittura nei buffer del kernel, deve svuotare il flusso fornito dalla funzione fflush. fflush accetta un singolo argomento del puntatore FILE al flusso specificato. Si noti che fflush forza la funzione di scrittura per i flussi di output mentre elimina i dati memorizzati nel buffer per i flussi di input (con file ricercabili). Se l’argomento è NULL, scarica tutti i flussi di output aperti.

Attenzione però, fflush non garantisce che i dati scritti siano fisicamente archiviati in quanto ciò richiede lo svuotamento dei buffer del kernel (cosa che può essere eseguita usando la chiamata fsync vista qui).

#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);
}

Produzione:

Username: tmp
Your username is set to - tmp

Dimostrare il comportamento di fflush usando la funzione printf in C

Nota che alcuni flussi (ad esempio stderr) non sono bufferizzati. Al contrario, la funzione printf che scrive implicitamente nel flusso stdout è bufferizzata, e se eseguiamo il bucle infinito stampando un singolo carattere ogni iterazione sotto il cofano, non invierà il contenuto al flusso finché il buffer interno non sarà pieno. Pertanto, il seguente esempio di codice produce la stampa a raffica dei caratteri del punto lista. Si noti che chiamiamo la funzione usleep ogni iterazione per rallentare l’esecuzione dell’occhio umano in modo che sia chiaramente osservabile.

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

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

  exit(EXIT_SUCCESS);
}

In alternativa, se sostituiamo la chiamata printf con fprintf, che stampa nel flusso stderr, produrrà il comportamento di stampa iterativo char per char ogni secondo. Anche in questo caso, il ritardo di 1 secondo a ogni iterazione viene utilizzato solo per garantire una buona dimostrazione.

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

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

  exit(EXIT_SUCCESS);
}

Infine, se avessimo bisogno di imitare lo stesso comportamento sul flusso stdout come visto nel codice di esempio precedente, possiamo aggiungere la chiamata fflush dopo la funzione printf. Ciò costringerà i buffer della libreria C a essere scritti nei buffer del kernel ad ogni iterazione, risultando in un comportamento simile.

#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);
}
Autore: 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

Articolo correlato - C IO