操作系统精选题(一)(PV经典问题之生产者与消费者)

🌈 个人主页:十二月的猫-CSDN博客
🔥 系列专栏: 🏀操作系统

💪🏻 十二月的寒冬阻挡不了春天的脚步,十二点的黑夜遮蔽不住黎明的曙光 

目录

前言

进程互斥与同步

 题目一

题目二

题目三

题目四

题目五

题目六

题目七

题目八

题目九

题目十

题目十一

总结


前言

本系列的重点是大学本科课程《操作系统概念》。总结操作系统学习中的各类知识点,并且对各类操作系统试中可能遇到的题型和对应的解法做总结归纳。在自我复习的同时也将这份心得带给大家,希望能对大家的操作系统学习提供帮助~~

进程互斥与同步

 题目一

1、wait与signal为什么要设计成原语?

解:

原语是指不可分的操作,是具有原子性的操作。安全性:wait和signal操作是用于信号量的控制,在信号量的变化过程中不允许其他进程抢占这个进程;原子性:wait和signal操作要求是原子的,也就是说这两个操作必须是不可分的,要么全完成,要么全不完成,不存在中间状态;一致性:wait和signal操作在所有系统的信号量处理中都要使用到,原语保证其是通用的,保持在所有系统中一致

题目二

经典PV问题——有界缓存

1、存在临界资源——>定义互斥锁

2、有界缓存——>定义信号量full、empty

3、生产者代码

4、消费者代码

生产者、消费者代码编写流程:

1、找进程:确定谁是消费者,谁是生产者 

2、找主营业务:一般都是一句话带过

3、找同步约束

  •  互斥
  • 资源(计数信号量、空闲空间信号量等)
  • 限额 

2、一个输入进程向一个缓冲区中输入数据,另一个输出进程从缓冲区中取出数据输出。缓冲区中每次只能存放一个数。

解:

semaphore empty=1;// 有界缓存区大小为1
semaphore full=0;// 开始有界缓冲区不为满
semaphore mutex=1;

producer{
    do{
        /*produce item*/
        wait(empty)
        wait(mutex)
        /*put item into the buffer*/
        signal(mutex)
        signal(full)
    }while(true)
}
consumer{
    do{
        wait(full)
        wait(mutex)
        /*get item from the buffer*/
        signal(mutex)
        signal(empty)
        /*consume the item*/
    }while(true)
}

题目三

有界缓存的变型

1、存在临界资源——>定义互斥锁

2、有界缓存——>定义信号量full、empty

3、输出进程只能拿加工后的数据——>进程存在执行顺序——>定义信号量去控制执行顺序

3、生产者代码

4、消费者代码

生产者:计算进程(送数)

消费者:加工进程、输出进程

输出进程和加工进程之间存在确定执行顺序 

3、三个进程共享一个缓冲区。一个计算进程送数;一个加工进程取出加工,然后将加工结果再送回缓冲区;一个输出进程将加工后的数据取出打印。缓冲区中每次只能存放一个数。

解:

semaphore empty=n;// 有界缓存区大小为n
semaphore full=0;// 开始有界缓冲区不为满
semaphore mutex=1;
semaphore processed=0;//已被加工的数据数量

producer{
    do{
        /*produce item*/
        wait(empty)
        wait(mutex)
        /*put item into the buffer*/
        signal(mutex)
        signal(full)
    }while(true)
}
process{
    do{
        wait(full)
        wait(mutex)
        /*get item from the buffer*/
        signal(mutex)
        signal(empty)
        /*process the item*/
        wait(empty)
        wait(mutex)
        /*put the item into buffer*/
        signal(mutex)
        signal(full)
        signal(processed)
    }while(true)
}
consumer{
    do{
        wait(full)
        wait(processed)
        wait(mutex)
        /*get item from the buffer*/
        signal(mutex)
        signal(empty)
        /*consume the item*/
    }while(true)
}

题目四

4、三个进程共享一个缓冲区。一个负责向缓冲区送数;一个取偶数输出,另一个取奇数输出。缓冲区中每次只能存放一个数。

解:

