我正在为Linux中的块设备驱动程序编写一个小示例。这个例子还没有完成,我一步一步地前进。我用blkdev_register
注册了一个块设备,并用alloc_disk
分配了gendisk结构。当插入模块时,所有功能都很好。它出现在/proc/设备中。但是如果我想用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
,那么这个命令就会被系统杀死。
发布于 2019-06-15 14:14:37
引文:
一旦设置了gendisk结构,就必须将其添加到活动磁盘的列表中;这是通过以下方法完成的: void add_disk(struct *disk); 在此呼叫之后,您的设备处于活动状态。关于add_disk(),有几件事情值得记住: add_disk()可以为设备创建I/O (读取分区表等)。在对驱动程序进行足够初始化以处理请求之前,不应该调用add_disk()。如果在驱动程序初始化例程中调用add_disk(),则不应在第一次调用之后失败初始化过程。对add_disk()的调用增加了磁盘的引用计数;如果要释放磁盘结构,则驱动程序负责减少该计数(使用put_disk())。 如果您需要从系统中删除磁盘,这是通过以下方法完成的: void del_gendisk(struct *disk); 此函数清除与给定磁盘关联的所有信息,并通常将其从系统中删除。调用del_gendisk()之后,将不再向给定设备发送任何操作。但是,您的驱动程序对gendisk对象的引用仍然存在;您必须使用以下方法显式地释放它: void put_disk(struct *disk); 该调用将导致释放gendisk结构,只要内核中没有其他部分保留对它的引用。
https://stackoverflow.com/questions/56611035
复制相似问题