Linux 读写文件时,异常断电或程序异常中止导致文件出错、损坏

 一、问题描述

Linux系统,嵌入式程序开发。

程序运行过程中,有读写配置文件保存当前位置信息的操作。在程序运行过程中突然断电,或者异常终止程序,就会出现配置文件内容出错(内容清空)或者文件直接损坏而无法打开的情况。文件损坏时,可能报出segmentation fault的错误,以致程序没法正常运行。

 

二、问题分析

断电瞬间正在往磁盘写文件。

内容丢失:Linux为延迟写(delayedwrite),突然断电时,文件缓冲区中数据还未写入文件

文件损坏:文件系统内部结构不一致,导致文件系统破坏

 

三、解决方法

方案一:我们自己在程序中先退出去,而不能让系统强制杀掉我们的程序。

C程序中加入SIGINT响应函数,保证程序正常退出。

(1)Linux中的kill命令,会导致写文件失败。

大部分的程序都需要一个handler来应对SIGINT信号。只有正常退出,才能做到flush,保证写文件成功。

“Linux中的kill命令用来终止指定的进程(terminate a process)的运行,是Linux下进程管理的常用命令。通常,终止一个前台进程可以使用Ctrl+C键,但是,对于一个后台进程就须用kill命令来终止,我们就需要先使用ps/pidof/pstree/top等工具获取进程PID,然后使用kill命令来杀掉该进程。kill命令是通过向进程发送指定的信号来结束相应进程的。在默认情况下,采用编号为15的TERM信号。TERM信号将终止所有不能捕获该信号的进程。对于那些可以捕获该TERM信号的进程就要用编号为9的kill信号,强行“杀掉”该进程。” 

我们平常所按ctrl+C不等价于终止进程ctrl+C一般情况下等价于kill -s SIGINT。即进程接受的是SIGINT信号。而接受了SIGINT信号并不是简单的杀死进程。

2)文件损坏修复

Linux下普遍采用的是ext3文件系统,ext3是一个具有日志记录功能的日志文件系统,可以进行简单的容错和恢复,但是在一个高负荷读写的ext3文件系统下,如果突然发生掉电,就很有可能发生文件系统内部结构不一致,导致文件系统破坏

Linux在启动时,会自动去分析和检查系统分区,如果发现文件系统有简单的错误,会自动修复,如果文件系统破坏比较严重,系统无法完成修复时,系统就会自动进入单用户模式下或者出现一个交互界面,提示用户介入手动修复。现象类似下面所示:
checking root filesystem
/dev/sdb5 contains a file system with errors, check forced
/dev/sdb5:
Unattached inode 68338812
/dev/sdb5: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY
(i.e., without -a or -p options)
FAILED
/contains a file system with errors check forced
an eror occurred during the file system check
****dropping you to a shell;the system will reboot
****when you leave the shell
Press enter for maintenance
(or type Control-D to continue):
give root password for maintenance
从这个错误可以看出,系统根分区文件系统出现了问题,系统在启动时无法自动修复,然后进入到了一个交互界面,提示用户进行系统修复。

一般情况下解决此问题的办法是采用fsck命令,进行强制修复
   根据上面的错误提示,当按下“Control-D”组合键后系统自动重启,当输入root密码后进入系统修复模式,在修复模式下,可以执行fsck命令,具体操作过程如下:
[root@localhost /]#umount /dev/sdb5
[root@localhost /]#fsck .ext3 -y  /dev/sdb5
e2fsck 1.39 (29-May-2006)
/ contains a file system with errors, check forced.
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Inode 6833812 ref count is 2, should be 1.  Fix<y>? yes
Unattached inode 6833812
Connect to /lost+found<y>? yes
Inode 6833812 ref count is 2, should be 1.  Fix<y>? yes
Pass 5: Checking group summary information
Block bitmap differences:  -(519--529) -9273
Fix<y>? yes
…… ……
/: ***** FILE SYSTEM WAS MODIFIED *****
/: 19/128520 files (15.8% non-contiguous), 46034/514048 blocks

 

方案二:在C程序中加入fflush函数,保证所有输出第一时间写入文件,防止数据丢失。

1. 背景:

fwrite函数只是将所写内容存入用户缓存,并不立刻写入文件.

fflush函数将用户缓存中的内容写入内核缓冲区

fsync函数则是将内核缓冲写入文件

fclose则先执行fflush,再关闭文件的读写.

 

2. 方法:

每次写完后fflush(FILE*fp) ; int fsync(int fd); →强制把数据写到磁盘

(还有就是可以把缓冲区设置成无缓冲. )

这样就能最多限度的保证不会因为缓冲的缘故而照此数据丢失.不过这要在效率上要付出代价的.

 

3.函数

(1)说明

fflush是libc.a中提供的方法,

fsync是系统提供的系统调用。

(2)原形

fflush接受一个参数FILE *.

fflush(FILE *);

fsync接受的时一个Int型的文件描述符。

fsync(int fd);

(3)功能

fflush:是把C库中的缓冲调用write函数写到磁盘[其实是写到内核的缓冲区]。

fsync:是把内核缓冲刷到磁盘上。

c库缓冲-----fflush---------〉内核缓冲--------fsync-----〉磁盘

 

方案三:建立备份配置文件,若原配置文件损坏,则新建配置文件,并将备份文件内容拷贝到新建配置文件。

解决找不到配置文件而产生段错误,以致程序无法启动或正常运行的问题。

 

补充学习:

Linux什么情况下文件会损坏出错?

https://www.cnblogs.com/ShaneZhang/p/4438066.html

http://blog.csdn.net/a421701136/article/details/51802070

 

 


  • 3
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值