void blk_start_queue(request_queue_t* queue);
//参数设置
void blk_queue_max_sectors(request_queue_t* q, unsigned short max);
/*请求可包含的最大扇区数.默认255*/
void blk_queue_max_phys_segments(request_queue_t* q, unsigned short max);
void blk_queue_max_hw_segments(request_queue_t* q, unsigned short max);
/*这两个函数设置一个请求可包含的最大物理段数(系统内存中不相邻的区),缺省是128*/
void blk_queue_max_segment_size(request_queue_t* q, unsigned int max);
/*告知内核请求短的最大字节数,默认2^16 = 65536*/
//通告内核
void blk_queue_bounce_limit(request_queue_t* queue, u64 dma_addr);
/*
* 此函数告知内核设备执行DMA时,可使用的最高物理地址dma_addr,常用的宏如下:
* BLK_BOUNCE_HIGH:对高端内存页使用反弹缓冲(缺省)
* BLK_BOUNCE_ISA:驱动只可以在MB的ISA区执行DMA
* BLK_BOUNCE_ANY:驱动可在任何地方执行DMA
*/
blk_queue_segment_boundary(request_queue_t* queue, unsigned long mask);
/*这个函数在设备无法处理跨越一个特殊大小内存边界的请求时,告知内核这个边界.*/
void blk_queue_dma_alignment(request_queue_t* q, int mask);
/*告知内核设备加于DMA传送的内存对齐限制*/
viod blk_queue_hardsect_size(request_queue_t* q, unsigned short max);
/*此函数告知内核块设备硬件扇区大小*/
块IO(bio)结构体:
通常一个bio对应一个IO请求,IO调度算法可以将连续的bio合并成一个请求,所以一个请求包含多个bio
struct bio {
sector_t bi_sector; /* device address in 512 byte sectors */
struct bio *bi_next; /* request queue link */
struct block_device *bi_bdev;
/*如果是一个写请求,最低有效位被置位,可使用bio_data_dir(bio)宏来获取读写方向*/
unsigned long bi_flags; /* status, command, etc */
unsigned long bi_rw; /* 低位代表:READ/WRITE,高位代表:优先级 */
unsigned short bi_vcnt; /* how many bio_vec's (bio_vec的数量)*/
unsigned short bi_idx; /* current index into bvl_vec(当前bio_vec的索引) */
/*不相邻的物理段的数目*/
unsigned short bi_phys_segments;
/*物理合并和DMA remap合并后不相邻的物理扇区*/
unsigned short bi_hw_segments;
/*被传送的数据大小(byte),用bio_sector(bio)获取扇区为单位的大小*/
unsigned int bi_size; /* residual I/O count */
/*被传送的数据大小(byte),用bio_sector(bio)获取扇区为单位的大小*/
/*为了明了最大的hw尺寸,考虑bio中第一个和最后一个虚拟的可合并的段的尺寸*/
unsigned int bi_hw_front_size;
unsigned int bi_hw_back_size;
unsigned int bi_max_vecs; /*能持有的最大bvl_vecs数*/
struct bio_vec *bi_io_vec; /*能持有的最大bvl_vecs数*/
...................
}
struct bio_vec {
struct page *bv_page; /*要操作的页指针*/
unsigned int bv_len; /*要传输的字节数*/
unsigned int bv_offset;/*偏移位置*/
};
/*一般不直接访问bio的bio_vec成员,而使用bio_for_each_segment()宏进行操作.
*该宏循环遍历整个bio中的每个段.
*/
#define __bio_for_each_segment(bvl, bio, i, start_idx)\
for(
bvl = bio_iovec_idx((bio),(start_idx)),i = (start_idx);\
i <(bio)->bi_vcnt;\
bvl++, i++\
)
#define bio_for_each_segment(bvl, bio, i)\
__bio_for_each_segment(bvl, bio, i, (bio)->bi_idx)
在内核中,提供了一组函数(宏)用于操作bio:
int bio_data_dir(struct bio* bio);
该函数用于获得数据传送方向.
struct page* bio_page(struct bio* bio);
该函数用于获得目前的页指针.
int bio_offset(struct bio* bio);
该函数返回操作对应的当前页的页内偏移,通常块IO操作本身就是页对齐的.
int bio_cur_sectors(struct bio* bio);
该函数返回当前bio_vec要传输的扇区数.
char* bio_data(struct bio* bio);
该函数返回数据缓冲区的内核虚拟地址.
char* bvec_kmap_irq(struct bio_vec* bvec, unsigned long* offset);
该函数也返回一个内核虚拟地址此地址可用于存取被给定的bio_vec入口指向的数据缓冲区.同时会屏蔽中断并返回一个原子kmap,因此,在此函数调用之前,驱动不应该是睡眠状态.
void bvec_kunmap_irq(char* buffer, unsigned long flags