320 likes | 523 Views
第二章 进程管理. 2.6 线程. 线程的基本概念. 线程的引入 如果说,在操作系统中引入进程的目的,是为了使多个程序能并发执行,以提高资源利用率和系统吞吐量,那么,在操作系统中再引入线程,则是为了减少程序在并发执行时所付出的时空开销,使 OS 具有更好的并发性。 若能将进程的上述两个属性分开,由操作系统分开处理,亦即对于作为调度和分派的基本单位,不同时作为拥有资源的单位,以做到“轻装上阵”;而对于拥有资源的基本单位,又不对之进行频繁的切换。正是在这种思想的指导下,形成了线程的概念。. 线程与进程的比较 1) 调度
E N D
第二章 进程管理 2.6 线程
线程的基本概念 • 线程的引入 如果说,在操作系统中引入进程的目的,是为了使多个程序能并发执行,以提高资源利用率和系统吞吐量,那么,在操作系统中再引入线程,则是为了减少程序在并发执行时所付出的时空开销,使OS具有更好的并发性。 若能将进程的上述两个属性分开,由操作系统分开处理,亦即对于作为调度和分派的基本单位,不同时作为拥有资源的单位,以做到“轻装上阵”;而对于拥有资源的基本单位,又不对之进行频繁的切换。正是在这种思想的指导下,形成了线程的概念。
线程与进程的比较 1) 调度 在传统的操作系统中,作为拥有资源的基本单位和独立调度、分派的基本单位都是进程。而在引入线程的操作系统中,则把线程作为调度和分派的基本单位,而进程作为资源拥有的基本单位,把传统进程的两个属性分开,使线程基本上不拥有资源,这样线程便能轻装前进,从而可显著地提高系统的并发程度。在同一进程中,线程的切换不会引起进程的切换,但从一个进程中的线程切换到另一个进程中的线程时,将会引起进程的切换。
2)并发性 在引入线程的操作系统中,不仅进程之间可以并发执行,而且在一个进程中的多个线程之间亦可并发执行,使得操作系统具有更好的并发性,从而能更加有效地提高系统资源的利用率和系统的吞吐量。 3)拥有资源 不论是传统的操作系统,还是引入了线程的操作系统,进程都可以拥有资源,是系统中拥有资源的一个基本单位。一般而言,线程自己不拥有系统资源(也有一点必不可少的资源),但它可以访问其隶属进程的资源,即一个进程的代码段、数据段及所拥有的系统资源。
4)系统开销 在创建或撤消进程时,系统都要为之创建和回收进程控制块,分配或回收资源,操作系统所付出的开销明显大于线程创建或撤消时的开销。一个进程中的多个线程具有相同的地址空间,在同步和通信的实现方面线程也比进程容易。在一些操作系统中,线程的切换、同步和通信都无须操作系统内核的干预。
线程的属性 在多线程OS中,通常是在一个进程中包括多个线程,每个线程都是作为利用CPU的基本单位,是花费最小开销的实体。线程具有下述属性。 (1)轻型实体。线程中的实体基本上不拥有系统资源,只是有一点必不可少的、 能保证其独立运行的资源。 (2)独立调度和分派的基本单位。在多线程OS中,线程是能独立运行的基本单位,因而也是独立调度和分派的基本单位。由于线程很“轻”,故线程的切换非常迅速且开销小。
(3)可并发执行。在一个进程中的多个线程之间可以并发执行,甚至允许在一个进程中的所有线程都能并发执行;同样,不同进程中的线程也能并发执行。 (4)共享进程资源。在同一进程中的各个线程都可以共享该进程所拥有的资源,这首先表现在所有线程都具有相同的地址空间(进程的地址空间)。这意味着线程可以访问该地址空间中的每一个虚地址;此外,还可以访问进程所拥有的已打开文件、定时器、信号量机构等。
线程的状态 (1)状态参数。在OS中的每一个线程都可以利用线程标识符和一组状态参数进行描述。状态参数通常有这样几项: ① 寄存器状态 ② 堆栈 ③ 线程运行状态 ④ 优先级 ⑤ 线程专有存储器 ⑥ 信号屏蔽,即对某些信号加以屏蔽
(2) 线程运行状态。线程在运行时也具有下述三种基本状态: ① 执行状态,表示线程正获得处理机而运行; ② 就绪状态,指线程已具备了各种执行条件,一旦获得CPU便可执行的状态; ③ 阻塞状态,指线程在执行中因某事件而受阻,处于暂停执行时的状态。
线程的创建和终止 在多线程OS环境下,应用程序在启动时,通常仅有一个线程在执行,该线程被人们称为“初始化线程”。它可根据需要再去创建若干个线程。在创建新线程时,需要利用一个线程创建函数(或系统调用),并提供相应的参数。 终止线程的方式有两种:一种是在线程完成了自己的工作后自愿退出;另一种是线程在运行中出现错误或由于某种原因而被其它线程强行终止。
多线程OS中的进程 在多线程OS中,进程是作为拥有系统资源的基本单位,通常的进程都包含多个线程并为它们提供资源,但此时的进程就不再作为一个执行的实体。多线程OS中的进程有以下属性: (1)作为系统资源分配的单位。 (2)可包括多个线程。 (3)进程不是一个可执行的实体。
线程间的同步和通信 • 互斥锁(mutex) 互斥锁是一种比较简单的、用于实现线程间对资源互斥访问的机制。由于操作互斥锁的时间和空间开销都较低,因而较适合于高频度使用的关键共享数据和程序段。互斥锁可以有两种状态,即开锁(unlock)和关锁(lock)状态。相应地,可用两条命令(函数)对互斥锁进行操作。其中的关锁lock操作用于将mutex关上,开锁操作unlock则用于打开mutex。
条件变量 在许多情况下,只利用mutex来实现互斥访问可能会引起死锁,为了解决这个问题便引入了条件变量。每一个条件变量通常都与一个互斥锁一起使用,亦即,在创建一个互斥锁时便联系着一个条件变量。单纯的互斥锁用于短期锁定,主要是用来保证对临界区的互斥进入。而条件变量则用于线程的长期等待,直至所等待的资源成为可用的资源。
信号量机制 1)私用信号量(private samephore) 当某线程需利用信号量来实现同一进程中各线程之间的同步时,可调用创建信号量的命令来创建一私用信号量,其数据结构存放在应用程序的地址空间中。私用信号量属于特定的进程所有,OS并不知道私用信号量的存在,因此,一旦发生私用信号量的占用者异常结束或正常结束,但并未释放该信号量所占有空间的情况时,系统将无法使它恢复为0(空),也不能将它传送给下一个请求它的线程。
2)公用信号量(public semaphort) 公用信号量是为实现不同进程间或不同进程中各线程之间的同步而设置的。由于它有着一个公开的名字供所有的进程使用,故而把它称为公用信号量。其数据结构是存放在受保护的系统存储区中,由OS为它分配空间并进行管理,故也称为系统信号量。如果信号量的占有者在结束时未释放该公用信号量,则OS会自动将该信号量空间回收,并通知下一进程。可见,公用信号量是一种比较安全的同步机制。
线程的实现方法 • 内核支持线程 内核支持线程KST(Kernel Supported Threads),是在内核的支持下运行的,即无论是用户进程中的线程,还是系统进程中的线程,他们的创建、撤消和切换等也是依靠内核,在内核空间实现的。此外,在内核空间还为每一个内核支持线程设置了一个线程控制块,内核是根据该控制块而感知某线程的存在,并对其加以控制。
这种线程实现方式主要有如下四个优点: (1)在多处理器系统中,内核能够同时调度同一进程中多个线程并行执行; (2)如果进程中的一个线程被阻塞了,内核可以调度该进程中的其它线程占有处理器运行,也可以运行其它进程中的线程; (3)内核支持线程具有很小的数据结构和堆栈,线程的切换比较快,切换开销小; (4)内核本身也可以采用多线程技术,可以提高系统的执行速度和效率。
内核支持线程的主要缺点是:对于用户的线程切换而言,其模式切换的开销较大,在同一个进程中,从一个线程切换到另一个线程时,需要从用户态转到内核态进行,这是因为用户进程的线程在用户态运行,而线程调度和管理是在内核实现的,系统开销较大。内核支持线程的主要缺点是:对于用户的线程切换而言,其模式切换的开销较大,在同一个进程中,从一个线程切换到另一个线程时,需要从用户态转到内核态进行,这是因为用户进程的线程在用户态运行,而线程调度和管理是在内核实现的,系统开销较大。
用户级线程 用户级线程ULT(User Level Threads)仅存在于用户空间中。对于这种线程的创建、撤消、线程之间的同步与通信等功能,都无须利用系统调用来实现。对于用户级线程的切换,通常发生在一个应用进程的诸多线程之间,这时,也同样无须内核的支持。由于切换的规则远比进程调度和切换的规则简单,因而使线程的切换速度特别快。可见,这种线程是与内核无关的。我们可以为一个应用程序建立多个用户级线程。在一个系统中的用户级线程的数目可以达到数百个至数千个。由于这些线程的任务控制块都是设置在用户空间,而线程所执行的操作也无须内核的帮助,因而内核完全不知道用户级线程的存在。
使用用户级线程方式的主要优点: (1)线程切换不需要转换到内核空间,对一个进程而言,其所有线程的管理数据结构均在该进程的用户空间中,管理线程切换的线程库也在用户地址空间运行。因此,进程不必切换到内核方式来做线程管理,从而节省了模式切换的开销,也节省了内核的宝贵资源。 (2)调度算法可以是进程专用的。在不干扰操作系统调度的情况下,不同的进程可以根据自身需要,选择不同的调度算法对自己的线程进行管理和调度,而与操作系统的低级调度算法是无关的。 (3)用户级线程的实现与操作系统平台无关,因为对于线程管理的代码是在用户程序内的,属于用户程序的一部分,所有的应用程序都可以对之进行共享。因此,用户级线程甚至可以在不支持线程机制的操作系统平台上实现。
用户级线程实现方式的主要缺点在于如下两个方面:用户级线程实现方式的主要缺点在于如下两个方面: (1)系统调用的阻塞问题。在基于进程机制的操作系统中,大多数系统调用将阻塞进程,因此,当线程执行一个系统调用时,不仅该线程被阻塞,而且进程内的所有线程都会被阻塞。而在内核支持线程方式中,则进程中的其它线程仍然可以运行。 (2)在单纯的用户级线程实现方式中,多线程应用不能利用多处理机进行多重处理的优点。内核每次分配给一个进程的仅有一个CPU,因此进程中仅有一个线程能执行,在该线程放弃CPU之前,其它线程只能等待。
组合方式 有些操作系统把用户级线程和内核支持线程两种方式进行组合,提供了组合方式ULT/KST 线程。在组合方式线程系统中,内核支持多KST线程的建立、调度和管理,同时,也允许用户应用程序建立、调度和管理用户级线程。一些内核支持线程对应多个用户级线程,程序员可按应用需要和机器配置对内核支持线程数目进行调整,以达到较好的效果。组合方式线程中,同一个进程内的多个线程可以同时在多处理器上并行执行,而且在阻塞一个线程时,并不需要将整个进程阻塞。所以,组合方式多线程机制能够结合KST和ULT两者的优点,并克服了其各自的不足。
线程的实现 • 内核支持线程的实现 在仅设置了内核支持线程的OS中,一种可能的线程控制方法是,系统在创建一个新进程时,便为它分配一个任务数据区PTDA(Per Task Data Area),其中包括若干个线程控制块TCB空间。在每一个TCB中可保存线程标识符、优先级、线程运行的CPU状态等信息 图 2-15 任务数据区空间
每当进程要创建一个线程时,便为新线程分配一个TCB,将有关信息填入该TCB中,并为之分配必要的资源,在撤消一个线程时,也应回收该线程的所有资源和TCB。可见,内核支持线程的创建、 撤消均与进程的相类似。 内核支持线程的调度和切换与进程的调度和切换十分相似,也分抢占式方式和非抢占方式两种。在线程的调度算法上,同样可采用时间片轮转法、优先权算法等。当线程调度选中一个线程后,便将处理机分配给它。当然,线程在调度和切换上所花费的开销,要比进程的小得多。
用户级线程的实现 用户级线程是在用户空间实现的。所有的用户级线程都具有相同的结构,它们都运行在一个中间系统的上面。当前有两种方式实现的中间系统,即运行时系统和内核控制线程。 1)运行时系统(Runtime System) 所谓“运行时系统”,实质上是用于管理和控制线程的函数(过程)的集合,其中包括用于创建和撤消线程的函数、 线程同步和通信的函数以及实现线程调度的函数等。正因为有这些函数,才能使用户级线程与内核无关。运行时系统中的所有函数都驻留在用户空间,并作为用户级线程与内核之间的接口。
2)内核控制线程 这种线程又称为轻型进程LWP(Light Weight Process)。每一个进程都可拥有多个LWP,同用户级线程一样,每个LWP都有自己的数据结构(如TCB),其中包括线程标识符、优先级、状态,另外还有栈和局部存储区等。它们也可以共享进程所拥有的资源。LWP可通过系统调用来获得内核提供的服务,这样,当一个用户级线程运行时,只要将它连接到一个LWP上,此时它便具有了内核支持线程的所有属性。这种线程实现方式就是组合方式。 在一个系统中的用户级线程数量可能很大,为了节省系统开销,不可能设置太多的LWP,而把这些LWP做成一个缓冲池,称为“线程池”。
当用户级线程不需要与内核通信时,并不需要LWP;而当要通信时,便需借助于LWP,而且每个要通信的用户级线程都需要一个LWP。当用户级线程不需要与内核通信时,并不需要LWP;而当要通信时,便需借助于LWP,而且每个要通信的用户级线程都需要一个LWP。 在内核级线程执行操作时,如果发生阻塞,则与之相连接的多个LWP也将随之阻塞,进而使连接到LWP上的用户级线程也被阻塞。
用户级线程与内核控制线程的连接 1) 一对一模型 该模型是为每一个用户线程都设置一个内核控制线程与之连接,当一个线程阻塞时,允许调度另一个线程运行。在多处理机系统中,则有多个线程并行执行。 该模型并行能力较强,但每创建一个用户线程相应地就需要创建一个内核线程,开销较大,因此需要限制整个系统的线程数。Windows 2000、Windows NT、OS/2等系统上都实现了该模型。
2)多对一模型 该模型是将多个用户线程映射到一个内核控制线程,为了管理方便,这些用户线程一般属于一个进程,运行在该进程的用户空间,对这些线程的调度和管理也是在该进程的用户空间中完成。当用户线程需要访问内核时,才将其映射到一个内核控制线程上,但每次只允许一个线程进行映射。 该模型的主要优点是线程管理的开销小,效率高,但当一个线程在访问内核时发生阻塞,则整个进程都会被阻塞,而且在多处理机系统中,一个进程的多个线程无法实现并行。
3)多对多模型 该模型结合上述两种模型的优点,将多个用户线程映射到多个内核控制线程,内核控制线程的数目可以根据应用进程和系统的不同而变化,可以比用户线程少,也可以与之相同。
作业: 2、6、9、13、14、18、34、36、38、39