LINUX系统下执行 insmod时候的详细过程
LINUX系统下执行 insmod时候的详细过程
之前在面试linux驱动的实习岗位的时候问到的问题,没想到几乎每天都用的一个指令,我居然都都没有留心,现在做个记录。
参考文章:(后续添加)
insmod其实是一个modutils模块实用程序,执行init_module函数
这个程序完成下面一系列工作:
1.计算存放模块代码、模块名和module对象所需要的内存大小。
2.在用户空间中分配一个内存区,把module对象、模块名以及为正在运行的内核所重定位的模块代码拷贝到这个内存里。其中,module对象中的init域指向这个模块的入口函数重新分配到的地址;exit域指向出口函数所重新分配的地址。
3.调用init_module(),向它传递上面所创建的用户态的内存区的地址,
4. 接着声明内核引用该模块;
5. 呼叫该模块的初始化涵数
6.释放用户态内存, 整个过程结束。
该函数准确应该是在 linux/kernel/module.c里, 但是在里面你不会找到sys_init_module这个函数,因为这个函数是通过一个宏来实现的。
> /* This is where the real work happens */
> SYSCALL_DEFINE3(init_module, void __user *, umod,
> unsigned long, len, const char __user *, uargs)
这个宏就代表了sys_init_module这个函数。
另外,insmod装载该模块后,该模块为内核模块
内核模块是在“内核空间”中运行的,而应用程序运行在“用户空间”。
Linux通过系统调用或者中断,完成从用户空间到内核空间的转换。
因为地址空间的原因,内核模块不能像应用程序那样自由地使用在用户空间定义的函数库如libc,例如printf()。内核模块的另外一个困难,是内核失效对于整个系统或者对于当前进程常常是致命的,而在应用程序的开发过程中,缺段(segment fault)并不会造成什么危害,我们可以利用调试器轻松地跟踪到出错的地方。所以在内核模块编程的过程中,必须特别的小心。