Linux系统的数据写入机制--延迟写入
我们都知道,在Linux关机的之前都会要运行一个命令那就是sync,这个命令是同步的意思,那为什么要运行这个?而且之前的数据改变我们已经看见了,为什么还要运行这个命令?要回答这个问题就要说一下Linux在这方面的执行机制。
首先我们要从buffer和cache说起,如下图:

buffer和cache都可以翻译成缓存,但是到底有什么区别呢?
cache:
目的是为了数据重复使用,在一定程度上解决读的效率,这里就是用来存放经常用到的数据,而不用每次都去磁盘上面读取,如果本次操作用到的数据没有,则会到磁盘上去寻找。这样就可以在一定程度上协议快速和慢速设备(比如:CPU和硬盘),另外cache也有换进换出机制,就是把原来经常用到,现在不常用的清除掉,这样就可以有空间放最近访问的数据了,以达到下次访问就直接从cache中读取。
buffer:
为了提高写如磁盘时的效率,其实也是为了协调快慢设备,避免造成把数据都提交到写入磁盘队列造成拥堵,因为内核把数据提交到写入队列不可能不管,它必须要等到有返回值才行。所以buffer的作用是先把数据写入(Linux中的write()函数)到buffer中,然后后台再去根据其他机制,把buffer中的数据提交到队列,最终完整同步到磁盘的过程。
我们知道用户发起的程序都会运行在内存中的用户空间内,这时候数据是放在内存中的,如果我们此时需要保存数据,这时候系统其实是先调用一个write()函数,然后再调用sync()或者fsync()函数(对于任何程序来说只要想把数据写入磁盘其过程都一样,有些也有例外)。
顺便说一句,这也就是为什么有人说Linux比Windows消耗内存的原因。
用户空间:常规进程所在区域,用户发起的,此区域的代码不能直接访问硬件
内核空间:操作系统所在区域,能访问硬件
当调用了write()函数时,该函数一旦返回正常值,我们可能就认为数据已经写入到了磁盘,但实际上,操作系统在实现磁盘文件的IO时,为了保证IO的效率,会在内存中使用一段专门的地址空间,该空间叫做内核空间,而内核空间之内又会有一段是用作IO的数据缓冲区(这个缓冲区就是buffer),write()函数的作用就是把数据写入到内核空间的IO缓冲区中。

