在上一篇文章讲到了进程,进程体现了两个属性资源分配的单位和调度运行的单位,作为资源分配的单位,一个进程有自己的地址空间,其中包括程序、数据、PCB及其他资源,如打开的文件,子进程,未处理的警报,信号,统计信息等。作为调度执行单位,一个进程在执行过程中需要使用一个或多个程序;另外,一个进程的执行过程会与其他进程夹在一起。操作系统根据进程的状态和调度优先级对就绪进程实施调度。由于进程是资源的拥有者,所以它的负载很重,因而在实施进程的创建、删除和切换过程中要付出较大的开销。这样,就限制了系统中进程的数目和并发活动程度,因此很多现代操作系统把上述进程的两个属性分别赋予不同的实体:进程只作为资源的拥有者,而调度和运行的属性赋予新的实体---线程。
线程的组成
每一个线程有一个thread结构,即线程控制块,用于保存自己的私有信息,其组成如下:
- 一个唯一的线程标识符
- 描述处理器工作情况的一组寄存器(PC,状态寄存器,通用寄存器)的内容
- 每个thread结构有两个栈指针,一个指向核心栈,一个指向用户栈。当用户线程转变到核心态方式下运行时,就用核心栈;当线程在用户态下执行时,就使用自己的用户栈
- 一个私有存储区,存放现场保护信息和其他与该线程相关的统计信息等
线程必须在某个进程内执行,它所需的其他资源,如代码段,数据段,打开的文件和信号等,都由它所属的进程拥有,即:操作系统分配这些资源以进程为单位。传统的进程就是只有一个线程的进程,当一个进程包含多个线程时,这些线程除了自己私有的少量的资源外,要共享所属进程的全部资源。
线程的状态
与进程相似,线程也有若干种状态,如运行态,阻塞状态,就绪状态和终止状态。
线程是一个动态过程。它的状态转换是在一定条件下实现的。通常,当一个新进程创建时,该进程的一个线程也被创建。以后这个线程还可以在它所属的进程内创建另外一个线程,为新线程提供指令指针和参数。同时为新线程提供私有的寄存器内容和栈空间,并且放入就绪队列中。当CPU空闲时,线程调度程序就从就绪队列中选择一个线程,令其投入运行。线程在运行过程中如果需要等待某个事件,它就让出CPU,进入阻塞状态。以后,当该事件发生时,这个线程就从阻塞状态变为就绪状态。
线程的管理
- 线程的创建:一个线程通过调用过程库中的thread_create可以创建新线程。创建新线程时将为新线程建立thread结构,分配栈空间。最后把它设置为就绪状态,放入就绪队列。
- 线程的终止:一个线程完成自己的工作后,通过调用过程库中的thread_exit终止自身。
- 线程的等待:在某些线程系统中,一个线程通过调用过程库中的thread_wait可以等待指定线程终止。这个过程使调用者线程变为阻塞状态,直至指定的线程终止,它才转为就绪状态
- 线程的让权:当一个线程自愿放弃CPU资源,让给另外的线程运行时,它可调用过程thread_yield
线程与进程的关系
- 一个进程可以有多个线程,但至少要有一个线程;并且一个线程只能在一个进程的地址空间内活动
- 资源分配给进程,同一个进程的所有线程共享该进程的所有资源
- 处理机分配给线程,即真正在处理机上运行的是线程
- 线程在执行过程中需要协作同步,不同进程的线程间要利用消息通信的办法实现同步
引入线程的好处
- 易于调度,在传统的进程中,由于资源分配与运行调度都是进程,因为在进程的创建、撤销和切换过程中,系统必须为之付出很大的时空开销。而线程属于轻量级的进程,它的切换时空消耗比进程小。
- 提高并发性,进程可以创建多个线程来执行同一程序的不同部分,这样,不仅进程之间可以并发执行,而且同一个进程内部的多个线程也可以并发执行
- 开销小,创建线程比创建进程要快
- 充分发挥多处理器的功能,传统的进程只能运行在但处理机上,使用多线程的进程可以运行在多处理机上
线程的实现
- 线程库整个地址放在用户空间,核心对线程一无所知。所以核心只关心对常规进程进行管理,并不知道线程是否存在。管理线程的工作全部由应用程序来完成
- 优点
- 线程切换速度很快,无需进程系统调度,这比使用系统调度线程并陷入核心去处理线程要快得多
- 调度算法可以由应用程序专用,允许不同应用程序采用何时自己要求的不同调度算法,并且不干扰底层的操作系统调度程序
- 用户级别线程可以运行在任何操作系统上
- 缺点
- 系统调度的阻塞问题,多数系统调用是阻塞式的,当一个线程执行系统调度时,不仅它自己被阻塞,而且在用一个进程内部的所有线程都会被阻塞
- 不具有多处理器同时运行的优点,因为核心只为每个进程一次分配一个处理器,每次只有该进程的一个线程得以运行,在该进程自愿放弃CPU之前,该进程内的其他线程不会运行。
- 优点
- 在核心空间实现线程,在这种方式下,核心知道线程的存在,并对它们实施管理。线程表不在每个进程的空间中,而是在核心空间中。线程表中记载系统中所有线程的情况。当一个线程想创建一个新线程或删除一个现有线程时,必须执行系统调用,后者通过更新核心空间的线程表来完成上述工作。另外,核心空间除了保存一个线程表外,还保存一个传统的进程表,其中记载系统中所有进程的信息。
- 优点:
- 在多处理机上可以同时运行同一个进程中的多个线程
- 如果一个进程的某个线程阻塞了,并不会影响同一个进程中的其他线程
- 缺点:
- 控制转移开销大, 在同一个进程中,把一个线程切换到另一个线程,需要将模式由用户态切换到核心态
- 优点: