我'm reading LDD3 and messing up with the kernel source code. Currently, I' m试图完全理解 struct bio
及其用法 .
到目前为止我所读到的内容:
https://lwn.net/images/pdf/LDD3/ch16.pdf
http://www.makelinux.net/books/lkd2/ch13lev1sec3
https://lwn.net/Articles/26404/
(a part of) https://www.kernel.org/doc/Documentation/block/biodoc.txt
如果我理解正确, struct bio
描述了在块设备和系统内存之间传输某些块的请求 . 规则是单个struct bio只能引用一组连续的磁盘扇区,但系统内存可以是非连续的,并且由 <page,len,offset>
的向量表示,对吗?也就是说,单个struct bio请求 bio_sectors(bio)
(众多)扇区的读/写,从扇区 bio->bi_sector
开始 . 传输的数据大小受实际设备,设备驱动程序和/或主机适配器的限制 . 我可以通过 queue_max_hw_sectors(request_queue)
获得该限制,对吗?因此,如果我继续提交在磁盘扇区中连续的 bio
,那么I / O调度程序/电梯会将这些 bio
合并为一个sigle,直到达到该限制,对吧?
此外, bio->size
必须是512的倍数(或等效的扇区大小),以便 bio_sectors(bio)
是一个整数,对吗?
此外,这些 bio_sectors(bio)
扇区将移入/移出系统内存,而内存则指 struct page
s . 由于 <page,len,offset>
和磁盘扇区之间没有特定的映射,我假设隐式 bio->bi_io_vec
按顺序或外观提供服务 . 也就是说,第一个磁盘扇区(从 bio->bi_sector
开始)将被写入/读取到 bio->bi_io_vec[0].bv_page
然后 bio->bi_io_vec[1].pv_page
等 . 是吗?如果是这样, bio_vec->bv_len
应该始终是sector_size或512的倍数吗?由于页面通常为4096字节, bv_offset
应该是 {0,512,1024,1536,...,3584,4096}
中的一个?我的意思是,例如,从偏移量200开始请求将100字节写入页面是否有意义?
另外, bio.bio_phys_segments
的含义是什么?为什么它与 bio.bi_vcnt
不同? bio_phys_segments
定义为"The number of physical segments contained within this BIO" . 不是三重 <page,len,offset>
我们称之为'physical segment'?
最后,如果 struct bio
是如此复杂和强大,为什么我们创建 struct bio
的列表并将它们命名为 struct request
并在 request_queue
中对它们进行排队?为什么没有 bio_queue
用于存储每个 struct bio
的块设备,直到它被服务为止?
我有点困惑所以任何文档的答案或指针都将非常有用!先感谢您 :)
1 回答
通用块层可以合并不同的段 . 当内存中的页面帧和磁盘上相邻的磁盘数据块是连续的时,结果合并操作会创建一个更大的内存区域,称为物理段 .
在通过专用总线电路处理总线地址和物理地址之间的映射的体系结构上允许另一个合并操作 . 由这种合并操作产生的存储区称为硬件段 . 在总线地址和物理地址之间没有这种动态映射的80 x 86架构中,硬件段始终与物理段重合 .
bi_io_vec包含IO的页面框架 . bv_offset是页面框架中的偏移量 . 在磁盘上实际写入/读取之前,每个东西都映射到扇区,因为磁盘处理扇区 . 这并不意味着长度必须在多个扇区中 . 因此,这将导致未对齐的读/写,这由底层设备驱动程序负责 .
请求队列是每个设备结构并负责刷新 . 每个块设备都有自己的请求队列 . 生物结构是IO的通用实体 . 如果你将request_queue特征结合到bio中,那么你将创建一个单一的全局bio_queue和太重的结构 . 不是个好主意 . 所以基本上这两种结构在IO操作的上下文中起到不同的作用 .
希望能帮助到你 .