操作系统之线程的引入和实现

操作系统之线程

线程的引入

人们在设计多道程序OS时,引入进程的概念,从而解决了单处理机环境下程序并发执行的问题。此后,进程一直作为能拥有资源和独立调度运行的基本单位。知道80年代,人们提出比进程还小的概念——线程,试图通过它来提高程序的并发执行程度,以进一步改善系统的服务质量。

如果说引入进程的概念是为了使多个程序可以并发执行,以提高系统资源的利用率和系统吞吐量,那么引入线程的概念就是为了减少程序在并发执行时所付出的时空开销。

进程的两个基本属性

  1. 进程是可拥有资源的最小独立单位。这里的资源包括存放程序正文、数据的磁盘和内存空间、运行时所需的IO设备、已打开的文件等。
  2. 进程是可独立调度参与运行和分派的基本单位。系统通过PCB感知进程的存在,也可以根据PCB中的消息对进城进行调度:利用PCB保留CPU上下文和恢复进程的执行环境,正是这个特点使得进程成为可接受调度和分派的最小单位;

程序并发所需要的开销

  1. 创建进程,系统在创建一个进程的时候需要分配其所需要的资源以及建立PCB;
  2. 撤销进程,系统在撤销进程时,必须对其所拥有的资源进行回收,然后再撤销其PCB;
  3. 进程切换,系统在对进程进行上下文切换时,需要保留当前进程的CPU环境,然后又设置新进程的CPU环境,因此也需要一些额外的开支;

由此可见,由于进程是一个资源的拥有者,因而在创建、撤销和调度中,系统必须为之付出较大的时空开销,这就限制了系统中所设置进程的数目,而且进程切换也不宜过于频繁,使得进程的并发程度受到限制。

线程——作为调度和分派的基本单位

为使多个程序更好滴并发,同时又减少系统的开销,需要将进程的两个基本属性分开:即调度和分派的基本单位不能同时也是资源拥有的单位,以实现“轻装上阵”。对于拥有资源的基本单位,对其不实施频繁的切换,这样就引出了线程的概念。

线程和进程的对比

线程由于具有很多进程的特点,所以又被称为轻型进程;我们将从调度性、并发性、系统开销和拥有资源等方面对进程和线程进行对比;

  1. 调度和分派的基本单位

    在传统OS中,进程是基本的调度和分派单位,在每次调度时,需要切换上下文,开销较大;引入线程的的OS中,线程是基本的调度和分派单位,线程调度时,仅需保存和设置少量的寄存器内容,切换代价小于进程;同一进程里的线程切换时不会引起进程切换;不同进程的线程切换时,必然引起进程的切换;

  2. 并发性

    引入线程的OS中,不仅进程之间可以并发执行,而且在一个进程中的多个线程也可以并发,这样就进一步提高了OS的并发性,从而更能有效提高系统资源的利用率和系统的吞吐量;

  3. 拥有资源

    进程可以拥有资源,并作为系统中拥有资源的一个基本单位。线程本身并不拥有资源,仅有一些保证能够独立运行的资源,包括控制线程运行的线程控制块TCB、指示被执行指令序列的程序计数器、局部变量和少数状态参数以及返回地址等的一组寄存器和堆栈;线程拥有少量资源,但是线程可以共享进程所拥有的资源。表现在:同一进程的所有线程拥有相同的地址空间,意味着,线程可以访问该地址空间的每一个徐地址;线程可以访问进程拥有的IO设备、打开的文件、定时器、信号量等内存空间;

  4. 独立性

    同一进程中的不同线程之间的独立性要低于不同进程之间的独立性。这是因为为了防止进程之间的相互干扰,每个进程都拥有一个独立的地址空间和其他资源,除了共享全局变量外,不允许其他进程访问。但是同一进程的不同线程通常是为了提高系统的并发性以及进行相互合作而创建的,它们之间所有资源都是共享的:一个线程打开的文件可以被同一进程中的其他线程使用等。

  5. 系统开销

    在创建或者撤销进程时,系统都要为之分配和回收进程控制块、分配和回收其拥有的资源。系统为之付出的代价要远远大于线程创建时付出的开销;类似的,在进行进程切换时,系统开销也高于线程之间的切换;由于同一个进程的多个线程拥有相同的地址空间,所以线程之间的通信、同步和切换都无需操作系统干预,也就方便一些;

  6. 对多处理机系统的支持

    在多处理机系统中,不管有多少处理机,每个进程都只能运行在一个处理机上;但是对于多线程的进程,就可以将一个进程中的多个线程分配到不同的处理机上,使得同一进程可以运行在多个处理机上;

