1.进程
1.1 终止
正常退出(自愿)
出错退出(自愿)
严重错误(非自愿)
被其他进程杀死(非自愿)
1.2 状态
就绪态:可运行,但因为其他进程正在运行而暂时停止
阻塞态:除非某种外部事件发生,否则进程不能运行
1.3 实现
一个进程在执行过程中可能被中断数千次,但每次中断后,被中断的进程都返回到与中断发生前完全相同的
中断发生后OS的底层工作
2.线程
2.1 模型
线程比进程更轻量级
通常每个线程会调用不同的过程,从而有不同的执行历史,因此每个线程需要自己的堆栈
第一列是一个进程中所有线程共享的内容,第二列是每个线程自己的内容
2.2 实现
用户空间中实现、内核空间中实现
混合实现
上行调用机制:
内核了解到一个线程被阻塞后,通知该进程的运行时系统,并在堆栈中以参数形式传递有问题的线程编号和所发生的事件的描述
内核通过一个已知的起始地址启动运行时系统,从发出通知
调度程序激活机制:
一旦如此激活,运行上系统就重新调度其线程
弹出式线程:
没有历史-没有必须存储的寄存器、堆栈等,每个线程从全新开始,每个线程彼此都完全一样,因此可能快速创建线程
3.进程间通信IPC
三个问题:传递、交叉、顺序
3.1 竞争
竞争条件:两个或多个进程读写某些共享数据,而最后的结果取决于进程运行的精确时序
互斥:阻止多个进程同时读写共享的数据
临界区:对共享内存进行访问的程序片段
解决竞争的4个条件:
任何两个进程不能同时处于临界区
不应该对CPU的速度和数量进行假设
临界区外运行的进程不得阻塞其他进程
不得使进程无限期等待加入临界区
忙等待的互斥:
屏蔽中断:
CPU只有发生时钟中断或其他中断时才会切换进程
屏蔽一个CPU的中断不会阻止其他CPU干预第一个CPU
锁变量:
类似于flg标记状态,读写间可能被插队
严格轮换法:
忙等待:连续测试一个变量直到某个值出现,但浪费CPU时间
自旋锁:用于忙等待的锁
一个进程比另一个慢很多时,不适合,违背条件3
TSL指令(测试并加锁 Test and set lock):
需要硬件支持
锁住内存总线,以禁止其他CPU在本指令结束之前访问内存
Peterson算法:
3.2 信号量
原子操作:一组关联的操作,要么都不间断地执行,要么都不执行
down:s>0则减1,s=0则挂起
up:抵消一个挂起的down,否则s加1
生产者-消费者问题:
二元信号量mutex:初始化为1保证任意时刻只有一个进程读写缓冲区和相关的变量
若每个进程在进入临界区前都执行一个down,在刚退出时执行一个up,就可以实现互斥
3.3 互斥量
只有一个缓冲区的生产者-消费者问题:
3.4 管程
一个管程是一个由过程、变量、数据结构等组成的集合,他们组成一个特殊的模块或软件包
进程可以在任何需要的时候调用管程中的过程,但不能在管程之外声明的的过程直接访问管程内的数据结构
任一时刻,管程中只能有一个活跃进程
3.5 消息传递
3.6 屏障
除非所有进程都就绪准备着手下一阶段,否则任何进程都不能进入下一阶段
当一个进程到达屏障时,会被阻拦,直到所有进程都到达屏障