admin 管理员组文章数量: 1087139
2024年4月18日发(作者:免费建站对比)
~
Di ssection of Linux Kerne1 ModuIe ImpIementation MechaniSill
张楠
Zhang Nan
(华东交通大学,江西南昌330013)
(East China Jiaotong University,Jiangxi Nanchang 33001 3)
摘要:本文讨论了操作系统的两种基本组织方式,即一体化内核及微内核的基本概念,分析了它们各
自的优缺点,进而阐明了在Linux下引入内核模块的主要动机,着重以图解的方式论述了Linux内核模块的
实现机制。
关键词:一体化内核;微内核;内核模块;内核符号表
中图分类号:TP316 文献标识码:A 文章编号:1671.4792.(2ol1)5.0092—04
Abstract:This paper mainly discussed two operating system organization models:monolithic kernel and mi-
cro kernel,analyzed their advantages and disadvantages.Then ta ̄ed about the motives of introduction of Linux
,
kernel module,finally illustrated the Linux kernel:module implementation mechanism with chart.
Keywords:Monolithic Kernel;Micro Kernel;Kernel Module;Kernel Symbol Table
0引言
而如果把所有的操作系统管理模块都放在特权
现代操作系统从功能构成上来说主要包括进程
管理、内存管理、文件管理、设备管理以及网络通信
模式下运行,则称之为一体化组织,见图二所示。
等几大模块。为了支持构建安全操作系统,现代
CPU一般都提供了至少两种运行模式:特权模式与
用户模式。根据各个管理模块是否放在特权模式下,
操作系统有微内核和一体化内核两种组织方式。如
果仅把必需的进程通信管理、中断管理以及内存管
理放在特权模式下运行,而把设备管理模块、文件系
统管理模块、网络通信管理模块放在用户模式下运
行,称之为微内核组织方式,见图一所示。
一
囤国圈圉圉
叫 圈囤圈
图二一体化内核组织方式
传统的Unix及大部分类Unix操作系统基本上
都属于一体化内核组织方式,而Mach、Windows
NT、Window 2000/XP等基本属于微内核组织方式。
目目圉圈圈
圈圈
图一微内核组织方式
其中一体化内核组织方式的优点是效率高、安全,缺
点是不容易扩展,要增加一种新设备驱动或文件系
统等功能必须对内核重新编译定制,而且占用内存
较多;而微内核组织方式的优点是可扩展性好,占用
内存少,缺点是效率低,也没有前者安全。
1 Linux内核模块引入动机及其实现基本思想
从上可以看出两种内核组织方式都有各自的
优缺点,在Linux中引入内核模块机制的主要动机
正是为了充分吸取两者的优点,克服它们的缺点。
内核模块本质上是一种目标对象文件,没有链
接,不能独立运行,但可以动态加载到内核并与内核链
序代码之外也有一张符号表,记录了此内核模块提
供的函数服务、符号变量及它们的相对地址,如fl
的相对地址为l5,同时也记录了它可能要引用到的
亡=
3
c
×
正在运行的内核中函数服务。但编译时它并不知道
这些函数及全局变量的地址,故在图四的符号表中
的s1、f3的地址用“?”表示。
起j豳坤~
鞠七, o一
接从而成为内核的一部分。其基本机理是,首先Linux
内核本身有一张内核符号表,此表中主要包括用来描
述系统提供哪些函数服务、系统全局变量及它们对应
模
一
块
实
现
机
制
m1
mZ Z奋
分
在内核中的位置。凡是需要输出的函数及系统全局变
量,在Linux源代码文件中都用一个宏EX.
PORT SYMBOL将其输出,以使内核各个模块能够
互相引用。例如:
EXPORT
_
SYMBOL ̄emel_tbread);
同理,每个内核目标模块也有一张类似的符号
表,其中定义了此模块所提供的功能函数以及变
量,以及此模块可能要用到的系统内核中的函数及
变量,但此时又不知其实际地址。为了使内核模块
真正成为Linux系统内核的一部分,必须将此内核
模块动态装入到内存中并把相应的各种符号函数
解析定位好,之后内核模块提供的各种函数才能真
正被使用。具体可以用下面的图三至图五来说明其
实现机理。图三是Linux操作系统初始内核映象,其
中包括系统代码部分和相应的Linux系统内核全局
符号表,其中f3的内核位置为52,sl为35,依此类
推。
。{
・恭
号}
・鱿
p|I
●蛮
图三初始系统内核映象
类似地,图四是一个内核模块映象,其中除了程
曩1 -,
蒸 卜 ,f231 l 4 .,凸o
析
棚l:=:
.
—IZ-_‘;,
●1=f_ 块@ 寰@
苎2
结束地~
图四内核模块映象
当要把图四所示的内核模块装入到正在运行的
像图三所示的Linux操作系统内核中,必须完成图
三操作系统内核模块与图四内核模块的动态链接。
具体过程是操作系统内核首先为要链人其中的内核
模块分配内存,将其程序代码装入其中,根据分配的
起始地址对内核模块内部的函数及变量地址进行重
新定位。同时在操作系统内核符号表中加入此内核
模块中定义的函数符号及变量,以便内核中的其它
子系统能够获得这个刚链人其中的模块的服务。例
如内核模块中n原来的相对地址为15,由于在装
入地址是300,故重定位地址应为3 1 5;还有原来在
内核模块中不知道f3,这时由于装入内存时知道B
的内核地址是52,所以也要做相应设置,同时在操
作系统全局符号表中增加内核模块所定义的功能函
数及变量符号。整个插入内核模块操作系统内核映
象如图五所示。
2模块技术分析
Linux中超级用户可以通过insmod和rmmod
命令显式地将模块载人核心或从核心中将它卸载。
核心也可在需要时,请求守护进程kemeld装载和卸
载模块。通过动态地将代码载人核心可以减小核心
~
图五插入内核模块之后的系统内核映象
代码的规模,使核心配置更为灵活。Linux允许模块
堆栈,即一个模块可请求其它模块为之提供服务,当
模块装载人系统内核时,系统修改内核中的符号表,
将新装载模块提供的资源和符号加到内核符号表
中。通过这种方法,新载入的模块可访问已装载模块
提供的资源。
若某个模块空闲,用户便可将它卸载出内核。
在卸载之前,系统释放分配给该模块的系统资源,如
核心内存、中断等,同时系统将该模块提供的符号从
核心符号表中删除。
Linux提供了一组命令用于模块操作,其中以
insmod、rmmod、l smod、depmod、kemeld这几个命
令最为重要,它们的功能如表一所示。
表一模块操作命令
靠尊 用运
I Ill f 列出内f;中已安暮的值
i“、IHl~I 挎悔 安墨到内 中
lIIIlJlI、I 内援审卸就I簟
‘pilllI. I生成城 於窝僻
K rI ¨ 幢 调磨
Linux内核中与模块有关的数据结构主要有两
个:
module和S ymbol_table。module是用来记录
模块信息和相互引用的关系;而symbol
_
table这个
结构用来将模块动态链接进核心,这是一个重要的
数据结构,主要记录两方面的信息:模块提供的函
数、变量和引用信息。前者用于核心同模块的通信,
后者记录本模块引用其它模块的情况。两个结构间
通过由module指向它对应的symbol_table指针来
联系。
2.1模块的装入
装入模块有两种方法:一是通过insmod命令手
工将模块载人核心,命令的格式为:insmod
/<path>/modulename.o;二是内核根据需要载入模
块,当内核发现需要某个模块时,内核请求守护进程
kerneld载入该模块(内核版本为2.0的调用方式,
到了2.1以后的版本,这份工作则交由k mod程序,
通过产生一个内核线程执行modprobe指令并装入
模块)。当该进程启动时,建立与内核之间的一个I
PC通道,内核通过该通道发送消息,请求kemeld完
成具体的任务。kemeld的主要功能是将模块载入
核心和将它卸载出核心,但kemeld本身并不执行这
些任务,它只是调用相应命令来完成(如insmod,
rmmod),也就是说它只是核心负责调度任务的一个
代理。Kerneld装入模块的过程如图六所示。
图六Kemeld守护进程模块装入
由上面分析可以得知,手工装入模块和守护进
程的按照需要载入模块,最后均通过insmod来实
现。insmod的具体实现过程如下:首先将待装入模
块读人虚存,通过符号表定位该模块中引用的核心
程序和资源指针,再将符号的地址添人模块中的相
块的AUTOCLEAN和VISITED标志也保存于此,
但只有由kenerld装入的模块这两个标记才有意义。
当模块标记为AUTOCLEAN时
系统可以将它们
,
广
3
C
模 ×
块
实
现
应位置。当insmod完成模块对符号表的引用后,通
过syscreatemodule()系统调用,为新模块分配一
个module数据结构和足够的核心空间,将新分配的
module结构置于模块列表(module list)中,并置新
模块状态为UNINITIALIZED。然后系统会将内核
分配给module的空间映射到insmod进程的地址空
自动卸载,而当VISITED被标记时表示该模块正在
被系统的其它部分使用,该模块是不能被卸载的。
当kemeld请求系统卸载满足上述两个条件的
模块时,它会遍历系统中模块列表,寻找候选模块。
系统仅考察标记为AUTOCLEAN和RUNNING的
模块,若候选模块的VISITED标记未被置位,
机
分
析
制
间,这样insmod进程能够将模块拷贝到分配的空
间。当模块加入到内核中以后,修改内核的符号表,
因为若一个模块被其它模块引用,则该模块的数据
结构中包含一个引用该模块的指针列表,所以需要
同时修改新模块依赖的所有模块中的相关指针。完
成上述工作之后,内核调用模块的初始化函数,并进
行模块的安装。最后,置该模块的状态为RUN.
NING,至此模块加载成功。
2.2模块的卸载
相对于模块装载,卸载模块同样也有两种方法:
第一种是用户使用rmmod命令卸载模块,命令的格
式为:rmmodmodulename。其实质是通过系统调用
sys_delete
_
module,将指定的module从系统模块链
中取出,卸载出核心并释放模块占用的内存空间。
第二种是kemeld自动卸载,能够由kerneld自动卸
载的模块必须满足两个条件:(1)kerneld根据需要
自动载人的模块;(2)它们不再需要。Linux中自
动卸载的机制为:每隔一定的时间,kerneld调用
sys_delete
_
module系统调用,将满足上述两个条件
的模块从系统中卸载,定时器的值在kerneld启动时
进行设置。
为了保证引用正确性,Linux规定当某个模块
被核心的某一部分使用时,该模块是不能被卸载的。
每一个模块均有一个计数器,计数器的值是内核中
依赖该模块的模块数目(module count)。一个模块的
模块数目的值保存在它的映像的第一个字节中,模
那么将该模块卸载,否则,系统清除该模块的VIS.
ITED标记位,然后考察系统中的下一个模块。当模
块被卸载时,系统会调用该模块的cleanup子程序,
通常该子程序是用于释放系统分配给该模块的核心
资源。若模块的状态为DELETED,则将它从系统的
模块列表中脱开,修改该模块所依赖的所有模块的
引用列表(reference list),将卸载的模块从它们的引
用列表中脱开,以释放分配给该模块的核心内存。
3结束语
Linux内核主要通过设置一张内核符号表,并
提供一些加载动态链接内核模块的几个基本服务函
数就可以发挥两种内核的优点,这样像文件系统以
及设备驱动一般都可以用Linux内核模块来实现。
参考文献
[1】李善平.边干边学一Linu)【内核指导[M].杭
州:浙江大学出版社.
[2]陈莉君.Linux内核设计与实现[M].北京:机
械工业出版社.
【3]陈莉君.深入理解Linux内核(第二版)[M】.
北京:电力工业出版社.
作者简介
张楠(1982一),男,北京市人,汉族,本科,华东
交通大学在读工程硕士。
95
版权声明:本文标题:Linux模块实现机制分析 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://roclinux.cn/p/1713439739a634757.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论