Linux kernel 从内核模块访问块设备

Linux kernel 从内核模块访问块设备,linux-kernel,block,device,Linux Kernel,Block,Device,我感兴趣的是开发一个内核模块,它将两个块设备绑定到一个新的块设备中,第一个块设备在装载时包含数据,而另一个块设备被认为是空的。每次写入都是对第二个分区进行的,所以在下一次装载时,基本文件系统保持不变。我知道像UnionFS这样的解决方案,但它们都是基于文件系统的,而我想把它开发成一个低层、基于块的解决方案 有人能告诉我如何从内核模块打开ad读/写块设备吗?可能不使用用户空间程序读取/写入合并块设备。我发现了类似的主题,但答案相当令人不满意,因为filp_*函数更适合读取小配置文件,而不是(大)块

我感兴趣的是开发一个内核模块,它将两个块设备绑定到一个新的块设备中,第一个块设备在装载时包含数据,而另一个块设备被认为是空的。每次写入都是对第二个分区进行的,所以在下一次装载时,基本文件系统保持不变。我知道像UnionFS这样的解决方案,但它们都是基于文件系统的,而我想把它开发成一个低层、基于块的解决方案

有人能告诉我如何从内核模块打开ad读/写块设备吗?可能不使用用户空间程序读取/写入合并块设备。我发现了类似的主题,但答案相当令人不满意,因为filp_*函数更适合读取小配置文件,而不是(大)块设备I/O

由于创建块设备的接口是标准化的,所以我考虑直接(或几乎直接)访问实现源设备的函数,因为我将被要求导出类似的函数。如果我能做到这一点,我只需要在源设备上创建一些调用适当函数的代理函数。我能否以某种方式获得指向属于不同驱动程序的gendisk结构的指针

这只服务于我自己的目的(满足quriosity是其中的主要目的),所以我不担心严重弄乱我的内核


或者有人知道这样的模块是否已经存在吗?

您知道,如果您是GPL的内核模块,您可以从内核模式调用open()、read()、write()等,对吗


当然,这种方法有一些警告,包括需要从内核模式分叉来为句柄创建生存空间。

考虑检查
dm
/
md
drivers/md中块设备的代码。这些现有驱动程序创建一个块设备,用于在其他块设备上存储数据


事实上,您可以在
md
中将您的想法作为另一个“RAID个性”来实现,从而利用现有的用户空间工具来设置设备。

设备映射器驱动程序中的源代码将满足您的需要。查看Linux/drivers/md/dm-*中Linux源代码中的代码

您不需要访问其他设备的gendisk结构,而是访问其请求队列。您可以准备I/O请求并将其下推到其他设备的队列中,其余的由它自己完成

我实现了一个简单的块设备,可以打开另一个块设备。请看我描述它的帖子:

下面是访问其他设备的gendisk所需的一些函数示例。 使用另一块设备的路径(“/dev/”)打开另一块设备的方法:

struct block_device*bdev_raw=lookup_bdev(dev_路径);
printk(“打开的%s\n”,开发路径);
如果(是错误的(未加工的))
{
printk(“stackbd:error opening raw device\n”,PTR_ERR(bdev_raw));
返回NULL;
}
如果(!bdget(bdev_raw->bd_dev))
{
printk(“stackbd:error bdget()\n”);
返回NULL;
}
if(blkdev_get(bdev_原始、STACKBD_bdev_模式和STACKBD))
{
printk(“stackbd:error blkdev_get()\n”);
bdput(bdev_原始);
返回NULL;
}
将I/O请求从一个设备传递到另一个设备的最简单示例是在不修改的情况下重新映射它。请注意,在下面的代码中,bi_bdev条目是用不同的设备修改的。还可以修改块地址(*bi_扇区)和数据本身

static void stackbd\u io\u fn(结构bio*bio)
{
bio->bi_bdev=stackbd.bdev_raw;
trace_block_bio_remap(bdev_get_队列(stackbd.bdev_raw)),bio,
bio->bi_bdev->bd_开发,bio->bi_部门);
/*不需要调用bio_endio()*/
通用申请(bio);
}

似乎md是一个很好的起点-至少可以看看我应该使用什么方法访问其他块设备。我怀疑我所需要的功能是否也可用-我将检查它。