RT

	/**
* 运行到此,说明进程是普通进程。现在开始更新普通进程的时间片。
*/
/* 首先递减普通进程的时间片计数器。如果用完,继续执行以下操作 */
if (!--p->time_slice) {
/**
* 既然用完了,就将当前进程从活动集合中摘除。
*/
dequeue_task(p, rq->active);
/**
* 当然,当前进程既然已经过期,就必须设置重新调度标志,
* 以便在中断返回前调用schedule选择另外一个进程来运行。
*/
set_tsk_need_resched(p);
/**
* 更新当前进程的动态优先级。
* effective_prio根据当前进程的static_prio和sleep_avg字段,
* 计算进程的动态优先级。
*/
p->prio = effective_prio(p);
/**
* 重填进程的时间片
*/
p->time_slice = task_timeslice(p);
/**
* 既然当前进程的一个时间片已经用完,
* 当然就需要清除first_time_slice标志了。
*/
p->first_time_slice = 0; /**
* 如果本地运行队列的expired_timestamp为0,表示过期进程集合为空。
* 并且当前进程马上就会变成过期进程,
* 那么将当前jiffies赋给expired_timestamp
* expired_timestamp表示当前队列中,过期队列中
* 最老进程被插入过期队列的时间。
*/
if (!rq->expired_timestamp)
rq->expired_timestamp = jiffies;
/**
* 把当前进程插入过期进程集合或者活动进程集合。
* TASK_INTERACTIVE判断当前进程是否是一个交互式进程。
* TASK_INTERACTIVE宏检查运行队列中的第一个过期进程
* 的等待时间是否已经超过1000个时钟节拍乘以运行队列
* 中的可运行进程数+1,如果是返回1.
* EXPIRED_STARVING表示如果当前进程的静态优先级大于
* 过期进程的静态优先级,也返回1.
*/
if (!TASK_INTERACTIVE(p) || EXPIRED_STARVING(rq)) {
/**
* 当前进程不是交互式进程,或者过期队列中有优先级
* 更高的进程,那么将当前进程插入到过期队列。
*/
enqueue_task(p, rq->expired);
/**
* 如果当前进程是过期队列中优先级最高的低,
* 就更新过期队列的最高优先级。
*/
if (p->static_prio < rq->best_expired_prio)
rq->best_expired_prio = p->static_prio;
} else
/* 进程是交互式进程,并且比过期队列中所有进程的静态优先级高,
* 那么就将它加到活动队列中。这实际上是对交互式进程的优待。 */
enqueue_task(p, rq->active);
}
else {/* 普通进程的时间片还没有用完,需要进一步检查是否时间片太长 */ /**
* 检查当前进程的时间片是否太长,因为对于交互式进程来说,
* 它时间片用完后,可能会再插入到活动队列,可能导致这种
* 进程的时间片特别长。
*/
if (TASK_INTERACTIVE(p) && !((task_timeslice(p) -
p->time_slice) % TIMESLICE_GRANULARITY(p)) &&
(p->time_slice >= TIMESLICE_GRANULARITY(p)) &&
(p->array == rq->active)) { requeue_task(p, rq->active);
set_tsk_need_resched(p);
}
}

1.effective_prio函数计算进程的动态优先级。

普通进程除了静态优先级,还有动态优先级,其值的范围是100(最高优先级)~139(最低优先级)。动态优先级是调度程序在选择新进程来运行的时候使用的数。它与静态优先级的关系用下面的经验公式表示:

bonus是范围从0-10的值,值小于5表示降低动态优先级以示惩罚,值大于5表示增加动态优先级以示奖赏。bonus的值依赖于进程过去的情况,说得更准确一些,是与进程的平均睡眠时间相关。

#define CURRENT_BONUS(p) \
(NS_TO_JIFFIES((p)->sleep_avg) * MAX_BONUS / \
MAX_SLEEP_AVG) /**
* 读取current的static_prio和sleep_avg字段,并根据公司计算进程的动态优先级。
*/
static int effective_prio(task_t *p)
{
int bonus, prio; if (rt_task(p))
return p->prio; bonus = CURRENT_BONUS(p) - MAX_BONUS / 2; prio = p->static_prio - bonus;
if (prio < MAX_RT_PRIO)
prio = MAX_RT_PRIO;
if (prio > MAX_PRIO-1)
prio = MAX_PRIO-1;
return prio;
}

2.TASK_INTERACTIVE宏判断进程是不是一个交互式进程。

粗略地讲,平均睡眠时间是进程在睡眠状态所消耗的平均纳秒数。注意,这绝对不是对过去时间的求平均值的操作。例如,在TASK_INTERRUPTIBLE状态与在TASK_UNINTERRUPTIBLE状态所计算出的平均睡眠时间是不同的。而且,进程在运行的过程中平均睡眠时间递减。最后,平均睡眠时间永远不会大于1s。

平均睡眠时间也被调度程序用来确定一个给定进程是交互式进程还是批处理进程。更明确地说,如果一个进程满足下面的公式,就被看作是交互式进程:

它相当于下面的公式:

#define DELTA(p) \
(SCALE(TASK_NICE(p), 40, MAX_BONUS) + INTERACTIVE_DELTA) #define TASK_INTERACTIVE(p) \
((p)->prio <= (p)->static_prio - DELTA(p))

