Linux优先级时间片调度

进程优先级

进程的优先级有2种度量方法,一种是nice值,一种是实时优先级(RTPRIO)。
nice值的范围是-20~+19,值越大优先级越低,也就是说nice值为-20的进程优先级最大。
实时优先级(RTPRIO)的范围是0~99,与nice值的定义相反,实时优先级是值越大优先级越高
实时进程都是一些对响应时间要求比较高的进程,因此系统中有实时优先级高的进程处于运行队列的话,它们会抢占一般的进程的运行时间。

进程的2种优先级会让人不好理解,到底哪个优先级更优先?一个进程同时有2种优先级怎么办?

对于第一个问题,到底哪个优先级更优先?答案是实时优先级高于nice值,在内核中,实时优先级的范围是 0~MAX_RT_PRIO-1。第二个但是进程不会同时拥有两个优先级。
MAX_RT_PRIO的定义参见include/linux/sched.h

 #define MAX_USER_RT_PRIO        100
 #define MAX_RT_PRIO             MAX_USER_RT_PRIO
 #define MAX_PRIO                (MAX_RT_PRIO + 40)

nice值在内核中的范围是 MAX_RT_PRIO~MAX_RT_PRIO+40 即 MAX_RT_PRIO~MAX_PRIO

基于时间片+优先级的调度

实现原理

  1. 确定每个进程能占用多少CPU时间(这里确定CPU时间的算法有很多,根据不同的需求会不一样)
  2. 占用CPU时间多的先运行
  3. 运行完后,扣除运行进程的CPU时间,再回到 1

例子

假设系统中只有3个进程ProcessA(NI=+10),ProcessB(NI=0),ProcessC(NI=-10),NI表示进程的nice值,时间片=10ms

  1. 调度前,把进程优先级按一定的权重映射成时间片(这里假设优先级高一级相当于多5msCPU时间)。

    假设ProcessA分配了一个时间片10ms,那么ProcessB的优先级比ProcessA高10(nice值越小优先级越高),ProcessB应该分配10*5+10=60ms,以此类推,ProcessC分配20*5+10=110ms

  2. 开始调度时,优先调度分配CPU时间多的进程
    由于ProcessA(10ms),ProcessB(60ms),ProcessC(110ms)。显然先调度ProcessC
  3. 10ms(一个时间片)后,再次调度时,ProcessA(10ms),ProcessB(60ms),ProcessC(100ms)。ProcessC刚运行了10ms,所
    以变成100ms。此时仍然先调度ProcessC
  4. 再调度4次后(4个时间片),ProcessA(10ms),ProcessB(60ms),ProcessC(60ms)。
    此时ProcessB和ProcessC的CPU时间一样,这时得看ProcessB和ProcessC谁在CPU运行队列的前面,假设ProcessB在前面,则调度ProcessB
  5. 10ms(一个时间片)后,ProcessA(10ms),ProcessB(50ms),ProcessC(60ms)。再次调度ProcessC
  6. ProcessB和ProcessC交替运行,直至ProcessA(10ms),ProcessB(10ms) ,ProcessC(10ms)。
    这时得看ProcessA,ProcessB,ProcessC谁在CPU运行队列的前面就先调度谁。这里假设调度ProcessA
  7. 10ms(一个时间片)后,ProcessA(时间片用完后退出),ProcessB(10ms),ProcessC(10ms)
  8. 再过2个时间片,ProcessB和ProcessC也运行完退出

调度实现

2.6.23内核以后,采用了“完全公平调度算法”,简称CFS。CFS算法在分配每个进程的CPU时间时,不是分配给它们一个绝对的CPU时间,而是根据进程的优先级分配给它们一个占用CPU时间的百分比

Ubuntu Linux查询内核方式

uname -a
//查询结果
Linux ubuntu 5.4.0-40-generic #44-Ubuntu SMP Tue Jun 23 00:01:04 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
cat /proc/version
//结果
Linux version 5.4.0-40-generic (buildd@lcy01-amd64-011) (gcc version 9.3.0 (Ubuntu 9.3.0-10ubuntu2)) #44-Ubuntu SMP Tue Jun 23 00:01:04 UTC 2020

比如:ProcessA(NI=1),ProcessB(NI=3),ProcessC(NI=6),在CFS算法中,分别占用CPU的百分比为:ProcessA(10%),ProcessB(30%),ProcessC(60%)。因为总共是100%,ProcessB的优先级是ProcessA的3倍,ProcessC的优先级是ProcessA的6倍。

Linux上的CFS算法主要有以下步骤

  1. 计算每个进程的vruntime,通过update_curr()函数更新进程的vruntime。
  2. 选择具有最小vruntime的进程投入运行。
  3. 进程运行完后,更新进程的vruntime,转入步骤2.

与系统有关的调用

与调度策略和进程优先级相关 (各种参数,优先级,时间片)

系统调用 描述
nice() 设置进程的nice值
sched_setscheduler() 设置进程的调度策略,即设置进程采取何种调度算法
sched_getscheduler() 与调度策略和进程优先级相关 (各种参数,优先级,时间片)获取进程的调度算法
sched_setparam() 设置进程的实时优先级
sched_getparam() 获取进程的实时优先级
sched_get_priority_max() 获取实时优先级的最大值,由于用户权限的问题,非root用户并不能设置实时优先级为99
sched_get_priority_min() 获取实时优先级的最小值,理由与上面类似
sched_rr_get_interval() 获取进程的时间片

与处理器相关

系统调用 描述
sched_setaffinity() 设置进程的处理亲和力,其实就是保存在task_struct中的cpu_allowed这个掩码标志。该掩码的每一位对应一个系统中可用的处理器,默认所有位都被设置,即该进程可以再系统中所有处理器上执行。用户可以通过此函数设置不同的掩码,使得进程只能在系统中某一个或某几个处理器上运行。
sched_getaffinity() 获取进程的对处理机的附着度
sched_yield() 暂时让出处理器

猜你喜欢

转载自blog.csdn.net/weixin_44029810/article/details/107444546