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. K-Means 聚类算法

    K-Means 概念定义: K-Means 是一种基于距离的排他的聚类划分方法. 上面的 K-Means 描述中包含了几个概念: 聚类(Clustering):K-Means 是一种聚类分析(Clus ...

  2. iOS开发系列--数据存取

    概览 在iOS开发中数据存储的方式可以归纳为两类:一类是存储为文件,另一类是存储到数据库.例如前面IOS开发系列-Objective-C之Foundation框架的文章中提到归档.plist文件存储, ...

  3. Leetcode 笔记 35 - Valid Soduko

    题目链接:Valid Sudoku | LeetCode OJ Determine if a Sudoku is valid, according to: Sudoku Puzzles - The R ...

  4. ABP(现代ASP.NET样板开发框架)系列之14、ABP领域层——领域事件(Domain events)

    点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之14.ABP领域层——领域事件(Domain events) ABP是“ASP.NET Boilerplate P ...

  5. 错误: 从内部类中访问本 地变量vvv; 需要被声明为最终类型

    从github 下载了源码, 进行编译, 出现了下面的错误 E:\downloads\ff\elasticsearch-master\elasticsearch-master>GRADLE :b ...

  6. MVC中的AOP

    一. AOP是什么? AOP(Aspect-Oriented Programming),面向切面编程,看着是跟OOP(面向对象编程)挺相近的,但实际上又有什么区别呢?OOP具有封装,继承,多态等东西来 ...

  7. web标准之道——笔记

    字体设置 sans和sans-serif为通用字体,具体哪个字体被最终应用由浏览器决定,通用字体只有在其他字体都无效时才会被当作代替方案.通用字体应该放在最后面 sans衬线字体 容易阅读,一般使用在 ...

  8. Windows 批处理

    1. 引言     在Windows上,经常需要做一些重复的工作.比如在不同的工作场所需要切换不同的ip:比如有时需要对一堆文件按1~n进行重命名:再比如我们需要删除一大堆文件,这些文件名字都差不多, ...

  9. ASP.NET Core管道深度剖析(2):创建一个“迷你版”的管道来模拟真实管道请求处理流程

    从<ASP.NET Core管道深度剖析(1):采用管道处理HTTP请求>我们知道ASP.NET Core请求处理管道由一个服务器和一组有序的中间件组成,所以从总体设计来讲是非常简单的,但 ...

  10. Oracle体系结构总结

    1.Oracle 体系结构摘要图 2.Oracle 体系结构相关笔记 1.Oracle 体系结构摘要图 2.Oracle 体系结构相关笔记 可参考Oracle Architecture系列随堂笔记: ...