广东快乐十分-广东快乐十分开奖结果_广东快乐十分投注平台

关于Linux操作系统中LKM的优势与不足研究与应用浅_医疗电子

作者:Aileen 发布时间:2019-08-24 02:01:34 点击数:105

Linux系统开放源代码、系统漏洞少,在面对病毒和黑客入侵时能提供更好的安全性和稳定性,基于以上这些优点,近年来对Linux操作系统及其相关技术的应用和研究越来越多。对Linux操作系统扩充或裁剪功能需要在重新编译内核上花费大量的时间。LKM机制由于大大缩短了开发和测试的时间,在 Linux开发、研究广东快乐十分-广东快乐十分开奖结果_广东快乐十分投注平台的过程中起到了举足轻重的作用。

LKM主要包括内核模块在操作系统中的加载和卸载两部分功能,内核模块是一些在启动的操作系统内核需要时可以载入内核执行的代码块,不需要时由操作系统卸载。它们扩展了操作系统内核功能却不需要重新编译内核、启动系统。如果没有内核模块,就不得不反复编译生成操作系统的内核镜像来加入新功能,当附加的功能很多时,还会使内核变得臃肿。

2. LKM的编写和编译

2.1 内核模块的基本结构

一个内核模块至少包含两个函数,模块被加载时执行的初始化函数init_module()和模块

被卸载时执行的结束函数cleanup_module()。在最新内核稳定版本2.6中,两个函数可以起

任意的名字,通过宏module_init()和module_exit()实现。唯一需要注意的地方是函数必须在宏的使用前定义。例如:

static int __init hello_init(void){}

staTIc void __exit hello_exit(void ){}

module_init(hello_init);

module_exit(hello_exit);

这里声明函数为staTIc的目的是使函数在文件以外不可见,__init的作用是在完成初始化后收回该函数占用的内存,宏__exit用于模块被编译进内核时忽略结束函数。这两个宏只针对模块被编译进内核的情况,而对动态加载模块是无效的。这是因为编译进内核的模块是没有清理收尾工作的,而动态加载模块却需要自己完成这些工作。

2.2 内核模块的编译

编译时需要提供一个makefile来隐藏底层大量的复杂操作,使用户通过make命令就可以完成编译的任务。下面就是一个简单的编译hello.c的makefile文件:

广东快乐十分-广东快乐十分开奖结果_广东快乐十分投注平台obj-m += hello.ko

KDIR := /lib/modules/$(shell uname -r)/build

PWD := $(shell pwd)

default:

广东快乐十分-广东快乐十分开奖结果_广东快乐十分投注平台$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules

广东快乐十分-广东快乐十分开奖结果_广东快乐十分投注平台编译后获得可加载的模块文件hello.ko。

内核版本2.6中使用.ko文件后缀代替了.o,这是为了与普通可执行文件相区别。

广东快乐十分-广东快乐十分开奖结果_广东快乐十分投注平台3. LKM的主要功能

3.1 模块的加载

模块的加载有两种方法,第一种是使用insmod命令加载,另一种是当内核发现需要加载某个模块时,请求内核后台进程kmod加载适当的模块。当内核需要加载模块时,kmod被唤醒并执行modprobe,同时传递需加载模块的名字作为参数。modprobe像insmod一样将模块加载进内核,不同的是在模块被加载时查看它是否涉及到当前没有定义在内核中的任何符号。如果有,在当前模块路径的其他模块中查找。如果找到,它们也会被加载到内核中。但在这种情况下使用insmod,会以“未解析符号”信息结束。

关于广东快乐十分-广东快乐十分开奖结果_广东快乐十分投注平台模块加载,可以用图3.1来简要描述:

关于Linux操作系统中LKM的优势与不足研究与应用浅析

insmod程序必须找到要求加载的内核模块,这些内核模块是已链接的目标文件,与其他文件不同的是,它们被链接成可重定位映象即映象没有被链接到特定地址上。insmod将执行一个特权级系统调用来查找内核的输出符号,这些符号都以符号名和数值形式如地址值成对保存。内核输出符号表被保存在内核维护的模块链表的第一个module结构中。只有特殊符号才被添加,它们在内核编译与链接时确定。insmod将模块读入虚拟内存并通过使用内核输出符号来修改其未解析的内核函数和资源的引用地址。这些工作采取由insmod程序直接将符号的地址写入模块中相应地址来进行。

当insmod修改完模块对内核输出符号的引用后,它将再次使用特权级系统调用申请足够的空间容纳新模块。内核将为其分配一个新的module结构以及足够的内核内存来保存新模块,并将其插入到内核模块链表的尾部,最后将新模块标志为UNINITIALIZED。insmod将模块拷贝到已分配空间中,如果为它分配的内核内存已用完,将再次申请,但模块被多次加载必然处于不同的地址。另外此重定位工作包括使用适当地址来修改模块映象。如果新模块也希望将其符号输出到系统中,insmod将为其构造输出符号映象表。每个内核模块必须包含模块初始化和结束函数,所以为了避免冲突它们的符号被设计成不输出,但是insmod必须知道这些地址,这样可以将它们传递给内核。在所有这些工作完成以后,insmod将调用初始化代码并执行一个特权级系统调用将模块的初始化和结束函数地址传递给内核。当将一个新模块加载到内核中时,内核必须更新其符号表并修改那些被新模块使用的老模块。那些依赖于其他模块的模块必须在其符号表尾部维护一个引用链表并在其module数据结构中指向它。内核调用模块的初始化函数,如果成功将安装此模块。模块的结束函数地址被存储在其module结构中,将在模块卸载时由内核调用,模块的状态最后被设置成RUNNING。

3.2 模块的卸载

document.write ('');