电脑死机的时候到底在干什么

2016-2-18 admin

这个问题,详细回答的话可以写一本书了。。。所以就挑重点吧。这里只讨论Windows系统。

首先软件还是硬件,说实话我见过也不知道所谓硬件死机是怎么一回事,难道是CPU停止执行下一条指令了?当然我并不熟悉硬件方面的东西,只能说真*硬件死机在我的知识范畴之外了。

抛开硬件死机,我们可以认为CPU总是兢兢业业地根据当前EIP的值来执行下一条指令。那么大部分我们见到的死机,发生时其实CPU还是在不停地工作的,只不过由于某些原因没能执行到用户所期待的代码。

最简单也是最厉害的就是当前CPU在执行于某个高IRQL的时候出不来了。IRQL是决定CPU执行代码的优先级,大部分的Windows及应用程序的代码都执行在DPC级别以下,而像中断处理代码则执行在DPC以上。那么如果某个CPU在执行一个中断处理的时候,由于代码原因死循环了,比如自旋锁永远自旋出不来了,这个CPU就废了,不能再执行更低IRQL的代码。只有更高级别的中断才能把这个CPU抢过去。

DPC级别以下,基本上就是通过我们熟悉的线程来执行各种代码了,而线程之间基于线程优先级来决定先执行哪个线程。这里包括内核态执行的线程和用户态执行的线程。大部分我们见到的“死机”,其实都是在这个级别“死”住的。

那么一个线程为什么会死住,以及他是如何影响到其他线程的呢?这里主要就是由于Windows的各种复杂的同步锁机制。最常见的现象,线程1在等某个锁,这个锁由于某种原因一直没被释放,那么线程1只能一直等下去。然后线程1可能自己拿了其他的一些锁,那么这些锁也无法被释放,其他在等这些锁的线程也会被迫等待。就这样连锁反应,最后大部分的线程都在等锁,你就看到“死机”了。

这种一般出现在内核态的锁,比如著名的registry lock,一旦某线程拿到注册表锁之后死住,其他所有企图访问注册表的线程都会死掉,那基本上就都死了。

而在用户态,一般来说用户态的锁只会影响当前进程,也就是最多你会发现某个程序死了,窗口发白,但是其他程序还正常。但是也有些用户态的锁是跨进程的,比如以前见过wininet里面的一个锁,所有进程共享,一旦锁住之后,所有进入到wininet操作的线程都会死掉。

然后说下为什么一个锁会死掉出不来,这基本上都是软件代码的bug。最经典的deadlock,A等B,B等A,永远出不来。这事只要学过一丁点计算机基础就都明白,大家都知道要按固定顺序加锁。然并luan,在实际代码中各种锁的关系实在是太复杂了,或者说整个Windows的代码实在是太复杂了,程序员很难保证所有的锁都是按固定顺序获取,这种bug真心在所难免。比如像著名的loader lock,就是每次载入dll时候要拿的锁,由于各种程序员写的dllmain里面做的那些奇奇怪怪的事情,这家伙和别人发生死锁的概率实在是太高了--就算你在MSDN里面写的再明白也没有用。我并不是在说小白程序员,就连windows内部的某些dll还是有过不少与loader lock死锁的问题,当你的代码复杂了之后真的会想不清楚锁的关系。

其实这时候windows在最核心的线程调度方面,还是在正常工作的。只不过发生的情景是这样的:

调度代码开始调度:线程A,你来执行吧。
线程A:我不行啊,我在等锁。
调度:线程B,你行不行啊?
线程B:我也不行啊,我在等A。
调度:还有谁现在能跑的?
。。。。
某线程X小声地说:我可以。
调度:你谁啊?

线程X:我就更新下系统时间的,打打酱油,不用等锁。

著作权归作者所有。
商业转载请联系作者获得授权,非商业转载请注明出处。
作者:Tim Chen
链接:https://www.zhihu.com/question/33576170/answer/83849491
来源:知乎

发表评论:

Powered by emlog