有趣! CPU 空闲时在干嘛?

人在空闲时会发呆会无聊,计算机呢?

假设你正在用计算机浏览网页,当网页加载完成后你开始阅读,此时你没有移动鼠标,没有敲击键盘,也没有网络通信,那么你的计算机此时在干嘛?

有的同学可能会觉得这个问题很简单,但实际上,这个问题涉及从硬件到软件、从 CPU 到操作系统等一系列环节,理解了这个问题你就能明白操作系统是如何工作的了。

你的计算机 CPU 使用率是多少?

如果此时你正在计算机旁,并且安装有 Windows 或者 Linux ,你可以立刻看到自己的计算机 CPU 使用率是多少。

这是博主的一台安装有 Win10 的笔记本:

可以看到大部分情况下 CPU 利用率很低,也就在 8% 左右,而且开启了 283 个进程,这么多进程基本上无所事事都在等待某个特定事件来唤醒自己,就好比你写了一个打印用户输入的程序,如果用户一直不按键盘,那么你的进程就处于这种状态。

有的同学可能会想也就你的比较空闲吧,实际上大部分个人计算机 CPU 使用率都差不多这样(排除掉看电影、玩游戏等场景),如果你的使用率总是很高,风扇一直在嗡嗡的转,那么不是软件 bug 就有可能是病毒。。。

那么有的同学可能会问,剩下的 CPU 时间都去哪里了?

剩下的 CPU 时间去哪里了?

这个问题也很简单,还是以 Win10 为例,打开任务管理器,找到 “详细信息” 这一栏,你会发现有一个 “系统空闲进程”,其 CPU 使用率达到了 99%,正是这个进程消耗了几乎所有的 CPU 时间。

那么为什么存在这样一个进程呢?以及这个进程什么时候开始运行呢?

接下来我们从操作系统讲起。

代码、进程与操作系统

当你用最喜欢的代码编辑器编写代码时,这时的代码不过就是磁盘上的普通文件,此时的程序和操作系统没有半毛钱关系,操作系统也不认知这种文本文件。

程序员写完代码后开始编译,这时编译器将普通的文本文件翻译成二进制可执行文件,此时的程序依然是保存在磁盘上的文件,和普通没有本质区别。

但此时不一样的是,该文件是可执行文件,也就是说操作系统开始 “懂得” 这种文件,所谓 “懂得” 是指操作系统可以识别、解析、加载,因此必定有某种类似协议的规范,这样编译器按照这种协议生成可执行文件,操作系统就能加载了。

在 Linux 下可执行文件格式为 ELF ,在 Windows 下是 EXE 。

此时虽然操作系统可以识别可执行程序,但如果你不去双击一下(或者在Linux下运行相应命令)的依然和操作系统没有半毛钱关系。

但是当你运行可执行程序时魔法就出现了。

此时操作系统开始将可执行文件加载到内存,解析出代码段、数据段等,并为这个程序创建运行时需要的堆区栈区等内存区域,此时这个程序在内存中就是这样了:

最后,根据可执行文件的内容,操作系统知道该程序应该执行的第一条机器指令是什么,并将其告诉 CPU ,CPU 从该程序的第一条指令开始执行,程序就这样运行起来了。

一个在内存中运行起来的程序显然和保存在磁盘上的二进制文件是不一样的,总的有个名字吧,根据“弄不懂原则”,这个名字就叫进程,英文名叫做Process。

我们把一个运行起来的程序叫做进程,这就是进程的由来

此时操作系统开始掌管进程,现在进程已经有了,那么操作系统是怎么管理进程的呢?

调度器与进程管理

银行想必大家都去过,实际上如果你仔细观察的话银行的办事大厅就能体现出操作系统最核心的进程管理与调度。

首先大家去银行都要排队,类似的,进程在操作系统中也是通过队列来管理的。

同时银行还按照客户的重要程度划分了优先级,大部分都是普通客户;但当你在这家银行存上几个亿时就能升级为 VIP 客户,优先级最高,每次去银行都不用排队,优先办理你的业务。

类似的,操作系统也会为进程划分优先级,操作系统会根据进程优先级将其放到相应的队列中供调度器调度。

这就是操作系统需要实现的最核心功能。

现在准备工作已经就绪。

接下来的问题就是操作系统如何确定是否还有进程需要运行。

队列判空:一个更好的设计

从上一节我们知道,实际上操作系统是用队列来管理进程的,那么很显然,如果队列已经为空,那么说明此时操作系统内部没有进程需要运行,这是 CPU 就空闲下来了,此时,我们需要做点什么,就像这样:

