linux模块概述
内核模块是Linux内核向外部提供的一个插口,其全称为动态可加载内核模块(Loadable Kernel Module,LKM),我们简称为模块。Linux内核之所以提供模块机制,是因为它本身是一个单内核(monolithic kernel)。单内核的最大优点是效率高,因为所有的内容都集成在一起,但其缺点是可扩展性和可维护性相对较差,模块机制就是为了弥补这一缺陷。
模块是具有独立功能的程序,它可以被单独编译,但不能独立运行。它在运行时被链接到内核作为内核的一部分在内核空间运行,这与运行在用户空间的进程是不同的。模块通常由一组函数和数据结构组成,用来实现一种文件系统、一个驱动程序或其他内核上层的功能。
一个内核模块的从创建到使用会经过如下过程
源代码-->Makefile文件-->编译模块-->加载模块-->卸载模块
从某种意义上来说,内核也是一个模块。模块可以理解为为内核或其他内核模块提供使用功能的代码块,是内核的动态扩展。
内核模块的优缺点
优点
将内核映象的尺寸保持在最小,并具有最大的灵活性;
便于检验新的内核代码,而不需重新编译内核并重新引导。
缺点
装入的内核模块和其他内核部分一样,具有相同的访问权限,因此,差的内核模块会导致系统崩溃;
为了使内核模块访问所有内核资源,内核必须维护符号表,并在装入和卸载模块时修改这些符号表;
有些模块要求利用其他模块的功能,因此,内核要维护模块之间的依赖性。
内核必须能够在卸载模块时通知模块,并且要释放分配给模块的内存和中断等资源;
内核版本和模块版本的不兼容,也可能导致系统崩溃,因此,严格的版本检查是必需的。
尽管内核模块的引入同时也带来不少问题,但是模块机制确实是扩充内核功能一种行之有效的方法,也是在内核级进行编程的有效途径。
内核模块的加载与卸载
开机自动加载模块
手动编译一些驱动程序或者是 tarball 的套件后,会得到 *.ko 一个编译成功的目标档案。我们需要把编译好的模块放置在核心应该要放置的地方
核心的模块放置目录: /lib/modules/`uname –r`/kernel/
核心的档案格式模块: /lib/modules/`uname –r`/kernel/fs
核心的网络卡驱动程序模块: /lib/modules/`uname –r`/kernel/drivers/net
在模块的加载方面,最主要的开机时加载/etc/modprobe.conf中记录的模块。因此,我们把编译好的模块放在相应位置后,想要在开机的时候立即启动这个模块,那么需要在写入/etc/modprobe.conf相应记录。
一般的Linux发行版本都有 /etc/modules.conf 或 /etc/modprobe.conf 。在这个文件中一般是写入模块的加载命令或模块的别名的定义等;比如我们在modules.conf 中可能会发现类似的一行 ;
格式:alias 别名 模块名称
代码:alias eth0 8139too
这样系统启动的时候,首先会modprobe 8139too ,然后再为8139too 指定别名为 eth0,然后我们在登录的时候,用 ifconfig就会查看到网卡的IP等情况,当然您得为网卡设置IP 才行;
一般的情况下,modproe.conf 或modules.conf的内容 是我们用相应的硬件配置工具而生成的;如果您的硬件驱动是没有被内核支持,您自己到硬件的厂商下载而来的驱动。一般的情况下都有安装和帮助文件。他们的驱动在配置时,他会写入硬件的支持到modules.conf 或modprobe.conf 文件中。
lsmod
lsmod显示当前加载的所有模块,相当于cat /proc/modules,假设你没有设定开机加载某个模块,比如ntfs,那么开机后执行lsmod,列表里不会有ntfs这个模块的,这时你再执行 mount -t ntfs xxx后,执行lsmod后列表里就会有ntfs这个模块了。
还要注意的是lsmod显示的是模块名,而不是别名(alias)。
# lsmod
Module Size Used by
nfs 229569 0
lockd 63081 1 nfs
注意:第三列表示该模块被几个模块依赖,如共有1个模块依赖lockd模块,该模块为nfs
modinfo
用于查看模块的详细信息
# modinfo lockd
filename: /lib/modules/2.6.18-164.el5/kernel/fs/lockd/lockd.ko
license: GPL
description: NFS file locking service version 0.5.
author: Olaf Kirch <okir@monad.swb.de>
srcversion: 5AB38783DF566BC39C8C6D4
depends: sunrpc
vermagic: 2.6.18-164.el5 SMP mod_unload 686 REGPARM 4KSTACKS gcc-4.1
parm: nlm_max_connections:uint
module_sig: 883f3504a.......9c902f38b
insmod
insmod想内核加载模块
# insmod [-fkps] module_name
参数说明:
-f :强制将模块加载,要加载不相同版本的模块时候可能会用到的参数
-k:自动在核心没有使用到该模块的时候,先清除干净!
-p:测试模块是否可以被加载,不会直接加载系统中!
-s:将一些执行讯息写到 syslog 这种登录档,而不是写到 terminal 当中!
insmod可以读取非 /lib/modules/`uname -r`/kernel 内的模块。而且还可以为模块进行加载测试,利用-p参数可以验证该模块的可执行性与否!
modprobe
insmod与modprobe都是载入kernel module,不过一般差别于modprobe能够处理 module 载入的相依问题。
比方你要载入 a module,但是 a module 要求系统先载入 b module 时,直接用insmod挂入通常都会出现错误讯息,不过 modprobe 倒是能够知道先载入b module后才载入a module,如此相依性就会满足。
modprobe之所以会知道模块之间的相依性,是通过读取 /lib/modules/`uname -r`/modules.dep得知的。而该档案是透过 depmod 程式所建立。
man modprobe
节选如下:
从linux核心中添加或删除模块。
为了一致性,模块名字中包含的_和-是没有任何区别的。modprobe会检查/lib/modules/`uname -r`下的所有模块,除了/etc/modprobe.conf配置文件和/etc/modprobe.d目录以外。所有/etc/modprobe.d/arch/目录下的文件将被忽略。
值得注意的是现在modprobe不会对模块本身进行操作,解析symbols和理解参数的工作都交由kernel来作,所以模块加载等错误有时将会包含在内核信息中,利用dmesg可以查看到。
modprobe会根据depmod生成的文件modules.dep来获取模块之间的依赖关系,从而添加或者删除模块。
现在版本的modprobe只支持2.5.48及以上的内核,如果它发现内核支持老版本的模块(该模块的大部分工作都在自己的运行空间完成),modprobe将在自己的运行空间尝试运行modprobe.modutils,该过程对用户完全透明。
如果在加载模块时指定参数,这些参数会和模块一起被传到内核中,并记录在配置文件中。
参数选项:
-l :列出目前系统所有的模块 ( 实际上modprobe会长modules.dep文件中找到相应模块后,才去搜索/lib/modules/`uname -r`下的模块 ),可以使用wildcard。
-c:列出目前系统所有的模块!(更详细的代号对应表)
-r:删除模块。
depmod
上文提到的模块依赖性是通过depmod命令生成的,该命令会分析/lib/modules/$(uname -r)/kernel目录下的所有模块,并将最终结果记录在modules.dep文件中供modprobe应用!
参数选项:
-A:不加任何参数時, depmod会主动的去分析目前内核模块,並且重新写入/lib/modules/$(uname -r)/modules.dep 当中。若加入 -A 参数时,depmod则会去搜索比modules.dep內还要新的模块,如果真找到新模块,才会更新。
-n:不写入modules.dep ,而是将結果输出到屏幕上(standard out);
-e:显示出目前已载入的不可执行的模块名称
参考至:http://blog.163.com/hu_cuit/blog/static/12284914320113972637691/
http://hi.baidu.com/scuxy06/item/7046362d0f5be8fd51fd8724
http://hi.baidu.com/20065562/item/15dcc4ce92c3d510b67a24af
http://baike.baidu.com/view/9243025.htm
http://www.cnitblog.com/xijia0524/archive/2012/11/08/86741.html
http://linux.vbird.org/linux_basic/0510osloader.php#kernel_modprobe
本文原创,转载请注明出处、作者
如有错误,欢迎指正
邮箱:czmcj@163.com