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

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的值越大,实时优先级越高。
  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux中,进程的调度策略和实时优先级可以通过调整相关参数进行设定。 进程的调度策略由调度类别和调度策略两部分组成。调度类别包括实时进程和普通进程,而调度策略包括FIFO(先进先出)、RR(轮转)、以及其他一些实时调度策略。 对于实时进程,可以通过设置调度策略和实时优先级,来决定进程的调度次序。调度策略包括SCHED_FIFO(先进先出)和SCHED_RR(轮转)两种。SCHED_FIFO策略下,实时进程的执行顺序按照进入等待队列的先后顺序,优先级越高的进程越先执行;而SCHED_RR策略下,实时进程以时间片为单位进行轮转调度,每个进程执行一个时间片后切换到下一个进程实时进程实时优先级范围为1-99,优先级越高的进程被调度的机会越多。 对于普通进程,可以选择使用其他实时调度策略,如SCHED_NORMAL(普通进程默认调度策略)等。除了实时优先级外,普通进程还有一个静态优先级,范围从0-39,静态优先级越高的进程在竞争CPU资源时被CPU调度程序考虑的机会越多。 在Linux系统中,可以使用相关命令和API函数来设定进程的调度策略和实时优先级。例如,通过使用命令"chrt"可以更改进程的调度策略和实时优先级,而在编程时可以使用调度相关的函数如sched_setscheduler()和sched_setparam()来进行设定。 通过合理设置进程的调度策略和实时优先级,可以优化系统的性能,使得实时任务能够按照预定的要求运行。但需要注意的是,过高的实时优先级可能会导致系统其他进程被饿死,因此需要在设定时进行权衡和限制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值