IO的生命周期

● submit_bh

来自cache的数据被封装成bio

● submit_bh -> submit_bio ->submit_bh_wbc->submit_io-> generic_make_request

make_queue_fn的注册在request queue初始化的时候blk_init_queue->blk_init_allocated_queue

● generic_make_request->blk_queue_bio

blk_queue_bio实现了对bio的合并调度。它调用的函数elv_merge是关键函数,它实现了对请求的调度,IO调度器就是在这里被调用的。

IO从块设备层(block IO layer),到发送到块设备驱动(device driver)整个过程经过三类队列:

1)unplug request queue 属于线程

2)elevator queue 调度队列,不同的调度器,队列不同

3)device request queue 派遣队列,dispatch queue。(例如,在deadline_dispatch_requests中实现)

此时bio(request)还在unplug 队列中。

● blk_queue_bio:

通过blk_flush_plug_list(也可通过_elv_add_request)将unplug 请求队列中的请求发送到调度队列elevator queue。

来自上层的请求,先尝试合并入unplug 队列,若不能合并,则调用elv_merge合并入调度队列elevator queue。若找不到可合并的请求,则获得一个空请求request,用该bio初始化该request,然后放到unplug队列中。

此时request在调度队列中。

● blk_queue_bio->elv_merge

IO调度器在该函数里调用。

此时request在调度队列中。

IO调度器的工作:合并,排序。

排序:使请求按扇区增长的方向有序排列。

CFQ:每个发起IO的进程都有一个队列。

Deadline:有4个队列,分为两类sort_list和fifo_list。每类都有读写两种队列。

sort_list 按请求起始扇区排序,fifo_list按请求生成的时间排序。

plug和unplug:目的是让请求马上被驱动程序处理。设备处于pluged状态,设备不会被激活。处于unplugged状态,被激活。

● 返回blk_queue_bio,然后

blk_queue_bio-> add_acct_request-> __elv_add_request

此时,request在device request queue(派遣队列)中。

这一步实现具体IO调度器对请求的派遣(发送到派遣队列):

__elv_add_request->elv_drain_elevator->elevator_dispatch_fn

elevator_dispatch_fn将被注册为具体调度器的派遣函数,例如deadline_dispatch_request

此时,请求在派遣队列(device request queue)中。

● 返回blk_queue_bio:

blk_queue_bio-> __blk_run_queue-> __blk_run_queue_uncond->request_fn(scsi_request_fn)-> blk_peek_request->__elv_next_request

request_fn被注册为scsi_request_fn,该函数是驱动程序的入口。

从device request queue中获得一个请求,准备发送到scsi块设备驱动(中间层)

● 在blk_peek_request中调用q->prep_rq_fn(注册为scsi_prep_fn),将request转化成scsi驱动能够识别scsi command。

此时,请求在派遣队列中。

● 回到scsi_request_fn,调用scsi_dispatch_cmd将scsi command发送给scsi host

● 在scsi_dispatch_cmd中,调用queuecommand方法,将scsi command挂在自己的队列中,然后启动DMA,将scsi command发送到具体的磁盘。DMA完毕后,DMA控制器中断CPU,告诉CPU DMA结束。并且在中断上下文中,设置DMA结束的中断下半部。DMA中断处理程序返回之后,触发软中断,执行scsi中断下部。

驱动:scsi中间层(middle level driver) +  scsi host driver。

scsi中间层抽象了scsi总线逻辑;scsi host driver控制scsi总线控制器,实现scsi数据的物理层传输。

queuecommand是这两层之间的桥梁。它将被注册为具体的物理块设备的函数,例如megaraid_queue。

● 在scsi中断下部,调用scsi command结束的回调函数scsi_done:scsi_dispatch_cmd->scsi_done。scsi_done调用blk_complete_request结束请求。

时间: 2024-11-08 11:37:31

IO的生命周期的相关文章

Spring点滴四:Spring Bean生命周期

Spring Bean 生命周期示意图: 了解Spring的生命周期非常重要,我们可以利用Spring机制来定制Bean的实例化过程. --------------------------------------------------------------------------------------------------------------------------------------------------- spring-service.xml: <?xml version=

Java多线程 2 线程的生命周期和状态控制

