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

进程与线程的根本区别

在 Linux 中,进程和线程的根本区别在于:资源管理方式隔离程度

简单来说:

  • 进程是资源分配的基本单位。每个进程都拥有独立的、完整的资源集合。

  • 线程是 CPU 调度的基本单位。它是进程的一个执行流,与同进程下的其他线程共享绝大部分资源。

详细对比表

特性进程线程说明与比喻
根本区别资源拥有的基本单位CPU 调度的基本单位进程是“公司”,拥有办公室、打印机等资源(内存、文件);线程是“员工”,共享公司资源,但各自执行任务。
资源隔离高。拥有独立的地址空间、数据栈、文件描述符表等。低。共享同一进程的地址空间、文件描述符、全局变量等。一个进程崩溃不会影响其他进程。一个线程崩溃通常会导致整个进程及其所有线程崩溃。
内存空间独立的虚拟地址空间。共享其所属进程的虚拟地址空间。进程间通信 (IPC) 需要特殊机制(如管道、消息队列、共享内存)。线程间通信非常简单,直接读写全局变量即可。
创建开销大。需要分配独立的内存空间、建立众多的数据结构(如页表)。小。只需分配自己的栈和少量寄存器状态,共享已有资源。fork() 一个进程比 pthread_create() 创建一个线程慢得多。
上下文切换开销大。需要切换虚拟地址空间(刷新 TLB 缓存)。开销小。只需切换栈和寄存器状态,地址空间不变。线程切换更快,效率更高。
数据共享复杂,需要通过进程间通信 (IPC) 机制。简单,天然共享全局变量、堆内存、文件句柄等。线程共享数据方便,但这也带来了同步问题(需用互斥锁、信号量等)。
健壮性高。一个进程崩溃,不会影响其他进程。低。一个线程崩溃(如段错误)会导致整个进程死亡,波及所有同进程线程。多进程架构更稳定,但通信成本高。
控制终端有独立的进程组、会话组概念。共享其所属进程的进程组和会话组。在终端中,Ctrl+C 会发送信号给整个进程组。

Linux实现方式

许多教科书会告诉你“进程和线程是不同的概念”,但在 Linux 的实现上,有一个关键点需要理解:

Linux 并不从内核层面严格区分进程和线程。

Linux 内核使用一种通用的模型——任务(Task)——来表示一个执行上下文。无论是我们称呼的“进程”还是“线程”,在内核里都是一个 task_struct 结构体。

那么区别是如何产生的呢?

关键在于 clone() 系统调用 的参数。

对于clone()的理解

  • 创建进程: 通过 fork()vfork() 系统调用,其底层调用 clone() 时,设置的参数共享资源很少(特别是设置了 CLONE_VM 标志,表示不共享内存地址空间)。

    • 相当于创建了一个拥有全新独立资源的 task_struct。
  • 创建线程: 通过 pthread_create() 库函数,其底层调用 clone() 时,设置的参数共享大量资源(如 CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND 等),这意味着新的 task_struct共享内存空间、文件系统信息、文件描述符表和信号处理程序。

    • 相当于创建了一个共享绝大部分资源的 task_struct。

因此,在 Linux 中:

  • 进程:可以看作是一个只有一个线程的进程。

  • 线程:可以看作是共享了同一份资源的“轻量级进程”(Light-Weight Process, LWP)。

你可以使用 ps -eLf 命令来查看进程和它们内部的线程(LWP)。其中 PID 是进程 ID,而 LWP 是线程 ID。对于主线程,PIDLWP 的值是相同的。

一个生动的比喻:浏览器

打开一个浏览器(如Chrome)就是一个进程。

  • 这个进程拥有它自己的内存空间,用来存储浏览器的代码、UI界面等

然后,你在这个浏览器中:

  • 打开一个标签页访问新闻网站 -> 浏览器进程可能会创建一个线程来处理网络请求和渲染页面。

  • 打开另一个标签页播放视频 -> 又会创建另一个线程来解码视频和音频。

  • 浏览器扩展也在后台运行 -> 每个扩展可能也运行在独立的线程中。

所有这些线程共享着浏览器进程的资源,比如Cookie数据、缓存文件、用户登录状态等。它们并行工作,让你可以同时看视频、下载文件而不卡顿。

如果其中一个标签页(线程)因为访问了一个有问题的网页而崩溃了,通常整个浏览器(进程)都会崩溃,因为你所有的标签页(线程)共享着同一个内存空间。

而如果你同时打开了Chrome和Firefox,它们就是两个不同的进程。Chrome崩溃了,Firefox依然可以正常运行,因为它们的内存空间是相互隔离的

小结

场景推荐使用原因
需要高安全性和稳定性多进程故障被隔离,一个组件崩溃不会导致整个应用瘫痪。
需要频繁创建和销毁多线程创建和上下文切换的开销小,速度快。
需要大量计算(CPU密集型)多进程(或多线程+多核)可真正利用多核CPU。但若需频繁共享数据,多线程可能更优。
需要大量IO操作(IO密集型)多线程线程在等待IO时,其他线程可以继续执行,效率极高。
需要频繁共享和交换数据多线程数据共享在同一内存空间,非常简单高效。

Linux 中的进程是资源分配的容器,而线程是在这个容器内并行执行的实体线程共享容器的资源,从而实现了轻量和高效,但也牺牲了隔离性带来的稳定性。内核通过 clone() 系统调用的不同参数来灵活地实现这两种概念。

http://www.xdnf.cn/news/19328.html

相关文章:

  • Parasoft赋能测试:精准捕捉运行时缺陷
  • 解决RTX3070魔改16G在UBUNTU中黑屏问题
  • AI ToB,阿里商旅找了个好赛道
  • C++ 并发编程:全面解析主流锁管理类
  • Day17_【机器学习—特征预处理(归一化和标准化)】
  • Unity学习----【数据持久化】二进制存储(一)
  • 仿真高斯光束同时分析光纤耦合特点并仿真
  • 大模型入门学习微调实战:基于PyTorch和Hugging Face电影评价情感分析模型微调全流程(附完整代码)手把手教你做
  • Lenovo C225 一体机拆机维修教程
  • 从零开始学Shell编程:从基础到实战案例
  • 【完整源码+数据集+部署教程】骨折检测系统源码和数据集:改进yolo11-EfficientHead
  • flume事务机制详解:保障数据可靠性的核心逻辑
  • Vue3 kkfileview 的使用
  • 第八章 惊喜01 测试筹备会
  • Shell 中 ()、(())、[]、{} 的用法详解
  • ros2--service/服务--接口
  • Redis不同场景下的注意事项
  • C++中自由函数(free function)概念
  • 比随机森林更快更强?极限森林的核心逻辑与完整实践指南
  • 零知识证明的刑事证据困境:隐私权与侦查权的数字博弈
  • Hal aidl 模板
  • open webui源码分析12-Pipeline
  • 用docker安装rstudio-server
  • 【python开发123】三维地球应用开发方案
  • Adobe Acrobat 中通过 JavaScript 调用 Web 服务
  • ros、slam、激光雷达、自动驾驶相关学习内容和计划
  • 深度拆解判别式推荐大模型RankGPT!生成式精排落地提速94.8%,冷启动效果飙升,还解决了传统推荐3大痛点
  • Pointer--Learing MOOC-C语言第九周指针
  • “北店南下”热潮不减,企业赴港开拓业务如何站稳脚跟
  • springboot java开发的rocketmq 事务消息保证