5、与模块有关的内核编译选项和过程
在使用make confing / make menuconfig / make xconfig对内核进行配置时,和模块有关的选项有:
Code maturity level options -->
Prompt for development and/or incomplete code/drivers
此选项为代码的成熟程度。所有新的设计与改进都首先在开发版(版本号为x.y.z,其中y是奇数)中试用,经过验证技术可行之后再在稳定版(版本号为x.y.z,其中y是偶数)中正式引入。尚不成熟或不完善的技术在默认的情况中是不会编译到内核中的,如果你希望试验这些内容(例如2.4.*版本中的khttpd、IPV6等),就要选中这个选项。
>
Loadable module support -->
Enable module support
Set version information on all module symbols
Kernel module loader
此选项是对可装载内核的支持以及对模块符号的版本号、内核模块装载程序支持的选项。对于其他大部分选项来说,你可以将相应的代码编译到内核中(使用build-in方式),也可以将他们编译成模块(使用module)方式。
如果你选用了模块方式,那么在编译内核的过程中,你除了要使用
make; make install
命令来编译/安装内核之外,还要使用
make modules; make modules_install
来编译/安装内核模块。编译好的模块被安装到/lib/modules/kernel-version/目录中。
编译过程中还要运行一个
depmod -a
命令。这个命令生成模块依赖文件,也就是/lib/modules/kernel-version/modules.dep,该文件格式为:
/lib/modules/2.2.14-5.0/fs/autofs.o:
/lib/modules/2.2.14-5.0/fs/binfmt_aout.o:
/lib/modules/2.2.14-5.0/fs/binfmt_java.o:
/lib/modules/2.2.14-5.0/fs/binfmt_misc.o:
/lib/modules/2.2.14-5.0/fs/coda.o:
/lib/modules/2.2.14-5.0/fs/fat.o:
/lib/modules/2.2.14-5.0/fs/hfs.o:
/lib/modules/2.2.14-5.0/fs/hpfs.o:
/lib/modules/2.2.14-5.0/fs/lockd.o: /lib/modules/2.2.14-5.0/misc/sunrpc.o
/lib/modules/2.2.14-5.0/fs/minix.o:
/lib/modules/2.2.14-5.0/fs/msdos.o: /lib/modules/2.2.14-5.0/fs/fat.o
......
这个文件中详细列出了所有的模块文件的绝对路径,每一行说明一个模块的信息;如果一行中有多个模块的信息,就说明了模块间具有依赖关系。例如,
/lib/modules/2.2.14-5.0/fs/lockd.o: /lib/modules/2.2.14-5.0/misc/sunrpc.o
这一行就说明模块lockd要引用sunrpc模块。有了这个文件,内核在装载模块时就可以根据所解析出的模块名来正确地定位模块的位置了。
6、与模块有关的配置文件
和模块有关的文件,除了上面这个modules.dep之外,还有几个配置文件。例如:
/etc/rc.d/rc.modules
/etc/conf.modules或/etc/modules.conf
例如笔者机器中后一个文件的内容为:
alias eth0 rtl8139
alias sound-slot-0 via82cxxx
分别说明了网卡和声卡的类型,例如第一行中eth0是我的第一块网卡,rtl8139是对应的模块,系统会查找/lib/modules/2.2.14-50/modules.dep文件,在其中找到
/lib/modules/2.2.14-5.0/net/rtl8139.o:
这一行,从而就可以定位正确的模块文件。
7、单独编译模块
我们除了可以在内核源程序树中使用
make modules; make modules_install
来编译安装内核模块之外,也可以自行对其进行编译,相关的编译选项有:
__KERNEL__--这个标志告诉头文件此代码将在内核模块中运行,而不是作为用户进程的一部分运行。
MODULE--这个标志告诉头文件要为内核模块给出适当的定义。
LINUX--从技术上讲,这个标志不是必要的。但是,如果你希望写一个比较正规的内核模块,它可以在多个操作系统上编译,这个标志将会使你感到非常方便。它可以允许你在独立于操作系统的部分进行常规的编译。
还有其它一些可被选择包含标志,这取决于编译模块使用的选项。如果你不能确定内核应该怎样编译,可以在/usr/include/linux/config.h中查到。
__SMP__--对称多处理。如果要把内核编译成可以支持对称多处理,那么必须定义这个标志
CONFIG_MODVERSIONS--如果CONFIG_MODVERSIONS被激活(也就是说要区分内核模块的版本号),你需要在编译内核模块时定义这个标志并包含头文件/usr/include/linux/modversions.h。
例如,我们自行下载rtl8139网卡的驱动程序的源程序rtl8139.c,可以这样编译:
gcc -Wall -O2 -DMODULE -D__KERNEL__ -DLINUX -o rtl8139.o rtl8139.c
然后修改前面介绍的相应的配置文件或者使用insmod命令就可以使用这个模块了。
8、相关问题
再次强调,模块实用工具的版本号最好不要低于内核的版本号。例如,如果你的modutils的版本号小于2.4.0,那么在你自己下载2.4.*版本的内核来编译时,即使各个步骤都完全正确,你会发现/lib/modules/kernel-version/modules.dep这个文件为空,即使你自己手工修改了这个文件,重新启动机器之后,这个文件又变成空了。所以对于这种情况,你应该使用2.4.*的modutils。2.2和2.4版本的内核模块存储的路径有很大的差别,/etc/conf.modules文件的结构也很不相同了,感兴趣的读者可以自行试验一下。