调度 15-17

十五: 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上 寻找任务,这样就确保了实时性的优先级要大于普通级任务。 调度 15-17       十六: - 调度, 切换运行进程, 有两种方式
    - 进程调用 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() . ● 调度 15-17  
上一篇:linux服务器死机了怎么办


下一篇:RT throttling分析【转】