当前位置: 首页 > news >正文

edd次元的避风港网站代理厦门做公司网站

edd次元的避风港网站代理,厦门做公司网站,商城网站建设流程图,企业网络搭建书籍Linux 是如何决定何时进行上下文切换的#xff1f; 在Linux中#xff0c;CPU 上下文切换是指当操作系统将 CPU 从一个进程切换到另一个进程时#xff0c;保存当前进程的执行状态#xff0c;并加载新进程的执行状态的过程就称为上下文切换。 但在 Linux 内核中#xff0c…Linux 是如何决定何时进行上下文切换的 在Linux中CPU 上下文切换是指当操作系统将 CPU 从一个进程切换到另一个进程时保存当前进程的执行状态并加载新进程的执行状态的过程就称为上下文切换。 但在 Linux 内核中是否切换进程通常由一个关键标志位 TIF_NEED_RESCHED 来决定。 当该标志被设置时内核会在合适的时机例如从中断返回或系统调用结束时调用schedule()从而触发上下文切换。 TIF_NEED_RESCHED标志的设置过程 刚才我们提到切换进程或任务是由TIF_NEED_RESCHED标志位来判断那这个标志位是如何设置的呢 接下来我们将从 scheduler_tick() 函数开始逐步揭示这个标志位是如何被设置并最终触发上下文切换的。 1. scheduler_tick()调度的“心跳” 让我们先从**scheduler_tick()**函数开始 说起 scheduler_tick() 是由定时器中断以 HZ 频率触发的调度驱动函数。它会获取当前 CPU 上正在运行的进程并调用该进程所属调度器的 task_tick() 方法然后根据具体对应的调度策略判断是否需要重新调度。 // kernel/sched/core.c void scheduler_tick(void) {int cpu smp_processor_id();struct rq *rq cpu_rq(cpu);struct task_struct *curr rq-curr;struct rq_flags rf;// ...rq_lock(rq, rf); // 加锁以保护运行队列// ... 省略 ...// 这是核心调用根据任务类型调用其对应的 task_tick 方法curr-sched_class-task_tick(rq, curr, 0);// ... 其他逻辑 ...rq_unlock(rq, rf); // 解锁// ... }在上述代码中最关键的一行是 curr-sched_class-task_tick(rq, curr, 0); 这行代码是调度器逻辑的入口它根据当前运行任务 (curr) 所属的调度类 (sched_class)动态地调用其特有的 task_tick 方法。对于 CFS完全公平调度器任务就会调用 task_tick_fair()从而进入具体的调度决策流程。 2. task_tick_fair()CFS 的任务周期调度 刚才提到过每种调度策略都会通过一个sched_class结构体定义其行为完全公平调度器CFS的调度类定义在**kernel/sched/fair.c** 文件中它通过 DEFINE_SCHED_CLASS(fair) 结构体被绑定到 task_tick 接口上。 /* kernel/sched/fair.c */ DEFINE_SCHED_CLASS(fair) {.enqueue_task enqueue_task_fair,.dequeue_task dequeue_task_fair,.yield_task yield_task_fair,....task_tick task_tick_fair, // 心跳函数绑定在这里....update_curr update_curr_fair, };那我们接着就看一下task_tick_fair函数 /** scheduler tick hitting a task of our scheduling class.** NOTE: This function can be called remotely by the tick offload that* goes along full dynticks. Therefore no local assumption can be made* and everything must be accessed through the rq and curr passed in* parameters.*/ 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);update_misfit_status(curr, rq);update_overutilized_status(task_rq(curr));task_tick_core(rq, curr); }首先CFS 把调度的最小单位抽象成 sched_entity它即可以是线程也可以是进程组。每个sched_entity都会对应一个 运行队列 struct cfs_rq *cfs_rq; struct sched_entity *se curr-se;接着**for_each_sched_entity循环会一直向上遍历到最顶层的调度实体**例如线程 → 进程组 → 父组并在每一层都调用 entity_tick() 函数。 for_each_sched_entity(se) {cfs_rq cfs_rq_of(se);entity_tick(cfs_rq, se, queued); }3. entity_tick() 与 update_deadline()判断是否“超时” 在 entity_tick() 函数中会调用 update_curr()该函数会负责更新当前任务的运行时间统计信息并在此过程中判断任务是否已超出其分配的时间片。 update_curr() 随后会调用 update_deadline()这里便是我们寻找的触发点。该函数会更新当前任务的运行时间并判断是否需要触发调度。我们先看一下update_deadline的具体代码 /** XXX: strictly: vd_i N*r_i/w_i such that: vd_i ve_i* this is probably good enough.*/ static void update_deadline(struct cfs_rq *cfs_rq, struct sched_entity *se) {if ((s64)(se-vruntime - se-deadline) 0)return;/** For EEVDF the virtual time slope is determined by w_i (iow.* nice) while the request time r_i is determined by* sysctl_sched_base_slice.*/se-slice sysctl_sched_base_slice;/** EEVDF: vd_i ve_i r_i / w_i*/se-deadline se-vruntime calc_delta_fair(se-slice, se);/** The task has consumed its request, reschedule.*/if (cfs_rq-nr_running 1) {resched_curr(rq_of(cfs_rq));clear_buddies(cfs_rq, se);} }当Linux中任务的虚拟运行时间超过其截止时间并且运行队列 (cfs_rq) 中有其他可运行的任务时就会认为当前任务的时间片已用完。此时就会调用 resched_curr() 从而设置TIF_NEED_RESCHED 标志位了 if (cfs_rq-nr_running 1) {resched_curr(rq_of(cfs_rq));clear_buddies(cfs_rq, se); }4. resched_curr()设置 TIF_NEED_RESCHED 标志 最后再看一下**resched_curr**的代码代码在kernel/sched/core.c中 /** 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;lockdep_assert_rq_held(rq);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;}if (set_nr_and_not_polling(curr))smp_send_reschedule(cpu);elsetrace_sched_wake_idle_without_ipi(cpu); }检查是否已标记 resched_curr函数首先会检查当前任务 (curr) 的 need_resched 标志是否已经被设置。如果已经被设置说明任务已经被标记为需要调度就直接返回避免重复操作。 if (test_tsk_need_resched(curr))return;处理当前对应CPU核心上的调度 这段代码检查 resched_curr 是否在当前 CPU 上被调用。如果是它会执行两个关键步骤 set_tsk_need_resched(curr): 显式地设置当前任务的 TIF_NEED_RESCHED 标志。set_preempt_need_resched(): 告诉抢占机制在下一个安全点例如从中断返回或系统调用结束时应该检查该标志并立即进行一次上下文切换。 if (cpu smp_processor_id()) {set_tsk_need_resched(curr); // 标记当前任务需要被调度set_preempt_need_resched(); // 触发抢占检查return; }总结need_resched 的调用链 现在我们可以清晰地梳理出 TIF_NEED_RESCHED 标志的完整设置流程 这个调用链展示了 Linux 内核如何利用一个周期性的定时器中断结合 CFS 调度器的公平性原则最终实现了抢占式多任务的调度核心。 完整代码参考 完整的源码可以在 Linux 内核源码的 kernel/sched/fair.c 和 kernel/sched/core.c 文件中找到这些函数的完整实现。 linux/kernel/sched/fair.c at master · torvalds/linux · GitHublinux/kernel/sched/core.c at master · torvalds/linux · GitHub
http://www.zqtcl.cn/news/67094/

