• linux 实时调度实现


    调度入口__schedule() 主要做了几件事:

    deactivate_task() -> pick_next_task() -> context_switch()

    pick_next_task 的实现中主要两个步骤: 

    1. (IN __pick_next_task)
    2. put_prev_task_balance(rq, prev, rf);
    3. for_each_class(class) {
    4. p = class->pick_next_task(rq);
    5. if (p)
    6. return p;
    7. }

    put_prev_task_balance 会从高优先级向低优先级搜索可调度的task,优先级的顺序是:

    stop > deadline > real time > fair > idle

    balance_rt 中如果 pushable_tasks 队列的最高优先级的task比当前优先级要小,且当前任务队列的load 很大了,则尝试为它们决定应该调度到哪个cpupull_rt_task()大概过程是:

    • for cpu in 调度域中的其它cpus:
      • 找到pushable_tasks的优先级比自己高的cpu2的pushable_tasks.
      •  取出那个cpu2的pushable_tasks中优先级最高的task2.2
      • 如果它比当前cpu1上task1优先级高,但没有那个cpu2上正执行的task2.1优先级高,则尝试迁移过来,执行resched_curr()     
        • 一个特殊情况是那个task不支持迁移,则为它加一个push_cpu_stop的stop级别的任务(我看的版本代码里要求添加stop任务要求cpu2 == smp_processor_id(),那按说一定不会添加成功,可能是历史原因吧)     
        • 当这个任务在那个cpu2上被调度时,会暂停cpu2正在执行的task2.1,为它找到合适的cpu去执行(有可能给到我当前的cpu1,也可能给到别人),从而给这个task2.2一个被pick的机会.

    之后执行 put_prev_task_rt,这里会更新统计信息,如果发现有 task 已经超出了队列的时间片sched_rt_runtime_exceeded),则尝试从调度域中其它的cpu瓜分时间片过来(do_balance_runtime)。如果成功的话,且这个任务还没结束,则把它放到可调度pushable_tasks队列上(enqueue_pushable_task)。如果无济于事的话,则从各层active 队列里摘除,并尝试插入到上面某个时间片充足的层级的group的active 队列中(dequeue_rt_entity),并重新调度这个实时队列(resched_curr)。

    现在假设active队列上还有其它 active 的任务,执行 pick_next_task,找出下一个active 的最高优先级任务:

    1. static struct task_struct *pick_next_task_rt(struct rq *rq)
    2. {
    3. struct task_struct *p = pick_task_rt(rq);
    4. if (p)
    5. set_next_task_rt(rq, p, true);
    6. return p;
    7. }

    pick_task_rt 会根据bitmap 找到最高优先级的队列,从中拿出第一个task,作为要执行的task。set_next_task_rt 会把这个选中的task从pushable_tasks中摘除下来,并注册一个push_rt_tasks的callback,并在active队列上任务全耗尽时通过__balance_callbacks来调度pushable_tasks中剩下的task。

    如果执行过程中有抢占或time_tick到达,则可能会把task 放回 active 队列(requeue_task_rt)。

  • 相关阅读:
    JavaEE——Java线程的几种状态
    ccd电池充电器坏了
    国庆在家没事干?教大家用Python做一个任何视频都能看的软件, 当然,只能看正经的
    Acrel-2000Z电力监控系统在重庆五桂堂历史文化商业街区的应用
    git fetch 和 git pull 的区别
    使用SSH通过FinalShell远程连接Ubuntu服务器
    Spring框架概述 --- 常用注解
    威纶通触摸屏的配方功能具体使用方法介绍(宏指令写入PLC)
    python爬虫:JavaScript 混淆、逆向技术
    Android Studio的代码笔记--关于类的注释和函数的注释,以及USER值的修改。
  • 原文地址:https://blog.csdn.net/qq_37517281/article/details/134080158