当前位置: 代码迷 >> 综合 >> sync、fsync、fdatasync
  详细解决方案

sync、fsync、fdatasync

热度:82   发布时间:2023-11-17 04:51:18.0

问题描述

    某天、测试程序的小哥告诉我程序为什么点击保存配置之后,断电重启设备,保存的配置没有了。

    得到反馈我的第一想法就是是不是上位机程序的配置指令没有发送过去,然后自己测试发现指令发了过去、并且用vi命令打开发现保存的参数也正确。然后断电重启。再去看文件中的配置参数没有了。

    于是多尝试了几次发现有的时候,配置文件能够保存,有的时候却变成了空文件。

推测

    考虑到文件系统是Flash的关系。Linux内核是在内存中运行的,在把内核加载到内存的同时也会映射虚拟文件系统(NFS)。

    那就有可能是配置参数只保存在了内存中、并没有调用Flash接口,把它写入Flash中。要想写入Flash中就要调用写Flash的函数。

解决办法

    在配置文件的读写(read write)后加入fsync函数手动调用,把参数保存入Flash。

Flash函数详解

    sync函数原型:  void sync(void);

sync函数会强制将内核中的所有修改过的缓冲区刷新,并立刻返回,不会等到实际的I/O操作完成后再返回。所以sync函数并不能保证数据一定写入到了磁盘中。在Linux中有一个名为update的守护进程会定期(几秒或几十秒)调用sync函数,来将刷新内核缓冲区。

    fsync函数原型: int fsync(int fd);

fsync函数会强制将内核中与fd文件相关的缓冲区刷新,并等待到实际I/O操作结束后再返回,如果实际I/O操作未结束,那么函数将一直处于阻塞状态。所以fsync函数可以保证数据一定被写入到磁盘中。

    fdatasync函数原型:  int fdatasync(int fd);

fdatasync函数和fsync函数类似,唯一的区别就是fdatasync函数只会将文件的数据部分更新到磁盘中,而fsync函数不仅会将文件的数据部分还会将文件的属性更新到磁盘中。

思考

    在使用write函数向文件中写入数据的时候,并不是在调用了函数后数据就被写进了磁盘,操作系统在内核中设置了一块专门的缓冲区,数据会先被写入到内核的缓冲区中,等到缓冲区满了或者系统需要重新利用缓冲区的时候才会将此缓冲区排入到写队列中去,待到达队首的时候,将数据真正写入到磁盘当中。这就是延迟写,延迟写会造成缓冲区中的数据和磁盘中的数据之间的不同步。

    用户态 -----write----------> 内核态 --------fsync---------> NandFlash


  相关解决方案