4

好的,首先有一点背景可以帮助我弄清楚我的问题:

我正在开发一种设备,该设备从传感器收集某些数据并使用 GSM 调制解调器将它们发布到服务器。由于 GSM 连接不是 100% 可靠的,它会包含一个日志机制,可以将未发送的数据写入 SD 卡。

我们正在使用Chan 的 FatFs模块为我们提供文件系统,因为我们希望日志在 PC 上可读。

现在我一直在测试 FAT 系统的边界条件,即试图完全填满卡。

在第一次运行中,我打开了文件并将代码设置为继续写入字符串,直到驱动器已满。该程序将在每次写入后同步。

我让代码在一夜之间运行。

第二天,我检查了 SD 卡。我发现该文件只有 150 MB 大小。大约有 120 万行写入其中。该卡仍然可以读取,但不能写入或格式化。

下次我尝试了相同类型的测试,但这次我使用了f_lseek()函数将文件预分配到 1GB。然后它将写入该文件,直到达到该限制。这次数据将在 50 次写入后同步。然后它将关闭该文件并打开另一个文件以执行相同的操作。

正如您可以猜到的那样,另一张勇敢的小卡片在那天丢失了它。

所以这些是我想要帮助的:

  1. 写入大量数据时如何防止卡损坏?
  2. 长时间打开文件是否有任何负面影响?

由于完整的代码可能太长,这里是写作的主要部分

for(file_count=3;file_count>=0;--file_count){

    ax_log_msg(E_LOG_INFO,"===================================");

    ax_log_msg(E_LOG_INFO,file_names[file_count]);


    f_open(&file_ptr,file_names[file_count],FA_WRITE|FA_OPEN_ALWAYS);

    if(result!=FR_OK){

        ax_log_msg(E_LOG_INFO,"\n\rf_open Failed\n\rResult code");
        ax_log_msg(E_LOG_INFO,FRESULT_S[result]);

        continue;

    }

    ax_log_msg(E_LOG_INFO,"\n\rf_open Sucessfull");

    result=f_lseek(&file_ptr,FILE_SIZE_LIMIT_1GB);

    if(result!=FR_OK){

        ax_log_msg(E_LOG_INFO,"\n\rf_lseek Failed for preallocation\n\rResult code");
        ax_log_msg(E_LOG_INFO,FRESULT_S[result]);

        f_close(&file_ptr);

        continue;

    }

    ax_log_msg(E_LOG_INFO,"\n\rf_lseek Sucessfull for preallocation");

    f_lseek(&file_ptr,0);

    bytes_to_write=sizeof(messages[file_count]);

    write_count=0;

    while( (f_tell(&file_ptr) < FILE_SIZE_LIMIT_1GB )){

        result=f_write(&file_ptr,messages[file_count],bytes_to_write,&bytes_written);

        if(result==FR_OK){
            ++write_count;

            if(write_count%50==0){

                f_sync(&file_ptr);
            }

        }else{

            ax_log_msg(E_LOG_INFO,"\n\rWrite failed\n\rFRESULT=");
            ax_log_msg(E_LOG_INFO,FRESULT_S[result]);

            break;

        }

    }

    f_close(&file_ptr);


}

笔记 :

  1. ax_log_msg() 是要在控制台上打印的设备固件的一部分。
  2. FRESULT_S[result] 用于将枚举结果代码转换为字符串。

如果有任何数据丢失,请务必提及。

谢谢你

4

2 回答 2

3

您可能需要缓冲整个数据块,可能是 4 KB,以避免每次刷新都刷新整个数据块。但是,文件系统或驱动程序应该为您执行此操作,只要您不fflush显式调用,这是真正的教训。

为什么需要如此频繁地同步它?也许计时器会比每个记录数的间隔更好?

于 2014-07-24T10:49:22.720 回答
-2

由于每个扇区的写入周期限制为 100,000 次,因此延长闪存寿命是一项非常具有挑战性的任务。在我对其进行编写测试后,我的一张卡片在一个晚上就死了。然后我计算了时间段,这确实很容易在一个晚上执行 100,000 次写入(在同一扇区中)(不考虑通过经验得出的计算)。

那时我被告知在某些文件系统中有一个智能监视器,它们会计算并保存每个扇区的写入数,以便每个扇区的写入数是相同的,我猜。我既没有服用也没有测试过。

我现在为 Raspberrypi 找到了一些非常受欢迎/投票率很高的答案/建议,我现在在这里引用它:

