目录
背景
解决方案
具体实现
编译
卸载异常驱动
在进行驱动编程的时候, 如果驱动出现了异常, insmod、 rmmod、 或者使用过程中出现了异常, 那么导致系统的驱动加载了, 但是却无法被卸载, 或者卸载时出错,如下错误:rmmod: ERROR: Module kerneloops is in use.
通过force_rmmod外部驱动模块强制卸载异常驱动.
#include#include #include #include #include #include #include #include #include /* * 加载模块的时候, 传递字符串到模块的一个全局字符数组里面 * * module_param_string(name, string, len, perm) * * @name 在加载模块时,参数的名字 * @string 模块内部的字符数组的名字 * @len 模块内部的字符数组的大小 * #perm 访问权限 * * */ static char *modname = NULL; module_param(modname, charp, 0644); MODULE_PARM_DESC(modname, "The name of module you want do clean or delete...\n"); static int force_cleanup_module(char *del_mod_name) { struct module *mod = NULL, *relate = NULL; int cpu; // 方法一, 遍历内核模块树list_mod查询 struct module *list_mod = NULL; /* 遍历模块列表, 查找 del_mod_name 模块 */ list_for_each_entry(list_mod, THIS_MODULE->list.prev, list) { if (strcmp(list_mod->name, del_mod_name) == 0) { mod = list_mod; } } /* 如果未找到 del_mod_name 则直接退出 */ if(mod == NULL){ printk("[%s] module %s not found\n", THIS_MODULE->name, modname); return -1; } // 如果有其他驱动依赖于当前驱动, 则不能强制卸载, 立刻退出 /* 如果有其他模块依赖于 del_mod */ if (!list_empty(&mod->source_list)){ /* 打印出所有依赖target的模块名 */ list_for_each_entry(relate, &mod->source_list, source_list){ printk("[relate]:%s\n", relate->name); } } else { printk("No modules depond on %s...\n", del_mod_name); } // 清除驱动的状态和引用计数 // 修正驱动的状态为LIVE mod->state = MODULE_STATE_LIVE; // 清除驱动的引用计数 for_each_possible_cpu(cpu) { local_set((local_t*)per_cpu_ptr(&(mod->refcnt), cpu), 0); } atomic_set(&mod->refcnt, 1); printk("[after] name:%s, state:%d, refcnt:%u\n", mod->name, mod->state, module_refcount(mod)); return 0; } static int __init force_rmmod_init(void) { return force_cleanup_module(modname); } static void __exit force_rmmod_exit(void) { printk("name : %s, state : %d EXIT \n", THIS_MODULE->name, THIS_MODULE->state); } module_init(force_rmmod_init); module_exit(force_rmmod_exit); MODULE_LICENSE("GPL");
#KERNELDIR := /home/scs/project/linux-6.1.18 KERNELDIR := /lib/modules/$(shell uname -r)/build CURRENT_PATH := $(shell pwd) obj-m := force_rmmod.o build: kernel_modules kernel_modules: $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules clean: $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean
sudo insmod force_rmmod.ko modname=异常驱动名