semaphore empty=n;// 有界缓存区大小为n
semaphore full=0;// 开始有界缓冲区不为满
semaphore mutex=1;
semaphore odd=0;//偶数信号量
semaphore even=0;//奇数信号量

producer{
    do{
        item=produce_item()
        wait(empty)
        wait(mutex)
        buffer.put(item)
        if item is even
            signal(even)
        else
            signal(odd)
        signal(mutex)
        signal(full)
    }while(true)
}
consumer1{
    do{
        wait(full)
        wait(odd)
        wait(mutex)
        item = buffer.get()
        signal(mutex)
        signal(empty)
        process(item) 
    }while(true)
}
consumer2{
    do{
        wait(full)
        wait(even)
        wait(mutex)
        item = buffer.get()
        signal(mutex)
        signal(empty)
        process(item) 
    }while(true)
}

题目五

5、四个进程共享一个缓冲区,一个送偶数,一个送奇数,一个取偶数,一个取奇数。缓冲区中每次只能存放一个数。

解:

semaphore empty=n;// 有界缓存区大小为n
semaphore full=0;// 开始有界缓冲区不为满
semaphore mutex=1;
semaphore odd=0;//偶数信号量
semaphore even=0;//奇数信号量

producer1{
    do{
        item=produce_item()
        wait(empty)
        wait(mutex)
        buffer.put(item)
        signal(even)
        signal(mutex)
        signal(full)
    }while(true)
}
producer2{
    do{
        item=produce_item()
        wait(empty)
        wait(mutex)
        buffer.put(item)
        signal(odd)
        signal(mutex)
        signal(full)
    }while(true)
}
consumer1{
    do{
        wait(full)
        wait(odd)
        wait(mutex)
        item = buffer.get()
        signal(mutex)
        signal(empty)
        process(item) 
    }while(true)
}
consumer2{
    do{
        wait(full)
        wait(even)
        wait(mutex)
        item = buffer.get()
        signal(mutex)
        signal(empty)
        process(item) 
    }while(true)
}

题目六

生产者-消费者问题变型——不存在生产者,利用初始化一次性完成生产

1、一次性完成生产也就不是有界缓存问题——>不需要full和empty

2、拿黑子,拿白子访问一个buffer——>互斥变量mutex

3、拿黑子和白子需要生产后才可以进行,存在先后执行顺序——>信号量white和black(也可以用普通变量来表示white和black的值,不用信号量)

4、先拿黑子,同时进程交替拿棋子,存在执行顺序——>信号量whiteTurn和blackTurn

6、围棋问题:数量相等的黑子与白子混在一起,利用两个进程分开。一个进程拣白子,另一个进程拣黑子。要求:

(1)一个进程拣了一个子,必须让另一个进程拣子;即两个进程应交替拣子;

(2)假定先拣黑子。

解:

semaphore mutex=1;
semaphore whiteTurn=0;
semaphore blackTurn=1;//先拿黑色棋子
semaphore black=n1;
semaphore white=n2;

# 拣黑子的进程
black_picker {
    do {
        wait(blackTurn)          # 等待轮到拣黑子
        wait(black)
        wait(mutex)              # 获取互斥锁,确保独占访问缓冲区
        if buffer has black piece:
            item = buffer.get_black()  # 获取一个黑子
            process(item)        # 处理黑子
        signal(mutex)            # 释放互斥锁
        signal(whiteTurn)        # 释放白子的信号量,让白子进程拣子
    } while (true)
}
# 拣白子的进程
white_picker {
    do {
        wait(whiteTurn)          # 等待轮到拣白子
        wait(white)
        wait(mutex)              # 获取互斥锁,确保独占访问缓冲区
        if buffer has white piece:
            item = buffer.get_white()  # 获取一个白子
            process(item)        # 处理白子
        signal(mutex)            # 释放互斥锁
        signal(blackTurn)        # 释放黑子的信号量,让黑子进程拣子
    } while (true)
}

题目七

进程前驱图作用:

1、体现进程间的执行顺序

2、体现进程间的依赖关系

3、体现进程是否存在死锁等问题

7、画出下面4条语句的前趋图(符号“:=”是赋值的意思)
S1:a:=x+y
S2:b:=z+1
S3:c:=a-b
S4:w:=c+1

