Linux块设备驱动(二)请求

与请求处理相关的几个数据结构:
struct request_queue
struct request
struct bio
一个bio对应上层传递的I/O请求,I/O调度算法会把多个bio合并为一个request,多个request又构成了request_queue,request_queue是上节提到的gendisk结构中的成员。
bio的定义:

struct bio {
	struct bio  *bi_next; /* request queue link */
 	struct block_device *bi_bdev;
	unsigned long  bi_flags; /* status, command, etc */
	unsigned long  bi_rw;  /* bottom bits READ/WRITE,
       					* top bits priority
       					*/
       	struct bvec_iter bi_iter;
       	
       	/* Number of segments in this BIO after
  	* physical address coalescing is performed.
 	 */
 	 unsigned int  bi_phys_segments;
 	 ...
 	 struct bio_vec  *bi_io_vec; /* the actual vec list */
 	 struct bio_set  *bi_pool;
 	 ...
}

其中bio_vec用来描述与bio对应的内存,这些bio_vec可能不在同一数据页中,所以要用向量(bi_io_vec)来表示,bio_vec的定义为:

struct bio_vec {
 	struct page *bv_page;
 	unsigned int bv_len;
 	unsigned int bv_offset;
};

bvec_iter是用来遍历bio的迭代器,记录了当前bi_io_vec的处理情况

struct bvec_iter {
	sector_t  bi_sector; /* device address in 512 byte sectors */
	unsigned int  bi_size; /* residual I/O count */
	unsigned int  bi_idx;  /* current index into bvl_vec */
	unsigned int bi_bvec_done; /* number of bytes completed in current bvec */
};

宏定义__rq_for_each_bio()用来遍历一个请求的所有bio

#define __rq_for_each_bio(_bio, rq)

宏定义bio_for_each_segment()遍历一个bio所有的bio_vec。

#define bio_for_each_segment(bvl, bio, iter)    

简单来说,请求处理就是在请求对应的内存和磁盘之间进行数据传输,传输数据需要知道请求的内存数据页,磁盘的扇区地址和传输的数据量这三个要素。
通过宏定义__bio_kmap_atomic()将bio_vec的页映射为内核的虚拟地址

__bio_kmap_atomic(bio, iter)

例如:char *buf = __bio_kmap_atomic(bio, iter);
对应的,用宏定义__bio_kunmap_atomic(addr)来解除映射

#define __bio_kunmap_atomic(addr)

例如:__bio_kunmap_atomic(buf)

磁盘的扇区地址由bvec_iter的bi_sector成员获得
传输的数据量可以由函数bio_cur_bytes()获得

static inline unsigned int bio_cur_bytes(struct bio *bio);

综上所述,我们可以得出请求处理的方法:
遍历一个请求的所有bio,再遍历一个bio的所有bio_vec,得到数据传输的三个主要参数,再根据实际情况完成数据的读写。

你可能感兴趣的:(嵌入式Linux驱动)