【问题标题】:Why is data not being flushed to file on process exit?为什么在进程退出时数据没有被刷新到文件中?
【发布时间】:2011-09-02 08:59:41
【问题描述】:
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;
}

【问题讨论】:

    标签: c windows file-io posix


    【解决方案1】:

    这与文件系统无关,而是您使用的 C 实现的行为决定了何时刷新打开的流。

    在 POSIX 下,SIGTERM 信号的默认动作动作是:

    进程异常终止。进程以_exit() 的所有后果终止...

    _exit()根据C标准相当于_Exit(),标准没有规定是否刷新流的选择:

    _Exit() 和 _exit() 函数不得调用用 atexit() 注册的函数或任何注册的信号处理程序。是否刷新或关闭打开的流,或者删除临时文件是实现定义的...

    假设您在 Linux 上使用 glibc,来自 documentation(强调我的):

    当进程因任何原因终止时(无论是因为程序终止,还是由于信号),都会发生以下情况:

    • 进程中所有打开的文件描述符都已关闭。请参阅低级 I/O。 请注意,当进程终止时,流不会自动刷新;请参阅 Streams 上的 I/O。

    我不熟悉 Windows 的 WriteFileTerminateProcess,所以我无法评论记录的行为是什么。

    【讨论】:

    • 谢谢,我到家后会用系统调用而不是crt再次测试
    【解决方案2】:

    它与文件系统驱动程序没有任何关系。问题是 CRT 正在缓冲文件流本身。您使用 setvbuf() 设置缓冲区大小,如果您不使用此函数,它将使用默认值。当您使用 WriteFile() 时,应用程序中没有缓冲,输出缓冲在操作系统的文件系统缓存中。免受应用程序突然中止的影响。

    你必须调用 fflush() 来达到同样的效果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-10
      • 2019-06-24
      • 2014-09-18
      • 1970-01-01
      • 2010-12-07
      • 2018-09-11
      • 2011-12-15
      • 1970-01-01
      相关资源
      最近更新 更多