在内核中,肯定不能对所有的进程一视同仁,有的进程需要优先运行,有的进程需要运行更长的时间
为了更好地实现进程调度,每个进程都有自己的优先级和调度策略
所谓优先级,就是表示这个进程的重要性,优先级高的自然会被更好的对待
那调度策略又是什么呢?想一想,进程调度其实是一个非常复杂的问题,想使用一种算法来实现良好的进程调度是不可能的,Linux内核实现了好几种调度算法。所谓调度策略,你可以理解为使用哪种算法来管理进程
每个进程都使用 task_struct 结构来表示,在这个结构体中,关于调度策略的定义如下:
unsigned int policy;
policy 表示该进程采用哪种调度策略,内核提供了以下几种调度策略policy 表示该进程采用哪种调度策略,内核提供了以下几种调度策略:
#define SCHED_NORMAL 0
#define SCHED_FIFO 1
#define SCHED_RR 2
#define SCHED_BATCH 3
#define SCHED_IDLE 5
#define SCHED_DEADLINE 6
Linux内核的进程大概可分为两类,一类是普通进程,一类是实时进程
其中属于实时进程的调度策略是:
属于普通进程的调度策略是:
下面我来跟你详细讲解每个调度策略代表什么:
讲完调度策略,我们来将优先级
task_struct 中关于优先级的定义如下:
int prio, static_prio, normal_prio;
unsigned int rt_priority;
这四个变量有什么联系呢?
prio 和 normal_prio 最初的值是相等的,它们都是基于 static_prio 或者 rt_priority 计算的(至于基于 staticc_prio 还是 rt_priority,取决于调度策略)
下面来看一看内核的代码
内核中将0139的优先级划分为两个范围,099表示实时进程优先级,100~139的优先级表示普通进程的优先级,数值越小表示优先级越高:
首先我们讲static_prio,进程启动的时候会设置好静态优先级。如果需要修改,可以通过nice系统调用来设置,nice的范围是-2019,最终映射到优先级为100139的部分,如下所示:
内核中定义如下:
/* nice的范围 */
#define MAX_NICE 19
#define MIN_NICE -20
#define NICE_WIDTH (MAX_NICE - MIN_NICE + 1) //20
#define DEFAULT_PRIO (MAX_RT_PRIO + NICE_WIDTH / 2) //120
#define NICE_TO_PRIO(nice) ((nice) + DEFAULT_PRIO) //100~139
void set_user_nice(struct task_struct *p, long nice)
{
...
p->static_prio = NICE_TO_PRIO(nice);
...
}
而 rt_priority 动态优先级又是怎么指定的呢?
用户层可以通过 sched_setscheduler,将普通进程更改为实时进程,通过更改进程的调度策略,同时设置 rt_priority,也就是说它的值可以是应用程序指定的,范围是0~99
在清楚 static_prio 和 rt_priority 怎么得来之后,我们来看看 normal_prio 和 prio 这两个变量是怎么计算的
内核中通过下面的代码来设置:
p->prio = effective_prio(p);
看一下 effective_prio 的定义:
static int effective_prio(struct task_struct *p)
{
p->normal_prio = normal_prio(p);
if (!rt_prio(p->prio))
return p->normal_prio;
/* 如果进程的优先级本来是实时优先级或者进程被提高到实时进程,那么就保持不变 */
return p->prio;
}
可以看到,通过这条指令 p->prio = effective_prio§,会同时设置 prio 和 normal_prio,下面来看看 normal_prio 函数的定义,这个函数也是解开这几个变量之间关系的关键:
#define MAX_DL_PRIO 0
static inline int normal_prio(struct task_struct *p)
{
int prio;
if (task_has_dl_policy(p)) //deadline调度策略
prio = MAX_DL_PRIO-1; //-1
else if (task_has_rt_policy(p)) //FIFO或者RR的调度策略
prio = MAX_RT_PRIO-1 - p->rt_priority; //99-rt_priority
else //普通进程调度策略(NORMAL、BATCH、IDLE)
prio = __normal_prio(p);
return prio;
}
normal_prio 根据进程不同的调度策略,使用不同的方法来设置进程的优先级:
static inline int __normal_prio(struct task_struct *p)
{
/* 直接返回static_prio */
return p->static_prio;
}
将上述的关系整理下表:
优先级和调度策略都存在于 task_struct 中,它们都是描述进程的信息,它们具体有什么用,我们下面将会介绍。
文章参考:https://blog.csdn.net/weixin_42462202/article/details/102887008?spm=1001.2014.3001.5502
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有