欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 美食 > 【Linux】进程优先级和进程切换

【Linux】进程优先级和进程切换

2025/4/26 10:11:35 来源:https://blog.csdn.net/tan_run/article/details/147481329  浏览:    关键词:【Linux】进程优先级和进程切换

📝前言:
这篇文章我们来讲讲进程优先级和进程切换

🎬个人简介:努力学习ing
📋个人专栏:Linux
🎀CSDN主页 愚润求学
🌄其他专栏:C++学习笔记,C语言入门基础,python入门基础,C++刷题专栏


这里写目录标题

  • 一,进程优先级
    • 实时操作系统和分时操作系统
  • 二,进程切换
    • 1 保护上下文
    • 2 Linux2.6内核进程O(1)调度队列
      • Linux2.6内核中进程队列的数据结构
      • queue[140]
      • bitmap[5]
      • nr_active
      • a 队列和 e 队列

一,进程优先级

进程的优先级就是指:进程获取CPU资源的先后顺序。
在Linux中,优先级用task_struct里面的一个整型表示,值越低,优先级越高。

我们运行起来一个进程,然后查看它的信息
在这里插入图片描述

  • UID:用户id
  • PRI:优先级(默认为80)
  • NI:优先级的修正值(nice)

1,对UID的理解:
进程会通过UID来记录用户。
我们都知道一切命令和程序都是进程,那么访问文件的本质就是进程在访问。进程会用记录的UID来判断此ID拥有的权限,识别权限是识别进程和文件之间的权限。【一切行为实质上都是进程,用户用进程来和系统交互】

2,对PRI和NI的理解:
进程的优先级PRI = 默认值(80) + nice值
且nice值的取值范围是:[-20, 19],一共40个级别(这是有讲究的)

如果我们要修改一个进程的优先级,可以通过renice修改nice值:
renice [nice值] + 进程PID
在这里插入图片描述
但是进程的优先级不建议频繁修改。

实时操作系统和分时操作系统

  • 实时操作系统:对外部事件做出快速响应,并且严格要求在一定时间内完成。优先级高的进程可以中断优先级低的进程。
  • 分时操作系统:有时间片,轮流为进程提供服务。(即:尽管进程的优先级高,但是每次只能在CPU上运行一个时间片那么长的时间,运行完以后就被拿下来,然后运行其他进程)

举个形象的例子理解两种操作系统的运用场景:
1,汽车进行刹车操作:运用实时操作系统,即:一旦有刹车指令,刹车指令放在第一位,把刹车指令执行完才能运行别的
2,边运行代码边听音乐:运用的是分时操作系统,即:没有要求跑代码的时候音乐就暂停,而是两个进程交替在CPU上运行。(只是速度太快,让我们感觉两个在一起)

理论上,单个CPU在某一时刻,只能有一个进程在运行。
但某一时段,可以通过并发的方式,让我们感觉在运行多个进程。
比如只有两个进程:运行代码和听音乐,两个进程是交替获取CPU资源的,一个进程运行完一个时间片以后,就立马换成另一个,只是切换的速度太快了。

进程的特点

  • 竞争性(竞争CPU资源)
  • 独立性(多进程运行间互相不干扰)
  • 并行性(多个进程在多个CPU下分别,同时进行运行)
  • 并发性(多个进程在⼀个CPU下采⽤进程切换的⽅式,在⼀段时间之内,让多个进程都得以推进)

二,进程切换

那么,一个进程被拿下来以后,下次再上CPU时,为什么能够延续上一次的位置继续运行呢?这是因为,数据会被记录。

1 保护上下文

CPU在运行进程时,主要关注数据和代码。CPU中的各种寄存器会用来记录当前进程的临时数据。(CPU的寄存器是一块空间,是数据临时存储的地方)
假如现在有一个进程A和一个进程B,保护上下文的流程:

  • 进程A先运行,此时CPU中的寄存器就会记录进程A的各种数据,比如:运算(1 + 2) * 3,加数 2 和被加数 1 被存储到寄存器中,+这个指令也被存储到寄存器中,1+2得到的结果3也被储存到寄存器中
  • 然后,A进程的时间片到了,这时候,B进程要上来
  • 则A就会将CPU中寄存器的数据保存到task_struct中一个叫tss的结构体(即硬件上下文数据,保存到task_struct中的tss),比如运算的临时结果3,还有后续的*操作等
  • B上去以后,就会用自己的数据直接覆盖寄存器里面的数据,然后运行B进程
  • 等到B的时间片运行完了,B像A一样自己记录自己的数据
  • 然后到A运行,A又重新把上一次记录的数据放到寄存器里,然后接着运行

Linux内核0.11的task_struct中的tss_struct
在这里插入图片描述
在这里插入图片描述

2 Linux2.6内核进程O(1)调度队列

⼀个CPU拥有⼀个runqueue(调度队列),那调度队列的数据结构到底是怎么样?如何管理这些进程的?
进程A的时间片运行完以后,进程A又去了哪里,下一个要运行的进程B是怎么找到的,进程A又是怎么回来重新运行的?

Linux2.6内核中进程队列的数据结构

一个CPU一个runqueue
在这里插入图片描述

queue[140]

queue[140]的底层是哈希表(用的是哈系统)

  • [0, 99]:是实时优先级(我们不关心)
  • [100, 139]:是普通优先级,刚好对应 nice 值的40个优先级级别
  • 同一级别中的不同进程,是通过哈希桶的方式链起来的

找运行队列时:全局上从上到下看优先级,局部上(同一优先级),进程队列FIFO。

bitmap[5]

哈希桶的头插效率是O(1),因为queue[140]大小固定,查找效率也是O(1),但是每次找进程都要从上到下遍历整个queue[140]还是太慢了,于是有了位图unsigned int bitmap[5]
unsigned int4 个字节,即:32个bit位,长度为 5 的话就是 160 个比特位。于是从 0 开始 0 - 139位就与queue[140]的下标一一对应。想要知道哪个下标还有进程,就只需要查bitmap0 代表无进程,1 代表还有进程。

nr_active

nr_active用来指明当前queue[140]里的进程数量

a 队列和 e 队列

一个进程的时间片运行完以后被放到哪里呢?
这就要谈谈 e 队列,在上面的结构图中我们可以看到两份:
在这里插入图片描述
这两份一份是活跃队列(a 队列),一份是过期队列(e 队列),分别被*active*expired 指针指向

进程的运行顺序以及交替:

  • 首先,我们在 a 队列里面挑进程:全局上从上到下(利用bitmap),局部上,FIFO(直接拿链表第一个)
  • 当一个进程的时间片运行完以后,这个进程会从 a 队列移动到 e 队列
  • 直到所有 a 队列里面的进程都被执行过了一遍(即:nr_active == 0
  • 然后,会交换*active*expired 指针,再运行 a 队列,重复上面的过程

(这就是O(1)调度算法:在系统当中查找⼀个最合适调度的进程的时间复杂度是⼀个常数,不随着进程增多⽽导致时间成本增加)

其实,上述过程中进程在 e 队列时的状态就是操作系统中的就绪状态,不过Linux中不对就绪状态和R状态进行区分。

还有两个小细节:

1,当一个进程的优先级被改了,这个进程怎么移动位置呢?

答:当一个进程的优先级被改,本次的PRI是不变的,等到本次从 a 队列中运行完以后到了 e 队列,下次从 e 队列回到 a 的时候,在重新计算,改变位置

2,当有新进程加入时,新进程进 a 还是 e

  1. 一般情况:新进程进 e
  2. 内核抢占情况:新进程进 a

🌈我的分享也就到此结束啦🌈
要是我的分享也能对你的学习起到帮助,那简直是太酷啦!
若有不足,还请大家多多指正,我们一起学习交流!
📢公主,王子:点赞👍→收藏⭐→关注🔍
感谢大家的观看和支持!祝大家都能得偿所愿,天天开心!!!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词