Linux文件系统学习摘要--2

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xiaoyilong2007101095/article/details/87859696

声明:

本文只作为参考,我也是初学者,请辩证的看待文章内容,欢迎各位在评论区补充经典博文链接。

本篇文章主要记录下文件系统中 读写文件 相关的内容

读写文件就是文件IO,文件input和output

整体结构如下:

用户态buffer

————————————————————

libc buffer

————————————————————

page cache

————————————————————

IO Queue+ device driver

—————————————————————

disk cache

——————————————————————

disk

首先是用户要写的内容,当然是放到自己分配的空间(用户态buffer),接下来就是如果使用了fwrite函数(libc提供)那么就要用到libc的buffer,libc下面是VFS提供的write系统调用,用到了pagecache,pagecache就到了内核这块了,接下来到设备的cache,最后存储到物理设备。

如果想绕过libc的buffer,就不用libc提供的文件操作函数,比如fread,fwrite等等,我个人也没有感觉到fXXX函数的优越性,所以一般不用。

不用libc了,那就直接到了VFS了,也就是直接系统调用了,系统调用就要用到pagecache了,那如果想绕过pagecache呢?

那就在open的时候加个O_DIRECT

关于O_DIRECT在man中的描述如下:

O_DIRECT (since Linux 2.4.10)
              Try to minimize cache effects of the I/O to and from this
              file.  In general this will degrade performance, but it is
              useful in special situations, such as when applications do
              their own caching.  File I/O is done directly to/from user-
              space buffers.  The O_DIRECT flag on its own makes an effort
              to transfer data synchronously, but does not give the
              guarantees of the O_SYNC flag that data and necessary metadata
              are transferred.  To guarantee synchronous I/O, O_SYNC must be
              used in addition to O_DIRECT.  See NOTES below for further
              discussion.

              A semantically similar (but deprecated) interface for block
              devices is described in raw(8).

提到O_DIRECT会尽力同步写数据,也就是不一定完全按照synchronous的那种方式来,一定是写完才返回,言外之意是:没写完也会返回?那没写完的怎么处理?我不知道了。文中也建议把O_SYNC加上。

最后同时提到了O_RAW,这个查相关博客看到可以直接写扇区,man手册提到已经废弃了,不建议使用。

文件的几种访问方式:

1,以标准的系统调用或者libc系列函数来访问,也就是read write或者fread fwrite系列函数,也就是缓存io,需要说明的是linux的

      缓存io其实就是 延迟写,对于系统调用来说,只是写到了pagecache,什么时候写到磁盘是内核决定的,当然也可以调用

       fsync来直接写到磁盘,注意是磁盘,不是磁盘缓存。与延迟写对应的还有一个叫异步写,异步写后面说。

2,directio,就是加O_DIRECT标识,直接访问也就是没有内核的缓冲,这种方式一般情况都会造成性能下降,但是对于想自己

      控制缓存的应用来说,至少是一个办法,比如有应用想自己在应用层做缓存,就没有必要再引入一层缓存了。

3,mmap

4,异步io访问

mmap

mmap就是把文件映射到内存的虚拟地址空间,实现文件磁盘地址和进程虚拟地址空间中的映射关系,像访问内存一样访问文件。但是怎么实现的?

实现具体代码没有查看过,只是网上搜集出来的实现情景:

首先找到一块连续的虚拟地址段,然后内核会针对mmap分配的虚拟内存地址段建立一个vma,vma对于可执行文件的各个段都有一个对应的结构,vma里面会定义针对映射的这个段的函数操作集合,功能类比read,write,但是操作每个段肯定不一样,接着通过fd找到文件信息,在读内存的时候,就会触发缺页中断,进而使用vma里面的函数读文件,并且拷贝到用户内存空间,也就是说略过了内核的pagecache。少了一次拷贝,这就是mmap的优势,呵呵,欢迎各位补充。

异步io

对于linux主要有两个版本的异步io可以使用

glibc的异步io 和linux本身的libaio

先说glibc,glibc是用户态的异步io,主要实现方式就是多线程,提交一个读写请求,glibc会动态的创建线程来同步的执行读写操作,执行完了通过回调或者其它方式通知用户。对的,就是通过多线程来做的!

接下来是libaio

libaio是针对regular file的,对于socket用不了!!

对于常规文件,在读文件的时候,虽然我们感觉时间很短,但是其实也是阻塞的,读到数据成功为止,比如read一个文件,返回的时候要么读到数据,要么失败,读到数据就是拷贝到了用户态的缓冲区间,经过了磁盘到内核到用户态这么一个过程。使用libaio可以直接下发一个read指令,然后就返回了,内核会把磁盘数据拷贝到用户态空间,应该略过了内核缓冲?。至于什么原理,我讲不出个所以然,查了一些文档也没有讲个什么,后续更新吧。

猜你喜欢

转载自blog.csdn.net/xiaoyilong2007101095/article/details/87859696
今日推荐