欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 时评 > 【Linux】进程优先级与进程切换理解

【Linux】进程优先级与进程切换理解

2025/5/4 13:13:53 来源:https://blog.csdn.net/2301_80955819/article/details/147683881  浏览:    关键词:【Linux】进程优先级与进程切换理解

🌟🌟作者主页:ephemerals__

🌟🌟所属专栏:Linux

目录

前言

一、进程优先级

1. 什么是进程优先级

2. 为什么有进程优先级

3. 进程优先级的作用

4. Linux进程优先级的本质

5. 修改进程优先级

二、进程切换

1. 概念 

2. 进程切换的过程

3. 进程切换的意义

4. Linux的进程调度(O(1)调度算法)

总结


前言

        本篇文章我们在了解了进程概念和状态等基础知识之上,继续学习进程的优先级,以及进程切换相关知识。

正文开始

一、进程优先级

1. 什么是进程优先级

        进程优先级是操作系统分配给进程的一种“权重”或“级别”,用来决定在多个进程同时竞争 CPU 资源时,哪一个进程先获得运行的机会。优先级高的进程会被优先调度执行,低优先级的进程则可能需要等待。 

2. 为什么有进程优先级

        大多数情况下,正在执行的程序数量是比较多的,而CPU资源有限为了使那些重要、急需执行的任务先执行,就有了优先级。这样一来,资源分配会得到优化,整个系统更加合理高效。

注:现代操作系统更加考虑进程获取资源的公平性,优先级的差距不会太大。

3. 进程优先级的作用

        进程优先级可以保证关键任务或实时任务及时调度(如操作系统内核进程通常优先级较高),并且可以防止某个进程长期占用 CPU,改善系统性能。其次,优先级可以实现多用户或多任务下的公平资源分配

4. Linux进程优先级的本质

        在Linux下,进程优先级的本质就是一个整数,存储在task_struct结构体当中,直接影响了进程调度的先后顺序。进程优先级的值越小,优先级越高

可以使用以下命令查看到当前所有进程的优先级:

ps -al

运行结果:

PRI:进程优先级的值,默认是80

NI:也叫做nice值,是进程优先级的修正数据。其取值范围是[-20, 19]

PRI的默认值(80) 和 NI 之和表示进程的真实优先级大小。也就是说,Linux进程优先级的范围是[60, 99],一共40个。

注:ps -l指令还可以看到当前进程的PID,父进程ID等。其中还有一项UID,它用来标识Linux下的用户,进行用户区分。当用户创建进程时,进程会记录用户的UID,访问文件时(本质是进程在访问),进程就拿这个UID与文件的拥有者或所属组的UID进行对比。

5. 修改进程优先级

        在Linux下,修改进程优先级主要是通过修改nice值来完成(注意nice值的取值范围)。可以使用top命令修改进程优先级:

输入top --> 按“ r ” --> 输入进程的PID --> 输入新的nice值

注意:普通用户只能给自己的进程设置优先级,且只能将优先级调低(nice值调高);而root用户可以在取值范围内随意调整任意进程的优先级。 

 接下来我们尝试调整一个进程process的优先级:

process的源码:

#include <stdio.h>
#include <unistd.h>int main()
{while(1){sleep(1);printf("hello\n");}return 0;
}

首先运行process,查看process的优先级:

可以看到process的优先级是80。接下来将nice修改为10:

这里process的PRI变成了90,而nice值为10。此时90是process的真实优先级。 

如果修改为-10:

可以看到,普通用户下,将nice值调低是不被允许的。

如果改为100:

由于取值范围的限制,nice值最高为19,输入100只能将其改为19。

注意:如果优先级设置不合理,就会导致优先级低的进程长时间获取不到CPU资源,导致进程饥饿。

二、进程切换

1. 概念 

        CPU在执行一个进程时,由于还有其他进程的存在,它不会一次将所有代码全部跑完,而是跑一会后,转而去执行其他进程,再来执行当前进程......这样才可以在一段时间之内使得多个进程都有所推进。CPU从执行当前进程变为执行其他进程的过程叫做进程切换

当代操作系统都是分时的,每个进程都有它相应的时间片(本质就是一个计时器)。当前进程的时间片用完后,就会切换到其他进程。

2. 进程切换的过程

        一个进程在CPU上运行到时间片结束之后,首先存储自己执行位置的上下文数据到自己的TSS(任务状态段,存储在task_struct当中)当中,然后将进程重新放入调度队列队尾。进程发生切换时,将新的进程的TSS中的数据拷贝(恢复)到CPU的对应寄存器中,继续执行。 

进程的上下文数据指的是进程在运行时,需要保存和恢复的所有关键信息(例如发生切换时CPU寄存器中的数据),这样就可以保证进程发生一系列切换后,重新执行该进程时,能从原来的状态继续执行。