相关文章:

  • 自己做的网站外网访问18款禁用网站app全部
  • 中国会议营销网站成都做公司网站推广
  • 网站的网页建设知识ppt国外网站如何备案
  • 手机网站费用新闻专业为啥学网页制作
  • 企业网站建设原则是惠州seo排名收费
  • 手机网站你了解的电子商务平台经营者的特点体现在
  • 有好看图片的软件网站模板下载android搭建wordpress
  • 公司网站开发策略和基本步骤拌合站建站方案
  • 平面设计手绘网站网站设计的灵感来源
  • 厚街镇网站建设榆次住房保障和城乡建设局网站
  • 学校做网站有些什么好处服务外包有哪些
  • 制作网站的公司注册资本要多少深圳市官网网站建设报价
  • 网站建设平台开发集团门户网站建设公司
  • 深圳龙华汽车网站建设企业网站的页面特点
  • 做图像网站学做电商网站
  • 杭州网站制作哪家好wordpress主题集成插件下载
  • 网站建设协调机制作文网入口
  • 南宁网站建设哪家公司实力强wordpress推荐形式模版
  • 做外贸免费的网站有哪些网站如何绑定域名
  • 属于网站的管理 更新 维护wordpress个人支付插件
  • 校园图书馆网站建设官方网站建设 磐石网络知名
  • 域名建网站福州网站建设要找嘉艺网络
  • 毕业设计可以做哪些简单网站智能建站免费
  • 郑州网站建设兼职一个公司可以做两个网站吗
  • 宜春网站建设哪家专业怎么申请商标品牌
  • 网站建站公司多少钱专业网站建设电话
  • 哪些网站可以做签约设计师大理州建设局网站门户网
  • 长沙做网站seo优化外包wordpress采集文章发布
  • 佛山小企业网站建设盐城代运营
  • 佛山电商网站制作施工企业物资管理制度百度