【Linux】进程5——进程优先级

1.进程优先级

1.1.什么是进程优先级

  • cpu资源分配的先后顺序,就是指进程的优先权(priority)。
  • 优先权高的进程有优先执行权利。配置进程优先权对多任务环境的linux很有用,可以改善系统性能。
  • 还可以把进程运行到指定的CPU上,这样一来,把不重要的进程安排到某个CPU,可以大大改善系统整 体性能。

1.2.为什么要进程优先级

  1. 资源是有限的,进程是多个的,注定了进程之间是竞争关系
  2. 操作系统必须保证大家是良心竞争,如果我们进程长时间得不到CPU资源,该进程的代码长时间无法得到推进------该进程的饥饿问题

如果长时间得不到CPU资源,那么这个在windows上表现为该程序长时间无响应

2.查看系统进程

在linux或者unix系统中,用ps --l命令则会类似输出以下几个内容:

默认情况下,ps -l只会显示当前账号的进程,看不到别的终端的进程

我们ps -al就能看到别的终端的进程了

干扰信息太多了 ,我们筛选一下自己创建的myproc进程

此命令会显示当前用户下所有进程的内容。

我们很容易注意到其中的几个重要信息,有下:

  1. UID : 代表执行者的身份
  2. PID : 代表这个进程的代号
  3. PPID :代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号
  4. PRI :代表这个进程可被执行的优先级,其值越小越早被执行
  5. NI :代表这个进程的nice值

2.1.UID

我们很明显的知道了,root的UID是0,zs_108的UID是1000

2.1.PRI和NI

  • PRI也还是比较好理解的,不就是priority嘛,即进程的优先级,或者通俗点说就是程序被CPU执行的先后顺序,此值越小进程的优先级别越高。
  • Linux的默认优先级为80。Linux的优先级是可以被修改的,范围在[60,99]。
  • NI,就是我们所要说的nice值了,其表示进程可被执行的优先级的修正数值
  • PRI值越小越快被执行,那么加入nice值后,将会使得PRI变为:PRI(new)=PRI(old)+nice
  • 这样,当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行
  • 所以,调整进程优先级,在Linux下,就是调整进程nice值
  • nice其取值范围是-20至19,一共40个级别
    看完了上面的定义我们的问题就来了,在Linux中为什么调整优先级是受限制的呢?Linux为什么不能可以将[60,99]调整为[-∞,+∞]。

那是因为如果不加限制,如果恶意将自己的优先级调整的非常高,而给其余人的优先级调整的非常低(优先级较高的进程先享受CPU的资源),那些系统开启自启动的进程也就是正常系统进程很难再享受到CPU的资源,会变得卡顿。这样的情况叫做进程饥饿。

任何的分时操作系统在调度上都要保证较为公平的调度

2.3.调整优先级

更改优先级的方法有挺多的,nice和renice指令是不错的选择,大家可以去百度一下

我们这里讲用top指令来更改优先级

我们先开启两个账号

这个test的优先级是80

我们打开top

打开了之后,我们点击r------重新调整优先级

然后输入test的PID

按回车,接下来通过修改nice值来修改PRI

普通用户不能调优先级

我们换root账号来重复上面的步骤,完成了

NICE值变成了-20,这个是因为他的范围限制!!!!

PRI的也是60,也是因为它的范围限制

我们此时再去调整PRI,我们把nice值设置为10,我们发现NI变成了10,但是PRI变成了90

注意:pri(old)的优先级再每一次设置时都是80,而不是前一次的优先级!!!

3.进程的调度与切换

  1. **竞争性:**系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级
  2. 独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰
  3. 并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行
  4. **并发:**多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发

我们都知道在程序都被task_struct进行管理的,当进程需要运行时,就需要进行排队。 我们也知道CPU中有个时间片的东西来控制各个进程一次在CPU中最长占用时间。当某些程序过大导致在规定的时间片内执行不完时,我们就需要切换到下一个队列中的程序。那之前的程序应该怎么办?

