日常工作中,电脑是大多数人都在用的工具。
那肯定所有人都有碰到过电脑蓝屏死机,或者是Mac上的5国语言报错吧。
那么你有没有深入的想过,电脑死机的时候,它到底在干些什么呢?今天这一期,就来聊聊这个事。
电脑死机有好几种,一种是比较彻底的,屏幕被冻结,或是直接蓝屏和黑屏,你只能按下电源键来强制重启。
而另一种是鼠标还能移动,但点按都没反应,并且鼠标的图标变成沙漏或是转圈。这种时候,按下键盘上 CTRL+ATL+DELETE,还能调出任务管理器,强制关闭未响应的程序还能让电脑恢复的。
所以可以说电脑死机,也就是计算机的核心“中央处理器CPU”出了问题。
上过计算机基础课的同学们一定知道一个原理。CPU是一根筋死脑筋,只知道不断的取出指令来一条一条得执行,直到关机为止。好在现在的电脑都具有多核心了,要是像几十年前的老电脑,一旦多开几个重量级应用,那运行缓慢,死机等情况都会如约而至。主要原因是同一时间给到CPU的指令太多,CPU一下子运算不过来了,后续的指令就需要前一条完后再来处理。但是加上一些程序本身设计的原因,CPU等待的时间大于了程序本来预设的超时时间,就造成程序前后断链,使得CPU跳过了原本要运行一段指令,转而运行后面的指令去了。这样就造成CPU自己也懵了圈,怎么就驴头不对马嘴了。就好比怎么这人进门的时候是男的,出门就变成女的了。CPU进入逻辑错误,被困在一个地方出不来了,使得后续的程序无法执行,就变得像是死机一样了。
这就是软件层面的死机。
但如果有人说,CPU这么容易死脑筋,那我写一段永远循环的代码让CPU自己跑起来那也能像病毒一样让电脑死机崩溃了?其实没这么简单。虽然电脑可能会风扇全力运转,但是计算机却依旧能正常工作,并没有死机。唉?这不就前后矛盾了吗?前面说CPU是一根筋的,怎么现在让它被困在原地却还能运行呢?
那么就要提到另一个概念“中断”。
中断这个概念,绝对是计算机史上最伟大的发明之一。
中断,顾名思义,用于打断CPU正常的工作,让它去执行别处的指令程序。
操作系统之所以能够掌控全局,就得益于它启动时给CPU安插的一系列的中断处理函数(比如我们最常见的时钟中断),好让操作系统能周期性的收回CPU的执行权,调度别的线程来执行。
所以,即便你某个线程进入了死循环,在给你时间片用完之后,穿插的中断函数就会起作用,查看是否还在正常运算,如果不正常,就把出问题的应用给踢出CPU运算队列,让别的程序来执行。
所以,想用一个死循环程序就把电脑搞死机,那自然是不可能的。
退一万步讲,就算不考虑中断的影响,现在的CPU大都是多核,一个线程进入死循环,但还有别的核可以参与系统调度,也依然不会死机。
那么问题又来了,既然有中断,那为什么CPU还是会被困在原地里死机出不来了呢?
这其实有两种情况:
- 中断优先级不够
中断在运行时,也有优先级的概念。
这很容易理解,比如CPU正在执行程序,突然发生了一个中断事件。CPU保存好当前执行的上下文,转头去处理这个中断事件,但刚处理到一半儿,这时又有一个新的中断事件来了,那CPU怎么办?要不要响应?这时,就要看谁的官大听谁的。
所以,低优先级的中断无法打断高优先级的中断。
有了这个前提来试想一下,如果由于操作系统内核代码写的不当,在处理某个中断的时候陷入了死循环,会发生什么?
因为在处理中断的时候,CPU运行在一个很高的优先级上,一般的中断是无法把执行权抢过去的,这就导致这颗CPU核心成为了“植物人”,怎么叫它都没反应了。也就死机了。
2.中断能抢到CPU,但发现没有进程程可以调度
这里又有一个新的概念,死锁。
死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。
这里可以有一个比喻,2辆公交车并排准备出同一个站头,由于出站门只能同时出一辆车。于是调度说(也就是CPU说)A车你先出,A车说不行,因为驾驶员还在B车上,B车你先出。B车说也不行,按照规定我是一定要等你A车出了以后才我能出的(优先级没你高)。A车说那你开门让驾驶员下来,B车说那也不行,你不先出去我开不了门。最后CPU蒙圈得说,那先谁也别出了,就在门口把事情绕清楚再说。等待良久CPU又说,还是A车你先出,A车说不行,因为驾驶员还在B车上。。。 于是循环又开始了。
如果这个死锁发生在应用层面,那问题不大,最多就是两个程序死了。但如果发生在内核呢?
比如在Windows操作系统内核中,就有大量的全局性的锁,一个不小心造成死锁,其他想要的线程都得进入等待队列,那就凉凉了。
所以死机时,电脑不是真的罢工了,而是在内部的逻辑中反复运算。尝试能让自己说服自己。但往往这些折腾都是徒劳的。最终还是直接拔电源重启来的干脆。
那这,就是电脑死机时发生的那点事。归根到底,程序的设计上有BUG,造成通道堵塞引起CPU进入循环出不来。但程序上的BUG是永远存在,修复老BUG会有新BUG的出现。工程师能做的,就是尽量得精益求精,但无法十全十美。