
Linux 进程调度深度解析task_struct 档案与 sched_entity 简历如何协作【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux在 Linux 内核源码树GitHub_Trending/li/linux中进程调度由一对核心结构体驱动task_struct是内核给每个进程建的完整档案sched_entity是调度器真正翻阅的简历。读完这篇你能说清一个进程凭什么比另一个先拿到 CPU并会用一条命令直接读出它的虚拟运行时间。先看你手上能看到什么 不必读内核源码用户态就有现成的观察口。进程调度的全部决策最终都会落在这两个结构体里而/proc把它们的一部分投影了出来。一条命令读出进程的调度数据cat /proc/1/sched这条命令输出进程 1 的调度字段其中se.vruntime是虚拟运行时间se.sum_exec_runtime是累计实际运行时间prio是静态优先级。换个 PID 就能看到任意进程当前的简历数字这是理解 CFS 调度器最直接的入口。同一目录下还有/proc/1/schedstat记录这个进程在三个状态上的累计耗时适合做性能对比想看调度器内部队列可以看/proc/sched_debug它由 kernel/sched/debug.c 提供。进程状态调度器只关心能不能跑task_struct的第一个关键字段是__state见 include/linux/sched.h它标记进程此刻处于哪种状态。内核用三个宏区分TASK_RUNNING可运行、TASK_INTERRUPTIBLE可中断睡眠、TASK_UNINTERRUPTIBLE不可中断睡眠。调度器每一轮只从TASK_RUNNING的进程里挑人睡着的进程不进候选队列所以能不能跑是比跑得多久更前置的判断。内核里的一对搭档task_struct 与 sched_entity一句话结论task_struct存进程的全部信息sched_entity是从中抽出的、只服务调度的那一小部分两者是档案和简历的关系。档案 task_struct调度关键字段都在里面task_struct定义在 include/linux/sched.h是内核最大的结构体之一。除了__state、prio这类状态字段它还在成员区里直接内嵌了三个调度实体struct sched_entity se; /* 普通进程用 */ struct sched_rt_entity rt; /* 实时进程用 */ struct sched_dl_entity dl; /* 截止时间进程用 */注意se不是指针而是直接嵌在task_struct里的成员。每个普通进程都自带一份se进程从出生到结束一直复用这正是档案的一部分而非临时分配。简历 sched_entity只保留调度要用的几个数sched_entity同样定义在 include/linux/sched.h字段少而精字段含义白话解释load负载权重这个进程值多少优先级run_node红黑树节点用来把它挂进调度队列vruntime虚拟运行时间跑得越久越大排序核心依据min_vruntime最小虚拟运行时间判断它该不该轮到的门槛avg平均负载指数平滑统计出的近期活跃程度调度决策几乎只依赖这几列数字进程名、地址空间、打开的文件描述符等其它档案内容一概不用——这就是把简历单独抽出来的意义让调度器只看它需要看的东西。CFS 如何挑出下一个运行的进程CFS完全公平调度器负责普通进程实现在 kernel/sched/fair.c。它的思路不是谁等得久给谁而是让每个进程公平地累积虚拟时间。红黑树加虚拟运行时间每个可运行进程按min_vruntime挂在一棵红黑树上run_node就是这棵树上的节点。红黑树保证找最小值是 O(log n)调度器每次直接取最左那个也就是虚拟时间落后最多、最该补的进程。进程实际运行期间vruntime会按它的权重持续增长优先级越低涨得越快于是它更快追平别人从而实现越闲的越先跑。一个调度回合选完进程后调度器更新它的sum_exec_runtime与vruntime等它下次运行或让出 CPU 时重新入队。整个过程由update_curr()记账、pick_next_task_fair()选人都集中在 kernel/sched/fair.c是阅读 CFS 最好的起点。不改内核也能动调度相关的几个旋钮 ️参数调优不必改源码。内核把可运行时的调度参数暴露在/proc/sys/kernel/下先确认你的系统有哪些sysctl -a 2/dev/null | grep ^kernel\.sched这条命令列出当前系统所有kernel.sched*参数避免照着旧文档敲不存在的名字。参数方向关注点说明时间片 / 带宽单位时间内进程能用多少 CPU由 CFS 带宽控制例如sched_cfs_bandwidth_slice_us决定每片时长调度延迟 / 粒度多久重新挑一次进程影响多任务间的切换节奏唤醒抢占阈值新进程来时要不要立刻抢走 CPU太小会频繁切换太大响应变钝这些名字随内核版本演进尤其在新内核引入 EEVDF最早可行虚拟截止时间优先后底层改用了deadline、min_slice、max_slice等字段所以先查再用比背默认值更可靠。调参前建议先用cat /proc/pid/sched和perf sched record记录基线再小步改动避免把响应性和吞吐一起砸下去。到这里你已经能从看到 vruntime一路走到理解它如何决定谁先跑。下一步值得深挖两处源码一是 include/linux/sched.h 里task_struct与sched_entity的完整字段二是 kernel/sched/fair.c 中enqueue_task_fair()、pick_next_task_fair()这条选人链路想读设计动机可翻 Documentation/scheduler/。理解到这一层再回头看视频渲染时浏览器为何依旧流畅你就知道那其实是调度器在毫秒之间做的一连串公平取舍。【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考