首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用rmmod (del_gendisk)卸载时,Linux块设备模块挂起。

使用rmmod (del_gendisk)卸载时,Linux块设备模块挂起。
EN

Stack Overflow用户
提问于 2019-06-15 13:59:43
回答 1查看 346关注 0票数 0

我正在为Linux中的块设备驱动程序编写一个小示例。这个例子还没有完成,我一步一步地前进。我用blkdev_register注册了一个块设备,并用alloc_disk分配了gendisk结构。当插入模块时,所有功能都很好。它出现在/proc/设备中。但是如果我想用rmmod卸载它,它就挂起了。

我发现,在模块卸载函数中,调用del_gendisk导致了挂起。我知道gendisk结构有一个嵌入的kobject,它负责引用计数。此机制妨碍您在使用模块时卸载该模块。但是,由于我不调用add_disk,所以不应该引用该结构。

代码语言:javascript
运行
复制
#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,那么这个命令就会被系统杀死。

EN

回答 1

Stack Overflow用户

发布于 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结构,只要内核中没有其他部分保留对它的引用。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56611035

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档