首页 > *nix技术, 跟踪调试 > uml使用详细

uml使用详细

2012年8月26日 发表评论 阅读评论 6,213 次浏览

1,内核编译:
先说下环境如下,操作系统为CentOS 6.0 64位,除内核被升级为2.6.38.8外,其它基本环境无改变:
[root@localhost uml]# cat /etc/issue
CentOS Linux release 6.0 (Final)
Kernel \r on an \m

[root@localhost uml]# uname -a
Linux localhost.localdomain 2.6.38.8 #5 SMP Sun Aug 19 21:23:53 CST 2012 x86_64 x86_64 x86_64 GNU/Linux

解压配置,就以linux-2.6.38.8为例,因为刚好有这个内核源码压缩包:
[root@localhost uml]# tar xjf linux-2.6.38.8.tar.bz2
[root@localhost uml]# cd linux-2.6.38.8
[root@localhost linux-2.6.38.8]# make ARCH=um menuconfig

选下如下几项:
将以虚拟块设备作为根文件系统,并且我这里提供的根文件系统是ext4的:
Device Drivers —>
[*] Block devices —>
[*] Virtual block device
[*] Always do synchronous disk IO for UBD
File systems —>
<*> The Extended 4 (ext4) filesystem

将以虚拟设备作为网络设备,可根据需要选择,比如如下:
[*] Networking support —>
UML Network Devices —>
[*] Virtual network device
[*] Ethertap transport
[*] TUN/TAP transport
[*] SLIP transport
[*] Daemon transport
[ ] VDE transport
[*] Multicast transport
[ ] pcap transport
[*] SLiRP transport

既然是调内核,这两个选项必不可少:
Kernel hacking —>
[*] Compile the kernel with debug info
[*] Compile the kernel with frame pointers

执行编译:
[root@localhost linux-2.6.38.8]# make ARCH=um
或者只要linux执行文件:
[root@localhost linux-2.6.38.8]# make ARCH=um linux

如果没有错误,那么就算初步成功,否则请参考前面的文章做错误修复:
[root@localhost linux-2.6.38.8]# ls linux -lFh
-rwxr-xr-x. 2 root root 35M Aug 24 14:36 linux*

2,UML执行:
首先需要一个根文件系统,从这个网址:http://fs.devloop.org.uk/下载即可:
[root@localhost linux-2.6.38.8]# cp linux ../
[root@localhost linux-2.6.38.8]# cd ..
[root@localhost uml]# ls
linux linux-2.6.38.8 linux-2.6.38.8.tar.bz2 rootfs
[root@localhost uml]# ./linux ubda=./rootfs mem=256m

正常进入到UML系统,退出输入halt或init 0即可。

3,初次调试内核:
首先找到uml对应的进程,一般会有多个:
[root@localhost uml]# ps uf | grep linux | grep -v grep
root 26897 4.3 5.6 270320 57112 pts/0 S+ 14:48 0:12 \_ ./linux ubda=./rootfs mem=256m
root 26904 0.0 5.6 270320 57112 pts/0 S+ 14:48 0:00 \_ ./linux ubda=./rootfs mem=256m
root 26905 0.4 5.6 270320 57112 pts/0 S+ 14:48 0:01 \_ ./linux ubda=./rootfs mem=256m
root 26906 0.0 5.6 270320 57112 pts/0 S+ 14:48 0:00 \_ ./linux ubda=./rootfs mem=256m
root 26907 0.0 0.1 3776 1516 pts/0 t+ 14:48 0:00 \_ ./linux ubda=./rootfs mem=256m
root 27058 0.2 0.0 3120 772 pts/0 t+ 14:48 0:00 \_ ./linux ubda=./rootfs mem=256m
root 27342 0.0 0.0 3152 644 pts/0 t+ 14:48 0:00 \_ ./linux ubda=./rootfs mem=256m
root 27636 0.0 0.0 3400 664 pts/0 t+ 14:48 0:00 \_ ./linux ubda=./rootfs mem=256m
root 27663 0.0 0.1 4036 1376 pts/0 t+ 14:48 0:00 \_ ./linux ubda=./rootfs mem=256m
root 27672 0.0 0.1 4056 1768 pts/0 t+ 14:48 0:00 \_ ./linux ubda=./rootfs mem=256m
一般情况下,用gdb attach到主进程即可:
[root@localhost uml]# gdb -p 26897
进入gdb后立即设置:(gdb) set follow-fork-mode parent
因为UML在运行的过程中可能会fork新的子进程(比如UML启动了新的系统服务),如果不做这个设置,会导致gdb跟丢UML。
试试在schedule()函数处下个断点,按c继续后马上被中断(这是当然的):
(gdb) b schedule
Breakpoint 1 at 0x601ca50f: file kernel/sched.c, line 4017.
(gdb) c
Continuing.

