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

时间:2011-09-02 08:59:41

标签: c windows file-io posix

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 个答案:

答案 0 :(得分:7)

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

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

  

过程异常终止。该过程终止于_exit()...

的所有后果
根据C标准,

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

  

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

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

  

当一个进程因任何原因终止时 - 或者因为程序终止,或者由于信号而导致 - 以下情况发生:

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

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

答案 1 :(得分:5)

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

你必须调用fflush()来实现同样的目标。