if (queue.empty()) {do_someting();
}

这些编写内核代码虽然简单,但内核中到处充斥着 if 这种异常处理的语句,这会让代码看起来一团糟,因此更好的设计是没有异常,那么怎样才能没有异常呢?

很简单,那就是让队列永远不会空,这样调度器永远能从队列中找到一个可供运行的进程。

而这也是为什么链表中通常会有哨兵节点的原因,就是为了避免各种判空,这样既容易出错也会让代码一团糟。

就这样,内核设计者创建了一个叫做空闲任务的进程,这个进程就是Windows 下的我们最开始看到的“系统空闲进程”,在 Linux 下就是第 0号进程。

当其它进程都处于不可运行状态时,调度器就从队列中取出空闲进程运行,显然,空闲进程永远处于就绪状态,且优先级最低

既然我们已经知道了,当系统无所事事后开始运行空闲进程,那么这个空闲进程到底在干嘛呢?

这就需要硬件来帮忙了。

一切都要归结到硬件

在计算机系统中,一切最终都要靠 CPU 来驱动,CPU 才是那个真正干活的。

原来,CPU 设计者早就考虑到系统会存在空闲的可能,因此设计了一条机器指令,这个机器指令就是 halt 指令,停止的意思。

这条指令会让部分CPU进入休眠状态,从而极大减少对电力的消耗,通常这条指令也被放到循环中执行,原因也很简单,就是要维持这种休眠状态。

值得注意的是,halt 指令是特权指令,也就是说只有在内核态下 CPU 才可以执行这条指令,程序员写的应用都运行在用户态,因此你没有办法在用户态让 CPU 去执行这条指令。

此外,不要把进程挂起和 halt 指令混淆,当我们调用 sleep 之类函数时,暂停运行的只是进程,此时如果还有其它进程可以运行那么 CPU 是不会空闲下来的,当 CPU 开始执行halt指令时就意味着系统中所有进程都已经暂停运行。

软件硬件结合

现在我们有了 halt 机器指令,同时有一个循环来不停的执行 halt 指令,这样空闲任务进程的实际上就已经实现了,其本质上就是这个不断执行 halt 指令的循环,大功告成。

这样,当调度器在没有其它进程可供调度时就开始运行空间进程,也就是在循环中不断的执行 halt 指令,此时 CPU 开始进入低功耗状态。

在 Linux 内核中,这段代码是这样写的:

while (1) {while(!need_resched()) {cpuidle_idle_call();}
}

其中 cpuidle_idle_call 最终会执行 halt 指令,注意,这里删掉了大量代码,实际 Linux 内核在实现空闲进程时还要考虑很多很多,不同类型的 CPU 可能会有深睡眠浅睡眠之类,操作系统必须要预测出系统可能的空闲时长并以此判断要进入哪种休眠等等,但这并不是我们关注的重点。

总的来说,这就是计算机系统空闲时 CPU 在干嘛,就是在执行这一段代码,本质上就是 CPU 在执行 halt 指令。

实际上,对于个人计算机来说,halt 可能是 CPU 执行最多的一条指令,全世界的 CPU 大部分时间都用在这条指令上了,是不是很奇怪。

更奇怪的来了,有的同学可能已经注意到了,上面的循环可以是一个while(1) 死循环,而且这个循环里没有break语句,也没有return,那么操作系统是怎样跳出这个循环的呢?关于这一问题我们将在后续文章中讲解。

总结

CPU 空闲时执行特定的 halt 指令,这看上去是一个很简单的问题,但实际上由于 halt 是特权指令,只有操作系统才可以去执行,因此 CPU 空闲时执行 halt 指令就变成了软件和硬件相结合的问题。

操作系统必须判断什么情况下系统是空闲的,这涉及到进程管理和进程调度,同时,halt 指令其实是放到了一个 while 死循环中,操作系统必须有办法能跳出循环,所以,CPU 空闲时执行 halt 指令并没有看上去那么简单。

希望这篇文章对大家理解 CPU 和操作系统有所帮助。

