Linux 线程概念

Linux 线程概念

  • 1. 什么是线程
  • 2. Linux的进程和线程
  • 3. 虚拟内存与线程创建
  • 4. 进程vs线程
  • 5. 线程的优点和缺点
  • 6. 线程异常

1. 什么是线程

  线程程序执行的最小单位,是进程内的独立执行流。一个进程可以包含多个线程,它们共享大部分资源,包括地址空间、文件和其他系统资源。线程的特点包括最小执行单元、资源共享、轻量级等。在多线程中,线程间可以并发执行,提高程序的效率和响应性。

这里举个例子说明:
想象你是一名大厨,整个厨房是一个进程。任务如炒菜、烧水,代表在进程内部同时执行的不同任务,如果只有一个炉灶时(单线程),你只能一个一个地做事。如果有多个炉灶时(多线程),你可以同时炒菜、烧水,提高效率。线程就像是并行执行厨房任务,共享厨房资源,让整个烹饪过程更高效。

2. Linux的进程和线程

Linux 操作系统中,线程的实现是通过轻量化的进程(Lightweight Process,LWP)来模拟线程的概念。
Linux 线程概念_第1张图片

task_struct 结构体:
Linux 中的每个进程都由一个 task_struct 结构体表示,该结构体包含了进程的各种信息,如进程 ID、状态、寄存器值等。 在内核中,并没有专门的数据结构用于表示线程,而是通过复用 task_struct 结构体来表示线程。

轻量化进程(LWP): Linux 将线程称为轻量化进程,即 LWP。每个轻量化进程都对应一个 task_struct 结构体,表示一个执行流。 多个轻量化进程可以共享相同的地址空间,实现了在进程内部执行流的独立性和轻量性。

Linux线程的实现方式是通过轻量化进程,即共享 task_struct 结构体,共享地址空间,实现了在进程内部执行流的独立性和轻量性。这种实现方式简化了内核的设计,同时在进程和线程之间提供了较高的兼容性。

3. 虚拟内存与线程创建

在操作系统中,每个进程都拥有独立的虚拟地址空间,其中包含用户空间和内核空间。在这个进程内,我们创建线程,将一部分资源分配给线程,以实现并发执行。
Linux 线程概念_第2张图片

  1. 虚拟内存划分
    进程虚拟地址空间: 4 GB的32位地址空间,划分为用户空间和内核空间。
    虚拟地址结构: 32位虚拟地址划分为10位+10位+12位,对应页目录、页表和页内偏移。
    二级页表结构: 通过页目录和页表实现虚拟地址到物理地址的映射。

  2. 线程创建的虚拟内存分配
    虚拟地址共享: 线程在创建时与父线程共享相同的虚拟地址空间,包括代码、数据和栈。
    划分进程资源: 创建线程是将进程一部分资源分配给线程,共享代码段和数据段。
    独立栈空间: 每个线程有独立的栈,用于存储局部变量和函数调用信息。
    共享堆空间: 虚拟内存的堆空间是线程共享的,用于动态内存分配。

  3. 虚拟内存管理与线程
    MMU地址转换: 当线程访问虚拟地址时,MMU负责将其转换为物理地址。
    动态页表更新: 多线程环境下,线程创建可能导致页表的动态更新,确保正常访问共享地址空间。
    线程共享页目录: 每个进程有一个页目录,线程共享该页目录。这意味着线程间共享相同的虚拟地址空间,加强了资源的共享。

这种虚拟内存划分和管理机制使得线程在同一进程内高效运行,通过共享和独立性的平衡,提高了并发性和资源利用率,同时保障了线程之间的数据隔离和同步。

4. 进程vs线程

基本单位
进程是资源分配的基本单位。
线程是调度的基本单位。

共享资源
进程拥有独立的地址空间。
线程共享同一地址空间,包括Text Segment、Data Segment等。

线程私有数据
线程的独立性通过线程私有数据和独立栈实现。线程私有数据包括线线程ID、一组寄存器、栈、errno、信号屏蔽字、调度优先级等,而独立栈为每个线程提供独立存储,确保数据隔离和程序稳定。

资源共享
进程中的多个线程共享大部分资源和环境,如文件描述符表、信号处理方式、当前工作目录、用户id和组id。

切换的轻量化
进程切换: 操作系统在切换进程时需要改变页表、保存和恢复完整的上下文信息,包括通用寄存器、程序计数器等,增加了切换的开销。。
线程切换: 由于线程共享相同的地址空间,切换线程不需要切换页表,使得线程切换更为轻量。线程拥有独立的上下文,包括线程ID、一组寄存器、栈、errno、信号屏蔽字、调度优先级等,独立保存在各自的数据结构中,有效实现了轻量级切换。

页表的角度
进程切换: 进程切换会涉及切换整个页表,因为每个进程都有独立的虚拟地址空间和页表。
线程切换: 由于线程共享相同的虚拟地址空间,线程切换不需要切换页表,减少了从虚拟地址到物理地址的映射开销。

缓存的利用
线程内切换: 由于线程在同一进程内,它们共享相同的代码段和数据段,这使得 CPU 缓存更加有效地利用,因为线程切换时不需要刷新缓存。
进程切换: 进程切换涉及到不同进程的代码和数据段的切换,这可能导致 CPU 缓存的失效,增加了额外的开销。

5. 线程的优点和缺点

线程的优点

创建代价低: 创建一个新线程的代价相比创建一个新进程要小得多。
切换代价低: 线程之间的切换相比进程之间的切换需要的操作系统开销较少。
资源消耗少: 线程占用的资源相比进程较少。
多处理器利用: 能够充分利用多处理器的可并行数量。
异步执行: 在等待慢速I/O操作结束的同时,程序可执行其他计算任务。
任务分解: 对于计算密集型应用,可以将计算任务分解到多个线程中以在多处理器系统上运行。
I/O重叠: 对于I/O密集型应用,线程可以同时等待不同的I/O操作。

线程的缺点

性能损失: 在计算密集型应用中,如果线程数量超过可用处理器数量,可能导致性能损失。
健壮性降低: 编写多线程程序需要更全面的考虑,可能因为共享变量等问题导致健壮性降低。
缺乏访问控制: 在一个线程中调用某些OS函数可能对整个进程产生影响,缺乏细粒度的访问控制。
编程难度提高: 编写和调试多线程程序相比单线程程序更为困难。

6. 线程异常

在多线程应用中,线程异常可能对整个进程产生深远影响。

  1. 线程异常触发信号机制,可能导致整个进程终止。
  2. 为防止异常传播,适当的异常处理和最佳实践至关重要。
  3. 采用异常捕获、线程隔离和合理资源管理是确保进程稳定性的关键。

你可能感兴趣的:(linux,服务器)