解:

题目八

N<A产品数量 – B产品数量<M——>存在同步约束中的限额

限额:(共享量对资源的使用产生限制)(这里就是利用count差值来限制)(差值限额)

1、限额意味着限额要控制进程的活动——>设定两个信号量控制进程活动

2、限额本身需要两个变量来控制——>两个变量控制进程信号量资源的释放

3、限额的检查要在实际操作之前

8、有一个仓库,可以存放X与Y两种产品,仓库的存储空间足够大,但要求:

(1)每次只能存入一种产品(X或Y);

(2)N<A产品数量 – B产品数量<M;

其中,N和M是正整数。试用“存放A”和“存放B”和wait、signal描述产品A与产品B的入库过程。

解:

semaphore mutex=0;
semaphore sem_A=0;//控制A进程的信号量
semaphore sem_B=0;//控制B进程的信号量
int countA=0;
int countB=0;//共享的限额量,全局变量

storeA{
    wait(mutex);
    if countA-countB<M
        signal(sem_A)
    signal(mutex);

    wait(sem_A)
    wait(mutex)
    store(A);
    countA++;
    if countA-countB>N
        signal(sem_B)
    signal(mutex);
}
storeB{
    wait(mutex)
    if countA-countB>N
        signal(sem_B);
    signal(mutex)

    wait(sem_B)
    wait(mutex)
    store(B);
    countB++;
    if countA-countB<M
        signal(sem_A)
    signal(mutex)
}

注意!!

这里为了提高进程运行的效率也可以设定两个互斥信号量:1、mutex_buffer;2、mutex_count。实现对不同临界资源的限制 

1、确定生成者消费者

2、写主营业务

3、找限额控制进程信号量写上(常有两个对应的存在)

4、资源视角找同步约束(进程控制信号量)

5、找互斥

题目九

多生产者-多消费者问题+广播机制

1、多生产者-多消费者意味着实际运行需要开许多进程同步来跑

2、m个缓冲区每个放一个信息 等价于 一个缓冲区放m个信息

2、广播机制则要将一个缓冲区看为多个缓冲区,一个读进程单独享有一个缓冲区

9、进程A1、A2,……,An1通过m个缓冲区向进程B1,B2,……,Bn2不断地发送消息。发送和接收工作遵循如下规则:

(1)每个进程发送一个消息,写入一个缓冲区,缓冲区大小与消息长度一样;

(2)对每一个消息,B1,B2,……,Bn2都需各接收一次,读入各自的数据区中;

(3)m个缓冲区都满时,发送进程等待,没有可读取的消息时,接收进程等待。

试用wait与signal操作组织正确的发送和接收操作。

解:

int n2;//存在n2个读进程,这个值不是临界资源
semaphore empty[n2] = m;
semaphore full[n2] = 0;

//创建n1个写进程,都用下面的代码
producer{
    while(1)
    {
        for(int i=0;i<n2;i++)
        {
            P(empty[i]);
        }
        P(mutex);
        消息放入缓冲区;
        V(mutex);
        for(i = 0;i<n2;i++)
        {
            V(full[i]);
        }
    }
}
//创建n2个读进程,给不同的arg值和producer中的full和empty对应
consumer(void* arg){
    id=(int)arg
    while(1)
    {
        P(full[id]);
        P(mutex);
        读取缓冲区;
        V(mutex);
        V(empty[i]);
    }
}

题目十

本题和前面的限额问题没有区别,就是消费者消费、生产者生产需要按照队列去组织以实现FIFO

这里的限额是:差值限额

10、有一个仓库存放两种零件A和B,最大库容为各为m个。有一个车间不断地取A和B进行装配,每次各取一个。为避免零件锈蚀,遵循先入库者先出库的原则。有两组供应商分别不断地供应A和B(每次一个)。为保证齐套和合理库存,当某种零件的数量比另一种的数量超过n(n<m)个时,暂停对数量大的零件的进货,集中补充数量少的零件。试用wait和signal正确实现之。

解:

int m = 10; // 缓冲区大小
int n = 3;  // 数量差异限制
int n2;     // 读进程数量

