btt User Guide在百度找了3天没找到,bing也不行,结果google第一页第5个结果就是。
可恶的GFW
参见:
http://www.fis.unipr.it/doc/blktrace-1.0.1/blktrace.pdf
https://allstar.jhuapl.edu/repo/p1/amd64/blktrace/doc/blktrace.pdf
https://github.com/efarrer/blktrace/blob/master/README
通过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)
图片引自https://blog.csdn.net/Z_Stand/article/details/103302112
根据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:
-
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.
-
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.
-
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").
-
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:
-
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.
-
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.
-
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.
-
-
Invokes the q->make_request_fn method to insert the bio request in the request queue q.
-
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:
-
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.
-
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.
-
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.
-
-
The bio has been merged inside an already existing request. Jumps to step 7 to terminate the function.
-
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."
-
Initializes the fields of the request descriptor. In particular:
-
Initializes the various fields that store the sector numbers, the current bio, and the current segment according to the contents of the bio descriptor.
-
Sets the REQ_CMD flag in the flags field (this is a normal read or write operation).
-
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.
-
Sets the rq_disk field with the bio->bi_bdev->bd_disk address.
-
Inserts the bio in the request list.
-
Sets the start_time field to the value of jiffies.
-
-
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).
-
Terminates.
未完待续
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具