6

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

我的灵感主要来自《Linux Device Drivers, 3rd Edition 》一书,该书已于 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;
}

但是在编译时出现以下错误:

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));

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

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

我有点迷茫,因为如果请求不再提供内核虚拟地址,我找不到应该在哪里找到内核虚拟地址。

我怎么知道在哪里传输数据?

4

1 回答 1

4

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

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

这是在过去使用的,当时洋葱是适当的黄色。基本上它映射到要传输的当前缓冲区。随着 highmem 十多年前被添加,大多数驱动程序从 bio 中映射页面,并且rq->buffer没有指向任何有效的东西。

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

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

char *bio_data(struct bio *bio)

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

所以看起来你会bio_data(rq->bio)rq->buffer.

作者编辑:
还发现这个链接分为两部分,第一部分是生物层,第二部分是请求层。

于 2018-04-11T18:16:52.723 回答