从用户空间开始进行对文件的读过程

读:

读取一个文件的时候,陷入系统调用,先检查数据是否在缓存中,如果没有则触发一次读盘操作,然后等待磁盘上的数据被更新到缓存中。

读取磁盘过程:调用文件系统层的readpages函数,使用各种文件系统层的get_block函数获取磁盘物理地址,存放到bh里(即buffer_head),使用bh构造bio,然后提交bio(一般使用submit_bio函数将数据bio提交到io的块设备层)。函数generic_make_request转发bio,generic_make_request是一个循环,通过generic_make_request提交请求给I/O调度层,这个函数最后调用到q->make_request_fn(q, bio),那么对于这个函数的调用就是I/O调度层的入口点(ps: Generic_make_request的执行上下文可能有两种,一种是用户上下文,另一种为pdflush.)

q->make_request_fn调用的是blk_queue_bio函数(早期版本是__make_request),在blk_init_allocated_queue里注册。blk_queue_bio函数是Linux提供的块设备请求处理函数,实现IO Schedule。在该函数中试图将转发过来的bio merge到一个已经存在的request中,如果可以合并,那么将新的bio请求挂载到一个已经存在request中。如果不能合并,那么分配一个新的request,然后将bio添加到其中。

blk_queue_bio里分为plug和unplug机制 ,在plug下就直接把request存到plug list(例如dio就是依赖于plug机制)。unplug下就直接调用queue的request_fn方法把request提交给磁盘驱动进行真正的处理了。当然,我们现在使用的是unplug机制。

然后q->request_fn调用queue队列的request_fn方法scsi_request_fn函数(我们这里选择sda,sdb之类scsi设备),
在scsi_request_fn函数中会扫描request队列,通过blk_peek_request(原先版本是:elv_next_request)函数从队列中获取一个request。在blk_peek_request函数中通过scsi总线层注册的q->prep_rq_fn(scsi层注册为scsi_prep_fn)函数将具体的request转换成scsi驱动所能认识的scsi command。获取一个request之后,scsi_request_fn函数直接调用scsi_dispatch_cmd函数将scsi command发送给一个具体的scsi host。

到这一步, 在scsi_dispatch_cmd函数中,通过scsi host的接口方法queuecommand将scsi command发送给scsi host。通常scsi host的queuecommand方法会将接收到的scsi command挂到自己维护的队列中,然后再启动DMA过程将scsi command中的数据发送给具体的磁盘。DMA完毕之后,DMA控制器中断CPU,告诉CPU DMA过程结束,并且在中断上下文中设置DMA结束的中断下半部。DMA中断服务程序返回之后触发软中断,执行SCSI中断下半部。

在SCSi中断下半部中,调用scsi command结束的回调函数,这个函数往往为scsi_done,在scsi_done函数调用blk_complete_request函数结束请求request,每个请求维护了一个bio链,所以在结束请求过程中回调每个请求中的bio回调函数,结束具体的bio。Bio又有文件系统的buffer head生成,所以在结束bio时,回调buffer_head的回调处理函数bio->bi_end_io(注册为end_bio_bh_io_sync)。自此,由中断引发的一系列回调过程结束,总结一下回调过程如下:scsi_done->end_request->end_bio->end_bufferhead

那什么时候知道数据已经在缓存里了呢?
do_generic_file_read –> PageUptodate(page) 即检查 PG_uptodate标志位。

参考的资料:
Linux scsi设备读写流程 :
http://blog.chinaunix.net/uid-29634482-id-5127267.html
块设备读写流程 :
http://blog.chinaunix.net/uid-25052030-id-58337.html
usb驱动学习笔记 :
http://blog.chinaunix.net/uid-25627207-id-3341609.html
plug/unplug机制 :
http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=14528823&id=4778396

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值