Linux操作系统从入门到实战(二十一)进程切换与进程调度
- 前言
- 一、进程切换是什么?
-
- [1. 为什么需要进程切换?](#1. 为什么需要进程切换?)
- [2. 什么是"CPU上下文"?](#2. 什么是“CPU上下文”?)
- [2. 进程切换的完整步骤](#2. 进程切换的完整步骤)
- 第一步:保存当前任务的上下文
- 第二步:加载下一个任务的上下文
- 二、进程调度
-
- [1. 为什么要进程调度?](#1. 为什么要进程调度?)
- [2. Linux里有几类"调度员"?](#2. Linux里有几类“调度员”?)
- [3. 进程排队用什么队形?](#3. 进程排队用什么队形?)
- [4. CFS怎么做到"公平"?](#4. CFS怎么做到“公平”?)
- [5. 什么时候会"换进程"?](#5. 什么时候会“换进程”?)
- [6. 调度选进程、换进程,具体怎么操作?](#6. 调度选进程、换进程,具体怎么操作?)
- [7. 多CPU时,活会分给谁?](#7. 多CPU时,活会分给谁?)
- [9. Idle进程是做什么?](#9. Idle进程是做什么?)
- 总结
前言
上一篇博客中,我们介绍了进程优先级;
- 这一篇,我们将讲解进程切换与进程调度。
我的个人主页,欢迎来阅读我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343我的Linux知识文章专栏
欢迎来阅读指出不足
https://blog.csdn.net/2402_83322742/category_12879535.html?spm=1001.2014.3001.5482
一、进程切换是什么?
1. 为什么需要进程切换?

你有没有想过,电脑明明只有一个CPU(或者几个核心),却能同时运行微信、浏览器、音乐播放器?比如你一边刷网页,一边听歌,还能聊微信------这其实是CPU在"骗"你。
CPU的"本事"是快速在不同任务(进程)之间切换,快到你感觉不到卡顿,误以为它们在同时运行。
- 而CPU在不同任务之间切换的过程,就叫进程切换(也叫任务切换)。
2. 什么是"CPU上下文"?
切换任务时,有个很重要的问题:
-
比如你正在用浏览器看视频,突然切到微信发消息,等会儿再切回浏览器,浏览器得知道"刚才看到哪一秒了""视频缓冲到哪里了",不然就会从头开始。
CPU也一样,它处理一个任务时,会把这个任务的"当前进度"存在一些叫寄存器的硬件里。
- 寄存器就像CPU的"小笔记本",记着:
-
- 下一条要执行的指令存在内存的哪个位置;
-
- 刚才计算到一半的临时数据(比如加法算到哪一步);
-
- 任务的状态(比如是运行中、还是暂停了)。
这些存在寄存器里的"进度信息",就叫CPU上下文 ------简单说,就是"当前任务在CPU里的所有状态记录"。
2. 进程切换的完整步骤
当CPU决定"先放下当前任务,去处理另一个任务"时,就会执行"上下文切换",步骤分两步:
第一步:保存当前任务的上下文
- CPU会把"小笔记本"(寄存器)里记录的当前任务的所有信息,存到这个任务自己的堆栈里。
- 就像你暂停看视频时,播放器会自动记录"看到第30秒",存在自己的缓存里一样。
第二步:加载下一个任务的上下文
- 然后,CPU会从下一个要运行的任务的"专属储物柜"(堆栈)里,把它上次存的"进度信息"(上下文)取出来,重新写到自己的"小笔记本"(寄存器)里。
- 就像你打开之前暂停的视频,播放器会从缓存里读"第30秒",接着播放。
做完这两步,CPU就开始处理新任务了------这整个过程,就是"进程切换"(上下文切换)。
举个例子
假设CPU要在"浏览器(任务A)"和"音乐播放器(任务B)"之间切换:
- 一开始CPU在处理任务A(浏览器加载网页),寄存器里记着"浏览器下一条指令在内存地址X,临时数据是50";
- 到了切换时间,CPU先把寄存器里的"X地址、数据50"存到任务A的堆栈里(保存上下文);
- 然后从任务B的堆栈里,取出它上次存的"下一条指令在内存地址Y,临时数据是30",写到寄存器里(加载上下文);
- 接下来CPU就按照寄存器里的信息,开始处理任务B(播放音乐);
- 过一会儿又要切回任务A,重复上面的步骤:先存B的上下文,再加载A的上下文,继续处理浏览器。
这样快速切换,我们就能感觉浏览器和音乐播放器在同时运行了。
二、进程调度
-
我们每天用电脑时,可能同时开着浏览器、音乐播放器、文档编辑器......这些程序背后都是"进程",而CPU就像一个"超级打工人",得给这些进程安排干活的顺序------这就是"进程调度"要干的事。
1. 为什么要进程调度?
CPU那么快,直接让所有进程一起跑不行吗?
- 不行
-
- CPU同一时间只能给一个进程干活(即使是多核心CPU,每个核心也只能同时处理一个进程)。但我们又需要"多任务"(比如边听歌边写文档),这就需要一个"调度员"来决定:现在该让哪个进程用CPU?用多久?下次轮到谁?
这个"调度员"的目标很简单:
- 公平:普通进程别抢着用,大家分一分CPU时间;
- 实时:紧急任务(比如游戏里的按键响应、工业设备的控制)必须马上处理,不能卡;
- 高效:调度本身别太费时间,别让CPU光忙着安排任务,没空干活。
2. Linux里有几类"调度员"?
问题 :所有进程都按一个规则调度吗?
- 进程有"急"有"缓",Linux专门设计了3类"调度员"(调度类),按优先级从高到低排:
-
实时调度类(RT) :管"急活"
比如工厂里的机器控制、游戏里的画面刷新,这些任务不能等,优先级最高(1-99,数字越大越急)。
它有两种规则:
SCHED_FIFO
(先到先得):一旦开始跑,不主动停下就一直占着CPU;SCHED_RR
(时间片轮转):虽然急,但也不能一直占着,给个时间片(比如10ms),到点就换另一个同优先级的实时进程。
-
完全公平调度类(CFS) :管"普通活"
我们日常用的浏览器、文档、音乐播放器,大多是这类。它的目标是"大家尽量公平用CPU",优先级对应一个叫
nice
的值(-20到19):nice=-20
:最"不谦让",能多占点CPU(对应调度优先级100);nice=19
:最"谦让",少占点CPU(对应调度优先级139)。
-
Idle调度类 :管"没人干活时"
只有当所有进程都"歇着"(比如电脑没开任何程序),它才出来"值班",让CPU跑点空操作,甚至帮CPU省电,优先级最低。
3. 进程排队用什么队形?
问题 :这么多进程,调度员怎么快速找到"下一个该干活的"?
-
每个CPU都有一个"任务队列"(
rq
),里面按调度类分了小队伍: -
实时队列(rt_rq):像个"优先级货架",有99个格子(对应优先级1-99),每个格子里是同优先级的实时进程,排成链表。调度员找实时进程时,直接从最高优先级的格子里抓第一个就行,快得很。
-
CFS队列(cfs_rq) :用"红黑树"(一种平衡的二叉树)排的队。
-
- 树里的进程按"虚拟运行时间(vruntime)"排序,
vruntime
越小,越靠前(越先被调度)。
为啥用红黑树?因为它增删改查都快(像查字典找单词一样),能快速找到"最该先跑"的进程。
- 树里的进程按"虚拟运行时间(vruntime)"排序,
4. CFS怎么做到"公平"?
问题:普通进程那么多,怎么保证"你用一会儿,我用一会儿"?
-
CFS的秘诀是"虚拟运行时间(vruntime)"和"权重":
-
权重 :
nice
值决定的"抢CPU能力"。nice=-20
的进程权重高(1024),nice=19
的权重低(128)------权重高的,就该多占点CPU。 -
vruntime计算 :
vruntime = 实际运行时间 × (1024 / 权重)
。比如:
- 高权重进程(
nice=-20
)跑1ms,vruntime
只加1ms(1×1024/1024=1); - 低权重进程(
nice=19
)跑1ms,vruntime
要加8ms(1×1024/128=8)。
- 高权重进程(
这样一来,高权重进程的vruntime
长得慢,在红黑树里总排在前面,能更频繁地被调度(多占CPU);低权重的则相反------看似"不公平",其实是按"优先级"分配的"比例公平"。
5. 什么时候会"换进程"?
问题 :调度员啥时候会喊"停,下一个"?
分两种情况:
-
主动让贤 :进程自己说"我先歇会儿"。
比如你用浏览器点了"刷新",浏览器要等网络数据,就会主动放弃CPU,去"睡觉"(阻塞)。
-
被动打断:调度员强制换进程。
- 时钟中断(比如每10ms响一次):检查当前进程是不是"用太久了"(比如RT的RR策略时间片到了,或CFS的
vruntime
该换了); - 高优先级进程被唤醒:比如你按了游戏按键,对应的实时进程醒来,直接把当前的普通进程"挤下去";
- 新进程诞生:比如你新开了一个程序,可能比当前进程优先级高,直接抢占CPU。
- 时钟中断(比如每10ms响一次):检查当前进程是不是"用太久了"(比如RT的RR策略时间片到了,或CFS的
6. 调度选进程、换进程,具体怎么操作?
- 核心靠一个叫
schedule()
的"调度函数",步骤很简单:
- 挑调度类:先看有没有实时进程(RT),有就优先选;没有就选CFS的普通进程;都没有就选Idle进程。
- 选具体进程 :
- RT类:从实时队列里挑最高优先级的第一个;
- CFS类:从红黑树里挑
vruntime
最小的那个。
- 换任务:保存当前进程的"工作进度"(寄存器、栈等),加载新进程的"进度",让新进程开始用CPU。
7. 多CPU时,活会分给谁?
-
电脑有多个CPU核心,会不会有的忙死、有的闲死?
-
有可能!所以需要"负载均衡":
-
为啥要均衡:比如一个CPU核心跑了10个进程,另一个核心闲着,太浪费了,得把进程挪过去点。
-
怎么均衡:
- 定时检查各CPU的"负载"(进程数量+权重);
- 把负载高的CPU上的进程,挪到负载低的CPU上(优先挪普通进程,实时进程尽量不动,怕影响响应速度)。
9. Idle进程是做什么?
当所有进程都歇着,CPU在干啥?
这时每个CPU核心会跑一个"Idle进程"------它不是摸鱼,而是:
- 跑点空操作,让CPU有事干(不然CPU可能"懵圈");
- 触发硬件节能(比如降低CPU频率),帮电脑省电。
总结
- 对紧急任务(RT):让它们优先跑,保证不卡顿;
- 对普通任务(CFS):用
vruntime
和红黑树,按优先级公平分配CPU; - 多CPU时:均衡负载,不让任何核心闲着;
- 没事干时:让Idle进程"看场子",还能省电。
以上就是这篇博客的全部内容,下一篇我们将继续探索Linux的更多精彩内容。
我的个人主页
欢迎来阅读我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343我的Linux知识文章专栏
欢迎来阅读指出不足
https://blog.csdn.net/2402_83322742/category_12879535.html?spm=1001.2014.3001.5482
|--------------------|
| 非常感谢您的阅读,喜欢的话记得三连哦 |
