我目前正在尝试实现一个(不是那个?)简单的内核块设备驱动程序。
我的灵感主要来自于2005年出版的“Linux设备驱动程序,第3版”一书,这本书已经不完全是最新的了。
不管怎样,逻辑仍然存在,我从中学到了很多。然而,例子并没有真正有效,因为自2005年以来,许多事情都发生了变化。
我找到了一个github储存库,其中的示例应该更新以在最近的内核上工作,但我认为仍然有一些东西需要更新,因为我无法调整示例使其在内核4.9.0上工作。
这里是我的模块的制作方式:
初始化时:
register_blkdev将模块注册为块设备gendisk结构gendisk结构add_disk创建磁盘然后,我实现了一个函数来处理来自请求队列的请求事件,并处理块设备上的读和写事件。
这是一个函数:(它是从LLD-3的高度灵感,经过一些修改,以匹配当前的内核函数)
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字段应该是一个指向虚拟内核地址的指针。我认为,一旦这个缓冲区填充/读取,内核将处理数据到/从用户空间的传输。
我有点迷路了,因为如果请求不再给出内核虚拟地址,我就找不到它的位置了。
我怎么知道在哪里传输数据?
发布于 2018-04-11 18:16:52
由明磊撰写的包含罪魁祸首变更的提交消息:
块:删除struct请求缓冲区成员 这是在过去的日子里使用,当洋葱是适当的黄色。基本上,它映射到要传输的当前缓冲区。随着10多年前就添加了highmem,大多数驱动程序都会从bio中映射页面,而
rq->buffer并没有指出任何有效的东西。 将旧风格的驱动程序转换为只使用bio_data()。
有一些很好的资源可供阅读有关生物,如这个职位 on lwn。相关片段:
char *bio_data(struct bio *bio)关联返回数据缓冲区的内核虚拟地址。
因此,使用bio_data(rq->bio)代替rq->buffer似乎会取得更大的成功。
编辑作者:
发现此链接分为两部分,第一部分是生物层,第二部分是请求层。
https://stackoverflow.com/questions/49781081
复制相似问题