面试官问:
写文件的时候,进程如果宕机了,数据是否会丢失?
前置知识:
在应用程序中会有一些日志写到磁盘里面,如果进程宕机了,我们之前数据是否会丢失?
这里主要考察的是写文件流程是否清晰。
大家在写文件的时候会用到一些库:
第一个就是stdio函数库;
另外一个就是最原生的open、write去写接口。
这两种写的方式有什么不同?
如果我们使用的是stdio函数库:
里面会有这么几个接口fopen、fwrte、fflush 。最后,如果我们需要把缓冲池里面的数据刷到磁盘里面,那我们还会调用fsync,有这么几个流程。写完之后,我们调用fclose。这么几个接口。
还有就是原生的。原生就是直接open 打开一个fd,打开之后write,调用fsync把数据刷到磁盘里面,最后close。
有什么不同呢?
-
前者的函数参数 是file 开头的数据流
-
后者的是fd相关的
stdio数据库写文件流程图
首先fopen打开一个文件,文件是file类型,然后把数据发write写到用户态的这个buf里面,调用fflush,把数据刷到page cache,然后再调用fsync,把数据刷到磁盘里面,这是一个完整的流程。
需要注意的是,如果我们没有调用这个fflush,那数据就是在用户态,此时数据就可能会丢失。那fclose也是同样的作用,如果没有调用fflush,而是调用的fclose,那数据同样是可以刷到我们的page cache的。fflush本质上就是把系统调用的write封装了一层而已。
第二种接口是怎么写数据的呢?
Open打开一个具体文件,返回的是一个fd。然后在通过write系统调用,把用户态的数据刷到page cache再用fsync把数据刷到磁盘里面。
回归问题本身,数据是否丢失?
需要分情况讨论(如果是使用的stdio数据库):
1.如果没有调用fflush、fclose。那数据就还在用户态缓冲区里面,进程宕机了,那么进程所对应的数据就丢失了,所以肯定会丢失。
2.如果数据调用了fflush、fclose,那数据是在page cache,但机器断电了,数据还是会丢失。
扩展:
1.如果我们使用了直接文件IO open(o_redict),那文件是不会丢失的,会直接到磁盘。
2.Fflush和fsync的区别在于:fflush是把数据从用户态缓冲区刷到page cache,而fsync是把数据从page cache刷到磁盘。
3.Fsync和fdatasync有什么区别?Fdatasync是把fd所对应的数据直接刷到磁盘里面。Fsync还会把文件属性刷到磁盘里面。
原文转载于:公众号