Li em Programação Avançada em Ambiente Unix isto:
O buffer de linha vem com duas ressalvas. Primeiro, o tamanho do buffer que a biblioteca de E/S padrão usa para coletar cada linha é fixo, então a E/S pode ocorrer se preenchermos esse buffer antes de escrever uma nova linha. Segundo, sempre que a entrada for solicitada por meio da biblioteca de E/S padrão de (a) um fluxo sem buffer ou (b) um fluxo com buffer de linha (que requer que os dados sejam solicitados do kernel), todos os fluxos de saída com buffer de linha são liberados. O motivo do qualificador em (b) é que os dados solicitados podem já estar no buffer, o que não requer que os dados sejam lidos do kernel. Obviamente, qualquer entrada de um fluxo sem buffer, item (a), requer que os dados sejam obtidos do kernel.
https://www.gnu.org/software/libc/manual/html_node/Flushing-Buffers.html afirma:
Liberar a saída em um fluxo em buffer significa transmitir todos os caracteres acumulados para o arquivo. Há muitas circunstâncias em que a saída em buffer em um fluxo é liberada automaticamente:
Quando você tenta fazer uma saída e o buffer de saída está cheio.
Quando o fluxo é fechado. Veja Fechando Fluxos.
Quando o programa termina chamando exit. Veja Término Normal. Quando uma nova linha é escrita, se o fluxo for bufferizado por linha.
Sempre que uma operação de entrada em qualquer fluxo realmente lê dados de seu arquivo.
Então eu escrevi um programa para testar isso:
#include <stdio.h>
#include <unistd.h>
int
main()
{
printf("Hello");
FILE *fp = fopen("hugefile", "r");
if (fp == NULL) {
fprintf(stderr, "Cannot open file\n");
return -1;
}
setvbuf(fp, NULL, _IONBF, 0);
sleep(2);
char buf[10];
while (fread(buf, sizeof(char), 10, fp) == 10) {
}
if (ferror(fp)) {
fprintf(stderr, "Read error\n");
return -1;
}; // I expect "Hello" to appear on a screen but it doesn't
fclose(fp);
sleep(50);
}
Mas fread() não dispara o flashing da saída. Estou esquecendo de algo?
Não sei o que pode ser relevante aqui, mas eu uso:
gcc versão 14.2.1 20240910
glibc 2.40+r16+gaa533d58ff-2
Acredito que esvaziar o buffer não significa que ele será impresso na tela ou em qualquer stdout para onde for redirecionado.
Liberando stdout lendo de stdin:
Você pode obter o comportamento do seguinte buf.c:
Execute-o:
A string "Hello" é impressa no stdout e não termina com uma nova linha) (\n) então ela não é liberada após 2 segundos, mas é liberada quando
fread()
é executada. Se ela fosse removida, ela seria liberada somente após o último sleep.Sempre que uma operação de entrada em qualquer fluxo realmente lê dados de seu arquivo.
Liberando para arquivo por meio da leitura do arquivo:
Para reproduzir sempre que uma operação de entrada em qualquer fluxo realmente lê dados de seu arquivo. que eu acho que era seu objetivo principal:
Execute-o assim: criarei um pequeno ARQUIVO que conterá apenas uma data atual e executarei um binário em segundo plano para que eu possa ver todas as mensagens impressas e examinar o conteúdo do ARQUIVO ao mesmo tempo:
Como você pode ver,
add more characters to FILE
a linha foi adicionada ao ARQUIVO somente depois quefread()
foi executada.