基础知识
思维导图
调度类和调度策略
摘自:https://zhuanlan.zhihu.com/p/554149581
Stop调度器,stop_sched_class:优先级最高的调度类,可以抢占其他所有的进程,但不能被其他进程抢占。用于执行一些特别紧急的进程。由于每个cpu只有一个stop线程(migration/N),所以就没有具体的调度策略及优先级,内核提供了一些接口可以向这些进程push work。主要用于负载均衡机制中的进程迁移、softlockup检测、cpu hotplug、RCU等。
Deadline调度器,dl_sched_class:使用红黑树,把进程按照绝对截止期限进行排序,选择最小进程进行调度运行,属于硬实时,是用于对调度时间有明确要求的进程。由于该调度类用的是进程设置的三个调度参数(运行周期、运行时间、截止时间)作为调度依据,用不到优先级,不过为了跟其他调度类有优先级划分,该类调度器的进程优先级被设为-1。用于调度有严格时间要求的实时进程,如视频编解码等。常见的调度策略是:
- SCHED_DEADLINE:限期进程调度策略,使task选择Deadline调度器来调度运行。
RT调度器,rt_sched_class:实时调度器,为每个优先级维护一个队列,属于软实时,适用于只要可运行就希望立马能运行的进程。优先级为0~99,数字越大优先级越高。实时调度类分为两个调度策略:
- SCHED_RR:时间片轮转,进程用完时间片后加入优先级对应运行队列的尾部,把CPU让给同优先级的其他进程。
- SCHED_FIFO:先进先出调度没有时间片,没有更高优先级的情况下,只能等待主动让出CPU。
- SCHED_RR:时间片轮转,进程用完时间片后加入优先级对应运行队列的尾部,把CPU让给同优先级的其他进程。
CFS调度器,cfs_sched_class,完全公平调度器,采用完全公平调度算法,引入虚拟运行时间概念。给广大普通线程使用。优先级为100~139。该调度类包含三个调度策略:
- SCHED_NORMAL:使进程选择CFS调度器来调度运行
- SCHED_BATCH:批量处理,希望减少调度次数,每次调度能执行的时间长点。
- SCHED_IDLE:优先级特别低的进程,能分到的cpu时间比例很低,但也是总能分到。
- SCHED_NORMAL:使进程选择CFS调度器来调度运行
IDLE调度器,idle_sched_class:空闲调度器,每个CPU都会有一个idle线程,当没有其他进程可以调度时,调度运行idle线程。在内核启动的时候就创建了每cpu的idle进程,属于最低优先级的进程。
在task_struct中有4个字段表示优先级:
- Rt_priority:用来记录实时进程的用户空间的静态优先级。
- Static_prio:用来记录CFS进程的用户空间的动态优先级并做了转换(nice+120),在进程启动时分配,用户可以通过nice()或sched_setscheduler()更改。
- Normal_prio:规范优先级,在创建进程时会继承父进程的normal_prio。为了将RT进程和CFS进程的优先级统一在一个数轴上,实时进程的转换:normao_prio = 99 – rt,普通进程的转换:normal_prio = static_prio。
- Prio:动态优先级,是调度类考虑的优先级,有些时候会暂替提高该优先级,比如实时互斥锁。一般等于normal_prio,对进程所有的处理都以动态优先级为准。
数据结构
摘自:https://zhuanlan.zhihu.com/p/554149581
对于每个CPU只能有一个stop和idle,因此不需要队列;
每一个CPU都会有一个per-cpu变量struct rq,每个struct rq上又会有三个不同调度类的调度队列,然后调度队列要用不同的数据结构(比如红黑树)来管理每一个进程的调度实体(sched_entity),进程的task结构体中也会有指针指向它自己的调度实体。
调度过程
摘自:https://zhuanlan.zhihu.com/p/554149581
还是经典的状态转换图:
无论是新建的进程,还是阻塞的进程,想要进入到运行队列,都是靠唤醒来实现的,只不过两种唤醒有所不同。🤔
关于调度时机,文章是这样介绍的🤔:
我们跟着看被动调度:😊
时钟中断
唤醒阻塞进程的时候
创建新进程的时候
设置进程优先级的时候
负载均衡时
这里对触发调度和执行调度做一个简单的理解,以时钟中断为例,时钟中断只是触发调度,此时检查进程的时间片有没有用完,如果没有用完是不会切换进程的🤔(只是简单的理解举例)
再理解一下唤醒:(纯个人瞎猜😂)
如果是创建新的进程,那么就顺着走,创建完了新的进程就会调用唤醒相关的函数,然后决定调度;
如果是阻塞唤醒,笔者猜想是否相应的事件会产生中断来通知内核?🤔这样就会触发调度来决定被唤醒的进程被调度到哪里?🤔
对于设置进程的优先级,会通过nice主动进入到内核,然后调用到相关调度的内核模块:
负载均衡又是什么道理呢?🤔
参考这个https://zhuanlan.zhihu.com/p/662916716
似乎负载均衡也要靠时钟中断来维持捏🤔
如何设置进程的优先级
参考这篇文章:https://docs.pingcode.com/baike/1019204
#include <stdio.h> |
参考
https://zhuanlan.zhihu.com/p/554149581