You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux内核模块中如何通过struct gendisk读取磁盘指定已知扇区

持有struct gendisk指针读取指定扇区的实现步骤

前置检查

  • 首先获取磁盘的逻辑块大小,确认访问对齐:
    逻辑块大小通过queue_logical_block_size(gendisk->queue)获取,你要读取的起始扇区偏移、总读取长度必须和该值对齐,否则IO会直接报错。注意内核默认的bi_sector字段以512B为单位,如果你要读取的扇区单位是4K,需要提前做单位转换。

核心实现流程

我们以最简单的同步读场景为例(适用于进程上下文,允许阻塞):

  1. 分配IO所需的内存页
    读取到的数据会存在这个页里,单页最大支持4K读取,如果你要读更长的内容可以分配多个页:
    struct page *page = alloc_page(GFP_KERNEL);
    if (!page) {
        // 处理分配失败逻辑
        return -ENOMEM;
    }
    
  2. 分配并初始化bio结构体
    bio是内核块IO的核心载体:
    struct bio *bio = bio_alloc(gendisk->queue, 1, GFP_KERNEL);
    if (!bio) {
        __free_page(page);
        return -ENOMEM;
    }
    bio_set_dev(bio, gendisk->bdi->dev);
    // 替换成你要读取的目标扇区号(512B为单位)
    bio->bi_iter.bi_sector = target_sector;
    // 把页挂载到bio上,这里的读取长度按你实际需求填,最大为PAGE_SIZE
    if (!bio_add_page(bio, page, read_len, 0)) {
        bio_put(bio);
        __free_page(page);
        return -EINVAL;
    }
    
  3. 提交同步IO请求
    5.10及之后的内核可以直接用submit_bio_wait简化操作,不需要手动写回调:
    int ret = submit_bio_wait(REQ_OP_READ, bio);
    if (ret) {
        // IO执行失败,处理错误
        bio_put(bio);
        __free_page(page);
        return ret;
    }
    
    如果是更老的内核,需要自己定义完成量和end_io回调来等待IO完成,示例回调如下:
    static void bio_read_end_io(struct bio *bio)
    {
        complete(bio->bi_private);
        bio_put(bio);
    }
    // 提交逻辑
    DECLARE_COMPLETION_ONSTACK(bio_done);
    bio->bi_end_io = bio_read_end_io;
    bio->bi_private = &bio_done;
    submit_bio(REQ_OP_READ, bio);
    wait_for_completion(&bio_done);
    // 检查bio状态判断是否成功
    
  4. 读取数据并释放资源
    IO成功之后就可以映射页到内核地址空间访问数据了:
    void *data_buf = kmap(page);
    // 这里直接访问data_buf就可以拿到读取到的扇区内容
    // 访问完成后释放资源
    kunmap(page);
    __free_page(page);
    bio_put(bio);
    

注意事项

  • 不要在原子上下文(比如中断处理、持有自旋锁)中调用同步IO接口,这类场景必须使用异步回调处理IO结果,避免阻塞内核。
  • 如果要读取的长度超过4K,你可以给bio添加多个页,或者拆分多个bio分批提交。
  • 所有错误分支都要记得释放已经分配的资源,避免内核内存泄漏。

内容的提问来源于stack exchange,提问作者K_K

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.10 03:24:02