摘 要: 作为最流行的开源操作系统,Linux在各行各业得到了广泛的应用。因此了解Linux 内核的架构及工作机制就显得非常重要。然而目前对Linux 内核的主要学习途径是各种教科书以及经验博客,而对于Linux内核的实时动态监控技术却很少有人了解。本文提供一种动态监视内核运行过程的方法。通过此方法可以动态地观察Linux内核的函数调用情况,以及CPU寄存器值等动态信息。
关键词: Linux内核;实时;动态;函数调用
0 引言
众所周知Linux是目前公认的最好的开源操作系统。它被广泛应用于各行各业。因此对Linux内核的学习就显得尤为重要。目前对于Linux内核的学习一般都是通过以下几个途径。
⑴通过经典教材,这些教材一般由著名的Linux 内核开发者编写。比较常用的如参考文献[1-3] 。通过这些教材读者可以从宏观的角度去了解Linux内核的整体架构以及运行机制。但是由于教科书只能提供基于作者理解的内核架构,读者无法从中获得直观的内核的动态运行状况,而这点对加深内核的理解是非常有益的。
⑵通过Linux内核的邮件列表,Linux 的开发者可以从这些列表中与其他开发者交流遇到的问题。
⑶Linux内核的源代码。Linux 的源代码涵盖了Linux的所有实现细节,但由于源代码的数量非常巨大,所以开发者往往需要在了解了相关机制以后才可以定位代码片段的位置。
以上提到的是目前了解和学习Linux内核的一些主要途径,通过这些途径可以了解内核的大体运行机制。然而这些方法都存在一个相同的问题就是无法动态实时地反应内核的运行情况。而在分析Linux内核的运行机制尤其是在遇到通过函数指针的赋值调用的情况时能够动态实时地检测内核的运行情况是非常必要的。
本文将介绍一种基于 DDD (Data Display Debugger)[4]、 BusyBox [5]、QEMU(Quick Emulator)[6]工具来对Linux内核代码运行进行动态检测的方法。
1 相关实验工具简介
本文将利用QEMU[7]搭建一个虚拟机,同时用BusyBox[5]在虚拟机上搭建一个小型Linux文件系统,然后用命令行调试程序DDD[4]来监视Linux内核的运行情况。
1.1 QEMU简介
QEMU[7]是一套由Fabrice Bellard所编写的模拟处理器的自由软件。QEMU能模拟至接近真实电脑的速度。通过QEMU可以建立一个运行目标内核的轻量级的虚拟机,并可以像调试普通应用程序一样对虚拟机中的内核代码进行单步调试,从而可以很清楚地看到代码跳转过程、CPU寄存器的变化、内核堆栈的变化等内核动态运行信息。
1.2 DDD简介
DDD(Data Display Debugger)是命令行调试程序,它特有的图形数据显示功能可以把数据结构按照图形的方式显示出来。DDD的功能非常强大,可以调试用C\C++ 、Ada、Fortran、Pascal、Modula-2和Modula-3编写的程序。可以超文本方式浏览源代码;同时可以进行断点设置、显示各种数据结构之间的关系并由此将数据结构以图形化形式显示。
1.3 BusyBox简介
BusyBox集成压缩了 Linux 的许多工具和命令,也包含了 Android 系统的自带的shell。BusyBox将许多具有共性的小版本的Unix工具结合到一个单一的可执行文件。BusyBox提供了一个比较完善的环境,可以运行任何小的系统或嵌入式系统。
2 验证流程
2.1 实验环境
本文将在Linux发行版Ubuntu 12.04上搭建实验工具。
2.2 实验工具搭建说明
这个工具套件的环境搭建由以下几个步骤组成:
⑴编译内核
选用Linux Kernel 3.5.4的内核版本。在进行内核代码的验证之前先要对目标内核进行编译,用wget命令从内核服务器下载3.5.4版本的内核,在对其编译之后就能获得内核镜像文件bzImage。
⑵安装QEMU
从QEUM的官方网站[5]上下载QEMU的最新源码文件。而后切换到 QEMU 的源码目录输入./configure生成 makefile 文件。在完成后输入编译命令make 开始编译QEMU。最后用make install命令将QEMU安装到系统中。
⑶制作根文件系统
利用DD 命令建立一个大小为10 MB的磁盘镜像文件。本实验内核将运行在这个系统上。在完成后挂载刚刚生成的镜像。在镜像中建立Linux根目录下的文件夹dev、proc、sys。
⑷安装 BusyBox 到根文件系统
在BusyBox的官方网站[8]上下载最新的BusyBox 源码。切换到BusyBox的源码目录,输入命令 make menuconfig 配置编译选项。
在弹出的配置菜单中勾选静态编译的选项(BusyBox Settings→Build options→Build BusyBox as a static binary)。
完成后输入命令make 开始编译。最后用命令make install 把编译好的BusyBox文件系统安装到刚刚生成的镜像根文件系统中。
通过以上4个步骤就可以完成Linux内核运行验证系统的搭建。
3 验证演示实例
3.1 验证的内核模块
在本文中将演示验证Linux 内核中虚拟终端(TTY)子系统open操作的运行流程。通过阅读源代码,总结出TTY子系统open操作的主要流程如图1所示。
3.2 DDD中显示的内核运行结果
⑴因为在Linux内核中TTY设备被归于字符型设备,所以TTY初始化的第一步是将申请的设备描述结构体的open操作函数指针(def_chrfops->chrdec_open)赋值成字符设备open函数(chrdev_open)的函数指针。 程序代码如下:
const struct file_operations def_chr_fops = {
.open = chardev_open,
.llseek = nop_llseek,
};
⑵调用字符设备子系统的open函数进入char_open函数。相关代码如下:
static int chardev_open(struct *inode,struct file *filp){
struct dev *p;
struct cdev *new =NULL;
int ret = 0;
}
⑶检测内核kobject链表是否有TTY设备,如果找不到这个设备,则返回错误。其内核代码如下所示:
if(!kobj)
return -ENXIO;
new = container_of(kobj, struct codec,kobj);
spin_lock(&cdev_lock);
p = inode->i_cdev;
⑷运行内核 filip结构体的open函数。以下为相关代码:
if(filp->f_op->open){
ret = filp->f_op->open(inode,filp);
if(ret)
goto out_cdev_put;
}
通过DDD对Linux内核运行的检测结果发现,Linux内核中TTY子系统的打开操作的流程与我们通过源代码分析出来的结论是一致的。从而验证了我们流程图的正确性。
4 结束语
本文介绍了一个基于DDD、QEMU、BusyBox工具套件,对Linux内核进行动态检测的方法。通过该方法能够对这个Linux内核的实时运行情况进行监测,从而使内核学习者和研究者对Linux 的整个运行机制有了立体的了解,对内核的运行有直观深刻的印象。本文还以虚拟终端(TTY)子系统open操作为例进行了完整的分析。展示了这个方法对一个具体的应用场景进行动态分析的过程及通过这个套件捕捉到Linux内核函数指针的动态赋值及调用过程。
参考文献
[1] Bovet D P, Cesati M. Understanding the Linux Kernel [M]. O'Reilly,2006.
[2] Wolfgang Mauerer.Professional Linux Kernel Architecture [M]. Wiley India Pvt. Limited, 2008.
[3] Robert Love. Linux Kernel Development [M]. Addison-Wesley Professional, 2010.
[4] Zeller A, Lütkehaus D. DDD-a free graphical front-end for UNIX debuggers [J]. ACM Sigplan Notices [C]. 1996, 31(1): 22-27.
[5] Bellard, Fabrice. QEMU open source processor emulator [OL]. (2007-04-03)[2014-07-15]http://www.qemu.org (2007).
[6] Wells N. BUSYBOX: A swiss army knife for Linux [J]. Linux Journal, 2000, 2000(78es): 10.
[7] Fabrice B. QEMU, a fast and portable dynamic translator[C]. USENIX Annual Technical Conference, FREENIX Track, 2005.
[8] Andersen, Erik. BusyBox[OL]. (2008-01-19)[2014-07-15]http://www. BusyBox.net (2008).