Breakpoint 1, schedule () at kernel/sched.c:4017
4017 if (need_resched())
(gdb) up
#1 0x0000000060012424 in default_idle () at arch/um/kernel/process.c:246
246 schedule();
(gdb) list
241 /*
242 * although we are an idle CPU, we do not want to
243 * get into the scheduler unnecessarily.
244 */
245 if (need_resched())
246 schedule();
247
248 tick_nohz_stop_sched_tick(1);
249 nsecs = disable_timer();
250 idle_sleep(nsecs);
(gdb)

4,网络支持:
以TUN/TAP为例。关于更多的信息可以参考:
http://user-mode-linux.sourceforge.net/old/networking.html
UML可以利用host机器的TUN/TAP虚拟网络设备来创建虚拟网卡与外界通信。这里先在host机器上创建tap设备,创建tap设备需要的应用层工具tunctl可从此处下载:http://sourceforge.net/projects/tunctl/files/

[root@localhost uml]# tar xzf tunctl-1.5.tar.gz
[root@localhost uml]# cd tunctl-1.5
[root@localhost tunctl-1.5]# make
[root@localhost tunctl-1.5]# make install
[root@localhost tunctl-1.5]# tunctl -t tap1
[root@localhost tunctl-1.5]# ifconfig tap1 10.0.0.1

这就在host机器里创建了tap类型的虚拟网络设备,再以如下命令执行UML,从而在UML里创建一个可与该虚拟网络设备通信的网卡eth0:
[root@localhost uml]# ./linux ubda=./rootfs mem=256m eth0=tuntap,tap1,,

在UML里ping host机的tap1的操作:
[root@localhost ~]# ifconfig eth1 10.0.0.2
[root@localhost ~]# ping 10.0.0.1
PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=67.2 ms
64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.338 ms
^C
— 10.0.0.1 ping statistics —
2 packets transmitted, 2 received, 0% packet loss, time 1569ms
rtt min/avg/max/mdev = 0.338/33.814/67.290/33.476 ms
[root@localhost ~]#

在host机里ping UML的eth0:
[root@localhost tunctl-1.5]# ping 10.0.0.2
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.411 ms
64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.177 ms
^C
— 10.0.0.2 ping statistics —
2 packets transmitted, 2 received, 0% packet loss, time 1312ms
rtt min/avg/max/mdev = 0.177/0.294/0.411/0.117 ms
[root@localhost tunctl-1.5]#

可以创建多个tap虚拟网络设备,让UML创建更多的虚拟网卡:
[root@localhost tunctl-1.5]# tunctl -t tap2
[root@localhost tunctl-1.5]# ifconfig tap2 20.0.0.1
再以“./linux ubda=./rootfs mem=256m eth0=tuntap,tap1,, eth1=tuntap,tap2,,”执行UML即可。其它虚拟网络设备,比如ethertap、Multicast、switch daemon、slip、slirp等也都可以利用,这里有一套官方工具:http://user-mode-linux.sourceforge.net/uml_utilities_20070815.tar.bz2

5,利用uml_switch对UML虚拟机进行组网:
首先,使用uml_switch命令创建三台虚拟交换机:switch1、switchA和switchB,其中:
switch1的网络为10.0.0.0/24,并且其对应的tap1的host ip地址为10.0.0.1,启动和配置方式为:
[root@localhost af]# nohup uml_switch -tap tap1 -unix /tmp/switch1 &
[root@localhost af]# ifconfig tap1 10.0.0.1
switchA的网络为192.168.11.0/24,启动方式为:
[root@localhost af]# nohup uml_switch -tap tapA -unix /tmp/switchA &
switchB的网络为192.168.22.0/24,启动方式为:
[root@localhost af]# nohup uml_switch -tap tapB -unix /tmp/switchB &

