bio结构简介
bio结构就是kernel中block I/O的基础容器,它是在”linux/bio.h”中被定义的。这个结构将当前激活的block I/O操作表示为一个segment的list。segment就是内存中一块连续的buffer。因此,个别的buffer在内存中不需要连续。为了使buffer可以组成块,bio结构可以将内存多处组成一个buffer,并使kernel在该buffer上进行block I/O操作。这样的I/O被称为scatter-gather I/O。
bio的struct分析
下面是在”linux/bio.h”中定义的bio的struct:
struct bio {
sector_t bi_sector; /* associated sector on disk */
struct bio *bi_next; /* list of requests */
struct block_device *bi_bdev; /* associated block device */
unsigned long bi_flags; /* status and command flags */
unsigned long bi_rw; /* read or write? */
unsigned short bi_vcnt; /* number of bio_vecs off */
unsigned short bi_idx; /* current index in bi_io_vec */
unsigned short bi_phys_segments; /* number of segments after coalescing */
unsigned short bi_hw_segments; /* number of segments after remapping */
unsigned int bi_size; /* I/O count */
unsigned int bi_hw_front_size; /* size of the first mergeable segment */
unsigned int bi_hw_back_size; /* size of the last mergeable segment */
unsigned int bi_max_vecs; /* maximum bio_vecs possible */
struct bio_vec *bi_io_vec; /* bio_vec list */
bio_end_io_t *bi_end_io; /* I/O completion method */
atomic_t bi_cnt; /* usage counter */
void *bi_private; /* owner-private method */
bio_destructor_t *bi_destructor; /* destructor method */
};
bio结构的主要作用就是表示一个正在使用的block I/O操作。因此,在这个结构中最重要的属性是与日常管理相关的,分别是bi_io_vecs, bi_vcnt和bi_idx。下图中展示了struct bio, strcut bio_vec与struct page之间的联系:
其中,bi_io_vecs属性指向了一个bio_vec结构的数组。这些结构用于表示一列特殊block I/O操作的特定segments。每一个bio_vec都是一个”page, offset, len”形式的向量,描述了一个特定的segment。其中的page表示这个segment所在的物理页,offset表示这个block相对于所在页的偏移量,len则是这个block从该偏移量开始的长度。由这些向量组成的整个数组表示了这个完整的buffer。
bio_vec结构在”linux/bio.h”中是这样被定义的:
struct bio_vec {
/* pointer to the physical page on which this buffer resides */
struct page *bv_page;
/* the length in bytes of this buffer */
unsigned int bv_len;
/* the byte offset within the page where the buffer resides */
unsigned int bv_offset;
};
对于每个给定的block I/O操作,在bio_vec数组中,都会有从bi_io_vecs开始的bi_vcnt向量。当这个block i/o操作被执行,bi_idx属性就会是想数组中当前的index。
总的来说,每一个block I/O请求都会被一个bio结构表示。每一个请求都由一个或多个block组成,并存储在一组bio_vec结构中。这些结构用向量表示,并描述了每个segment在内存物理页中的地址。I/O操作中的第一个setment使用b_io_vec进行指引。之后添加的segment都连接在第一个segment之后,形成segment的list: bi_vcnt。当block I/O层在请求中提交segments,bi_idx属性就会被更新并指向当前的segment。