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()函数的调用时机(周期性调度)相关推荐
- Angular 依赖注入里factory函数的调用时机
我们调用InjectionToken构造器,创建一个新的InjectionToken实例时,除了传入一个字符串作为description,还可以指定一个options结构: const MY_SERV ...
- 关于 Angular Component ngOnDestroy 钩子函数的调用时机
我开发了一个 Angular Component,实现了 ngOnDestroy 钩子方法之后,没有找到其被调用的方法.查看这个StackOverflow链接后,得知无论是我刷新浏览器,还是从当前页面 ...
- js for循环_JS 函数的执行时机(深入理解6个6)
定时器:setTimeout() setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式 提示: 1000 毫秒= 1 秒. 提示: 如果你只想重复执行可以使用 setInterval ...
- kernel调度(2)----主调度器和周期性调度器
进程切换 上一章介绍了调度相关的基础知识,那么这章准备介绍一下进程切换相关的原理.包括主调度器和周期性调度器都做了哪些工作.以及进程切换都做了哪些工作. 周期性调度器都做了什么 我们知道周期性调度器就 ...
- 【Linux 内核】CFS 调度器 ④ ( 调度子系统组件模块 | 主调度器、周期性调度器 | 调度器类 )
文章目录 一.调度子系统组件模块 二.主调度器.周期性调度器 三.调度器类 一.调度子系统组件模块 调度器 需要对 被调度的进程 进行 排序 和 调度管理 , 进程管理过程需要 调度器 的 组件模块 ...
- Linux系统核心调度器——周期性调度器详解
日期 内核版本 架构 作者 内容 2019-5-13 Linux-2.6.32 X86 Bystander Linux进程调度 1 绪论 在<Linux系统进程调度--调度架构详细分析>一 ...
- linux cfs 参数设置,Linux CFS如何处理周期性调度器、CFS的周期性调度及总结
1. CFS如何处理周期性调度器 周期性调度器的工作由scheduler_tick函数完成(定义在kernel/sched/core.c, line 2910), 在scheduler_tick中周期 ...
- schedule函数浅析
本文主要讲了: 1.schedule函数的大体框架 2.调度的时候对prev进程都做了什么操作 3.怎么选出的next进程(O(1)算法和CFS算法) 4.CPU负载均衡在做什么 现代用户对操作系统的 ...
- schedule()函数(重点)
好了,前面的准备工作都做完了,我们就进入进程调度的主体程序--schedule()函数. 函数schedule()实现调度程序.它的任务是从运行队列的链表rq中找到一个进程,并随后将CPU分配给这个进 ...
- 哈工大李治军老师操作系统笔记【13】:一个实际的schedule函数(Learning OS Concepts By Coding Them !)
文章目录 0 回顾 1 linux0.11的schedule() 1.1 counter的作用 2 总结 0 回顾 实际的schedule是多种基本算法的融合,综合考虑各种情况,但也要求算法本身尽可能 ...
最新文章
- 搭建Ubuntu18.04+Anaconda3.x+Pycharm+SimpleITK(二)
- hibenate5.1配置mysql_hibernate5.2的基本配置方法(详解)
- vl02n 批次拆分
- 操作系统:升级Windows 11正式版的四种方法,值得收藏!
- 【剑指offer】面试题19:正则表达式匹配(Java)
- 收藏 | 从头训练深度监督目标检测
- Spring IOC学习心得之注册bean的依赖关系
- JAVA实现ATM源代码及感想
- AC日记——独木桥 洛谷 p1007
- C++ json解析
- 高速无人驾驶车辆防滑移MPC控制 学习笔记(未完结)
- Qt 中使用librdkafka librdkafka++ 创建消费者
- 输入法linux debin,Debian下安装搜狗拼音输入法
- ajax removeclass,Ajax成功后的jQuery addClass/removeClass
- 2018天津大学夏令营机试第二题
- openjudge 4978 宠物小精灵之收服
- 圆锥形怎么画_(艺考生必看)素描圆锥体怎么画?详解过程,想提高成绩的进来!...
- 微信影视小程序是如何赚钱的?效果怎么样?
- day26-多进程多线程
- 转:在Linux服务器上配置phpMyAdmin
热门文章
- java用信号量写理发师_课内资源 - 基于Java实现的生产者与消费者问题、读者写者问题、哲学家进餐问题、理发师睡觉问题、医生看病问题...
- 力扣-面试题 10.05 稀疏数组搜索
- Harmony OS — TabList和Tab分页栏
- vscode怎样打开终端 使用命令行
- Eclipse 中侧边栏、控制台、Server打不开怎么办?
- L1-035 情人节 (15 分)—团体程序设计天梯赛
- 【bug】VUE:Cannot read property '_withTask' of undefined
- 求10000以内n的阶乘(openjudge 2923)
- 创建5个组,然后把30个用户分别加入到5个组中
- 详解IOS开发应用之并发Dispatch Queues