接着,启用serverA,使其有两个网卡,一个连接switch1(eth0),一个连接switchA(eth1),启动serverA的命令为:
[root@localhost net_simu]# ./serverA/linux ubda=./serverA/rootfs mem=128m eth0=daemon,,unix,/tmp/switch1 eth1=daemon,,unix,/tmp/switchA
执行成功登陆UML系统后,可看到有两个网卡表示正常。

启动serverB,使其也有两个网卡,一个连接switch1(eth0),一个连接switchA(eth1),启动serverB的命令为:
[root@localhost net_simu]# ./serverB/linux ubda=./serverB/rootfs mem=128m eth0=daemon,,unix,/tmp/switch1 eth1=daemon,,unix,/tmp/switchB

启动clientA1,使其有一个网卡,连接switchA(eth0),启动命令为:
[root@localhost net_simu]# ./clientA1/linux ubda=./clientA1/rootfs mem=128m eth0=daemon,,unix,/tmp/switchA

启动clientB1,使其有一个网卡,连接switchB (eth0),启动命令为:
[root@localhost net_simu]# ./clientB1/linux ubda=./clientB1/rootfs mem=128m eth0=daemon,,unix,/tmp/switchB

启动clientB2,使其有一个网卡,连接switchB (eth0),启动命令为:
[root@localhost net_simu]# ./clientB2/linux ubda=./clientB2/rootfs mem=128m eth0=daemon,,unix,/tmp/switchB

做网络测试:
在clientB2上ping clientB1和serverB没问题,其它几个switch域内互ping也没问题;
在serverA上ping host机器OK,ping google的DNS服务器不行,那是当然的,需要我们再在host机器上加上NAT才能当UML的数据发送出去,先对host机器做如下设置:

[root@www ~]# echo 1 > /proc/sys/net/ipv4/ip_forward
[root@www ~]# iptables -F INPUT
[root@www ~]# iptables -F OUTPUT
[root@www ~]# iptables -F FORWARD
[root@www ~]# iptables -t nat -F POSTROUTING
[root@www ~]# iptables -t nat -F PREROUTING
[root@www ~]# iptables -t nat -A POSTROUTING -o eth3 -s 10.0.0.0/24 -j MASQUERADE

再试试ping google DNS服务器,就已经可以了。

6,试用总结
在2.6内核下(UML自2.6.9开始合入到kernel主线里),UML的使用非常的简单,它能做和不能做的总结如下:
1 调试内核代码流程 √
2 调试业务内核模块逻辑功能 √
3 抓取非硬件导致的oops和宕机 √
4 非法内存或空指针访问 √
5 进程请求资源死锁 √
6 非硬件因素导致的文件/文件系统损坏 √ 文件访问处断点
7 一台实体机器上运行多个UML实例 √
8 模拟复杂的网络环境 √
9 调试UML内普通进程 × 已被UML监控
10 调试intel网卡驱动 × 硬件相关皆无视
11 模拟高性能网络环境 × 网络性能很差
12 捕获SMP条件下才可能出现的问题 × X86_64 SMP待研究

转载请保留地址:http://www.lenky.info/archives/2012/08/1890http://lenky.info/?p=1890


备注:如无特殊说明,文章内容均出自Lenky个人的真实理解而并非存心妄自揣测来故意愚人耳目。由于个人水平有限,虽力求内容正确无误,但仍然难免出错,请勿见怪,如果可以则请留言告之,并欢迎来讨论。另外值得说明的是,Lenky的部分文章以及部分内容参考借鉴了网络上各位网友的热心分享,特别是一些带有完全参考的文章,其后附带的链接内容也许更直接、更丰富,而我只是做了一下归纳&转述,在此也一并表示感谢。关于本站的所有技术文章,欢迎转载,但请遵从CC创作共享协议,而一些私人性质较强的心情随笔,建议不要转载。

法律:根据最新颁布的《信息网络传播权保护条例》,如果您认为本文章的任何内容侵犯了您的权利,请以Email或书面等方式告知,本站将及时删除相关内容或链接。

分类: *nix技术, 跟踪调试 标签:
  1. 本文目前尚无任何评论.
  1. 本文目前尚无任何 trackbacks 和 pingbacks.