linux 线程优先级 rt_prio static_prio prio normal_prio

 转载:https://www.cnblogs.com/tongye/p/9615625.html

 

kthread_create 创建线程的时候是默认的优先级默认的RT线程rt_prio是0,rt_prio范围是0-99

调整线程优先级的函数sched_setschduler 可以调整线程优先级,因为GPL的原因会有必要绕到user space调用的userspace的sched_setscheduler 函数来调整线程优先级

传参5 调整后结果  [static_prio 120]  [normal_prio 5]  [prio:5]  [rt_prio 94] 对于RT thread 只关注rt_prio即可

(ps  -el 是查看不到  rt_prio的 以上结果用debug tool看到的)

/**
 * sched_setscheduler - change the scheduling policy and/or RT priority of a thread.
 * @p: the task in question.
 * @policy: new policy./**
 * sched_setscheduler - change the scheduling policy and/or RT priority of a thread.
 * @p: the task in question.
 * @policy: new policy.
 * @param: structure containing the new RT priority.
 *
 * Return: 0 on success. An error code otherwise.
 *
 * NOTE that the task may be already dead.
 */
int sched_setscheduler(struct task_struct *p, int policy,
		       const struct sched_param *param)
{
	return _sched_setscheduler(p, policy, param, true);
}
EXPORT_SYMBOL_GPL(sched_setscheduler);

 

 

       #include <sched.h>

       int sched_setscheduler(pid_t pid, int policy,
                              const struct sched_param *param);

       The sched_setscheduler() system call sets both the scheduling policy
       and parameters for the thread whose ID is specified in pid.  If pid
       equals zero, the scheduling policy and parameters of the calling
       thread will be set.

_______________________________________________________________________________________________

Linux 中采用了两种不同的优先级范围,一种是 nice 值,一种是实时优先级。在上一篇粗略的说了一下 nice 值和实时优先级,仍有不少疑问,本文来详细说明一下进程优先级。linux 内核版本为 linux 2.6.34 。

  进程优先级的相关信息,存放在进程描述符 task_struct 中:

复制代码

struct task_struct {
        ...
    int prio, static_prio, normal_prio;
    unsigned int rt_priority;
        ...
}

复制代码

  可以看到,有四种进程优先级: prio、static_prio、normal_prio 和 rt_priority,它们的具体定义在 kernel/sched.c 中,在介绍这四种优先级之前,先介绍一下以下宏定义:

复制代码

/* linux-kernel 2.6.34 /include/linux/sched.h */

/*
 * Priority of a process goes from 0..MAX_PRIO-1, valid RT
 * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH
 * tasks are in the range MAX_RT_PRIO..MAX_PRIO-1. Priority
 * values are inverted: lower p->prio value means higher priority.
 *
 * The MAX_USER_RT_PRIO value allows the actual maximum
 * RT priority to be separate from the value exported to
 * user-space.  This allows kernel threads to set their
 * priority to a value higher than any user task. Note:
 * MAX_RT_PRIO must not be smaller than MAX_USER_RT_PRIO.
 */

#define MAX_USER_RT_PRIO     100
#define MAX_RT_PRIO          MAX_USER_RT_PRIO

#define MAX_PRIO            (MAX_RT_PRIO + 40)
#define DEFAULT_PRIO        (MAX_RT_PRIO + 20)    // 默认优先级,对应 nice 值为 0 的静态优先级

复制代码

 

1、prio 动态优先级

  prio 的值是调度器最终使用的优先级数值,即调度器选择一个进程时实际选择的值。prio 值越小,表明进程的优先级越高。prio  值的取值范围是 0 ~ MAX_PRIO,即 0 ~ 139(包括 0 和 139),根据调度策略的不同,又可以分为两个区间,其中区间 0 ~ 99 的属于实时进程,区间 100 ~139 的为非实时进程。用语言不好描述,我们通过内核代码来详细描述 prio:

复制代码

/* linux-kernel 2.6.34  /kernel/sched.c  */

#include "sched_idletask.c"
#include "sched_fair.c"
#include "sched_rt.c"
#ifdef CONFIG_SCHED_DEBUG
#include "sched_debug.c"
#endif

/*
 * __normal_prio - return the priority that is based on the static prio
 */
static inline int __normal_prio(struct task_struct *p)    // _normal_prio 函数,返回静态优先级值
{
    return p->static_prio;
}

/*
 * Calculate the expected normal priority: i.e. priority
 * without taking RT-inheritance into account. Might be
 * boosted by interactivity modifiers. Changes upon fork,
 * setprio syscalls, and whenever the interactivity
 * estimator recalculates.
 */
