问题背景:

客户反馈,设备断电以后,重新启动,原有配置丢失变砖

问题分析:

变砖的直接原因是配置丢失,配置丢失的原因是启动后flash上的数据已经被破坏,读取失败;

进一步分析,主要是flash数据未完全写入导致;

为何先前发布的yaffs2文件系统没有问题?目前的ubi文件系统会存在问题?

分析app层对于flash数据的操作流程,主要是以下步骤:

fopen -> fwrite -> fsync -> fclose

然而,实际的应该是如下步骤:

fopen -> fwrite -> fflush -> fsync -> fclose

fopen是带有缓冲的io操作,fflush的调用,可以使c库缓冲中的数据刷新到os层,而fsync只是将os层数据同步到介质中;

因此再缺失fflush的情况下,只是fsync再fclose,立即断电,会导致刷新数据不全。

至于yaffs2文件系统为什么没有问题,内核方面给出解释是:yaffs2文件系统是不带缓冲的,fclose可以触发将缓冲中残留数据刷新到介质;

结合man手册的走读,有如下结论:

1. 如果需要再描述符关闭前,将数据同步刷新到介质,需要调用fync接口,尤其针对一些关键的数据(丢失会引起严重问题的数据);

2. fopen方式打开的,如果需要调用fsync,正确的调用顺序为:fopen -> fwrite -> fflush -> fsync -> fclose

3. open方式打开的,如果需要调用到fsync,正确的调用顺序为:open -> write -> fsync -> close

问题修复:

1. 写配置文件的接口中,fsync前用fflush,出临时版本

2. 检索工程中,所有fopen打开文件,调用fsync前,增加fflush的调用

3. 鉴于业务的特殊情况,检索工程中,所有fclose或者close前,没有调用fsync的接口,需要补充fsync的调用

以下是man手册上摘录相关接口的一些注意点:

close()调用的理解(来自https://linux.die.net/man/2/close):

Not checking the return value of close() is a common but nevertheless serious programming error. It is quite possible that errors on a previous write(2) operation are first reported at the final close(). Not checking the return value when closing the file may lead to silent loss of data. This can especially be observed with NFS and with disk quota.

A successful close does not guarantee that the data has been successfully saved to disk, as the kernel defers writes. It is not common for a file system to flush the buffers when the stream is closed. If you need to be sure that the data is physically stored use fsync(2). (It will depend on the disk hardware at this point.)

It is probably unwise to close file descriptors while they may be in use by system calls in other threads in the same process. Since a file descriptor may be reused, there are some obscure race conditions that may cause unintended side effects

有可能有些write的错误,是报在close调用的时候,close的返回值不判断可能会不知情的情况下,已经丢失了数据。尤其是在带有磁盘配额的NFS文件系统上;

close函数不保证数据写到介质上的,要保证刷新到介质,需要调用fsync进行刷新,再去看fsync的接口手册,对于自身带有缓冲的介质,fsync也是无法保证真正写入的。

fclose()调用的理解(来自man手册):
Note that fclose() only flushes the user space buffers provided by the C library. To ensure that the data is physically stored on disk the kernel buffers must be flushed too,
for example, with sync(2) or fsync(2).

fclose只刷新C库提供的用户空间buf,数据到物理介质的写入还需要sync或者fsync来保证;

最新文章

  1. AngularJS过滤器filter-保留小数,小数点-$filter
  2. Windows下安装Oracle拖慢开机速度的解决方法
  3. 树链剖分I 原理
  4. 菜鸟-教你把Acegi应用到实际项目(9)-实现FilterInvocationDefinition
  5. Visual Assist X 10.6.1837完美破解版(带VS2010破解)
  6. Myeclipse 2013 professional 破解,下载
  7. HTML 内嵌JS脚本、相关参考手册
  8. ANDROID SHAPE画圆形背景_ANDROID实现角标布局
  9. ZOJ3640-Help Me Escape
  10. stm32中断优先级
  11. How to image a CD/DVD ROM and generate hash value
  12. Java线程池详解
  13. mysql主从同步+mycat读写分离+.NET程序连接mycat代理
  14. 优化TestNG测试报告
  15. sqlserver 电脑重启以后服务突然无法启动 报错
  16. mvc 在弹出框中实现文件下载
  17. Eclipse修改Maven仓库配置
  18. Mac删除默认美国输入法
  19. 廖雪峰Java6 IO编程-3Reader和Writer-2Writer
  20. dubbo接口FindMemberInfoTest思路整合

热门文章

  1. python doctest测试
  2. mysql如何查看错误代码具体释义?(基于perror)
  3. 第13章 GPIO-位带操作—零死角玩转STM32-F429系列
  4. Status bar - iOS之状态栏
  5. 关于var和ES6中的let,const的理解
  6. Go HTTP模块处理流程简析
  7. docker官方仓库下载镜像
  8. 【Effective C++ 读书笔记】导读 Introduction
  9. HDU 6274 二分+预处理(CCPC K题
  10. @ApiModelProperty用法