程序的顺序执行特征:
- 顺序性:程序按次序逐步执行
- 封闭性:独占全机资源,所有资源状态由程序完成
- 可再现性:程序的执行结果不变,且与计算机的执行速度无关
程序在并发执行时的特征:
- 间断性:多个程序相互制约(如输入程序与计算程序的先后关系)
- 失去封闭性:多个程序共享资源(资源状态由多个程序改变)
- 不可再现性:程序的执行结果与计算机的执行速度有关,也与其它程序的执行相关
程序(纯代码段+数据段)+程序专用控制数据区 = 进程
1、进程的定义
- 进程是程序的一次执行
- 进程是进程实体(包括程序段、数据和PCB)的运行过程,是系统进行资源分配和调度的一个独立单位
2、进程的特征
- 结构性:由程序段、数据段和进程控制块组成
- 动态性:进程可以被动态地创建、执行、撤消
- 并发性:在同一时间内有多个进程运行
- 独立性:是独立运行和获得资源的基本单位
- 异步性:异步执行
3、进程与程序的区别
- 进程是动态的,程序是静态的(是指令的集合)
- 一个程序可以包含多个进程
- 进程可以描述并发活动,程序则不明显
- 进程执行需要处理机,程序存储需要介质
- 进程有生命周期,程序是永存的
4、进程的类型
系统进程、用户进程、父进程:由系统或用户首先创建的进程、子进程:由父进程创建的进程
父、子进程的关系:
- 进程控制:任何子进程只能由父进程创建及撤消,子进程不能对父进程实施控制
- 运行方式:可同时执行,也可以等待子进程完成后,父进程再执行
- 资源共享:子进程可全部或部分共享父进程的拥有的资源
5、进程的结构
进程由(纯)代码段、数据和进程控制块组成
- 代码段:描述进程所完成的功能
- 数据集合:程序运行时所需要的数据区
- 进程控制块(PCB):既能标识进程的存在,又能刻画进程瞬间特征的数据结构
进程的三种基本状态:
- 就绪状态:进程获得了除处理机CPU之外的所有资源(可以有多个,排成就绪队列)
- 执行状态:进程的程序正在处理机上执行(单CPU中只有一个进程处于该状态)
- 阻塞状态:因发生某事件(如请求I/O,申请缓存空间等)而暂停执行的状态(也称为睡眠状态或等待状态)
进程基本状态的转换:
处于执行状态的进程,可以主动用阻塞原语(block)将其变为阻塞状态
处于阻塞状态的进程,可以用唤醒(wakeup) 原语将其变为就绪状态
进程的挂起状态
- 挂起状态是一种静止状态,即不能马上投入运行的状态,包括静止就绪状态(Readys)和静止阻塞状态(Blockeds)
- 处于挂起状态的进程可以存放到外存上保留,而且可以回收这些挂起状态进程的内存、设备等部分资源
设置挂起状态的原因:
- 终端用户的需要:(调试)
- 父进程的需求: (子进程同步)
- 负荷调节的需要:(减轻负荷)
- 操作系统的需要:(检查资源使用情况)
活动状态与挂起状态的转换
- 处于活动状态的进程(Readya, Blockeda) ,可以用挂起(Suspend)原语将其变为挂起状态(Readys, Blockeds)
- 处于挂起状态(静止状态)的进程,可以用激活(Active)原语将其变为活动状态
进程控制块PCB(process control block):
1、PCB的作用:
- 描述进程的变化过程
- 记录进程的外部特征
- 记录进程与其他进程的联系
- 是进程存在的唯一标志
- 系统通过PCB控制和管理进程
2、PCB的内容
⑴、进程标识符信息
- 内部标识符信息(进程唯一序号)
- 外部标识符信息(由创建者提供的进程名字)
⑵、处理机状态信息
- 处理机执行进程的现场信息
- 包括通用寄存器、指令计数器、程序状态字PSW(Program Status Word)、用户堆栈指针等信息
⑶、进程调度信息
- 进程状态
- 进程优先级
- 进程调度所需的其它信息(如进程已用CPU时间)
- 事件(阻塞原因)
⑷、进程控制信息
- 程序和数据的地址
- 进程同步和通信机制(如消息队列指针等)
- 资源清单
- 链接指针(与其它PCB形成一个队列)
3、PCB的组织形式
⑴、线性表方式:将所有PCB不分状态,全部组织在一个连续表中
⑵、链接方式:把具有相同状态的PCB,链接成一个队列
⑶、索引方式:把具有相同状态的PCB在PCB表中的首址,按顺序组成一个索引表(如就绪索引表、阻塞索引表)
处理机的执行状态分为系统态和用户态两种不同状态
- 系统态:也叫管态或内核态,具有较高的特权,能执行一切指令,访问所有寄存器和存储区
- 用户态:也叫目态,具有较低特权的执行状态,只能执行规定的指令,访问规定的寄存器和存储区
通常,操作系统内核运行在系统态,而用户程序则都是运行在用户态
进程的创建:
1、引起进程创建的事件
- 用户登录:用户合法登录后(分时系统)
- 作业调度:某作业被调度后(批处理系统)
- 提供服务:用户调用某些系统调用或命令后
- 应用请求:由用户程序自己创建进程,如Unix中的fork()函数,Windows中的CreateProcess()函数
进程控制由原语操作实现。
进程的终止:
- 进程正常结束
- 异常结束:出现某些错误和故障而迫使进程终止(如保护错、越界/权、非法指令、超时、错误等)
- 外界干预:用户或系统干预\父进程请求或终止
终止进程的实质是收回PCB
进程的阻塞
引起进程阻塞的事件:
- 请求系统服务(如请求分配I/O)
- 启动某种操作(如启动I/O)
- 新数据尚未到达(如进程通信)
- 无新工作可做(系统进程)
阻塞是一种主动的行为
进程的唤醒
引起进程唤醒的事件:
- 系统请求实现(如获得I/O资源)
- 某种操作完成(如I/O操作完成)
- 新数据已经到达(如其它进程已将数据送达)
- 又有新工作可做(系统进程)
进程的挂起:
调用挂起原语suspend
进程的激活 :
调用激活原语active
进程同步
进程之间的关系
- 相互合作关系(直接相互制约) (I→C→P),主要源于资源共享
- 资源共享关系(间接相互制约) (I1→ I2→ I3→),主要源于进程合作
临界资源
- 临界资源是一个时刻只能由一个进程使用的资源
- 硬件资源:许多都属于临界资源,如打印机,磁带机等
- 软件资源:如变量、表格、队列等
临界资源使用方法:
- 对临界资源的使用采用互斥方式
- 互斥:一个进程使用完之后,另一个进程才能使用
1、临界区:进程中访问临界资源的代码段
必须要在临界区前加一段代码,用来检查对应的临界资源是否正被其他进程访问,这段代码被称为进入区;相应地,在临界区后也要加一段称为退出区的代码,用于将临界区从正被访问的标志恢复为未被访问的标志
2、同类临界区:涉及同一临界资源的不同进程中的临界区
临界资源使用的同步准则:
- 空闲让进:(提高效率)
- 忙则等待:(解决互斥)
- 有限等待:等待进入临界区的要求应在一有限时间满足(以免死等)
- 让权等待:放弃占用CPU(以免忙等)
临界资源的状态判断与设置
对临界资源状态(是否正在使用)必须判断与设置同时进行,即判断与状态设置(状态改变)为原子操作,否则,会出现问题
信号量(Semaphore)
信号量是一种特殊的变量(S)
除初始化外,对信号量变量(S)的操作只能由两个标准的原子操作(不可中断)实现
- wait(S):等待操作(也叫P操作)
- signal(S):发信号操作(也叫V操作)
信号量变量是由一个整型数和一个阻塞等待进程链表构成的记录型数据结构
所有对同一个信号量进行操作且进入等待状态的进程,都自动进入阻塞等待(让权等待)状态,并将其挂在该信号量阻塞等待队列L中
信号量机制的特性:
- wait(s)操作和signal(s)操作必须成对出现(可以不在同一进程中)
- 缺少wait(s)不能保证资源互斥使用
- 缺少signal(s)将可能使资源永远得不到释放
- 不存在“忙等”问题
AND型信号量集机制:
- 将进程运行过程中需要的所有临界资源,一次性地全部分配给进程(即要么全部分配,要么一个也不分配)
- 进程使用完后再一起释放
P原子操作(Swait)
V原子操作(Ssignal)
一般信号量集机制:
- 进程运行需要多个临界资源
- 一次需要N个同类临界资源
- 大于t个同类临界资源才准予分配
P原子操作(Swait)
V原子操作(Ssignal)
一般信号量集特例:
- Swait(s, d, d): 一个信号量,每次同时分配d个同类资源
- Swait(s, 1, 1): 等效于记录型信号量
- Swait(s, 1, 0): s=1, 允许多个进程进入特定区; s=0, 阻止任何进程进入特定区
生产者-消费者问题
生产者-消费者问题描述:
有一群生产者进程在生产消息,并将此消息提供给另外一群消费者进程去消费 生产者进程(多个),产品存放缓冲区(n个),消费者进程(多个)
缓冲区是临界资源
生产者-消费者关系:
- 公用信号量mutex:初值为1,实现临界资源(缓冲区)互斥使用。(如果缓冲区只有一个缓冲块,可以只用这一个信号量)
- 生产者私用信号量empty:初值为n,指示空缓冲块数目
- 消费者私用信号量full:初值为0,指示满缓冲块数目
- 整型量in, out:初值均为0,in指示首空缓冲块序号,out指示首满缓冲块序号
采用信号量应注意的问题:
- 公用(互斥)信号量(mutex)和私用信号量(empty, full)都必须成对出现
- 在进入临界区之前,先对私用信号量(empty, full)进行wait操作,再对公用信号量进行wait操作(不能颠倒,否则易于造成“死锁”)
读者-写者问题:
读者-写者问题描述:
指多个只读进程(reader)可以同时访问共享对象,而改写进程(writer)必须与其它进程(包括reader, writer)互斥地访问共享对象的同步问题
读者-写者关系:
互斥信号量wmutex:初值为1,实现临界资源(文件)互斥使用。
读者数目:readcount,初值为0,表示正在读的进程数目
- 如果readcount=0,读者进程必须执行wait(wmutex)操作
- 读者操作完成之后,如果readcount-1=0,读者进程必须执行signal(wmutex)操作
读操作信号量rmutex:初值为1,实现对readcount的互斥访问
采用信号量应注意的问题:
- 写(互斥)信号量(wmutex)必须成对出现
- 在对readcount(所有读者进程共用的临界资源)进行处理之前,必须先进行wait(rmutex)操作;处理完之后(+1或-1),再执行signal(rmutex)操作
采用一般信号量集解决读者-写者问题
管程利用共享数据结构抽象地表示系统中的共享资源,并且将对该共享数据结构实施的特定操作定义为一组过程。换句话说,管程是由一组局部的共享变量、对局部变量进行操作的一组过程以及对局部变量进行初始化的语句序列构成的一个软件模块
一个管程定义了一个数据结构和能为并发进程所执行(在该数据结构上)的一组操作,这组操作能同步进程和改变管程中的数据
管程实际上是一种能实现进程同步的特殊的子程序(函数、过程)的集合
管程的组成:
- 名称:该管程的标识
- 共享变量说明:局部于管程的变量说明(包括特殊同步变量即条件变量)
- 一组过程:对该数据结构进行操作的程序段(相当于临界区代码段)
- 初始化:对局部于管程的数据设置初始值
进程的互斥访问:
- 进程访问临界资源,必须经过管程
- 管程每次只允许一个进程进入,即只要某个进程进入了管程,则要么执行完成,要么因故阻塞,然后下一个进程才可以进入管程
进程的同步:
- 设置条件变量(相当于互斥信号量) var x: condition
- 当临界资源已被占用,执行x.wait,将进程挂在x条件变量的阻塞等待队列中
- 当临界资源已空闲,执行x.signal,从x条件变量的阻塞等待队列中,唤醒第一个进程
利用管程解决生产者-消费者问题
1、过程:
- put(item)过程:生产者将产品放入缓冲区
- get(item)过程:消费者从缓冲区取得一个产品
2、变量:
- 整型量in, out:初值均为0,in指示首空缓冲块序号,out指示首满缓冲块序号
- Buffer[0…n-1]:缓冲区
- 整形量count:满缓冲块数目
- 条件变量notfull, notempty:指示缓冲区已满、已空
3、管程描述
4、进程描述
管程的优点:
- 使用临界资源的进程进行调用时非常简单
- 进程结构清晰
- 易于查错
进程通信:
进程通信是指进程之间的信息交换
进程通信的三种类型:
- 共享存储器系统(无格式)
- 消息传递系统(有格式)
- 管道通信系统(相当于文件)
进程通信(同步)的三种方式:
- 发送进程阻塞,接收进程阻塞(没有缓冲区)
- 发送进程不阻塞,接收进程阻塞(如后台打印)
- 发送进程不阻塞,接收进程不阻塞(有多个缓冲区)
共享存储器系统:
进程间以共享存储器方式进行数据通信
1、基于共享数据结构的通信方式:
由用户程序定义数据结构、申请内存,并同步各进程对该数据结构的访问,如生产者—消费者问题
2、基于共享存储区的通信方式:
系统设置一共享存储区,由系统同步各进程对该共享存储区的访问。
用户需要共享存储区时,到系统中去申请,系统分配一部分共享存储分区给用户并返回该分区的名字,相关进程按名共享该分区
消息传递通信:
- 进程间的数据交换以消息(message)为单位
- 操作系统直接提供一组命令(原语)实现通信直接消息传递通信
消息传递系统根据实现方式又分直接通信和间接通信。
- 直接通信方式:源进程可直接将消息发送给目标进程
- 间接通信方式:进程间需要通过某种中间实体,即信箱来进行通信。
直接消息传递通信:
1、特点:
- 发送进程直接将消息发送给接收进程,并将它挂在接收进程的消息缓冲队列上
- 接收进程从消息缓冲队列中取得消息
2、消息通信命令:
- 直接消息传递通信主要采用两种命令(原语)
- 发送消息原语Send(Receiver, message)
- 接收消息原语Receive(message)
4、直接通信机构:
- mq:进程的消息队列首指针
- mutex:进程的消息队列互斥信号量,初值为1
- sm:同步信号量,用于消息队列中的消息计数,初值为0
5、直接通信Send原语:
6、直接通信Receive原语
间接消息传递通信:
1、特点:
- 需要某种共享数据结构的实体作为中介
- 发送进程将发送给目标进程的消息暂存于该中介中
- 接收进程从中介中,取出发送给自己的消息
- 中介一般称为信箱(mailbox),因此,间接消息传递通信也称信箱通信
2、信箱通信命令:
- 信箱创建命令Create(mailbox)
- 信箱撤消命令Delete(mailbox)
- 消息发送命令Send(mailbox, message)
- 消息接收命令Receive(mailbox, message)
3、信箱种类:
- 私用信箱:由用户进程创建,其它进程只能向该信箱发送消息
- 公用信箱:由操作系统创建,并提供给系统中的所有核准进程使用
- 共享信箱:由某进程创建,并指明共享者名字;所有共享者和创建者进程都可以取走自己的消息
4、发送进程与接收进程的关系:
- 一对一:在发送与接收进程之间设立专用通信链路
- 多对一:客户/服务器方式
- 一对多:一个发送进程向多个接收进程广播消息
- 多对多:设立一个公用信箱
线程:
为了提高计算机系统的并发执行能力,减少程序在并发执行时所付出的时空开销
线程与进程的关系:
- 线程是进程中的运行实体
- 一个进程可包含多个线程
- 一个进程中至少包含一个线程,称主线程
- 进程相当于线程的载体
资源分配的最小单位:进程
程序执行的最小单位:线程
多线程OS中的进程:
- 拥有资源的基本单位与调度和分派的基本单位分开处理
- 进程不是一个可执行的实体,但是每个线程都是一个可执行的实体
- CPU调度和分派的基本单位是线程
线程由线程标识符、程序计数器、一组寄存器的值和堆栈组成
线程基本不拥有资源
线程的状态:
- 执行状态:线程正获得CPU而运行
- 就绪状态:一旦获得CPU就可运行
- 阻塞状态:因等待某一事件而暂停
线程的创建和终止:
- 创建:新线程由正在执行的线程所创建 线程创建一般通过创建函数(或系统调用)来实现,并提供相应的参数,如指向线程主程序的入口指针,堆栈的大小,优先级等
- 终止:线程同样有生命期,当线程完成任务后,会自动终止 线程终止还有可能由其它线程实现
线程的分类:
- 内核支持线程:线程的处理均由内核实现,内核为线程保留TCB,并通过TCB感知线程
- 用户级线程:线程的处理不通过内核实现,线程的状态信息等全部存放在用户空间中,内核不能感知用户级线程
线程同步--条件变量:
在进入临界区之前,先关上互斥锁,进行判断,是否条件可以满足
- 不能满足时,自行转为等待状态,并打开互斥锁
- 满足条件,则继续执行临界区,完成后,打开互斥锁
线程同步--信号量机制:
- 私用信号量:用于同一进程中不同线程之间的同步和通信
- 公用信号量:用于不同进程中的线程之间的同步和通信
线程控制:
1、内核支持线程的实现:
- 进程创建线程时,调用内核函数
- 内核支持的线程,其创建、调度都与仅有进程的创建与调度情况类似
2、用户级线程的实现:
⑴、运行时系统:
用于管理和控制线程的函数(过程)的集合
- 用于创建和撤消线程的函数
- 线程同步和通信的函数
- 实现线程调度的函数等
⑵、内核控制线程:
- 内核控制线程又称为轻型进程(LWP),专门用于用户级线程与内核发生联系
- 每个用户级线程只要连接到LWP上,就具有了内核支持线程的所有属性
设置LWP的优点: 使系统保持尽量少的线程数目,节省系统开销 用户级线程数目不限