线程的基本状态

同进程类似,线程也具有就绪、执行和阻塞状态,同样也有着类似的状态转化,这里不再赘述;

线程控制块TCB

如同,进程控制块之于进程的意义,系统也为每个线程配置了线程控制块TCB,用于将所有控制和管理线程所需要的信息记录在线程控制块中。其内部结构通常包含:

  1. 线程标记符:每个线程的唯一标记;
  2. 一组寄存器:包括程序计数器、状态寄存器和通用寄存器;
  3. 线程的运行状态:用于描述线程当前处于何种状态,以便对线程进行管理;
  4. 线程优先级:描述程序执行的优先级;
  5. 线程专用存储区:用于记录线程切换时需要记录的信息以及其他相关的统计信息;
  6. 信号屏蔽:记录需要屏蔽的信号;
  7. 堆栈指针:由于线程运行时经常发生过程调用,所以每个线程拥有自己的堆栈,用来在发生过程调用时记录局部变量以及相应的返回地址。通常,TCB中有两个堆栈指针,分别指向用户自己堆栈的栈顶和指向系统核心栈的指针,前者是指当线程运行在用户态时,使用用户自己的用户栈来保存局部变量和返回地址,后者是指当线程运行在系统态时使用系统的核心栈;

多线程环境下的进程属性

  1. 进程是拥有资源的基本单位。在多线程OS中,进程仍然是系统资源分配的基本单位;
  2. 多个线程可以并发执行。通常一个进程拥有多个线程,并为之提供资源及运行环境。在OS中的所有线程都只能属于一个进程;
  3. 进程不再是可执行的基本单位。在多线程OS中,线程是可执行的基本单位。虽然如此,进程仍然具有与执行相关的状态。只是,该状态反应的是其所拥有的线程的状态;

线程的实现

线程在许多系统中都有实现,但是不同系统的实现方式不同,有的系统采用内核支持线程,有的系统采用的是用户级线程;而有的系统同时实现了这两种类型的线程;

内核支持线程(Kernel Supported Threads,KST)

在OS中的所有进程,不管是系统进程还是用户进程,都是在操作系统内核的支持下运行的,与内核关系紧密;而内核支持线程KST同样也是在内核的支持下运行的,它们的创建、撤销、阻塞和切换都是在内核空间实现的。为了对内核进程的管理和控制,在内核空间也为每一个内核线程设置了一个线程控制块。这种实现方式主要有以下四个优点:

  1. 在多处理器系统,内核能够同时调度同一进程中的多个线程并发执行;
  2. 如果一个进程的某个线程被阻塞,内核可以调度该进程的其他线程运行,也可以调度其他进程的线程运行;
  3. 内核支持线程有着较小的数据结构和堆栈,线程的切换比较快,切换开销小;
  4. 内核本身也可以采用多线程技术,可以提高系统的执行速度和效率;

内核支持线程的主要缺点是:对于用户线程的调度,其模式切换开销比较大,在同一个进程中,从一个线程切换到另一个线程时,需要从用户态转到核心态实现,这是因为,线程运行在用户态,而线程调度和管理是在内核实现的,因此系统开销较大;

用户级线程(User Level Threads)

