第4章 进程调度
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第4章 进程调度相关的知识,希望对你有一定的参考价值。
参考技术A 调度程序负责决定将哪个进程投入运行,何时运行以及运行多长时间。进程调度程序可看作在可运行态进程之间分配有限的处理器时间资源的内核子系统,是像Linux这样的多任务操作系统的基础。多任务操作系统就是能同时并发地交互执行多个进程的操作系统。可以分为两类:
进程可以分为I/O消耗型和处理器消耗型(进程可以同时展示这两种行为)。
调度策略通常要在两个矛盾的目标中寻找平衡:进程响应迅速和最大系统利用率。Linux为了保证交互式应用和桌面系统的性能,对进程的响应做了优化(缩短响应时间),更倾向于优先调度I/O消耗型进程。
Linux采用了两种不同的优先级范围:
实时优先级和nice值处于互不相交的两个范畴,任何实时进程的优先级都高于普通进程。
时间片是一个数值,它表明进程在被抢占前所能持续运行的时间。
Linux自2.6内核系统开始引入新的进程调度算法,其中最著名的是“反转楼梯最后期限调度算法(rotating staircase deadline scheduler,RSDL)”,被称为“完成公平调度算法(CFS)”。
Linux的CFS调度器并没有直接分配时间片到进程,而是将处理器的使用比例划分给进程,也就是说,进程所获得的处理器时间和系统负载密切相关的。当一个进程进入可运行状态,他就被准许投入运行。Linux的CFS调度器,其抢占时机取决于新的可运行进程消耗了多少处理器使用比。如果消耗的使用比例比当前进程小,则新的进程立刻投入运行,抢占当前进程,否则推迟运行。
Linux调度器是以模块方式提供的,以允许不同类型的进程可以有针对性地选择调度算法。这种模块化结构被称为调度器类,它允许多种不同的可动态添加的调度算法并存,调度属于自己范畴的进程。每个调度器都有一个优先级,基础调度器会按照优先级顺序进程遍历调度类,拥有一个可执行进程的最高优先级的调度类胜出,去选择接下来要执行的程序。
CFS允许每个进程运行一段时间、循环轮转、选择运行最少的进程作为下一个运行的进程。nice值作为进程获得的处理器运行比的权重,nice值越低权重越高。每个进程都按照其权重在全部可行进程中所占比例的“时间片”来运行,任何进程所获的处理器时间是由它自己和其他所有可运行进程nice值的相对差值决定的。为了计算准确的时间片,CFS为完美多任务中的无限小调度周期的近似值设立了一个目标,称为目标延迟。
CFS调度算法的实现,主要关注:
所有的调度器都必须对进程运行时间做记账。CFS通过时间记账确保每个进程只在公平分配给它的处理器时间内运行。
CFS使用调度器实体结构来追踪进程运行记账,该结构为进程描述符(struct task_struct的成员变量):
vruntime变量存放进程的虚拟运行时间,经过了所有可运行进程总数的标准化(被加权的)。以ns为单位,和定时器节拍不相关。CFS使用vruntime来记录一个程序到底运行了多长时间以及它还应该再运行多久。
update_curr()函数实现了记账功能。是由系统定时器周期性调用的,无论进程处于可运行态,还是不可运行态。因此,vruntime可以准确地测量给定进程的运行时间,而且知道谁是应该被下一个运行的进程。
CFS算法的核心:选择具有最小的vruntime任务。
CFS使用红黑树(rbtree)来组织可运行进程队列,其节点的键值为可运行进程的虚拟运行时间vruntime,有利于迅速找到最小vruntime的进程(可通过__pick_next_entity()函数来访问红黑树最左的叶子即可,当然最左的叶子可能被缓存在rb_left_most字段中,可直接读取)。
另外,可通过enqueue_entity/dequeue_entity函数从红黑树中增加/删除进程。这两个函数都会调用update_curr()函数来更新所处理任务的运行时统计数据。
进程调度的主要入口点是schedule()函数,是内核其他部分用于调用进程调度器的入口:选择哪个进程运行,何时将其投入运行。schedule()函数会通过pick_next_task()函数遍历调度类,找出优先级最高的调度类(struct sched_class),再通过调度类的pick_next_entity()函数(会调用__pick_next_entity()函数)来选择要执行的进程。
休眠(被阻塞)的进程处于不可运行的状态。内核对其操作是:进程把自己标记称休眠状态,从可执行红黑树中删除,放入等待队列,然后调用schedule()选择和执行下一个进程。
唤醒:进程被设置为可执行状态,然后从等待队列中移到可执行红黑树中。
其中,等待队列是由等待某些事件发生的进程组成的简单链表。
上下文切换,也就是从一个可执行进程切换到另一个可执行进程,由context_switch函数处理。
用户抢占:
Linux完整地支持内核抢占,只要重新调度是安全的,内核就可以在任何时间抢占正在执行的任务。只要没有持有锁,内核就可以进行抢占。内核抢占主要发生在:
普通的、非实时的调度策略是SCHED_NORMAL。
Linux提供两种实时调度策略:
Linux为实时调度策略提供一种软实时工作方式。也就是内核调度进程,尽力使进程在它的限定时间内运行,但内核不保证总能满足这些进程的要求。
对应的,硬实时系统保证在一定条件下,可以满足任何调度的要求。
七、与调度相关的系统调用
《现代操作系统》——第1章 操作系统概念
- 操作系统的五大基本功能:
- 进程/线程管理(CPU管理):进程/线程状态、控制、同步互斥、通信、调度...
- 存储管理:分配回收、地址转换、存储保护、地址扩充...
- 文件管理:文件目录、文件操作、磁盘空间、文件存取控制...
- 设备管理:设备驱动、分配回收、缓冲技术...
- 用户接口:系统命令、缓冲接口...
- 操作系统的主要特征:
- 并发:指处理多个同时性活动的能力。与并行的区别:并发是在单CPU上多个活动的同时进行,在宏观上是并行,微观上是串行;而并行指的是真正的多个同时性活动并列执行
- 共享:与用户共享有限的系统资源,提供资源管理的功能,包括资源的互斥共享、资源管理策略等
- 虚拟:即抽象,抛开对硬件等底层的概念,抽象出面向应用的顶层概念(个人理解)
- 随机:对不可预测的随机事件进行相应和处理
- 操作系统分类:
- 批处理操作系统
- 分时操作系统
- 实时操作系统
- 个人计算机操作系统
- 网络操作系统
- 分布式操作系统
- 嵌入式操作系统
以上是关于第4章 进程调度的主要内容,如果未能解决你的问题,请参考以下文章
[架构之路-39]:目标系统 - 系统软件 - Linux OS内核进程/线程调度的基本原理