Linux 内核read工作过程

普通文件读过程

(1)当应用程序调用库函数read(),触发对系统资源使用,所以就触发了系统调用sys_read()。为了本身支持多种文件系统,Linux开发统一抽象虚拟文件系统接口---虚拟文件系统(VFS)。所以理所当然调用该层的vfs_read()函数。

(2)为了改进系统系能,所以引入缓存(磁盘高速缓存disk cache)---众所周知内存与硬盘读写速度差距是非常大,并且内存与硬盘特点也不同。因此首先进入磁盘缓冲(内存),查找要读取文件数据。如果找到并且有效数据,立刻返回给应用程序。否则只能进入具体文件系统磁盘映射层(mapping layer).另外在这一层还有一个重要概念,磁盘数据预读,这也是改进i/o性能重要途径,但是有条件的。条件是磁盘数据是连续的。一般来说普通文件存放都是连续,所以当我们顺序读取数据时,可以把接下来要使用的,同时读入,后面读取可以从磁盘高速缓冲中。如果多次启动读取操作,相当与频繁的发送中断,增加系统负担。


(3)进入具体文件系统之后,计算逻辑与真实数据映射关系,获取数据在磁盘位置以及读取数据存放是否连续等。有了上面的信息,进入具体通用块层(generic block layer)


(4)通用块层目的基于上面映射关系构造块i/o,数据结构bio描述。一般来说一组磁盘数据相邻,构造一个bio, 如果不相邻,需要构造几个bio.构造了数据操作,接下来要提交操作到设备队列中,进入了i/o调度层。


(5)i/o调度层对提交块i/o进行,排序和合并,构造或者放入已有的设备请求队列中的数据请求中,排序和合并策略按照/sys/block/sda/queue/scheduler进行。可见磁盘读写bio,放入请求队列中,并不是立即触发读写,在磁盘队列中进行读写排序与合并--这也是改进i/o性能重要途径(硬盘特点)。大家知道read()调用是阻塞的,原因也不言自明了。


(6)最后进入真正设备驱动层了,进行实际数据传输。
首先从请求队列中,摘取一个个请求request: elv_next_request(q); 摘取一个个请求按照/sys/block/sda/queue/scheduler注册的策略进行
然后从请求中,获取一个个bio: rq_for_each_bio(bio, rq) 每个请求意味着磁盘数据是连续(磁盘存放)
最后从一个bio中,获取一个个bvec:bio_for_each_segment。 每个bvec意味这缓冲区是连续的(内存存放),这样目的是启动DMA传输,每个DMA操作所需内存要求是连续的。启动DMA传输,启动中断,中断中调用数据传送函数


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值