Linux到底在何时panic
遇到内核panic,我们很无奈,我们总是以为内核自动的检查出了错误,然后panic了,可事实上,panic是一个函数,需要显式调用的,panic机制固然是一种检查内核正常的好机制,可是其背后隐藏了大量内核开发者的心血,内核开发者必须知道什么情况下内核属于不正常状态,然后显式调用panic,如果此时不调用panic的话,说实话,系统还是会继续运行的,然而结果会真的“不可预料”,在遇到惶恐之事件的时候,最好的办法就是呆在原地,也就是panic。
对于纯程序员来讲,特别是习惯于使用“库”的程序员来讲,他们总是认为肯定“底层”会捕获错误的,唯一的例外是c语言的malloc/free,用malloc/free来阐述panic机制应该再好不过了。malloc的内存当然要在不使用的时候free掉,然而即使你free了,这个内存对于操作系统来讲可能还是可用的,也就是说在页表中还是具有映射的,只是对于程序来讲,它已经不能再使用了。操作系统和程序并不站在一个层次考虑问题,操作系统比程序更底层,由于设计原因它只提供机制,因此它并不知道内存的实际用处,它对内存访问的约束是很小的,只要求页表中有映射即可,然而程序却对内存的使用有着更多的依赖,且这种依赖并不为内核所知,因此应用程序必须自己管理内存的使用。
对于panic的机制而言,由于它是内核的机制,因此也不能指望更底层的机制发现错误并调用它,而是需要自己调用。更底层的无非就是cpu硬件了,对于cpu而言,它的约束更少,它只是顺序得从物理内存中取得一个指令,然后执行之,仅此而已,至于是什么指令它不管。如果它取出的不是指令,cpu会触发一个异常,异常号为6,在操作系统初始化的时候需要设置这个异常处理程序:
set_trap_gate(6,&invalid_op);
这也许是cpu提供的最后的措施了,你完全可以在6号异常的处理函数中什么都不做。接下来cpu只管不断取出指令不断执行。试想一种情况,如果panic函数所在的内存被清零了,会发生什么?panic还会调用吗?注意,cpu的hlt指令并不能使cpu停止运行,若想其停止运行,必须借助外部的电源电路。而且也不要觉得在操作系统中输入reboot之后系统就会重启,因此就认为cpu有所谓的复位功能,其实cpu并没有复位,而仅仅跳转到了计算机刚启动时实模式的某一个地址中去了。
现在先在/proc/kallsyms中找到panic的地址:
c126c156 T panic
我们根据linux的内存映射模型,知道panic的物理地址是0x126c156,于是我们执行下面的操作:
dd if=/dev/zero of=/dev/mem bs=1 count=128 seek=0x126c156
然后写一个module,在init函数中直接调用panic,这样我们在insmod的时候,内核会报段错误,因此即使你设置了kernel.panic=1,也不要指望系统在panic后1秒后重启,因为系统根本就不会panic了,panic已经没个球了。
正如应用程序员需要严守malloc/free一样,内核的编写者必须明确何时应该panic。