引入
1. 程序:源代码程序、目标程序、可执行程序
2. 程序执行:编写、编译、链接、执行
3. 交换:将部分进程换出到外存,腾出内存空间。被换出去的进程处于挂起状态。只有挂起它的进程才能恢复被挂起的进程。
4. 虚拟存储:每个进程只能装入一部分程序和数据
进程描述及控制
1. 进程的概念
申请/拥有资源的单位
程序是静态概念,进程是存在于内存的动态概念,表现为程序的运行
2. 进程的结构
程序
数据集合
进程控制块PCB
PCB是进程存在的唯一标识,PCB代表着进程是不是存在
3. PCB的构成
(1)构成
进程标识信息
处理机状态信息
进程调度信息
其它信息
(2)组织方式
单一队列
通过链表组织成单一队列,适用进程数目不多,否则查找困难。插入、删除都麻烦
表格结构
PCB按照进程状态不同,组织成不同的表:就绪进程表、执行进程表、阻塞进程表
4. 进程的状态
(1)五状态
新建-->就绪
就绪-->被调度-->执行
执行-->时间到-->就绪
执行-->IO等待-->阻塞
执行-->完成-->终止
阻塞-->IO完成-->就绪
(a)某些系统,父进程可任何情况下终止子进程
(b)父进程终止、子进程必须终止
(2)具有挂起的进程状态图
(a)阻塞挂起,当事件发生时,变成就绪挂起
5. 进程的创建
(1)系统为进程分配唯一标识ID,PID
(2)主进程表增加表项,记录进程对应的PCB
(3)为进程分配空间:用户地址空间、用户栈空间、PCB空间。有共享内存,就建立链接
(4)初始化PCB:进程标识、状态
(5)建立链接:插入调度队列
进程调度
1. 调度方式
进程调度方式分为剥夺式和非剥夺两种。
IO阻塞并非剥夺,属于主动放弃CPU
2. 调度类型
长程调度:作业从外存调进来
中程调度:交换出去外存的挂起进程调进来
短程调度:
3. 调度算法
(1)FCFS先来先服务:非剥夺,对短时进程不公平,对IO型不公平。整个等待时间肯定长
(2)短进程优先:非剥夺,但是需要对进程进行排序,而且难以估算进程时间
(3)时间片轮转:分时联机系统,剥夺式,进程切换多,额外开销,时间片大小问题。对短进程有利,不利于IO型进程,中断太多不适合批处理
(4)基于优先级:典型的是剩余时间减少优先级提高、排队时间增加优先级提高。反馈调度法就是很好的一个实现。
(5)反馈调度法:根据历史执行情况进行调整,结合了优先级和时间片轮转调度思想
根据优先级分多个就绪队列,每个队列的时间片递增。
就绪队列0 时间片0 优先级高
就绪队列1 时间片1
...
就绪队列n 时间片n 优先级低
线程
1. 为什么引入线程
为了减少程序并发执行时系统所付出的额外开销,使系统有更好的并发性。比如有些应用场景,必须是多进程/多线程并发才能实现功能的,如果采用进程的话,需要增加创建进程时候的开销,另外就是进程切换的时候,要保护现场等,比线程切换复杂。
线程是进程的一个实体,自身不拥有系统资源,只拥有少许运行中必不可少的私有资源。线程可与同属一个进程的其它线程共享进程的全部资源。
2. 线程状态
就绪、阻塞、执行
一般没有挂起状态:因为挂起是指将程序和数据交换出去外存,而多个线程是共享程序和数据的。
3. 进程与线程区别
(1)进程是资源申请的最小单位,线程是系统调度的最小单位
(2)进程切换开销比线程切换要大,线程具有相同的地址空间,使得线程间通信同步容易
(3)进程有挂起,线程没有
(4)windows、linux采用多进程、多线程技术
UNIX采用多进程、单线程技术
java虚拟机采用单进程、多线程技术
MS DOS采用单进程、单线程技术
4. 用户级线程和内核级线程
这个跟具体操作系统设计有关,而不是应用程序自己决定采用哪种的。
5. 线程阻塞会否造成进程阻塞
(1)如果是线程1等待线程2而阻塞,不会引起进程阻塞
(2)如果是线程1等待IO而阻塞,内核需要启动系统IO,控制从用户级转向内核级,会引起进程阻塞
互斥与同步
1. 同步:协作 互斥:竞争
2. 临界资源:一次只允许一个进程访问的资源。
临界区:访问临界资源的那段代码
3. 互斥条件
忙则等待
有限等待
空闲让进
让权等待
4. 死锁和饥饿
5. 实现方法
(1)软件方法
(a)进程严格顺序使用临界区
(b)为临界区设置一个状态标志,“忙”和“空闲”。问题:同时进入了。
(c)先表明要进去,然后再看下对方进去没。问题:都不进去
(d)谦让一段时间,再重新尝试进去
(e)有序谦让
(2)硬件方法
(3)信号量方法
(a)信号量定义
信号量包括如下机构:
count:可用资源数
queue:阻塞进程队列
(b)原语
原子操作,操作系统保证了一次执行不可中断。
wait(s) == P(s) 申请信号量,s--,判断s>=0则进入临界区,否则阻塞,s绝对值表示有多少个被阻塞的进程
signal(s) == V(s) 释放信号量,s++,判断s<=0,唤醒一个进程,s绝对值表示有多少个被阻塞的进程
(c)信号量类型
互斥信号量
资源信号量
经典问题
1. 生产者/消费者问题
(1)特点:生产者创建数据,消费者使用数据,用完就没了,消耗型的。生产者可以多个,消费者也可以多个。
(2)生产者消费者共享大小固定的缓冲区。假设缓冲区大小为n,有插入指针和取出指针
(3)要求:
生产者与生产者之间要互斥
生产者与消费者之间要互斥
生产者不能向满缓冲区写数据
消费者不能向空缓冲区取数据
e: 资源信号量,表示缓冲区大小
n:资源信号量,非空单元
x:互斥信号量,对缓冲区的操作权限
生产者:
wait(e)
wait(x)
生产数据
signal(x)
signal(n)
消费者:
wait(n)
wait(x)
取走数据
signal(x)
signal(e)
(4)资源信号量要先申请,然后再申请互斥信号量。也就是说多的要先申请。
2. 读者/写者问题
要求:
写者间互斥
写者读者间互斥
读者间可同时读
读完数据还在
(1)读者优先
读者:
wait(x)
reader++;
if(reader == 1)
wait(wsem)
signal(x)
读数据
wait(x)
reader--;
if(reader == 0)
signal(wsem)
signal(x)
写者:
wait(wsem)
写数据
signal(wsem)
(2)写者优先
读者:
wait(z)
wait(rsem)
wait(x)
reader++;
if(reader == 1)
wait(wsem)
signal(x)
signal(rsem)
signal(z)
读数据
wait(x)
reader--;
if(reader == 0)
signal(wsem)
signal(x)
写者:
wait(y)
writer++;
if(writer == 1)
wait(rsem)
signal(y)
wait(wsem)
写数据
signal(wsem)
wait(y)
writer--;
if(writer == 0)
signal(rsem)
signal(y)
进程通信
1. 进程通信类型
控制信息和数据信息
2.常用的进程通信机制
(1)共享存储区
(1.1)要求本地进程之间,数据空间固定
(1.2)同步互斥方式:
程序设计
操作系统实现:进程将存储区连接到本地进程中,互斥同步由操作系统实现,进程只管读写。
(2)消息传递
(2.1)消息格式
消息头:消息类型+目的地址+原地址+消息长度+控制信息
消息体:消息内容
Send原语:如果没有空闲的缓冲区,则进程阻塞;
Receive原语:如果缓冲区为空,则进程阻塞;
同步方式:
阻塞发送、阻塞接收
不阻塞发送、阻塞接收:发送进程不是一定要发送的,而接收进程一定要等有数据
不阻塞发送、不阻塞接收
(3)邮箱机制
邮箱:消息的容器
使用邮箱实现互斥同步:创建一个邮箱,里面有一条空消息。接收阻塞方式,读取时如果为空则阻塞,等待进入临界区;如果取到了,就进入临界区。
3. 死锁
(1)安全状态、不安全状态
(2)安全序列、安全算法
4. 哲学家算法
(1)问题描述
五个哲学家围成一桌,5碗面,五支筷子在面左右,同时获得两支筷子才能进食。
(2)死锁
如果每个哲学家都申请自己右边的筷子,再申请左边的筷子,很容易进入死锁
wait(fork(i));
wait(fork(i+1 )mod 5);
eat;
signal(fork(i+1) mod 5);
signal(fork(i));
(3)解决方案
增加一位服务员,先让4位哲学家进餐,4位哲学家竞争5支筷子,肯定有一个能够取得一对,然后再安排最后一位进餐。
room:semaphore(4)
wait(room)
wait(fork(i));
wait(fork(i+1 )mod 5);
eat;
signal(fork(i+1) mod 5);
signal(fork(i));
signal(room);