设为首页 加入收藏

TOP

块设备驱动编写总结(二)
2014-11-24 03:17:22 】 浏览:10091
Tags:设备驱动 编写 总结
io请求挂载到一个已经存在request中。如果不能合并,那么分配一个新的request,然后将bio添加到其中。这一切搞定之后,说明通过generic_make_request转发的bio已经抵达了内核的一个站点——request,找到了一个临时归宿。此时,还没有真正启动物理设备的操作。在__make_request退出之前,会判断一个bio中的sync标记,如果该标记有效,说明请求的bio是一个是实时性很强的操作,不能在内核中停留,因此调用了__generic_unplug_device函数,该函数将触发下一阶段的操作;如果该标记无效的话,那么该请求就需要在queue队列中停留一段时间,等到queue队列触发闹钟响了之后,再触发下一阶段的操作。__make_request函数返回0,告诉generic_make_request无需再转发bio了,bio转发结束。

9、 到目前为止,文件系统(pdflush或者address_space_operations)发下来的bio已经merge到request queue中,如果为sync bio,那么直接调用__generic_unplug_device,否则需要在unplug timer的软中断上下文中执行q->unplug_fn。后继request的处理方法应该和具体的物理设备相关,但是在标准的块设备上如何体现不同物理设备的差异性呢?这种差异性就体现在queue队列的方法上,不同的物理设备,queue队列的方法是不一样的。举例中的sda是一个scsi设备,在scsi middle level将scsi_request_fn函数注册到了queue队列的request_fn方法上。在q->unplug_fn(具体方法为:generic_unplug_device)函数中会调用request队列的具体处理函数q->request_fn。Ok,到这一步实际上已经将块设备层与scsi总线驱动层联系在了一起,他们的接口方法为request_fn(具体函数为scsi_request_fn)。

10、明白了第(9)点之后,接下来的过程实际上和具体的scsi总线操作相关了。在scsi_request_fn函数中会扫描request队列,通过elv_next_request函数从队列中获取一个request。在elv_next_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 command具体转发给那个scsi host呢?秘密就在于q->queuedata中,在为sda设备分配queue队列时,已经指定了sda块设备与底层的scsi设备(scsi device)之间的关系,他们的关系是通过request queue维护的。

11、 在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中断下半部。

12、 在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。

13、 回调结束之后,文件系统引发的读写操作过程结束。


首页 上一页 1 2 下一页 尾页 2/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇GDB调试程序用法 下一篇Java动态定义二维数组问题

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目