Почему данные не сбрасываются в файл при выходе из процесса? - PullRequest
6 голосов
/ 02 сентября 2011
int main(int argc, char *argv[])
{
    FILE *fp = fopen("a.txt", "wt");

    fprintf(fp, "AAAA");

    // No flush. and No close
    raise(SIGTERM);

    exit(EXIT_SUCCESS);
}

result: No data has written to a.txt

Я ожидал, что это нормально. Поскольку система закроет дескриптор файла, а затем драйвер файловой системы сбрасывает непроверенные данные в своем обработчике закрытия. Но это не так. Я тестировал этот код на EXT4, Ubuntu 11.10

Вопрос: Я думал, что ВСЕ файловые системы должны сбрасывать непроверенные данные при его закрытой обработке.
У Posix нет правила?

P.S. Этот код хорошо работал (хорошо работал) на NTFS, Win7

int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE h = CreateFile(L"D:\\a.txt", GENERIC_READ|GENERIC_WRITE,
        0, 0, OPEN_ALWAYS, 0, 0);
    BYTE a[3];
    memset(a, 'A', 3);
    DWORD dw;
    WriteFile(h, (PVOID)a, 3, &dw, 0);

    TerminateProcess(GetCurrentProcess(), 1);
    return 0;
}

Изменить:
Я проверил это снова с системным вызовом write. И это было хорошо покраснело.

int main(int argc, char** argv)
{
    int fd = open("a.txt", O_CREAT|O_TRUNC|O_WRONLY);
    char buf[3];
    memset(buf, 'A', 3);
    size_t result = write(fd, buf, 3);

    raise(SIGTERM);
    exit(EXIT_SUCCESS);   
    return 0;
}

Ответы [ 2 ]

7 голосов
/ 02 сентября 2011

Это не имеет ничего общего с файловой системой, скорее поведение, которое вы используете для реализации C, определяет, очищаются ли открытые потоки или нет.

В POSIX действие действия по умолчанию дляSIGTERM сигнал:

Аварийное завершение процесса.Процесс завершается со всеми последствиями _exit () ...

_exit() эквивалентно _Exit() в соответствии со стандартом C, и выбор, очищать ли потоки, не определяетсястандарт:

Функции _Exit () и _exit () не должны вызывать функции, зарегистрированные с помощью atexit (), или любые зарегистрированные обработчики сигналов.Сбрасываются ли открытые потоки или закрываются, или удаляются временные файлы, определяется реализацией ...

Предполагается, что вы используете glibc в Linux из документации (выделено мной):

Когда процесс завершается по любой причине - либо потому, что программа завершается, либо в результате сигнала - происходят следующие вещи:

  • Все дескрипторы открытых файловв процессе закрыты.Смотрите Низкоуровневый ввод / вывод. Обратите внимание, что потоки не очищаются автоматически после завершения процесса ;см. ввод / вывод в потоках.

Я не знаком с Windows * WriteFile и TerminateProcess, поэтому не могу комментировать, что такое документированное поведение.

5 голосов
/ 02 сентября 2011

Это не имеет ничего общего с драйверами файловой системы. Проблема в том, что CRT буферизует сам файловый поток. Вы устанавливаете размер буфера с помощью setvbuf (), он использует значение по умолчанию, если вы не используете эту функцию. При использовании WriteFile () в приложении нет буферизации, выходные данные буферизируются в кеше файловой системы операционной системы. Невосприимчивость к резким сбоям приложения.

Вам потребуется вызвать fflush (), чтобы добиться того же.

...