Linux操作系统--进程调度

  1.  nice值:
    1. 取值范围是-20至19;进程创建时,默认从父进程继承该值;一般是0;
    2. nice命令:创建 给定nice值的进程;
    3. renice命令:可以动态修改正在运行的进程;
    4. 越nice的进程,越可以容忍别的进程占用更多的CPU资源;值越大,权重越低;
    5. nice值,称为静态优先级,一般不改变;
    6. 对应priority的100-139;
  2. priority值:
    1. 称为动态优先级;
    2. 范围0-140;其中0-99属于实时进程的优先级;
    3. 新的进程默认优先级: #define DEFAULT_PRIO  (MAX_RT_PRIO + NICE_WIDTH/2) 等于 120;即nice值为0对应的优先级;
  3. 实时进程的调度算法:
    1. 调度算法更加简单,调度延时更低;
    2. 要求中断的延时更小;
  4. 调度器和调度策略:
    1. 用户可以指定创建的进程使用哪种调度策略;
    2. 系统中同时运行多个调度策略;
    3. 只有当实时进程全部退出,才会运行非实时进程;
    4. O1调度:
      1. 时间片轮转,每个进程分配时间片,轮流运行;
      2. 问题:是否是每个CPU都有一个队列。还是所有的任务共享一个任务队列?
    5. CFS调度:
      1. runtime:进程的实际运行时间;
      2. nice:决定了任务的运行权重;
      3. 最小运行时间:sched_min_granularity_ns(默认0.75ms)
      4. 调度延迟:
        1. 当进程数小于8时,sysctl_sched_latency   默认为6ms;
        2. 当进程数大于8时,sysctl_sched_latency  = 进程数 * sched_min_granularity_ns;
      5. vruntime:用于给任务排序,下次调度应该选择哪个任务?即选择运行时间(vruntime)最小的进程,使用rbtree管理;
      6. rbtree:vrutntime最小的进程,位于最左侧叶子节点;里面都是ready的任务;
      7. rbtree任务插入:(任务创建、任务唤醒)
      8. rbtree任务删除:
      9. vruntime溢出风险:无符号值比较,只需要比较相对值,可以使用类似于的time_after原理来解决溢出风险,实现溢出后的大小正确比较;
      10. 如何保证任务不会来回频繁切换:
      11. 权重设计原则:nice值差1, CPU的占用差别10%左右;
      12. 每个CPU都有一个运行队列,避免进程调度时对其他CPU的干扰;(相比于O1的调度算法的优点)
      13. 负载均衡:
        1. 因为每个CPU都有一个运行队列,那么会存在负载不均衡的问题;
        2. 解决:CFS定期检查各个CPU的运行队列,并使之均衡;
        3. 线程从CPU1迁移到CPU2,vruntime需要变化:?
      14. 实际任务的运行时间:
        1. 与系统tick周期有关系,当tick周期是4ms,频率为250hz, 那么任务最少运行时间为4ms而不是sched_min_granularity_ns;
      15. 问题:
        1. 如何使用top等命令工具查看系统中的各个任务优先级和nice值?
        2. 负载均衡的周期? 多久检查一次?在哪里实现的?内核线程?

1、Linux的CFS调度器并没有直接分配时间片到进程,而是将处理器的使用比例划分给进程。在大多数操作系统中,是否将一个进程立刻投入运行完全取决于:进程优先级和是否有时间片。CFS调度器抢占时机取决于:可运行程序消耗了多少处理器使用比。

2、调度器类:每个调度器都有一个优先级,都有0个或若干个可执行进程。基础调度器会按照优先级遍历调度器类,选择一个有可执行进程的最高优先级的类,再从此类中选择可执行进程。

3、CFS调度器原理:允许每个进程允许一段时间,循环轮转,选择运行时间最少进程作为下一个进程,而不再分配时间片。CFS在所有可运行进程总数基础上计算一个进程应该运行多久。不依靠nice值来计算时间片,而是使用nice值作为可以获得处理器运行比的权重。

vruntime变量存放进程的虚拟运行时间,该运行时间经过所有可运行进程总数的标准化。

选择具有最小vruntime的任务运行。cfs_rq按照红黑树组织,vruntime的最小的进程的sched_entity被放在最左侧的叶子节点上。并且最左侧节点存放在cfs_rq中的rb_leftmost字段中。

4、调度器入口:schedule()函数:找一个调度器类,在该类的运行队列中寻找下一个可运行进程。

5、抢占:每个进程有一个need_resched标志。

用户抢占:从系统调用返回用户空间;从中断处理程序返回用户空间。

内核抢占:只要没有持有锁,内核就可以进行抢占。为支持内核抢占,加入preempt_count标志,在thread_info结构体中。

                内核抢占时机:中断返回内核时候,会检查need_resched和preempt_count标志;如果need_resched被设置,并且preempt_count=0。那么可以安全的抢占,如果preempt_count=1,表示不能抢占,内核持有锁,等内核释放锁的时候会重新将preempt_count=0,然后检查need_resched是否被设置,如果是,可以抢占。

                归纳:中断返回内核,且在返回用户空间之前;内核代码再一次具有可抢占性;内核中显示的调用schedule();内核中的任务阻塞,也会调用schedule()。

睡眠/休眠:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值