为什么进程退出时数据没有刷新到文件?

发布于 2024-12-02 12:22:10 字数 1081 浏览 2 评论 0原文

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

结果:没有数据写入 a.txt

我预计这很好。因为系统将关闭文件句柄,然后文件系统驱动程序在其 Close 处理程序中刷新未刷新的数据。但事实并非如此。 我在 EXT4、ubuntu 11.10 上测试了这段代码

问题: 我认为所有文件系统都必须在其关闭处理时刷新未刷新的数据。
posix没有这个规则吗?

PS 此代码在 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;
}
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

I expected this is fine. Because the system will close the file handle and then the filesystem driver flushes the unflushed data in his Close handler. But it wasn't.
I tested this code on EXT4, ubuntu 11.10

Question:
I thought ALL filesystems must flush unflushed data at his close processing.
Posix doesn't have the rule?

P.S This code worked well (flushed well) on 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;
}

Edit:
I tested it again with system call write. And it was flushed well.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

嗳卜坏 2024-12-09 12:22:10

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

在 POSIX 下,SIGTERM 信号的默认操作为:

进程异常终止。进程终止,并产生 _exit() 的所有后果...

根据 C 标准以及是否刷新的选择,_exit() 相当于 _Exit()标准未指定流:

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

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

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

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

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

This isn't anything to do with the filesystem, rather it's the behaviour of the C implementation you are using that determines when open streams are flushed or not.

Under POSIX, the default action action for the SIGTERM signal is:

Abnormal termination of the process. The process is terminated with all the consequences of _exit()...

_exit() is equivalent to _Exit() according to the C standard and the choice of whether to flush streams is not specified by the standard:

The _Exit() and _exit() functions shall not call functions registered with atexit() nor any registered signal handlers. Whether open streams are flushed or closed, or temporary files are removed is implementation-defined...

Assuming you are using glibc on Linux, from the documentation (emphasis mine):

When a process terminates for any reason—either because the program terminates, or as a result of a signal—the following things happen:

  • All open file descriptors in the process are closed. See Low-Level I/O. Note that streams are not flushed automatically when the process terminates; see I/O on Streams.

I'm not familiar with the Windows' WriteFile and TerminateProcess so I can't comment on what the documented behaviour is.

鹤舞 2024-12-09 12:22:10

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

您必须调用 fflush() 才能实现相同的目的。

It doesn't have anything to do with file system drivers. The issue is that the CRT is buffering the file stream itself. You set the buffer size with setvbuf(), it uses a default if you don't use this function. There's no buffering in the application when you use WriteFile(), output is buffered in the operating system's file system cache. Immune from abrupt app aborts.

You'll have to call fflush() to achieve the same.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文