btt User Guide在百度找了3天没找到,bing也不行,结果google第一页第5个结果就是。

可恶的GFW

http://www.fis.unipr.it/doc/blktrace-1.0.1/blktrace.pdf

通过blktrace btt工具分析得知,block在get request时的event有如下:

  • A:表示IO被重新映射到不同的设备(IO was remapped to a different device)。
  • B: IO反弹(io bounced)
  • C: IO完成。(io completion)
  • D: IO发送给驱动(io issued to driver)
  • F: 在队列中请求合并前的IO(io front merged with request on queue)
  • G: 获取请求(get request)
  • I: IO插入到请求队列(io inserted onto request queue)
  • M: 在队列中请求合并后的IO(io back merged with request on queue)
  • P: 阻塞请求(Plug request)
  • Q: IO已被请求队列处理(io handled by request queue code)
  • S: 请求睡眠(sleep request)
  • T: 拔下由于超时(unplug due to timeout)
  • U: 分发请求(unplug request)
  • X: 分拆IO(split)

根据Understanding the Linux Kernel, 3rd Edition的描述,可以确定以上的动作顺序。

Q------------>G------------>I------------>D------------>C

(SA)X?                             F&M,T&U

14.2.3. Submitting a Request

Once the bio descriptor has been properly initialized, the kernel invokes the generic_make_request( ) function, which is the main entry point of the generic block layer. The function essentially executes the following steps:

  1. Checks that bio->bi_sector does not exceed the number of sectors of the block device. If it does, the function sets the BIO_EOF flag of bio->bi_flags, prints a kernel error message, invokes the bio_endio() function, and terminates. bio_endio( ) updates the bi_size and bi_sector fields of the bio descriptor, and it invokes the bi_end_io bio's method. The implementation of the latter function essentially depends on the kernel component that has triggered the I/O data transfer; we will see some examples of bi_end_io methods in the following chapters.

  2. Gets the request queue q associated with the block device (see the section "Request Queue Descriptors" later in this chapter); its address can be found in the bd_disk field of the block device descriptor, which in turn is pointed to by the bio->bi_bdev field.

  3. Invokes block_wait_queue_running( ) to check whether the I/O scheduler currently in use is being dynamically replaced; in this case, the function puts the process to sleep until the new I/O scheduler is started (see the next section "The I/O Scheduler").

  4. Invokes blk_partition_remap( ) to check whether the block device refers to a disk partition (bio->bi_bdev not equal to bio->bi_dev->bd_contains; see the section "Block Devices" later in this chapter). In this case, the function gets the hd_struct descriptor of the partition from the bio->bi_bdev field to perform the following substeps:

    1. Updates the read_sectors and reads fields, or the write_sectors and writes fields, of the hd_struct descriptor, according to the direction of data transfer.

    2. Adjusts the bio->bi_sector field so as to transform the sector number relative to the start of the partition to a sector number relative to the whole disk.

    3. Sets the bio->bi_bdev field to the block device descriptor of the whole disk (bio->bd_contains).

    From now on, the generic block layer, the I/O scheduler, and the device driver forget about disk partitioning, and work directly with the whole disk.

  5. Invokes the q->make_request_fn method to insert the bio request in the request queue q.

  6. Returns.

14.3.5. Issuing a Request to the I/O Scheduler

As seen in the section "Submitting a Request" earlier in this chapter, the generic_make_request( ) function invokes the make_request_fn method of the request queue descriptor to transmit a request to the I/O scheduler. This method is usually implemented by the _ _make_request( ) function; it receives as its parameters a request_queue descriptor q and a bio descriptor bio, and it performs the following operations:

  1. Invokes the blk_queue_bounce( ) function to set up a bounce buffer, if required (see later). If a bounce buffer was created, the _ _make_request( ) function operates on it rather than on the original bio.

  2. Invokes the I/O scheduler function elv_queue_empty( ) to check whether there are pending requests in the request queuenotice that the dispatch queue might be empty, but other queues of the I/O scheduler might contain pending requests. If there are no pending requests, it invokes the blk_plug_device( ) function to plug the request queue (see the section "Activating the Block Device Driver" earlier in this chapter), and jumps to step 5.

  3. Here the request queue includes pending requests. Invokes the elv_merge( ) I/O scheduler function to check whether the new bio can be merged inside an existing request. The function may return three possible values:

    • ELEVATOR_NO_MERGE: the bio cannot be included in an already existing request: in that case, the function jumps to step 5.

    • ELEVATOR_BACK_MERGE: the bio might be added as the last bio of some request req: in that case, the function invokes the q->back_merge_fn method to check whether the request can be extended. If not, the function jumps to step 5. Otherwise it inserts the bio descriptor at the tail of the req's list and updates the req's fields. Then, it tries to merge the request with a following request (the new bio might fill a hole between the two requests).

    • ELEVATOR_FRONT_MERGE: the bio can be added as the first bio of some request req: in that case, the function invokes the q->front_merge_fn method to check whether the request can be extended. If not, it jumps to step 5. Otherwise, it inserts the bio descriptor at the head of the req's list and updates the req's fields. Then, the function tries to merge the request with the preceding request.

  4. The bio has been merged inside an already existing request. Jumps to step 7 to terminate the function.

  5. Here the bio must be inserted in a new request. Allocates a new request descriptor. If there is no free memory, the function suspends the current process, unless the BIO_RW_AHEAD flag in bio->bi_rw is set, which means that the I/O operation is a read-ahead (see Chapter 16); in this case, the function invokes bio_endio( ) and terminates: the data transfer will not be executed. For a description of bio_endio( ), see step 1 of generic_make_request( ) in the earlier section "Submitting a Request."

  6. Initializes the fields of the request descriptor. In particular:

    1. Initializes the various fields that store the sector numbers, the current bio, and the current segment according to the contents of the bio descriptor.

    2. Sets the REQ_CMD flag in the flags field (this is a normal read or write operation).

    3. If the page frame of the first bio segment is in low memory, it sets the buffer field to the linear address of that buffer.

    4. Sets the rq_disk field with the bio->bi_bdev->bd_disk address.

    5. Inserts the bio in the request list.

    6. Sets the start_time field to the value of jiffies.

  7. All done. Before terminating, however, it checks whether the BIO_RW_SYNC flag in bio->bi_rw is set. If so, it invokes generic_unplug_device( ) on the request queue to unplug the driver (see the section "Activating the Block Device Driver" earlier in this chapter).

  8. Terminates.

