您的位置:首页 > 运维架构 > Linux

建立UML(user mode linux)的linux内核调试环境

2012-10-23 17:32 246 查看
其实调试内核我最喜欢的还是print,因为它很灵活,这基本上是一个万能的东西,但是print总是需要自己去找对位置然后写上合适的print语句,有时还要为print一个东西而作很多准备工作。如果很复杂的时候可能要在很多点放置print,然后重新编译一遍,再跑一遍再看,如果不行还要再重新写,这就是print的局限性(但我还是乐此不疲

)。由于print的缺点我们会去寻求其它的调试内核的手段,下面要说的就是其中一种调试手段——UML。

注意,UML这里不是统一建模语言,而是User Mode Linux的缩写,从字面上也可以理解出来,是在用户态运行linux内核,把内核当作一个应用程序在跑,这样我们就可以用调试应用层程序的方法调试内核了,应用层的强大调试工具gdb就派上用场了。很多时候我们写内核代码,当遇到算法比较复杂但又不涉及底层结构的时候总是喜欢现在应用层实现并调试,然后在写到内核层。为什么,就是因为用户层调试比内核调试方便。但是局限性也说了,就是不能涉及底层,所以UML的最大局限性就是不能调试硬件关联性强的代码,但是还有有很多方面可以应用的,比如调度算法、VFS等。用gdb像跟踪用户程序一样跟踪这样的代码,相信你一定非常感兴趣,那么让我们马上开始第一步——搭建一个UML测试环境。

我是在debian6.0系统上操作的,内核是2.6.32版本。我现在所在的目录是我的家目录下的VM目录下( ~/VM/ ),在这个目录下我创建如下几个目录:

mkdir -p UML/kernel/

mkdir -p UML/mnt/debian/

mkdir -p UML/disks/

我在kernel里放着我要编译成UML内核的linux内核源码。disks目录用于存放一个从/dev/zero中dd出来的制作的设备文件。mnt/debian/目录用于挂载上面的设备文件,这个目录除了挂载时使用以外基本没用。

第一步你需要安装编译内核的软件,什么gcc啊、make啊、tar啊该装的都给它装上,有时你可能还需要libstdc++,哦对了,还有容易遗忘但是编译前第一步就需要的libncurses-dev包(名字可能不完全一样)。

第二步你需要一个linux内核源码,找一个你想要调试的版本,下载下来解压。进入源码目录就行了。如果你不知道到哪里去下载linux代码,参考www.kernel.org。我把它下载下来放到了kernel目录下。

第三步,编译前配置内核(确定你已经进入linux内核的第一层目录)。执行

" make ARCH=um menuconfig "

命令你将会看到类似如下的画面:



注意ARCH=um是必不可少的,否则就不是编译UML平台的内核了。如果编译过正常平台下(如amd64, i386,ppc等)的内核的人会发现,这个配置列表和以往的有一些不同,这就是ARCH=um的作用,我们现在要配置的是一个要跑在应用层的内核。除了选上你需要的功能对应选项以外,还有一些选项是必要为UML选的:

在UML-specific options--->Host Processor type features--->Processor family里选择你的处理器平台,我的是amd处理器,我选择了Opteron/Athlon64/Hammer/K8。如果你发现有Generic x86 support配置(不一定会出现),请保证它不生效。

Character devices中的stderr console, Virtual serial line, null channel support, port channel support, pty channel support, tty channel support, xterm channel support等是需要选中的。

Enable loadable module support 在UML中一般是不需要的,可以取消它,当然你不取消也没关系。

Networking support 里的Amateur Radio support, IrDA (infrared) subsystem support, Bluetooth subsystem support等的也是可以去掉的。而UML Network Devices里的东西是需要依据具体情况而定的,我这里就使用了默认的配置,如果你有特殊需求还请根据自己的需求选。NetLabel subsystem support我选了,因为我需要调试网络标签。

Block Devices---> Virtual block devices需要选中。

File systems嘛……这个就比较复杂了,我需要使用Ext3文件系统,比且需要扩展属性支持,所以我选择了Ext3 journalling file system support及其下面的Ext3 extended attributes。至于你需要什么就自己选吧。

