进程与线程到底差在哪?Linux 内核给出答案

发布时间:2026/8/31 23:42:05
进程与线程到底差在哪?Linux 内核给出答案 进程与线程到底差在哪Linux 内核给出答案“进程是资源分配的单位线程是调度的单位”——这句话背了无数遍但你真的理解了吗今天不从教科书出发直接翻开 Linux 内核源码进程和线程在内核里到底是什么答案可能颠覆你的直觉它们都是同一个结构体 task_struct。一、教科书里的 PCB 与内核里的 task_struct操作系统原理课告诉我们每个进程有一个 PCB进程控制块装着状态、寄存器现场、地址空间、打开的文件、优先级……到了 Linux v6.x 这个工业级内核PCB 落地成一个具体得不能再具体的结构体——task_struct定义在include/linux/sched.h。它是内核里被引用最频繁、最庞大的结构体之一是理解整个进程子系统的总钥匙。关键字段长这样节选structtask_struct{structthread_infothread_info;/* 内核栈信息 */unsignedint__state;/* 进程状态 */intprio;/* 动态优先级 */conststructsched_class*sched_class;/* 调度类 */structsched_entityse;/* CFS 调度实体 */structmm_struct*mm;/* 内存描述符地址空间*//* ... 文件表、信号、命名空间…… */};二、颠覆认知线程也是 task_struct重点来了在 Linux 眼里进程和线程没有本质区别——都是 task_struct。那它们差在哪看mm字段进程每个 task_struct 有独立的mm地址空间互不共享线程多个 task_struct共享同一个mm只是各自有独立的栈和寄存器现场所以进程 vs 线程的区别在内核里就是一句话共享不共享地址空间。这也是为什么线程也叫轻量级进程LWP——创建线程不需要复制整个地址空间只需新建一个 task_struct 并指向同一个 mm。三、内核栈与 current怎么找到我是谁每个 task_struct 都配一块内核栈x86-64 上是 16KB。内核里到处要拿到当前任务的 task_struct这就是current宏做的事。早期内核把 thread_info 放在栈底靠栈指针对齐算出 task_struct 地址Linux v6.x 默认CONFIG_THREAD_INFO_IN_TASKthread_info 直接嵌进 task_struct 首部current变成读一个每 CPU 的当前任务指针——O(1) 拿到我是谁。这个细节告诉你工业级代码和教科书模型的差别往往藏在性能和安全的取舍里。四、代码演示用 Python 模拟 task_struct 与进程/线程fromdataclassesimportdataclass,fielddataclassclassTaskStruct:pid:intstate:strTASK_RUNNINGprio:int120mm:objectNone# 内存描述符地址空间files:listfield(default_factorylist)parent:objectNonechildren:listfield(default_factorylist)defcreate_process(pid,parentNone):tTaskStruct(pidpid,mm{code:0x400000,stack:0x7fff},parentparent)ifparent:parent.children.append(t)returntdefcreate_thread(pid,parent):tTaskStruct(pidpid,mmparent.mm,parentparent)# 共享 mmparent.children.append(t)returnt maincreate_process(1000)t1create_thread(1001,main)# 线程共享地址空间p1create_process(1002,main)# 进程独立地址空间print(f线程 t1 与主进程共享地址空间:{t1.mmismain.mm})print(f进程 p1 与主进程地址空间独立:{p1.mmisnotmain.mm})print(f内核视角: 三者都是 task_struct, 主进程 children{[c.pidforcinmain.children]})运行输出线程 t1 与主进程共享地址空间: True 进程 p1 与主进程地址空间独立: True 内核视角: 三者都是 task_struct, 主进程 children[1001, 1002]这个模型虽然简化但抓住了内核视角的本质进程和线程都是 task_struct区别只在 mm 是否共享。五、避坑清单线程是调度的单位不完全准确Linux 的调度器调度的是 task_struct也叫任务进程和线程都参与调度线程切换不一定比进程切换快同进程线程切换省了地址空间切换TLB 刷新但现代 CPU 上这个差距在缩小多线程崩溃会带走整个进程共享地址空间意味着一个线程的野指针可能毁掉所有线程task_struct 很大v6.x 上约 7KB所以内核用 slab 缓存复用创建线程也要小心分配开销看内核源码别被吓到task_struct 有几百个字段按语义分段读调度/内存/文件/信号一次只读一段六、想系统学 Linux 内核本文精选自ima 知识号【Kruptos】《Linux内核源码精读》订阅库第 011 期 task_struct 进程在内核里到底是什么、第 012 期 fork/clone/vfork 源码路径等 100 期系统教程从启动流程、进程管理、内存管理、文件系统到调度器每期配可运行代码。 完整系列 100 期 配套代码已在 ima 知识号发布本文只是系列的一个切片。完整系列100 期系统教程 每期可运行代码在 ima 知识号【Kruptos】持续更新中 67 技术知识库信号与系统、SDR 软件无线电、数字信号处理、操作系统、AI Agent、大模型微调……几乎覆盖全部软硬件技术栈 8 款 AI 技能系列生产、知识库管理、CMMI 受管开发、自进化 Agent 等已在 ima 技能广场上架即装即用✅ 全部免费订阅后续更新自动推送 订阅方式打开 ima腾讯智能工作台→ 搜索「Kruptos」→ 一键订阅。或在 ima 内直接搜索《Linux内核源码精读》等知识库名称。作者Kruptos西电毕业13 年无线通信/DSP/嵌入式科研原创内容转载注明出处