关于模块insmod和rmmod出错的解决方案
来源:互联网 发布:铁路数据服务平台 编辑:程序博客网 时间:2024/06/04 19:11
问题描述
这两天在学习Linux内核的时候遇到了一个让人抓狂的问题,问题如下: 在编写内核模块时,代码中出现错误,但是编译器并没有检查出来,比如一些内存的问题,访问了空指针等,我遇到的是不小心对一个NULL指针进行了赋值比较,导致在insmod **.ko的时候出现了错误,第一次直接提示KILL(或已杀死)。当不明所以地第二次insmod的时候会阻塞,应该说卡死在那里吧(即使已经把代码修改成功)。
问题分析
因为代码的原因导致这个问题的发生是很可悲的啊,通过lsmod查看已加载的模块,会发现之前insmod的模块已经存在,但是无法卸载,而且引用计数不为0。再通过cat /proc/modules 看到此模块的状态为loading,而不是living。所以要卸载此模块,就需要将这两个东西修改掉,将状态和引用计数都修改为0。
问题解决
找到问题,分析完问题,就可以开始解决问题了。 由于通过手动insmod加载的module是临时的,所以通过重启机器是能够结果上述问题的,但是我们不能每次都重启吧,所以我们再编写一个模块,通过insmod这个模块来修改那个错误模块的相关属性。 通过查看内核源码,看到struct module结构包含的以下几个成员:
struct module { enum module_state state; //模块的状态,这是一个枚举变量 char name[MODULE_NAME_LEN]; //模块的名称 struct module_ref __percpu *refptr; //模块的引用计数}
enum module_state { MODULE_STATE_LIVE, /* Normal state. */ MODULE_STATE_COMING, /* Full formed, running module_init. */ MODULE_STATE_GOING, /* Going away. */ MODULE_STATE_UNFORMED, /* Still setting it up. */};
我们修改状态和引用计数即可。
- 修改引用计数通过以下两个函数来实现
int try_module_get(struct module *); //增加module的引用计数
void module_put(struct module *); //减少module的引用计数 修改状态直接可以对module的成员state进行赋值
以下是我写的一些测试代码,好了废话不多说,贴代码
/*print_module.c*/#include<linux/kernel.h>#include<linux/init.h>#include<linux/list.h>#include<linux/module.h>MODULE_LICENSE("GPL");/***每次重启内核时都要通过这个命令来获取**sudo cat /pro/kallsyms | grep [^_]modules$ */#define MODULES 0xffffffff8ec5b470 /*在两个修改方案上选择*/#define DEBUG_MODULE 0 /*是否启动调试*/#define DEBUG 1 static char *name = "testtesttest";/*模块参数,传入一个模块的名称*/module_param(name,charp,S_IRUGO); static int __init print_module_init(void) { struct list_head *module_head; struct list_head *pos; struct module *p; int i= 0; int ret; printk(KERN_INFO "print module init\n"); module_head = (struct list_head*)MODULES; /*遍历所有的module*/ list_for_each(pos,module_head) { p = list_entry(pos,struct module,list);#if DEBUG#if DEBUG_MODULE/*如果匹配到这个模块,修改状态为living,增加引用计数*/ if(strcmp(p->name,name)==0){ p->state = MODULE_STATE_LIVE; if((ret = try_module_get(p)) == 0) { printk(KERN_ALERT "try_module_get error\n"); } printk(KERN_INFO "%s ret is inc\n",p->name); }#else/*降低匹配到的模块的引用计数*/ if(strcmp(p->name,name) == 0) { module_put(p); printk(KERN_INFO "%s ref is dec\n",p->name); }#endif#endif } return 0;}static void __exit print_module_exit(void){ printk(KERN_INFO "print module exit\n");}module_init(print_module_init);module_exit(print_module_exit);
Makefile如下
obj-m:= print_module2.oKDIR:= /lib/modules/$(shell uname -r)/buildall: $(MAKE) -C $(KDIR) M=$(shell pwd) modulesclean: $(MAKE) -C $(KDIR) M=$(shell pwd) clean
编译通过后,insmod print_module.ko name=xxxx进行加载,xxx是出错的那个模块
在过程中可以通过lsmod和cat /proc/modules 查看模块相关信息
1 1
- 关于模块insmod和rmmod出错的解决方案
- insmod和rmmod
- insmod 和 rmmod
- 模块在insmod之后无法rmmod问题
- insmod,rmmod
- insmod/rmmod
- linux 加载insmod和卸载rmmod驱动
- 内核与内核模块:depmod,lsmod,modinfo,insmod,rmmod,mdprobe
- 内核与内核模块:depmod,lsmod,modinfo,insmod,rmmod,mdprobe
- 内核模块相关命令:lsmod,depmod,modprob,modinfo,insmod,rmmod
- 内核与内核模块:depmod,lsmod,modinfo,insmod,rmmod,mdprobe
- ko驱动模块rmmod 后insmod 异常问题解决
- 内核与内核模块:depmod,lsmod,modinfo,insmod,rmmod,mdprobe
- insmod & modprobe & rmmod
- insmod lsmod rmmod
- insmod & modprobe & rmmod
- lsmod insmod rmmod modprobe
- 核心模组的载入与移除: insmod, modprobe, rmmod
- MyEclipse 2014启动两个Tomcat的最快方案
- ThinkPHP入门,从路由的角度
- NEFUOJ-18-滑雪
- 4.26
- 正则大作战 基础篇(一)
- 关于模块insmod和rmmod出错的解决方案
- Css的伪元素选择器
- 使用百度脑图kityminder-editor进行数据可视化二次开发
- qsort
- angular常见内置指令
- Java Servlet(数据传输 页面跳转 jsp)
- Unsafe--Java为什么会引入及如何使用Unsafe
- docker容器中查看容器linux版本
- json对象与json字符串相互转化