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

【Linux】线程概念与控制(1)

1. Linux 线程概念

线程是进程内的执行流,是操作系统调度的基本单位。在 Linux 中,线程与进程深度融合(通过 “轻量级进程” 实现),共享进程的地址空间、文件描述符等资源,同时具备独立的执行上下文(如寄存器、栈)。本节从内存管理、线程特性、优缺点等角度,解析 Linux 线程的本质。

1-1 什么是线程

线程是进程内部的控制序列,核心特点:

  • 进程与线程的关系:进程是资源分配的基本单位,线程是调度的基本单位。一个进程至少包含一个线程(主线程)。
  • 运行空间:线程在进程的地址空间内运行,共享进程的代码段、数据段、堆、文件描述符等资源。
  • 轻量级 PCB:Linux 中,线程以 “轻量级进程(LWP)” 形式存在,内核的PCB(进程控制块)对线程的管理更轻量化(共享大部分进程资源,仅需维护独立的执行上下文)。

1-2 分页式存储管理:线程资源划分的基础

线程能共享进程资源,依赖分页式虚拟内存管理—— 通过虚拟地址、页表、物理内存的分层映射,实现 “进程地址空间共享,物理内存离散分配”。

1-2-1 虚拟地址与页表的由来

问题背景:若直接使用物理内存,进程需连续的物理空间,易导致 “内存碎片”(进程退出后,物理内存被分割为零散块,无法被大进程利用)。

解决方案:虚拟内存 + 分页

  • 物理内存分页:将物理内存划分为固定大小的 “页框(Page Frame)”,每个页框存一个 “物理页(Page)”(32 位系统通常为 4KB,64 位系统多为 8KB)。
  • 虚拟地址空间:为每个进程分配独立的虚拟地址空间(32 位系统为 0~4GB),进程通过虚拟地址间接访问物理内存。
  • 页表映射:操作系统维护 “页表”,记录虚拟页(虚拟地址划分的页)与物理页框的映射关系。

效果:虚拟地址连续,物理内存可离散分配,解决了内存碎片问题。

1-2-2 物理内存管理

Linux 内核用struct page管理每个物理页,核心字段:

  • flags:页的状态(如是否脏页、是否锁定)。
  • _mapcount:页被引用的次数(-1 表示未被内核引用,可分配)。
  • virtual:页的虚拟地址(高端内存可能为NULL,需动态映射)。

内存开销:若物理内存为 4GB(4KB 页框),共需4GB / 4KB = 1,048,576struct page。若每个struct page占 40 字节,总开销为1,048,576 × 40B = 40MB,仅占物理内存的 1%(可接受)。

1-2-3 页表:多级映射优化

单级页表的问题:32 位系统中,虚拟地址 4GB,4KB 页框需4GB / 4KB = 1,048,576个页表项,每个项占 4 字节,总页表大小为4MB,需4MB / 4KB = 1024个连续页框 —— 既浪费内存,又违反 “离散分配” 的初衷。

多级页表(以二级为例)

  • 将单级页表拆分为 “页目录表 + 页表”:
    • 页目录表:含 1024 个项,每个项指向一个 “页表”。
    • 页表:每个页表含 1024 个项,指向物理页框。
  • 优势:进程仅需加载 “实际使用的页表”,无需加载全部 1024 个页表,节省内存(如 10MB 进程仅需 3 个页表)。

1-2-4 页目录与地址转换

  • 页目录表:管理所有页表,其物理地址由CR3寄存器存储(每个进程的CR3不同,实现地址空间隔离)。
  • 地址转换流程
    1. CPU 将虚拟地址拆分为 “页目录索引 + 页表索引 + 页内偏移”。
    2. 通过CR3找到页目录表,再通过 “页目录索引” 找到目标页表。
    3. 通过 “页表索引” 找到物理页框,结合 “页内偏移” 得到物理地址。

1-2-5 TLB:加速地址转换

多级页表虽节省内存,但增加了地址转换的 “查表次数”(二级页表需查 2 次表)。为加速转换,CPU 引入TLB(Translation Lookaside Buffer,转译后备缓冲器)

  • TLB 是 “页表项的高速缓存”,存储近期使用的虚拟页→物理页映射。
  • 工作流程
    • 地址转换时,先查 TLB:命中则直接获取物理地址。
    • 未命中则查多级页表,同时将新映射存入 TLB(淘汰旧项)。

