简单了解那些磁盘的文件处理的概念

拜拜、爱过 提交于 2020-03-27 15:49:14

3 月,跳不动了?>>>

多级缓存

文件数据的存取是计算机世界比较常见的需求,为提升文件存取效率,操作系统对于整个文件IO过程做了比较大的优化,多级缓存的思路在设计中无处不在。

用户操作数据到达磁盘存取流程如下:

黑色实线是用户态和内核态的分界线。

C语言开发的stdio库定义了文件操作相关的函数,stdio中实现的文件操作函数都有自己的stdio buffer,是在用户态实现的缓存。

如果用户操作读写都是较小size文件连续读写的话,stdio库可以将多次读写操作通过buffer进行缓冲与聚合之后统一处理,以提高程序运行效率。stdio库中的fflush函数可以主动的刷新buffer,主动调用底层操作系统进行buffer里面的数据更新。

操作系统调用read/write函数操作和磁盘之间也存在一层buffer,kernel buffer cache就是这层缓存。我们经常把linux中文件缓存称为page cache,设备纬度的缓存称为buffer cache。

  • page cache用于缓存文件内容,和文件系统相关,文件系统和磁盘建立映射,映射关系由文件系统维护
  • buffer cache用于缓存存储设备扇(块)区的数据,而不关心文件系统

总结来说,linux下的io操作,write/read函数调用是用户态和内核态之间的分界线。在用户态和内核态及物理磁盘之间对于连续的小size文件操作都存在buffer缓存,文件系统层面的缓存称为page cache,设备纬度的缓存称为buffer cache。

多种IO操作比较

在系统调用接口往下,Linux的IO栈分为三个层次:

  1. 文件系统层:如write操作,内核拷贝write参数指定的用户态数据,到文件系统的cache中,并向下层同步
  2. 块层:管理块设备的IO队列,对于IO请求进行合并,排序(FIFO)
  3. 设备层:通过DMA与内存直接交互,完成数据和设备之间的交互

Buffered IO,mmap,Direct IO有什么作用呢?

传统的Buffered IO要通过read读取文件时,如果文件不在cache中流程是什么样呢?

  1. open打开文件内核后建立一系列数据结构
  2. 之后调用read,到达文件系统层,发现page cache不存在该位置的磁盘映射
  3. 然后建立page cache和磁盘扇区关联关系,之后请求到达设备层
  4. 在IO队列里面排队,接收调度到达设备驱动层,使用DMA方式读取磁盘扇区数据到达cache中(一次)
  5. 之后read函数拷贝数据到达用户态的buffer中(两次)

BUffered操作的整个过程数据从磁盘到page cache算是一次数据拷贝,从page cache到用户态buffer算是第二次数据拷贝。

同样的操作我们对比图中mmap操作,mmap直接把page cache映射到了用户态地址空间里,所以mmap方式读取文件没有第二次数据拷贝过程。

那么我们看下图中Direct IO操作,他直接让用户态和块层直接IO对接,直接放弃了page cache。 从磁盘直接和用户态拷贝数据,带来的好处是,写操作直接映射进程中的buffer到磁盘扇区,以DMA方式传输数据,减少了到page cache层的一次拷贝,提升了写效率。如果只有一次读操作效率也会有所提高,但如果多次读就不如传统读取操作了,因为没有了相应的cache数据了。

Page cache同步

cache同步分为两种:write through 和 wirte back。

  • write through:指的是write操作将数据拷贝到page cache后立即和下层进行同步写操作,完成下层的数据更新后返回
  • write back:指的是写完page cahce后就可以返回了,数据同步通过异步更新完成

Buffered IO默认使用的是write back机制,文件操作只写到page cache就返回,之后通过异步方式更新page cache数据到磁盘。page cache中被修改的内存页被称为脏页,脏页在特定的时候被一个pdflush(page dirty flush)内核线程写入磁盘。

写入条件如下:

  1. 当空闲内存低于特定阈值后,内核需将脏数据写回磁盘,用来释放内存
  2. 当脏页在内存中驻留时间超过特定阈值后,内核需要将超时脏页写到磁盘
  3. 用户进程调用sync,fsync,fdatasync系统调用时,内核执行相应的写回磁盘操作

当写操作的可靠性高于写操作效率时,可以通过fsync之类的系统调用实现,或者在open打开文件时,传入O_SYNC这个参数即可。

现代磁盘一般内置了缓存,数据一般先写到磁盘的高速缓存。

文件操作和锁

write写操作不是原子性操作,多线程进行write操作和多个线程访问共享变量没什么区别。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!