内核空间的IO缓冲区也有一定大小,当该缓冲区没有写满时或者没有到一个同步周期时,会持续的把write()函数传递的数据写入到该缓冲区中,而当该缓冲区写满或者到了一个同步周期,则会把该缓冲区的内容提交到输出队列,当需要数据到达队列队首的时候,开始执行真正的磁盘IO操作,把数据写入磁盘(这里虽然用了写入磁盘,但是真正的动作不是移动而是复制,复制完成之后,内核空间的IO缓冲区才会释放该数据占用的空间)。这种方式叫做延迟写入。
所以这就会出现一个问题,当调用了write()函数后并不等于数据真的保存到了磁盘,但是这里又会有一个错觉,就是你再次请求该文件的时候,可以显示你最后一次更新的内容,其实这个内容并不是从磁盘上读取过来的,而是从用户空间的缓冲区读取的。接着刚才提到的问题,如果数据在内核空间的IO缓冲区内,而此时操作系统出现故障、断电等异常情况就会造成数据丢失。
为了解决数据丢失问题,Unix系统提供了sync、fsync和fdatasync三个函数。
| 函数 | 功能 |
| sync | 函数返回0表示成功,该函数负责把所有内核空间中IO缓冲区内修改过的内容推送到输入队列,然后就返回,它并不等待所有磁盘IO操作完成。所以即使调用了sync函数,也不等于成功保存到磁盘了。 |
| fsync | 函数返回0表示成功,与sync不同,它只会对指定文件描述符的单一文件生效,强制与该文件相连的所有修改过的数据传送到磁盘上,并且等待磁盘IO完毕,然后返回。当该函数返回0时,才真正表示成功保存到磁盘。数据库会在调用了write()之后调用fsync()。 |
| fdatasync | 它与fsync类似,它只影响文件数据部分,不涉及数据属性,比如inode信息。所以相对于fsync它需要较少的写磁盘操作。 |
看了上面的内容你就应该明白为什么关机前要运行一下sync命令了。
Linux系统的数据写入机制--延迟写入的更多相关文章
- linux 系统中将数据写入文档不能立即保存问题的解决方法
应用场景: 设备跑的是Linux系统,与PC上位机进行通信,上位机可以给Linux发送设备配置信息,Linux将配置信息写入文件中以备设备断电重启时使用. bug现象: 设备正常运行,设备配置信息为A ...
- Linux系统的快速启动机制(内核切换) 【转】
转自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=26807463&id=4187846 原文地址:Linux系统的 ...
- (转)Linux系统sersync数据实时同步
Linux系统sersync数据实时同步 原文:http://blog.csdn.net/mingongge/article/details/52985259 前面介绍了以守护进程的方式传输或同步数据 ...
- Linux系统捕获数据包流程
Linux系统捕获数据包流程 为了提高数据包的捕获效率,瓶颈问题是一个需要非常关注的焦点.减少在捕获数据包过程中的瓶颈,就能够提高数据包捕获的整体性能.下面本文将以Linux操作系统为平台,分析捕获数 ...
- Linux系统实时数据同步inotify+rsync
一.inotify简介 inotify是Linux内核的一个功能,它能监控文件系统的变化,比如删除.读.写和卸载等操作.它监控到这些事件的发生后会默认往标准输出打印事件信息.要使用inotify,Li ...
- 阿里云Linux系统挂载数据盘
Linux云服务器数据盘未做分区和格式化,我们可以根据以下步骤进行分区以及格式化操作. 目录 [隐藏] 1 查看数据盘 2 对数据盘进行分区 3 查看新的分区 4 格式化新分区 5 添加分区信息 6 ...
- Linux系统SCSI磁盘扫描机制解析及命令实例(转)
转载请在文首保留原文出处:EMC中文支持论坛 介绍 Linux系统扫描SCSI磁盘有几种方式?Linux新增LUN之后,能否不重启主机就认出设备?如果安装了PowerPath,动态添加/删除LUN的命 ...
- Linux系统SCSI磁盘扫描机制解析及命令实例
介绍Linux系统扫描SCSI磁盘有几种方式?Linux新增LUN之后,能否不重启主机就认出设备?如果安装了PowerPath,动态添加/删除LUN的命令是什么?本文总结了Linux主机对磁盘设备进行 ...
- 阿里云里面的Linux 系统挂载数据盘
转自:http://www.cnblogs.com/adjk/p/5112360.html 适用系统:非IO优化+SSD云盘Linux(Redhat , CentOS,Debian,Ubuntu)实例 ...
随机推荐
- C#代码总结01---如何清空页面上所有文本框的内容。(用于录入后的清空)
/// <summary> /// 清空页面上所有TextBox的内容.用于录入后的清空 /// </summary> /// <param name="top ...
- [转]PHP实现页面静态化的超简单方法
为什么要页面静态化? 1.动态文件执行过程:语法分析-编译-运行 2.静态文件,不需要编译,减少了服务器脚本运行的时间,降低了服务器的响应时间,直接运行,响应速度快:如果页面中一些内容不经常改动,动态 ...
- BZOJ.4145.[AMPPZ2014]The Prices(状压DP)
BZOJ 比较裸的状压DP. 刚开始写麻烦惹... \(f[i][s]\)表示考虑了前\(i\)家商店,所买物品状态为\(s\)的最小花费. 可以写求一遍一定去\(i\)商店的\(f[i]\)(\(f ...
- Ubuntu下编译SqlCipher以及解密微信数据库EnMicroMsg.db过程和坑
wget https://codeload.github.com/sqlcipher/sqlcipher/zip/v3.4.2 ./configure --enable-tempstore=yes C ...
- Vue 记录 Cannot read property '_withTask' of undefined
第二次遇到,年前偶尔代码中频繁出现过,因为没影响到交互,赶工期中,没有去深究. 今天又遇到了, 在事件触发后,脚本报错,终止了界面交互. 最后查找到这里的原因,检查并移除无效业务事件,错误消失了. ( ...
- kubernetes之Kubeadm快速安装v1.12.0版
通过Kubeadm只需几条命令即起一个单机版kubernetes集群系统,而后快速上手k8s.在kubeadm中,需手动安装Docker和kubeket服务,Docker运行容器引擎,kubelet是 ...
- textarea--去掉空格的办法
我在初次用到textarea多行文本框时,遇到的问题是:默认出现了两行空格,如图: 代码是(错误的写法): 最后才发现,原来是: textarea标签是需要写在同一行,不能换行,正确的写法:
- 3.jmeter接口测试---脚本录制
安装好jmeter后,就要进入主题了,进行接口测试,接口测试的脚本获取方式 ①手动填写 ②badboy录制后,导入jmeter使用 ③jmeter录制 不会安装的可以进入这里:https://www. ...
- echarts-for-react 从新渲染数据
<ReactEcharts option={option} notMerge={true} style={{height: '600px', width: '100%'}} className ...
- 马昕璐201771010118 《面对对象程序设计(java)》第九周学习总结
第一部分:理论知识学习部分 异常:在程序的执行过程中所发生的异常事件,它中断指令的正常执行. Java把程序运行时可能遇到的错误分为两类: 非致命异常:通过某种修正后程序还能继续执行. 致命异常:程序 ...