semaphore mutex = 1; // 互斥信号量
semaphore sem_A = 0; // 控制A进程的信号量
semaphore sem_B = 0; // 控制B进程的信号量
int countA = 0;      // A零件计数器
int countB = 0;      // B零件计数器

void producerA() {
    while(1) {
        wait(mutex);
        if (countA - countB < m) {
            signal(sem_A);
        }
        signal(mutex);

        wait(sem_A);
        wait(mutex);
        // 消息放入缓冲区(存储A零件)
        countA++;
        printf("Stored A part, countA: %d\n", countA);
        if (countA - countB > n) {
            signal(sem_B);
        }
        signal(mutex);
    }
}

void producerB() {
    while(1) {
        wait(mutex);
        if (countB - countA < m) {
            signal(sem_B);
        }
        signal(mutex);

        wait(sem_B);
        wait(mutex);
        // 消息放入缓冲区(存储B零件)
        countB++;
        printf("Stored B part, countB: %d\n", countB);
        if (countB - countA > n) {
            signal(sem_A);
        }
        signal(mutex);
    }
}

void consumer(void* arg) {
    int id = (int)arg;
    while(1) {
        wait(sem_A); // 等待A零件
        wait(sem_B); // 等待B零件
        wait(mutex);
        // 从缓冲区读取零件A和B进行装配
        countA--;
        countB--;
        printf("Workshop assembled A and B, countA: %d, countB: %d\n", countA, countB);
        signal(mutex);
        signal(sem_A); // 通知可以放入新的A零件
        signal(sem_B); // 通知可以放入新的B零件
    }
}

题目十一

1、多生产者单消费者问题+有界缓冲+限额

2、在其他网站上看到很多人会选择增加一个guard进程来控制,但是实际上能够从限额的角度去看待这个PV问题,不需要增加一个监视进程

3、单消费者意味着不可能存在广播,没有广播需求即只有一个消费者在乖乖拿东西,那也就是说仅仅需要一个有界缓冲区即可(一个消费者只能拿一个缓冲区、一个缓冲区只能接受一个消费者。两者是一一对应关系) 

11、某高校计算机系开设网络课并安排上机实习。假定机房共有2m台机器,有2n个学生选该课,规定:

(1)每两个学生组成一组,各占一台机器,协同完成上机实习;

(2)只有一组两个学生到齐,并且此时机房有空闲机器时,该组学生才能进入机房;

(3)上机实习由一名教师检查,检查完毕,一组学生同时离开机房。

试用wait和signal正确实现之。

  • 学生是生产者
  • 教师是消费者
  • 电脑是有界缓冲区,也就是共享资源
  • 两个学生绑定为一个,也就是两台电脑绑定为一个。即有界缓存是m个资源
  • m个有界缓冲区每个一个空间可以认为是一个有界缓冲区有m个空间

解:

int m ; // 机房机器数量
int n ;  // 学生组数量(每组2个学生)

semaphore machine_num=m;    // 表示有界缓冲区的数量
semaphore mutex=1;            // 保护共享资源的互斥信号量
semaphore pair_sem=0;         // 用于限额释放的信号量(配对限额)
int waiting_students = 0;     // 记录已经到达的学生数量
semaphore teacher_sem=0;      // 表示教师可以进行检查
semaphore studentGroup_sem=0; // 表示学生可以离开

student{
    while(1){
        //学生过来
        wait(mutex)
        waiting_students++
        if(waiting_students%2==0)
            signal(pair_sem)
        signal(mutex)

        wait(pair_sem)
        wait(machine_num)
        wait(machine_num)
        wait(mutex)
        //操作电脑
        signal(mutex)
        signal(teacher_sem)
        wait(studentGroup_sem)
        //离开实验室
        signal(machine_num)
        signal(machine_num)
        
    }
}
teacher{
    wait(teacher_sem)
    wait(mutex)
    //检查学生作业
    signal(mutex)
    signal(studentGroup_sem)
}

总结

本文到这里就结束啦~~下节课我们再来进入剩下的三种调度算法
如果觉得对你有帮助,辛苦友友点个赞哦~

