《Linux内核设计与实现》——进程调度
来源:互联网 发布:矩阵特征空间 编辑:程序博客网 时间:2024/05/09 15:36
一、多任务
1、进程调度负责决定将那个进程投入运行,何时运行以及运行多长时间。
2、最大限度地利用处理器的原则是,只要有可以执行的进程,那么就总会有进程正在执行。但是只要系统中可运行的进程的数目比处理器的个数多,就注定某一给定时刻会有一
些进程进程不能执行。
3、多任务操作系统就是能同时并发的交互执行多个进程的操作系统。
4、多任务系统可以划分为两类:非抢占式多任务和抢占式多任务。
5、在抢占式多任务模式下,由调度来决定什么时候停止一个进程的运行,以便其他进程能够得到执行的机会,这个强制的挂起动作就叫做抢占。
6、进程被抢占之前能够运行能够运行的时间是预先设置好的,而且有一个专门的名字,叫进程的时间片。时间片实际上就是分配给每个可运行进程的处理器时间段。
7、在抢占多任务模式下,除非自己主动停止运行,否则它会一直执行。进程主动挂起自己的操作称为让步。
二、Linux的进程调度
1、O(1)调度程序。
2、完全公平调度算法(CFS)
三、策略
1、策略决定调度程序在何时让什么程序运行。调度器的策略往往就决定系统的整体印象,并且,还要负责优化使用处理器时间。
2、I/O消耗型和处理器消耗型的进程
1)、进程可以被分为I/O消耗型和处理器消耗型。
2)、I/O消耗型指进程的大部分时间用来提交I/O请求或是等待I/O请求。
3)、处理器消耗型进程把时间大多用在执行代码上。除非被抢占,否则它会不停地运行。从系统响应速度考虑,调度器不应该经常让它们运行。对于处理器消耗型的进程,
调度策略往往是尽量降低它们的调度频率,而延长其运行时间。
4)、I/O消耗型和处理器消耗型划分并不是绝对的。有的进程既是I/O消耗型,也是处理器消耗型。还有些进程可以是I/O消耗型,但属于处理器消耗型活动范围。
5)、调度策略通要在两个矛盾的目标中间寻找平衡:进程响应迅速(响应时间短)和最大系统利用率(高吞吐量)。
6)、Llinux为了保证交互式应用和桌面系统的性能,所以对进程的影响做了优化,更趋向于优先调度I/O消耗型进程。
3、进程优先级
1)、对进程分级的通常做法是(其并未被Linux系统完全采用)优先级高的进程先运行,低的后运行,相同优先级的进程按轮转方式进行调度。
2)、Linux采用两种不同的优先级范围:
I、第一种是nice值,它的范围是从-20到+19,默认值为0;越大的nice意味着更低的优先级。相比搞nice值得进程,低nice值得进程可以获得更多的处理器时间。
II、第二种是实时优先级,其值是可配置的,默认情况下它的变化范围是0-99。与nice相反,越高的实时优先级数代表进程优先级越高。
III、任何实时优先级进程的优先级都高于普通的进程,也就是说实时优先级和nice优先级处于互不相交的两个范畴。
4、时间片
1)、时间片是一个数值,它表明进程在被抢占前所能持续运行的时间。
2)、Linux的CFS调度器并没有直接分配时间片到进程,它是将处理器的使用比划分给了进程。Linux中的1抢占时机取决于新的可运行程序消耗了多少处理器使用比。如果消
耗的使用比比当前进程小,则新进程立刻投入运行,抢占当前进程。否则,将推迟其运行。
5、调度策略的活动
1)、Linux操作系统对多进程的处理方法:不再给定的时间片和优先级,而是分配一个给定的处理器使用比。
四、Linux调度算法
1、Linux调度器是以模块方式提供的,这样做的目的是允许不同类型的进程可以有针对性地选择调度算法。这种模块1化的结构被称为调度器类,它允许多种不同的可动态添加
的调度算法并存,调度属于自己范畴的进程。
2、完全公平调度(CFS)是一个针对普通进程的调度类,在Linux中称为SCHED_NORMAL。
3、Unix系统中的进程调度
1)、传统Unix系统的调度过程问题
4、公平调度
1)、CFS多进程实现:允许每个进程运行一段时间、循环轮转、选择运行最少额进程作为下一个运行的进程,而不再采用分配给每个进程时间片的做法,CFS在所有可运行
进 程总数基础上计算出一个进程应该运行多久,而不是依靠nice值来计算时间片。
2)、nice值在CFS中被作为进程获得的处理器运行比权重:越高的nice值进程获得更低的处理器使用权重,这是相对默认nice值进程的进程而言的;相反,更低的nice值得进
程获得更高的处理器使用权重。
3)、每个进程都按其权重在全部可运行进程中所占比例的“时间片”来运行,为了计算准确的时间片,CFS为完美多任务中的无限小调度周期的近似值设立了一个目标。而这个
目标称作“目标延迟”,越小的调度周期将带来越好的交互性,同时也更接近完美的多任务。但是必须承受更高的切换代价和更差的系统总吞吐能力。
4)、CFS引入每个进程获得的时间片底线,这个底线称为最小粒度。默认情况下这个值是1ms。
5)、任何进程所获得的处理器时间是由它自己和其他所有可运行进程nice值得相对值决定的。nice值ui时间片的作用不再是算数加权,而是集合加权。任何nice值对应的绝对
时间不再是一个绝对值,而是处理器的使用比。
五、Linux调度的实现
1、时间记账
1)、调度器实体结构
I、CFS使用调度器实体结构来追踪进程运行记账:
struct sched_entity {
struct loa_weight load;
struct rb_node run_node;
struct list_head group_node;
unsigned int on_rq;
u64 exec_start;
u64 sum_exec_runtime;
u64 vruntime;
u64 prev_sum_exec_yuntime;
u64 last_wakeup;
u64 avg_overlap;
u64 nr_migrations;
u64 start_runtime;
u64 avg_wakeup;
};
II、调度器实体结构作为一个名为se的成员变量,嵌入在进程描述符struct task_struct内。
2、虚拟实时
1)、vruntime变量存放进程的虚拟运行时间,该运行时间的计算是经过了所有可运行总数的标准化。虚拟时间是以ns为单位的,所以vruntime和定时器节拍不再相关。
2)、CFS使用vruntime变量来记录一个程序到底运行了多长时间以及它还应该再运行多久。
3)、定义在kernel/sched_fair.c文件中的update_curr()函数实现了该记账功能。
I、update_curr()计算了当前进程的执行时间,并且将其存放在变量delta_exec中然后他又将运行时间传递给了_ _update_curr()。由后者在根据当前可运行进程总数对时间
进行加权计算。最终将上述的权重值与当前运行进程的vruntime相加。
II、update_curr()是由系统定时器周期性调用的,无论是在进程处于可运行状态,还是被堵塞处于不可运行状态。根据这种方式,vrumtime可以准确地测量给定进程的运行
时间,而且可知道谁应该是下一个被运行的进程。
3、进程选择
I、当CFS需要选择下一个运行进程时,它会挑一个具有最小vrumtime的进程。这其实就是CFS算法的核心:选择具有最小vruntime的任务。
II、CFS利用红黑树来组织可运行进程队列,并利用其迅速找到最小vruntime值得进程。
III、在Linux中,红黑树被称为rbtree,它是一个自平衡二叉搜索树。
1)、挑选下一个任务
I、CFS的进程选择算法可简单总结为“运行rbtree树中最左边叶子点所代表的那个进程”。实现这一过程的函数是_ _pick_next_entity()。(P45)
2)、向树中加入进程
I、enqueue_entity()函数实现,该函数更新运行时间和其他一些统计数据。
II、然后调用_ _enqueue_entity()进行繁重的插入操作,把数据真正插入到红黑树中。
III、平和二叉树的基本规则是,如果键值小于当前节点的键值,则需转向蜀的左分支;相反如果大于当前节点的键值,则转向右分支。
3)、从树中删除进程
I、删除工作发生在进程堵塞获知终止时:dequeue_entity()函数。
II、从树中删除进程:_ _dequeue_entity()。
4、调度器入口
1)、进程调度的主要入口点是函数schedule(),它正是内核其他部分用于调用进程调度器入口:选择哪个进程可以运行,合适将其投入运行。
2)、schedule()通常都需要和一个具体的调度类相关联,它会找到一个最高优先级的调度类——后者需要有自己的可运行队列,然后问后者谁才是下一个该运行的进程。
5、睡眠和唤醒
1)、休眠(被堵塞)的进程处于一个特殊的不可执行状态。
I、休眠有两种相关的进程状态:TASK_INTERRUPTIBLE和TASK_UNINTERRUPTIBLE。
II、处于TASK_UNINTERRUPTIBLE的进程会忽略信号,而处于TASK_INTERRUPTIBLE状态的进程如果接收到一个信号。会被提前唤醒并响应该信号。
III、两种状态的进程位于同一个等待队列,等待某些事件,不能够运行。
2)、等待队列
I、休眠通过等待队列进行处理。等待队列是由等待某些事件发生的进程组成的简单链表。
II、内核用wake_queue_head_t来代表等待队列。
III、等待队列可以通过DECLRE_WAITQUEUE()静态创建,也可以通过init_waitqueue_head()动态创建。
3)、唤醒
I、唤醒操作通过函数wake_up()进行,它会唤醒指定的等待队列上的所有进程。
II、关于休眠有一点需要注意,存在虚假的唤醒。
六、抢占和上下文切换
1、上下文切换,也就是从一个可执行进程切换到另一个可执行进程,由定义在kernel/sched.g中的context_switch()函数负责处理。
2、内核提供了一个need_resched标志来表明是否需要重新执行一次调度(表4-1)。
1)、该标志对于内核来讲是一个信息,它表示有其他进程应当被运行们要尽快调用调度程序。
2)、再返回用户空间以及中断返回的时候,内核也会检查need_resched标志。如果已经设置,内核会在继续执行之前调用调度程序。
3、用户抢占
1)、内核即将返回用户空间的时候,如果need_resched标志被设置,会导致schedule()被调用,此时就会发生用户抢占。
2)、用户抢占在以下情况时产生:
I、从系统调返回用户空间时。
II、从中断处理程序返回用户空间时。
4、内核抢占
1)、内核抢占会发生在:
I、中断处理程序正在执行,且返回内核空间之前。
II、内核代码再一次具有可抢占性的时候。
III、如果内核中的人物显式地调用schedule()。
IV、如果内核中的人物堵塞。
七、实时调度策略
1、Linux提供了两种实时调度策略:SCHED_FIFO和SCHE_RR。而普通的、非实时的调度策略是SCHED_NORMAL。
1)、SCHED_FIFO实现了一种简单的、先入先出的调度算法:它不使用时间片。处于可运行状态的SCHED_FIFO级的进程回避任何SCHED_NORMAL级的进程都先等到调
度。
2)、SCHE_RR与SCHED_FIFO大体相同,只是SCHE_RR级的进程在耗尽事先分配给它的时间后就不能在继续执行。SCHE_RR是带时间片的SCHED_FIFO——这是一种
实时轮流调度算法。
2、软实时的含义是,内核调度进程,尽量使进程在它的限定时间到来前运行,但内核不保证总能满足这些进程的要求。相反,硬实时系统保证在一定条件下,可以满足任何调
度的要求。
八、与调度相关的系统调用(P55 表4-2)
1、与调度策略和优先级相关的系统调用
2、与处理器绑定有关的系统调用
3、放弃处理器时间
- 《Linux内核设计与实现》——进程调度
- 《Linux内核设计与实现》笔记——进程调度
- 《Linux内核设计与实现》--进程调度
- 【Linux内核设计与实现】进程调度
- Linux内核设计与实现-进程管理与进程调度
- [Linux内核设计与实现]Linux进程调度
- 《Linux内核设计与实现》——第4章(进程调度)
- 《linux内核设计与实现》4进程调度
- 《linux内核设计与实现》Chapter4进程调度(笔记)
- 《Linux内核设计与实现》- 进程的调度
- 进程调度(一)--linux内核设计与实现读书笔记
- Linux内核设计与实现之进程调度
- Linux内核设计与实现 读书笔记(4)进程的调度
- [笔记]《Linux内核设计与实现》第四章进程调度
- 《Linux内核设计与实现》读书笔记(二)--进程调度
- 每日阅读3之内核设计与实现(第三版)4.5——linux调度实现之进程选择
- Linux内核设计与实现读书笔记四——进程调度(内附思维导图)
- Linux内核设计与实现读书笔记四——进程调度(内附思维导图)
- Java反射机制
- 深入理解ARM体系架构(S3C6410)---外部中断控制实例
- 第10周项目1.3 getchar()接收数据
- java hashtable 使用
- webdriver 截图公用方法
- 《Linux内核设计与实现》——进程调度
- 使用canvas画不规则图形
- 虚拟机VM添加共享磁盘
- I.MX6x工业行业最高端的开发平台
- 集合框架
- JVM垃圾回收(gc)原理
- FLAG_ACTIVITY_CLEAR_TOP FLAG_ACTIVITY_SINGLE_TOP
- MT6582 KK版本加入modem
- Generate Parentheses