1、前驱图和程序执行
前驱图
- 概念
- 一个有向无循环图。
- 用于描述进程之间的前后关系。
- 表示程序执行的逻辑。
- 表示
→ = { ( p 1 , p 2 ) ∣ p 1 b e f o r e p 2 } \rightarrow=\{(p_1,p_2)|p_1\ before\ p_2\} →={(p1,p2)∣p1 before p2}
-
元素
- 把没有前趋的结点称为初始结点(
Initial Node
)。 - 把没有后继的结点称为终止结点(
Final Node
)。 - 权重(
Weight
)表示该结点所含有的程序量或结点的执行时间。
- 把没有前趋的结点称为初始结点(
-
图示
不一定单一起点、单一终点。
只考虑顺序,不考断断续续与否。
按照要求执行,只能说明逻辑正确。
程序的顺序执行
- 程序执行有固定的时序。
- 前一段操作完成后,才能执行后继操作。
- 前提
- 单道顺序执行
- 特征
- 顺序性:处理机的操作严格按照程序所规定的顺序执行。
- 封闭性:程序运行时独占全机资源,程序一旦开始执行,其执行结果不受外界因素影响。
- 可再现性:只要程序执行时的环境和初始条件相同,都将获得相同的结果。
程序的并发执行
- 并发条件
- 两个任务之间无关系(不是前驱也不是后继)。
- 特征
- 间断性:进程共享系统资源,导致依赖环境被破坏,为完成同一项任务而相互合作,导致并发的进程之间形成了相互制约的关系,断后需保存,执行后恢复。
- 失去封闭性:多个资源共享资源。
- 不可再现性:失去封闭性的同时会导致不可再现性。
2、进程的描述
进程的定义和特征
-
引入原因
- 程序不能并发执行。
- 对并发执行的程序加以控制和描述。
-
结构特征
- 为使程序能独立运行,应配置一个进程控制块。
- 系统利用
PCB
(Process Control Block
)来描述进程的基本情况和活动过程,进而控制和管理进程。 - 由程序段、数据段及进程控制块三部分构成,总称“进程映像”。
-
定义
- 进程是程序的一次执行。
- 进程是一个程序及其数据在处理机上顺序执行时所发生的活动。
- 进程是具有独立功能的程序在一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位。
- 进程是进程实体的运行过程(递归定义),是系统进行资源分配和调度的一个独立单位。
-
表现特征
- 动态性
- 它由创建而产生,由调度而执行,由撤消而消亡。
- 由
PCB
实现。 - 程序(静态的)为剧本,而进程(动态的)是剧本的一次演绎。
- 并发性
- 这是指多个进程实体同存于内存中,且能在一段时间内同时运行。
- 独立性
- 指进程实体是一个能独立运行、独立分配资源和独立接受调度的基本单位;
- 有线程后,线程变成调度单元,进程负责资源分配。
- 异步性
- 指进程按各自独立的、不可预知的速度向前推进,或说进程实体按异步方式运行。
- 动态性
进程的基本状态及转换(原因)
- 状态转换
- 进程执行要由调度程序调度才能占用
CPU
。
- 进程执行要由调度程序调度才能占用
- 三种基本状态
- 就绪状态:进程已分配到除
CPU
之外的资源后,只差获取CPU
即可运行。 - 执行状态:进程已获得
CPU
,正在执行。 - 阻塞状态:执行的进程由于发生某事件而无法继续执行,需要暂停等待该事件,也称为等待状态。
- 就绪状态:进程已分配到除
就绪无法直接到阻塞。
-
单阻塞队列
- 阻塞事件不唯一。
-
多阻塞队列
- 根据阻塞事件区分队列。
- 每个队列串行执行,不能用线程并行操作。
-
创建状态
- 此时资源未准备完成。
- 进程创建过程复杂,未完成创建的进程不能调度。
- 从开始建立
PCB
到加入就绪队列转入就绪状态。 - 可根据系统性能或主存容量推迟新进程的创建完成,增加管理的灵活性。
-
终止状态
- 避免再被调度。
- 步骤
- 等待进程终止的善后处理;
- 撤销进程的
PCB
。
-
五种基本状态转换
挂起操作和进程状态的转换
- 挂起操作
- 使执行的进程暂停下来,就绪状态的进程暂不接受调度。
- 挂起的原因
- 终端用户的请求。
- 父进程请求。
- 负荷调节的需要:当实时系统中的工作负荷较重,把一些不重要的进程挂起,以保证系统能正常运行。
- 操作系统的需要:操作系统有时希望挂起某些进程,以便检查运行中的资源使用情况或进行记账。
- 一般为人为原因:手动暂停。
若在运行时挂起,则进入静止就绪状态。
-
-
创建到活动就绪还是静止就绪状态是可选的。
进程管理中的数据结构(掌握)
- 管理控制
- 内存表
- 设备表
- 文件表
- 进程表
PCB
的作用- 作为独立运行基本单位的标志。
- 提供进程管理和调度所需要的信息。
- 实现与其他进程的同步与通信。
- 间断性运行时,保存运行时的
CPU
现场。
切换过程:进程停下时,进程信息放入
PCB
。
- 进程标识符
- 内部标识符:赋予一个唯一的数字标识符,通常是进程的序号。
- 外部标识符:描述进程的家族关系,以及拥有该进程的用户。
- 处理机状态信息
- 通用寄存器
- 指令计数器
- 程序状态字
PSW
- 用户栈指针
中断和进程切换需要保护处理机状态信息。
- 进程调度和对换信息
- 进程状态
- 进程优先级
- 进程调度所需的其它信息
- 事件
多路阻塞队列,不需要记录事件,因为该队列已标识该事件。
- 进程控制信息
- 程序和数据的地址
- 进程同步和通信机制
- 资源清单
- 链接指针
3、进程控制(掌握)
操作系统内核
-
OS
的层次- 通常将一些与硬件紧密相关的模块(如中断处理程序等)、各种常用设备的驱动程序以及运行频率较高的模块(如时钟管理、进程调度和许多模块公用的一些基本操作),都安排在紧靠硬件的软件层次中,将他们常驻内存,即通常被称为的
OS
内核。
- 通常将一些与硬件紧密相关的模块(如中断处理程序等)、各种常用设备的驱动程序以及运行频率较高的模块(如时钟管理、进程调度和许多模块公用的一些基本操作),都安排在紧靠硬件的软件层次中,将他们常驻内存,即通常被称为的
-
处理机的执行状态
- 系统态/管态/内核态(考别名)
- 较高特权,执行一切指令,访问所有寄存器和存储区。
- 内核在系统态运行。
- 用户态/目态
- 较低特权,有限的指令和访问区域。
- 应用只能在用户态运行。
- 这样的机制是为了保护
OS
不被破坏。
- 系统态/管态/内核态(考别名)
-
OS
内核功能- 支撑功能
- 中断处理
- 时钟管理
- 原语操作
- 资源管理功能
- 进程管理
- 存储器管理
- 设备管理
- 支撑功能
-
原语(重要)
- 若干条指令组成,用于完成一个过程,该过程执行时不可分割。
单机系统采用屏蔽中断的方式保证操作的原子性。
多
CPU
无法依赖屏蔽中断来保证原子性。
进程的创建
- 层次结构
- 创建形成的父子进程关系。
- 子进程继承父进程的资源。
- 父进程终止导致子进程终止。
PCB
中记录家族关系。Windows
没有进程层次关系。
- 进程图
其中
A
进程又称为0
号进程。
- 进程创建过程
进程的终止
-
正常结束
- 批处理系统:
Holt
指令或终止的系统调用。 - 分时系统:
Logs off
。
- 批处理系统:
-
异常结束
- 越界错误
- 保护错误
- 非法指令
- 特权指令错误
- 运行超时
- 等待超时
- 算术运算错误
I/O
故障
-
外界干预
- 操作员/操作系统干预
- 父进程请求终止该进程
- 父进程终止,其所有子进程终止
-
进程终止过程
-
Linux
进程终止- 正常
return
exit()
- 异常
abort
- 进程收到信号使得程序终止
- 正常
进程的阻塞与唤醒
-
阻塞过程
-
唤醒过程
- 首先把被阻塞的进程从等待该事件的阻塞队列中移出,将其
PCB
中的现行状态由阻塞改为就绪。 - 然后再将该
PCB
插入到就绪队列中。
- 首先把被阻塞的进程从等待该事件的阻塞队列中移出,将其
进程的挂起与激活
-
进程的挂起
- 当出现了引起进程挂起的事件时,系统将利用挂起原语
suspend( )
将指定进程挂起或处于阻塞状态的进程挂起。
- 当出现了引起进程挂起的事件时,系统将利用挂起原语
-
挂起过程
-
-
进程的激活
- 若是静止就绪,便将之改为活动就绪;
- 若为静止阻塞,便将之改为活动阻塞。
-
Linux
的挂起原语pause(void)
任何信号都能挂起。sigsuspend(const sigset_t *sigmask)
信号集中的信号导致挂起。
采用抢占调度策略时,每当有新进程加入就绪队列,都应检查是否重新调度。
创建、终止(自己)、挂起(自己)、激活、阻塞、唤醒都可能会产生新的调度。
终止一定触发调度。
- 进程切换
-
把处理机分配给不同的进程占用,称为进程调度。
-
被分配到处理机的程序为调度程序。
-
进程切换时,要保护执行现场,这就是进程的上下文。
-
过程
-
-
步骤
- 保存进程上下文环境。
- 更新当前运行进程的控制块内容,将其改为就绪或者阻塞态。
- 将进程控制块移到相应队列(就绪/阻塞)。
- 改变需投入运行进程的控制块内容,将其状态改为运行态。
- 恢复需投入运行进程的上下文。
-
4、进程同步
进程同步的基本概念(掌握)
- 同步
- 并发进程在执行次序上的协调,以达到有效的资源共享和相互合作,使程序执行有可再现性。
- 概念
- 资源共享和协作导致相关进程间形成制约。
- 制约关系
- 资源共享关系(间接)
- 需互斥地访问资源。
- 存在中间控制体。
- 相互合作关系(直接)
- 因协作而产生阻塞和唤醒。
- 例如共享缓冲区。
- 资源共享关系(间接)
- 临界资源
- 多进程访问的资源(前提)。
- 一次仅允许一个进程访问的资源(特点)。
不可再现性是因为临界资源没有互斥访问。
- 采用多道程序并发设计技术的操作系统对各个进程的并发控制是非常重要和必需的。
- 临界区
- 进程访问临界资源的那段代码。
- 保证临界区使用标志(锁)是可以被共享的全局变量。
- 进程们对标志的修改操作必须互斥。
Repeat
Entry section
Critical section
Exit section
Until false
进入区和退出区都允许多进程存在,临界区只能有一个进程进入。
- 互斥使用临界资源
- 可以进入,必须设置临界区使用标志,阻止其它后来的进程进入临界区。
- 后来的进程查看临界区使用标志,发现不能进入临界区,则进入阻塞队列。
- 使用完毕后,在退出区修改临界区使用标志,并唤醒阻塞队列中的一个进程,让其进入临界区。
- 同步机制遵循准则
- 空闲让进
- 临界区空闲,有进程申请就让其进入。
- 忙则等待
- 每次仅允许一个进程处于临界区,保证互斥访问。
- 有限等待
- 不能让其他进程在临界区外陷入死等。
- 让权等待
- 进程不能进入临界区时,应该释放处理机,避免陷入忙等。
- 空闲让进
让权等待对单
CPU
十分重要。
硬件同步机制
- 存在问题
- 软件方法无法解决忙等现象,能实现两个进程的互斥,很难控制多个进程的互斥。
- 算法设计需要非常小心,不然容易出现死锁、互斥失败的问题。
- 硬件指令
Test-and-Set
Swap
- 指令的本质
- 确保对锁的检测和关锁操作的原子性。
- 关中断
- 单
CPU
系统屏蔽中断之后不会出现进程切换。 - (单
CPU
)进程在临界区执行屏蔽中断,可以保证互斥执行。 - 缺点
- 关中断时间过长会影响系统效率。
- 多
CPU
系统屏蔽中断无用。
- 单
- 互斥伪代码实现
While(true)
{
<disable interrupts> //屏蔽中断
<critical section> //临界区
<enable interrupt> //启用中断
<remainder> //其余部分
}
Test-and-Set实现互斥
boolean TS(boolean *lock){ //返回当前lock状态
boolean old = *lock;
*lock = TRUE; //保持lock为TRUE
return old;
}
do{
...
while TS(&lock);
//临界区
...
lock = FALSE;
}while(TRUE);
Swap实现互斥
do{
boolean key = TRUE;
do{
swap(&lock,&key);
}while(key != FALSE);
//临界区
...
lock = FALSE;
}while(TRUE);
- 机器指令优点
- 可应用于单处理机或多处理机中,多进程共享存储器,实现互斥使用。
- 非常简单、易于证明。
- 可支持多个临界区,每个临界区可用自己的变量定义。
- 机器指令缺点
- 忙等现象:进程需要循环检测
- 饥饿现象:当一个进程退出临界区,有许多进程想进入时,无排序机制,可能某个进程一直抢不到锁,从而出现饥饿现象。
- 死锁
- 与软件解决方法比较,这种方法减少了系统额外开销,但由于需要太强的硬件约束条件,以及可能导致进程饥饿与死锁现象,一直没有成为通用的解决方法。
信号量机制(四种)
- 引入原因
- 软件方法和硬件方法都存在忙等的问题,信号量可以解决这个问题。
- 基本原理
- 两个或多个进程可以通过传递信号进行合作,可以迫使进程在某个位置暂时停止执行(阻塞等待),直到它收到一个可以“向前推进”的信号(被唤醒)。
- 相应地,将实现信号灯作用的变量称为信号量。
操作系统内核以系统调用的方式提供
wait
和signal
原语,应用程序将该系统调用作为实现互斥的接口。利用信号量实现进程互斥是高效的。
整形信号量(必考)
- 是一个整型量,通过
wait()
(P操作)和signal()
(V操作)来访问。
Wait(s): while s<=0 do no-op
s:=s-1;
Signal(s): s:=s+1
不使用布尔的原因:布尔无法处理多个资源可申请使用的情况。
Wait()
和Signal()
的原子性由硬件指令TS
、SWAP
实现。
记录型信号量
- 整型机制中,会不断测试不满足“让权等待”的判断,从而引入。
type semaphore=record
value:integer;
L: list of process;//进程列表(等待队列)
end
procedure wait(s)
var s: semaphore
begin
s.value:=s.value –1;
if s.value <0 then block (S,L);//加入阻塞队列
end
procedure signal (S)
var s:semaphone
begin
s.value:=s.vaule+1
if s.value<=0 then wakeup(s.L)
end
用
wait()
和signal()
实现同步与互斥。
信号量类型
- 分类
- 互斥信号量
- 用于申请或释放资源的使用权,初始化为
1
。 - 默认为记录型信号量。
- 用于申请或释放资源的使用权,初始化为
- 资源信号量
- 用于申请或者归还资源,可以初始化为大于
1
的正整数。 - 表示某类资源可用的个数。
- 用于申请或者归还资源,可以初始化为大于
- 互斥信号量
- 互斥实现
- 使得多进程能够互斥访问临界区,只须设置互斥信号量初始值为
1
。 - 将进程访问的临界区代码段放在
wait()
和signal()
之间。
- 使得多进程能够互斥访问临界区,只须设置互斥信号量初始值为
取值范围
value >= 0
时,表示可执行wait(s)
而不会阻塞的进程数。value < 0
时,表示被阻塞的进程数。
1 − n ≤ S . v a l u e ≤ 1 1-n\leq S_{.value}\leq 1 1−n≤S.value≤1
AND型信号量
- 特点
- 要么全分配,要么不分配。
用于互斥的总结
- 确定运行实体(进程)。
- 确定互斥访问的资源。
- 为每类资源分配信号量。
- 设置信号量的初值
1
。 - 访问资源前wait对应信号量。
- 访问资源后wait对应信号量。
解决前驱关系(同步)
- 确定需要同步的关系。
- 为每个边安排一个信号量。
- 为信号量设置初值
0
。 wait
前驱到自己的信号量。- 为后继信号量
signal
。
- 每个操作都是一个运行实体。
总结
- 信号量的含义
- 整型信号量和记录型信号量,是除了初始化外只能进行
wait
和signal
的变量。 - 理解
wait
和signal
的实现。
- 整型信号量和记录型信号量,是除了初始化外只能进行
- 信号量的物理意义
- 一个信号量
S
对应通常对应一类临界资源。 S.value
的含义?wait
是消耗资源,signal
是释放资源。
- 一个信号量
- 用信号量实现互斥
- 一个临界资源一个信号量,初值为
1
,进入临界区wait
,退出临界区signal
,必须成对出现。
- 一个临界资源一个信号量,初值为
- 用信号量实现前趋关系
- 是同步关系,每个关系设置一个信号量,初值为
0
,后继进程wait
,前趋进程signal
。
- 是同步关系,每个关系设置一个信号量,初值为
- 用信号量实现资源使用
- 资源使用的信号量初始化为开始资源数,使用时
wait
,释放时signal
。
- 资源使用的信号量初始化为开始资源数,使用时
5、经典进程同步问题(重要)
生产者-消费者(重点)
- 特点
- 共享一个大小固定的缓冲区。
- 不能同时生产和消费。
- 要求
- 互斥进入缓冲区。
- 必须同步。
- 信号量设置
- 互斥信号量
mutex
- 实现诸进程对缓冲池的互斥使用。
- 资源信号量
empty
- 表示缓冲池中空缓冲区的数量。
- 资源信号量
full
- 表示满缓冲区的数量。
- 只要缓冲池未满,生产者便可将消息送入缓冲池。
- 只要缓冲池未空,消费者便可从缓冲池中取走一个消息。
- 互斥信号量
解法1
- 利用记录型信号量解决。
此处的
wait
和signal
必须配对,且只能嵌套不能交叉。先申请资源信号量,再申请互斥信号量,此处不能颠倒。
解法2
- 利用
AND
信号量同时申请资源信号量和互斥信号量。
解法3
- 使用管程的
put()
和get()
过程,使得进程有序。
哲学家进餐
- 特点
- 哲学家、筷子之间都是存在差异的。
n
根筷子用n
个信号量表示。
解法1
- 利用记录型信号量标识每一根筷子。
- 哲学家每次使用相邻两根。
do{
wait(chopstick[i]);
wait(chopstick[(i+1) %5]);
...
//eat
...
signal(chopstick[i]);
signal(chopstick[(i+1) % 5]);
...
//think;
...
} while (TRUE)
仍存在死锁的可能:每个哲学家抢到一根筷子。
- 死锁解决方法
- 限制使用者个数不超过
n-1
。 - 左右的两个筷子必须同时空闲才能拿起。
- 规定拿筷子的顺序。
- 限制使用者个数不超过
解法2
- 使用
AND
信号量实现两根筷子同时拿起。
Var chopstick: array[0, 1, 2, 3, 4] of semaphore:=(1,1,1,1,1);
processi
Repeat
think;
Sswait(chopstick[(i+1)mod 5],chopstick[i]);
eat;
Ssignal(chopstick[(i+1)mod 5],chopstick[i]);
Until false
读者-写者
- 特点
- 读者可共享资源。
- 写者不能共享资源。
解法1
- 利用记录型信号量解决。
semaphore rmutex=1, wmutex =1;
intreadcount =0;
void reader() {
do{
wait(rmutex);
if (readcount==0) wait(wmutex);
readcount++;
signal(rmutex);
...
perform read operation
...
wait(rmutex);
readcount--;
if readcount=0 then signal(wmutex);
signal(rmutex);
}while (TRUE)
}
void writer(){
do{
wait(wmutex)
perform write operation;
signal(wmutex)
}while (TRUE);
}
解法2
- 使用信号量集解决。
6、进程间通信(掌握)
- 范围
- 此处指的是一台主机内部的两个进程。
- 形式
- 消息传递
- 进程间不能直接访问
- 管道
- 共享存储区
- 不需要拷贝
- 邮箱机制
- 消息传递
通信方式
-
通信内容类型
- 控制信息
- 低级通信
- 批量数据
- 高级通信
- 控制信息
-
低级通信
- 进程之间同步与互斥的过程。
- 效率低。
- 通信对用户不透明。
-
高级通信
- 使用方便,向用户提供一组命令(原语)。
- 高效。
共享存储区
- 例子
- 生产者和消费者通过共享缓冲区实现数据传递。
- 共享数据区
- 属于每个相互通信进程的组成部分。
- 不要求数据移动。
- 一般用于本地通信。
管道通信
- 管道
- 用于连接一个读进程和一个写进程以实现他们之间通信的一个共享文件。
- 形式
- 向管道提供输入的发送进程,以字符流形式(无格式)将数据送入管道。
- 接收管道输出的接收进程(读进程),从管道中读数据。
消息传递方式
- 形式
- 以格式化的消息为单位的数据交换。
- 实现方法
- 直接通信
- 间接通信
进程同步方式
- 方式
- 发送进程阻塞、接收进程阻塞(汇合)。
- 发送进程不阻塞、接收进程阻塞。
- 发送进程和接收进程均不阻塞。
只要发送进程不阻塞,就说明存在中介缓冲区。
信箱通信方式
-
信箱
- 进程之间需要通过共享数据结构的实体进行通信,该实体就是信箱。
-
创建和撤销
- 创建者给出信箱名字、信箱属性和共享者名字。
- 使用撤销原语将之撤销。
-
发送和接收
- 必须使用共享信箱。
- 利用系统提供的通信原语进行通信。
-
信箱分类
- 差异在于可以读的范围不同。
- 私用信箱
- 可自己创建。
- 可采用单向通信链路。
- 公用信箱
- 由操作系统创建。
- 提供给所有核准进程使用。
- 采用双向通信链路。
- 共享信箱
- 由某进程创建。
消息缓冲队列通信机制
数据结构
- 消息缓冲区
typedef struct message_buffer {
int sender;
int size;
char *text;
sruct message_buffer *next;
}
PCB
中应增加的数据项。
struct message_buffer * mq; //消息队列队首指针
semaphore mutex; //消息队列互斥信号量
semaphore sm; //消息队列资源信号量
发送原语
procedure send(receiver, a)
begin
getbuf(a.size,i); //根据a.size申请缓冲区;
i.sender∶ =a.sender;
//将发送区a中的信息复制到消息缓冲区之中;
i.size∶ =a.size;
copy(i.text, a.text);
i.next∶ =0;
getid(PCB set, receiver.j); //获得接收进程内部标识符;
wait(j.mutex);
insert(j.mq, i); //将消息缓冲区插入消息队列;
signal(j.mutex);
signal(j.sm);
end
接受原语
procedure receive(b)
begin
j∶ =internal name; //j为接收进程内部的标识符;
wait(j.sm);
wait(j.mutex);
remove(j.mq, i); //将消息队列中第一个消息移出;
signal(j.mutex);
b.sender∶ =i.sender;
//将消息缓冲区i中的信息复制到接收区b;
b.size∶ =i.size;
copy(b.text, i.text);
releasebuf(i);
end
7、线程的基本概念(重要)
- 引入原因
- 线程能比进程更好地提高程序的并行执行程度。
- 线程共享存储区,故线程之间不需要通信。
- 降低时空开销。
线程的引入
- 进程的基本属性
- 资源所有权
- 一个进程对应一个虚地址空间。
- 拥有对资源的控制和所有权。
- 调度/执行
- 进程是
OS
调度的实体。
- 进程是
- 资源所有权
- 区分进程线程
- 调度并分派的部分是线程/轻便线程(执行单位)。
- 资源所有权的部分通常称为进程。
线程的属性
- 概念
- 线程是一个被调度和分派的基本单位并可独立运行的实体。
- 特点
- 线程可并发执行。
- 共享进程资源。
- 挂起/终止进程会挂起/终止进程中的所有线程。
- 线程是轻型实体,切换时只保存少量寄存器的内容。
线程一定附属于某个进程。
线程和进程的比较(考过)
-
调度的基本单位
- 线程促进了并发的效率。
-
并发性
-
拥有资源
- 运行栈。
-
独立性
- 比进程低。
-
系统开销
- 更少,更快。
-
支持多处理机系统
-
优点
- 在已有进程中创建一个新线程比创建一个全新进程所需时间少。
- 终止一个线程比终止一个进程花费少。
- 线程间切换比进程快。
- 线程提高了不同执行程序间通信的效率。
线程状态和线程控制块
状态
- 运行
- 就绪
- 阻塞
线程控制块
- 作用
- 用于控制和管理线程。
- 内容
- 线程标志符
- 一组寄存器
CPU
的保存信息。
- 线程运行状态
- 优先级
- 专有存储区
- 用户栈
- 信号屏蔽
- 信号交给执行实体。
- 基本操作
- 派生
- 产生新进程时,为进程派生一个初始化线程。
- 阻塞
- 线程需要等待一个事件时,将其阻塞。
- 接触阻塞
- 等待事情发生后,线程被转移到就绪队列中。
- 结束
- 释放寄存器和栈的内容。
- 线程没有终止时,等待进程终止。
- 派生
- 注意
- 仍然有一个与进程相关联的进程控制块和用户地址空间,但是每个线程都有一个独立的栈和独立的线程控制块TCB,包含寄存器值、优先级和其他与线程相关的状态信息。
- 进程中的所有线程共享该进程的状态和资源,它们驻留在同一块地址空间中,并且可以访问到相同的数据。
- 线程阻塞不一定引起进程阻塞。
- 系统调用时进入核心态时,若线程阻塞则其所在进程也会被阻塞。
- 在同一进程中的线程切换不会引起进程切换。
- 在不同一进程中的线程切换会引起进程切换。
8、线程的实现
- 线程分为
- 内核级线程
- 用户级线程
- 组合方式
内核级线程
- 概念
- 是在内核的支持下运行的,即无论是用户进程中的线程,还是系统进程中的线程,他们的创建、撤消和切换等,也是依靠内核实现的。
- 特点
- 知道线程存在,调度其本身。
- 在内核空间为每一个内核线程设置了一个线程控制块。
- 优点
- 内核可以同时把同一个进程中的多个线程调度到多个处理器中并行执行。
- 如果进程中的一个线程被阻塞,内核可以调度同一个进程中的另一个线程,也可以运行其它进程的线程。
- 内核例程自身也是可以使用多线程的。
- 结构简单,高效。
- 缺点
- 是在同一个进程中把控制从一个线程传送到另一个线程, 需要从用户态转到内核态进行,线程调度和管理是在内核实现的,系统开销较大。
用户级线程
- 概念
- 用户级线程的创建、撤消、线程之间的同步与通信等功能,都无须利用系统调用来实现,用户级线程的切换也无须内核的支持。
- 优点
- 线程控制块设置在用户空间,内核完全不知道用户级线程的存在,这样可以节省模式切换系统开销。
- 各进程可以独立选择线程调度算法。
- 用户级线程与操作系统平台无关,甚至可以在不支持线程机制的操作系统平台上实现。
- 缺点
- 当线程执行系统调用引起进程阻塞时,进程中所有的线程都会被阻塞,会削弱进程中的线程的并发性。而内核支持线程不存在这个问题。
- 由于内核每次给一个进程分配一个CPU,用户级线程不能有效利用多处理机进行进程内的多线程并行操作。
调度单位为进程。
习题
题目一
题目二
题目三
题目四