CPU中存在大量的寄存器,我们在VS中调用堆栈可以看到,有一些:eds/ecs/fg/gs,eip,cr0-cr4,eax/ebx/ecx/edx,等待。这些寄存器可以帮助我们进行对这些代码数据进行记录保存,例如eip(也叫pc指针),这个寄存器可以记录我们的代码执行到了哪一部分。所以说进程在运行过程中要产生大量临时数据放在CPU的寄存器中!!!这些临时数据被我们保存在各个进程的PCB中。

CPU内部的所有临时数据我们叫做进程硬件的上下文。保存我们的进程上下文叫做保护上下文。在首次调度时,我们只需要将代码的起始地址放到eip中,然后逐步进行,进行时生成的临时数据被我们放到寄存器中。而二次调度时,我们只需要将上下文数据恢复到寄存器中即可!

上图是早期进程切换源码 。

总结:所有的保存都是为了最终的恢复,所有的恢复都是为了在上一次保存的位置继续执行!!!

CPU内的寄存器只有一套,而寄存器内部保存的数据可以有多套。所以虽然寄存器数据放在了一个共享的CPU中,但是所有的数据其实都是被私有的!!

4.内核进程调度队列

上图是Linux2.6内核中进程队列的数据结构,之间关系也已经给大家画出来。在这里我们只看红框和蓝框对应的部分。

首先我们来看queue[140],真正的类型:task_struct* queue[40]。他其实是一个指针数组,里面存放的是task_struct指针,那为什么是140个呢?前0~99我们不用,因为0~99中我们存放的时实时操作,剩下的100~130一共40个刚好对应的是我们上文所提到的优先级的范围差值,正好在每一个数组中可以存放相同优先级的task_struct。这就好比一个C++中的哈希桶结构。

当我们执行进程时,我们就从优先级最高的开始依次往下执行。但是有些队列是为空的,我们需要依次进行扫描判断吗?这就要出现第二个数据int bitmap[5]。 一个int4个字节,32bit,那么这个数组就是32*5 = 160比特位。所以比特位的位置表示哪一个队列,比特位的内容表示这个队列是否为空!就是所谓的位图算法。

我们可以注意到蓝框与红框的内容是一样的,为了避免进程的饥饿问题,Linux操作系统就想出了以对策:

我们可以看到上图中有一个array结构体数组,他里面存放了蓝框与红框的内容,蓝框中的queue被称为活跃队列,红框中被称为过期队列。当活跃队列中的进程开始被cpu进行调度时,后来的进程就不能在放入到活跃队列中去,而是放到过期队列中。直到活跃队列中的进程全部执行完毕后,再将活跃队列与过期队列进行交换,交换时只需要改变指针变量的内容即可。

相关推荐
The-Dog31 分钟前
Linux命令使用记录(自用)
linux
识途老码1 小时前
什么是单臂路由
运维·服务器·网络·单臂路由
Linux运维老纪1 小时前
Ansible 铸就 Linux 安全之盾(Ansible Builds Linux Security Shield)
linux·服务器·网络·安全·云计算·ansible·运维开发
唐青枫1 小时前
Linux apropos 命令使用详解
linux
刘大猫.2 小时前
Centos Ubuntu RedOS系统类型下查看系统信息
linux·ubuntu·centos·ip·ifconfig·redos·查询系统信息
YuSun_WK3 小时前
程序&进程&多任务&线程
linux·运维·服务器
HeLLo_a1194 小时前
第11章 安全网络架构和组件(一)
linux·服务器·网络
南川琼语4 小时前
TCP概念+模拟tcp服务器及客户端
linux·服务器·网络·tcp/ip
潘yi.8 小时前
web技术与nginx网站环境部署
服务器·网络·nginx
安顾里9 小时前
Linux命令-iostat
linux·运维·服务器