我正在测试固态写入失败时间(c 代码),并且设备没有失败

  • 本文关键字:失败 代码 测试 时间 c linux io
  • 更新时间 :
  • 英文 :


原来我误解了损耗均衡,我最初认为将驱动器访问为RAW会丢失此功能,但由于这是控制器上的一个功能,这解释了为什么我对正在测试的"逻辑扇区"进行了数百万次写入

我正在编写一个应用程序,其中我将使用一个像循环缓冲区一样的RAW磁盘分区,即没有文件系统。

我需要一个地方来跟踪我的读/写缓冲区头,它在引导过程中是持久的,我想我可以创建另一个分区来存储这两个指针。

但我担心在扇区死亡之前,我可以向设备固态驱动器中的扇区写入多少次,所以我写了下面的代码来敲击单个扇区,看看它失败的速度有多快。

  1. 创建随机块(512字节)
  2. 使用pwrite写入扇区0
  3. 使用spread从扇区0读取块
  4. 比较每个字节
  5. 发现差异时退出

但它现在已经运行了数百万次扇区写入!!

我本以为它会失败10000-100000次这样的标准?

我使用sprad/pwrite,如下所示,每个循环都有一个随机缓冲区,然后对两个缓冲区进行比较。

void WriteBlock(const char* device, unsigned char* dataBlock, size_t sector, int size)
{
int fd = open(device, O_WRONLY);
if(fd <= 0)
{
std::cout << "error opening " << device << " '" << strerror(errno) << "'rn";
exit(EXIT_FAILURE);
}
ssize_t r = pwrite(fd, dataBlock, size, sector*SECTOR_SIZE);
if (r<=0 || r<size)
{
std::cout << "failure writing '" << strerror(errno) << "'rn";
exit(EXIT_FAILURE);
}
close(fd);
}
void ReadBlock(const char* device, unsigned char* dataBlock, size_t sector, int size)
{
int fd = open(device, O_RDONLY);
if(fd <= 0)
{
std::cout << "error opening " << device << "rn";
exit(EXIT_FAILURE);
}
ssize_t r = pread(fd, dataBlock, size, sector*SECTOR_SIZE);
if (r<=0 || r<size)
{
std::cout << "failure writing '" << strerror(errno) << "'rn";
exit(EXIT_FAILURE);
}
close(fd);
}

代码只是在每次写入缓冲区等于读取缓冲区的情况下继续运行。

仅供参考,我不是在比较写缓冲区本身!如果我将一个值硬编码到读取缓冲区中,它会捕获这个值并将其解释为失败。

我本以为它会在标准的地方失败10000-100000次?

大多数固态驱动器都具有磨损均衡功能。这意味着,当你向逻辑块0写入时,设备会说"嘿,逻辑块0中的旧数据正在被覆盖,所以我可以假装一个完全不同的物理块现在是逻辑块0"。通过不断地写入同一个逻辑块,您可以写入许多完全不同的物理块。

要击败损耗均衡(并实际写入同一物理块),您必须说服设备所有其他块都在使用中。这是不可能的,因为有多余的容量。例如,对于1TiB设备,您可以用数据填充所有1TiB的逻辑块(无需进行任何"修剪"等),但可能会有额外的512GiB空闲空间,并且您对同一逻辑块的写入将分布在512GiB的空闲空间中;当你真正看到错误时,这可能意味着512 GiB空闲空间中的每个块都发生了故障(而不仅仅是一个块)。

如果你知道实际有多少空闲空间,那么你可能能够基于此进行计算——例如,如果有1000个空闲块,并且你在看到错误之前写了10亿次,那么你可以说"10亿次写/1000个块=每个物理块写100万次"。

现在,想象一下你是一个制造商,你有一个1000吉布的驱动器。您决定将其作为消费者驱动器出售(假设驱动器大部分是空的,并且损耗均衡能够很好地工作),并且您可以说它是一个900 GiB的驱动器(具有100 GiB的备用块),在10000次写入后将失败。然后,您决定还销售与企业级驱动器完全相同的驱动器(假设驱动器可能已满,损耗均衡不会那么有效),并且您可以说它是一个900 GiB的驱动器(有100 GiB的备用块),在2000次写入后会失败。然后,您决定可以增加备用空间,还可以销售与500 GiB企业级驱动器(具有500 GiB的备用块)"基本相同"的驱动器,该驱动器在20000次写入后将失败。

下一步;假设您测试1000个相同的驱动器(使用您正在编写的软件),并测量"在用于测试的特定条件下(例如,其余逻辑块均为空闲/空),平均20000次故障前写入"。这些信息大多是无用的——如果有人在不同的条件下使用同一个驱动器(例如,空闲/空闲的逻辑块较少),那么它会比你说的更快(或更晚)失败。

对于(可能更好的)替代方案;您可以使用从"S.M.A.R.T."获得的信息(请参阅https://en.wikipedia.org/wiki/S.M.A.R.T.)。不幸的是,您可以获得的一些最有用的信息是特定于制造商的(例如,Used Reserved Block Count Total、Unused Reserved BlockCount Total),而有些设备(USB闪存)根本不支持它。

最新更新