system administrator 使用的模块处理CLI命令主要是如下的工具包:
$ dpkg -S $(which modprobe)
module-init-tools: /sbin/modprobe
kernel module编译
这一篇文章: http://www.cyberciti.biz/tips/compiling-linux-kernel-module.html讲述了如何编译自己的写的module, 相当不错.
但是少了点"为什么要这样做"的解释
看URL里写的Makefile里的这句话:
make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
参数M是什么? 参数modules又是什么? gcc怎么没有调用? 为什么可以简单的一行命令可以完成编译?
带着问题去找答案:
$ ls -ld /lib/modules/$(uname -r)/build
lrwxrwxrwx 1 root root 40 2010-03-31 09:43 /lib/modules/2.6.31-21-generic/build -> /usr/src/linux-headers-2.6.31-21-generic
ubuntu下的/usr/src/linux-headers-2.6.31-21-generic目录下的Makefile其实就是kernel代码下的Makefile文件。所以上面的make命令中的modules参数与在kernel代码目录里的modules参数是一致的。
参数"-C"表示进入此目录, 目录下有另一个Makefile文件(/lib/modules/2.6.31-21-generic/build/Makefile), 此Makefile内的一小段代码:
62 # Use make M=dir to specify directory of external module to build
63 # Old syntax make ... SUBDIRS=$PWD is still supported
64 # Setting the environment variable KBUILD_EXTMOD take precedence
65 ifdef SUBDIRS
66 KBUILD_EXTMOD ?= $(SUBDIRS)
67 endif
68
69 ifeq ("$(origin M)", "command line")
70 KBUILD_EXTMOD := $(M)
71 endif
这已经可以解决疑问:
自己写的模块编译Makefile文件只是为/lib/modules/2.6.31-21-generic/build/Makefile 提供两个参数:
- directory of external module
- "modules"
找个复杂的驱动试试是否为这样, 于是从intel官网下载了e1000e-1.2.20.tar.gz代码
234 ifeq ($(KOBJ),$(KSRC))
235 $(MAKE) -C $(KSRC) SUBDIRS=$(shell pwd) modules
236 else
237 $(MAKE) -C $(KSRC) O=$(KOBJ) SUBDIRS=$(shell pwd) modules
238 endif
239 endif
.......(还有很多不显示).......
274 default:
275 $(MAKE)
下面是编译的具体过程:
jessinio@jessinio-laptop:/tmp/e1000e-1.2.20/src$ make
make -C /lib/modules/2.6.31-21-generic/build SUBDIRS=/tmp/e1000e-1.2.20/src modules
make[1]: Entering directory `/usr/src/linux-headers-2.6.31-21-generic'
CC [M] /tmp/e1000e-1.2.20/src/netdev.o
CC [M] /tmp/e1000e-1.2.20/src/ethtool.o
CC [M] /tmp/e1000e-1.2.20/src/param.o
CC [M] /tmp/e1000e-1.2.20/src/e1000_82571.o
CC [M] /tmp/e1000e-1.2.20/src/e1000_ich8lan.o
CC [M] /tmp/e1000e-1.2.20/src/e1000_80003es2lan.o
CC [M] /tmp/e1000e-1.2.20/src/e1000_mac.o
CC [M] /tmp/e1000e-1.2.20/src/e1000_nvm.o
CC [M] /tmp/e1000e-1.2.20/src/e1000_phy.o
CC [M] /tmp/e1000e-1.2.20/src/e1000_manage.o
CC [M] /tmp/e1000e-1.2.20/src/kcompat.o
LD [M] /tmp/e1000e-1.2.20/src/e1000e.o
Building modules, stage 2.
MODPOST 1 modules
CC /tmp/e1000e-1.2.20/src/e1000e.mod.o
LD [M] /tmp/e1000e-1.2.20/src/e1000e.ko
make[1]: Leaving directory `/usr/src/linux-headers-2.6.31-21-generic'
jessinio@jessinio-laptop:/tmp/e1000e-1.2.20/src$ lsmod|grep e1000e
jessinio@jessinio-laptop:/tmp/e1000e-1.2.20/src$ sudo insmod e1000e.ko
编译与加载一路通!
insmod和rmmod组合与modprobe的区别
其实大家都知道: modprobe解决module的依赖问题. insmod和rmode不会处理这种依赖问题.
依赖的依据是: `代码中使用的module名`
CLI下可以这样查看:
$ modinfo iptable_filter|grep depends
depends: ip_tables
被依赖的ip_tables可能又依赖于其它module, 不断的向下查找. 直到depends为NULL.
depmod为处理这种问题的工具:modprobe expects an up-to-date modules.dep file, as generated by depmod
可以看出modprobe和depmod工具的关系.
使用modprobe查看依赖树:
$ modprobe --show-depends iptable_filter
insmod /lib/modules/2.6.31-21-generic/kernel/net/netfilter/x_tables.ko
insmod /lib/modules/2.6.31-21-generic/kernel/net/ipv4/netfilter/ip_tables.ko
insmod /lib/modules/2.6.31-21-generic/kernel/net/ipv4/netfilter/iptable_filter.ko
上面出现的insmod是有先后顺序的.
因为modprobe是使用了modules.dep文件, 所以面对没有放在/lib/modules下或者没有调用depmod命令去更新modules.dep文件, modprobe是无法加载模块的:
# modprobe hello
FATAL: Module hello not found.
# insmod hello.ko
# rmmod hello
modprobe除了可以方便insert和remove模块外, 还有这样一些方便的功能:
1. option
2. alias
这是通过modprobe读取/etc/modprobe.conf( /etc/modprobe.d) 文件完成.
alias主是是用于调用modprobe工具时使用管理者喜欢的模块名代替实现的module名(编译后的模块名)
* alias不会影响 lsmod 命令列出的模块名. lsmod是列出真实的模块名
module有哪些option呢?
$ /sbin/modinfo bnx2|grep parm
parm: disable_msi:Disable Message Signaled Interrupt (MSI) (int)
parm: enable_entropy:Allow bnx2 to populate the /dev/random entropy pool (int)
上面列出指定的bnx2网卡module的参数.
kernel编译
jessinio@jessinio-laptop:~/linux-2.6.36.2$ make help|grep oldconfigoldconfig - Update current config utilising a provided .config as base
silentoldconfig - Same as oldconfig, but quietly, additionally update deps
oldnoconfig - Same as silentoldconfig but set new symbols to n (unset)
这三个参数都是利用旧kernel的configure文件. 例如:
jessinio@jessinio-laptop:~/linux-2.6.36.2$ cp /boot/config-2.6.31-21-generic ./.config
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.