/*真胖子同志制作,转载请注明出处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)检查是否已经建立了依赖关系。原理是遍历b的source_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加载
模块部分到此为止,基本原理就是这样,至于模块热插拔和自动加载机制在介绍到驱动程序模型的时候或许更能说的清楚,就在不久之后再介绍吧。~~~~~~~