CPU 空闲时在干嘛?相关推荐

  1. CPU空闲时在忙什么

    GitHub版本: https://github.com/cncounter/translation/blob/master/tiemao_2014/CPUIdel/CPUIdel.md CPU在绝大 ...

  2. 当 CPU 空闲时它都在做什么?(网上整理)

    CPU闲着的时候在干什么? Gustavo Duarte写的一篇详细文章指出,CPU空闲时并不是什么都不干,而是在运行空闲任务(idle tasks). CPU整体设计就是完成当前操作后尽可能快速地返 ...

  3. 【译文】CPU空闲时做什么?

    我们知道任何时候有且只有一个进程在CPU上活动.但是如果没有任何事做时,CPU做什么呢? 这个情景是非常常见的,对于大多数的个人电脑这个场景很常见:海量的睡眠进程,都在等待特定的条件进行唤醒,接近10 ...

  4. 解决WIN10“系统和压缩内存”“ntoskrnl.exe”系统空闲时占用大量CPU

    前些天装了WIN10,感觉,一般般,最近发现个怪现象,一旦机器有空闲一会,那个"系统和压缩内存"进程就会占用我20%的CPU不知道干嘛.百度一下,国内都在讨论这个进程对内存的消耗, ...

  5. VS Code 空闲时的 CPU 使用率是 13%

    (点击上方蓝字,快速关注我们) VS Code 自从推出后,在技术圈引起了很多关注.最近国外程序员 joliss 在 VS Code 的 issue 中反馈了一个问题:VS Code 处于空闲时,鼠标 ...

  6. 拯救者Y7000P 2020H款安装deepin20.5后资源空闲时经常出现风扇狂转现象

    拯救者Y7000P 2020H款安装deepin20.5后资源空闲时经常出现风扇狂转现象 记录下来备忘,不要再踩坑了!

  7. C#在类型实例化时都干了什么:从一道笔试题说开去

    C#在类型实例化时都干了什么:从一道笔试题说开去 原文来自:http://www.cnblogs.com/instance/archive/2011/05/27/2059409.html 前一阵子我参 ...

  8. 【分析】CPU hotplug时进程上下文切换流程分析

    本文是真对<vfp 原生bug导致开机概率定屏问题>cpu down时进程上下文的保存与恢复流程做简要分析,以便更好的理解这个问题. 在分析上下文切换流程前,先要对thread_info结 ...

  9. 计算机转机械硬盘,机械硬盘空闲时却还狂转,到底为什么?

    原标题:机械硬盘空闲时却还狂转,到底为什么? 在使用个人电脑(PC)时,可能大多数玩家都有几天不关电脑的习惯,甚至还有一些玩家十天半个月都不关电脑呢.我就是一例,"懒关电脑患者". ...

最新文章

  1. linux卸载netbeans,如何清除NetBeans中的缓存
  2. css样式引入方式,及常用设置标签样式
  3. Express 的使用
  4. 第九章:在Spark集群上掌握比较重要的图操作之Structural Operators
  5. Linux学习笔记:用户、用户组、文件系统和网络
  6. Linux内核深入理解系统调用(3):open 系统调用实现以及资源限制(setrlimit/getrlimit/prlimit)
  7. 两个向量的点乘和叉乘怎么算_【解析几何】赋值法(点乘双根法)解决解析几何大题...
  8. caffe :error MSB4062: 未能从程序集** 加载任务“NuGetPackageOverlay”
  9. 利用锁机制解决商品表和库存表并发问题
  10. 查看python安装的库_查看python及其第三方库的版本和安装位置
  11. Bamboo 0.2.11 发布,HAProxy 自动配置
  12. iweboffice文档内容服务器文件,iWebOffice2015使用常见问题-NTKOOffice文档控件.doc
  13. postman全方位讲解(有空看下)
  14. 微信小程序开发笔记 进阶篇⑤——getPhoneNumber 获取用户手机号码(基础库 2.21.2 之前)
  15. 车机软件测试ADBShell命令集合
  16. Java 下载压缩文件
  17. 计算机网络基础知识点快速复习手册
  18. 懒惰学习_为了懒惰!
  19. 万字干货:当了5次韭菜总结出来的抖音运营指南
  20. 加权GN算法的Java实现

热门文章

  1. get占位符传多个参数_未知环境下的Lidar概率占位栅格图(Occupancy Grid Map) Python代码实现...
  2. 大智慧825 自选股 导出_互联网技术更新智慧党校迎来发展契机-威尔 WEDS-BP31_济南考勤机行情...
  3. 基于ECS部署LAMP环境实验记录
  4. 软件体系架构阅读笔记一
  5. 菜鸟的DUBBO进击之路(二):Dubbo初识
  6. PARSEC測试集的应用领域和working set的大小
  7. Nexenta和ParaScale发布开源存储产品
  8. 聊聊 #pragma 和 // MARK:
  9. PHP语言 -- 基础
  10. SQL SERVER2005加密解密数据