Linux中实时优先级最高的是哪个优先级?

84
在Linux实时进程优先级范围1到99之间,我不确定哪个是最高优先级,是1还是99。《深入理解Linux内核》(O'Reilly)第7.2.2节表示1是最高优先级,这很有道理,因为普通进程的静态优先级为100到139,其中100是最高优先级。另一方面,《sched_setscheduler》手册页面(RHEL 6.1)声称99是最高优先级。那么,哪一个是最高实时优先级呢?
7个回答

101

我进行了如下实验来确定这个问题:

  • 进程1:实时优先级为40,CPU亲和力为CPU 0。这个进程“旋转”10秒钟,因此它不会让任何低优先级的进程在CPU 0上运行。

  • 进程2:实时优先级为39,CPU亲和力为CPU 0。这个进程每0.5秒打印一条消息到标准输出,在两次打印之间休眠。它在每条消息中打印经过的时间。

我正在运行一个带有PREEMPT_RT补丁的2.6.33内核。

为了运行这个实验,我在一个窗口中(作为root用户)运行进程2,然后在另一个窗口中启动进程1(作为root用户)。结果是进程1似乎抢占了进程2,不允许它完整地运行10秒钟。

在第二个实验中,我将进程2的实时优先级更改为41。在这种情况下,进程1不会抢占进程2。

这个实验表明,在sched_setscheduler()中使用更大的实时优先级值具有更高的优先级。这似乎与Michael Foukarakis从sched.h指出的相矛盾,但实际上并不是这样。在内核源代码sched.c中,我们有:

static void
__setscheduler(struct rq *rq, struct task_struct *p, int policy, int prio)
{
        BUG_ON(p->se.on_rq);

        p->policy = policy;
        p->rt_priority = prio;
        p->normal_prio = normal_prio(p);
        /* we are holding p->pi_lock already */
        p->prio = rt_mutex_getprio(p);
        if (rt_prio(p->prio))
                p->sched_class = &rt_sched_class;
        else
                p->sched_class = &fair_sched_class;
        set_load_weight(p);
}

rt_mutex_getprio(p)的作用如下:

return task->normal_prio;

normal_prio()函数执行以下操作:

prio = MAX_RT_PRIO-1 - p->rt_priority;  /* <===== notice! */
...
return prio;

换句话说,我们有(我的解释):

p->prio = p->normal_prio = MAX_RT_PRIO - 1 - p->rt_priority

哇!那太令人困惑了!简而言之:

  • 使用p->prio,较小的值会抢占较大的值。

  • 使用p->rt_priority,较大的值会抢占较小的值。这是使用sched_setscheduler()设置的实时优先级。


49

简答

99将成为实时优先级的获胜者。

PR是优先级等级(范围从-100到39)。 PR越低,进程的优先级就越高。

PR的计算如下:

  • 对于普通进程:PR = 20 + NI(NI很好,范围从-20到19)
  • 对于实时进程:PR = -1-real_time_priority(实时优先级的范围为1至99)

详细回答

有两种类型的进程,即普通进程实时进程。仅对普通进程应用“好”的规则如下:

"好"尺度从-20到19,其中-20是最高优先级,19是最低优先级。优先级等级的计算如下:

PR = 20 + NI

其中NI是好的水平,而PR是优先级水平。因此,我们可以看到-20实际上映射到0,而19映射到39。

默认情况下,程序的好价值是0,但是超级用户可以使用以下命令启动具有指定好价值的程序:

nice -n <nice_value> ./myProgram 

实时性

我们可以更进一步。优先级的好处实际上是用于用户程序的。而UNIX/LINUX整体优先级有140个值的范围,良好的优先级值使该进程能够映射到范围的最后部分(从100到139)。这个方程式使范围从0到99的值不可达,这将对应负PR级别(从-100到-1)。为了能够访问这些值,该进程应该被声明为“实时”。

LINUX环境中有5个调度策略,可以使用以下命令显示:

chrt -m 

它将显示以下列表:

1. SCHED_OTHER   the standard round-robin time-sharing policy
2. SCHED_BATCH   for "batch" style execution of processes
3. SCHED_IDLE    for running very low priority background jobs.
4. SCHED_FIFO    a first-in, first-out policy
5. SCHED_RR      a round-robin policy

调度过程可以分为两组,常规调度策略(1到3)和实时调度策略(4和5)。 实时进程将始终优先于常规进程。可以使用以下命令调用实时进程(以下示例是如何声明SCHED_RR策略的):

chrt --rr <priority between 1-99> ./myProgram

为了得到实时进程的PR值,应使用以下方程:

PR = -1 - rt_prior

其中rt_prior对应于1到99之间的优先级。因此,将具有比其他进程更高优先级的进程称为以数字99调用的进程。

重要的是要注意,对于实时进程,不使用美好值。

要查看进程的当前“niceness”和PR值,可以执行以下命令:

top

以下是显示的输出:

输入图像描述

该图显示了PR和NI值。值得注意的是,具有实时值对应的PR值为-51的进程。还有一些进程其PR值被说明为“rt”。 实际上,这个值对应于-100的PR值。


对于寻求关于实时调度中chrt的快速答案的人们。对于chrt,1具有最低优先级,99具有最高优先级。我很惊讶在chrt的man页面中没有提到这一点。 - B.Z.
2
我无法提出进一步的编辑建议,但我认为这个答案中存在一些矛盾的细节。答案一开始说“PR = 20 - NI”,并且PR值的范围从-100到40。但后来它说“PR = 20 + NI”,并且PR值的范围从-100到39。我相对有信心认为后者(即PR = 20 + NI,并且范围从-100到39)是正确的! - Ken Lin
@KenLin 是的,之前有一个错误,但实际上相反。PR = 20 + NI。已经进行了更正,感谢您指出。 - J Agustin Barrachina
1
我仍然看到“PR是优先级水平(范围为-100到40)”。40不应该改为39吗? - Ken Lin

11

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.
 */

注意这一部分:

优先级数值是反转的:较低的 p->prio 值表示更高的优先级。


1
但是这些优先级值是向用户空间公开的吗?(我不这么认为)。 - davmac
1
@davmac:不,它们完全不同。这些是内核内部的。 - Michael Foukarakis
1
好的。看起来这本书谈论的是这些值,因为我不认为单个等效优先级值可供用户空间使用。在这种情况下,假设MAX_PRIO=139和MAX_RT_PRIO=99,那么这本书只有一个细节错误:最高优先级值为0,而不是1。(点赞:你的回答很到位)。 - davmac

6

要确定您可以在程序中编程设置的最高实时优先级,请利用sched_get_priority_max函数。

在Linux 2.6.32上,调用sched_get_priority_max(SCHED_FIFO)会返回99。

参见http://linux.die.net/man/2/sched_get_priority_max


3
更适用于OP的问题,来自同一个手册页:“具有数值较高优先级值的进程会在具有数值较低优先级值的进程之前被安排运行。” - davmac

2

Linux内核实现了两个不同的优先级范围 -

  1. Nice值:-20至+19;较大的 Nice 值对应着 较低的优先级

  2. 实时优先级:0至99;较高的 实时优先级值对应着 更高的优先级


谢谢您的帮助,但是您可以通过解释这两个优先级之间的关系来改进答案。例如,添加有关实时优先级范围和非实时范围重叠的详细信息,以及在此上下文中“nice”优先级的含义。 - Olli

1

你认为正常进程的静态优先级从100到139是不稳定的,最坏的情况下是无效的。我的意思是:set_scheduler只允许使用SCHED_OTHER / SCHED_BATCH和SCHED_IDLE(截至2.6.16),sched_priority为0(表示动态优先级调度程序)。

在编程上,静态优先级仅适用于SCHED_RR和SCHED_FIFO,范围为1-99。

现在你可能会看到动态调度程序内部使用了100-139的优先级,但是内核在管理动态优先级时所做的操作(包括翻转高优先级与低优先级的含义以使比较或排序更容易)应该对用户空间不透明。

请记住,在SCHED_OTHER中,您主要将进程放入相同的优先级队列中。

这样做的想法是使内核更易于调试并避免愚蠢的越界错误。

因此,切换含义的理由可能是作为内核开发人员,不想使用像139-idx这样的数学公式(以防idx>139)...最好使用idx-100进行数学计算,并反转低优先级与高优先级的概念,因为idx<100是众所周知的。

另一个副作用是niceness变得更容易处理。 100-100 <=> nice == 0; 101-100 <=> nice == 1; 等等更容易。 它也很好地折叠为负数(与静态优先级无关)。 99-100 <=> nice == -1 ...


好的,我看到sched_priority与静态优先级不同,并且所有非实时进程的sched_priority为0。 - David Steinhauer
1
因此,静态优先级仅影响实时进程的时间片。我认为sched_priority是O'Reilly书中所称的“实时优先级”。如果是这样,那么O'Reilly书反了过来。那么,回到我的最初问题:sched_priority的值为99是否表示最高优先级,还是值为1表示最高优先级呢? - David Steinhauer

0
  1. 是的,实时优先级适用于RT策略FIFO和RR,范围为0-99。
  2. 我们确实有40作为批处理、其他策略的非实时进程优先级计数,范围为0-39而不是100至139。您可以通过查看系统中任何不是实时进程的进程来观察到这一点。默认情况下,它将具有20的PR和0的niceness。如果您降低进程的niceness(通常是越小或负数的数字表示进程越饥饿),例如从0到-1,则会发现优先级从20下降到19。 这只是告诉您,如果您让进程更加饥饿或希望通过降低PID的niceness值获得更多关注,您也会获得优先级的降低,因此优先级数字越低,优先级越高。

    示例:
    
    PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    2079 admin     10 -10  280m  31m 4032 S  9.6  0.0  21183:05 mgmtd
    [admin@abc.com ~]# renice -n -11 2079
    2079: old priority -10, new priority -11
    [admin@abc.com ~]# top -b | grep mgmtd
    2079 admin      9 -11  280m  31m 4032 S  0.0  0.0  21183:05 mgmtd
    ^C
    
希望这个实际的例子能够澄清疑问,如果有的话,可能会帮助修正源代码中不正确的单词。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接