初识进程:时间片与上下文数据
本文介绍了操作系统中的进程概念及其管理机制。进程是运行中的程序实例,由程序代码、数据和内核管理的PCB(进程控制块)组成。Linux系统中,PCB以struct task_struct结构体形式存在,记录进程ID、状态、优先级等关键信息,并通过双向链表组织管理。为实现多任务并发,CPU采用时间片轮转调度算法,每个进程获得短暂执行时间后强制切换。上下文数据保存了进程的运行现场,确保切换后能恢复执行。
2. PCB与struct task_struct:进程的身份证
一、进程:操作系统调度的最小单元
1. 进程是什么?
进程是正在运行的程序实例。我们要区分程序与进程的区别:
程序 :程序是存放在硬盘上的、静态的、编译好的可执行文件,它是进程在运行前的“胚胎”状态。
进程 : 加载到内存中的程序代码与数据 + 程序运行所需的全部管理信息。
其中所有管理信息,全部由内核结构体 struct task_struct(PCB)进行封装保存;操作系统会将系统内所有进程的task_struct结构体,以双向循环链表的形式串联起来,形成进程链表。
直白理解:进程链表相当于操作系统的进程花名册。程序的代码和数据分散存储在内存各处,而每一个进程的管控信息,全部串联在这张双向链表中;内核无需遍历零散的内存代码,仅通过遍历这张进程链表,就能统一完成对所有进程的管理、检索与CPU调度。
2. PCB与struct task_struct:进程的身份证
操作系统如何管理成百上千个进程?它无法直接识别二进制代码,所以内核为每一个进程创建一个专属的数据结构,也就是PCB(进程控制块)。
(1)PCB基本概念
PCB是操作系统内核用于描述、管理进程的核心数据结构,相当于进程的「档案袋」,进程的所有信息都会存入PCB。只要进程存在,PCB就不会销毁,操作系统通过遍历PCB,完成进程调度、资源分配。
(2)Linux下的struct task_struct
不同操作系统的PCB实现不同,Linux内核中,PCB的本质就是 struct task_struct 结构体,这个结构体包含上百个成员,完整记录进程所有属性,我整理了最核心的常用字段:
-
进程标识信息:pid(进程唯一ID)、ppid(父进程ID),用于区分不同进程;
-
进程状态信息:运行态、阻塞态、就绪态、终止态,标记进程当前工作状态;
-
优先级:决定CPU调度顺序,优先级高的进程优先占用CPU资源;
-
内存指针:指向进程占用的内存空间,记录代码、数据存放位置;
-
上下文数据:保存CPU寄存器数据,是进程切换的核心依据;
-
文件描述符表:记录进程打开的文件、网络套接字;
-
信号处理信息:管控进程的信号接收、处理逻辑,比如强制结束进程指令;
-
进程记账信息:记录进程占用CPU时长、内存大小,用于资源统计。
简单来说:Linux内核眼中没有进程,只有一个个task_struct结构体,所有进程管理操作,本质都是对结构体的增删改查。
3. 上下文数据:进程切换的关键
这里我们重点补齐两个核心疑问:什么是时间片?为什么一定要有上下文数据?同时详解进程切换的底层逻辑。
(1)什么是时间片?
时间片(Time Slice)是操作系统CPU调度器分配给单个进程的最小CPU执行时间段。
在单核心CPU下,同一时刻只能运行一个进程。为了让用户感觉电脑可以同时运行多个程序,操作系统采用时间片轮转调度算法:
-
时间片时长极短,通常为几毫秒;
-
系统给链表中每一个就绪进程,公平分配一小段CPU执行时间;
-
一旦时间片耗尽,无论程序是否执行完毕,CPU都会强制剥夺当前进程的执行权限,切换下一个进程。
通俗理解:CPU就是一座单人独木桥,所有进程排队过桥,操作系统规定每个人只能走5毫秒,时间一到强制换下一个人。因为切换速度极快,人眼无法感知延迟,造成了“多个程序同时运行”的错觉。
(2)什么是上下文数据?
CPU内置大量高速寄存器,寄存器读写速度远高于内存,专门用来临时存放正在执行的指令与运算数据。进程上下文数据,是进程在CPU运行期间,留存于寄存器内的全部临时运行现场数据。
举个例子:进程A执行至中途、还未结束时,寄存器中保存着当前运算中间结果、下一条指令地址、堆栈状态等专属数据,这一组记录运行现场的数据,就是进程A的上下文。
(3)为什么必须要有上下文数据?
结合上面的时间片概念,我们可以直白得出结论:上下文数据是时间片轮转调度的必备前提。
因为时间片极短,进程永远无法一次性跑完,执行中途一定会被CPU强制切下。如果没有上下文保存机制:
-
进程被切下时,CPU寄存器的数据会被新进程覆盖;
-
下次该进程重新上CPU时,丢失了上次运行记录,只能从头执行;
-
所有程序无法持续运行,电脑彻底瘫痪。
所以,上下文的本质就是保存进程的运行现场,保证进程多次轮转CPU时,能够无缝衔接、接着上次的代码继续执行。
(4)上下文的保存与恢复
-
保存上下文:将CPU寄存器中进程A的所有数据,拷贝存入A程序的task_struct结构体中;
-
恢复上下文:把进程A的上下文数据,从task_struct中读取出来,写入CPU寄存器,让进程A继续执行。
(5)上下文的意义与开销
上下文数据保证了进程切换不会丢失运行进度,让每一个进程都觉得自己独占CPU资源。我们日常一边听歌、一边打字、一边浏览网页,无感切换多个程序,底层全部依赖上下文的保存与恢复。
补充知识点:频繁切换进程会产生上下文开销,占用CPU资源,所以进程数量过多时,电脑会出现卡顿现象。
四、全文总结
本文全程围绕进程展开,核心逻辑总结如下:程序是存放于硬盘的静态文件,当程序加载至内存后就成为进程,进程的专业定义为:加载到内存中的程序代码与数据 + 程序运行所需的全部管理信息。Linux内核依靠 struct task_struct(PCB进程控制块)记录进程所有信息,并将所有进程以链表的方式串联,以此统一管理调度进程。为实现多程序并发执行,CPU采用时间片轮转调度算法,给进程分配极短的执行时间,强制轮换执行;而上下文数据是进程留存于CPU寄存器中的运行现场,是进程切换的核心。进程切换时需完成上下文的保存与恢复,保障进程接续执行,频繁切换会产生上下文开销,造成设备卡顿。总而言之,Linux通过结构体描述进程、链表组织进程、时间片轮转调度进程、上下文保留运行现场,最终实现多进程平稳并发运行。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)