2010年02月23日 星期二 16时13分12秒
近几日一直在openSuSE上做内核模块编程。以前在fedora上写过一些例子,比较顺手。刚接触openSuSE,走了一些弯路,记录下来。
1、在安装openSuSE时,我在“开发”选择了“Linux内核开发”。所以,有了当前内核的源代码,和内核开发的一些文档。如果一开始没有选择,则要下载和当前内核版本一致的内核源代码(或者可以选择其他版本的源代码)。
2、我重新编译了内核源码,耗时数十分钟!
cd /usr/src/linux-2.6.31.5-0.1/
mkdir /home/sahu/build
mkdir /home/sahu/build/kernel
cp /boot/config-2.6.31.5-0.1-desktop .config
make O=/home/sahu/build/kernel/ oldconfig
make O=/home/sahu/build/kernel/
sudo make O=/home/sahu/build/kernel/ modules_install
sudo make O=/home/sahu/build/kernel/ install
这次编译内核,我参看了内核的README文件,将内核编译的结果放在一个自定义的目录中,而不是和内核源代码放在一起。
3、编写测试内核模块:dropAll.c,功能是丢弃所以网络数据包。
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
#include <linux/ip.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
MODULE_LICENSE("GPL");
/* This is the structure we shall use to register our function */
static struct nf_hook_ops nfho;
/* This is the hook function itself */
unsigned int hook_func(unsigned int hooknum,
struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
return NF_DROP; /* Drop ALL packets */
}
/* Initialisation routine */
int init_module()
{
/* Fill in our hook structure */
nfho.hook = hook_func; /* Handler function */
nfho.hooknum = NF_INET_PRE_ROUTING; /* First hook for IPv4 */
nfho.pf = PF_INET;
nfho.priority = NF_IP_PRI_FIRST; /* Make our function first */
nf_register_hook(&nfho);
pr_info("dropAll install into kernel!/n");
return 0;
}
/* Cleanup routine */
void cleanup_module()
{
nf_unregister_hook(&nfho);
pr_info("dropAll removed from kernel!/n");
}
4、编写Makefile文件,直接拷贝以前写的。
obj-m +=dropAll.o
all:
make -C /usr/src/linux/ SUBDIRS=$(PWD) modules
clean:
make -C /usr/src/linux M=$(PWD) clean
install:
/sbin/insmod dropAll.ko
remove:
/sbin/rmmod dropAll
编译时,各种错误!百思不得其解,偶然发现内核源码目录中有一个“Documentation/”目录,想必就是安装openSuSE时,“Linux内核开发”所带的文档,大喜!翻阅各个文档,发现有“kbuild/”目录,其中的modules.txt文件详细介绍了自定义内核模块的编译和安装等等。原来,上面的Makefile写法,是默认内核编译的输出目录是和内核源代码相同的。
于是将Makefile文件改为:
obj-m +=dropAll.o
all:
make -C /lib/modules/`uname -r`/build M=`pwd`
clean:
make -C /lib/modules/`uname -r`/build M=`pwd` clean
install:
/sbin/insmod dropAll.ko
remove:
/sbin/rmmod dropAll
没问题!
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
欣喜之余,查看/lib/modules/2.6.31.5-0.1-desktop/,发现其中有个“build/”链接指向编译内核时自定义的输出目录:“/home/sahu/build/kernel
”;有“source/”链接指向内核源码目录:“/usr/src/linux-2.6.31.5-0.1”
因我安装了xen内核,于是重启机器到xen内核下,用上述Makefile编译,也没问题。查看/lib/modules/2.6.31.5-0.1-xen/,亦有build和source两个链接。只是build指向/usr/src/linux-2.6.31.5-0.1-obj/i386/xen,不同于前者。比较/usr/src/linux-2.6.31.5-0.1-obj/i386/xen和/home/sahu/build/kernel的大小,相当惊人7M Vs 3.5G!!
想想没重新编译内核之前,并没有/home/sahu/build/kernel,可见只是些编译的中间结果。于是重新建立链接:
rm /lib/modules/2.6.31.5-0.1-desktop/build
ln -s /usr/src/linux-2.6.31.5-0.1-obj/i386/desktop/ /lib/modules/2.6.31.5-0.1-desktop/build
删除/home/sahu/build/kernel
rm -r /home/sahu/build/kernel
所以一开始,没有必要重新编译内核!是所以为“弯路”也!当然如果要安装新内核,则另当别论!
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5、编译此模块:
make
6、安装模块
make install
7、测试
ping 127.0.0.1
可以发现,ping不通,哈哈!
8、卸载模块
make remove
9、清理
make clean
10、注意 :使用SSH登录目标机器的谨慎使用,因为连接会断开的!