知识来源:操作系统概念(黑宝书)、山东大学高晓程老师PPT及课上讲解、山东大学操作系统往年题、部分考研题。不要私下外传

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/729103.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

开发uniapp插件包aar文件,使uniapp可以调用jar包

背景 使用 uniapp 开发应用时&#xff0c;很多时候都需要调用第三方的sdk&#xff0c;一般以 jar 为主。为了应对这个问题&#xff0c;官方提供了插件方案&#xff0c;可以将第三方 jar 包进行封装为 aar 包后&#xff0c;再集成到 uniapp 中使用。 一、环境安装工具 1、jdk…

后台管理台字典localStorage缓存删除

localStorage里存放了如以下dictItems_开头的字典数据&#xff0c;localStorage缓存是没有过期时间的&#xff0c;需要手动删除。同时localStorage里还存有其他不需要删除的数据。 这里的方案是遍历localStorage&#xff0c;利用正则和所有key进行匹配&#xff0c;匹配到dict…

qt打包失败 ,应用程序无法正常启动0xc000007b解决办法

用 windeployqt 打包QT程序&#xff0c;运行时提示程序无法正常启动0xc000007b #原因&#xff1a;因本机装了多个版本的Qt&#xff0c;包括32位&#xff0c;64位的&#xff0c;在cmd下可能是环境变量原因&#xff0c;用 windeployqt 打的包无法运行 解决办法&#xff1a; 1、…

【netty】三万字详解!JAVA高性能通信框架,关于netty,看这一篇就够了

目录 1.概述 2.hello world 3.EventLoop 4.channel 4.1.同步 4.2.异步 4.3.调试 4.4.关闭 4.5.为什么要用异步 5.future 6.promise 7.pipeline 8.byteBuf 8.1.创建 8.2.内存模式和池化 8.2.1.内存模式 8.2.2.池化 8.3.组成 8.4.操作 8.4.1.读写 8.4.2.释放…

内容安全复习 2 - 网络信息内容的获取与表示

文章目录 信息内容的获取网络信息内容的类型网络媒体信息获取方法 信息内容的表示视觉信息视觉特征表达文本特征表达音频特征表达 信息内容的获取 网络信息内容的类型 网络媒体信息 传统意义上的互联网网站公开发布信息&#xff0c;网络用户通常可以基于网络浏览器获得。网络…

数据结构_优先级队列(堆)

目录 一、优先级队列 1.1 堆 1.2 PriorityQueue接口 二、模拟实现优先级队列 2.1 初始化 2.2 创建大根堆 (向下调整) 2.3 堆的插入 2.4 堆的删除 2.5 堆排序 总结 一、优先级队列 优先级队列是一种特殊的队列&#xff0c;其出队顺序与入队顺序无关&#xff0c;而与优…

Unet已死,Transformer当立!详细解读基于DiT的开源视频生成大模型EasyAnimate

Diffusion Models视频生成-博客汇总 前言&#xff1a;最近阿里云PIA团队开源了基于Diffusion Transformer结构的视频生成模型EasyAnimate&#xff0c;并且提出了专门针对视频的slice VAE&#xff0c;对于目前基于Unet结构的视频生成最好如SVD形成了降维打击&#xff0c;不论是生…

16s功能注释--PICRUST2的安装及使用

文章目录 安装本地安装conda安装 使用一些报错 安装 本地安装 在github网址下载压缩包&#xff1a;https://github.com/picrust/picrust2/releases/tag/v2.5.2 解压后将bin目录设置到环境变量 conda安装 利用bioconda安装 conda create -n picrust2 -c bioconda -c conda-…

Matlab基础语法:变量和数据类型,基本运算,矩阵和向量,常用函数,脚本文件

目录 一、变量和数据类型 二、基本运算 三、矩阵和向量 四、常用函数 五、脚本文件 六、总结 一、变量和数据类型 Matlab 支持多种数据类型&#xff0c;包括数值类型、字符类型和逻辑类型。掌握这些基本的变量和数据类型&#xff0c;是我们进行数学建模和计算的基础。 数…

网络安全复习笔记

概述 要素 CIA&#xff1a;可用性&#xff1b;完整性&#xff1b;保密性。 可控性&#xff1b;不可否认性&#xff1b;可审查性。 攻击 被动&#xff1a;窃听 - 保密性&#xff1b;监听 - 保密性主动&#xff1a;假冒 - 完整性&#xff1b;重放 - 完整性&#xff1b;改写 -…

数学建模系列(4/4):Matlab建模实战

目录 引言 1. Matlab简介与安装 1.1 Matlab简介 1.2 Matlab的安装 2. Matlab基础操作 2.1 Matlab基础语法和常用命令 2.2 Matlab中的数据类型和数据结构 3. 用Matlab进行建模 3.1 矩阵运算与线性代数 矩阵运算 3.2 Matlab中的绘图功能 绘制2D图形 绘制3D图形 3.3…

中服云产品远程运维系统

中服云产品远程运维系统主要针对设备售后市场服务的管理&#xff0c;利用工业物联网技术&#xff0c;一方面面向设备生产厂商&#xff0c;将分散的经销商、客户、销售出去的设备统一管理&#xff1b;另一方面面向设备使用厂家&#xff0c;实现设备实时运行监控&#xff1b;系统…

【手机号性别查询、姓名查询、年龄查询、要素核验接口】支持高并发查询。

** 最近更新时间&#xff1a;2024-06-21 用户手机号注册实名认证接口&#xff0c;精度高&#xff0c;简化注册用户的认证流程&#xff0c;输入手机号码就可以获得认证结果&#xff0c;适合金融、社交、教育、电商、商户入驻等业务场景&#xff0c;用于简化实名认证流程&#…

AI网络爬虫:用deepseek提取百度文心一言的智能体数据

真实网址&#xff1a;https://agents.baidu.com/lingjing/experhub/search/list?pageSize36&pageNo1&tagId-99 返回的json数据&#xff1a;{ "errno": 0, "msg": "success", "data": { "total": 36, "p…

Ollma本地大模型沉浸式翻译【403报错解决】

最终效果 通过Chrome的 沉浸式翻译 插件&#xff0c;用OpenAI通用接口调用本地的Ollma上的模型&#xff0c;实现本地的大模型翻译文献。 官方文档指导的Ollama的配置&#xff1a;一定要配置环境变量&#xff0c;否则会出现【403报错】

H6901B 2.7-24V36V60V72V80V100V 高效率高精度升压型大功率LED恒流驱动芯片

H6901B是一款高效率高精度升压型大功率LED恒流驱动芯片&#xff0c;它具备多种特性和优势&#xff0c;应用于多种LED照明产品中。 首先&#xff0c;H6901B具有宽范围的输入电压&#xff0c;从2.7V到100V&#xff0c;这使其能够适应不同电压源的应用场景。同时&#xff0c;其高效…

【解决方案】智慧园区解决方案(配套源码)

智慧园区整体解决方案-综合运营管理系统 1. 园区现状与发展机遇 2. 智慧园区愿景 3. 智慧解决方案架构 4. 智慧园区各子系统介绍 5. 智慧园区建设意义 楼宇管理&#xff0c;物业管理&#xff0c;消防管理&#xff0c;巡检管理&#xff0c;门禁管理&#xff0c;停车管理等综合实…

如何手机录屏?2个方法轻松搞定!

随着智能手机的普及和移动互联网的飞速发展&#xff0c;手机录屏已经成为人们在日常生活中经常需要使用的功能。无论是录制游戏精彩瞬间、分享App操作教程&#xff0c;还是保留重要聊天信息&#xff0c;手机录屏都发挥着重要作用。可是你知道如何手机录屏吗&#xff1f;本文将介…

若电路板上的二极管损坏后怎么确定型号呢?

若电路板上的二极管损坏后&#xff0c;还可以看清原来管子的型号&#xff0c;换用一个同型号的二极管即可。若看不清型号或管子未标注型号&#xff0c;一般可以根据该二极管在电路中的作用来代换。电路板上的二极管坏了&#xff0c;如何确定它的型号&#xff1f;。 一般来说看…

Linux 软链接

# 语法 ln -s <文件夹or文件的真实路径> <自定义路径别名> # 例子 ln -s /etc/sysconfig/network-scripts/ifcfg-ens33 ~/ens33