static inline int normal_prio(struct task_struct *p)    // normal_prio 函数
{
    int prio;

    if (task_has_rt_policy(p))                 // task_has_rt_policy 函数,判断进程是否为实时进程,若为实时进程,则返回1,否则返回0
        prio = MAX_RT_PRIO-1 - p->rt_priority;        // 进程为实时进程,prio 值为实时优先级值做相关运算得到: prio = MAX_RT_PRIO -1 - p->rt_priority
    else
        prio = __normal_prio(p);                // 进程为非实时进程,则 prio 值为静态优先级值,即 prio = p->static_prio
    return prio;
}

/*
 * Calculate the current priority, i.e. the priority
 * taken into account by the scheduler. This value might
 * be boosted by RT tasks, or might be boosted by
 * interactivity modifiers. Will be RT if the task got
 * RT-boosted. If not then it returns p->normal_prio.
 */
static int effective_prio(struct task_struct *p)       // effective_prio 函数,计算进程的有效优先级,即prio值,这个值是最终调度器所使用的优先级值
{
    p->normal_prio = normal_prio(p);              // 计算 normal_prio 的值
    /*
     * 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;                  // 若进程是非实时进程,则返回 normal_prio 值,这时的 normal_prio = static_prio
    return p->prio;                         // 否则,返回值不变,依然为 prio 值,此时 prio = MAX_RT_PRIO -1 - p->rt_priority
} 

/*********************** 函数 set_user_nice ****************************************/
void set_user_nice(struct task_struct *p, long nice)
{
     ....
    p->prio = effective_prio(p);                   // 在函数 set_user_nice 中,调用 effective_prio 函数来设置进程的 prio 值
     ....
}

复制代码

  从上面代码中我们知道,当进程为实时进程时, prio 的值由实时优先级值(rt_priority)计算得来;当进程为非实时进程时,prio 的值由静态优先级值(static_prio)得来。即:

prio = MAX_RT_PRIO - 1 - rt_priority    // 进程为实时进程

prio = static_prio          // 进程为非实时进程

  简单计算上面的两个式子,可以知道,prio 值的范围是 0 ~ 139 。

 

2、static_prio 静态优先级

  静态优先级不会随时间改变,内核不会主动修改它,只能通过系统调用 nice 去修改 static_prio,如下:

复制代码

/*
 * Convert user-nice values [ -20 ... 0 ... 19 ]
 * to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ],
 * and back.
 */
#define NICE_TO_PRIO(nice)    (MAX_RT_PRIO + (nice) + 20)
#define PRIO_TO_NICE(prio)    ((prio) - MAX_RT_PRIO - 20)
#define TASK_NICE(p)        PRIO_TO_NICE((p)->static_prio)

/*
 * 'User priority' is the nice value converted to something we
 * can work with better when scaling various scheduler parameters,
 * it's a [ 0 ... 39 ] range.
 */
#define USER_PRIO(p)        ((p)-MAX_RT_PRIO)
#define TASK_USER_PRIO(p)    USER_PRIO((p)->static_prio)
#define MAX_USER_PRIO        (USER_PRIO(MAX_PRIO))

/********************* 函数 set_user_nice *****************************/
p->static_prio = NICE_TO_PRIO(nice);        // 当有需要时,系统会通过调用 NICE_TO_PRIO() 来修改 static_prio 的值

复制代码

 

  由上面代码知道,我们可以通过调用 NICE_TO_PRIO(nice) 来修改 static_prio  的值, static_prio 值的计算方法如下:

static_prio = MAX_RT_PRIO + nice +20

  MAX_RT_PRIO 的值为100,nice 的范围是 -20 ~ +19,故 static_prio 值的范围是 100 ~ 139。 static_prio 的值越小,表明进程的静态优先级越高

 

3、normal_prio 归一化优先级

  normal_prio 的值取决于静态优先级和调度策略,可以通过 _setscheduler 函数来设置 normal_prio 的值 。对于非实时进程,normal_prio 的值就等于静态优先级值 static_prio;对于实时进程,normal_prio = MAX_RT_PRIO-1 - p->rt_priority。代码如下:

复制代码

static inline int normal_prio(struct task_struct *p)    // normal_prio 函数
{
    int prio;

    if (task_has_rt_policy(p))                 // task_has_rt_policy 函数,判断进程是否为实时进程,若为实时进程,则返回1,否则返回0
        prio = MAX_RT_PRIO-1 - p->rt_priority;        // 进程为实时进程,prio 值为实时优先级值做相关运算得到: prio = MAX_RT_PRIO -1 - p->rt_priority
    else
        prio = __normal_prio(p);                // 进程为非实时进程,则 prio 值为静态优先级值,即 prio = p->static_prio
    return prio;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值