Linux2.6内核进程调度系列--scheduler_tick()函数3.更新普通进程的时间片的更多相关文章

  1. Linux2.6内核进程调度系列--scheduler_tick()函数2.更新实时进程的时间片

    RT /** * 递减当前进程的时间片计数器,并检查是否已经用完时间片. * 由于进程的调度类型不同,函数所执行的操作也有很大差别. */ /* 如果是实时进程,就进一步根据是FIFO还是RR类型的实 ...

  2. Linux2.6内核进程调度系列--scheduler_tick()函数1.总体思想

    参考的是ULK第三版,Linux2.6.11.12内核版本. 调度程序依靠几个函数来完成调度工作,其中最重要的第一个函数是scheduler_tick函数,主要步骤如下: /** * 维持当前最新的t ...

  3. Linux2.6内核--进程调度理论

    从1991年Linux的第1版到后来的2.4内核系列,Linux的调度程序都相当简陋,设计近乎原始,见0.11版内核进程调度.当然它很容易理解,但是它在众多可运行进程或者多处理器的环境下都难以胜任. ...

  4. Linux2.6内核协议栈系列--TCP协议2.接收

    1.排队机制 接收输入TCP报文时,有三个队列: ● 待处理队列 ● 预排队队列 ● 接收队列 接收队列包含了处理过的TCP数据段,也就是说,去除了全部的协议头,正准备将数据复制到用户应用程序.接收队 ...

  5. Linux2.6内核协议栈系列--TCP协议1.发送

    在介绍tcp发送函数之前得先介绍很关键的一个结构sk_buff,在linux中,sk_buff结构代表了一个报文: 然后见发送函数源码,这里不关注硬件支持的分散-聚集: /* sendmsg系统调用在 ...

  6. Linux2.6内核实现的是NPTL

    NPTL是一个1×1的线程模型,即一个线程对于一个操作系统的调度进程,优点是非常简单.而其他一些操作系统比如Solaris则是MxN的,M对应创建的线程数,N对应操作系统可以运行的实体.(N<M ...

  7. linux2.6内核compat_ioctl函数

    一.内核原型(linux2.6.28-7) long (*compat_ioctl)(struct tty_struct *tty, struct file * file,               ...

  8. Linux2.6内核--抢占

    [摘要]本文首先介绍非抢占式内核(Non-Preemptive Kernel)和可抢占式内核(Preemptive Kernel)的区别.接着分析Linux下有两种抢占:用户态抢占(User Pree ...

  9. Linux0.11内核--进程调度分析之2.调度

    [版权所有,转载请注明出处.出处:http://www.cnblogs.com/joey-hua/p/5596830.html ] 上一篇说到进程调度归根结底是调用timer_interrupt函数, ...

随机推荐

  1. Jquery EasyUI 开发实录

    有好几年没有用过EasyUI了,最近在外包做的一个项目中新增功能时,又用到了,本以为和按照以前那样用就可以了,可当我真正用的时候,发现许多地方不一样了,就连官网的文档都更新了,最突出的就是不知道什么时 ...

  2. js中几种实用的跨域方法原理详解(转)

    今天研究js跨域问题的时候发现一篇好博,非常详细地讲解了js几种跨域方法的原理,特分享一下. 原博地址:http://www.cnblogs.com/2050/p/3191744.html 下面正文开 ...

  3. CSS3 滤镜

    了解摄影活着美图秀秀之类美图软件的同学对滤镜肯定不陌生,CSS3对各种滤镜效果有了支持,可以做出很多好玩儿效果,走马观花了解一下 语法 filter: function(param); 很很多CSS3 ...

  4. ABP教程-给项目添加SwaggerUI,生成动态webapi

    上一篇,我们是正式将ABP生成的代码项目,跑起来了,然后演示了下多租户的不同.那么这篇我们就来实现下SwaggerUI. Q:SwaggerUI是干什么的呢? A:他是一个能将我们的webapi,通过 ...

  5. ABP框架 - 模块系统

    文档目录 本节内容: 简介 模块定义 生命周期方法 PreInitialize(预初始化) Initialize(初始化) PostInitialize(提交初始化) Shutdown(关闭) 模块依 ...

  6. Failed to stop iptables.service: Unit iptables.service not loaded.

    redhat 7 [root@lk0 ~]# service iptables stop Redirecting to /bin/systemctl stop iptables.service Fai ...

  7. Git(进击学习:远程仓库操作)-V3.0

    1.查看当前的远程仓库:git remote或git remote -v 2.添加远程仓库:git remote add [shortname] [url] git remote add pb git ...

  8. 生成任意长度的随机数 JS

    1.Math.random().toString(36).substr(2); 结果:ywv6cnpkliahj4tep0 2.   1 2 3 4 5 6 7 8 9 10 11 12 13 14 ...

  9. 【解决方案】 org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userHandler': Injection of resource dependencies failed;

    一个错误会浪费好多青春绳命 鉴于此,为了不让大家也走弯路,分享解决方案. [错误代码提示] StandardWrapper.Throwableorg.springframework.beans.fac ...

  10. xdebug断点调试原理

    通过Xdebug进行远程调试时,PHPSTORM等IDE会监听Xdebug设置的调试ip和端口(php.ini中配置) [xdebug] ; Xdebug zend_extension=php_xde ...