您的位置:首页 > 运维架构 > Linux

【linux】非实时进程,实时进程, 优先级

2014-06-06 13:46 211 查看
Linux的进程分普通进程和实时进程,普通进程即非实时进程SCHED_OTHER或SCHED_NORMAL,而实时进程又分SCHED_FIFO与SCHED_RR,实时进程的优先级(0~99)都比普通进程的优先级(100~139)高,且直到死亡之前始终是活动进程,当系统中有实时进程运行时,普通进程几乎是无法分到时间片的(只能分到5%的CPU时间)。

1.调度策略

task_struct->unsigned long policy;指定调度策略

#define SCHED_NORMAL 0 //非实时进程,CFS

#define SCHED_FIFO 1 //实时进程,先进先出,它就一直运行直到退出,除非它阻塞才会释放CPU, 或被更高优先级的实时进程抢占。

#define SCHED_RR 2 //实时进程,基于优先级的轮回法(Round Robin),只有当它的时间片用完,内核会把它放到进程队列的末尾。

2.下面细述普通进程和实时进程及其优先级

内核代码中有下面4种优先级: dynamic priority (task_struct->prio), normal priority(task_struct->normal_prio), static priority,以及实时进程的rt_priority。

2.1 static priority

static priority的范围是100-139(MAX_RT_PRIO - MAX_PRIO-1),

static priority Base Time Quantum(5ms ~ 800ms)

< 120 (140 - static priority) × 20

>= 120 (140 - static priority) × 5

静态优先级数值越大,进程的优先级越小,分配的基时间量就越少。

一个进程通常会继承其父进程的static priority。也可以通过系统调用nice()或者setpriority()指定。

内核2.6中的静态优先级相当于内核2.4中的nice值,但转到MAX_RT_PRIO到MAX_PRIO-1取值范围,其公式为:

static priority = nice + 20 + MAX_RT_PRIO

内核定义两个宏来实现此转化:nice_to_prio() and prio_to_nice()

#define NICE_TO_PRIO(nice) (MAX_RT_PRIO + (nice) + 20)

#define PRIO_TO_NICE(prio) ((prio) - MAX_RT_PRIO - 20)

读取进程nice值

#define TASK_NICE(p) PRIO_TO_NICE((p)->static_prio)

静态优先级决定了进程的权重,也就是进程虚拟时间增长的快慢?

# define scale_load(w) (w)

static void set_load_weight(struct task_struct *p)

{

int prio = p->static_prio - MAX_RT_PRIO;

struct load_weight *load = &p->se.load;

/*

* SCHED_IDLE tasks get minimal weight:

*/

if (p->policy == SCHED_IDLE) {

load->weight = scale_load(WEIGHT_IDLEPRIO);

load->inv_weight = WMULT_IDLEPRIO;

return;

}

load->weight = scale_load(prio_to_weight[prio]);

load->inv_weight = prio_to_wmult[prio];

}

p->static_prio - MAX_RT_PRIO,决定了进程优先级权重在prio_to_weight数组中的取值

static const int prio_to_weight[40] = {

/* -20 */ 88761, 71755, 56483, 46273, 36291,

/* -15 */ 29154, 23254, 18705, 14949, 11916,

/* -10 */ 9548, 7620, 6100, 4904, 3906,

/* -5 */ 3121, 2501, 1991, 1586, 1277,

/* 0 */ 1024, 820, 655, 526, 423,

/* 5 */ 335, 272, 215, 172, 137,

/* 10 */ 110, 87, 70, 56, 45,

/* 15 */ 36, 29, 23, 18, 15,

};

NICE_0_LOAD = 1024,是中间值。

2.2实时进程的rt_priority

除了dynamic priority, normal priority, static priority之外,每个实时进程都有一与其相关的实时优先级,取值范围0-MAX_RT_PRIO-1(0~99)。

其大小可以通过sched_setscheduler()和__setscheduler_params()来改变。

实时进程被一个进程替换,可能的情况有:

a)进程被拥有更高优先级的进程抢占。

b)进程发生阻塞进入睡眠状态。

c)进程被终止(状态为TASK_STOPPED OR TASK_TRACED)或者被杀死(EXIT_DEAD OR EXIT_ZOMBIE)。

d)进程通过调用sched_yield()自愿放弃处理器。

e)进程是轮回实时(SCHED_RR)且其时间片执行完毕。

f)当在SCHED_RR时调用nice()和set_priority()函数并不影响实时优先级,只会影响静态优先级(从而影响基时间片)。

2.3 normal priority和dynamic priority

dynamic priority (task_struct->prio), normal priority(task_struct->normal_prio)与static priority, rt_priority之间有着不可分割的联系。

static_prio是其他priority计算的开始。假定static_prio已经设置好,kernel通过effective_prio()来计算其他优先级。

p->prio = effective_prio(p);

kernel/sched/core.c

static int effective_prio(struct task_struct *p)

{

p->normal_prio = normal_prio(p);

/*

* If we are RT tasks or we were boosted to RT priority,

* keep the priority unchanged. Otherwise, update priority

* to the normal priority:

*/

if (!rt_prio(p->prio))

return p->normal_prio;

return p->prio;

}

static inline int normal_prio(struct task_struct *p)

{

int prio;

if (task_has_rt_policy(p))

prio = MAX_RT_PRIO-1 - p->rt_priority;

else

prio = __normal_prio(p);

return prio;

}

static inline int __normal_prio(struct task_struct *p)

{

return p->static_prio;

}

结合这三个函数看一下,task_has_rt_policy()用来区分进程是否是实时进程()

如果进程是普通进程,那么normal_prio被设置为static_prio,(prio也等于static_prio?),dynamic priority = normal priority = static priority

如果进程是实时进程,那么normal_prio被设置成(MAX_RT_PRIO-1 - p->rt_priority),prio被设置成(MAX_RT_PRIO-1 - p->rt_priority)。

rt_priority的值越大,实时优先级越高。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: