进程调度之优先级详解...

This commit is contained in:
gatieme
2016-06-19 21:29:24 +08:00
parent fcf515c571
commit 968d0769b1
2 changed files with 120 additions and 20 deletions
@@ -124,9 +124,12 @@ linux把进程区分为实时进程和非实时进程, 其中非实时进程进
这需要与CPU的紧密交互. 每个进程刚好属于某一调度类, 各个调度类负责管理所属的进程. 通用调度器自身不涉及进程管理, 其工作都委托给调度器类.
#优先级的内核表示
##优先级的内核表示
-------
**linux优先级概述**
>在用户空间通过nice命令设置进程的静态优先级, 这在内部会调用nice系统调用, 进程的nice值在-20~+19之间. 值越低优先级越高.
>
>setpriority系统调用也可以用来设置进程的优先级. 它不仅能够修改单个线程的优先级, 还能修改进程组中所有进程的优先级, 或者通过制定UID来修改特定用户的所有进程的优先级
@@ -147,6 +150,10 @@ linux把进程区分为实时进程和非实时进程, 其中非实时进程进
![内核的优先级标度](./images/priority.jpg)
**内核的优先级表示**
内核表示优先级的所有信息基本都放在[include/linux/sched/prio.h](http://lxr.free-electrons.com/source/include/linux/sched/prio.h?v=4.6)中, 其中定义了一些表示优先级的宏和函数,
优先级数值通过宏来定义, 如下所示,
其中MAX_NICE和MIN_NICE定义了nice的最大最小值
@@ -159,20 +166,11 @@ linux把进程区分为实时进程和非实时进程, 其中非实时进程进
#define MIN_NICE -20
#define NICE_WIDTH (MAX_NICE - MIN_NICE + 1)
/* http://lxr.free-electrons.com/source/include/linux/sched/prio.h?v=4.6#L21 */
#define MAX_USER_RT_PRIO 100
#define MAX_RT_PRIO MAX_USER_RT_PRIO
/* http://lxr.free-electrons.com/source/include/linux/sched/prio.h?v=4.6#L24 */
#define MAX_PRIO (MAX_RT_PRIO + 40)
#define DEFAULT_PRIO (MAX_RT_PRIO + 20)
```
此外新版本的内核还引入了EDF实时调度算法, 它的优先级比RT进程和NORMAL/BATCH进程的优先级都要高, 因此内核将MAX_DL_PRIO设置为0, 可以参见内核文件[include/linux/sched/deadline.h](http://lxr.free-electrons.com/source/include/linux/sched/deadline.h)
```c
#define MAX_DL_PRIO 0
````
| 宏 | 值 | 描述 |
| ------------- |:-------------:|:-------------:|
@@ -186,6 +184,7 @@ linux把进程区分为实时进程和非实时进程, 其中非实时进程进
而内核提供了一组宏将优先级在各种不同的表示形之间转移
```c
// http://lxr.free-electrons.com/source/include/linux/sched/prio.h?v=4.6#L27
/*
@@ -206,13 +205,43 @@ linux把进程区分为实时进程和非实时进程, 其中非实时进程进
#define MAX_USER_PRIO (USER_PRIO(MAX_PRIO))
```
此外也提供了一些EDF调度算法的函数, 如下所示
还有一些nice值和rlimit值之间相互转换的函数nice_to_rlimit和rlimit_to_nice, 这在nice系统调用进行检查的时候很有用, 他们定义在[include/linux/sched/prio.h, L47](http://lxr.free-electrons.com/source/include/linux/sched/prio.h#L47)中, 如下所示
```c
/*
* Convert nice value [19,-20] to rlimit style value [1,40].
*/
static inline long nice_to_rlimit(long nice)
{
return (MAX_NICE - nice + 1);
}
/*
* Convert rlimit style value [1,40] to nice value [-20, 19].
*/
static inline long rlimit_to_nice(long prio)
{
return (MAX_NICE - prio + 1);
}
```
**DEF最早截至时间优先实时调度算法的优先级描述**
此外新版本的内核还引入了EDF实时调度算法, 它的优先级比RT进程和NORMAL/BATCH进程的优先级都要高, 关于EDF的优先级的设置信息都早内核头文件[include/linux/sched/deadline.h](http://lxr.free-electrons.com/source/include/linux/sched/deadline.h?v=4.6#L10)
因此内核将MAX_DL_PRIO设置为0, 可以参见内核文件[include/linux/sched/deadline.h](http://lxr.free-electrons.com/source/include/linux/sched/deadline.h?v=4.6#L10)
```c
#define MAX_DL_PRIO 0
```
此外也提供了一些EDF优先级处理所需的函数, 如下所示, 可以参见内核文件[include/linux/sched/deadline.h](http://lxr.free-electrons.com/source/include/linux/sched/deadline.h?v=4.6#L12)
```c
/* 判断一个优先级数值是不是EDF调度算法的优先级 */
static inline int dl_prio(int prio)
{
/* 数组小于MAX_DL_PRIO的优先级就是EDF算法的优先级 */
if (unlikely(prio < MAX_DL_PRIO))
return 1;
return 0;
@@ -227,7 +256,7 @@ static inline bool dl_time_before(u64 a, u64 b)
{
return (s64)(a - b) < 0;
}
```
````
#进程的优先级表示
@@ -34,6 +34,9 @@ linux优先级操作的系统调用有nice和getpriority, setpriority
##优先级的内核表示
-------
**linux优先级概述**
>在用户空间通过nice命令设置进程的静态优先级, 这在内部会调用nice系统调用, 进程的nice值在-20~+19之间. 值越低优先级越高.
>
>setpriority系统调用也可以用来设置进程的优先级. 它不仅能够修改单个线程的优先级, 还能修改进程组中所有进程的优先级, 或者通过制定UID来修改特定用户的所有进程的优先级
@@ -54,6 +57,10 @@ linux优先级操作的系统调用有nice和getpriority, setpriority
![内核的优先级标度](./images/priority.jpg)
**内核的优先级表示**
内核表示优先级的所有信息基本都放在[include/linux/sched/prio.h](http://lxr.free-electrons.com/source/include/linux/sched/prio.h?v=4.6)中, 其中定义了一些表示优先级的宏和函数,
优先级数值通过宏来定义, 如下所示,
其中MAX_NICE和MIN_NICE定义了nice的最大最小值
@@ -71,11 +78,6 @@ linux优先级操作的系统调用有nice和getpriority, setpriority
#define DEFAULT_PRIO (MAX_RT_PRIO + 20)
```
此外新版本的内核还引入了EDF实时调度算法, 它的优先级比RT进程和NORMAL/BATCH进程的优先级都要高, 因此内核将MAX_DL_PRIO设置为0, 可以参见内核文件[include/linux/sched/deadline.h](http://lxr.free-electrons.com/source/include/linux/sched/deadline.h)
```c
#define MAX_DL_PRIO 0
````
| 宏 | 值 | 描述 |
| ------------- |:-------------:|:-------------:|
@@ -89,6 +91,7 @@ linux优先级操作的系统调用有nice和getpriority, setpriority
而内核提供了一组宏将优先级在各种不同的表示形之间转移
```c
// http://lxr.free-electrons.com/source/include/linux/sched/prio.h?v=4.6#L27
/*
@@ -109,9 +112,59 @@ linux优先级操作的系统调用有nice和getpriority, setpriority
#define MAX_USER_PRIO (USER_PRIO(MAX_PRIO))
```
此外也提供了一些EDF调度算法的函数, 如下所示, 可以参见内核文件[include/linux/sched/deadline.h](http://lxr.free-electrons.com/source/include/linux/sched/deadline.h)
还有一些nice值和rlimit值之间相互转换的函数nice_to_rlimit和rlimit_to_nice, 这在nice系统调用进行检查的时候很有用, 他们定义在[include/linux/sched/prio.h, L47](http://lxr.free-electrons.com/source/include/linux/sched/prio.h#L47)中, 如下所示
```c
/*
* Convert nice value [19,-20] to rlimit style value [1,40].
*/
static inline long nice_to_rlimit(long nice)
{
return (MAX_NICE - nice + 1);
}
/*
* Convert rlimit style value [1,40] to nice value [-20, 19].
*/
static inline long rlimit_to_nice(long prio)
{
return (MAX_NICE - prio + 1);
}
```
**DEF最早截至时间优先实时调度算法的优先级描述**
此外新版本的内核还引入了EDF实时调度算法, 它的优先级比RT进程和NORMAL/BATCH进程的优先级都要高, 关于EDF的优先级的设置信息都早内核头文件[include/linux/sched/deadline.h](http://lxr.free-electrons.com/source/include/linux/sched/deadline.h?v=4.6#L10)
因此内核将MAX_DL_PRIO设置为0, 可以参见内核文件[include/linux/sched/deadline.h](http://lxr.free-electrons.com/source/include/linux/sched/deadline.h?v=4.6#L10)
```c
#define MAX_DL_PRIO 0
```
此外也提供了一些EDF优先级处理所需的函数, 如下所示, 可以参见内核文件[include/linux/sched/deadline.h](http://lxr.free-electrons.com/source/include/linux/sched/deadline.h?v=4.6#L12)
```c
static inline int dl_prio(int prio)
{
if (unlikely(prio < MAX_DL_PRIO))
return 1;
return 0;
}
static inline int dl_task(struct task_struct *p)
{
return dl_prio(p->prio);
}
static inline bool dl_time_before(u64 a, u64 b)
{
return (s64)(a - b) < 0;
}
````
##进程的优先级表示
-------
@@ -384,6 +437,24 @@ clamp_val宏定义在[include/linux/kernel.h, L757](http://lxr.free-electrons.co
##can_nice
-------
can_nice可检查有没有nice的权限, 该函数定义在[kernel/sched/core.c, #L3544](http://lxr.free-electrons.com/source/kernel/sched/core.c?v=4.6#L3544)中, 如下所示
```c
/*
* can_nice - check if a task can reduce its nice value
* @p: task
* @nice: nice value
*/
int can_nice(const struct task_struct *p, const int nice)
{
/* convert nice value [19,-20] to rlimit style value [1,40] */
int nice_rlim = nice_to_rlimit(nice);
return (nice_rlim <= task_rlimit(p, RLIMIT_NICE) ||
capable(CAP_SYS_NICE));
}
```
##security_task_setnice
-------