3. 进程切换的意义

        进程切换让操作系统能管理多个进程,保证各进程能按照优先级获得CPU使用权,是实现多任务的基础。多个进程可以“轮流”运行,系统利用率和响应速度得以提高。

4. Linux的进程调度(O(1)调度算法)

        高效的进程切换不仅保证了多任务系统的流畅运行,还直接影响着系统的响应速度与整体性能。为了实现快速、合理的进程调度,Linux内核采用了多种调度算法,其中O(1)调度器就是在2.6版本中所引入的一种重要算法。接下来,我们将深入了解O(1)调度算法,看看它是如何实现对大量进程的高效管理的。

        在之前的文章中,我们提到过一个CPU维护一个进程调度队列,该队列中存放着一个个PCB,等待CPU对它们进行调度。实际上这个“进程调度队列”远远比传统的队列复杂。在Linux中,进程调度队列叫做runqueue,它的结构如图所示:

一个CPU维护一个运行队列runqueue,其中数组prio_array_t中的queue是存放进程PCB的关键。

queue本质是一个链地址法的哈希表,其中有140个哈希桶(前100个哈希桶表示实时优先级,剩余40个刚好对应40种优先级,所以哈希桶的下标 - 40就是进程优先级),相同优先级的进程task_struct存放在同一个哈希桶中,这样,当需要调度时,按照下标小到大的顺序扫描每一个哈希桶,先访问到的进程就是优先级高的(因为优先级的值越小,优先级越高),然后拿出桶中的task_struct进行调度。

考虑到每次都要遍历140个哈希桶,效率较低,所以有一个位图bitmap,位图中有5个32位的整形变量,加起来一共160位,其中的140位表示对应的哈希桶中是否有task_struct,所以可以直接判断哪一位是“1”,就表示哪一个桶需要被访问。除此之外,还有一个变量nr_active,表示整个哈希表中的元素个数,对应正在运行时的进程个数。

queuebitmapnr_active共同构成一个结构体,叫做rqueue_elem。

如此,访问位图,按顺序找到存在元素的哈希桶,进行调度,整个调度过程效率就能达到O(1)。 

但是图中的prio_array_t数组有两个元素,也就是说有两张哈希表,这是为什么呢?这就要从进程切换的角度开始谈起了。

试想,如果只有一张哈希表,那么发生进程切换时会怎么样?

假设第100个哈希桶当中有3个进程,第一个进程的时间片耗尽后,会发生进程切换,此时按照优先级,只能将它重新插入在当前哈希桶的链表尾部,当然,其他两个进程也是如此。这样虽然能够完成这3个进程的轮流调度,但是更低优先级(也就是下标更大的哈希桶)的进程呢?当前哈希桶中只要有元素,CPU就会一直轮流调度当前哈希桶中的进程,而会忽略优先级更低的进程,导致进程饥饿。要调度优先级更低的进程,就必须等待当前优先级的进程全部调度完毕,显然是不合理的,极大地损失了公平性

因此,前辈们想到了一个巧妙的方法:再创建一个相同的结构体rqueue_elem,其中也包含一个queuebitmapnr_active,两个rqueue_elem构成一个数组prio_array_t[2]

然后创建两个指针nativeexpired,分别指向prio_array_t[0]和prio_array_t[1],native指向的表示“活跃队列”;expired指向的表示“过期队列”。当发生进程切换时,被调度结束的进程会插入到“过期队列”的对应优先级的哈希桶中,然后继续访问“活跃队列”中的哈希桶,一个个地调度。这样,当前“活跃队列”哈希桶中的元素就会越来越少,直到为0,就可以访问优先级更低的哈希桶......最后所有进程都会被调度,而不是高优先级进程运行完毕后才能调度低优先级进程。

当“活跃队列”整个哈希表内的进程都被调度过后(此时这些进程应全都位于“过期队列”对应的哈希桶中),交换native和expired两个指针的指向,这样“过期队列”就变成了“活跃队列”,就可以开始下一轮的调度了。

如果有新进程出现,会直接插入“过期队列”当中。此时新进程处于“就绪状态”,等待一轮的调度结束后,新进程就可以被调度。

总结

        本篇文章,我们系统地了解了进程优先级的定义、意义以及在Linux下的调整方法,也梳理了进程切换的基本流程与核心作用。从进程优先级到切换机制,再到Linux的O(1)调度算法,这些知识共同揭示了操作系统在多任务管理中的高效与精妙。掌握这些原理,有助于更深入理解和优化 Linux 系统的性能,为后续程序地址空间进程控制的学习打下坚实基础。如果你觉得博主讲的还不错,就请留下一个小小的赞在走哦,感谢大家的支持❤❤❤

版权声明:

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

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

热搜词