调度 15-17

淺唱寂寞╮ 提交于 2019-12-23 20:31:51
十五:
Linux的进程:
1)实时进程;
2)普通进程;
1.task_struct内成员变量:
1)调度策略
#define SCHED_NORMAL 0
#define SCHED_FIFO 1
#define SCHED_RR 2
#define SCHED_BATCH 3
#define SCHED_IDLE 5
#define SCHED_DEADLINE 6
2)优先级
int prio, static_prio, normal_prio;
unsigned int rt_priority;
说明:实时进程:1-99;普通进程100-139;数值越低级别越高
3)调度策略;
-- 实时进程: SCHED_FIFO(先到先得), SCHED_RR(轮询), SCHED_DEADLINE(交付任务最近的最优先)
--普通进程: SCHED_NORMAL, SCHED_BATCH, SCHED_IDLE
4)执行等级(Class)
即 sched_classs,分5类class
2. 普通进程的CFS算法(common Fair scheduling)
Fair_sched_class: Tick;vruntime;
3.调度队列和调度实体(红黑树);
 
- 实时调度实体 sched_rt_entity,Deadline调度实体sched_dl_entity,以及完全公平算法sched_entity
- 每个调度策略都同样有自己数据结构进行排序,目的区分运行的先后次序;
- 次序,红黑树左边vruntime 最小的作为处理任务,查收次序:先优先进程,在普通进程
4.运行场景如下:
每个CPU都有一个队列rq,这个队列内有多个子队列,
如rt_rq和cfs_rq,不同的队列有不同的实现方式,
其中cfs_rq就是红黑树来实现。
执行任务的逻辑: rt_sched_class先被调用,在rt_rq上寻找任务,
当没有任务时,会在fair_sched_class上找,也就是在cfs_rq上
寻找任务,这样就确保了实时性的优先级要大于普通级任务。
 
 
 
十六:
- 调度, 切换运行进程, 有两种方式
    - 进程调用 sleep 或等待 I/O, 主动让出 CPU
    - 进程运行一段时间, 被动让出 CPU
- 主动让出 CPU 的方式, 调用 schedule(), schedule() 调用 __schedule()
    - __schedule() 取出 rq; 取出当前运行进程的 task_struct
    - 调用 pick_next_task 取下一个进程
        - 依次调用调度类(优化: 大部分都是普通进程), 因此大多数情况调用 fair_sched_class.pick_next_task[_fair]
        - pick_next_task_fair 先取出 cfs_rq 队列, 取出当前运行进程调度实体, 更新 vruntime
        - pick_next_entity 取最左节点, 并得到 task_struct, 若与当前进程不一样, 则更新红黑树 cfs_rq
    - 进程上下文切换: 切换进程内存空间, 切换寄存器和 CPU 上下文(运行 context_switch)
        - context_switch() -> switch_to() -> __switch_to_asm(切换[内核]栈顶指针) -> __switch_to()
        - __switch_to() 取出 Per CPU 的 tss(任务状态段) 结构体
        - > x86 提供以硬件方式切换进程的模式, 为每个进程在内存中维护一个 tss, tss 有所有寄存器, 同时 TR(任务寄存器)指向某个 tss, 更改 TR 会触发换出 tss(旧进程)和换入 tss(新进程), 但切换进程没必要换所有寄存器
        - 因此 Linux 中每个 CPU 关联一个 tss, 同时 TR 不变, Linux 中参与进程切换主要是栈顶寄存器
        - task_struct 的 thread 结构体保留切换时需要修改的寄存器, 切换时将新进程 thread 写入 CPU tss 中
        - 具体各类指针保存位置和时刻
            - 用户栈, 切换进程内存空间时切换
            - 用户栈顶指针, 内核栈 pt_regs 中弹出
            - 用户指令指针, 从内核栈 pt_regs 中弹出
            - 内核栈, 由切换的 task_struct 中的 stack 指针指向
            - 内核栈顶指针, __switch_to_asm 函数切换(保存在 thread 中)
 
 
十七:
1.抢占式调度
①Schedule_tick函数
逻辑是:schedule_tick取出cpu的当前运行队列,得到task_struct。如果当前是普通进程,Class: fair_sched_class, 函数:task_tick_fair
根据当前task_struct, 调度队列,调用entity_tick
②唤醒调度
Try_to_wake_up()唤醒进程,调用ttwwu_queu将被唤醒的进程添加到队列,在通过ttwu_do_actiate激活。
③抢占时机
①用户态时机。 发生在:从系统调用中返回的那一刻。
②内核态时机。 抢占取决于preempt_enable()。实际操作中,进程先调用preempt_diskable()
.

 
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!