自己做网站能宣传自己的产品吗,上海房地产网站建设,个人律师网站模板,哪个网站做图文素材多文章目录 前言一、简介二、源码分析2.1 scheduler_tick2.2 task_tick2.3 entity_tick2.4 check_preempt_tick2.5 resched_curr 参考资料 前言
Linux内核调度器主要是主调度器和周期性调度器#xff0c;主调度器请参考#xff1a;Linux 进程调度之schdule主调度器
一、简介 … 文章目录 前言一、简介二、源码分析2.1 scheduler_tick2.2 task_tick2.3 entity_tick2.4 check_preempt_tick2.5 resched_curr 参考资料 前言
Linux内核调度器主要是主调度器和周期性调度器主调度器请参考Linux 进程调度之schdule主调度器
一、简介
每当定时器中断发生时都会调用定时器中断处理程序。每当调用定时器中断处理程序时处理程序会调用update_process_times函数将一个时钟滴答分配给当前进程。在其中会调用scheduler_tick函数。scheduler_tick函数执行和调度相关的一些操作如检查是否有进程需要调度和切换。
时钟中断是调度器的脉搏内核依靠周期性的时钟来处理器CPU的控制权。时钟中断处理程序检查当前进程的执行时间是否超额如果超额则设置重新调度标志(_TIF_NEED_RESCHED)时钟中断处理函数返回时被中断的进程如果在用户模式下运行需要检查是否有重新调度标志设置了则调用schedule()调度。
周期性调度器scheduler_tick()以固定的频率检测是否有必要进行进程调度和切换。在CFS调度类中scheduler_tick会检测一个进程执行的时间是否过长以避免过程的延时是时候让其他CFS就绪队列中的进程运行.
注意周期性调度器scheduler_tick()设置TIF_NEED_RESCHED标志来对进程进行标记需要被抢占设置该位则表明需要进行调度切换没有进行实际的抢占只是将当前进程标记为应该被抢占。而实际的切换将在抢占执行点来完成。
如果当前进程需要重新调度的条件成立这里只是会设置TIF_NEED_RESCHED标志并不会马上调用schedule()来进行调度。真正的调度时机发生在从中断/异常返回时会判断当前进程有没有被设置TIF_NEED_RESCHED如果设置则调用schedule()来进行调度。
二、源码分析
流程图如下图左边所示
2.1 scheduler_tick
// linux-4.10.1/kernel/sched/core.c/** This function gets called by the timer code, with HZ frequency.* We call it with interrupts disabled.*/
void scheduler_tick(void)
{(1)int cpu smp_processor_id();struct rq *rq cpu_rq(cpu);struct task_struct *curr rq-curr;(2)raw_spin_lock(rq-lock);update_rq_clock(rq);curr-sched_class-task_tick(rq, curr, 0);cpu_load_update_active(rq);calc_global_load_tick(rq);raw_spin_unlock(rq-lock);(3)
#ifdef CONFIG_SMPrq-idle_balance idle_cpu(cpu);trigger_load_balance(rq);
#endif}这段代码是调度器的定时器中断处理函数用于处理定时器中断事件。以下是对代码的详细说明 1 首先获取当前处理器的ID并根据ID获取对应的运行队列rq和当前正在运行的任务curr。
2 使用原子自旋锁(raw_spin_lock)锁定运行队列确保原子操作的执行。 调用update_rq_clock()函数更新运行队列的时钟。 通过curr-sched_class-task_tick()函数调用调用当前任务所属调度类的task_tick()函数执行任务级别的时钟滴答处理。 调用cpu_load_update_active()函数更新运行队列的活跃CPU负载。即就绪队列的cpu_load[]数据。 调用calc_global_load_tick()函数计算全局负载的时钟滴答。 解锁运行队列使用raw_spin_unlock。
3 如果编译选项中启用了SMP对称多处理器支持会进行一些额外的处理
将rq-idle_balance设置为idle_cpu(cpu)表示当前运行队列是否处于空闲状态。
调用trigger_load_balance()函数触发负载平衡操作。其中主要是
curr-sched_class-task_tick(rq, curr, 0);2.2 task_tick
curr-sched_class-task_tick(rq, curr, 0);// kernel/sched/fair.cconst struct sched_class fair_sched_class {.task_tick task_tick_fair,
}// kernel/sched/fair.c/** scheduler tick hitting a task of our scheduling class:*/
static void task_tick_fair(struct rq *rq, struct task_struct *curr, int queued)
{struct cfs_rq *cfs_rq;struct sched_entity *se curr-se;for_each_sched_entity(se) {cfs_rq cfs_rq_of(se);entity_tick(cfs_rq, se, queued);}if (static_branch_unlikely(sched_numa_balancing))task_tick_numa(rq, curr);
}这段代码是调度器中的公平调度类fair的任务时钟滴答处理函数。以下是对代码的详细说明 1首先定义了一个指向当前任务的调度实体sched_entity的指针se并获取与该实体相关联的CFS运行队列cfs_rq。
2使用for_each_sched_entity迭代当前任务的调度实体对每个实体执行以下操作
获取与该实体相关联的CFS运行队列cfs_rq。
调用entity_tick()函数处理该实体的时钟滴答事件。其中entity_tick函数最为重要检查该任务是否需要调度这里表明需要进行调度切换没有进行实际的抢占只是将当前进程标记为应该被抢占。而实际的切换将在抢占执行点来完成。
* 在不支持组调度条件下, 只循环一次
* 在组调度的条件下, 调度实体存在层次关系,
* 更新子调度实体的同时必须更新父调度实体#ifdef CONFIG_FAIR_GROUP_SCHED
/* Walk up scheduling entities hierarchy */
#define for_each_sched_entity(se) \for (; se; se se-parent)#else /* !CONFIG_FAIR_GROUP_SCHED */#define for_each_sched_entity(se) \for (; se; se NULL)
#endif /* CONFIG_FAIR_GROUP_SCHED */static inline struct task_struct *task_of(struct sched_entity *se)
{return container_of(se, struct task_struct, se);
}#define task_rq(p) cpu_rq(task_cpu(p))static inline struct cfs_rq *cfs_rq_of(struct sched_entity *se)
{struct task_struct *p task_of(se);struct rq *rq task_rq(p);return rq-cfs;
}3如果静态分支static_branchsched_numa_balancing为真表示启用了NUMA非统一内存访问平衡功能则调用task_tick_numa()函数处理与NUMA平衡相关的任务时钟滴答。
2.3 entity_tick
static void
entity_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr, int queued)
{/** Update run-time statistics of the current.*/(1)update_curr(cfs_rq);/** Ensure that runnable average is periodically updated.*/(2)update_load_avg(curr, UPDATE_TG);......(3)if (cfs_rq-nr_running 1)check_preempt_tick(cfs_rq, curr);
}1update_curr用来更新当前任务调度实体的 vruntime 值和更新cfs_rq就绪队列的min_vruntime成员。
2update_load_avg更新该进程调度实体的负载和CFS就绪队列的赋值。
3如果CFS运行队列中的可运行任务数大于1则调用check_preempt_tick()函数检查是否需要进行抢占即当前进程是否需要调度。
2.4 check_preempt_tick
/** Preempt the current task with a newly woken task if needed:*/
static void
check_preempt_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr)
{unsigned long ideal_runtime, delta_exec;struct sched_entity *se;s64 delta;ideal_runtime sched_slice(cfs_rq, curr);delta_exec curr-sum_exec_runtime - curr-prev_sum_exec_runtime;if (delta_exec ideal_runtime) {resched_curr(rq_of(cfs_rq));/** The current task ran long enough, ensure it doesnt get* re-elected due to buddy favours.*/clear_buddies(cfs_rq, curr);return;}/** Ensure that a task that missed wakeup preemption by a* narrow margin doesnt have to wait for a full slice.* This also mitigates buddy induced latencies under load.*/if (delta_exec sysctl_sched_min_granularity)return;se __pick_first_entity(cfs_rq);delta curr-vruntime - se-vruntime;if (delta 0)return;if (delta ideal_runtime)resched_curr(rq_of(cfs_rq));
}这段代码是调度器中的检查任务抢占的函数。以下是对代码的详细说明 1首先定义了一些变量来保存理想运行时间ideal_runtime和已执行时间的增量delta_exec。 2使用sched_slice()函数计算出当前调度实体的理想运行时间。 3计算当前调度实体的已执行时间的增量即sum_exec_runtime减去prev_sum_exec_runtime。 4如果已执行时间的增量大于理想运行时间表示当前任务运行时间超过了预期将当前任务重新调度并清除与当前任务相关的伙伴buddy任务的优先级。 5如果已执行时间的增量小于sysctl_sched_min_granularity最小调度粒度则直接返回避免任务因为执行时间过短而被抢占。 6选取CFS运行队列中的第一个调度实体并计算当前调度实体的虚拟运行时间与选取的调度实体的虚拟运行时间之间的差值delta。 7如果delta小于0表示当前调度实体的虚拟运行时间较小不进行抢占。 8如果delta大于理想运行时间表示当前调度实体的虚拟运行时间较大将当前任务重新调度。
这段代码用于检查是否需要抢占当前任务。它比较当前任务的已执行时间与理想运行时间的差异并根据一定的条件决定是否重新调度当前任务。如果当前任务的运行时间超过了预期或者与其他任务的虚拟运行时间相比较大将触发任务的重新调度。
因此抢占决策很容易做出决定, 如果检查发现当前进程运行需要被抢占, 那么通过resched_task发出重调度请求.这会在task_struct中设置TIF_NEED_RESCHED标志, 核心调度器会在下一个适当的时机发起重调度.
其实需要抢占的条件有下面两种可能性 1curr进程的实际运行时间delta_exec比期望的时间间隔ideal_runtime长 此时说明curr进程已经运行了足够长的时间
2curr进程与红黑树中最左进程left虚拟运行时间的差值大于curr的期望运行时间ideal_runtime 此时说明红黑树中最左结点left与curr节点更渴望处理器, 已经接近于饥饿状态, 这个我们可以这样理解, 相对于curr进程来说, left进程如果参与调度, 其期望运行时间应该域curr进程的期望时间ideal_runtime相差不大, 而此时如果curr-vruntime - se-vruntime curr.ideal_runtime, 我们可以初略的理解为curr进程已经优先于left进程多运行了一个周期, 而left又是红黑树总最饥渴的那个进程, 因此curr进程已经远远领先于队列中的其他进程, 此时应该补偿其他进程。
如果检查需要发生抢占, 则内核通过resched_curr(rq_of(cfs_rq))设置重调度标识, 从而触发延迟调度
2.5 resched_curr
/** resched_curr - mark rqs current task to be rescheduled now.** On UP this means the setting of the need_resched flag, on SMP it* might also involve a cross-CPU call to trigger the scheduler on* the target CPU.*/
void resched_curr(struct rq *rq)
{struct task_struct *curr rq-curr;int cpu;if (test_tsk_need_resched(curr))return;cpu cpu_of(rq);if (cpu smp_processor_id()) {set_tsk_need_resched(curr);set_preempt_need_resched();return;}
}这段代码是调度器中的重新调度当前任务的函数。以下是对代码的详细说明 1首先获取当前运行队列的当前任务指针curr。
2如果当前任务的need_resched标志已经被设置则直接返回无需进行重新设置。
3如果当前处理器ID等于当前运行队列的处理器ID即在本处理器上执行则设置当前任务的need_resched标志并设置调度器的preempt_need_resched标志表示当前任务需要重新调度。
周期性调度器并不显式进行调度, 而是采用了延迟调度的策略, 如果发现需要抢占, 周期性调度器就设置进程的重调度标识PREEMPT_NEED_RESCHED, 然后由主调度器完成调度工作.
TIF_NEED_RESCHED标识, 表明进程需要被调度, TIF前缀表明这是一个存储在进程thread_info中flag字段的一个标识信息
在内核的一些关键位置, 会检查当前进程是否设置了重调度标志TLF_NEDD_RESCHED, 如果该进程被其他进程设置了TIF_NEED_RESCHED标志, 则函数重新执行进行调度
前面我们在check_preempt_tick中如果发现curr进程已经运行了足够长的时间, 其他进程已经开始饥饿, 那么我们就需要通过resched_curr来设置重调度标识TIF_NEED_RESCHED
参考资料
https://kernel.blog.csdn.net/article/details/52068050 https://xiaolizai.blog.csdn.net/article/details/128646726 https://www.cnblogs.com/LoyenWang/p/12249106.html https://www.cnblogs.com/LoyenWang/p/12495319.html
https://scslab-intern.gitbooks.io/linux-kernel-hacking/content/chapter04.html 文章转载自: http://www.morning.yccnj.cn.gov.cn.yccnj.cn http://www.morning.fwblh.cn.gov.cn.fwblh.cn http://www.morning.mflhr.cn.gov.cn.mflhr.cn http://www.morning.zqkms.cn.gov.cn.zqkms.cn http://www.morning.gpcy.cn.gov.cn.gpcy.cn http://www.morning.yhsrp.cn.gov.cn.yhsrp.cn http://www.morning.rbkgp.cn.gov.cn.rbkgp.cn http://www.morning.qrmyd.cn.gov.cn.qrmyd.cn http://www.morning.mdpcz.cn.gov.cn.mdpcz.cn http://www.morning.qnbgk.cn.gov.cn.qnbgk.cn http://www.morning.wrysm.cn.gov.cn.wrysm.cn http://www.morning.china-cj.com.gov.cn.china-cj.com http://www.morning.lqzhj.cn.gov.cn.lqzhj.cn http://www.morning.spbp.cn.gov.cn.spbp.cn http://www.morning.yhjlg.cn.gov.cn.yhjlg.cn http://www.morning.bhxzx.cn.gov.cn.bhxzx.cn http://www.morning.qbjrf.cn.gov.cn.qbjrf.cn http://www.morning.bryyb.cn.gov.cn.bryyb.cn http://www.morning.hqjtp.cn.gov.cn.hqjtp.cn http://www.morning.srbsr.cn.gov.cn.srbsr.cn http://www.morning.btwrj.cn.gov.cn.btwrj.cn http://www.morning.tbbxn.cn.gov.cn.tbbxn.cn http://www.morning.pltbd.cn.gov.cn.pltbd.cn http://www.morning.lsmnn.cn.gov.cn.lsmnn.cn http://www.morning.rbsmm.cn.gov.cn.rbsmm.cn http://www.morning.fbmzm.cn.gov.cn.fbmzm.cn http://www.morning.clpkp.cn.gov.cn.clpkp.cn http://www.morning.qypjk.cn.gov.cn.qypjk.cn http://www.morning.rdzlh.cn.gov.cn.rdzlh.cn http://www.morning.wftrs.cn.gov.cn.wftrs.cn http://www.morning.hjjhjhj.com.gov.cn.hjjhjhj.com http://www.morning.xsklp.cn.gov.cn.xsklp.cn http://www.morning.krkwh.cn.gov.cn.krkwh.cn http://www.morning.ptwzy.cn.gov.cn.ptwzy.cn http://www.morning.caswellintl.com.gov.cn.caswellintl.com http://www.morning.pumali.com.gov.cn.pumali.com http://www.morning.lxfyn.cn.gov.cn.lxfyn.cn http://www.morning.mjctt.cn.gov.cn.mjctt.cn http://www.morning.bqdgr.cn.gov.cn.bqdgr.cn http://www.morning.wtnyg.cn.gov.cn.wtnyg.cn http://www.morning.ckctj.cn.gov.cn.ckctj.cn http://www.morning.rlbfp.cn.gov.cn.rlbfp.cn http://www.morning.mznqz.cn.gov.cn.mznqz.cn http://www.morning.rqfkh.cn.gov.cn.rqfkh.cn http://www.morning.lxqyf.cn.gov.cn.lxqyf.cn http://www.morning.jfzbk.cn.gov.cn.jfzbk.cn http://www.morning.dhqyh.cn.gov.cn.dhqyh.cn http://www.morning.fqqcd.cn.gov.cn.fqqcd.cn http://www.morning.snmth.cn.gov.cn.snmth.cn http://www.morning.fbccx.cn.gov.cn.fbccx.cn http://www.morning.fgsct.cn.gov.cn.fgsct.cn http://www.morning.trkl.cn.gov.cn.trkl.cn http://www.morning.mqxzh.cn.gov.cn.mqxzh.cn http://www.morning.kcwkt.cn.gov.cn.kcwkt.cn http://www.morning.htbbp.cn.gov.cn.htbbp.cn http://www.morning.ndmh.cn.gov.cn.ndmh.cn http://www.morning.jrgxx.cn.gov.cn.jrgxx.cn http://www.morning.bpmmq.cn.gov.cn.bpmmq.cn http://www.morning.lyzwdt.com.gov.cn.lyzwdt.com http://www.morning.zwzlf.cn.gov.cn.zwzlf.cn http://www.morning.gxtbn.cn.gov.cn.gxtbn.cn http://www.morning.huarma.com.gov.cn.huarma.com http://www.morning.nnpfz.cn.gov.cn.nnpfz.cn http://www.morning.nfpgc.cn.gov.cn.nfpgc.cn http://www.morning.gwmny.cn.gov.cn.gwmny.cn http://www.morning.srxhd.cn.gov.cn.srxhd.cn http://www.morning.pzwfw.cn.gov.cn.pzwfw.cn http://www.morning.ygpdm.cn.gov.cn.ygpdm.cn http://www.morning.fqyqm.cn.gov.cn.fqyqm.cn http://www.morning.lwtld.cn.gov.cn.lwtld.cn http://www.morning.btlmb.cn.gov.cn.btlmb.cn http://www.morning.swwpl.cn.gov.cn.swwpl.cn http://www.morning.wsgyq.cn.gov.cn.wsgyq.cn http://www.morning.knscf.cn.gov.cn.knscf.cn http://www.morning.hqgkx.cn.gov.cn.hqgkx.cn http://www.morning.gblrn.cn.gov.cn.gblrn.cn http://www.morning.drspc.cn.gov.cn.drspc.cn http://www.morning.tftw.cn.gov.cn.tftw.cn http://www.morning.lhyhx.cn.gov.cn.lhyhx.cn http://www.morning.nypgb.cn.gov.cn.nypgb.cn