作为多任务的操作系统,Linux内核为每个创建的进程分配时间片并根据其优先级进行调度。当进程被创建时,其对应的task_struct里包含了四个优先级:
struct task_struct {
……
int prio, static_prio, normal_prio;
unsigned int rt_priority;
……
};
在内核头文件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)
内核中规定进程的优先级范围为[0, MAX_PRIO-1]。其中实时任务的优先级范围是[0, MAX_RT_PRIO-1],非实时任务的优先级范围是[MAX_RT_PRIO, MAX_PRIO-1]。优先级值越小,意味着级别越高,任务先被内核调度。
那任务的优先级又是如何确定的呢?和task_struct中的成员是什么关系?
① prio指的是任务当前的动态优先级,其值影响任务的调度顺序。
② normal_prio指的是任务的常规优先级,该值基于static_prio和调度策略计算。
③ static_prio指的是任务的静态优先级,在进程创建时分配,该值会影响分配给任务的时间片的长短和非实时任务动态优先级的计算。
④ rt_priority指的是任务的实时优先级。若为0表示是非实时任务,[1, 99]表示实时任务,值越大,优先级越高。
static_prio = MAX_RT_PRIO + 20 + nice(nice的缺省值是0,范围[20, 19])
rt_priority缺省值为0,表示非实时任务。[1,99]表示实时任务
对于实时任务,prio = normal_prio = static_prio
对于非实时任务 prio = normal_prio = MAX_RT_PRIO – 1 – rt_priority
prio的值在使用实时互斥量时会暂时提升,释放后恢复成normal_prio
下面来了解一下如何在应用程序中改变进程的优先级。
#include
#include
int setpriority(int which, int who, int prio);
//该函数可以修改进程、进程组或用户所有进程的nice值从而影响static_prio
which : PRIO_PROCESS // 修改某个进程
PRIO_PGRP // 修改进程组
PRIO_USER // 修改用户所有进程
who : 进程号(0表示当前调用进程)、进程组号或UID
prio : 新的用户态优先级(即nice值,范围[-20,19])
返回值 : 执行成功返回0,失败返回-1并设置errno
……
if (setpriority(PRO_PROCESS, 0, 2)
{
perror(“fail to setpriority”);
exit(-1);
}
……
************************************************************************
#include
int sched_setscheduler(pid_t pid, int policy, const struct sched_param *param);
struct sched_param
{
int __sched_priority;
};
// 该函数修改某个进程的调度策略和rt_priority
pid : 要修改的进程号,0表示当前调用进程
policy : 调度策略
SCHED_OTHER(针对非实时进程的调度策略)
SCHED_RR(针对实时进程的轮转调度策略)
SCHED_FIFO(针对实时进程的先进先出调度策略)
param : 指向的结构体中存放着要设置的rt_priority
返回值 : 执行成功返回0,失败返回-1并设置errno
……
struct sched_param sp = {1};
if (sched_setscheduler(0, SCHED_FIFO, &sp) < 0)
{
perror(“fail to sched_setscheduler”);
exit(-1);
}
……