Linux2.6内核进程调度系列--scheduler_tick()函数3.更新普通进程的时间片
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.更新普通进程的时间片的更多相关文章
- Linux2.6内核进程调度系列--scheduler_tick()函数2.更新实时进程的时间片
RT /** * 递减当前进程的时间片计数器,并检查是否已经用完时间片. * 由于进程的调度类型不同,函数所执行的操作也有很大差别. */ /* 如果是实时进程,就进一步根据是FIFO还是RR类型的实 ...
- Linux2.6内核进程调度系列--scheduler_tick()函数1.总体思想
参考的是ULK第三版,Linux2.6.11.12内核版本. 调度程序依靠几个函数来完成调度工作,其中最重要的第一个函数是scheduler_tick函数,主要步骤如下: /** * 维持当前最新的t ...
- Linux2.6内核--进程调度理论
从1991年Linux的第1版到后来的2.4内核系列,Linux的调度程序都相当简陋,设计近乎原始,见0.11版内核进程调度.当然它很容易理解,但是它在众多可运行进程或者多处理器的环境下都难以胜任. ...
- Linux2.6内核协议栈系列--TCP协议2.接收
1.排队机制 接收输入TCP报文时,有三个队列: ● 待处理队列 ● 预排队队列 ● 接收队列 接收队列包含了处理过的TCP数据段,也就是说,去除了全部的协议头,正准备将数据复制到用户应用程序.接收队 ...
- Linux2.6内核协议栈系列--TCP协议1.发送
在介绍tcp发送函数之前得先介绍很关键的一个结构sk_buff,在linux中,sk_buff结构代表了一个报文: 然后见发送函数源码,这里不关注硬件支持的分散-聚集: /* sendmsg系统调用在 ...
- Linux2.6内核实现的是NPTL
NPTL是一个1×1的线程模型,即一个线程对于一个操作系统的调度进程,优点是非常简单.而其他一些操作系统比如Solaris则是MxN的,M对应创建的线程数,N对应操作系统可以运行的实体.(N<M ...
- linux2.6内核compat_ioctl函数
一.内核原型(linux2.6.28-7) long (*compat_ioctl)(struct tty_struct *tty, struct file * file, ...
- Linux2.6内核--抢占
[摘要]本文首先介绍非抢占式内核(Non-Preemptive Kernel)和可抢占式内核(Preemptive Kernel)的区别.接着分析Linux下有两种抢占:用户态抢占(User Pree ...
- Linux0.11内核--进程调度分析之2.调度
[版权所有,转载请注明出处.出处:http://www.cnblogs.com/joey-hua/p/5596830.html ] 上一篇说到进程调度归根结底是调用timer_interrupt函数, ...
随机推荐
- AutoMapper(六)
返回总目录 List和数组 AutoMapper只要求元素类型的配置而不要求可能会用到的任何数组或者list类型.比如,我们有一个简单的源和目标类型: public class Source{ pub ...
- Hadoop1 Centos伪分布式部署
前言: 毕业两年了,之前的工作一直没有接触过大数据的东西,对hadoop等比较陌生,所以最近开始学习了.对于我这样第一次学的人,过程还是充满了很多疑惑和不解的,不过我采取的策略是还是先让环 ...
- iOS开发系列--通知与消息机制
概述 在多数移动应用中任何时候都只能有一个应用程序处于活跃状态,如果其他应用此刻发生了一些用户感兴趣的那么通过通知机制就可以告诉用户此时发生的事情.iOS中通知机制又叫消息机制,其包括两类:一类是本地 ...
- Entity Framework 6 Recipes 2nd Edition(9-7)译->在WCF服务中序列化代理
9-7. 在WCF服务中序列化代理 问题 从一个查询里返回一个动态代理对象,想要把它序列为一个POCO(Plain-Old CLR Objects)对象. 实现基于POCO实体对象, 在运行时,EF会 ...
- BVT & BAT (版本验证测试和版本验收测试)
BVT & BAT 版权声明:本文为博主原创文章,未经博主允许不得转载. 一.BVT: (Build Verification Test ) BVT的概念: BVT(版本验证测试)是在所有开发 ...
- 我为NET狂群福利:逆天常用的一些谷歌浏览器插件
逆天书库:http://www.cnblogs.com/dunitian/p/5734677.html 常用工具:http://www.cnblogs.com/dunitian/p/5640147.h ...
- 在SQL Server中为什么不建议使用Not In子查询
在SQL Server中,子查询可以分为相关子查询和无关子查询,对于无关子查询来说,Not In子句比较常见,但Not In潜在会带来下面两种问题: 结果不准确 查询性能低下 下面 ...
- $.extend({},defaults, options) --(初体验三)
1.$.extend({},defaults, options) 这样做的目的是为了保护包默认参数.也就是defaults里面的参数. 做法是将一个新的空对象({})做为$.extend的第一个参数, ...
- 了解HTML表单之form元素
前面的话 表单是网页与用户的交互工具,由一个<form>元素作为容器构成,封装其他任何数量的表单控件,还有其他任何<body>元素里可用的标签 表单能够包含<input& ...
- Java多线程系列--“JUC锁”04之 公平锁(二)
概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...