1-2-6 缺页异常:内存不足时的补救

当 CPU 访问的虚拟页无物理页映射(或权限错误)时,触发缺页异常(Page Fault),进入内核态处理:

  • 硬缺页(Major Page Fault):物理内存中无对应页,需从磁盘(如交换分区、可执行文件)加载页到内存,再建立映射。
  • 软缺页(Minor Page Fault):物理内存中有对应页(如其他进程共享的页),仅需建立映射。
  • 无效缺页:访问越界(如空指针、非法地址),触发SIGSEGV信号,终止进程。

线程资源划分的真相

线程共享进程的虚拟地址空间,因此天然共享进程的代码、数据、堆等资源。操作系统只需为线程分配独立的栈空间(通常为 8MB)和寄存器上下文,即可实现 “进程内多执行流”。

1-3 线程的优点

相比进程,线程具备以下优势:

  1. 创建开销小:线程共享进程的地址空间、文件描述符等资源,创建时无需重复分配这些资源,仅需初始化栈和寄存器上下文,开销远小于进程。

  2. 切换开销小

    • 线程切换时,虚拟地址空间不变,无需刷新 TLB(页表缓存),仅需切换寄存器和栈。
    • 进程切换需切换地址空间,刷新 TLB,开销是线程切换的数倍。
  3. 资源占用少:线程仅需独立的栈和少量控制结构,相比进程(需完整的地址空间、文件描述符表等),资源占用显著减少。

  4. 多核并行:多线程可在多核 CPU 上并行执行,提升计算密集型任务的效率。

  5. IO 与计算重叠:IO 密集型任务中,线程可在等待 IO(如磁盘读写、网络传输)时,让其他线程继续执行计算,提升整体吞吐量。

1-4 线程的缺点

  1. 性能损失:若计算密集型线程数超过 CPU 核心数,线程切换(上下文切换)会产生额外开销,导致整体性能下降。

  2. 健壮性降低:线程共享进程资源,一个线程的错误(如野指针、除零)可能导致整个进程崩溃,缺乏进程级的隔离性。

  3. 缺乏访问控制:进程是系统 “访问控制的基本粒度”,线程无法独立设置资源权限(如文件权限、内存权限),一个线程的操作可能影响整个进程。

  4. 编程难度高:多线程需处理竞态条件死锁数据同步等问题,调试难度远高于单线程程序。

1-5 线程异常

线程是进程的 “执行分支”,线程异常会直接导致进程崩溃:

  • 若线程出现 “除零错误”“野指针访问” 等,会触发内核的信号机制(如SIGFPESIGSEGV),最终终止整个进程,进程内所有线程随之退出。

1-6 线程用途

  1. 提升 CPU 密集型任务效率:多线程可在多核 CPU 上并行计算,将大任务拆分为多个子任务,充分利用 CPU 资源。

  2. 优化 IO 密集型任务体验:如 “边下载文件边显示进度”,IO 线程等待网络 / 磁盘时,UI 线程可继续响应用户操作,提升交互体验。

总结

  • 线程本质:进程内的轻量级执行流,共享进程地址空间,独立维护执行上下文。
  • 内存基础:分页式虚拟内存管理让线程可高效共享进程资源,同时通过页表、TLB、缺页异常保证内存访问的灵活性与效率。
  • 适用场景:CPU 密集型任务(多核并行)、IO 密集型任务(IO 与计算重叠),但需权衡线程切换开销与同步复杂度。

2. Linux 进程 VS 线程:资源共享与独占的边界

进程与线程的核心差异在于资源分配与调度粒度:进程是资源分配的基本单位,线程是调度的基本单位。线程作为进程内的执行流,共享进程的大部分资源,但也拥有独立的私有数据以保证执行独立性。

2-1 进程与线程的核心定位

  • 进程:操作系统进行资源分配的基本单位(如内存、文件描述符、用户 ID 等),进程间相互独立,拥有各自的地址空间。
  • 线程:操作系统进行调度的基本单位(CPU 时间片分配的对象),线程依附于进程存在,共享进程的资源。

2-2 线程的私有资源(独占)

