Chinaunix首页 | 论坛 | 博客
  • 博客访问: 818859
  • 博文数量: 264
  • 博客积分: 592
  • 博客等级: 中士
  • 技术积分: 1574
  • 用 户 组: 普通用户
  • 注册时间: 2011-10-24 22:02
文章分类

全部博文(264)

文章存档

2019年(2)

2018年(1)

2017年(1)

2016年(4)

2015年(14)

2014年(57)

2013年(88)

2012年(97)

分类: LINUX

2014-06-20 21:40:05

 
五,源码分析
1,应用层
busybox中的insmod源码:
        if ((fd = open(filename, O_RDONLY, 0)) < 0) {
                bb_perror_msg_and_die("cannot open module `%s'", filename);
        }

        fstat(fd, &st);
        len = st.st_size;
        map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
        if (map == MAP_FAILED) {
                bb_perror_msg_and_die("cannot mmap `%s'", filename);
        }

      ret = syscall(__NR_init_module, map, len, options);
        if (ret != 0) {
                bb_perror_msg_and_die("cannot insert `%s': %s (%li)",
                                filename, moderror(errno), ret);
        }
 
上面的代码其功能就是将.ko映射到内存,以供sys_init_module使用。
 
2,内核层
 
syscall(__NR_init_module, map, len, options)会调用sys_init_module函数
/kernel/module.c中:
 
asmlinkage long
sys_init_module(void __user *umod,
                unsigned long len,
                const char __user *uargs)
{
        struct module *mod;
        int ret = 0;
        /* Must have permission */
        if (!capable(CAP_SYS_MODULE))
                return -EPERM;
 
如果没有权限,那么会返回一个ERROR NOT PERMISSION,没有权限,不然大家都可以insmod,那天下岂不乱套。
 
        /* Only one module load at a time, please */
        if (mutex_lock_interruptible(&module_mutex) != 0)
                return -EINTR;
 
保证每次这有一个驱动被加载,这样可以简化程序的设计。
在Linux内核中,有不少设计被做简化了,如内核任务退出,如果你在内核任务退出时调用kthread_stop,那末就会造成死锁。
 
        /* Do all the hard work */
        mod = load_module(umod, len, uargs);
        if (IS_ERR(mod)) {
                mutex_unlock(&module_mutex);
                return PTR_ERR(mod);
        }
 
load_module应该做了绝大部分的工作,将驱动拷贝到内核,重定位等等,具体后面会分析。
 
        /* Now sew it into the lists.  They won't access us, since
           strong_try_module_get() will fail. */
        stop_machine_run(__link_module, mod, NR_CPUS);
        /* Drop lock so they can recurse */
        mutex_unlock(&module_mutex);
        blocking_notifier_call_chain(&module_notify_list,
                        MODULE_STATE_COMING, mod);
        /* Start the module */
 
MODULE_INIT()就是在这里开始运行的:)
        if (mod->init != NULL)
                ret = mod->init();
 
如果失败了,就是MODULE_INIT()返回值不为0,那么,不用说,释放资源~~
 
        if (ret < 0) {
                /* Init routine failed: abort.  Try to protect us from
                   buggy refcounters. */
                mod->state = MODULE_STATE_GOING;
                synchronize_sched();
                if (mod->unsafe)
                        printk(KERN_ERR "%s: module is now stuck!\n",
                               mod->name);
                else {
                        module_put(mod);
                        mutex_lock(&module_mutex);
                        free_module(mod);
                        mutex_unlock(&module_mutex);
                }
                return ret;
        }
 
        /* Now it's a first class citizen! */
        mutex_lock(&module_mutex);
        mod->state = MODULE_STATE_LIVE;
        /* Drop initial reference. */
        module_put(mod);
        unwind_remove_table(mod->unwind_info, 1);
        module_free(mod, mod->module_init);
 
上面的代码是释放__init段的内存,如果你的函数有__init的属性,那么,此时会被释放掉,节约内存。
 
        mod->module_init = NULL;
        mod->init_size = 0;
        mod->init_text_size = 0;
        mutex_unlock(&module_mutex);
        return 0;
 
        OK,驱动加载完成。
}
 
当然,mod = load_module(umod, len, uargs)才是重点。
后面会对它进行详细的分析。
阅读(1240) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~