内核模块(4)模块卸载

/*真胖子同志制作,转载请注明出处http://blog.csdn.net/figtingforlove/article/details/20156543*/

当需要修改某个模块的功能的时候我们可以使用rmmod命令卸载模块,与模块的加载相比这个要简单得多,j结构也很清晰,下面还是通过源码简要介绍其思想。

822 SYSCALL_DEFINE2(delete_module, const char __user *, name_user,
823                 unsigned int, flags)
824 {
825         struct module *mod;
826         char name[MODULE_NAME_LEN];
             /*从用户空间拷贝要卸载的模块名*/
832         if (strncpy_from_user(name, name_user, MODULE_NAME_LEN-1) < 0)
833                 return -EFAULT;
834         name[MODULE_NAME_LEN-1] = '\0';
             /*在模块全局链表中根据模块名查找要卸载的模块*/
839         mod = find_module(name);
              /*判断有没有其他模块依赖于本模块(重要的模块依赖关系)*/
845         if (!list_empty(&mod->source_list)) {
             /*省略中间的一些判断和处理,不影响理解*/
883         /*执行模块析构函数 */
884         if (mod->exit != NULL)
885                 mod->exit();
886         blocking_notifier_call_chain(&module_notify_list,
887                                      MODULE_STATE_GOING, mod);
              /*...*/
892          /*释放模块占据的内存*/
893         free_module(mod);
894         return 0;
898 }


 

上面模块卸载代码中有检查模块依赖关系的部分,如果有模块A依赖于模块B的导出函数,那么那么模块B不能卸载,内核用struct module数据结构的如下成员变量跟踪模块间的依赖关系。 

359 /* What modules depend on me? */
360    struct list_head source_list;
361 /* What modules do I depend on? */
362    struct list_head target_list;


这两个成员用来构建有依赖关系的模块的链表,此外还需借助另一个数据结构

195 /* modules using other modules: kdb wants to see this. */
196 struct module_use {
197         struct list_head source_list;//链接依赖与的
198         struct list_head target_list;//链接所依赖的模块
	/*source指向要求依赖其它模块的模块,target指向被依赖的模块*/
199         struct module *source, *target;
200 };

模块依赖关系的建立最早发生在模块被加载时,前面介绍“未解决的引用”符号时讲了在模块链表中查找引用的另一个模块的符号,此外还要建立两个模块之间的关系。

1253 /* Resolve a symbol for this module.  I.e. if we find one, record usage. */
1254 static const struct kernel_symbol *resolve_symbol(struct module *mod,
1255                                  const struct load_info *info,
1256                                  const char *name,
1257                                  char ownername[])
1258 {
1275 
1276         err = ref_module(mod, owner);
1288 }
1289 

684 /* Module a uses b: caller needs module_mutex() */
685 int ref_module(struct module *a, struct module *b)
686 {
687         int err;
688         /*检查依赖关系*/
689         if (b == NULL || already_uses(a, b))
690                 return 0;
691 
692         /*模块b的引用计数+1,使它不能移除. */
693         err = strong_try_module_get(b);
694         if (err)
695                 return err;
696         /*建立模块间的依赖关系*/
697         err = add_module_usage(a, b);
698         if (err) {
699                 module_put(b);
700                 return err;
701         }
702         return 0;
703 }

already_uses(a,b)检查是否已经建立了依赖关系。原理是遍历bsource_list链表,借助于use变量查看是否有a依赖于b

644 /* Does a already use b? */
645 static int already_uses(struct module *a, struct module *b)
646 {
647         struct module_use *use;
648 
649         list_for_each_entry(use, &b->source_list, source_list) {
650                 if (use->source == a) {
651                         pr_debug("%s uses %s!\n", a->name, b->name);
652                         return 1;
653                 }
654         }
655         pr_debug("%s does not use %s!\n", a->name, b->name);
656         return 0;
657 }

add_module_usage(a,b)为模块建立依赖关系,模块a依赖于模块b,函数也结构很清晰。

659 /*
660  * Module a uses b
661  *  - we add 'a' as a "source", 'b' as a "target" of module use
662  *  - the module_use is added to the list of 'b' sources (so
663  *    'b' can walk the list to see who sourced them), and of 'a'
664  *    targets (so 'a' can see what modules it targets).
665  */
666 static int add_module_usage(struct module *a, struct module *b)
667 {
668         struct module_use *use;
669 
670         pr_debug("Allocating new usage for %s.\n", a->name);
671         use = kmalloc(sizeof(*use), GFP_ATOMIC);
672         if (!use) {
673                 printk(KERN_WARNING "%s: out of memory loading\n", a->name);
674                 return -ENOMEM;
675         }
676 
677         use->source = a;
678         use->target = b;
679         list_add(&use->source_list, &b->source_list);
680         list_add(&use->target_list, &a->target_list);
681         return 0;
682 }


下面用一幅图表示模块A和模块B依赖于模块S,二模块A先于B加载



模块部分到此为止,基本原理就是这样,至于模块热插拔和自动加载机制在介绍到驱动程序模型的时候或许更能说的清楚,就在不久之后再介绍吧。~~~~~~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值