【Linux手册】进程优先级:操作系统世界里的“资源争夺”

发布于:2025-06-20 ⋅ 阅读:(25) ⋅ 点赞:(0)

目录

前言

优先级是什么

为什么需要优先级

如何做到谁先,谁后

进程内容的补充

进程一些概念

进程切换:并发

补充


前言

现实世界中干什么都要排队,在计算机世界中也是如此,每一个进程都想要使用CPU资源,但是CPU又只有一个,所以就有了运行队列让进程排队依次运行,这也就必定存在一些重要的进程需要先运行,而不太重要的可以放在后面运行。所以引入了优先级来解决进程谁先,谁后的问题。

优先级是什么

在前言处就已经引出了优先级是什么:优先级就是描述进程对于资源访问,谁先,谁后的概念。

优先级是用来描述进程的属性的,那么其一定保存在PCB数据结构体对象中,在Linux下如何查看呢?在Linux命令行中用ps查看进程进程的属性,其中PRI(priority)就表示一个进程的优先级。

为什么需要优先级

CPU只有一个,但是进程有多个,多个进程都要同时访问CPU的资源就必须将这些进程组织起来防止一个进程长时间得不到资源,无法继续执行代码-------进程饥饿问题。所以通过优先级让进程的有序的排列起来依次使用CPU资源。

如何做到谁先,谁后

在解释优先级如何做到让进程先后执行之前,先对ps显示的进程各个属性简单介绍一下。

ps -l:显示当前终端的进程属性;ps -al:显示所有终端进程属性。

PRI:代表进程的优先级,数值越小代表优先级越高;

进程有先后顺序,那么用户一定能够对进程的优先级进行修改。是的,用户可以通过NI(nice值)对进程的优先级进行修改。

真实的PRI=原来的PRI(一般是80)+NI:通过调整进程的nice值可以对进程的优先级进行修改;当然操作系统不会允许你对进程的优先级进行过度修改,所以在Linux中操作系统限制了nice的范围:从[-20,19]也意味着PRI的范围一般是[60,99]。

修改nice值得方法:

  • 使用nice命令进行修改:nice  -n [修改后得nice值] +[命令]:命令本质上就是可执行程序,通过上面方式可以实现修改命令得优先级,并运行命令。如下图所示
  • renice:在进程执行过程对进程优先级进行修改。renice [修改后的nice值] [进程PID]
  • top指令:先通过top命令查看进程得动态属性,r PID nice:对进程得优先级进行修改。

 不同的进程有不同得PID,那么操作系统是如何保证这些进程依次使用CPU资源得呢???

在计算机中如果只有一个CPU那就只有一个运行队列。在操作系统中用一个长度为140的数组存放各个优先级的进程,其中0-99一般在日常开发中接触不到,100-139是我们运行的进程存放位置,在上面我们谈到进程的优先级范围是[60,99]这就正好对应这40个位置。

在操作系统中有两个队列:活动队列和过期队列,活动队列中存放着各种优先级的进程,active指针指向该队列,CPU依次从该队列中拿取进程运行,运行过后放入过期队列(expired指针指向该队列)中;当活动队列中的所有位置进程都运行完后,将active指针与expired指针指向的内容进行交换,就实现了活动队列与过期队列的交换,从而让CPU继续运行程序。

在检查运行队是否运行完时,可以使用位图来实现,这样就不用遍历一边数组了。


进程内容的补充

进程一些概念

  • 独立性:各个进程之间是独立的,进程之间互不干扰,一个进程挂了不会影响其他进程的正常运行;
  • 竞争性:一个计算机中有多个进程,但是CPU只有一个,这就导致了各个进程之间必定对相互竞争CPU资源;
  • 并行:多个进程在多个CPU下同时运行,有多个运行队列,在同一时间真正实现多个进程同时运行;
  • 并发:多个进程在一个CPU下采取进程切换的方式,在一段时间内,让多个进程都得以推动。

进程切换:并发

并发:反复的将进程放到CPU上,再从CPU上拿下,使得在一段时间内每个进程都都能被推动;因为CPU处理速度很快所以我们感受不到程序的卡顿。

并发的实现:进程切换+时间片(基于时间片轮转的调度算法,用来记录每个进程在CPU上运行的时间,保证每个进程都能被公平调度)。

进程反复放到CPU上,又从CPU上拿下来,那CPU每一次运行时如何知道每个进程上一次运行到哪里了?从哪里继续运行?

在学习编程语言的时候,我们就知道CPU中有寄存器能够存储一些返回值等临时变量。那么CPU中有没有什么可以存储运行到的位置???

CPU中有程序计数器(pc,eip)能够记录:程序中即将执行的下一条指令。

CPU的寄存器中保存这进程的各个属性及数据,这些临时数据被称为进程的上下文

当进程从CPU中离开时,将进程的上下文也保存到每个进程自己的PCB数据结构对象中,当进程再次运行的时候,再将进程的上下文加载到CPU中就能实现进程的连续运行。

上面问题的答案不就是:进程通过保存上下文,回复上下文来实现继续运行。

补充

当一个返回值很大的时候,寄存器要如何对这个返回值进行处理呢???

在面向对象中,我们知道返回值实际上还是调用拷贝构造函数,那对于很大的对象在进行返回的时候也可以一个个的构造成员变量,汇编中就是对应多条move指令。

过大的数据也可以先保存到上级栈帧中,先放到内存中,而不是寄存器中。


网站公告

今日签到

点亮在社区的每一天
去签到