Используя xinetd/inetd, почему серверы должны вызывать fflush()?

Все программы в xinetd (которые я прочитал) вызывают fflush(). Зачем?

Например, Inetd-Wikipedia

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

int main(int argc, char **argv)
{
  const char *fn = argv[1];
  FILE *fp = fopen(fn, "a+");

  if(fp == NULL) 
    exit(EXIT_FAILURE);

  char str[4096];
  //inetd passes its information to us in stdin.
  while(fgets(str, sizeof(str), stdin)) {
    fputs(str, fp);
    fflush(fp);
  }
  fclose(fp);
  return 0;
}

2 ответа

Решение

fopen использует буферизованный ввод. То есть это призвание fputs запишет в буфер в памяти и не будет необходимости записывать данные на диск. призвание fflush принудительно записывает выходной буфер на диск.

В вашем примере кода используется этот шаблон, поэтому файл будет записан, как только некоторые данные будут записаны через сокет, и вы сможете отслеживать файл, чтобы узнать, что было написано.

Я не думаю, что вам когда-либо нужно вызывать fflush как раз перед fclose. Я не вижу причин для вызова fflush после каждого fputs. По сути, fflush нужен только тогда, когда вам нужно синхронизировать некоторые действия, но в большинстве случаев есть лучшие способы сделать это. Вам следует избегать fflush в IMO, если вы не разработчик базы данных или что-то в этом роде.

Если вы удалите fflush, программа будет работать так же хорошо, то есть выгрузит stdin в файл и закроет файл при выходе.

Кроме того, я не думаю, что это имеет какое-либо отношение к inetd или xinetd.

Как написано в другом ответе, мониторинг файла будет показывать данные сразу, только если буферы сброшены, но я думаю, что это плохая практика программирования - сбрасывать после каждого чтения. Если вы хотите всегда получать данные немедленно, лучше использовать:

setvbuf(fp, NULL, _IONBF, 0)

Но даже этого недостаточно, поскольку буферизация stdin источник ваших данных AFAIK не указан. Вам также нужно установить это:

setvbuf(stdin, NULL, _IONBF, 0)

Я считаю, что вы всегда должны отдавать предпочтение функциям POSIX, а не функциям ANSI, если вы хотите точно контролировать поведение чтения / записи и не ориентируетесь на платформы, отличные от POSIX. Семантика POSIX open(), read() а также write() гораздо проще, чем один из fopen(), fread() а также fwrite(), Он просто читает / записывает как можно больше данных за один системный вызов, и нет никакой буферизации, кроме вашего собственного буфера и буфера сокета ядра, который просто дает вам данные всякий раз, когда вы их запрашиваете.

Другие вопросы по тегам