mirror of
https://github.com/gatieme/LDD-LinuxDeviceDrivers.git
synced 2026-09-25 14:53:35 +08:00
进程调度之优先级详解...
This commit is contained in:
@@ -144,6 +144,8 @@ linux把进程区分为实时进程和非实时进程, 其中非实时进程进
|
||||
| 0——99 | 实时进程 |
|
||||
| 100——139 | 非实时进程 |
|
||||
|
||||

|
||||
|
||||
|
||||
优先级数值通过宏来定义, 如下所示, 其中MAX_RT_PRIO指定了实时进程的最大优先级, 而MAX_PRIO则是普通进程的最大优先级数值
|
||||
|
||||
@@ -425,7 +427,7 @@ static int effective_prio(struct task_struct *p)
|
||||
|
||||
* 设置进程的普通优先级(实时进程99-rt_priority, 普通进程为static_priority)
|
||||
|
||||
* 计算进程的动态优先级(实时进程则维持动态优先级的prio不变, 普通进程普通优先级即为动态优先级)
|
||||
* 计算进程的动态优先级(实时进程则维持动态优先级的prio不变, 普通进程的动态优先级即为其普通优先级)
|
||||
|
||||
最后, 我们综述一下在针对不同类型进程的计算结果
|
||||
|
||||
@@ -457,47 +459,81 @@ policy == SCHED_FIFO || policy == SCHED_RR;
|
||||
|
||||
对于临时提高至实时优先级的非实时进程来说, 这个是必要的, 这种情况可能发生在是哦那个实时互斥量(RT-Mutex)时.
|
||||
|
||||
|
||||
##设置prio的时机
|
||||
-------
|
||||
|
||||
|
||||
在新进程用wake_up_new_task唤醒时, 或者使用nice系统调用改变其静态优先级时, 则会通过effective_prio的方法设置p->prio
|
||||
|
||||
|
||||
* 在新进程用wake_up_new_task唤醒时, 或者使用nice系统调用改变其静态优先级时, 则会通过effective_prio的方法设置p->prio
|
||||
|
||||
>wake_up_new_task(), 计算此进程的优先级和其他调度参数,将新的进程加入到进程调度队列并设此进程为可被调度的,以后这个进程可以被进程调度模块调度执行。
|
||||
|
||||
* 进程创建时copy_process通过调用sched_fork来初始化和设置调度器的过程中会设置子进程的优先级
|
||||
|
||||
##nice系统调用的实现
|
||||
-------
|
||||
|
||||
nice系统调用是的内核实现是sys_nice, 其定义在[kernel/sched/core.c#L7498](http://lxr.free-electrons.com/source/kernel/sched/core.c?v=4.6#L7498),
|
||||
|
||||
它在通过一系列检测后, 通过[set_user_nice函数](http://lxr.free-electrons.com/source/kernel/sched/core.c?v=4.6#L3497), 其定义在[kernel/sched/core.c#L3497](http://lxr.free-electrons.com/source/kernel/sched/core.c?v=4.6#L3497)
|
||||
|
||||
关于其具体实现我们会在另外一篇博客里面详细讲
|
||||
|
||||
|
||||
##fork时优先级的继承
|
||||
-------
|
||||
|
||||
|
||||
在进程分叉处子进程时, 子进程的静态优先级继承自父进程. 子进程的动态优先级p->prio则被设置为父进程的普通优先级, 这确保了实时互斥量引起的优先级提高不会传递到子进程.
|
||||
|
||||
可以参照sched_fork函数, 在进程复制的过程中copy_process通过调用sched_fork来设置子进程优先级, 参见[sched_fork函数](http://lxr.free-electrons.com/source/kernel/sched/core.c#L2236)
|
||||
|
||||
|
||||
```c
|
||||
/*
|
||||
* fork()/clone()-time setup:
|
||||
*/
|
||||
int sched_fork(unsigned long clone_flags, struct task_struct *p)
|
||||
{
|
||||
/* ...... */
|
||||
/*
|
||||
* Make sure we do not leak PI boosting priority to the child.
|
||||
* 子进程的动态优先级被设置为父进程普通优先级
|
||||
*/
|
||||
p->prio = current->normal_prio; /* 子进程的动态优先级被设置为父普通优先级 */
|
||||
p->prio = current->normal_prio;
|
||||
|
||||
/*
|
||||
* Revert to default priority/policy on fork if requested.
|
||||
*/
|
||||
if (unlikely(p->sched_reset_on_fork)) {
|
||||
if (task_has_dl_policy(p) || task_has_rt_policy(p)) {
|
||||
p->policy = SCHED_NORMAL;
|
||||
p->static_prio = NICE_TO_PRIO(0);
|
||||
p->rt_priority = 0;
|
||||
} else if (PRIO_TO_NICE(p->static_prio) < 0)
|
||||
p->static_prio = NICE_TO_PRIO(0);
|
||||
* sched_reset_on_fork标识用于判断是否恢复默认的优先级或调度策略
|
||||
|
||||
p->prio = p->normal_prio = __normal_prio(p);
|
||||
*/
|
||||
if (unlikely(p->sched_reset_on_fork)) /* 如果要恢复默认的调度策略, 即SCHED_NORMAL */
|
||||
{
|
||||
/* 首先是设置静态优先级static_prio
|
||||
* 由于要恢复默认的调度策略
|
||||
* 对于父进程是实时进程的情况, 静态优先级就设置为DEFAULT_PRIO
|
||||
*
|
||||
* 对于父进程是非实时进程的情况, 要保证子进程优先级不小于DEFAULT_PRIO
|
||||
* 父进程nice < 0即static_prio < 的重新设置为DEFAULT_PRIO的重新设置为DEFAULT_PRIO
|
||||
* 父进程nice > 0的时候, 则什么也没做
|
||||
* */
|
||||
if (task_has_dl_policy(p) || task_has_rt_policy(p))
|
||||
{
|
||||
p->policy = SCHED_NORMAL; /* 普通进程调度策略 */
|
||||
p->static_prio = NICE_TO_PRIO(0); /* 静态优先级为nice = 0 即DEFAULT_PRIO*/
|
||||
p->rt_priority = 0; /* 实时优先级为0 */
|
||||
}
|
||||
else if (PRIO_TO_NICE(p->static_prio) < 0) /* */
|
||||
p->static_prio = NICE_TO_PRIO(0); /* */
|
||||
|
||||
/* 接着就通过__normal_prio设置其普通优先级和动态优先级
|
||||
* 这里做了一个优化, 因为用sched_reset_on_fork标识设置恢复默认调度策略后
|
||||
* 创建的子进程是是SCHED_NORMAL的非实时进程
|
||||
* 因此就不需要绕一大圈用effective_prio设置normal_prio和prio了
|
||||
* 直接用__normal_prio设置就可 */
|
||||
p->prio = p->normal_prio = __normal_prio(p); /* 设置*/
|
||||
|
||||
/* 设置负荷权重 */
|
||||
set_load_weight(p);
|
||||
|
||||
/*
|
||||
@@ -506,8 +542,12 @@ int sched_fork(unsigned long clone_flags, struct task_struct *p)
|
||||
*/
|
||||
p->sched_reset_on_fork = 0;
|
||||
}
|
||||
}`
|
||||
``
|
||||
/* ...... */
|
||||
}
|
||||
```
|
||||
|
||||
http://blog.sina.com.cn/s/blog_9ca3f6e70102wkwp.html
|
||||
http://lxr.free-electrons.com/source/kernel/sched/core.c#L3527
|
||||
http://blog.chinaunix.net/uid-20671208-id-4909620.html
|
||||
http://blog.chinaunix.net/uid-20671208-id-4909623.html
|
||||
http://www.linuxidc.com/Linux/2016-05/131244.htm
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 8.6 KiB |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user