Linux 可加载模块 探索

来源:互联网 发布:免费的域名 编辑:程序博客网 时间:2024/05/16 12:33
        因为没有环境的原因,现在的这些东西只能算是记忆了。本来想在windows下装个虚拟机的,可惜电脑磁盘空间不够了。


       先开始写,先记一下今天为了写Linux下的输入法程序,而无意间搜到的一篇很好的博客:http://blog.csdn.net/absurd/article/details/1497463,此文是李先静老师的一篇关于学习方法的博客,很有感触,我想关于学习,我走过了很多误区,以前只会看,看得很多很泛而且很多东西还是质量很差的文章,结果自己的技术积累很低,实践能力也没跟上,接下来的目标:1,要多看源码,2,要多写程序,3,还是要多写。


        这次要把内核模块的数据结构理解一下,以及模块的加载过程。


        首先是模块的加载,模块的加载过程需要“用户空间应该程序来帮助"(这一点还需要自己去验证,说法是来自《深入Linux内核架构》),所以先从系统调用开始。跟模块相关的系统调用接口有两个一个初始化,另一个是删除的。


函数原型:


     asmlinkage long sys_init_module(void __user *umod, unsigned long len,const char __user *uargs);


     asmlinkage long sys_delete_module(const char __user *name_user,unsigned int flags);


     一开始就上内核树上去搜索这两个函数的定义了,但看来看去也只看到了sys_init_module的原型就是没找到定义,只好静下来把syscalls.h 和 module.c 认真认真的看了遍,结果发现内核是以宏的形式实现了这两个函数:


SYSCALL_DEFINE3(init_module, void __user *, umod,unsigned long, len, const char __user *, uargs)


SYSCALL_DEFINE2(delete_module, const char __user *, name_user,unsigned int, flags)


#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)


asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))       \
             __attribute__((alias(__stringify(SyS##name)))); 


asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__))       \
{                                                               \
     long ret = SYSC##name(__MAP(x,__SC_CAST,__VA_ARGS__));  \
     __MAP(x,__SC_TEST,__VA_ARGS__);                         \
     __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__));       \
     return ret;                                             \
}                                                               \
static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))


   一开始想不明白为什么系统调用的接口要写的这么复杂,用了这么些预处理宏,我想肯定不是内核开发者为show 自己的水平吧,一阵谷歌,在RedHat Bug 跟踪网站上找到这么些写原来是要处理一个系统安全漏洞,网站的地址忘记记录了,大概的意思是系统的ABI规定,64位的系统,用户空间向内核空间传递32位数据时要将其符号扩展到64位,如果没有这么做就导致内存访问异常的内存空间导致系统crash了,这个Bug出在Mips,Spack等处理器上。既然问题很明确那就是将用户空间的参数先转换成64位,然后再去调用接口函数,那么为什么还要这么弄出这么多宏呢,原来内核开发者的目标是不仅要解决问题,而且还要finish it in art。所以就有了这么多这么漂亮的代码了。


    这里还有一个地方我没搞明白,就是这些系统接口都能看到 asmlinkage 的连接声明,我猜大概是为了在防止在用户空间用C++编译器编译代码,导致ABI不兼容吧,因为Linux系统规定的系统调用的参数都要放在栈上。关于ABI,要花点时间去弄明白,先Mark一下。


     sys_init_module,先检查模块,然后上篇中介绍的数据从用户空间拷贝的内核空间,接着调用load_module。这些代码还没细看,先写这些了。
0 0
原创粉丝点击