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. maven常见异常以及解决方法

    本文写的是我在整合ssm框架时遇到的一些问题,我估计很多人也会遇到,所以,这里作为一个总结,希望能够帮助大家解决问题 一,加入shiro组件时抛出的异常 加入步骤(略) 问题 1,保存后,无法导入sh ...

  2. 开源一个WEB版本GEF,基于SVG的网页流程图框架

    8月开始断断续续的制作这个web gef,没有任何依赖,完全原生js开发,目前已经完成了雏形,基本上可以在项目里应用了. 下图展示的是demo1的效果,包括拖拽,生成连线,点击生成\取消墙体,整个de ...

  3. Netty构建分布式消息队列(AvatarMQ)设计指南之架构篇

    目前业界流行的分布式消息队列系统(或者可以叫做消息中间件)种类繁多,比如,基于Erlang的RabbitMQ.基于Java的ActiveMQ/Apache Kafka.基于C/C++的ZeroMQ等等 ...

  4. 对CSS中的Position、Float属性的一些深入探讨

    对CSS中的Position.Float属性的一些深入探讨 对于Position.Float我们在平时使用上可以说是使用频率非常高的两个CSS属性,对于这两个属性的使用上面可能大多数人存在一些模糊与不 ...

  5. 应用Grunt自动化地优化你的项目前端

    在不久前我曾写了一篇 应用r.js来优化你的前端 的文章,为大家介绍了r.js这个实用工具,它可以很好地压缩.合并前端文件并打包整个项目.但是如果将r.js放到项目中,我们不得不顾及到一个问题——项目 ...

  6. 惊心动魄的一上午,感谢eclipse 的文件恢复功能

    昨晚倒腾了半天android 的程序,夜里三点多了,不争气的笔记本由于太热,突然熄火.话说就在昨天还在想着一定要把东西放到svn上,防止文档找不到或者笔记本丢失带来的严重后果.呵呵,就是这么想着,今天 ...

  7. 用C表达面向对象语言的机制——C#版

    PS:本文PDF版在这里(格式更好看一些).最新的源代码请在本页面文末下载,PDF中的链接不是最新的. 用C表达面向对象语言的机制——C#版 我一直认为,面向对象语言是对面向过程语言的封装.如果是这样 ...

  8. Gulp探究折腾之路(I)

    前言: gulp是前端开发过程中对代码进行构建的工具,是自动化项目的构建利器:她不仅能对网站资源进行优化,而且在开发过程中很多重复的任务能够使用正确的工具自动完成:使用她,我们不仅可以很愉快的编写代码 ...

  9. Atitit rss没落以及替代品在线阅读器

    Atitit rss没落以及替代品在线阅读器 1.1. 对RSS的疯狂追逐,在2005年达到了一个高峰.1 1.2. Rss的问题,支持支rss,不支持url1 1.3. ,博客受到社交网络的冲击.s ...

  10. Android-AndroidStudio-添加依赖

    Android Studio 添加依赖,没有 Eclipse 那么简单, EC 只需要把 jar 复制到 libs 下,然后添加进去,不行就再项目的属性那里勾选一下,就可以了. Android 提供以 ...