1.前言 - 2 -
2.实例配置 - 2 -
2.1 监控主机的配置 - 2 -
2.2 被监控主机的配置 - 2 -
2.3 实例测试 - 3 -
3.Netconsole内核源码分析 - 4 -
3.1 几个重要的数据结构 - 4 -
3.1.1 struct console - 4 -
3.1.2 struct netpoll - 5 -
3.1.3 struct net_device - 5 -
3.1.4 struct netpoll_info - 6 -
3.2 实现分析 - 6 -
3.2.1 Netconsole初始化 - 7 -
3.2.2 具体运行实现 - 11 -
1.前言
Netconsole是Linux2.6版内核的一个新的特性。它允许将本机的dmesg系统信息,通过网络的方式传送到另一台主机上。这样,就可以实现远程监控某台机子的kernel panic信息了。使用起来非常方便,也给开发人员调试内核提供了更加便捷的途径。
1.1 menuconfig选项
File systems -> Pseudo filesystems中
< M > Userspace-driven configuration filesystem
Device Drivers -> Network device support中
< M > Network console logging support
[ * ] Dynamic reconfiguration of logging targets
[*] Netpoll traffic trapping
2.实例配置
由于2.6版本的内核本身已经支持Netconsole,并以模块形式编译进了内核。所以,下面的介绍都是基于2.6版内核,且本身在内核编译的时候,已经选择了将Netconsole以模块进行编译的方式。如果内核本身并没有编译Netconsole这个模块,那就需要重新编译内核了(笔者暂时没有找到其他的解决方案)。
监控主机有两种配置方式:使用本身的syslogd和利用netcat这个工具。Syslogd使用了514这个特定的UDP端口,而netcat工具可以指定任意未被使用的UDP端口进行监视。我这里使用的是netcat的方式进行监视的。安装好netcat后,执行shell命令:
# netcat -l -p 30000 –u
这里使用了端口30000来进行接收,这个端口是任意制定的,只要不发生冲突即可。
在需要被监控的主机上加载运行netconsole模块,由于netconsole模块需要许多其他模块的依赖,以及在加载时必须配置相关的端口,IP地址等信息,所以shell执行命令如下:
#modprobe netconsole netconsole=6666@10.14.0.225/eth7, 30000@10.14.0.220 /00:0C:29:E2:87:E8
我们来分析一下这段加载命令。
Modprobe 这个模块加载命令是指在加载该模块时,同时加载其依赖的其它模块;
第一个@前的6666是本地端口,这个我们可以在源码中看到,是一个源代码中默认的本地端口;
10.14.0.225/eth7:这里指配本机的IP地址及网卡名称(通常我们可以用ifconfig –a来查看到);
30000@10.14.0.220/00:0C:29:E2:87:E8:三个位段分别是,远端监控端口,远端IP地址及远端机子的MAC地址。也就是我们在2.1节中指定的监控端口30000,以及其IP地址和MAC地址了。
以上配置就算完成了,让我来看一个实例吧。在被监控的主机上运行一个简单的hello world模块,看看我们的printk信息是怎样被发送到监控主机上去的。
模块helloworld源码:
hello.c
1 /*hello.c*/
2 #include <linux/kernel.h>
3 #include <linux/init.h>
4 #include <linux/module.h>
5 MODULE_LICENSE("Dual BSD/GPL");
6
7 static int hello_init(void)
8 {
9 printk(KERN_ALERT "Hello World\n" );
10 return 0;
11 }
12 static void hello_exit(void)
13 {
14 printk(KERN_ALERT "Goodbye World\n" );
15 }
16
17 module_init(hello_init);
18 module_exit(hello_exit);
1 obj-m:=hello.o
2 KDIR:=/lib/modules/$(shell uname -r)/build
3 PWD:=$(shell pwd)
4
5 default:
6 $(MAKE) -C $(KDIR) M=$(PWD) modules
7
8 clean:
9 $(RM) *.o *.mod.c *.ko *.symvers
执行:
# make
# insmod hello.ko
在监控机的终端上,我们看到以下信息:
netconsole: network logging started
Hello World
第一条是我们先前加载netconsole模块时收到的,第二条是我们加载helloworld模块时收到的。
再运行rmmod hello
监控机终端上将看到:
netconsole: network logging started
Hello World
Goodbye World
OK,以上测试顺利完成,当然,我们也可以测试kernel panic的情况,例如操作一个内核的非法地址等。下面,我们开始来分析内核源码的netconsole的实现。