嵌入式开发 > 详情

Linux可加载内核模块机制的研究与应用

发布时间:2020-07-07 发布时间:
|

1. 引言

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

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

2. LKM的编写和编译

2.1 内核模块的基本结构

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

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

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

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]

3. LKM的主要功能

3.1 模块的加载

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





『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
django是什么_django能做什么