进程的分类在 CPU 的角度看进程行为的话 , 可以分为两类:
- CPU 消耗型:此类进程就是一直占用 CPU 计算 , CPU 利用率很高
- IO 消耗型:此类进程会涉及到 IO , 需要和用户交互 , 比如键盘输入 , 占用 CPU 不是很高 , 只需要 CPU 的一部分计算 , 大多数时间是在等待 IO
为了更快响应 IO 消耗型进程 , 内核提供了一个抢占(preempt)机制 , 使优先级更高的进程 , 去抢占优先级低的进程运行 。内核用以下宏来选择内核是否打开抢占机制:
- CONFIG_PREEMPT_NONE: 不打开抢占 , 主要是面向服务器 。此配置下 , CPU 在计算时 , 当输入键盘之后 , 因为没有抢占 , 可能需要一段时间等待键盘输入的进程才会被 CPU 调度 。
- CONFIG_PREEMPT : 打开抢占 , 一般多用于手机设备 。此配置下 , 虽然会影响吞吐率 , 但可以及时响应用户的输入操作 。
task_struct我们先把 task_struct 中和调度相关的结构拎出来:
struct task_struct { ...... const struct sched_class *sched_class; struct sched_entity se; struct sched_rt_entity rt; ...... struct sched_dl_entity dl; ...... unsigned int policy; ......}
- struct sched_class:对调度器进行抽象 , 一共分为5类 。
- Stop调度器:优先级最高的调度类 , 可以抢占其他所有进程 , 不能被其他进程抢占;
- Deadline调度器:使用红黑树 , 把进程按照绝对截止期限进行排序 , 选择最小进程进行调度运行;
- RT调度器:为每个优先级维护一个队列;
- CFS调度器:采用完全公平调度算法 , 引入虚拟运行时间概念;
- IDLE-Task调度器:每个CPU都会有一个idle线程 , 当没有其他进程可以调度时 , 调度运行idle线程;
- unsigned int policy:进程的调度策略有6种 , 用户可以调用调度器里的不同调度策略 。
- SCHED_DEADLINE:使task选择Deadline调度器来调度运行
- SCHED_RR:时间片轮转 , 进程用完时间片后加入优先级对应运行队列的尾部 , 把CPU让给同优先级的其他进程;
- SCHED_FIFO:先进先出调度没有时间片 , 没有更高优先级的情况下 , 只能等待主动让出CPU;
- SCHED_NORMAL:使task选择CFS调度器来调度运行;
- SCHED_BATCH:批量处理 , 使task选择CFS调度器来调度运行;
- SCHED_IDLE:使task以最低优先级选择CFS调度器来调度运行;
文章插图
- struct sched_entity se:采用CFS算法调度的普通非实时进程的调度实体 。
- struct sched_rt_entity rt:采用Roound-Robin或者FIFO算法调度的实时调度实体 。
- struct sched_dl_entity dl:采用EDF算法调度的实时调度实体 。
runqueue 运行队列runqueue 运行队列是本 CPU 上所有可运行进程的队列集合 。每个 CPU 都有一个运行队列 , 每个运行队列中有三个调度队列 , task 作为调度实体加入到各自的调度队列中 。
struct rq { ...... struct cfs_rq cfs; struct rt_rq rt; struct dl_rq dl; ......}
三个调度队列:- struct cfs_rq cfs:CFS调度队列
- struct rt_rq rt:RT调度队列
- struct dl_rq dl:DL调度队列
文章插图
- cfs_rq:跟踪就绪队列信息以及管理就绪态调度实体 , 并维护一棵按照虚拟时间排序的红黑树 。tasks_timeline->rb_root是红黑树的根 , tasks_timeline->rb_leftmost指向红黑树中最左边的调度实体 , 即虚拟时间最小的调度实体 。
推荐阅读
- 黑客如何搭建和使用VMware和Kali Linux使用环境?
- 彻底搞懂Java线程池的工作原理
- 电脑鼠标右键菜单管理及彻底删除方法技巧
- Kali Linux,一个你欲罢不能的东西,非专业勿入
- Linux 命令总结
- 50个应知必会的Linux常识和操作
- 详细解析Linux /etc/passwd文件
- Linux系统安全攻防技术
- Linux 怎么修改最大文件打开数量?
- Linux经典面试题:网卡接收数据后,经过几次拷贝才能到用户进程