linux内核工程师 2.08节 linux内核实现多处理(进程优先级与权重)

1.进程优先级内核表示 
进程的优先级的nice值在-20~+19之间。0~139表示内部优先级,0~99的范围专供实时进程使用。nice值在[-20,+19]映射到100~139之间。如下图所示。 
这里写图片描述 
进程优先级宏在不同形式间转换:

/*  从用户优先级的nice值和静态优先级的转换 */
#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)

/* 用户优先级根据调度参数转变到最佳共作级别 */
#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))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

2.进程优先级的计算 
static是计算的起点,假定已经设置成功。 
则计算当前进程优先级,p->prio = effective_prio(p);

    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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
普通进程优先级计算的实现:
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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

普通进程的优先级只是返回了静态优先级而已。

static inline int __normal_prio(struct task_struct *p)
{
    return p->static_prio;
}
  • 1
  • 2
  • 3
  • 4

下面表格对上述的实现做了总结, 对各种类型的进程计算优先级。

这里写图片描述 
注意:在进程支出子进程时,子进程的静态优先级继承自父进程。子进程的动态优先级则设置为父进程的普通父进程,这确保了实时互斥量引起的优先级提高不会传递给子进程。 
3.计算负荷权重 
进程的重要性由优先级和task_struct->se.load的负荷权重。set_load_weight负责根据进程类型及其静态优先级计算负荷权重。

其实现过程如下:
     static void set_load_weight(struct task_struct *p)
{
    if (task_has_rt_policy(p)) {
        p->se.load.weight = prio_to_weight[0] * 2;
        p->se.load.inv_weight = prio_to_wmult[0] >> 1;
        return;
    }

    /*
     * SCHED_IDLE tasks get minimal weight:
     */
    if (p->policy == SCHED_IDLE) {
        p->se.load.weight = WEIGHT_IDLEPRIO;
        p->se.load.inv_weight = WMULT_IDLEPRIO;
        return;
    }

    p->se.load.weight = prio_to_weight[p->static_prio - MAX_RT_PRIO];
    p->se.load.inv_weight = prio_to_wmult[p->static_prio - MAX_RT_PRIO];
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

负荷权重包含在数据结构load_weight中:

<sched.h>
struct load_weight {
unsigned long weight, inv_weight;
};
  • 1
  • 2
  • 3
  • 4
一般进程每降低一个nice值,则看获得10%的CPU时间。内核将优先级转换为权重值,下面是这个转换表。
  • 1
  • 2
    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,
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

不仅进程,就绪队列也关联到了一个负载权重。在进程被加载进就绪队列时,内核会调用inc_nr_running,还将进程的权重添加到就绪队列的权重中。

static inline void update_load_add(struct load_weight *lw, unsigned long inc)
{
    lw->weight += inc;
}

static inline void update_load_sub(struct load_weight *lw, unsigned long dec)
{
    lw->weight -= dec;
}
static void inc_nr_running(struct task_struct *p, struct rq *rq)
{
    rq->nr_running++;
    inc_load(rq, p);
}

猜你喜欢

转载自blog.csdn.net/zjy900507/article/details/80664980