在内核态Block Layer访问块设备

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

为减少内核态与用户态之间大量的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
    }
}

重要的数据结构和函数

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zs.w

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值