有时将错误的字节写入磁盘。硬件问题?

时间:2016-08-18 08:49:02

标签: c++ hardware ram sha256

我使用C ++ 11(VS2013)编写了基于UDP的传输协议。它的速度非常快 - 99.9%的时间都很棒。

enter image description here

但是我已经观察过几次将错误的字节写入磁盘(三星250 GB SSD 850 EVO) - 或者至少看起来如此。

这基本上是我转移6GB测试文件时会发生的事情:

  1. 该文件被拆分为较小的UDP数据包 - 大小为64K。 (网络层将UDP数据报分解并重组为更大的包)。
  2. 客户端将datapackage(udp)发送到服务器 - 使用AES256(OpenSSL)加密有效负载并包含数据+元数据。 Payload还包含整个有效负载的SHA256哈希值 - 作为UDP校验和的额外完整性检查。
  3. 服务器接收数据包,将“ACK”包发送回客户端,然后计算SHA256哈希。哈希与客户端哈希相同 - 一切都很好
  4. Server然后将包的数据写入磁盘(由于巨大的性能差异,使用fwrite而不是流)。服务器一次只处理一个包 - 每个文件指针都有一个互斥锁,可以保护它不被另一个工作线程关闭,该工作线程关闭已经处于非活动状态10秒的文件放大器。
  5. 客户端收到UDP“ACK”包,并重新发送未被确认的包(意味着他们没有成功)。传入ACK包的速率控制客户端的发送速度(也就是拥塞控制/ throtteling)。服务器上收到的包的顺序无关紧要,因为每个包都包含一个Position值(文件中应该写入数据的位置)。
  6. 在传输完整个文件之后,我在服务器和客户端上对6GB文件执行完整的SHA256哈希,但令我恐惧的是,我在最近几天观察到两次散列相同(进行大约20次测试转移时)。

    在比较Beyond Compare中的文件后,我经常发现服务器端有一位或两位(在6 GB文件中)。

    请参见下面的屏幕截图:enter image description here

    服务器代码 - 在验证DataPackage哈希后调用

    void WriteToFile(long long position, unsigned char * data, int lengthOfData){
    
        boost::lock_guard<std::mutex> guard(filePointerMutex);
    
        //Open if required
        if (filePointer == nullptr){
            _wfopen_s(&filePointer, (U("\\\\?\\") + AbsoluteFilePathAndName).c_str(), L"wb");
        }
    
        //Seek
        fsetpos(filePointer, &position);
    
        //Write - not checking the result of the fwrite operation - should I?
        fwrite(data, sizeof(unsigned char), lengthOfData, filePointer);
    
        //Flush
        fflush(filePointer);
    
        //A separate worker thread is closing all stale filehandles 
        //(and setting filePointer to NULLPTR). This isn't invoked until 10 secs
        //after the file has been transferred anyways - so shouldn't matter
    }
    

    总结一下:

    • char *在服务器上的内存是正确的 - 否则服务器SHA256哈希会失败 - 对吧? (与sha256的哈希冲突极不可能)。
    • 写入磁盘时似乎发生了腐败。因为在发送6GB文件时,这些64k软件包中有大约95,000个写入磁盘 - 而且它只发生一次或两次(当它发生时) - 意味着它是一种罕见的现象

    这怎么可能发生?我的硬件(坏ram /磁盘)是否应该归咎于此?

    我是否真的需要在写完后从磁盘读取,并且例如memcmp是为了100%确保将正确的字节写入磁盘? (哦,小男孩 - 这将是什么样的表演......)

1 个答案:

答案 0 :(得分:4)

在我的本地电脑上 - 原来这是一个RAM问题。通过运行memtest86找到。

尽管如此 - 我修改了在我们的生产服务器上运行的软件的代码 - 使其从磁盘读取以验证事实上是否写入了正确的字节。这些服务器每天向磁盘写入大约10TB - 在运行新代码一周后 - 错误发生一次。该软件通过再次编写和验证来纠正这一点 - 但看到它确实发生了仍然很有趣。

560000000000000位中的1位被写入磁盘错误。惊人的。

我可能稍后会在这台服务器上运行memtest86以查看这是否也是一个RAM问题 - 但我不再非常关注这一点,因为文件完整性或多或少得到了保证,并且服务器没有显示任何迹象否则会出现硬件问题。

所以 - 如果文件完整性对您来说非常重要(就像我们这样) - 那么就不要100%信任您的硬件并验证读/写操作。异常可能是硬件问题的早期迹象。