Tuesday, January 4, 2011

linux kernel and modules

本文主要是回顾linux modules这部分的管理.

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 oldconfig
  oldconfig       - 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.