【内核】深入分析内核panic(二)--内核中的少林扫地僧-NMI Watchdog Timer
没有完美的代码
没有完美的人,更没有完美的代码。虽然教科书上说deadlock(死锁)多么不好不好,但是在现实生活中,很难把它完全消灭。假设不小心内核出现了deadlock,可能你得干瞪眼。CPU就在那里空等着,空转着,叫天天不应,叫地地不灵。等到海枯石烂,CPU生锈的那一天,它还会那么痴痴地等着那个霸占了锁的家伙会良心发现,解下这个锁。
也许你会说,哎呀,这么麻烦干嘛?RESET一下,不就一了百了吗?但是如果是一台肩负重担的Server(服务器),在夜深人静你正呼呼大睡的时候发生了deadlock呢?如果deadlock的原因没有查到,三天五天就会发生一次,光这样被动的重启也不是办法……
不用说让人心惊胆颤的deadlock,很多时候,一段小小的循环,就会把你彻底雷到。我们总认为循环是可以结束的,但是别要忘记,事物都是辩证的,有的时候,碰巧发生了某些预料之外的条件,让这个循环成了彻彻底底的死循环。
恰巧此时,CPU的中断如果已经被禁掉,那神仙也救不了你。“我佛慈悲,能不能把循环给我停掉?”“阿弥陀佛,神仙也得遵守潜规则,你让我给你停掉循环,好歹也要给我一个中断,让我能够施法吧?”
……不能怪父母,更不能怪政府,如果你正好在电脑旁边,可以RESET;如果你不在旁边,就等着老板的电话吧。“小福啊,今天又超过100位客户打电话投诉我们的交友网站不能访问了,你赶紧打的到公司,看看是怎么回事。
赶紧啊!有个客户说,如果今晚12点之前不能登录网站,取得要约会的5位MM的详细资料,他就会携带人体炸弹到办公楼来砸场子……“
保留现场,强行重启
言归正传。如果应用程序进入死循环,我们可以把它KILL掉。如果内核因为意料之外的原因,导致系统进入无法自拔的死循环,最好的办法就是让系统给强行重启。
当然,这种重启最好是自动的,不需要人干预的,且最好能够打印出导致重启的原因,便于开发者调试错误。在Linux内核中,用NMI看门狗(NMI Watchdog Timer)的方式来实现该机制。
在系统的正常运行过程当中,每秒都有非常多的中断产生。即便它啥都不做,啥外部中断都不接收,每秒至少有数以百计的用来给线程调度的时钟中断。(如果调度时间片为10ms,则有100个时钟中断。)假设如果内核发现5秒钟之内,没有产生一个中断,那将会是怎么一回事呢?
这个时候,CPU会辩解道:“我兢兢业业地执行每一条指令,有没有中断不干我的事,叫我干啥就干啥,我是真正的劳动模范,不要怀疑我会捣鬼。
中断既来之,我就安之。不来之,则说明中断已经被禁掉了。肯定是有个幕后黑手已经调用CLI之类的指令关闭了全局的外部中断,然后偷偷摸摸干自己相干的事情,不被其他人给打断。人都有自己的隐私嘛,代码也不例外。
屏蔽中断,执行不被打断的代码,人之常情。但是用得不恰当,如同毒品一样,就会出现大问题。少量鸦片,可以当作药品;携带超过5克海洛因,就得上刑场。
禁掉中断占用一点点CPU时间,可以让程序很容易地绕开race condition(竞争条件);但是如果中断被禁掉的时间长达5秒钟,那就违反常理了。5秒钟之内系统不会有其他响应,其影响之深远,罪行之恶劣,不用满清十大酷刑简直不足以平息民愤……”
“该杀!该杀!”这个时候,内存,芯片组,硬盘……所有硬件都附和。看来CPU还是一直是IT届的老大。不怪我们不客气了,赶紧打印出现场(CPU出现LOCKUP时的相关上下文,包括寄存器值,函数调用栈等),且记入LOG,作为判案的证据,同时有警示后人只用。接着,就对施以极刑,给内核来一个oops,彻底终止它的执行,让它重新启动。
少林扫地僧——NMI
不对,不对!也许你有这样的感觉,既然5秒之内没有一个中断,基本肯定中断是已经被禁掉了,那CPU就被迫只会一直执行那段有问题的代码,根本没有机会来执行所谓的“保留现场,强行重启”的代码。
这些代码放在内核的另外一个地方,要调用它,必须由中断出发。可是,可是中断不是已经被禁了吗?借尸还魂?恐怖,恐怖……
“再厉害的黑社会,也斗不过我们人民警察!”这个时候,CPU又冷笑了,“虽然中断被禁掉了,但是,我还拥有秘密武器。那就是Non-maskable interrupt,不可屏蔽中断,简称NMI。你要禁,只能禁掉一般的可屏蔽中断。NMI,我压根就让你摸不着,碰不着!”
原来,内核中隐藏着一个神秘的高手,那就是NMI。我们调用spin_lock_irq,虽然能够禁掉本地的中断,但是NMI却不行。
内核中设置了一个watchdog timer,它的中断类型就被置为NMI,每过一定的时间,这个timer就执行一次,用来悄悄监视系统的运行。
如果系统正常,它啥事都不做,仅仅是更改一些时间计数;如果系统不正常(默认5秒没有任何普通外部中断),那它就闲不住了,会立马跳出来,且中止之前程序的运行。该出手时就出手!
我想到了在血腥的武林当中,有无数的高手。刚开始的时候,似乎人人都是高手;但后来,昔日的高手看起来都是菜鸟,强中更有强中手。再后来,更高的高手出来了,开始这里论剑那里比武,争霸天下了。
最后来,天下也许是第一第二的高手开始决战……似乎故事就这个时候结束了,但是让人大跌眼镜的是,一个小小的少林扫地僧,却能轻易地两位顶尖高手制服。
NMI就是这样的角色,平时从不站在前台,也很少为人所知。除了用NMI watchdog timer监测系统是否锁住之外,一些特殊的严重的硬件错误,比如内存奇偶校验错等,也会触发NMI的发生。不过这些错误,估计很多人从来不会碰到过。
More
如果出现死循环的地方没有把中断禁掉,那是不是不会触发NMI watchdog timer了呢?
理论上是的。至少Linux2.6的抢占内核应该不会触发。但是,由于系统还是有机会调度到其他线程,所以整个系统可能响应很慢,但不至于给死掉。我们可以通过top命令查看进程状况等手段来进行分析。
不是所有的Linux内核都支持NMI watchdog timer的。必须在内核中添加APIC的支持。(现在的内核和硬件一般都是没有问题的)如果是x86-64的硬件体系结构,APIC是被默认支持的。
在很多发行版本当中,需要在启动的时候添加内核启动参数nmi_watchdog=N来启动NMI watchdog timer。N代表了该timer的source,如果为1,表示利用IO APIC的始终源;如果为2,表示利用LOCAL APIC的performance counter。
具体哪个好用,可以分别测试一下,一般来说,比较新的CPU(一般都是双核了)选择2的话,系统负担更小一点。想要更多的了解NMI watchdog timer,请看如下的kernel文档
http://www.kernel.org/doc/Documentation/nmi_watchdog.txt
想要知道啥时APIC(注意不是ACPI),啥是IO APIC,啥是LOCAL APIC,那就请google一下吧。
原文链接:https://blog.csdn.net/freemancqcsdn/article/details/4499100 版权归原作者所有,如有侵权,请联系作者删除
【内核】深入分析内核panic(二)--内核中的少林扫地僧-NMI Watchdog Timer的更多相关文章
- 【内核】linux2.6版本内核编译配置选项(二)
目录 Linux2.6版本内核编译配置选项(一):http://infohacker.blog.51cto.com/6751239/1203633 Linux2.6版本内核编译配置选项(二):http ...
- linux内核--内存管理(二)
一.进程与内存 所有进程(执行的程序)都必须占用一定数量的内存,它或是用来存放从磁盘载入的程序代码,或是存放取自用户输入的数据等等.不过进程对这些内存的管理方式因内存用途不一而不尽相同,有些内 ...
- Linux内核启动代码分析二之开发板相关驱动程序加载分析
Linux内核启动代码分析二之开发板相关驱动程序加载分析 1 从linux开始启动的函数start_kernel开始分析,该函数位于linux-2.6.22/init/main.c start_ke ...
- 小说接入UC浏览器内核技术对话(二)
质辛@灿岩 质辛跟我们说一下那个删除文件的逻辑吧质辛@灿岩 应该不是删除cache下所有文件吧?质辛质辛@智鹰 提供一下我们的临时文件完整路径给 灿岩吧质辛@智鹰 是负责我们ucsdk的 技术对 ...
- kernel:NMI watchdog: BUG: soft lockup - CPU#6 stuck for 28s! CentOS7linux中内核被锁死
环境说明:虚拟机 CentOS7中解压一个8G的包时,内核报错 Message from syslogd@cosmo-01 at Apr 25 11:05:59 ... kernel:NMI watc ...
- Netlink 内核实现分析(二):通信
在前一篇博文<Netlink 内核实现分析(一):创建>中已经较为具体的分析了Linux内核netlink子系统的初始化流程.内核netlink套接字的创建.应用层netlink套接字的创 ...
- ARM-Linux内核移植之(二)——Linux2.6.22内核移植
平台:mini2440 交叉工具链:arm-linux-gcc-4.3.2 一.内核移植基本知识 移植内核也叫构建BSP(boardsupprot packet).BSP的作用有两个:一是为内核运行 ...
- 抢占式内核与非抢占式内核中的自旋锁(spinlock)的差别
一.概括 (1)自旋锁适用于SMP系统,UP系统用spinlock是作死. (2)保护模式下禁止内核抢占的方法:1.运行终端服务例程时2.运行软中断和tasklet时3.设置本地CPU计数器preem ...
- 用户空间和内核空间通讯之【Netlink 中】
原文地址:用户空间和内核空间通讯之[Netlink 中] 作者:wjlkoorey258 今天我们来动手演练一下Netlink的用法,看看它到底是如何实现用户-内核空间的数据通信的.我们依旧是在2.6 ...
- Linux内核驱动学习(二)添加自定义菜单到内核源码menuconfig
文章目录 目标 drivers/Kconfig demo下的Kconfig 和 Makefile Kconfig Makefile demo_gpio.c 目标 Kernel:Linux 4.4 我编 ...
随机推荐
- 海上液化天然气 LNG 终端 | 图扑数字孪生
关于 LNG 液化天然气 (Liquefied Natural Gas,简称 LNG) 在能源转型过程中被广泛认可为相对较清洁的能源选择. 相对于传统的煤炭和石油燃料,LNG 的燃烧过程产生的二氧化碳 ...
- 【UniApp】-uni-app-修改组件主题和样式
前言 好,经过上个章节的介绍完毕之后,了解了一下 uni-app-扩展组件 那么了解完了uni-app-扩展组件之后,这篇文章来给大家介绍一下 uni-app-修改组件主题和样式 首先不管三七二十一, ...
- 一个适用于定制个性化界面的WPF UI组件库
前言 今天给大家推荐一个能让你用最少的代码来实现期望的UI效果,适用于定制个性化界面的WPF UI组件库:Panuon.WPF.UI. 组件库官方介绍 Panuon.WPF.UI 是一个适用于定制个性 ...
- Grafana系列-Loki-基于日志实现告警
系列文章 Loki 系列文章 前言 实际应用中除了基于 Metrics 告警, 往往还有基于日志的告警需求, 可以作为基于 Metrics 告警之外的一个补充. 典型如基于 NGINX 日志的错误率告 ...
- springboot去除内嵌tomcat
springboot去除内嵌tomcat步骤 在pom文件中加入以下代码 点击查看代码 <!-- 多模块排除内置tomcat --> <dependency> <grou ...
- ESP32 IDF iic通信( 已验证) C语言
关于iic原理建议B站自己看视频去, 然后本文主要实现了esp32的初始化, 写地址, 写数据, 读数据的功能, 从机的代码因为展示不需要,没写. 园子里面有个兄弟写了iic的代码.但是里面有点毒,多 ...
- vue3 + element-plus 的 upload + axios + django 文件上传并保存
之前在网上搜了好多教程,一直没有找到合适自己的,要么只有前端部分没有后端,要么就是写的不是很明白.所以还得靠自己摸索出来后,来此记录一下整个过程. 其实就是不要用默认的 action,要手动实现上传方 ...
- Altas&Ranger快速入门
Altas&Ranger快速入门 一.元数据 企业内部远行多种类型的数据库,有关系型数据库.非关系型数据库.图数据库.时序数据库等,常见有mysql.redis.Mongodb.oracle. ...
- 鱼和熊掌兼得:C++代码在编译时完成白盒测试
摘要:如果能够让代码在编译的时候,自动完成白盒测试,这不是天方夜谭. 白盒测试也叫开发者测试,是对特定代码函数或模块所进行的功能测试.当前主流的白盒测试方法是:先针对仿真或者生产环境编译出可执行文件, ...
- 轻松带你学习java-agent
摘要:java-agent是应用于java的trace工具,核心是对JVMTI(JVM Tool Interface)的调用. 本文分享自华为云社区<Java动态trace技术:java-age ...