内核块设备

Ark*_*aik 6 c linux linux-device-driver linux-kernel block-device

我目前正在尝试实现一个(不是那个?)简单的内核块设备驱动程序.

我的灵感主要来自Linux设备驱动程序,第3版,这本书在2005年发布时已不再完全更新了.

无论如何,逻辑仍然存在,我从中学到了很多东西.然而,自2005年以来,许多事情都发生了变化,因此实例并不真

我找到了一个github存储库,其中应该更新示例以处理最近的内核,但我认为还有一些事情需要更新,因为我无法调整示例以使其在内核4.9.0运行

以下是我的模块的制作方法:

初始化时:

  • 将模块注册为块设备 register_blkdev
  • 分配设备数据缓冲区
  • 初始化自旋锁
  • 初始化请求队列
  • 配置请求队列
  • 分配gendisk结构
  • 填充gendisk结构
  • 使用创建磁盘 add_disk

然后我实现了一个函数来处理来自请求队列的请求事件,并处理块设备上的读写事件.

这是函数:(它受LLD-3rd的高度启发,经过一些修改以匹配当前的内核函数)

static void block_mod_request(struct request_queue *queue)
{
    printk(KERN_NOTICE "Entering request function\n");
    struct request *request;

    while(NULL != (request = blk_fetch_request(queue)))
    {
        blk_mod_t *self = request->rq_disk->private_data;
        // Check if request is a filesystem request (i.e. moves block of data)
        if(REQ_TYPE_FS != request->cmd_type)
        {
            // Close request with unsuccessful status
            printk(KERN_WARNING "Skip non-fs request\n");
            __blk_end_request_cur(request, -EIO);
            continue;
        }
        // Treat request
        block_mod_transfer(self, blk_rq_pos(request), blk_rq_cur_sectors(request), request->buffer, rq_data_dir(request));
        // Close request with successful status
        __blk_end_request_cur(request, 0);
    }
    return;
}
Run Code Online (Sandbox Code Playgroud)

但是在编译时我收到以下错误:

block_mod.c:82:91: error: ‘struct request’ has no member named ‘buffer’
         block_mod_transfer(self, blk_rq_pos(request), blk_rq_cur_sectors(request), request->buffer, rq_data_dir(request));
Run Code Online (Sandbox Code Playgroud)

将文件检blkdev.h入内核v4.9.0头文件后,似乎该字段buffer不再存在struct request.
但是,我无法找到有关事情如何演变以及如何修改代码以使其工作的任何信息.

如果我理解得很好,该buffer字段应该是指向虚拟内核地址的指针.我想,一旦这个缓冲区填满/读取,内核就会处理向/从用户空间传输数据.

我有点失落,因为如果请求不再提供,我找不到内核虚拟地址的位置.

我怎么知道在哪里转移数据?

小智 4

来自包含罪魁祸首更改的提交的消息,由 Ming Lei 撰写:

块:删除结构请求缓冲区成员

这是在过去使用的,当时洋葱是适当的黄色。基本上它映射到当前要传输的缓冲区。十多年前就添加了 highmem,大多数驱动程序都会从​​个人简介中映射页面,并且rq->buffer不会指向任何有效的内容。

将旧式驱动程序转换为仅使用bio_data().

有一些关于 BIO 的好资源可供阅读,例如lwn 上的这篇文章。相关片段:

char *bio_data(struct bio *bio)

  返回数据缓冲区的内核虚拟地址。

所以看来你使用bio_data(rq->bio)代替会取得更大的成功rq->buffer

作者编辑:
还找到了此链接,该链接分为两部分,第一部分呈现生物层,第二部分呈现请求层。