文档介绍:第9章模块的动态加载和系统配置
第9章模块的动态加载和系统配置
本章介绍了Linux内核动态加载功能模块的工作原理。分析了 Linux 内核中的系统配置结构,解释了 Makefile 和配置文件的格式以及配置语句的含义。最后给出一个简单的例子,说明如何将自行开发的代码加入到 Linux 内核中。
模块的动态加载
操作系统通常由内核和一些系统服务程序(命令解释、库文件、链接和编译程序等)组成。内核是操作系统的灵魂,它为用户进程提供了一个虚拟机接口。用户进程可以并行运行、公平的占用系统资源而互不干扰。
模块的动态加载
操作系统通常由内核和一些系统服务程序(命令解释、库文件、链接和编译程序等)组成。内核是操作系统的灵魂,它为用户进程提供了一个虚拟机接口。用户进程可以并行运行、公平的占用系统资源而互不干扰。
从结构上来分,可将操作系统分为微内核结构和单块结构两类。Windows NT 和 MINIX 是典型的微内核操作系统,而Linux 则是单块结构的操作系统。微内核结构可方便地在系统中添加新的组件,而单块结构却不容易做到这一点。为此,Linux系统使用可动态加载和卸载的内核模块(Loadable Kernel Modules,LKMs),可方便地在内核中添加新的组件或卸载不再需要的内核组件。Linux使用insmod来显式加载内核模块,使用rmmod来卸载模块。同时内核自身也可以请求内核后台进程kerneld来加载与卸载模块。Linux模块大多数是设备驱动程序以及伪设备驱动程序模块, 如网络设备和文件系统等。
动态可加载代码的优点是可以让内核保持很小的尺寸并非常灵活。模块机制可以无需重构内核并频繁重新启动来尝试运行新内核代码。用户可以根据自己系统的需要构筑自己的私有内核。Linux源码的公开更是为改造其内核、重建有特殊要求的操作系统提供了可能。
模块必须能够找到其需要使用的内核资源。例如模块需要分配内存时,要调用内核的内存分配例程kmalloc()。但在构造模块时并不知道kmalloc()在内存中何处,这样内核必须在使用这些模块前修改模块中对 kmalloc()的引用地址。内核在其内核符号表中维护着一个内核资源链表这样当加载模块时它能够解析出模块中对内核资源的引用。Linux还允许存在模块堆栈,它在模块之间相互调用时使用。
例如,因为VFAT(VirtuaI File Allocation Table)文件系统是从FAT(File Allocation Table)文件系统中扩展而来,VFAT文件系统模块可能需要FAT文件系统模块的服务。某个模块对其他模块的服务或资源的需求类似于模块对内核本身资源或服务的请求。不过此时所请求的服务是来自另外一个事先已加载的模块。当加载模块时,内核就把新近加载模块输出的所有资源和符号添加到内核符号表(Kernel-Symbol-Table) 中。
在/proc/,这就是内核符号表。这些内核符号是可以被LKM引用的。LKM中所存取的每一个符号(像函数名)也会被列在这个文件里面。在该文件中可以看到LKM到底可以调用那些函数。
当试图卸载某个模块时,内核需要知道此模块是否已经没有被使用,同时它需要有种方法来通知此将卸载模块。模块必须能够在从内核种删除之前释放其分配的所有系统资源,如内核内存或中断。当模块被卸载时,内核将从内核符号表中删除所有与之对应的符号。
但是,内核模块的引入也带来了如下问题:
但是,内核模块的引入也带来了如下问题:
(1) 有可能同时带来与内核模块相关的性能与内存损失。可加载模块的代码一般较长,且额外的数据结构可能会占据一些内存,对内核资源的间接使用也可能带来效率方面的问题。对系统性能和内存利用有负面影响;
但是,内核模块的引入也带来了如下问题:
(1) 有可能同时带来与内核模块相关的性能与内存损失。可加载模块的代码一般较长,且额外的数据结构可能会占据一些内存,对内核资源的间接使用也可能带来效率方面的问题。对系统性能和内存利用有负面影响;
(2) 一旦Linux模块被加载,则和普通内核代码一样成为内核的一部分,具有与其他内核代码相同的权限与职责。因此,Linux内核模块也可以象所有内核代码和设备驱动一样使内核崩溃;