电脑“闲”下来时,CPU 真的在休息吗。
大家都觉得电脑不用的时候,CPU就没事了,所有人都这么想的,但是,真的就这么简单吗。
电脑闲下来,我们只是看看网页,不动鼠标,那种时候,CPU在干什么,大家都在想,它是在休息吗。
打开电脑的任务管理器,或者linux的系统监控,就能看到CPU的使用率,一般情况下,打开了很多程序,CPU占用率可能只有百分之几,比如百分之八,这可能说明电脑没啥事,那剩下的时间呢,CPU跑哪里去了。
如果CPU占用率很高,那可能出问题了,有可能是哪个软件出bug了,也可能是中毒了,总之,得查查,但是,今天说的不是这个,所有人都知道该怎么解决,这不重要。
重要的是那个“系统空闲进程”,它占了CPU的绝大部分时间,可能有百分之九十九,甚至更高,这才是我们需要关注的地方,它到底是什么,它在干什么,大家都在想。
代码,一开始只是文本文件,写在编辑器里,程序员写,然后,通过编译,变成二进制文件,就是exe或者elf,这取决于操作系统,操作系统再把它们加载到内存里,变成进程。
操作系统也得有自己的“协议”,得知道怎么识别这些文件,怎么把它们加载到内存,然后运行,这很关键,不然,根本实现不了,想想就可怕。
操作系统会给程序分配内存,代码放一块,数据放一块,堆栈也得有,还得给它一个“身份”,就是进程,这样,程序才能跑起来,不然,操作系统都不知道该怎么办。
就像银行排队,操作系统也得管理这些进程,把它们放到队列里,一个一个来,不然,乱了套,事情就麻烦了。
进程有优先级,操作系统会根据这个来决定先跑哪个,后跑哪个,重要的先来,不重要的等等,这很公平,至少操作系统是这么想的。
操作系统调度的本质,就是让CPU不停地跑不同的进程,切换来切换去,看起来好像所有程序都在同时运行,但其实,CPU一次只能跑一个,所有人都知道。
如果所有进程都跑完了,那怎么办,操作系统总不能停下来吧,或者,一直判断有没有进程要运行,那也太浪费资源了,大家都在想,有什么更好的办法。
所以,操作系统就创建了一个永远不会为空的进程队列,里面放一个特殊的进程,这样,就不用一直判断队列是不是空的了,省事多了,大家都在想,这办法真聪明,有点绕。
这个特殊的进程,在Windows下叫“系统空闲进程”,在Linux下是0号进程,反正名字不一样,但是,作用一样,本质相同,大家都明白,不难理解。
这个空闲进程,永远都准备好了,但是,它的优先级最低,只有在没有其他进程要运行的时候,才会轮到它,大家都在想,这才是真正的工具人。
CPU设计的时候,就预留了一个指令,叫halt,这个指令可以让CPU进入休眠状态,降低功耗,不然,CPU一直跑着,电费都要交不少,谁都受不了。
空闲任务进程的核心,就是一个循环,不停地执行halt指令,让CPU睡觉,省电,等有活了,再叫醒它,继续干活,就这么简单,所有人都能理解。
但是,halt指令不是谁都能用的,它属于特权指令,只能在内核态下执行,普通的程序没资格用,想想也是,要是随便一个程序都能让CPU睡觉,那还得了。
挂起进程,比如用sleep函数,和halt指令不一样,挂起只是让进程暂停一下,但是,CPU还在跑别的进程,而halt指令是让CPU整个都停下来,进入休眠,这完全是两码事,不能混淆,要区分开来。
Linux内核代码里,空闲进程的核心逻辑就是执行halt指令,汇编代码,看起来有点复杂,但其实就那么几行,不难理解,所有人都觉得,这玩意儿真有用。
实际的空闲进程,比想象的要复杂,还要考虑CPU的睡眠模式,选择哪种模式更省电,还要预测CPU空闲的时间,看看多久进入休眠比较合适,这里面有很多细节。
CPU大部分时间都在执行halt指令,处于低功耗状态,这才是真相,并不是我们想象的那样,CPU一直在忙,它其实很闲,大家都在想,有点颠覆认知。
在个人电脑上,halt指令可能是CPU执行频率最高的指令,想想就觉得不可思议,我们以为CPU一直在算数,其实,它大部分时间都在睡觉,很真实。
很多人看完这个故事,都会去想,电脑的运行方式,比我们想象的要复杂得多,也巧妙得多,我们只是用了冰山一角。
