【原理】线程的属性与特征分析
线程概念的提出是计算机系统的技术发展和操作系统对进程管理优化过程的自然产物。随着计算机处理能力的提高,内存容量的加大,在一个计算机系统中会存在大量的进程,为了提高整个系统的执行效率,需要进程间能够进行简洁高效的数据共享和进程切换,进程创建和进程退出。这样就会产生一个自然的想法:能否改进进程模型,提供一个简单的数据共享机制,能否加快进程管理(特别是进程切换)的速度?再仔细看看进程管理的核心数据结构进程控制块和处理的流程,就可以发现,在某种情况下,进程的地址空间隔离不一定是一个必须的需求。假定进程间是可以相互“信任”的(即进程间是可信的),那么我们就不必需要地址空间隔离,而是让这些相互信任的进程共用(共享)一个地址空间。这样一下子就解决上述两个问题:在一个地址空间内,一个进程对某内存单元的修改(即写内存单元操作)可以让其他进程马上看见(即读内存单元操作),这是共享地址空间带来的天然好处;另外由于进程共享了地址空间,所以在创建进程或回收进程的时候,只要不是相互信任的进程组的第一个或最后一个,就没必要再创建一个地址空间或回收地址空间,节省了创建进程和退出进程的执行开销;而且对于频繁发生的进程切换操作而言,由于不需要切换页表,所以TLB中缓存的虚拟地址—物理地址映射关系(页表项的缓存)不必清除或失效,减少了进程切换的开销。
为了区别已有的进程概念,我们把这些共享资源的进程称为线程。从而把进程的概念进行了细化。原有的进程概念缩小为资源管理的最小单位,而线程是指令执行控制流的最小单位。且线程属于进程,是进程的一部分。一个进程至少需要一个线程作为它的指令执行单元,进程管理主要是资源(如内存空间等)分配、使用和回收的管理,而线程管理主要是指令执行过程和切换过程的管理。一个进程可以拥有多个线程,而这些线程共享其所属进程所拥有的资源。这样,采用多线程模型来设计应用程序,可以使得程序的执行效率也更高。
从执行线程调度时CPU所处特权级角度看,有内核级线程模型和用户级线程模型两种线程模型。内核级线程模型由操作系统在核心态进行调度,每个线程有对应的进程控制块结构。用户级线程模型有用户态的线程管理库在用户态进行调度,操作系统不能“感知”到这样的线程存在,所以也就没有对应进程控制块来描述它。相对而言,由于用户级线程模型在执行线程调度切换时不需从用户态转入核心态,开销相对较小,而内核级线程模型虽然开销相对较大,但由于操作系统直接负责管理,所以在执行的灵活性上由于用户级线程模型。比如用户级线程模型中某线程执行系统调用而可能被操作系统阻塞,这会引起同属于一个进程的其他线程都被阻塞。但内核级线程模型不会有这种情况后发生。这两种线程模型还可以结合在一起形成一种“混合”线程模型。“混合”线程模型通常都能带来更高的效率,但也带来更大的实现难度和实现代价。ucore出于“简单”的设计思路,参考Linux实现了内核级线程模型。
从线程执行时CPU所处特权级角度看,有内核线程和用户线程之分,内核线程共享操作系统内核运行过程中的所有资源,最主要的就是内核虚拟地址空间,但没有内核线程有各自独立的核心栈,且没有用户态的地址空间。用户线程共享属于同一用户进程的所有资源,最主要的就是用户虚拟地址空间,所以同享同一用户进程的进程控制块所描述的一个页表和一个内存管理数据结构。接下来我们看看ucore中如何具体实现用户线程这个概念。