进程和线程

进程和线程
操作系统的关键抽象:

 

来源《深入理解计算机》


 
比喻:厨师做蛋糕(现代操作系统)
做蛋糕的食谱:程序
做蛋糕的原料:输入数据
厨师:CPU
厨师阅读食谱,用原料做蛋糕的一系列动作的总和:进程


厨师的儿子跑进了,说是被蜜蜂蛰了
-厨师记录下当前做到哪一步了(保存当前进程状态)
-拿出急救手册,按其中的指示进行处理(开始另外一个进程)

把I/O设备抽象成文件,就不用对硬盘,控制台,输出设备进行操作了。
物理主存加文件就是虚拟存储器,是对内存和硬盘抽象,每一个进程都有一个超大空间。内存大小有限,不可能把所有进程都放入内存空间。每个进程有独立虚拟地址空间,会被映射到真实内存中去,程序只有一块代码被调入到真实内存中去,

进程的状态:


进入就绪态并不会占用CPU,操作系统维护一个列表,进程A在等待硬盘操作,就进入硬盘等待设备列表,等待键盘输入,就进入等待键盘列表中,等待位于CPU维护的一个列表中,不会占用CPU,就绪也不会占用。


进程调度:
非抢占式(dos/win3.1/win3.2)
-调度程序一旦把CPU分配给某一进程后便让他一直运行下去,直到进程完成或发生某件事件而不能运行,才将CPU分给其他进程。
-适用批处理系统,不适合交互式操作

-简单、系统开销小


抢占式(win95后)
-当一个进程正在执行时,系统可以基于某种策略剥夺CPU给其他进程。剥夺的原则有:
优先权原则、短进程优先原则、时间片原则
-适用于交互式系统


进程调度:评价标准
公平

-合理的分配CPU


响应时间短

-响应时间:从用户输入到产生反应的时间


吐量大

-吞吐量:单位时间完成的任务数量


批处理系统的调度:

先来先服务

-公平,简单(FIFO队列),非抢占,不适合交互式

最短作业优先

-系统的平均等待时间最短

-但是需要预先知道每个任务的运行时间


交互式调度策略(1):轮转

每个进程分配一个固定时间片

假设进程切换一次的开销为1ms

时间片为4ms

-20%的时间浪费在切换上

时间片为100ms

-浪费只有1%,但是假设有50个进程,最后一个需要等待5s


交互式系统调度策略(2):优先级


交互式系统调度策略(3):多级队列反馈



进程间同步:




多进程情况下,共享变量counter会出错!


初始情况
counter = 3;
生产者(p):
register = counter;
register = register+ 1;
counter = register;
消费者(C):
register = counter;
register = register- 1;
counter = register;
并发执行:
P.register = counter;
P.register = P.register+ 1;
生产者进程被OS打断,执行消费者进程
C.register = counter;
C.register = C.register- 1;
counter = P.register;
counter = C.register;


问题的核心
-不可控制的调度
-在机器层面,counter++,counter--并不是原子操作


临界区
-访问/修改共享资源(变量,表,文件。。。)

-当进程进入临界区时,不允许其他进程在临界区执行




解决临界区问题(1):暴力手段,关闭中断

-CPU收到时钟中断以后偶,会检查当前进程的时间片是否用完,用完则切换。


-在进程p进入临界区之前,通知OS,不要做进程切换不就行了。
--关闭中断(时钟中断),这样CPU就不会被打断
--离开临界区一定要记住打开中断

--但是把中断操作开放给应用程序是非常危险的。





解决临界区问题(3):信号量
信号量S是个整数变量,除了初始化外,有两个操作,wait(),sinal()
或者是P/V,或者down/up

wait(S){
while(S<=0){
;//啥也不做
}
S--;
}

signal(S){
S++;
}

semaphore mutex = 1;
wait(mutex);
进入临界区
signal(mutex);
剩余区

为了确保信号量能工作,需要用一种原子的方式实现它。


解决临界区问题(4):不能忙等

typedef struct{
int value;
struct process *list;
}semaphore;

wait(semaphore *s){
s->value--;
if(s->value<0){
把当前进程加到s->list中;
block();
}
}

wignal(semaphore *s){
s->value++;
if(s->value<=0){
从s->list取出一个进程p
wakeup(p);
}
}


解决临界区问题(5):用信号量解决打印问题
semaphore mutex = 1;
semaphore empty = 5;
semaphore full = 0;

生产者:
while(true)(
wait(empty);
wait(mutex);
把新产生的文件加入队列;
signal(muterx);
signal(full);
)
消费者:
while(true)(
wait(full);
wait(mutex);
把队列头的文件打印,删除;
signal(muterx);
signal(empty);
)


线程:
 

线程的优点:

浏览器

-线程1显示图像

-线程2从网络接收数据

文字处理器

-线程1显示图形

-线程2读取用户键盘输入

-线程3自动定时的保存文档



线程的实现:完全在用户层实现
 

 





 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值