暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

【Linux编程】如何保证数据存文件不丢失

嵌入式软件开发交流 2021-09-12
1762


前言


    最近在项目开发中遇到一个问题,就是打开文件,然后调用write()将数据写到文件中,然后对设备进行重启,起来之后发现写入的数据都丢失了。



原因分析


    Linux编程中使用write()函数写数据到文件中时,其实数据不会马上写入磁盘,而是会经过层层缓存。这些缓存的存在是为了加速读写操作,因为直接读写磁盘效率是很低的。但是缓存也会带来一些数据丢失的问题。所以我们要确保及时将数据落盘。



I/O缓存机制


通过下面一张图来看看缓存机制:

上图说明了应用程序到磁盘的数据流,以及经过的缓冲区。从图中可以看出用户空间和内核空间都有缓存。


  • 用户空间缓存

应用本身的缓存是开发者自己控制的,我们就不说了。我们来看一下库维护的缓存,比如C标准库stdio就维护着一个缓冲区,我们使用printf时要在末尾加上'\n' , 或者fflush()方法强制刷新。否则是不会输出的,这就是库维护的缓存。


  • 内核空间缓存

应用程序使用系统调用write()会将数据写入内核缓冲区。系统提供了三个系统调用来执行刷新内核缓冲区:sync,fsync,fdatasync

void sync(void)
void fsync(int filedes)
void fdatasync(int filedes)

在Linux中syncfsync功能差不多,都是保证数据落盘后返回,前者是对所有文件,后者则是对指定的文件。

fdatasync功能也类似,只是fdatasync不一定需要刷新文件的元数据部分到存储设备。元数据指的就是修改日期,文件长度等数据。



解决方案


为了保证数据及时落盘,防止数据丢失,有两种方案:

(1)写完数据后调用sync,fsync,fdatasync之一,根据自己的需要来调用。

(2)使用open()打开文件时,可以设置标志位:O_SYNCO_DSYNC

fd = open( "file" , O_RDWR | O_CREAT | O_SYNC , S_IRUSR | S_IWUSR);

设置O_SYNC相当于每次write()后自动调用fsync()。

设置O_DSYNC相当于每次write()后自动调用fdatasync()。



参考资料:

《UNIX环境高级编程》

https://lwn.net/Articles/457667/





往期精彩回顾




蓝牙mesh基础知识
手把手教你制作根文件系统
OpenWRT之UCI


文章转载自嵌入式软件开发交流,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论