一.线程的生命周期 线程状态转换图: 1.新建状态 用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于新生状态.处于新生状态的线程有自己的内存空间,通过调用start方法进入就绪状态(runnable). 注意:不能对已经启动的线程再次调用start()方法,否则会出现Java.lang.IllegalThreadStateException异常. 2.就绪状态 处于就绪状态的线程已经具备了运行条件,但还没有分配到CPU,处于线程就绪队列(尽管是采用队列形式,事实上,把它

Servlet的生命周期+实现方式

1.Servlet的生命周期:        (1)被创建:            默认情况下,Servlet第一次被访问时,被服务器创建.会调用init()方法.                一个Servlet只会被创建一次.init()方法也只会被调用一次.                Servlet是单例的.而服务器时多线程的.可能存在线程安全问题.                  为了避免安全问题,在Servlet中尽量不要定义成员变量.即使定义了.也不要进行其他操作(只能查询).

Spring容器中Bean的生命周期

日出日落,春去秋来,花随流水,北雁南飞,世间万物皆有生死轮回.从调用XML中的Bean配置信息,到应用到具体实例中,再到销毁,Bean也有属于它的生命周期. 人类大脑对图像的认知能力永远高于文字,因此,闲言少叙,书归正传,上图先: 步骤很多,切莫惊慌,我们可以把上面的步骤归纳如下: 1-2:创建实例: 现在假设spring就是个容器,而配置文件中配置的bean属性才是我们真正需要的东西.创建实例就是说,我把配置文件中的bean信息取出来化作一个真正的bean并放到容器中. 3-4:注入依赖关系:

J2EE--Servlet生命周期与原理

Servlet是在服务器上运行的小程序.而在java中应用程序多是在容器中进行生命周期的管理(这里指Tomact容器). Servlet基本的架构图 首先是 web页面通过提交表单 tomact获取传递过来的数据,进行解析 创建HttpSaervletRequest,该对象包含了客户端信息,如表单数据,客户端的主机名称和ip地址. 创建HttpServletResponse对象,可以向浏览器写入数据. 之后是调用Servelt,创建Servelet实例 创建servelet实例的过程中 首先调用

PHP扩展-生命周期和内存管理

1. PHP源码结构 PHP的内核子系统有两个,ZE(Zend Engine)和PHP Core.ZE负责将PHP脚本解析成机器码(也成为token符)后,在进程空间执行这些机器码:ZE还负责内存管理,变量作用域管理和对PHP函数的调度管理. PHP Core负责和SAPI层的通信:PHP Core也为safe_mode, open_basedir的检查提供了统一控制层:PHP Core还提供了streams层,用于用户域的文件和网络IO操作.其中SAPI(Server Application

Java实现生命周期管理机制

先扯再说 最近一直在研究某个国产开源的MySQL数据库中间件,拉下其最新版的代码到eclipse后,启动起来,然后做各种测试和代码追踪:用完想要关闭它时,拉出它的STOP类想要运行时,发现这个类里赫然只写以下几行代码,于是我感觉瞬间受到了很多伤害. public static void main(String[] args) { System.out.println(new Date() + ",server shutdown!"); } 这个中间件启动和运行的时候,开启了监听,启动着

javaweb学习总结二十一(servlet开发入门、servlet生命周期以及调用过程)

一:servlet开发入门 servlet是sun公司一门开发动态web资源的技术,下面编写一个servlet入门程序: 1:在tomcat服务器webapps目录下新建firstServlet目录,在firstServlet目录下创建WEB-INF/classes目录 在classes目录下,写servlet程序. 类FirstServlet.java 1 /** 2 * 3 */ 4 package com.hlcui.servlet; 5 6 import java.io.IOExcept

javaEE:day2-servlet生命周期、提交解决中文乱码、tomcat加载jar包或类文件的顺序

servlet生命周期 生命周期简介: servlet在服务器第一次被请求的时候new出来,并初始化(即init())再调用service方法.这个实在服务器中new出来,然后用HashMap加的,与客户端无关.客户端之后访问只调用这个servlet的service方法. 具体分为4步: 1 构造方法 :服务器在被客户端第一次请求的时候运行 仅在服务器中运行一次 2 init方法:客户端第一次访问服务器的时候在服务器中进行初始化 仅一次.并且可以通过config参数在 web.xml中通过(ke