为减少内核态与用户态之间大量的copy_from/to_user 内存拷贝以及定制I/O软件流程,可以在内核态直接访问块设备。
代码示例
struct block_device *blkdev = blk_get_by_path("/dev/block/by-name/boot", FMODE_READ, THIS_MODULE);
loff_t blkdev_size = i_size_read(blkdev->bd_inode);
#define MAX_BIOVEC 256
struct bio_vec bio_vec[MAX_BIOVEC];
struct page* page_buffer[MAX_BIOVEC];
for (i = 0; i < MAX_BIOVEC; i++) {
page_buffer[i] = alloc_page(GFP_KERNEL);
}
注:每个 struct bio_vec 只能指向一个 page 或者多个物理内存连续的 pages;
struct bio *bio = bio_alloc(GFP_KERNEL, 1);
loff_t page_count = blkdev_size / PAGE_SIZE;
for (page_off = 0; page_off < page_count; page_off += MAX_BIOVEC) {
loff_t read_pages = (page_off+MAX_BIOVEC) > page_count? page_count - page_off : MAX_BIOVEC;
bio_reset(bio);
bio_init(bio, bio_vec, read_pages);
bio_set_dev(bio, blkdev);
for (i = 0; i < read_pages; i++) {
bio_add_page(bio, page_buffer[i], PAGE_SIZE, 0);
}
bio->bi_iter.bi_sector = page_off * (PAGE_SIZE / 512);
bio_set_op_attrs(bio, REQ_OP_READ | REQ_SYNC, 0);
submit_bio_wait(bio);
struct bio_vec bvec;
struct bvec_iter iter;
bio_for_each_bvec(bvec, bio, iter) {
// bvec.bv_page
// bvec.bv_len
}
}

文章介绍了如何通过在内核态直接操作块设备来减少内核态与用户态之间的内存拷贝,从而提高效率。通过使用bio_vec和page_buffer等数据结构,构建并提交bio进行I/O操作,同时展示了如何遍历和处理bio_vec的代码示例。这种方法优化了I/O软件流程,简化了驱动程序代码,并允许更灵活地处理部分完成的bio。
最低0.47元/天 解锁文章
1154

被折叠的 条评论
为什么被折叠?



