内核块设备

时间:2018-04-11 17:21:14

标签: c linux linux-kernel linux-device-driver block-device

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

我的灵感主要来自于Linux Device Drivers, 3rd Edition这本书,它不再像2005年出版的那样完全是最新的。

无论如何,逻辑依旧存在,我从中学到了很多东西。然而,自2005年以来,许多事情发生了变化,这些例子并没有真正有效。

我找到了一个github repository,其中应该更新示例以处理最近的内核,但我认为还有一些内容需要更新,因为我无法调整示例以使其适用于内核4.9 0.0

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

初始化时:

  • 使用register_blkdev
  • 将模块注册为块设备
  • 分配设备数据缓冲区
  • 初始化spinlock
  • 初始化请求队列
  • 配置请求队列
  • 分配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字段应该是指向虚拟内核地址的指针。我想,一旦这个缓冲区填满/读取,内核就会处理数据到用户空间的传输。

我有点失落,因为如果请求不再提供内核虚拟地址,我就无法找到它。

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

1 个答案:

答案 0 :(得分:4)

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

  

阻止:删除struct request buffer member

     

这是在古代使用的,当洋葱适当时      黄色。基本上它映射到当前缓冲区      转移。随着十多年前加入highmem,      大多数司机将页面映射为生物,而rq->buffer则不是      指着任何有效的东西。

     

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

有一些很好的资源可供阅读BIO,例如lwn上的this post。相关摘录:

  

char *bio_data(struct bio *bio)

     

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

因此,使用bio_data(rq->bio)代替rq->buffer,您将获得更多成功。

按作者编辑:
还找到了this link,它分为两部分,第一部分是生物层,第二部分是请求层。