schedule()函数的调用时机(周期性调度)
今天纠正了一个由来已久的认识错误:一个进程的时间片用完之后,当再次发生时钟中断时内核会调用schedule()来进行调度,把当前的进程上下文切出CPU,并把选定的下一个进程切换进来运行。我一直以为schedule()函数是在时钟中断处理函数中被调用的。其实不是,如果真是这样的话,那么在第一次这样的调度完成之后,时钟中断可能就要被mute掉了,系统从此失去“心跳”。
我之前那样理解是基于这样两点考虑:
- 在时钟中断发生时会更新进程的时间片(对于CFS调度器来说,就是更新进程的虚拟运行时间virtual run-time)。 更新完这个时间信息之后,立刻运行schedule()顺理成章,调度就应该在这个时机发生;
- 中断发生之后,(以arm架构为例)系统会从IRQ模式迅速切换成SVC模式,并且在此后的中断处理过程中,中断是关闭的,只有在切换回USR模式(其中还经过IRQ模式)时,才回再把中断打开。如果在中断处理函数中调用schedule()并不会带来中断无法再次打开的问题,因为最后总是要切换到USR模式的,那时时钟中断也总是有机会能重新打开的。
但是我没有注意到一个问题,就是ARM中断控制器(VIC)的mask/unmask操作。在进入中断响应函数之前,需要先对相应的中断设计掩码,即把正在处理的这个中断mask掉,在响应完后再把它unmask回来,好让中断能够继续发生。这段代码在kernel/irq/chip.c中(以下是经简化的示例代码):
void handle_level_irq(unsigned int irq, struct irq_desc *desc)
{
......
mask_ack_irq(desc, irq);
......
action_ret = handle_IRQ_event(irq, action);
......
unmask_irq(desc, irq);
......
}
注:中断的mask/unmask与enable/disable是两个层次的概念:enable/disable是对所有中断而言,如果disable的话任何中断都不会发生;而mask/unmask是对一个特定的中断而言的,mask之后,指定的中断不会再发生了,但并不影响其它的中断。
所以,基于这种设计,在中断响应过程中,只能更新进程的时间片,却不可以进行调度。如果一旦在上述的handle_IRQ_event()里面调用了schedule()函数,就会立刻切换到其它进程(SVC模式,内核态),接下来的unmask_irq()执行不到,时钟中断就再也没有机会打开。切换到下一个进程之后,因为没有时钟中断,系统也就失去了心跳。
正确的方法是在中断处理快要结束时调用schedule():
在中断处理的汇编代码中(arm架构下主要看__irq_usr),主要的中断处理过程都完成之后,会跑到ret_to_user处准备返回用户模式。这时就会检查进程的thread_info结构中是否置有“_TIF_NEED_RESCHED”标志,如果是的话,说明需要进行进程调度,这时再调用函数schedule()。在这个时间点上,中断控制器中相应的位已经被unmask过,接下来只要开中断即可。
上面提到的汇编代码比较零散,这里就不贴了,都在文件arch/arm/kernel/entry-armv.S和entry-common.S中。
schedule()函数的调用时机(周期性调度)的更多相关文章
- MFC浅析(7) CWnd类虚函数的调用时机、缺省实现
CWnd类虚函数的调用时机.缺省实现 FMD(http://www.fmdstudio.net) 1. Create 2. PreCreateWindow 3. PreSubclassWindow 4 ...
- CWnd类虚函数的调用时机、缺省实现
MFC(VC6.0)的CWnd及其子类中,有如下三个函数: class CWnd : public CCmdTarget{ public: virtual BOOL PreCrea ...
- Linux CFS调度器之task_tick_fair处理周期性调度器--Linux进程的管理与调度(二十九)
1. CFS如何处理周期性调度器 周期性调度器的工作由scheduler_tick函数完成(定义在kernel/sched/core.c, line 2910), 在scheduler_tick中周期 ...
- Linux核心调度器之周期性调度器scheduler_tick--Linux进程的管理与调度(十八)
我们前面提到linux有两种方法激活调度器:核心调度器和 周期调度器 一种是直接的, 比如进程打算睡眠或出于其他原因放弃CPU 另一种是通过周期性的机制, 以固定的频率运行, 不时的检测是否有必要 因 ...
- Direct3D Draw函数 异步调用原理解析
概述 在D3D10中,一个基本的渲染流程可分为以下步骤: 清理帧缓存: 执行若干次的绘制: 通过Device API创建所需Buffer: 通过Map/Unmap填充数据到Buffer中: 将Buff ...
- Spring AOP在函数接口调用性能分析及其日志处理方面的应用
面向切面编程可以实现在不修改原来代码的情况下,增加我们所需的业务处理逻辑,比如:添加日志.本文AOP实例是基于Aspect Around注解实现的,我们需要在调用API函数的时候,统计函数调用的具体信 ...
- 驱动:中断【2】中断处理程序、中断上下文中处理延时及一些函数的调用规则(调IIC中断驱动有感)
中断处理程序.中断上下文中处理延时及一些函数的调用规则(调IIC中断驱动有感)http://blog.csdn.net/samantha_sun/article/details/6790492 1,中 ...
- (copy)赋值构造函数的4种调用时机or方法
第一种调用方法: demo #include <iostream> using namespace std; class Text { public: Text() // 无参数构造函数 ...
- 周期性调度器scheduler_tick
周期性调度器由中断实现,系统定时产生一个中断,然后启动周期性调度器,周期性调度器执行过程中要关闭中断, 周期性调度器执行完毕后再打开中断(handle_IRQ_event, IRQF_DISABLE ...
随机推荐
- 十天学习PHP之第四天
学习目的:学会连接数据库 PHP简直就是一个函数库,丰富的函数使PHP的某些地方相当简单.建议大家down一本PHP的函数手冊,总用得到. 我这里就简单说一下连接MYSQL数据库. 1.mysql ...
- poj1573&&hdu1035 Robot Motion(模拟)
转载请注明出处:http://blog.csdn.net/u012860063? viewmode=contents 题目链接: HDU:pid=1035">http://acm.hd ...
- Linux的inode的理解 [转]
Linux的inode的理解 [转] 一.inode是什么? 理解inode,要从文件储存说起. 文件储存在硬盘上,硬盘的最小存储单位叫做"扇区"(Sector).每个扇区储存51 ...
- Coin Toss
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=31329#problem/G 使用二维数组f[ i ] [ j ] 表示前i 位中有j个 ...
- 在SharePoint 2013 中使用文档库Scheduling (计划公布功能)
本文讲述在SharePoint2013 中使用文档库Scheduling (计划公布功能)的步骤和注意的事项. 文档库Scheduling (计划公布功能) 用于设定当文档通过审批后特定的时间区间内才 ...
- 自定义navigationBar的高度
原来看过一些解决办法,都不太好,最近解决自定义 tab bar的高度的问题,从中受到启发,找到下面的解决办法. 个人觉得和网上找到的其它方法比还是很简洁的. 关键是要调整navBarTransitio ...
- winform窗体全屏
bool fullscreen = false;Rectangle rect = new Rectangle();private void button4_Click(object sender, E ...
- 在 Visual Studio 2010 中开发和部署 Windows Azure 应用程序
原文 在 Visual Studio 2010 中开发和部署 Windows Azure 应用程序 在 Visual Studio 2010 中开发和部署 Windows Azure 应用程序 Jim ...
- hdu4709求三角形面积
Herding Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Su ...
- hdu4722 Good Numbers
Good Numbers Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...