线程作为独立的执行流,需要维护自身的执行状态,因此拥有以下私有资源

  1. 线程 ID(TID)标识线程的唯一编号(类似进程 ID,但仅在进程内唯一),用于内核调度和线程管理。

  2. 寄存器上下文包括程序计数器(PC,记录下一条指令地址)、栈指针(SP)、通用寄存器等,用于线程切换时保存和恢复执行状态。

  3. 线程栈独立的栈空间(默认 8MB,可调整),用于存储局部变量、函数调用参数和返回地址,避免多线程执行时栈数据冲突。

  4. errno 变量记录线程执行系统调用时的错误码(线程私有,避免多线程操作同一全局errno导致的混乱)。

  5. 信号屏蔽字线程可独立设置对某些信号的屏蔽(如sigprocmask),不影响其他线程的信号处理。

  6. 调度优先级线程有独立的调度优先级(如nice值),内核根据优先级分配 CPU 时间片。

2-3 线程共享的进程资源

线程属于进程的一部分,天然共享进程的大部分资源,这是线程轻量性的核心原因:

  1. 地址空间

    • 共享代码段(Text Segment):进程的函数可被所有线程调用。
    • 共享数据段(Data Segment)和堆(Heap):全局变量、静态变量、动态分配的内存(malloc/new)可被所有线程访问。
  2. 文件描述符表进程打开的文件、套接字等描述符对所有线程可见,线程关闭一个描述符会影响其他线程。

  3. 信号处理方式进程对信号的处理动作(忽略SIG_IGN、默认SIG_DFL、自定义函数)是全局的,所有线程共享(但线程可独立屏蔽信号)。

  4. 当前工作目录进程的工作目录由所有线程共享,一个线程调用chdir会改变所有线程的工作目录。

  5. 用户 ID(UID)和组 ID(GID)线程共享进程的用户身份,权限检查基于进程的 UID/GID,而非线程。

  6. 其他进程级资源如进程组 ID(PGID)、会话 ID(SID)、计时器、信号量等。

2-4 进程与线程的关系图示

2-5 对 “单进程” 的重新理解

之前学习的 “单进程” 本质是只包含一个线程的进程(主线程)。该进程的所有资源由主线程独占,执行流单一,无需考虑多线程同步问题。

总结

  • 核心差异:进程是资源容器,线程是执行流。线程共享进程资源以减少开销,同时通过私有资源保证独立调度。
  • 共享资源:地址空间、文件描述符、信号处理、工作目录等进程级资源。
  • 私有资源:线程 ID、寄存器、栈、errno、信号屏蔽字、优先级等执行相关状态。
  • 设计意义:线程的共享性降低了进程间通信成本,私有性保证了调度独立性,适合并发任务处理。
http://www.dtcms.com/a/454806.html

相关文章:

  • 网站做5年有多少流量网站关键词如何布局
  • H5网站开发工程师网站建设网站形象
  • 狮岭做包包的网站优秀网站推荐
  • Python chr() 函数
  • wordpress网站文章排版插件镇海建设银行网站
  • 用cms建网站ps网站首页设计图制作教程
  • wordpress 浮动播放器seo工作前景如何
  • wordpress做什么网站好网站推广策略有哪些
  • 昆山外贸公司网站建设流程国内做网站哪家公司好
  • 沧州各种网站wordpress首页循环
  • [Java]PTA:(选做) jmu-Java-03面向对象基础-clone方法、标识接口、深拷贝
  • 酒店网站建设考虑的因素wordpress手机版切换
  • Makefile快速入门1
  • 网站信息架构图怎么做阿里巴巴网站维护要怎么做
  • 企业网站网络营销婚礼婚庆网站建设需求分析
  • C4D组域及其他常见的8种域:深度解析与应用指南
  • 网站建设内容3000字网站制作群系统
  • 一个公司多个网站做优化北京餐饮网络营销公司
  • 自建网站有哪些营销培训心得
  • 用js做的网站代码吗山东德州网站建设哪家最好
  • Gorm学习笔记 - CRUD记要
  • 参股长江存储(长存集团)的公司
  • 写作网站官方做房地产公司网站的费用
  • JAVA算法练习题day28
  • 如何在谷歌做网站外链网络公关的作用
  • 医院网站规划方案手机网站开发最好用的框架
  • 快速排名优化怎么样郑州企业网站优化服务哪家好
  • 公司网站 制作wordpress 关键词设置
  • 无锡做网站服务wordpress 4.5.2 编辑器插件
  • 营销型网站单页wordpress页面的添加