首页 | 旧版 |中国计算机报 |中国电子报 |通信产业报 |计算机用户 |电脑教育报 |软件世界 |数字时代
高级检索
特别报道 | 评析 | 封面故事 | 企    业 | 系统平台 | 专家 | 行  业
CIO 之声 | 管理 | 应    用 | 产品主题 | 专    栏 | 报告 | 新安全
第12期 总第269期
浏览往期
当前位置:首页>>赛迪媒体>软件世界>开源
内核测试与调试
作者:Intel开源技术中心 尤永康 

内核作为Linux最关键的部分,其稳定性决定了系统的稳定性,而层出不穷的补丁为内核的修复带来了诸多问题,做好内核的测试与调试将是确保内核稳定的关键。

图1 AutoTest功能测试结果截图

开源造就了Linux世界的丰富多彩。在众多的程序员高手的努力下, Linux的应用范围不断扩大,功能不断增强,内核平均两到三个月就会升级一次版本。但是,内核开发人员常常需要花费大量的时间来查找并修复由于各种补丁程序引入的新问题。一旦某些严重的问题不能被及时发现,这将给修复带来更大的难度。因此开发人员们希望能通过好的内核测试来适应内核的快速变动,及时发现各种问题。

内核功能测试

Linux内核(以后简称内核)从功能上可划分为文件系统,内存管理,进程管理,外设管理,网络等几个部分。对内核特殊功能的修改和新功能的添加,极易引起连锁反应,导致其他功能的破坏。因此修改内核功能必须十分谨慎,修改后最好进行充分的测试。

Linux操作系统可分为两个运行级别,内核态和用户态。内核态掌控计算机资源的分配,用户态提供友好的界面同用户进行交互。用户态的程序不能直接使用系统资源,但它们可以通过内核提供的系统调用进入内核态完成请求的操作。Linux系统的两级设计方式增强了系统的安全性,但是却给测试内核带来了不便。测试人员无法像测试应用程序一样编写程序直接测试。尽管如此,系统还是有一些手段帮助我们实现对内核的测试。

通常测试内核功能的方式有如下4种:

◆通过内核提供的各种系统调用,测试内核功能的完整性;

◆把测试程序作为内核的一部分来测试,例如把测试程序写成内核模块,插入到内核中动态运行;也可以直接把测试程序编译到内核中,然后直接运行带有测试程序的内核;

◆通过内核和用户态的接口来进行交互测试,例如proc文件系统,sys文件系统;

◆通过内核调试程序进行内核测试。

在这四种方法中,系统调用测试是相对简单易行的方法。它的缺点是无法准确测试内核内部功能。第二种测试方法由于涉及具体的内核模块编程,本文不会涉及。第三和第四种测试方法会在内核调试一节中介绍。

Linux Test Project(简称LTP)是目前较为流行的Linux基本功能测试工具集。LTP包含了总多子功能测试模块,例如系统调用,系统命令,内存分配,磁盘读写,文件系统,网络,数学运算测试等等。系统调用的测试集包含约700个测试用例,基本上覆盖了大部分的系统调用。它们通过传递不同的参数来模拟正常或错误的调用,以达到测试的目的。内存测试反复测试系统各种分配和回收不同大小内存的能力。磁盘读写主要测试系统对文件大小和数量的读取和存储。数学运算测试主要测试系统的整数和浮点数运算。

测试人员还常常使用压力测试来检测系统在压力环境下的工作能力。LTP项目中有一个叫Crashme的测试,它包含有几个经典的测试用例:随机产生并执行机器指令;随机产生并执行系统调用;尽可能的不断分配和消耗系统内存;递归查询/proc文件系统中所有文件的内容;尽可能的不断fork子进程。执行这些压力测试用例可能会导致有缺陷的内核发生系统崩溃。

为了达到快速检查内核变动的能力,繁重的内核测试任务需要有自动化的实现。内核测试自动化的设计与普通应用程序测试自动化的设计并无太多区别,它主要包含以下几个方面:内核源代码自动化的下载,自动化的编译,自动化的安装,自动化的测试并报告测试结果。AutoTest是目前比较有名的自动化内核测试项目,由Martin J. Bligh发起并维护。它实现了一套较为先进的自动测试框架,并提供了一套接口供现有的测试工具(例如LTP)进行集成。当发现有新的Linux内核需要测试时,AutoTest便会生成一系列的测试任务,然后把测试任务分配到不同的Client Harness上进行环境准备和执行测试,最后把收集到的测试结果进行分析和发布。图1是AutoTest部分测试结果的截图,纵轴为内核版本的变迁,横轴是不同的测试平台。

内核功能测试中需要注意的问题有:

◆内核程序除了可以动态加载的模块(module)外,重新编译和安装内核,需要重新启动测试机;

◆内核缺陷不仅难于重现,并且在对不健康的内核进行测试时,容易导致系统崩溃,需要及时保存测试数据;

