(王道408考研操作系统)第二章进程管理-第一节5:线程概念和多线程模型

Posted 快乐江湖

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(王道408考研操作系统)第二章进程管理-第一节5:线程概念和多线程模型相关的知识,希望对你有一定的参考价值。

一:引导

  • 注意以下的task_struct是Linux中的PC
  • 可以观看下面的视频有一个大致的了解

【操作系统】进程和线程的区别


前面说过,创建一个进程通常会包含以下操作

  • 创建进程所需要的一系列数据结构(比如经典的task_struct,mm_struct,也就是地址空间等)
  • 为它开辟物理内存,把代码和数据加载进物理内存
  • 创建页表,负责映射
  • ········

如果再创建一个进程,无非就是重复上面的操作而已,也就是说我们创建进程的时候就是从0到1创建了很多很多的东西。

如果有三个进程,那么这三个进程分别各自有自己的地址空间,如果让第二个和第三个进程同时指向第一个进程的地址空间,也就是说这三个进程享有同一份地址空间,如下

接着我们这份地址空间的代码区和数据段一分为三,让这三个进程分别访问代码区和数据段中的某一块

这样一来在进程1的地址空间,或者通俗点说在一个main函数内就会出现三个执行流,因此现在我们对进程的认识应该有所变化了,现在对于进程的概念不应该只是我们以前认识的那个单独的task_struct上图中三个部分组成的整体叫做进程,每个之前的所谓的“进程”不过就是这个整体的真正的进程的一个执行流

二:区别“进程”、“线程”和“轻量级进程”

(1)进程和线程的关系

从上面的讲述中大家可以发现在,进程它实则就是承担分配系统资源的实体,而像之前所认识到的那些task_struct无非就是运行在这些资源上的一个执行流,CPU进行调度时其最小单位就是这些执行流,所以我们这些执行流称之为线程

所以线程是进程的一个执行流,线程在进程的地址空间内,所有线程使用的是一个地址空间,他们之间的关系是1:n,因此之前我们说到的进程其实就是只有一个执行流(或者说只有一个线程)的进程

(2)Linux中没有真正意义上的线程

操作系统管理遵循的原则就是先描述,再组织,从之前的学习我们可以看到,只要涉及数量多,关系复杂操作,操作系统就一定会有对应的数据结构进行管理,那么既然进程和线程的关系是1:n,而进程都被操作系统管理了,那么线程也应该有一定的数据结构进行管理才对这样的想法是正确的,但是在Linux中却没有像Windows中那样真实的数据结构来对线程管理,它是用进程模拟线程的

为线程专门创建数据结构其实从效率上讲不是特别的好,因为线程的数量往往是大于进程的,这样一来这样的数据结构不止要维护线程和线程的关系,还要维护线程和进程的关系,结构越是复杂,效率就越低

所以在Linux在设计多线程时,考虑到:既然进程和线程都是为了被调度,具有相同的属性,那么为什么需要再设计另外的数据结构呢?所以Linux中就用进程模拟线程,依旧采用task_struct表示线程,如果有一个task_struct就表示这是有一个执行流的进程,如果有多个task_struct就表示这是有多个执行流的进程。

(3)轻量级进程-LWP

所以在Linux中,所有的线程实则挂靠的是相同的地址空间。在Linux中“没有进程,也没有线程”,你所看到的task_struct只不过是一个轻量级的进程(LWP),它轻是因为可能有多其他的task_struct与它挂靠同一份地址空间,它也可以变的很重,是因为有可能它自己独享一份地址空间。从内核角度上看,它调度的基本单位是线程,也就是LWP


需要注意的是虽然是进程模拟线程,但是在Linux中仍然会有一些数据结构去维护这些信息,但是这样的结构体并不是真正意义上的专门维护线程的结构体,类似于thread_control_block(TCB)

三:线程的优缺点

(1)优点

  • 创建一个新线程的代价要比创建一个新进程小得多
  • 与进程之间的切换相比,线程之间的切换需要操作系统做的工作比较少
  • 线程占用的资源要比进程少得多
  • 能充分利用多处理器的可并行数量
  • 在等待慢速I/O操作结束的同时,程序可执行其他的计算任务
  • 计算密集型应用,为了能在多处理器系统上运行,将计算分解到多个线程中实现
  • I/O密集型应用,为了提高性能,将I/O操作重叠。线程可以同时等待不同的I/O操作。

(2)缺点

  • 性能损失:一个很少被外部事件阻塞的计算密集型线程往往无法与共它线程共享同一个处理器。如果计算密集型线程的数量比可用的处理器多,那么可能会有较大的性能损失,这里的性能损失指的是增加了额外的同步和调度的开销,而可用的资源不变
  • 健壮性降低:编写多线程需要更全面更深入的考虑,一个多线程程序里,因时间分配上的细微偏差或因共享了不该共享的变量而造成不良影响的可能性是很大的,或者说线程是缺乏保护的(比如假如一个线程发生了除0错误,那么所有线程将会全部退出。因为线程是进程的执行分支,线程出现异常,其实进程也就出现了异常,从而触发了信号机制,终止进程,而进程一旦终止,资源都没有了,所以所有线程将会全部退出
  • 缺乏访问控制:进程是访问控制的基本粒度,在一个线程中调用某些系统调用函数会对整个进程造成影响
  • 编程难度提高:编写与调试(尤其是调试)一个多线程程序比单线程程序困难得多

四:线程vs进程

  • 引入进程:为了更好地使多道程序并发执行,提高资源利用率和系统的吞吐量
  • 引入线程:为了减小程序在并发执行时所付出的时空开销,提高操作系统的并发性能

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

1:线程共享进程数据,但是也有自己的一部分数据

  • 线程ID
  • 一组寄存器(硬件上下文)
  • errno
  • 信号屏蔽字
  • 调度优先级

2:进程的多个线程共享地址空间,因此文本段,数据段都是共享的,所以一个全局变量多个线程都可以访问。除此之外,以下资源也是共享的

  • 文件描述符表
  • 每种信号的处理方式
  • 当前工作目录
  • 用户ID和组ID

3:进程和线程的关系可以用下面的图概括

五:线程实现方式

以上是关于(王道408考研操作系统)第二章进程管理-第一节5:线程概念和多线程模型的主要内容,如果未能解决你的问题,请参考以下文章

(王道408考研操作系统)第二章进程管理-第一节4:进程通信(配合Linux)

(王道408考研操作系统)第二章进程管理-第一节3:进程控制(配合Linux讲解)

(王道408考研操作系统)第二章进程管理-第一节1:进程PCB及其特征

专栏必读王道考研408操作系统万字笔记(有了它不需要你再做笔记了):各章节内容概述导航和思维导图

(王道408考研操作系统)第三章内存管理-第一节7:非连续分配管理方式之基本分段管理方式

(王道408考研操作系统)第三章内存管理-第一节7:非连续分配管理方式之基本分段管理方式