能否让write函数写入的内容,直到fsync才真的写入磁盘呢?

iuiwer 2013-07-05 03:07:11
linux的系统调用write/read在用户级是没有缓存的(不像stdio那样有buffer),而在内核级是有缓存的,对吧?
但是我写了一个小程序,来测试write操作是不是立刻写入磁盘,用RHEL6.3编译运行,如下:

#include<fcntl.h>
#include<sys/types.h>
int main()
{
int fd=open("/tmp/test1",O_CREAT|O_RDWR);
if(fd<0)exit(1);
write(fd,"you",3 );
sleep(100);
close(fd);
return 0;
}

程序运行到sleep(100)的时候,我立刻在另一个终端里面cat /tmp/test1就能发现我写入的内容。并没有等到close函数执行,内容就已经写入了文件。
(1) 我删掉这个文件,重来,一样的结果,文件显示you。
(2) 我把you改成him,重来,一样的结果,文件显示him。

这让我感觉很矛盾:
(a)看起来在内核层面,write也是没有缓存的啊,不需要任何flush操作就真的写入了。
(b)那么,如果linux实现的write/read是无缓存的,那么fsync函数还有什么存在的意义呢?

a和b这两点互相矛盾啊!
还请大侠解释一下我的疑惑!
...全文
407 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiaoyaoxiaonizi 2013-07-05
  • 打赏
  • 举报
回复 6
楼主的分析有点片面了,首先要坚信文档中说的,read和write是肯定有缓存的,这是内核为了提高硬盘效率必须做的优化。而为什么楼主测试的程序会看不出效果呢?原因其实你已经知道了,因为缓存是对内核而言,不是对程序而言的,所以内核存在一定的同步机制,不会让这种情况发生,具体是怎么同步的呢,大概是这样的,执行write之后,内核将数据缓存起来,等到缓存区满了之后或者执行了fsync再强制写入硬盘,这时候其实数据还不一定到了磁盘,因为硬盘也有一个缓存区,数据会首先写入那里。但是如果这是执行了read尝试读取刚刚写入的数据,内核会先判断这段数据在在缓存中有没有更新,如果有就会直接从缓存读取,所以就会产生一种假象,数据已经被写入硬盘,这其实是内核的一种策略。如果你想看数据是不是真的被写入硬盘,很简单,执行write之后,直接拔电源,重启后看看数据文件中数据是不是更新了。要强调一点,内核何时把数据写入硬盘是不确定的,所以即使拔电源也不一定会看到数据没有更新,但没有更新的概率会很大。
iuiwer 2013-07-05
  • 打赏
  • 举报
回复
引用 1 楼 erhou134 的回复:
可以刷新文件更新时间
如何“刷新文件更新时间”?
空的 2013-07-05
  • 打赏
  • 举报
回复
可以刷新文件更新时间

4,441

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 内核源代码研究区
社区管理员
  • 内核源代码研究区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