◆当内核中发生系统故障的时候(系统打出oops消息),就算不会导致系统崩溃(panic),也可能导致正在使用的系统资源丢失,例如设备不可用,内存无法回收。

内核性能测试

虽然Linux内核的功能不断扩大,版本不断上升,但是它性能却稳中有降,这已经引起包括Linus在内的Linux社区同仁的关注。内核开发人员和用户希望能得到准确的内核性能测试报告,来帮助开发人员及时定位和修复异常的性能下降。与内核功能测试类似,内核性能测试既可以针对特定应用软件测试系统的整体性能,也可以分别测试特定功能模块的性能。

编译包含大量功能模块的内核,会占用较大的系统内存,消耗大量CPU调度时间,进行大量的磁盘IO操作。不过由于它方便运行,内核编译常被用来作为一种简单的内核功能测试,它运行的快慢也可以作为快速测试系统性能的指标。

业界有许多标准的性能测试工具被用户广泛使用。例如,CPU2000(它的新版本是CPU2006)分别包含测试CPU整数和浮点数性能的CINT和CFP;Netperf主要用于测试各种网络连接方式下的传输性能;Sysbench可以测试包括内存分配,文件读写,进程调度,多线程以及数据库操作等在内的多种指标;Iometer则是专门测试I/O子系统性能的工具。

性能测试最初只注重速度和能力,但随着环保和节能越来越被人们所重视,能耗比成为了一个重要的指标。能耗比就是系统性能和能源消耗的比率,比值越高代表机器在相同的耗电量下可获得更好的性能。能耗比的测试不仅需要监控在最大系统性能的情况下,整机消耗能源的多少,还需要监控在系统空闲的情况下,是否能够利用ACPI的功能节省过多的能源消耗。目前内核这方面的测试还是一个比较新的领域。

内核性能测试与功能测试类似,也需要有自动化的帮忙,为此Kenneth Chen发起了Linux Kernel Performance(简称LKP)项目。该项目集成了性能测试的几个典型的测试工具(kernelbuild,netperf,aim,cpu2000等等)。

每当有新的内核版本发布时,它都会在几个典型平台上自动运行测试,及时获取性能数据。图2截取了LKP项目的一组性能测试结果,从图中可见由于测试的内容不同,每个测试结果曲线的变化也不一致。由此可见内核整体性能的好坏,不能只比较某一种性能测试的结果。

在进行内核性能测试时,需要注意的以下几个问题:

◆为了使采集的数据具有可比性,每次性能测试的环境和参数必须保持一致;

◆由于某些性能测试(例如测试磁盘IO)具有较大数学的方差,因此需要通过重复多次求平均值的方法来得到理想的数值;

◆细微的参数区别也可能会导致测试结果的巨大波动,因此需要通过调整参数值达到比较理想的测试结果;

◆相比功能测试工具,不同的性能测试工具在输入参数和输出结果上差别很大,给自动化测试系统的集成带来了难度。

内核调试

由于内核运行的独特性,一般的软件调试工具无法针对内核进行跟踪调试。对内核开发人员来说,最常用的调试手段就是利用printk来打印出相关的参数。printk通常都会把相关的信息输出到控制台,并记录在系统日志文件(/var/log/messages)中。

/proc和sysfs文件系统是Linux系统提供的一种特殊的内存文件系统。它们可以向用户传递内核掌握的信息,并能接收从用户方来的相关设置。根据/proc文件系统的特点,用户可以先在/proc文件系统中添加相关的文件,然后通过读写新添加的文件来进行信息交互。

当然,相比prink和/proc文件系统来说,调试器还是有着动态、实时的优点。GDB是Linux系统中最常见的调试器。由于GDB不能把内核程序运行在自己的控制之下,因而无法进行修改内核数据,设置断点和单步调试等操作。不过它可以对内核结构进行简单的查询操作,例如查看内核变量。在有内核符号表的情况下,GDB还可以实现打印结构,跟踪指针等操作。

内核开发人员也开发出一些能够调试内核的工具,例如KDB和KGDB。KDB是一种内置的内核调试器。除了查询数据外,KDB可以实现修改数据,设置断点,单步调试,反汇编等功能。

当在控制台按下Pause键或当内核发生oops时,都会触发KDB进入内核调试状态。KGDB与GDB远程调试功能一样。它需要通过串口把被调试系统和运行调试的系统连接起来,这样就可以进行远程内核调试了。KDB和KGDB都需要对内核打一些特别的补丁才能使用。

内核调试的新手段

随着虚拟技术的流行和其他调试方法的出现,内核调试技术也得到了进一步的发展。开发人员可以在同一台机器上,利用UML或者Xen相对轻松地调试客户机(Guest OS)的内核,也可以利用Kprobes和SystemTap来动态的获取内核信息。