Security options是我的关键,我需要调试安全机制,所以里面我选择了很多比如:Enable different security models,Enable the securityfs filesystem, Socket and Networking Security Hooks, Security hooks for pathname based access control, File POSIX Capabilities等。

SCSI device support中可以不需要。

Multiple devices driver support也可以不需要。

Kernel Hacking是一个比较重要的,需要选中Kernel debugging, Compile the kernel with debug info这两个需要选上,Show timing information on printks可以选上,其它的选项根据你要调试需求自己选择。

好了,配置好后你就可以保存退出了。

第四步,编译UML内核,执行下面的语句:

" make ARCH=um linux"

同样ARCH=um是必须的,后面那个linux的意思是把编译出来的vmlinux作一个硬链接到linux。然后就可以静静的等待编译的完成,这个编译过成会很快,不像我们平时编译内核时那么慢。因为这是一个UM的,所以很多驱动是不用编的,这就大大减少了编译的时间,大概五分钟左右就可以编好。

执行ls -li linux vmlinux可以看到

21055358 -rwxr-xr-x 2 zorro zorro 29501657 10月 23 14:05 linux

21055358 -rwxr-xr-x 2 zorro zorro 29501657 10月 23 14:05 vmlinux

已经有了一个UML的内核,下面呢?如果让它跑起来?这让我想起了Richard Stallman大师上次来和我们交流的时候最喜欢说的一句,"not linux, is GNU+Linux!!",我们总是把我们使用的系统叫Linux系统,其实应该叫GNU/Linux系统,Linux只是提供了一个核心,要想构成一个系统还需要GNU的软件。好了,答案出来了,我们还需要GNU的软件来构成一个可以运行的系统。这一步的工作就是构建一个最小环境。

第五步,构建运行环境。让uml的内核跑在一个独立出来的运行环境中,我们需要一块磁盘,并在这块磁盘上作一个文件系统,再在上面作一个可运行的最小系统。先用下面的命令创建一块并格式化为Ext3文件系统:

mkdir disks

dd if=/dev/zero of=disks/um-root bs=1024K count=1000

mkfs.ext3 disks/um-root

然后建立一个目录,把上面的设备挂载到这个目录上,执行:

mkdir -p mnt/debian

mount -o loop disks/um-root mnt/debian/

查看一下挂载有没有成功,执行:

" mount|grep mnt/debian "

得到如下的结果

/dev/loop0 on /home/zorro/VM/UML/mnt/debian type ext3 (rw)

证明disks/um-root设备已经作为/dev/loop0挂载到了mnt/debian/目录上,且是ext3文件系统,而且可读写。 现在mnt/debian下就挂载着我们作出来的这个“设备”,下面我们要在这个设备上安装一个可运行的系统,至少是一个最小系统。

如果你对系统组成很了解,你可以自己构建最小系统,如果你不是很了解,没关系,debian为你提供了一个命令让你可以从debian一个正常源中获取到一个最小系统到本地。因为我是在debian squeeze6.0系统上,所以我执行:

" debootstrap squeeze mnt/debian/ http://ftp.debian.org/debian "

在chroot-squeeze目录下构建了一个debian最小系统,这个chroot-squeeze就是你指定一个目录,最小系统就创建在这里,到时你可以chroot进来。如果你安装了debootstrap包,你的网络是畅通的,你输入的源地址又正确,你输入的命令格式也正确,你的硬盘足够大,那么你现在就可以去喝杯茶了,程序员一定要注意你的颈椎和腰椎等等,这个下载的过程在带宽是1M而且源比较流畅的情况下大概需要半个小时,好了去上个厕所或者出去抽根烟(抽烟有害健康)或者去作个广播体操再回来





这里有个小小的提示,如果你有心想了解最小系统组成的话,可以把上面那个命令的输出打印到一个文件里,因为它会列出它安装的所有软件包,然后你课下再对软件包进行研究。当然这个命令装下来的也不一定就是可以最小最小的运行系统。

……

……

做完广播体操回来我们的最小系统就完成了,第六步,到了这里你的系统就是一个没有配置过的基础系统。你需要对里面一些基本的配置文件进行配置,比如:

