? ? 在多道程序环境下,允许多个程序并发执行,此时它们将失去封闭性,并具有间断性及不可再现特性。为此引入了线程(Process)这个概念,以便更好地描述和控制程序的并发执行,实现操作系统的并发性和共享性(最基本的两个特性)
为了使参与并发执行的每一个程序(含数据)都能独立地运行,必须为之配备一个专门的数据结构,称为进程控制块(PCB)。系统利用PCB来描述现成的基本情况和运行状态,进而控制和管理进程。相应的,由程序段,相关数据,和PCB三部分构成了进程实体(又称进程映像)。所谓创建进程,实质上就是创建进程实体的PCB,而撤销进程,实质上就是撤销进程的PCB。值得注意的是,进程实体是静态的 ,而进程则是动态的
注意:? PCB是进程存在的唯一标识
进程在不同的角度上可以有不同的定义:
1) 进程是一次程序的执行
2) 进程是一个程序及数据在处理机上顺序执行时发生的活动
3) 进程是具有独立功能的程序在一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位
4)进程是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位
2.进程的特征
1)动态性:很好理解,进程是程序的一次执行,所以它有创建,活动,暂停,终止等过程,具有一定的生命周期,是动态地产生,变化,消亡的。
2)并发性:是指多个进程同时存在于内存之中,能在同一段时间运行。
3)独立性:指进程实体是一个独立运行,独立获取资源和独立接受调度的基本单位,凡未建立PCB的程序,都不能作为一个独立的单位参与运行
4)异步性:由于进程的相互制约,使得进程按照各自独立,不可预知速度向前运行,所以导致执行的结果不可见
进程的状态
1)运行态:进程在处理机上运行,在单处理机中,每个时刻只有一个线程运行
2)就绪态:除了处理机一切准备就绪,一般在就绪队列中等待
3)阻塞态:又称等待态,进程因为等待某一事件而暂停运行,即是处理机空闲该进程也不能运行,系统进程将处于阻塞态的进程排成一个阻塞队列,甚至根据阻塞原因的不同排成多个阻塞队列
4)创建态:进程正在被创建,尚未转到就绪状态
创建线程的步骤:首先申请一个PCB,并向PCB中填写用于控制和管理进程的信息;然后为该线程分配运行时需要的资源;最后把该线程转为就绪态插入队列。
5)终止态:进程正在从系统中消失,系统首先将该进程置为终止态,然后进一步处理资源释放和回收等工作
进程的状态的转换
就绪态-->运行态:处于就绪态的线程获得处理机资源(分配处理机时间片)
运行态-->就绪态:处于运行态的进程在时间片用完后不得不让出处理机,从而转为就绪态。此外,在可剥夺的操作系统中,当有跟高由县级的线程就绪时,当前正在执行的线程转为就绪态,让跟高优先级 的线程运行
运行态-->阻塞态:进程请求某一资源的使用(如外设)和分配或等待某一时间的发生(如IO操作的完成),它就从运行态转换为阻塞态。进程以系统调用的方式请求操作系统提供服务,这是一种特殊的,由用户运行态程序调用操作系统内核态过程的形式
阻塞态-->就绪态:进程等待事件到来时,中断处理程序必须把相应的进程状态由阻塞态转换为就绪态
PCB
PCB 主要包含进程描述信息,进程控制和管理信息,资源分配清单和处理机相关信息
进程描述信息:进程表示符,每一个线程都有的唯一的标识号。用户标识符,进程归属的用户,主要为共享和保护服务
进程控制和管理信息:进程当前状态:描述进程状态信息,作为处理机分配调度的依据。进程优先级,描述进城抢占处理机的优先级
资源分配清单:用于说明有关内存地址和虚拟地址的空间状态,所打开文件的李彪和所使用的的输入/输出设备信息
处理机相关信息:主要指处理机寄存器中各个值,当进程处于执行态时处理机许多信息都在寄存器中,当进程切换时,处理机状态信息必须保存在相应的PCB中,以便在该进程重新执行时,能从断点继续执行
程序段
能被进程调度程序调度到CPU执行的 程序段代码。注意:程序可以被多个进程共享,即多个进程可以运行同一个程序
数据段
一个程序的数据段,可以是线程对应程序加工处理的原始数据,也可以是程序执行时产生的中间或最终结果
1)进程的创建
操作系统创建进程的过程(创建原语)
1.为新进程分配一个唯一的进程标识,申请一个空白的PCB(PCB是有限的)若PCB申请失败,则创建失败
2.为进程分配其运行所需的资源,如内存,文件,I/O设备和CPU时间等,这些资源仅从操作系统中得到或者从父进程获得,如果资源不足不是创建失败,而是处于创建态,等待内存资源
3.初始化PCB,主要包括初始化标志信息,初始化处理机状态信息和初始化处理机控制信息,以及设置进程优先级
4.若进程就绪队列能够接纳新进程,则将新进程插入就绪队列,等待被系统调用
2)进程的终止
操作系统终止进程的过程(终止原语)
1.根据被终止进程的表示符,检索出该进程的PCB,从中读取出进程的状态
2.若被终止的进程处于运行的状态,立即终止该进程的执行,将处理机资源分配给其他进程
3.若该进程还有其他子孙进程也将其终止
4.将该进程拥有的所有资源都还给父进程或者操作系统
5.将该PCB从队列(链表)中删除
3)进程的阻塞和唤醒
阻塞原语(Block)执行过程
1.找到需要被阻塞进程的标识符对应的PCB
2.若该进程是运行态,则保护现场,将其状态转为阻塞态停止运行
3.把该PCB插入相应的事件的等待队列,将处理机资源调度给就绪进程
唤醒原语(Wakeup)执行过程
1.在该事件的等待队列中找对对应进程的PCB
2.将其从等待队列中移除,并置其状态为就绪状态
3.把该PCB插入就绪队列,等待调度程序调度
进程的通信是指进程之间的信息交换。PV操作是低级通信方式,高级通信方式是指以比较高的效率传输大量数据的通信方式。
1..共享存储
在通信的进程之间存在一块可以直接访问的共享空间,通过对这篇共享空间进行读/写操作实现进程之间的信息互换。
共享存储又分为两种:
低级方式的共享是基于数据结构的共享
高级的方式是基于存储区的共享
操作系统值负责为通信的进程提供可以共享的存储空间和同步互斥工具,而数据交换由用户自己安排读写指令完成
2.消息传递
若需要通信的进程之间不存在可以直接访问的共享空间,则必须利用操作系统提供的消息传递的方式实现进程通信。
进程通过系统提供的发送消息和接收消息两个原语进行数据交换。这种方式屏蔽了通信实现的细节,使通信过程对用户透明,简化了通信程序的设计
1)直接通信方式
发送进程直接把消息发送给接收进程,并将它挂在接收进程的消息缓冲队列上,接收进程从消息缓冲队列中取得消息
2)间接通信方式
发送进程把消息发送到某个中间实体,接收进程从中间实体中获得消息,这种中间实体一般称为信箱。
3.管道通信
管道通信允许两个进程按照生产者-消费者方式进行通信,生产者向管道一端写入数据,消费者从管道另一端读。数据在管道内是先进先出的。
在Linux中管道是一种使用十分频繁的通信机制,从本质上来说,管道也是一种文件,但它和一般的文件也不相同,管道可以客服使用文件通信的两个问题:
1.限制管道的大小,管道文件是一个固定大小的缓冲区,在Linux中该缓冲区的大小为4kb,这使得它的大小不像普通文件那样不加检验的增长。使用单个固定缓冲区也会出现问题,比如在写管道时可能变满,这种情况发生时,随后对管道的write()调用默认被阻塞,等待默写数据被读取
2.读进程也可能比写进程进行的快,当所有管道内的数据已被读取时,管道变空。随后read()调用将默认地被阻塞,等待某些数据被写入,这就解决了read()调用返回文件结束的问题
管道只能由创建进程所访问,当父进程创建一个管道后,由于管道是一种特殊文件,子进程会继承父进程打开的文件,因此也继承父进程的管道,并使用它来与父进程进行通信
注意?从管道读数据是一次性操作,数据一旦被读取就会释放空间以便写更多的数据,普通管道只允许单向通信,若想要实现父子进程双向通信,就需要定义两个管道
引入进程的目的是更好的使多道程序并发执行,提高系统资源利用率和系统吞吐量;而引入线程是为了减小线程在并发执行期间所付出的时空开销,提高系统的并发小性能
线程可用简单理解为“轻量级的进程”,它是CPU最基本的执行单元,也是程序执行流最小的单元,由线程ID,程序计数器,寄存器集合和堆栈组成。线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有操作系统的资源,只拥有一点儿在运行中必不可少的资源,但它可以和进程中其他线程共享进程拥有的全部资源
1)调度:在传统的的操作系统中,拥有资源和独立调度的基本单位都是进程,每次调度都要进行上下文切换,开销较大;在引入线程的操作系统中,线程是独立调度的基本单位,而线程切换的代价远远小于进程的切换,在同一个进程中,线程的切换不会引起进程的切换。
2)并发性:在引入线程的操作系统,不仅线程可用并发执行,而且一个进程中的多个线程也可以并发执行,甚至不同进程之间的线程也可以并发执行,使操作系统的并发性得到很大的提高,提高了系统资源的利用率和吞吐量
3)拥有资源:进程是系统拥有资源的基本单位,而线程不拥有系统资源(仅拥有一点必不可少的,能保证独立运行的资源),但线程可以访问其隶属进程的系统资源,主要表现在属于同一进程的所有线程都具有相同的地址空间。要知道如果线程也拥有资源,那么切换线程的开销也会变大,线程的提出也会变得没有意义
4)独立性:每一个进程都拥有独立的地址空间和资源,除了共享全局变量,不允许其他进程访问。所以某进程中的线程对其他进程不可见,同一进程中的线程的多个线程共享进程的地址空间和资源
5)系统开销:在创建和撤销进程的时候,系统都需要为之分配或回收PCB以及其他资源,操作系统会为此付出的开销,显然大于创建或者撤销线程时的开销
6)支持多处理机系统:对于传统单线程进程,不管有多少处理机,进程只能运行在一个处理机上。对于多线程进程,可以将进程中的多个线程分配到处理机上执行
在多线程的操作系统中进程已经不再是一个基本的执行实体,但它还是具有与执行相关的状态。所谓线程处于“执行状态”就是指该进程中的某个线程正在执行
线程的主要属性有:
1)线程不具有系统资源,但每一个线程都应该有一个唯一的标识符和一个线程控制块,线程控制块记录了线程执行的寄存器和栈等现场状态
2)不同的线程可以执行相同的程序,即一个同一个服务程序被多个不同用户调用时,操作系统会把它们创建成不同的线程
3)同一个进程中的线程共享该进程所拥有的资源
4)线程是处理机的独立调度单位,多个线程是可以并发执行。在单CPU的计算机系统中,各个线程是可以交替的占用CPU;在多CPU的计算机系统中,各线程可以占用不同的CPU
执行状态:线程已经获得了处理机正在执行
就绪状态:线程已具备各种执行条件,只需要再获取CPU便可以立即执行
阻塞状态:线程在执行中因某个事件受阻而处于暂停状态
1)线程控制块(TCB) 用于记录控制和管理线程的信息
2)线程的创建
在创建线程的时候,需要利用到一个线程创建函数,并提供相应的参数,如指向线程主程序入口的指针,堆栈大小,线程优先级等,当创建函数完成后返回一个线程标识符
3)线程的终止
线程终止调用相应的函数来执行终止操作,但通常情况下,线程被终止后并不立即释放它所占有的资源,只有当进程中的其他线程执行了分离函数后,被终止线程才与资源分离,此时的资源采用被其他线程利用
线程的实现可以分为两类:用户级线程(UTL)和内核级线程(KLT)
1)多对一模型 :将多个用户级线程映射到一个内核级线程
优点:线程管理是在用户空间进行效率高
缺点:在任何时候只有一个线程能访问内核,那一个线程发生阻塞就会导致整个进程阻塞
2)一对一模型:?将每一个用户级线程映射到一个内核级线程
优点:当一个线程阻塞时,允许调度另一个线程,并发性强
缺点:每创建一个用户线程就会对应一个内核线程开销大
3)多对对模型?将n用户级线程映射到m个内核级线程 n>=m
特点:既克服了多对一并发性不高的缺点,也克服了一对一的开销太大的缺点,还拥有上述两个模型的优点