繁体   English   中英

在 C++ 中写入不可靠的磁盘时引发 I/O 错误

[英]Raise I/O error while writing to an unreliable disk in C++

想象一下,您在 C++ 中有以下内容:

ofstream myfile;
myfile.open (argv[1]);

if (myfile.is_open()){
 for(int n=0;n<=10;n++){
     myfile << "index="<<n<<endl;
     sleep(1);
 }
}else{
cerr << "Unable to open file";
}

myfile.close();

在写入时,您正在写入的磁盘或介质变得不可用,但会在close()时重新打开,因此您之间会丢失数据。 或者想象您写入 USB 闪存驱动器,并且在写入过程中设备被取出并重新插入。

你怎么能检测到呢? 我尝试检查将写入放入try {} catchflags()rdstate() ,你的名字,但到目前为止似乎没有一个工作。

我不认为这是您可以在 stdio 级别检测到的东西。 通常,当硬盘驱动器暂时停止响应时,操作系统会自动重试命令,直到它们成功或达到超时,此时您的系统调用可能会收到错误。 (OTOH可能不会,因为您的调用可能已经返回,在数据写入内存文件系统缓存之后但在任何命令发送到实际磁盘之前)

如果你真的想检测易碎的硬盘驱动器,你可能需要编写低得多的代码,例如编写你自己的硬件驱动程序。

恕我直言,您可以尝试:

  1. 使用ios:异常
  2. 使用低级操作系统交互
  3. 验证 IO 是否成功(如果 1 和 2 不起作用)

我不确定这是否会涵盖您的场景(在写入过程中移除 USB 驱动器),但您可以尝试在流上启用例外:

myfile.exceptions(ios::failbit | ios::badbit);

以我的经验,iostreams 在使检测错误和错误类型变得困难方面做得“很棒”。

for(int n=0;n<=10;n++){
    if (!(myfile << "index="<<n<<endl))
        throw std::runtime_error("WRITE FAILED")
    sleep(1);
}

如果std::ostream由于任何原因失败,它会设置它的状态位,然后检查std::stream是否处于布尔上下文中。 这与检查std::istream是否正确将数据读入变量的方法相同。

但是,这与您说您尝试过的rdstate()相同。 如果是这种情况,则写入已到达缓冲区。 endl刷新程序缓冲区,表明它在操作系统的缓冲区中。 从那里,您必须使用特定于操作系统的调用来强制它刷新缓冲区。

[编辑] 根据http://msdn.microsoft.com/en-us/library/17618685(v=VS.100).aspx ,如果您有文件描述符,您可以使用_commit强制刷新。 我无法为std::ostream找到这样的保证。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM