[特殊字符] 深入理解 Linux 内核进程管理:架构、核心函数与调度机制
Linux 内核作为一个多任务操作系统,其进程管理子系统是核心组成部分之一。无论是用户应用的运行、驱动行为的触发,还是系统调度决策,几乎所有操作都离不开进程的创建、调度与销毁。本文将从进程的概念出发,深入探讨 Linux 内核中进程管理的架构、关键结构体、核心函数以及调度机制,帮助读者全面理解进程管理的内部实现。
1️⃣ 进程管理概述
1.1 什么是进程管理?
在操作系统中,进程是资源分配和调度的基本单位。Linux 内核通过进程管理子系统实现对进程的创建、调度、同步和终止等操作。掌握进程管理,有助于深入理解内核的调度策略与系统行为,在嵌入式开发、系统调试、驱动开发与性能调优等方面提供底层逻辑支持。
1.2 Linux 进程管理架构概览
Linux 内核的进程管理架构主要包括以下模块:
模块名称 | 核心职责 | 关键结构 / 函数示例 | 相关源码位置 |
---|---|---|---|
进程描述结构体 | 描述进程状态、资源、调度信息 | task_struct 、thread_info | include/linux/sched.h |
进程创建机制 | 创建进程、复制上下文、初始化资源 | fork() 、do_fork() 、copy_process() | kernel/fork.c |
程序执行加载 | 替换进程地址空间并执行新程序 | execve() 、do_execveat_common() | fs/exec.c 、kernel/exec_domain.c |
进程退出机制 | 释放资源、通知父进程、进入僵尸态 | exit() 、do_exit() 、release_task() | kernel/exit.c |
进程调度器 | 管理调度实体、决定谁运行、支持多种调度策略 | schedule() 、CFS、rq 、sched_class | kernel/sched/core.c 、fair.c |
上下文切换 | 切换执行流、保存/恢复 CPU 状态 | context_switch() 、switch_to() | kernel/sched/core.c 、arch/*/kernel/ |
进程状态管理 | 控制进程运行/睡眠/终止状态,便于调度与同步 | TASK_RUNNING 、TASK_INTERRUPTIBLE | include/linux/sched.h |
阻塞与唤醒机制 | 通过等待队列控制休眠/唤醒流程,协调资源争用 | wait_queue_head_t 、wake_up() | kernel/sched/wait.c 、include/linux/wait.h |
调度策略与优先级 | 支持普通、实时调度,动态调整权重与时间片 | SCHED_NORMAL 、SCHED_FIFO 、nice | kernel/sched/ 各调度策略子模块 |
用户态/内核态交互 | 系统调用入口、堆栈切换、权限切换 | sys_clone() 、do_syscall_64() | arch/arm64/kernel/entry.S 、kernel/ |
2️⃣ 进程的状态
在 Linux 中,进程的状态主要包括:
- TASK_RUNNING:可运行状态,正在运行或准备运行。
- TASK_INTERRUPTIBLE:可中断睡眠状态,等待某事件发生。
- TASK_UNINTERRUPTIBLE:不可中断睡眠状态,通常用于等待 I/O 操作完成。
- TASK_STOPPED:停止状态,进程被暂停。
- TASK_TRACED:被跟踪状态,进程正在被调试。
- EXIT_ZOMBIE:僵尸状态,进程已终止但尚未被父进程回收。
- EXIT_DEAD:死亡状态,进程资源已被释放。
这些状态的转换由内核调度器根据系统资源和进程行为进行管理。
3️⃣ 进程管理核心架构
3.1 task_struct
结构体
内核通过 task_struct
结构体来描述一个进程,它被称为进程描述符(Process Descriptor),保存着支撑一个进程正常运行的所有信息。
task_struct
包含的信息包括:
- 进程状态(如运行、睡眠等)
- 进程标识符(PID)
- 父子进程关系
- 调度信息(如优先级、调度策略)
- 内存管理信息(如地址空间)
- 文件系统信息(如打开的文件)
- 信号处理信息
- 安全信息(如权限)
通过 task_struct
,内核可以全面管理和调度进程。
3.2 核心函数
3.2.1 kernel_clone()
kernel_clone()
是 Linux 内核中用于创建新进程或线程的核心函数之一,广泛用于内核线程创建、系统调用 clone()
和 clone3()
的实现中。它负责准备和校验参数、决定是否进行 ptrace 跟踪、调用 copy_process()
完成进程复制,并处理进程唤醒与后续收尾逻辑。
其主要步骤包括:
- 参数校验,防止
CLONE_PIDFD
与CLONE_PARENT_SETTID
指向同一地址。 - 判断是否需要触发 ptrace 跟踪事件,如
PTRACE_EVENT_FORK
、CLONE
、VFORK
。 - 调用
copy_process()
创建并初始化新进程的task_struct
。 - 添加系统熵,增强内核熵池。
- 调度器事件追踪,记录进程创建事件。
- 获取新进程的 PID,并根据需要写入
parent_tid
。 - 若设置了
CLONE_VFORK
,初始化同步机制,并在父进程阻塞等待。 - 若未共享地址空间(非
CLONE_VM
),设置内存 LRU 跟踪。 - 唤醒新创建的子进程,启动任务调度。
- 如果启用了 ptrace 事件,发送通知。
- 如果是 vfork,阻塞当前进程直到子进程释放 VM。
- 释放 PID 引用,防止内存泄漏。
- 返回子进程 PID。
3.2.2 copy_process()
copy_process()
是内核创建新进程(包括 fork、vfork、clone 和内核线程)的核心函数,它的实现逻辑极其庞大。其主要职责包括:
- 复制当前进程的
task_struct
结构体,分配内存并初始化任务栈。 - 复制用户凭据(uid/gid/capability),对应
clone_flags
的CLONE_NEWUSER
等。 - 初始化延迟统计结构,仅用于性能跟踪。
- 调度器层面初始化新任务,分配调度相关结构。
- 初始化 perf 事件跟踪数据,支持性能事件分析。
- 分配审计信息结构,针对安全模块。
- 安全模块初始化,如 SELinux,与 LSM(Linux 安全模块)有关。
- 复制 SYSV 信号量取消状态,若使用信号量。
- 文件描述符表复制,区分共享与独立 fd 表。
- 复制
fs_struct
(cwd/root 等),控制工作目录和挂载点的继承。 - 复制信号处理函数表,若不共享 sighand(
CLONE_SIGHAND
)。 - 创建新的
signal_struct
(信号相关状态)
接续上文,本文将继续深入探讨 Linux 内核进程管理的关键机制,包括进程调度策略、上下文切换过程以及相关核心结构体的作用。
4️⃣ 进程调度机制
4.1 调度的基本概念
进程调度的核心任务是决定哪个进程在何时运行。调度器依据一定的策略,从就绪队列中选择一个进程分配 CPU 时间。调度策略的设计直接影响系统的响应速度、吞吐量和公平性。
4.2 调度策略分类
Linux 内核支持多种调度策略,主要包括:
- SCHED_NORMAL(或 SCHED_OTHER):默认的时间共享调度策略,适用于普通进程。
- SCHED_BATCH:适用于批处理作业,优化吞吐量。
- SCHED_IDLE:用于系统空闲时运行的低优先级任务。
- SCHED_FIFO 和 SCHED_RR:实时调度策略,适用于对响应时间有严格要求的任务。
- SCHED_DEADLINE:基于截止时间的调度策略,适用于具有明确时间约束的任务。
4.3 完全公平调度器(CFS)
CFS(Completely Fair Scheduler)是 Linux 内核自 2.6.23 版本起引入的默认调度器,旨在为所有进程提供公平的 CPU 时间分配。([linux-audit.com][1])
4.3.1 核心理念
CFS 模拟一个理想的多任务处理器,假设所有进程可以同时并行运行。由于实际硬件无法实现真正的并行,CFS 引入了“虚拟运行时间”(vruntime)的概念,用于衡量进程的实际运行时间与其应得运行时间之间的差距。([zh.wikipedia.org][2])
4.3.2 数据结构
CFS 使用红黑树(Red-Black Tree)作为就绪队列的数据结构,每个节点表示一个可调度实体(sched_entity),按照 vruntime 进行排序。调度器总是选择 vruntime 最小的进程进行调度。
4.3.3 时间片计算
CFS 不使用固定的时间片,而是根据系统的目标延迟(target latency)和就绪队列中的进程数量动态计算每个进程的时间片,确保每个进程在目标延迟内至少运行一次。([medium.com][3])
5️⃣ 上下文切换机制
5.1 上下文切换的定义
上下文切换是指操作系统保存当前运行进程的状态,并恢复另一个进程的状态,使其能够继续执行的过程。这是实现多任务处理的基础。
5.2 上下文切换的触发时机
上下文切换可能在以下情况下发生:
- 当前进程主动放弃 CPU(例如,调用
schedule()
)。 - 当前进程被阻塞(例如,等待 I/O 操作完成)。
- 系统发生中断或异常。
- 当前进程的时间片耗尽。
5.3 上下文切换的实现过程
在 Linux 内核中,上下文切换主要由 context_switch()
函数完成,其过程包括:
- 调用
prepare_task_switch()
准备切换。 - 调用
arch_start_context_switch()
执行架构相关的切换操作。 - 根据需要切换内存地址空间(即更新页表)。
- 保存当前进程的寄存器状态。
- 恢复目标进程的寄存器状态。
- 调用
finish_task_switch()
完成切换。([linux-kernel-labs.github.io][4])
整个过程确保了进程的执行环境被完整保存和恢复,实现了进程之间的无缝切换。
6️⃣ 调度相关的核心结构体
6.1 sched_class
sched_class
是一个结构体,定义了调度器的行为和操作函数指针,如选择下一个任务、任务入队出队等。不同的调度策略(如 CFS、实时调度器)通过实现各自的 sched_class
来定义其调度逻辑。
6.2 sched_entity
sched_entity
是 task_struct
中的一个成员,表示一个可调度的实体,包含了调度相关的信息,如 vruntime、权重等。在 CFS 中,调度器通过操作 sched_entity
来管理进程的调度。
7️⃣ 总结
Linux 内核的进程管理机制涵盖了从进程的创建、调度到终止的完整生命周期。通过深入理解 task_struct
、kernel_clone()
、copy_process()
、CFS 调度器以及上下文切换的实现,可以更好地掌握内核的工作原理,为系统优化和问题排查提供坚实的基础。
希望本文能帮助您构建起完整的进程管理知识体系,深入理解 Linux 内核的精妙设计。
相关文章:

[特殊字符] 深入理解 Linux 内核进程管理:架构、核心函数与调度机制
Linux 内核作为一个多任务操作系统,其进程管理子系统是核心组成部分之一。无论是用户应用的运行、驱动行为的触发,还是系统调度决策,几乎所有操作都离不开进程的创建、调度与销毁。本文将从进程的概念出发,深入探讨 Linux 内核中进…...
Nginx Stream 层连接数限流实战ngx_stream_limit_conn_module
1.为什么需要连接数限流? 数据库/Redis/MQ 连接耗资源:恶意脚本或误配可能瞬间占满连接池,拖垮后端。防御慢速攻击:层叠式限速(连接数+带宽)可阻挡「Slow Loris」之类的 TCP 低速洪水。公平接入…...
Spring Boot 定时任务的使用
前言 在实际开发中,我们经常需要实现定时任务的功能,例如每天凌晨执行数据清理、定时发送邮件等。Spring Boot 提供了非常便捷的方式来实现定时任务,本文将详细介绍如何在 Spring Boot 中使用定时任务。 一、Spring Boot 定时任务简介 Spr…...

Flutter:下拉框选择
 文档地址dropdown_button2 // 限价、市价 状态final List<String> orderTypes [普通委托, 市价委托];String? selectedOrderType 普通委托;changeOrderType(String …...

SpringAI(GA):Nacos2下的分布式MCP
原文链接地址:SpringAI(GA):Nacos2下的分布式MCP 教程说明 说明:本教程将采用2025年5月20日正式的GA版,给出如下内容 核心功能模块的快速上手教程核心功能模块的源码级解读Spring ai alibaba增强的快速上手教程 源码级解读 版…...
AC68U刷梅林384/386版本后不能 降级回380,升降级解决办法
前些时间手贱更新了路由器的固件,384.18版本。结果发现了一堆问题,比如客户端列表加载不出来,软件中心打不开等等。想着再刷一下新的固件,结果死活刷不上去。最后翻阅了大量前辈的帖子找到了相关的处理办法。现在路由器中开启SSH&…...

[AI绘画]sd学习记录(二)文生图参数进阶
目录 7.高分辨率修复:以小博大8.细化器(Refiner):两模型接力9.随机数种子(Seed):复现图片吧 本文接续https://blog.csdn.net/qq_23220445/article/details/148460878?spm1001.2014.3001.5501…...

CRM管理系统中的客户分类与标签管理技巧:提升转化率的核心策略
在客户关系管理(CRM)领域,有效的客户分类与标签管理是提升销售效率、优化营销ROI的关键。据统计,使用CRM管理系统进行科学客户分层的企业,客户转化率平均提升35%(企销客数据)。本文将深入解析在CRM管理软件中实施客户分类与标签管理的最佳实践…...

怎么解决cesium加载模型太黑,程序崩溃,不显示,位置不对模型太大,Cesium加载gltf/glb模型后变暗
有时候咱们cesium加载模型时候型太黑,程序崩溃,不显示,位置不对模型太大怎么办 需要处理 可以联系Q:424081801 谢谢 需要处理 可以联系Q:424081801 谢谢...

【AI系列】BM25 与向量检索
博客目录 引言:信息检索技术的演进第一部分:BM25 算法详解第二部分:向量检索技术解析第三部分:BM25 与向量检索的对比分析第四部分:融合与创新:混合检索系统 引言:信息检索技术的演进 在信息爆…...
windows10搭建nfs服务器
windows10搭建nfs服务器 Windows10搭建NFS服务 - fuzidage - 博客园...
simulink这边重新第二次仿真时,直接UE5崩溃,然后simulink没有响应
提问 : simulink这边重新第二次仿真时,直接UE5崩溃,然后simulink没有响应 simulink和UE5仿真的时候,simulink这边先停止仿真(也就是官方要求的顺序——注意:如果先在UE5那边停止仿真,如果UE5这…...
react 常见的闭包陷阱深入解析
一、引子 先来看一段代码,你能说出这段代码的问题在哪吗? const [count, setCount] = useState(0); useEffect(() => {const timer = setTimeout(() => {setCount(count + 1);}, 1000);return () => clearTimeout(timer); }, []);正确答案: 这段代码存在闭包陷阱…...
【CATIA的二次开发22】关于抽象对象Document概念详细总结
在CATIA VBA开发中,Document对象是最核心、最基础的对象之一。它代表了当前在CATIA会话中打开的一个文档(文件)。 几乎所有与文件操作、模型访问相关的操作都始于获取一个Document对象。 一、Document对象概述 1、获取Document对象: 当前活动文档: 最常见的方式是获取用户…...

模拟法解题的思路与算法分享
我们先来看思路与算法: 使用变长数组对栈进行模拟。 如果操作是 ,那么访问数组的后两个得分,将两个得分之和加到总得分,并且将两个得分之和入栈。如果操作是 D,那么访问数组的最后一个得分,将得分乘以 2 …...

mysql密码正确SpringBoot和Datagrip却连接不上
报错信息:SQLException: Access denied for user ‘root‘‘localhost‘ (using password: YES) 原因可能是是有端口号冲突 我这里是禅道端口与MySQL冲突,禅道端口也是3306,ctrlaltdelete打开任务管理器,关闭mysqlzt …...

高保真组件库:数字输入框
拖入一个文本框。 拖入一个矩形,作为整个数字输入框的边框,边框颜色为灰色DCDEE2,圆角半径为4。 拖入一个向上的箭头图标作为增加按钮,再拖入一个矩形,将向上箭头图标放入矩形内。矩形:18x15,边框颜色DCDEE2,边框左下可见,箭头图标:8x5,矩形置底,组合在一起命名”增…...
人工智能赋能高中学科教学的应用与前景研究
一、引言 1.1 研究背景 在科技飞速发展的当下,人工智能(Artificial Intelligence,简称 AI)已成为全球瞩目的关键技术领域,深刻地改变着人们的生活、工作和学习方式。从智能家居设备到智能交通系统,从医疗…...

【Linux】awk 命令详解及使用示例:结构化文本数据处理工具
【Linux】awk 命令详解及使用示例:结构化文本数据处理工具 引言 awk 是一种强大的文本处理工具和编程语言,专为处理结构化文本数据而设计。它的名称来源于其三位创始人的姓氏首字母:Alfred Aho、Peter Weinberger 和 Brian Kernighan。 基…...

紫光同创FPGA系列实现Aurora 8b/10b协议
特性 1.兼容XILINX aurora IP核 2.支持X1、X2、X4、X8模式(根据硬件条件选择模式) 3.支持FRAMING和STREAMING 用户接口 4.自动初始化和维护链路状态 5.支持热插拔 6.支持扰码、解扰 7.支持流量控制 8.支持crc用户数据 9.支持全双工或者半双工模式 10.最…...

DAY 44 预训练模型
知识点回顾: 预训练的概念常见的分类预训练模型图像预训练模型的发展史预训练的策略预训练代码实战:resnet18 (一)预训练的概念 我们发现准确率最开始随着epoch的增加而增加。随着循环的更新,参数在不断发生更新。 所以…...
[Harmony]颜色初始化
默认初始化颜色 let color: Color 0xFF00FF 创建一个工具,用十六进制颜色和RGBA初始化颜色 // 颜色工具类 export class ColorUtils {/*** 十六进制颜色初始化(支持透明度)* param hex 支持格式:#RRGGBB、#AARRGGBB、0xRRGGBB、…...
指针与函数参数传递详解 —— 值传递与地址传递的区别及应用
资料合集下载链接: https://pan.quark.cn/s/472bbdfcd014 在C语言中,函数参数的传递方式主要有两种:值传递和地址传递(通过指针)。理解两者的区别及应用对于正确操作数据和优化程序逻辑至关重要。本文将通过…...

【NLP中向量化方式】序号化,亚编码,词袋法等
1.序号化 将单词按照词典排序,给定从0或者1或者2开始的序号即可,一般情况有几 个特征的单词: PAD表示填充字符,UNK表示未知字符 在这个例子中,我们可以看到我们分别将3个文本分为了4个token,每个token用左侧的词典表示…...

C++学习-入门到精通【16】自定义模板的介绍
C学习-入门到精通【16】自定义模板的介绍 目录) C学习-入门到精通【16】自定义模板的介绍前言一、类模板创建一个自定义类模板:Stack\<T\> 二、使用函数模板来操作类模板特化的对象三、非类型形参四、模板类型形参的默认实参五、重载函数模板 前言…...
关于脏读,幻读,可重复读的学习
mysql 可以查询当前事务隔离级别 默认是RR repeatable-read 如果要测脏读 要配成未提交读 RU 读到了未提交的数据。 3.演示不可重复读 要改成提交读 RC 这个是指事务还未结束,其他事务修改了值。导致我两次读的不一样。 4.RR–可以解决不可重复读 小总结&…...

源码级拆解:如何搭建高并发「数字药店+医保购药」一体化平台?
在全民“掌上看病、线上购药”已成常态的今天,数字药店平台正在以惊人的速度扩张。而将数字药店与医保系统打通,实现线上医保购药,更是未来互联网医疗的关键拼图。 那么,如何从技术底层搭建一个 支持高并发、可扩展、安全合规的数…...
旅行商问题(TSP)的 C++ 动态规划解法教学攻略
一、问题描述 旅行商问题(TSP)是一个经典的组合优化问题。给定一个无向图,图中的顶点表示城市,边表示两个城市之间的路径,边的权重表示路径的距离。一个售货员需要从驻地出发,经过所有城市后回到驻地&…...
unix/linux,sudo,其内部结构机制
我们现在深入sudo的“引擎室”,探究其内部的结构和运作机制。这就像我们从观察行星运动,到深入研究万有引力定律的数学表达和物理内涵一样,是理解事物本质的关键一步。 sudo 的内部结构与机制详解 sudo 的执行流程可以看作是一系列精心设计的步骤,确保了授权的准确性和安…...

Hadoop 3.x 伪分布式 8088端口无法访问问题处理
【Hadoop】YARN ResourceManager 启动后 8088 端口无法访问问题排查与解决(伪分布式启动Hadoop) 在配置和启动 Hadoop YARN 模块时,发现虽然 ResourceManager 正常启动,JPS 进程中也显示无误,但通过浏览器访问 http://主机IP:8088 时却无法打…...