基于动态追踪的自愈操作系统故障监测技术
2015-04-14史佳龙朱怡安柴瑞亚
史佳龙,朱怡安,陆 伟,柴瑞亚
1.西北工业大学 计算机学院,西安 710072
2.西北工业大学 软件与微电子学院,西安 710072
1 引言
随着各类嵌入式系统应用日益广泛,对其可靠性和安全性的需求也随之提高[1-2]。具备自愈能力的操作系统可在无需人工干预的情况下自动发现、诊断并修复故障,进而使得操作系统在遭遇系统失效时,还能够继续为用户程序提供服务,可以有效减少当前操作系统内核在出现故障部分或全部服务失效时带来的损失[3],对提高系统可靠性有重要的意义。自愈操作系统中将系统的自愈过程抽象为监测、诊断和恢复三个自主元素,作为自愈操作系统对故障的感知手段,故障监测可以使操作系统具备自主发现故障的能力[4],是自愈操作系统实现自主故障定位诊断及恢复的基础,在自愈操作系统研究中具有重要的意义。当前已有的操作系统故障监测技术大都需要硬件支持或对系统代码进行修改,本文根据已有研究中对操作系统内核故障分类和故障点分布的研究,针对内核中动态内存分配和资源竞争相关故障提出了一种基于动态追踪的故障监测技术,在Linux操作系统中该机制利用操作系统支持的断点机制以可加载内核模块的形式实现,不需要对原系统进行扩展或修改,并通过故障注入实验对提出的监测技术的有效性从故障检测率、误报率、系统负载和监测延时几方面进行了验证。
2 基于动态追踪的故障监测技术
操作系统故障监测技术可分为基于异常事件、基于时间和基于系统性能指标三类。基于异常事件的监测技术主要通过感知系统中出现的异常事件来进行故障感知[5],其能够监测的故障类型有限,且一般需要对原系统代码进行修改;基于时间的监测典型代表为定时器机制[6],当系统出现故障导致定时器未被周期性重置时,则认为操作系统或某个部件出现故障,无法精确诊断出现了何种故障以及定位故障点,有时需要在原有系统中增加必要的软件模块或特定硬件;基于系统指标的监测技术通过对整体操作系统性能指标异常值的监测实现对故障的监测[7-8],通过故障映射模型实现较为精确的故障诊断,但模型的建立大都需要训练过程以达到较好的监测效果,可移植性无法得到保证。
已有研究中在设计故障监测技术时,大都没有对目标系统的故障分类和分布进行分析,故其适用性无法得到保证,当前已有的基于语义匹配的代码静态分析[9-10]和利用操作系统崩溃现场数据进行故障点分析[11]的研究结果表明,操作系统中的故障往往集中分布在特定内核位置。针对在操作系统中内核故障造成影响较应用程序故障更为严重的问题,Deshpande等人[12]进一步将操作系统的故障归结为以下四类:非法指针访问、程序逻辑中预先设定的崩溃点、内存泄露、同步机制的不恰当使用导致的资源竞争。四类故障中,除去人为设定的内核崩溃点,内核中的故障点集中于内存分配使用及回收、资源竞争同步等方面,且非法指针的访问造成在很多情形下是由于内存分配使用不当、同步不当导致的数据覆盖造成的。在Linux中由于内核程序共享执行空间,单点的故障会传播到整个内核进而影响其他程序的执行,甚至造成系统整体失效[13]。
针对Linux操作系统,基于以上内核故障点的分析,本文将内核中内存分配和资源竞争操作相关的故障作为主要监测目标,而此类操作在内核中往往表现为统一的方法调用(将其定义为内核关键方法),因此故障的产生与关键方法的不恰当使用存在直接的因果关系。通过动态追踪内核方法调用,可以对导致内核全局数据状态迁移的方法调用进行记录,依据设定的规则对记录的调用序列和数据进行分析,可实现对故障的监测和定位。图1中为本文提出的基于动态追踪的故障监测架构,内核动态追踪机制由三部分构成,监测断点定义模块设定需要监测的关键方法;监测数据采集模块用于记录系统调用的执行序列,将每次方法调用的内核上下文信息以及调用参数、返回值信息存储到监测信息链表中;故障诊断模块依据追踪信息和设计的规则进行故障诊断并输出诊断结果。
图1 内核动态追踪机制架构
自旋锁机制是操作系统中广泛使用的一种资源同步机制,已有的研究成果中也将其列为主要故障点,根据内核动态追踪架构,图2中描述了操作系统中监测自旋锁相关故障的过程,通过在自旋锁获取内核方法和自旋锁释放内核方法调用前后设置监测断点,可以对内核中获取和释放自旋锁的操作信息进行记录,并通过全局链表的方式进行保存,在进行内核信息采集时,需要注意分析当前方法调用导致的内核状态变化,确定断点处理程序类型为应当在关键方法之前或者之后执行,如当使用__raw_spin_lock_bh获取自旋锁时会关闭系统软中断,此时若要监测锁释放操作__raw_spin_unlock_bh则断点处理程序应当在释放锁关键方法之后执行,因为内核在关中断的状态下操作监测数据链表可能导致内核卡死。在进程调用do_exit方法退出时,检查监测队列中是否存在于当前要退出进程相关的记录,通过对记录中的信息分析进行故障诊断。
图2 内核自旋锁故障监测实例
Hector[13]、Lockout[14]使用代码静态分析的方法也实现了对内核故障点的追踪,但实际系统在运行过程中时,由于内核中中断、抢占等机制的存在,静态代码分析的故障追踪并不能完全发现系统中可能存在的故障,而本文中提出的监测技术可以侦测到内核中实际的调用序列和上下文信息,对故障实现更为有效的监测。
3 故障监测器实现
3.1 监测器架构
故障监测器由监测模块和数据显示两个主要模块构成,其中监测模块以可加载内核模块的形式实现,可以根据需求动态地加载到内核中运行,针对不同类型的故障可同时加载多个故障监测器,而数据显示模块在用户态实现,显示界面使用wxPython程序库设计实现,实现故障监测结果的显示,两个模块以系统日志为数据交互媒介。故障监测模块的实现包括监测点、监测数据链表和断点处理程序三部分,其中监测点可定义为Jprobe、Kretprobe和Kprobe三类,分别用于获取内核调用参数、返回值以及调用栈信息;监测数据链表用于存储监测信息;断点处理程序根据采集到的内核信息对监测数据链表进行维护,可令其在断点发生之前或之后执行,在程序退出时分析监测数据链表数据,从而进行故障诊断。
3.2 资源竞争故障监测
以自旋锁相关故障为例说明对资源竞争类故障的监测方法,主要是通过对锁获取函数、锁释放函数以及进程退出函数的监测实现对故障的定位诊断,其中使用的监测方法以及相应的断点处理程序功能描述如表1所示。
对于监测到的每一次锁操作,监测程序动态分配一个结构体来记录锁操作相关数据,监测记录结构体中会记录锁指针、获取锁的进程以及锁类型和当前进程执行上下文(flags),并维护一个监测记录链表来记录操作系统中当前锁的申请释放情况。在监测到某一个进程的释放锁操作后,查询监测链表并将其中对应的信息删除,在监测到某个进程的退出操作时(Linux中进程在退出时都会调用统一的接口do_exit),对监测链表执行相同查询过程,若发现不存在该进程相关记录,则说明该进程的锁操作没有出现获取而没有释放的错误,否则说明当前进程在退出时没有完全释放其占有的锁,可能造成资源竞争导致系统故障,此时监测程序会向系统日志中输出相关的故障信息,供显示模块读取。
3.3 动态内存分配监测
同对资源竞争类故障的监测原理相同,对内核动态内存分配的监测是通过对vmalloc和vfree以及do_exit方法的监测实现的,具体说明见表2。
对于监测到的每一次动态内存分配操作,监测程序动态分配一个结构体来记录内存操作相关数据,对于每一个动态内存分配操作,监测记录结构体中会记录分配的内存指针、获取内存的进程并维护一个监测记录链表来记录操作系统中当前动态内存的申请释放情况。监测链表的维护与自旋锁监测链表类似,若监测到当前进程在退出操作后存在未释放的内存时,说明当前进程出现了内存泄露故障,此时向系统日志输出相应的故障信息。
3.4 监测结果显示
关键方法监测模块以内核模块的形式根据监测需求动态加载到操作系统中在内核态运行,其监测信息会输出到系统日志文件中,用户态的显示程序会以固定的时间间隔读取日志文件中的信息,进行解析并显示在程序界面中,如图3中所示,从界面显示框中用户可以获取内核中每个进程申请释放锁和内存的信息,如288号进程获取了地址为f4a881eb的自旋锁,根据3.2节和3.3节中描述的监测规则若监测到当前系统中出现故障,显示模块会从系统日志文件中读取相应信息并显示。
表1 自旋锁相关操作监测方法列表
表2 内核动态内存分配相关操作监测方法列表
图3 监测结果显示界面
4 实验结果及分析
本文中采用故障注入实验的方法对故障监测器的有效性从故障监测率、误报率、系统的负载以及故障监测延时等方面进行分析验证。实验计算机配置为AMD速龙II双核 P360(2.3 GHz双核),2.0 GB内存,500 GB硬盘,内核版本为Linux 3.5。为了模拟系统真实的运行环境,在进行故障注入实验时选取了Unixbench 5.1.2测评集模拟系统运行负载,选用了多个负载测试集以保证对内核关键方法调用的覆盖率。故障库以内核模块的形式实现,在负载执行流中以一定的时间间隔动态加载到内核运行,并记录监测到的故障总数,通过系统在加载故障监测器加载前后的Unixbench在各个负载集下的系统评分,可以对故障监测器对系统造成的负载做出评估。
故障注入实验的故障库包含资源竞争(锁的不恰当使用如重复获取同一个锁、程序退出时不释放占用的资源)和内存泄露故障,分别选取context1、dhry、fstime、shell8、pipe、spawn、syscall、excel等标准测试集作为负载,在其正常执行流内分别注入上述两种类型的故障各50次,记录每个负载执行流在完成时监测到的故障总数,结果如图4所示,从结果中可知,监测器对79.25%的故障进行有效监测,但在shell8和execl负载流的执行上下文中不允许进行中断操作,否则会导致内核中数据不一致问题,甚至出现oops现象,而本文中设计的监测技术则需要利用中断产生断点进行信息采集,因此监测器在此时无法对内存泄露类故障进行有效的监测。在shell8和spawn负载中会产生大量并发进程并分配到两个CPU核上并发执行,由于每次创建进程退出进程操作都会执行断点处理程序,在短时间内会触发大量中断,kprobe断点机制在执行断点处理程序之前会产生int3和debug中断,在本实验中会导致系统死机,因此在spawn和shell8负载流下对资源竞争类错误的监测效果较差。
图4 故障注入实验结果
在context1负载集下进行内存泄露故障监测时,监测到的故障总数超过了50次,虽然可能是由于操作系统中存在内存泄露故障造成的,但本文中将监测到的非人为注入的故障视为误报,实验结果表明监测器在监测到的636次故障中仅存在两次误报。
监测器对整体系统的负载主要是由于在内核中产生中断采集监测信息以及对监测队列数据的维护造成的,Unixbench可以给出的在不同负载流下实验计算机在加载故障监测器前后的评分值,根据评分值可计算出监测器加载后系统性能下降了0.59%,故障监测器对系统造成的负载较小,具体评分值如图5所示。
图5 监测器负载分析结果
基于系统性能指标的故障监测技术中数据采样周期的设置会直接影响到故障监测延时,对该类型故障监测器进行故障监测延时评估的时候往往通过设置不同的监测周期来进行实验,研究[15]中提出的基于贝叶斯模型的进程级故障监测器在FDP和SWIMBOX两类负载下的故障监测延时分别为(100.26±136.76)ms和(100±33.33)ms;基于系统I/O吞吐量进行故障监器[16]仅使用了I/O吞吐量这一个性能指标,且没有复杂的故障判别模型,对于不同类型的故障监测延时差别较大,对于某些故障可能在很长的时间内无法进行有效的监测。
表3 基于时间的故障监测技术监测延时
基于时间的故障监测技术大都需要增加额外的硬件或者软件机制支持定时机制,带来了与具体进程或者系统的通信开销,根据在使用管道、Socket、无线网络三种通信方法[8]时其延时监测结果如表3中所示。
本文中提出的监测机制以内核模块的形式实现,可以动态地加载到内核中运行,采用中断的方式进行数据记录和分析,减少了与特定进程或者硬件进行通信的开销,故障监测延时实验结果如图6所示,从图中数据可知,监测的延时明显小于基于时间和系统指标的监测技术。由于对故障数据的采集和监测是通过中断方式实现,监测的延时不会受到监测器具体配置的影响如性能指标采样周期等。
图6 监测器故障监测延时实验结果
此外从实验结果中可以看出,对资源竞争类故障的监测延时要明显小于对内存泄露类故障的监测延时,这是由于资源竞争类故障往往和操作系统内的临界区相关,为了提高系统的整体运行效率临界区执行时间一般很短暂,且和多核中断抢占上下文相关,因此可在临界区执行结束退出时较快地侦测到故障,而对于内存泄露类的故障,由于其分配内存往往存在延时且可能导致该进程睡眠,因此对于此类故障监测的延时要长于资源竞争类故障。
5 结论
故障监测技术为自愈操作系统提供对故障的自主感知能力,是故障诊断和恢复的基础,根据已有的操作系统故障分布研究成果,本文提出了一种基于动态追踪的故障监测技术,通过三类监测点的插入可以有效地监测内核中动态内存分配和资源竞争相关的故障,并通过错误注入实验验证了该技术的可行性,实现的故障监测器可以在较低系统负载的条件下对注入的故障进行有效的监测,且故障误报率很低,监测延时较已有的基于时间和系统性能指标的监测技术明显降低。
[1]Barbosa R.Layered fault tolerance for distributed embedded systems[M].[S.l.]:Chalmers University of Technology,2008.
[2]Schneider C,Barker A,Dobson S.A survey of self-healing systems frameworks[J].Software:Practice and Experience,2014.
[3]Hamann P S,Perry R L.Compensation recommendations,US patent 20,140,032,382[P].2014.
[4]Asghari S A,Kaynak O,Taheri H.An investigation into soft error detection efficiency at operating system level[J].The Scientific World Journal,2014.
[5]Abaffy J,Krajcovic T.Software support for multiple hardware watchdog timers in the linux OS[J].Applied Electronics,2010:17-19.
[6]David F M,Campbell R H.Building a self-healing operating system[C]//Third IEEE International Symposium on Dependable,Autonomic and Secure Computing,2007:3-10.
[7]Zhu Y,Li Y,Xue J,et al.What is system hang and how to handle it[C]//Software Reliability Engineering(ISSRE).
[8]Abaffy J,Krajčovič T.Multiple software watchdog timers in the linux OS[M]//Emerging Trends in Computing,Informatics,Systems Sciences,and Engineering.[S.l.]:Springer,2013:759-765.
[9]Palix N,Thomas G,Saha S,et al.Faults in Linux:ten years later[C]//ACM SIGARCH Computer Architecture News,ACM,2011:305-318.
[10]Chou A,Yang J,Chelf B,et al.An empirical study of operating systems errors[Z].ACM,2001.
[11]Lisong L,Peter P,Tschudin S,et al.Oops!What about a Million Kernel Oopses?RT-0436[R].2013.
[12]Deshpande B D.System and methods for self-healing from operating system faults in kernel/supervisory mode,US Patent 20,140,032,962[P].2014.
[13]Saha S,Lozi J P,Thomas G,et al.Hector:detecting resource-release omission faults in error-handling code for systems software[C]//43rd Annual IEEE/IFIP International Conference on Dependable Systems and Networks.IEEE,2013:1-12.
[14]Kheradmand A,Kasikci B,Candea G.Lockout:efficient testing for deadlock bugs[R].2014.
[15]Bovenzi A,Cinque M,Cotroneo D,et al.OS-level hang detection in complex software systems[J].International Journal of Critical Computer-Based Systems,2011,2:352-377.
[16]Cotroneo D,Natella R,Russo S.Assessment and improvement of hang detection in the Linux operating system[C]//Reliable Distributed Systems,2009:288-294.