首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件开发 >

强力卸载内核模块(1)

2012-09-17 
强力卸载内核模块(一)概述 内核为2.6.32。卸载模块target时,不管是否为强制卸载,都输出:ERROR:Module targe

强力卸载内核模块(一)
概述

 

内核为2.6.32。

卸载模块target时,不管是否为强制卸载,都输出:

ERROR:Module target is in use.

用lsmod查看target,发现Used by计数为1,而据我所知,没有其它模块依赖target。

编写模块检查target的module结构,发现:

target->state == 0 // 模块存活

module_refcount(target) == 1 // 模块引用计数为1

list_empty(target->modules_which_use_me) == 1 // 模块依赖列表为空

这个就很奇怪,模块的引用计数为1,却没有引用者。

这可能是模块插入内核时出错而引起的,这里先不研究,先关注怎么把它强制卸载掉,虽然

insmod加载是临时的,所以通过重启电脑可以解决一些问题,但是不能总是依靠重启啊。

解决方法:编写模块mymod中把问题模块target的引用计数置为0,就可以顺利卸载掉target了!

 

代码

 

#include<linux/init.h>#include<linux/module.h>#include<linux/kernel.h>#include<linux/list.h>#include<linux/cpumask.h>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->modules_which_use_me)) {                                 list_for_each_entry(relate,&mod->modules_which_use_me,modules_which_use_me)                                        printk(KERN_ALERT"%s ",relate->name);                        } else                                printk(KERN_ALERT"used by NULL\n");                        // 把target的引用计数置为0                        for_each_possible_cpu(cpu)                                local_set(__module_ref_addr(mod,cpu),0);                        // 再看看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("Zhangsk");MODULE_LICENSE("GPL");MODULE_DESCRIPTION("Why module can not be removed");

 

内核

 

@include/linux/module.h:

extern struct module __this_module;#define THIS_MODULE (&__this_module);enum module_state{     MODULE_STATE_LIVE; // 模块存活,0     MODULE_STATE_COMING; // 正在加载模块,1     MODULE_STATE_GOING; // 正在卸载模块,2}; struct module {     enum module_state state; // 模块状态     /* Member of list of modules */     struct list_head list; // 内核模块链表     /* Unique handle for this module */     char name[MODULE_NAME_LEN]; //模块名称     ...#ifdef CONFIG_MODULE_UNLOAD     /* What modules depend on me? */     struct list_head modules_which_use_me;     /* Who is waiting for us to be unloaded */     struct task_struct *waiter;     /* Destruction function. */     void (*exit) (void);#ifdef CONFIG_SMP     char *refptr;#else     local_t ref;#endif#endif     ...};static inline local_t *__module_ref_addr(struct module *mod, int cpu){#ifdef CONFIG_SMP     return (local_t *) (mod->refptr + per_cpu_offset(cpu));#else     return &mod->ref;#endif}

@include/asm-generic/atomic.h:

typedef atomic64_t atomic_long_t;

@include/linux/types.h:

typedef struct {     volatile int counter;} atomic_t;#ifdef CONFIG_64BITtypedef struct {     volatile long counter;} atomic64_t;#endif

@arch/x86/include/asm/local.h:

typedef struct {    atomic_long_t a;} local_t; #define local_read(l) atomic_long_read(&(l)->a)#define local_set(l, i) atomic_long_set(&(l)->a, (i))//此外还有加减操作

@include/asm-generic/percpu.h:

#ifdef CONFIG_SMP/** per_cpu_offset() is the offset that has to be added to a percpu variable to get the instance for  * a certain processor. * Most arches use the __per_cpu_offset array for those offsets but some arches have their own  * ways of determining the offset (x86_64, s390).   */#ifndef __per_cpu_offsetextern unsigned long __per_cpu_offset[NR_CPUS];#define per_cpu_offset(x) (__per_cpu_offset[x])#endif

 

热点排行