用户模式Linux(UML)运行在基于Linux系统调用接口所实现的虚拟机之上。它可以在现有的Linux系统上再启动一个Linux。对UML的用户而言,他会感觉自己的Linux和原Linux占有相同的资源,但实际上UML只不过是运行在原Linux上的一个用户进程。这就给GDB留下了施展拳脚的舞台,于是用户就可以像调试普通程序一样来调试UML的内核了。不过由于UML只是通过原Linux的系统调用来进行资源访问,这使得UML的内核无法直接控制主机的硬件,从而难于调试硬件驱动程序。此外,UML目前还不支持SMP(对称多处理器),因此只能调试运行在单处理器上的内核。

Xen的HVM客户机在充分利用CPU虚拟化技术(VT)的基础上,外加了对常用设备(磁盘、网卡、终端、键盘、鼠标、串口等等)的模拟支持(利用Qemu来实现)。在虚拟的世界里,客户机上的Linux无需进行任何修改,就可以与CPU以及各种模拟的设备打交道。利用Xen的HVM来debug内核是由Nitin A. Kamble实现的,它的原理同KGDB有些类似,但是使用Xen的内核调试方法是将GDB和一个添加有Xen调试功能的gdbserver(对gdbserver的修改,可以在Xen的源代码树中获得)都放置在本机的服务系统(Service OS)上,再利用Xen提供的函数以及VT技术来实现对客户机内核的调试。它和KGDB不同的是,利用Xen的内核调试只需要在同一台机器上即可以完成。另外,HVM客户机可以支持SMP。不过鉴于设计的通用性和复杂性,Qemu所模拟的硬件设备并不是最新的设备,这使得目前的HVM客户机无法调试新的硬件设备驱动程序。不过当Xen全面支持VT-D技术后(预计在Xen 3.1.1中),HVM客户机将能直接独立访问某些具有DMA能力的系统硬件资源,到时调试网卡和磁盘就会变的更加便利了。当然,这种新的调试方式,需要用户的硬件设备支持VT和VT-D的功能。

Kprobes是Linux 2.6.9版本集成的新功能。它可以通过编写内核模块,在内核中设置断点。当内核运行到断点位置时,就会触发用户编写的Kprobes的程序,例如打印变量值或者寄存器值。Kprobes程序最大的好处是,可以动态的在内核中加入自己调试的代码,而无需重新编译内核。这给已发生一定问题的内核提供了一个有效的检查方法。

SystemTap工具利用Kprobes的功能来实现更为方便的内核诊断。它集成了语言的检查重组,编译,插入内核,跟踪指定程序,结果输出等一系列操作。用户只需要编写脚本语言,就可以方便的跟踪内核中的函数,来获取想要的变量值。SystemTap脚本语言的语法类似C和Shell,可以直接引用内核中的变量名,容易被用户学习和接受。不过为了使用SystemTap来调试内核,系统需要安装包含完整调试信息的内核包。

以上讲述的动态调试工具很难处理已经崩溃的系统。通常调查系统崩溃最好的方法就是保存(dump)系统崩溃时的所有信息(例如CPU寄存器的值,内存中的数据等等),然后再进行分析。Kdump是一种可以保存系统崩溃时状态的新方法,它利用了Kexec技术,能在系统崩溃的时候快速进入另一个预先准备好的内核,由第二个内核完成对信息的dump,从而保存了系统崩溃的事故现场。

图2 LKP项目性能测试结果截图

链 接

内核社区邮件格式

1.使用纯文本格式,HTML会被认为是垃圾邮件,Rich-text格式不能在纯文本的邮件客户端很好的显示,不要张贴MS Powerpoint或者Word文件;

2.使用_tricks_强调,而不要用大写的SHOUTING;

3.Outlook的用户请保持每行最多70个字符,并且使用hard breaks;

4.Outlook用户请不要使用”recall”试图收回错误的贴子,因为只有exchange邮件服务器才支持这个功能。

赛迪网JAVA专区,JAVA开发者乐园!
相关文章
· 通往BI 2.0的五项革命(续)(2007.07.03)
· 软博会打造中国软件第一展(2007.07.03)
· 因特网之父(2007.07.03)
· VPN代替IPSec?(2007.07.03)
· SSL VPN更需改进(2007.07.03)
·特别专辑

专题:iPhone手机美国上市 明年进入亚洲全文
专题:默多克有望50亿美元购得道琼斯全文


· 专题:互联星空涉黄SP被封杀中电信加强监管
· 专题:赛门铁克同意赔偿用户 但无现金补偿
· 专题:联想启动奥运火炬手全国公开选拔
· 专题:杨致远接替塞梅尔出任雅虎公司CEO
· 专题:微软9405万入股长虹 将长期战略合作
· 专题:万名博客集体网络搬家搜狐新浪激情PK
· 专题:苹果推新Safari 浏览器市场再燃战火
· 特别报道:2007第11届中国国际软件博览会
· AMD首发图形显示新品Radeon HD 2000系列
· 专题:电子支付条例将公布 注册门槛1亿起步

·赛迪社区