未完待续

IO在block级别的过程分析的更多相关文章

  1. Block层也是有IO的优先级的

    ---恢复内容开始--- 今天查看iotop的原理,竟然发现了IO优先级一说,IO是block层cfs调度器中的概念 block层也有一个类似于CPU的调度算法 对进程分成三个级别:RT,BE,IDL ...

  2. 限制容器的 Block IO - 每天5分钟玩转 Docker 容器技术(29)

    前面学习了如何限制容器对内存和CPU的使用,本节我们来看 Block IO. Block IO 是另一种可以限制容器使用的资源.Block IO 指的是磁盘的读写,docker 可通过设置权重.限制 ...

  3. 网络编程进阶:并发编程之协程、IO模型

    协程: 基于单线程实现并发,即只用一个主线程(此时可利用的CPU只有一个)情况下实现并发: 并发的本质:切换+保存状态 CPU正在运行一个任务,会在两种情况下切走去执行其他任务(切换有操作系统强制控制 ...

  4. 36、IO模型与socketserver实现并发

    特别声明本随笔copy于egon(林海峰). 一 IO模型介绍 为了更好地了解IO模型,我们需要事先回顾下:同步.异步.阻塞.非阻塞 同步(synchronous) IO和异步(asynchronou ...

  5. Python之IO模型

    IO模型介绍 为了更好地了解IO模型,我们需要事先回顾下:同步.异步.阻塞.非阻塞 同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞 ...

  6. 同步IO,异步IO,阻塞IO,非阻塞IO

    同步(synchronous):一个进程在执行某个任务时,另外一个进程必须等待其执行完毕,才能继续执行 #所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不会返回.按照这个定义, 其实 ...

  7. Python并发编程之IO模型

    目录 IO模型介绍 阻塞IO(blocking IO) 非阻塞IO(non-blocking IO) IO多路复用 异步IO IO模型比较分析 selectors模块 一.IO模型介绍 Stevens ...

  8. 转载博文: Py西游攻关之IO model

    Py西游攻关之IO model 转载:https://www.cnblogs.com/yuanchenqi/articles/5722574.html 事件驱动模型 上节的问题: 协程:遇到IO操作就 ...

  9. day 7-9 IO模型

    一,同步和异步,阻塞和非阻塞 同步(synchronous):一个进程在执行某个任务时,另外一个进程必须等待其执行完毕,才能继续执行 #所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就 ...

随机推荐

  1. S4 继承

    S3 系统是宽泛且灵活的,同类的 S3 对象也可能有不同的成员.但是,对于 S4 系统,就不会发生,也就是说,当我们创建一个属于某类的 S4 对象实例时,不能任意添加不在类表示中的字段.举个例子,在创 ...

  2. 雷林鹏分享:Ruby 正则表达式

    Ruby 正则表达式 正则表达式是一种特殊序列的字符,它通过使用有专门语法的模式来匹配或查找其他字符串或字符串集合. 语法 正则表达式从字面上看是一种介于斜杠之间或介于跟在 %r 后的任意分隔符之间的 ...

  3. php---------取汉字的第一个字的首字母

    开发中用到的方法,取出第一个汉字的首字母: /** * 取汉字的第一个字的首字母 * @param string $str * @return string|null */ function getF ...

  4. hdu1847sg函数

    刚开始因为没注意到f是从0开始的导致wa了几次,f遍历的时候从0到f[j]<=i 这个题只有一个子情况,求出sg值直接判断就好了 #include<map> #include< ...

  5. Spring MVC 实现跨域资源 CORS 请求

    说到 AJAX 跨域,很多人最先想到的是 JSONP.的确,JSONP 我们已经十分熟悉,也使用了多年,从本质上讲,JSONP 的原理是给页面注入一个 <script>,把远程 JavaS ...

  6. 创建对象并生成结果的3个步骤-Chapter 3 P38

    必须完成3个步骤才能创建对象并生成结果: 1 创建对象   namespace LanguageFeatures { public class Product { public int Product ...

  7. 将java打jar包成linux后台服务service

    将java打jar包成linux后台服务service 第一步:将java程序打成jar包 build.gradle配置文件中加spring-boot-gradle-plugin插件,具体配置如下(配 ...

  8. sgu 137. Funny Strings 线性同余,数论,构造 难度:3

    137. Funny Strings time limit per test: 0.25 sec. memory limit per test: 4096 KB Let's consider a st ...

  9. Mysql04

    mysql: dbs 数据库系统 bdms 数据库管理系统 bda 数据库管理员 db 数据库 dba通过dbms来操作db! 关系型数据库和非关系型数据库 登录mysql mysql -h主机地址 ...

  10. junit里面Test Case的执行顺序

    这里讨论的是junit在ant运行的情况,其他build工具应该也适用,但具体没试验过. 首先运行junit时是按照脚本中文件夹的顺序执行,如下脚本会先执行test1目录下的测试,其实是test2目录 ...