一、信号
1.信号的定义
用于通知某个进程某个特殊事件已经发生,进程在接受到一个信号后,会对该信号进行处理
2.信号的发送与保存
信号利用kill函数来进行发送和保存
kil函数的表达方式:
int kill(pid,sig)
pid:信号要发给谁;sig:要发什么信号
在PCB中会存储两个n比特位向量
待处理信号(pending)和 被阻塞信号(blocked)
由于是n比特位向量,所以每一位只能存一比特,后到的信号会被舍弃,所以无法区分信号的来源
内核给进程的信号传递无限制,进程之间的信号传递有限制
3.信号的处理
(1)什么时候处理信号?
进程由内核态转变为用户态,需要检查待处理信号
(2)怎么处理?
将blocked按位取反并与pending按位与
每个信号都有对应的处理程序,也可以自定义处理程序,但各进程的处理程序只作用于自己
当信号处理程序结束后,会返回进程的下一条指令继续执行,除非进程阻塞或终止
一但处理了某个信号,其对应的pending归零
进程如果同时接收了多个信号,优先处理小的
4.信号与异常的搭配
信号可以看成异常的配套机制,让进程对操作系统的异常处理做个性化的补充
有些异常内核可以自己全部处理,但是有些异常需要信号进行个性化处理,需要进程配合
但有些信号不能被用户自定义处理程序,也无法被阻塞。如:SIGKILL,SIGSTOP
二、线程
1.引入原因
需要某个进程同时做多个事,但传统进程是串行执行的,无法满足要求,所以引入线程
2.理解线程
一个进程会被分为多个线程,在引入线程后,线程是最小的调用单位
线程可以理解为轻量化的进程,是一个基本的cpu执行单元
3.引入线程所发生的变化
传统:进程既是资源分配的基本单位又是调度的基本单位,只能在进程间进行并发,且并发需要切换环境,系统开销较大
现在:进程只是资源分配的基本单位,线程是调度的基本单位,各线程之间也能并发,提升了并发度,且同一个进程内并发不需要切换环境,系统开销较小
4.线程的实现方式
(1)用户级线程:早期的OS只支持进程,线程由数据库来实现,数据库储存在用户态,由数据库来管理,OS意识不到
优点:线程切换在用户态内,不需要变态,系统开销小
缺点:如果一个线程被阻塞,整个进程都会被阻塞,并发度不高,且多线程不能在多核处理机上并发执行
(2)内核级线程:OS支持线程,线程由内核来进行管理,进程切换需要变态,OS能够意识到
优点:一个线程被阻塞后,进程不会被阻塞,并发度较高
缺点:线程切换需要变态,系统开销较大
5.多线程模型
(1)一对一
一个用户级线程映射到一个内核级线程,每个用户进程有与用户级线程等量的内核级线程
优点:一个线程被阻塞后,进程不会被阻塞,并发度较高
缺点:线程切换需要变态,系统开销较大
(2)多对一
多个用户级线程映射到一个内核级线程
(退化为用户级线程)
优点:线程切换在用户态内,不需要变态,系统开销小
缺点:如果一个线程被阻塞,整个进程都会被阻塞,并发度不高,且多线程不能在多核处理机上并发执行
(3)多对多
n个用户级线程映射到m个内核级线程(n≥m)
该模型成功地克服了上述两个模型的缺点
6.线程的状态与转换
与进程的状态与转换类似
7.线程的组织与管理
由TCB来组织管理
TCB包含线程标识符TID、程序计数器pc、其他寄存器、堆栈指针、线程运行状态、优先级等信息
程序计数器:线程目前执行到哪里
其他寄存器:运行的中间结果
堆栈指针:保存函数的调用信息和局部变量
优先级:线程调度、资源分配的优先级
当线程切换时应保存或恢复程序计数器、其他寄存器、堆栈指针等信息