在参考一些设备驱动书籍、网上资料实现一个软块设备时,即使把它们的提供的代码原封不动地照抄,一编译,错误满屏。简单看了下,发现是多数是“查无此人”。显然是内核版本不对了。比如blk_init_queue()就被新版内核弃用了。
首先先去https://kernel.org下载一个旧版本的内核如2.6.10.
然后找到blk_init_queue(),可以发现,它是作为一个高级接口,基于请求、请求队列等结构体的一些冗余字段和一些操作函数做了很多额外的工作从而实现制造请求、进出队列等等过程。
新版内核(如5.4.20)去除了这些高级接口以及简化了相关的结构体的字段,让驱动开发者自己来实现这些功能。
因此,我们还是可以参考旧版的操作,基于新版的内核实现blk_init_queue()的功能。
实现代码示例:
static void _transfer(_dev_t *dev, unsigned long sector, unsigned long nsect, char* buffer, int write)
{
unsigned long offset = sector * 512;
unsigned long nbytes = nsect * 512;
if((offset + nbytes) > dev->size)
{
return;
}
if(write)
{
memcpy(dev->data + offset, nbytes); //data是分配好的内存块,相当于扇区
}
}
blk_qc_t request_process(struct request_queue *q, struct bio *bio)
{
struct bvec_iter i;
struct bio_vec bvec;
sector_t sector = 0;
unsigned long nsect = 0;
bio_for_each_segment(bvec,bio,i)
{
char *buffer = kmap(bvec.bv_page) + bvec.bv_offset;
sector = i.bi_sector;
nsect = bvec.bv_len >> 9;
_transfer(&ofafdev, sector, nsect,
buffer, bio_data_dir(bio) == WRITE);
kunmap(bvec.bv_page);
}
bio_endio(bio);
return 0;
}
//gendisk注册部分代码
disk->queue = blk_alloc_queue(GFP_KERNEL); //替代blk_init_queue()
blk_queue_make_request(disk->queue, reqeust_process);