/etc/fstab

/etc/hostname

/etc/hosts

/etc/network/interfaces

/etc/apt/sources.list

/etc/securetty

/etc/inittab

上面的路径都是相对上面搭建的最小系统所处的目录(mnt/debian/)为根目录说的,注意千万不要修改我们host机的配置文件。如果到这句你不明白我说的是什么请不要进行下面的操作,否则后果自负。如果你不明白可以询问明白的人。

1. 对于/etc/fstab可以配置如下

/dev/ubd0 / ext3 defaults 0 1

proc /proc proc defaults 0 0

2. 对于/etc/hosthame文件可以配置如下:

uml

3. 对于/etc/hosts文件可以包含如下一行:

127.0.0.1 localhost

4. 对于/etc/network/interfaces文件可以配置如下:

auto lo

iface lo inet loopback

5. 对于/etc/apt/sources.list可以配置一个软件源,比如:

deb http://ftp.debian.org/debian squeeze main

但是我相信你用上面的debootstrap命令安装一个最小系统后这个源应该已经配置好了,如果有其它配置需求可以修改。

6. 对于/etc/securetty文件可以执行如下命令作配置:

echo "tty0" >> /etc/securetty

echo "ttys/0" >> /etc/securetty

7. 下面需要检查一下有没有一个节点为我们挂载使用,进入mnt/debian/dev目录,执行如下语句:

cd mnt/debian/dev

ls ubd*

如果没有输出udb0的话那么就需要创建这么一个设备,执行如下:

mknod --mode=660 ubd0 b 98 0

chown root:disk ubd0

8. 如果你想在boot起系统后立即就登录,那么你可以修改/etc/inittab文件,把

1:2345:respawn:/sbin/getty 38400 tty1

的tty1改为tty0,如下:

1:2345:respawn:/sbin/getty 38400 tty0

9. 最后你需要创建一个用户,修改root口令,在host机上执行:

chroot mnt/debian

adduser uml-test

passwd root

然后设置密码和其它信息就完成了,你可以通过su - uml-test切换到这个用户尝试一下。修改这个最小系统的root密码是为了你用uml-test用户登录后能su到root上。

10. 接着上面一步, 配置完后我们可以为系统安装需要的软件或文件,如果你不需要什么多余的东西安装进来,那就可以跳过这步。

如果你的网络畅通,那么你现在chroot进去还可以安装很多别的软件。比如我觉得我的最小系统里需要安装一个attr和sudo的软件包,那么执行:

apt-get install attr sudo

就可以在这个刚做好的最小系统里安装attr和sudo软件包,这个作用是很需要的,因为我们在UML条件小调试内核的时候需要借助这个最小系统构成的应用层的工具。比如我需要使用setfattr设置扩展属性,然后在内核中读出来,那么我就需要这个最小系统里有设置扩展属性的工具。以后每需要对最小系统作操作的时候都可以这样作,这个最小系统是根据我们调试内核时对运行环境的需要而修改的。

第七步,启动UML+最小系统。先保证从刚才的chroot中出来,chroot mnt/debian。然后保证卸载了挂载在mnt/debian上的disks/um-root,“umount mnt/debian”(一定不要忘了卸载)。接着就可以启动UML了,执行:

./kernel/linux ubd0=disks/um-root

如果你想要使用gdb跟踪启动就执行:

gdb ./kernel/linux

然后在gdb的命令行下输入:

(gdb) set args ubd0=disks/um-root mem=128M

(gdb)r

这样就可以运行起来了,对于gdb的使用这里就不再赘余了,因为这篇记录性文字不是说gdb的。但是gdb的使用很关键,如果你想用gdb很好的调试UML那么就你就需要能熟练的使用gdb,否则你会发现你调试起来会困难重重。

上面所说的配置也不一定就按照我说的来,比如制作一个运行系统和使用UML配合启动的方法还有很多其它的东西可以做,比如这里我没有做网络设备和交换分区等等,如果感兴趣的人可以继续研究,有更好建议的可以留言,我这里就抛砖引玉了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: