9.多进程图像的引出——多进程图像

1. 什么是多进程图像?

  1. 如何使用CPU? 让程序执行起来
  2. 如何充分利用CPU? 启动多个程序,交替执行
  3. 多进程图像:多个进程使用CPU的图像

操作系统 把这些 启动了的程序(进程)用PCB记录好,再按照合理的次序推进(分配资源、进行调度)
PCB:Process Control Block,用来记录进程信息的 数据结构

2.多进程如何组织?

这里写图片描述

有程序在执行;有一些进程在等待执行,放在就绪队列中;有一些进程在等待某个事件,放在 磁盘等待队列
PCB 用来记录进程信息的 数据结构,帮助系统 感知、管理进程

3.多进程的组织:PCB + 状态 + 队列

这里写图片描述

举例说明 进程状态:
银行窗口办理业务
运行态:正在办理业务的人
就绪态:后边等待的人
阻塞态:等待的人 特别多,超出等待队列范围,剩下的 办理业务的人 就是阻塞态
终止态:办理完业务的人

多进程组织:PCB放到不同的队列中,通过 切换进程的状态 推进进程

4.多进程如何交替?

  1. 一个进程启动磁盘读写;
  2. 状态置为阻塞态(pCur.state = ‘W’;)
  3. 将当前进程的PCB pCur 放到 磁盘阻塞队列(DiskWaitQueue)
  4. schedule() 切换进程:保护当前进程的现场,恢复下一个进程的 执行现场
schedule()
{
    pNew = getNext(ReadyQueue);// getNext 根据就绪队列找到下一个进程
    switch_to(pCur, pNew); // switch_to根据当前进程和下一个进程的PCB (pCur,pNew) 做切换
}

5. 进程交替的三个部分:队列操作+调度+切换

进程调度是一个很深刻的话题,如今也是 值得研究的课题

  • FIFO:先进先出,公平策略,没有考虑进程执行的任务的区别
  • Priority:优先级,优先级怎么设定?依靠 优先级,可能会导致进程饥饿。

切换进程时需要:
保存 正在执行的进程的 现场:将 物理CPU的该进程的信息,包存到 一个结构体 PCB中
恢复 要执行的进程的 现场:将该进程对应的PCB 恢复到 物理CPU中
该过程需要 精细控制,需要用 汇编实现

6.多进程的地址空间分离

问题:
进程1 用到了 地址100的值,进程2 会修改 地址100的值。进程1 2同时运行,会出错。
解决:
限制对地址100的读写,每个进程都有自己的映射表,进程1的地址100可能对应的物理内存地址的780
进程2的映射表的100,对应的物理地址 可能是 1260,通过映射表实现进程的隔离

这里写图片描述

多进程的地址空间分离 是 内存管理的主要内容

7.多进程如何合作?

7.1 问题1:打印的例子

打印是将要打印的内容放到打印队列,打印机从打印队列中取数据,打印。这时打印队列有6个打印数据,
进程1,2都要打印,同时往打印队列里加 数据,那么打印队列 第7个打印数据是哪个呢?

7.2 问题2:生产者 消费者例子

buffer是共享缓冲区
生产者 生产数据,往buffer里加数据 buffer[in] = item;
消费者 消耗数据,从buffer里取数据 item = buffer[out];
通过共享变量 counter 判断,生产者是否再生产,消费者是否再消耗

如果counter错了:
生产者中,buffer已经满了,counter != BUFFER_SIZE,还往buffer里写数据,就把原来的数据冲掉了
消费者中,buffer已经空了,counter != 0,还要从buffer里取数据,其实buffer已经空了

//生产者
while(true){
    //counter 是一个共享的变量,当buffer满了,就不再生产,不往buffer里写数据了
    while(counter == BUFFER_SIZE)
        ;
    buffer[in] = item;
    in = (in + 1) % BUFFER_SIZE;
    counter++;
}
//消费者
while(true){
    while(counter == 0)
        ;
    item = buffer[out];
    out = (out + 1) % BUFFER_SIZE;
    counter--;
}
//共享数据
#define BUFFER_SIZE 10
typedef struct{...}item;
item buffer[BUFFER_SIZE];
int in = out = counter = 0;

举例说明 counter 错了
正常情况:
共享数据 int counter = 0;

//生产者P counter++;
register = counter;
register = register + 1;
counter = register;
//消费者C counter--;
register = counter;
register = register - 1;
counter = register;

出错例子:
设 初始值 counter = 5,生产者进程 执行一半,切到 消费者进程

// 生产者进程
P.register = counter;// counter = 5
P.register = P.register + 1; // P.register = 6, counter = 5

//消费者进程
C.register = counter; // C.register = 5
C.register = C.register - 1; // C.register = 4, counter = 5

counter = P.register; // counter = 6

counter = C.register; //counter = 4

正常情况,初始值 counter = 5,生产1个,消费1个,结束时 counter = 5
上边的错误情况,counter = 4

7.3 解决:合理的推进进程顺序

这里写图片描述

操作counter之前 要看 是否已经锁上了,锁了不能操作counter;没上锁,操作counter前 要上锁,用完了 要解锁

//生产者进程
// --给counter上锁
P.register = counter;//counter = 5
P.register = P.register +1; // P.register = 6, counter = 5

//此时消费者要执行,检查锁,发现counter锁上了,不能执行消费者代码

//生产者 继续执行
counter = P.register; // counter = 6
// --给counter解锁

//消费者执行
// -- 给counter上锁
C.register = counter;
C.register = C.register - 1;
counter = C.register; // counter = 5

操作系统通过PCB来感知多进程,PCB是系统中 最重要的结果,贯穿系统始终,后续课程会继续讲解

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值