用户级线程是在用户空间实现的,对线程的创建、撤销、通信、同步等功能的实现,无需内核的支持,因而内核完全不知道用户级线程的存在;

值得注意的是,设置了用户级线程的系统,其调度仍是以进程为单位的。这主要体现在调度算法中。例如,A和B两个进程,系统为之分配的时间片是相同的,但是A中只有一个线程,B中有100个线程,那么A中线程的执行时间就是B中线程的100倍。因此,对进程是公平的调度算法,对线程却不一定公平;而如果系统设置的是内核支持线程,那么进程B获得的执行时间就是进程A的执行时间的100倍,而且进程B可使这些进程并发执行;

用户级线程的优点:

  1. 线程切换不需要转到内核空间。对一个进程而言,其所有的线程管理数据结构均在该进程自己的用户空间,管理线程切换的线程库也在用户地址空间运行,从而不需要切换到内核方式来做县城管理,从而节省了模式切换的开销;
  2. 调度算法可以是进程专用的。在不影响OS的调度情况下,进程可以根据自身的需要,选择不同的线程调度算法以实现对自己线程的管理和调度。
  3. 用户级线程的实现是与OS平台无关的。因为对于线程的管理是进程自己掌握的,是属于用户程序的一部分,所有应用程序可以共享这部分代码;

用户级线程的缺点:

  1. 系统调用的阻塞问题。在基于进程机制的OS中,大多数系统调用将阻塞进程,因此,当一个线程执行一个系统调用时,不但该线程被阻塞,该进程的所有线程都会被阻塞;而在内核支持线程中,该进程的其他线程仍然可以运行;
  2. 单纯的用户级线程无法充分利用多处理机系统进行多重处理,内核为进程只分配一个处理机,因此,进程中只有一个线程可以运行,其他线程只能等待;

组合方式

有些OS把用户级线程和内核支持线程这两种方式组合起来,提供组合方式ULT/KST线程。在组合方式线程系统中,内核支持多个内核支持线程的建立、调度和管理,同时也允许用户应用程序建立、调度和管理用户级线程。用户级线程通过分时多路复用内核支持线程来实现内核支持线程与多个用户级线程的对应。组合方式中,同一个进程的多个线程可以在多处理机上并发执行,而且一个线程的阻塞不会引起其他线程阻塞。即组合方式结合了KST和ULT的优点,而克服了各自的不足。由于内核支持线程与用户级线程的连接方式不同,从而形成了三种对应模式:多对一、一对一、多对多;

  1. 多对一模式,即多个用户线程映射到一个内核控制线程;用户线程一般属于一个进城,运行在进程的用户空间,对这些线程的管理和调度也是在该进程的用户空间里完成的。当用户线程需要访问内核时,才将其映射到内核支持线程上,但每次只允许一个线程进行映射。该模式的优点是线程管理开销小,效率高;主要缺点是如果一个线程在访问内核时发生阻塞,那么整个进程都会阻塞;此外,在任何时刻,只有一线程可以访问内核,多个线程不能同时在多个处理机上运行;
  2. 一对一模式,即每一个用户级线程对应一个内核支持线程。该模式的优点是,当一个线程阻塞时,允许调度另一个线程运行,所以它比多对一模式可以提供更好的并发功能。此外,在多处理机系统中,它允许多个线程并发地运行在多处理机系统上。该模式的缺点是,每创建一个用户线程,相应地就需要创建一个内核支持线程,开销比较大,因此会限制整个系统的线程数量;
  3. 多对多模式,即多个用户级线程对应到多个内核支持线程中。该模式中,内核控制线程的数目可以根据进程和系统的不同而变化,该模式结合了上述两种模型的优点,可以使一个进程的多个线程并行地运行在多处理机上,也可以像多对一模型那样,减少线程管理开销和提高效率;

猜你喜欢

转载自blog.csdn.net/slx3320612540/article/details/80740650