Flush Stdout Output Stream em C

Jinku Hu 12 outubro 2023
  1. Use a função fflush para liberar fluxo de saída stdout em C
  2. Demonstre o comportamento fflush usando a função printf em C
Flush Stdout Output Stream em C

Este artigo demonstrará vários métodos sobre como liberar o fluxo de saída stdout em C.

Use a função fflush para liberar fluxo de saída stdout em C

A biblioteca padrão C fornece uma biblioteca I/O, stdio, que essencialmente representa uma versão em buffer de operações I/O feitas no espaço do usuário, melhorando assim o desempenho para casos de uso comuns. Geralmente, o acesso a arquivos e a condução de operações sobre eles é fornecido pelos serviços do sistema operacional; assim, o usuário eventualmente precisa de uma chamada de sistema, por exemplo, para abrir um arquivo. Uma invocação frequente de chamadas de sistema torna o programa mais lento, pois acarreta o acesso às estruturas de dados do kernel do sistema operacional e a transferência de controle para frente e para trás. Como resultado, existem buffers mantidos pela biblioteca C para lidar com as operações de entrada/saída ao usar as chamadas de função stdio.

Se o usuário precisa forçar a gravação nos buffers do kernel, ele precisa liberar o fluxo fornecido pela função fflush. fflush recebe um único argumento do ponteiro FILE para o fluxo fornecido. Observe que fflush força a função de gravação para fluxos de saída enquanto descarta quaisquer dados em buffer para fluxos de entrada (com arquivos pesquisáveis). Se o argumento for NULL, ele esvazia todos os fluxos de saída abertos.

Porém, lembre-se de que fflush não garante que os dados gravados sejam armazenados fisicamente, pois isso requer que os buffers do kernel sejam liberados (o que pode ser feito usando a chamada fsync vista aqui).

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

Resultado:

Username: tmp
Your username is set to - tmp

Demonstre o comportamento fflush usando a função printf em C

Observe que alguns fluxos (por exemplo, stderr) não são armazenados em buffer. Em contraste, a função printf que escreve implicitamente para o fluxo stdout é armazenada em buffer, e se executarmos o loop infinito imprimindo um único caractere a cada iteração embaixo do capô, ele não enviará o conteúdo para o fluxo até que o buffer interno seja completo. Portanto, o exemplo de código a seguir resulta na impressão intermitente dos caracteres de marcador. Observe que chamamos a função usleep a cada iteração para desacelerar a execução do olho humano para que seja claramente observável.

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

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

  exit(EXIT_SUCCESS);
}

Alternativamente, se substituirmos a chamada printf por fprintf, que imprime no fluxo stderr, ele produzirá o comportamento iterativo de impressão char por char a cada segundo. Novamente, o atraso de 1 segundo a cada iteração é colocado apenas para garantir uma boa demonstração.

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

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

  exit(EXIT_SUCCESS);
}

Finalmente, se precisarmos imitar o mesmo comportamento no fluxo stdout como visto no código do exemplo anterior, podemos adicionar a chamada fflush após a função printf. Isso forçará os buffers da biblioteca C a serem gravados nos buffers do kernel a cada iteração, resultando em um comportamento semelhante.

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

Artigo relacionado - C IO