这些方法应该通过以各种方式最小化读/写次数来延长 SD 卡的使用寿命:

禁用交换

交换是将 SD 卡的一部分用作易失性存储器的过程。这将增加可用 RAM 的数量,但会导致大量的读/写。不太可能显着提高性能。

swapoff使用以下命令禁用交换:

sudo swapoff --all

您还必须防止它在重新启动后恢复:

  • 对于使用dphys-swapfile管理交换文件(而不是“普通”交换分区)的 Raspbian,您可以简单sudo apt-get remove dphys-swapfile地将其永久删除。最好删除,因为将 设置CONF_SWAPSIZE为 0,如本答案中所述,似乎不起作用,并且在重新启动后仍会创建 100MB 交换文件。
  • 对于使用交换分区而不是交换文件的其他发行版,请从/etc/fstab

在文件系统上禁用日志

使用诸如ext3或不使用日志之类的日志文件系统ext4是减少读/写的一种选择。使用禁用日志的文件系统的明显缺点是由于不正常的卸载(即电源故障后、内核锁定等)导致的数据丢失。

ext3您可以通过将其安装为来禁用日记功能ext2

ext4您可以像这样在未安装的驱动器上禁用日记功能:

tune4fs -O ^has_journal /dev/sdaX
e4fsck –f /dev/sdaX
sudo reboot

noatime 山旗

通过将 noatime 挂载标志添加到/etc/fstab.

对文件系统的读取访问将不再导致与文件关联的 atime 信息的更新。noatime 设置的重要性在于,它消除了系统对正在读取的文件进行写入文件系统的需要。由于如上一节所述,写入可能会有些昂贵,因此可以带来可衡量的性能提升。请注意,在启用此选项的情况下,只要写入文件,文件的写入时间信息就会继续更新。

RAM 中的目录

高度使用的目录,例如/var/tmp/并且可能/var/log可以/etc/fstab像这样重新定位到 RAM:

tmpfs /var/tmp tmpfs nodev,nosuid,size=50M 0 0

这将允许/var/tmp使用 50MB 的 RAM 作为磁盘空间。这样做的唯一问题是安装在 RAM 中的任何驱动器在重新启动后都不会持续存在。因此,如果您安装/var/log并且系统遇到导致其重新启动的错误,您将无法找出原因。

外部硬盘中的目录

您还可以将某些目录挂载到永久性 USB 硬盘上。更多细节可以在这个问题中找到。

Raspberry Pi 还可以从外部驱动器启动它的根分区。这可以通过 USB 或以太网进行,这意味着 SD 卡将仅用于在启动期间委托给不同的设备。这需要一些内核破解才能完成,因为我认为默认内核不支持 USB 存储。您可以在此问题此外部博客文章中找到更多信息。


这是另一个回答者的一个更有趣的考虑:

关于闪存文件系统的优秀文章。

谈论闪存文件系统时的重要问题如下:什么是磨损均衡?维基百科文章。基本上,在闪存盘上,您可以写入有限的次数,直到块变坏。之后,文件系统(如果硬件上没有内置的磨损均衡管理,如 SSD 通常有)必须将该块标记为无效,并避免再使用它。

典型的文件系统(例如 reiserfs、ntfs、ext3 等)是为没有这些限制的硬盘设计的。

JFFS2

包括压缩和优雅的磨损均衡保护。

YAFFS2

  • 与众不同的一件事:成功卸载后挂载时间短。
  • 实现一次写入属性:数据写入一个块后,无需重写。这对于防止磨损均衡很重要。

日志文件系统

  • 不是很成熟,但已经包含在 Linux 内核树中。
  • 支持比 JFFS2/YAFFS2 更大的文件系统,没有问题。

UBIFS

  • 比 LogFS 更成熟
  • 写缓存支持
  • 关于可扩展性:文章。在大磁盘上,性能优于 JFFS2

分机4

如果没有驱动程序或卡(例如 SSD 驱动器确实具有内部磨损均衡,至少通常)处理磨损均衡,那么 ext4 不是最好的主意,因为它不适合原始闪存使用。

什么是最好的?

当然,这取决于使用和支持。根据我从互联网上阅读的内容,我会推荐 UBIFS。对大型文件系统的良好支持,成熟的开发阶段,足够的性能并且没有很大的缺点。

感谢回答者:

如何延长 SD 卡的使用寿命?

为 GNU/Linux 选择 SD 卡上的文件系统

于 2014-07-27T10:31:22.110 回答