- 论坛徽章:
- 0
|
本帖最后由 kirapangzi 于 2013-08-28 09:37 编辑
基于对浏览如下两个CU帖子,以及自己项目里的问题;
1,紧急!Linux内核2.6关于NMI的处理!
http://bbs.chinaunix.net/forum.p ... mp;fromuid=28788494
2,求教育,关于NMI watchdog
http://bbs.chinaunix.net/forum.p ... mp;fromuid=28788494
发现最新的kernel中对于nmi watchdog的实现,与ULK3书中已经大不一样,且与现在网上较多能找到的资料(2.6版本 nmi_watchdog.txt)也不一样了;
下面的分析基于3.6.11内核源码与lockup-watchdogs.txt内核文档:
首先,为了让自己的逻辑清晰,将看门狗机制分为两部分:
1,喂狗部分(主角在人);2,狗是否咬、叫唤,是对于是否已经喂狗的判断(主角在狗);体现在内核狗中,即是否触发panic(需要其他参数配合)。
lockup-watchdogs.txt文档简述(仅限LZ自以为理解的。。):
内核可作为看门狗,检测软锁死:20s 内核没有调度;硬锁死:10s CPU没有其他中断产生;当启动参数选择nmi_watchdog=panic后,配合panic的sysctl参数(或启动参数)可以实现硬锁死后重启的效果;
(此处进一步查看内核启动参数文档,nmi_watchdog的取值已经没有2.6版本中的1、2了,而是0、panic、nopanic三个取值)
实现:软、硬锁死的检测,分别地,都基于hrtimer和perf子系统;(此处的红字,将在下面的源码中分析)
1,硬锁死部分:
喂狗:在每个hrtimer中断处理中(watchdog_timer_fn),会去步进percpu类型的hrtimer_interrupts 变量;
狗咬:简单的讲就是每watchdog_thresh周期的perf 类NMI中断来的时候,检查一下上面的hrtimer变量是否增加;没增加,表示CPU已经不响应中断了;
详细的讲。。就好复杂了,perf子系统是最近新出的一个特性,LZ基本不懂,也没有太多的资料,仅仅是找到代码路径,用于参考。
首先见下图,是perf子系统的一个函数注册调用图,用于在watchdog_nmi_enable 启动硬狗时,将硬狗的狗咬函数watchdog_overflow_callback 注册到处理器的pmu(performance monitor unit)中断处理中;
然后,perf子系统的中断源,其实是NMI中断(见init_hw_perf_events,将上述的pmu irqhandler 注册为nmi 中断handler);
再然后,每次nmi中断处理do_nmi中,会首先调用nmi_handle 处理per cpu的nmi中断请求;此时,便会walk到之前硬狗的狗咬检测;
2,软锁死部分(简单多了)
喂狗:一个内核线程被调度到时,刷新时间戳;
狗咬:在hrtimer中断处理中(对,与硬狗同一个handler中),先唤醒上面的线程;检查时间戳;然后决定是否叫唤;
下图是,内核注册整个软硬狗的函数调用图:
最后,试着回答一下之前两个帖子的问题,结合实验结果,部分属于推测:
1,依照ULK3书中所讲,可能在之前的旧版内核中,NMI中断是与LOC中断同步的,这样在cat /proc/interrupts当中,两者的数目基本相同,这样的NMI开销是非常大的;
但在新内核中,NMI中断数明显小于LOC:- [root@2 ~]# cat /proc/interrupts
- CPU0 CPU1
- 0: 130 0 IO-APIC-edge timer
- 1: 9 0 IO-APIC-edge i8042
- 5: 0 0 IO-APIC-edge parport0
- 8: 1 0 IO-APIC-edge rtc0
- 9: 0 0 IO-APIC-fasteoi acpi
- 16: 0 0 IO-APIC-fasteoi pata_via
- 23: 635 0 IO-APIC-fasteoi ehci_hcd:usb1, ehci_hcd:usb2
- 41: 15706 2664673 PCI-MSI-edge ahci
- 42: 851 0 PCI-MSI-edge i915
- 43: 159625 0 PCI-MSI-edge p6p1
- 44: 13 0 PCI-MSI-edge mei
- 45: 832 0 PCI-MSI-edge snd_hda_intel
- NMI: 100 278 Non-maskable interrupts
- LOC: 302917 279373 Local timer interrupts
- SPU: 0 0 Spurious interrupts
- PMI: 100 278 Performance monitoring interrupts
- IWI: 0 0 IRQ work interrupts
- RTR: 1 0 APIC ICR read retries
- RES: 107515 16093 Rescheduling interrupts
- CAL: 1255 1083 Function call interrupts
- TLB: 0 0 TLB shootdowns
- TRM: 0 0 Thermal event interrupts
- THR: 0 0 Threshold APIC interrupts
- MCE: 0 0 Machine check exceptions
- MCP: 43 43 Machine check polls
- ERR: 0
- MIS: 0
复制代码 我的理解是,NMI中断原来的触发方式因为开销太大已经没有再使用了;而perf子系统则是主动的依照watchdog_thresh时间去定制nmi中断(硬件的知识太匮乏,此处属猜测),从而达到平衡响应速度和开销的目的。
2,touch_nmi_watchdog()的调用时机:
不谈在我看代码的过程中这个函数给我的困扰了;你可以看到,整个软硬狗的喂狗、狗咬的部分都与该函数无关了,是吧?也就是它与看门狗的主体机制是无关的;
下面再简单概括下这个函数到底干点啥:就是设置标记或变量,让狗咬的时候,看到这个标记,就不再继续监测是否喂过狗了,直接返回;(硬狗:设置了watchdog_nmi_touch变量;软狗:清除了watchdog_touch_ts计数;)
有啥用:当内核在处理某些特殊任务的时候,不希望受到这只狗的打扰,能自我保证当前系统的状态是正常或异常的(也就是处于自知的状态);查看它的调用,如:kdb_bt(kgdb单步调试中),panic(panic time大于零时的循环等待中)等等;
疑问:请熟悉perf和hrtimer的大牛们讲解一下这两个子系统啊,尤其是perf子系统的底层中断硬件实现,google没弄出个一二三。。
|
|