我正在为Linux中的块设备驱动程序写一个小例子。这个例子还不完整,我会逐步进行。我向blkdev_register
注册了块设备,并向alloc_disk
分配了gendisk结构。插入模块时,一切正常。它显示在 / proc / devices 中。但是,如果我想用rmmod
卸载它,它将挂起。
我发现,在模块卸载功能中,对del_gendisk
的调用导致挂起。我知道gendisk结构有一个嵌入式的kobject,它负责引用计数。这种机制阻止您在使用模块时卸载模块。但是由于我不叫add_disk
,因此不应引用该结构。
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/genhd.h>
#include <linux/blkdev.h>
#define BLKDEVNAME "blkdev_test"
#define MINORS 16
struct block_device_operations bdops = {
.owner = THIS_MODULE
};
struct blkdev {
int major;
struct gendisk *disk;
struct request_queue *queue;
} dev;
static int __init blkdev_init(void)
{
dev.major = register_blkdev( 0, BLKDEVNAME );
if( dev.major < 0 )
return -EIO;
dev.disk = alloc_disk(MINORS);
if( dev.disk == NULL )
goto DISK_ERR;
dev.disk->major = dev.major;
dev.disk->first_minor = 0;
snprintf(dev.disk->disk_name, DISK_NAME_LEN, "bd0" );
dev.disk->fops = &bdops;
// dev.disk->queue = dev.queue;
// add_disk( dev.disk );
return 0;
DISK_ERR:
unregister_blkdev( dev.major, BLKDEVNAME );
return -EIO;
}
static void __exit blkdev_exit(void)
{
del_gendisk(dev.disk);
unregister_blkdev( dev.major, BLKDEVNAME );
}
module_init(blkdev_init);
module_exit(blkdev_exit);
MODULE_LICENSE("GPL");
如果我发出命令sudo rmmod mod.ko
,那么该命令将被系统杀死。
答案 0 :(得分:0)
操作gendisk设置了gendisk结构后,您将 必须将其添加到活动磁盘列表中;通过以下方式完成:
void add_disk(struct gendisk *disk);
此呼叫后,您的设备处于活动状态。有几件事值得 注意add_disk():
add_disk() can create I/O to the device (to read partition tables and such). You should not call add_disk() until your driver is sufficiently initialized to handle requests. If you are calling add_disk() in your driver initialization routine, you should not fail the initialization process after the first call. The call to add_disk() increments the disk's reference count; if the disk structure is ever to be released, the driver is responsible for decrementing that count (with put_disk()).
是否需要从系统中删除磁盘,已完成 与:
void del_gendisk(struct gendisk *disk);
此功能清除与以下内容相关的所有信息: 给定的磁盘,通常将其从系统中删除。致电后 del_gendisk(),不会再有其他操作发送到给定的设备。 但是,驱动程序对gendisk对象的引用仍然存在。您 必须通过以下方式明确释放它:
void put_disk(struct gendisk *disk);
该调用将导致释放gendisk结构,只要没有 内核的其他部分保留对它的引用。