说明:当一个模块加载失败(killed)或者模块被堵塞了,使用rmmod无法卸载,这时只能强制清除了。
方法一
直接重启系统,因为insmod是临时加入系统的,重启后会被消除。
方法二
解决方案是改变该模块的状态。(适用于内核2.6及其以后的版本)
1.把下面代码中的字符串变为要删除的模块名const char target[100] = “device”;//这是你要删除模块的名字;(其实可以通过外部传参方式实现,但因该方式是强制,如果参数有误,会把其他模块删除且不可逆,所以采用修改代码方式)
2.把下面代码像驱动一样加载进入内核,根据打印log可以看得到是否删除模块成功。
代码如下:
#include<linux/init.h>
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/list.h>
#include<linux/cpumask.h>
const char target[100] = "device";//这是你要删除模块的名字
static int __init mymod_init(void)
{
struct module *mod,*relate;
int cpu;
// 打印本模块的模块名和模块状态
printk(KERN_ALERT"[insmod mymod] name:%s state:%d\n",THIS_MODULE->name,THIS_MODULE->state);
// 遍历模块列表,查找target模块
list_for_each_entry(mod,THIS_MODULE->list.prev,list)
{
if(strcmp(mod->name,target)==0)
{
// 打印target的模块名、模块状态、引用计数
printk(KERN_ALERT"name:%s state:%d refcnt:%u ",mod->name,mod->state,module_refcount(mod));
// 打印出所有依赖target的模块名
if(!list_empty(&mod->source_list)) {
list_for_each_entry(relate,&mod->source_list,source_list)
printk(KERN_ALERT"%s ",relate->name);
}
else
printk(KERN_ALERT"used by NULL\n");
// 修正驱动的状态为LIVE
mod->state = MODULE_STATE_LIVE;
// 把target的引用计数置为0
unsigned int i = module_refcount(mod);
for(i;i>0;i--)
{
module_put(mod); //引用计数减一
}
// 再看看target的名称、状态、引用计数
printk(KERN_ALERT"name:%s state:%d refcnt:%u\n",mod->name,mod->state,module_refcount(mod));
}
}
return 0;
}
static void __exit mymod_exit(void)
{
printk(KERN_ALERT"[rmmod mymod] name:%s state:%d\n",THIS_MODULE->name,THIS_MODULE->state);
}
module_init(mymod_init);
module_exit(mymod_exit);
MODULE_AUTHOR("jack");
MODULE_LICENSE("GPL");
注:第二种方法的代码不是原创(原创地址我找不到了抱歉,原代码适用于2.4版本),而是进行二次修改而得,如果有所侵权,请您联系我,立即删除。