linux ext2 get block,read()/write()的生命旅程之二——第二章:read()

本章将介绍read()系统调用的过程。回忆一下第一章里讲到的read()系统调用发生后VFS将调用文件实际所在文件系统的file_operations.read(),我们就从这个地方开始。

1. read():从file

operation到page cache

这个过程是在file_operation.read()的核心函数:do_generic_file_read()中完成的。

虽然每种文件系统都会定义自己的file_operations,如ext2_file_operations,

ext3_file_operations,但大部分最后都会使用do_generic_file_read()这个通用的函数。所以说do_generic_file_read()的实现方法体现了Linux文件系统read()的典型流程。

这个函数的作用和流程如下:

a4c26d1e5885305701be709a3d33442f.png

2.  read():从page

cache到bio

这个过程是在a_ops->readpage()的流程里完成的。每个文件系统都会定义自己的address space

operations, 即a_ops。以ext2为例,下图就是ext2_aops.readpage()的流程。

a4c26d1e5885305701be709a3d33442f.png

在上面的流程图中可以看到读数据的最终实现是要将buffer head对应(Map)到block

device上的某个block,然后向该block device发出bio。那么从page cache和buffer

head以及bio是怎样联系的呢?下一节将做详细解释。

3.  重要概念:page

cache, buffer head和bio

在第一章中已经讲过kernel将文件以page为单位缓存在内存中,叫做page

cache。这是从kernel管理文件的角度来看的。但是文件最终要被读写到存储介质的角度的,从读写存储介质的角度来看,文件读写最终转化为对存储介质上的某些区域的读和写。Linux里最常见的存储介质是block

device,读写block device必须以block

device规定的block大小为单位进行。那么page是怎样转化成block的呢?在Linux kernel里,用bio(block

io)这一数据结构来代表对block

device的读写,bio以block为单位组织要读写的数据。我们知道page通常大小为4096,而block的大小是由block

device自己决定的,Linux kernel使用logic block为单位进行读写,Logic block

size是由block device driver报告给Kernel的。Logic block

size是kernel认为的读写该block device的block size。最常见的logic block size是512

bytes,也可以是1024, 2048或4096。logic block size不能超过page size,而且必须能被page

size整除。这是因为Linux Kernel里将以下面的分割page的方法来把page转换成block。

以最常见的1 Page = 4096 bytes, 1 block = 512 bytes为例,1 Page分割为 8 blocks,如下图所示block 0 ~ block

7。在要发生从存储读数据到Page,如第2节所述的a_ops.readpage或将Page写到存储的时候,如下一章将要讲述的writeback的时候,Linux

kernel会为page里的每个block创建一个叫buffer

head(bh)的数据结构,bh的作用就是要将每个block对应到物理存储上的一个block。bh实际上是联系文件和物理存储介质的桥梁。

bh->b_page,bh->data指向该block在文件中的位置,实际是文件在内存中的缓存page中的位置。注意buffer

head只是指向page中的位置,并没有新的buffer,所谓的buffer还是page的一块,buffer和page是同一块内存。

bh->b_bdev表示block在哪个block

device上, bh->blocknr表示该block在存储介质上的位置。要从一个文件里的某一块block得到其位于存储介质上的位置,这是文件系统要做的翻译。做这个翻译工作就是非常重要的get_block()函数。这个翻译也叫Map。如上面的ext2_get_block(),它的工作就是根据ext2的格式算出page里的某一块在整个ext2所在partition上的对应的blocknr。更直接的说,如果/dev/sda1这个partition上是个ext2的文件系统,里面有个文件a.txt,现在要读a.txt的开头的block(512

bytes),那么ext2_get_block()就负责找到这个block在/dev/sda1上的位置。

bh->state代表了buffer的状态,比较重要的有BH_Mapped,

BH_Uptodate和BH_Dirty。他们的含义在下图中已说明。上面所说的get_block()后bh->state就变成了BH_Mapped。

a4c26d1e5885305701be709a3d33442f.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值