Linux线程优先级

Sep 18th, 2013| Comments              

1. Linux线程优先级范围

Linux定义线程优先级范围在头文件<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)

2. Linux线程调度策略

Linux定义线程调度策略在头文件<linux/sched.h>

#define SCHED_NORMAL    0
#define SCHED_FIFO      1
#define SCHED_RR        2
#define SCHED_BATCH     3
/* SCHED_ISO: reserved but not implemented yet */
#define SCHED_IDLE      5

SCHED_NORMAL即为SCHED_OTHER:采用分时调度策略。
SCHED_FIFO:采用实时调度策略,且先到先服务,一直运行直到有更高优先级任务到达或自己放弃。
SCHED_RR:采用实时调度策略,且时间片轮转,时间片用完,系统将重新分配时间片,并置于就绪队列尾。
SCHED_BATCH:针对批处理进程。
SCHED_IDLE:使用此调度器的进程的优先级最低。在实现CFS时引入。

3. Linux线程调度算法

4 shell下查看线程优先级

1 top命令

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND                                                                          
    1 root      20   0  2804 1576 1192 S  0.0  0.3   0:00.97 init                                                                           
    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd                                                                       
    3 root      RT   0     0    0    0 S  0.0  0.0   0:00.00 migration/0                                                                    
    4 root      20   0     0    0    0 S  0.0  0.0   0:00.02 ksoftirqd/0                                                                    
    5 root      RT   0     0    0    0 S  0.0  0.0   0:00.00 watchdog/0                                                                     
    6 root      20   0     0    0    0 S  0.0  0.0   0:00.06 events/0

PR为线程优先级,范围[0, 40),实时优先级的线程显示为RT。值越小优先级越高
NI为Nice值,范围[-20, 20),PR值为初始线程优先级加上Nice值。
PR 和 NI 值都是从 proc文件系统中读取得到 “/proc/[pid]/stat”

cat /proc/1/stat
1 (init) S 0 1 1 0 -1 4202752 4680 154640 23 343 6 136 154 151 20 0 ...
cat /proc/3/stat
3 (migration/0) S 2 0 0 0 -1 2216730688 0 0 0 0 0 0 0 0 -100 0  ...

通过man proc 查看stat的第18项和第19项的说明如下

priority %ld
(18) (Explanation for Linux 2.6) For processes running a real-time scheduling policy (policy below; see sched_setscheduler(2)), 
this is the negated scheduling priority, minus one; that is, a number in the range -2 to -100, corresponding to real-time priorities 1 to 99. 
For processes running under a non-real-time scheduling policy, this is the raw nice value (setpriority(2)) as represented in the kernel. 
The kernel stores nice values as numbers in the range 0 (high) to 39 (low), corresponding to the user-visible nice range of -20 to 19.

Before Linux 2.6, this was a scaled value based on the scheduler weighting given to this process.

nice %ld
(19) The nice value (see setpriority(2)), a value in the range 19 (low priority) to -20 (high priority).

2 ps命令

c@c-desktop:~$ ps -el
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S     0     1     0  0  80   0 -   702 poll_s ?        00:00:01 init
1 S     0     2     0  0  80   0 -     0 kthrea ?        00:00:00 kthreadd
1 S     0     3     2  0 -40   - -     0 migrat ?        00:00:00 migration/0
1 S     0     4     2  0  80   0 -     0 ksofti ?        00:00:00 ksoftirqd/0
5 S     0     5     2  0 -40   - -     0 watchd ?        00:00:00 watchdog/0
1 S     0     6     2  0  80   0 -     0 worker ?        00:00:00 events/0

这里的PRI为什么和top的PR不一样呢,通过查看procps源代码找到了原因

In linux procps, the column labeled "PRI" in ps -l is -o opri
c@c-desktop:~$ ps -e -o pid,pri,opri,intpri,priority,ni,cmd
  PID PRI PRI PRI PRI  NI CMD
    1  19  80  80  20   0 /sbin/init
    2  19  80  80  20   0 [kthreadd]
    3 139 -40 -40 -100  - [migration/0]
    4  19  80  80  20   0 [ksoftirqd/0]
    5 139 -40 -40 -100  - [watchdog/0]
    6  19  80  80  20   0 [events/0]

procps/output.c中含有具体说明

// "priority"         (was -20..20, now -100..39)
// "intpri" and "opri" (was 39..79, now  -40..99)
// "pri_foo"   --  match up w/ nice values of sleeping processes (-120..19)
// "pri_bar"   --  makes RT pri show as negative       (-99..40)
// "pri_baz"   --  the kernel's ->prio value, as of Linux 2.6.8     (1..140)
// "pri"               (was 20..60, now    0..139)
// "pri_api"   --  match up w/ RT API    (-40..99)

5 shell下修改线程优先级

1 nice命令

nice命令可以指定线程加载时的Nice值,来改变线程优先级。
nice -n [priority] [command]
输入的优先级超过19时取19,小于-20时取-20。

root@c-desktop:~/Code# nice -n -20 ./a.out &
root@c-desktop:~/Code# ps -o pid,priority,ni,cmd
  PID PRI  NI CMD
 2138   0 -20 ./a.out

root@c-desktop:~/Code# nice -n 19 ./a.out &
root@c-desktop:~/Code# ps -o pid,priority,ni,cmd
  PID PRI  NI CMD
 2145  39  19 ./a.out

2 renice命令

renice命令可以改变运行中线程的Nice值,进而改变线程的优先级。
renice -n [priority] -p [pid]
输入的优先级超过19时取19,小于-20时取-20。

root@c-desktop:~/Code# ps -o pid,priority,ni,cmd
  PID PRI  NI CMD
 2145  39  19 ./a.out

root@c-desktop:~/Code# renice -n -20 -p 2145
2145: old priority 19, new priority -20

root@c-desktop:~/Code# ps -o pid,priority,ni,cmd
  PID PRI  NI CMD
 2145   0 -20 ./a.out

6. Reference

(1) http://oreilly.com/catalog/linuxkernel/chapter/ch10.html
(2) http://superuser.com/questions/286752/unix-ps-l-priority
(3) http://procps.sourceforge.net/download.html 需要×××
(4) http://www.linuxjournal.com/article/3910
(5) http://www.linuxjournal.com/magazine/real-time-linux-kernel-scheduler
Author: chenxiawei@gmail.com

Sep 18th, 2013



                                                     zhuan