有界缓冲区问题(生产者消费者)

目录

题目:

设计思路:

代码实现:

init.sh

producer.sh

consumer.sh

signal.sh

wait.sh

kill.sh

详细思路:


题目:

有界缓冲区问题,使用Bash Scripting 设计脚本,利用信号量技术处理生产者-消费者的任务,通过 两个竞争性进程共享一个逻辑资源。在这个任务中,这个共享资源是一个字符(a-z 或A-Z)缓冲区。我们的连续可重用资源的内容将存储在一个名为 buffer.txt 的文件 中,一次只能由一个进程使用(mutual exclusion)。Producer的任务是生成数据单元 以便将它们放入缓冲区;相反,Consumer 的任务是从缓冲区中删除数据单元(在此任务中是字符)

设计思路:

对于生产者消费者问题,首先需要一个生产者脚本producer.sh和消费者脚本consumer.sh,生产者生产共享资源到文件buffer.txt中,消费者从buffer.txt中读取并消费资源,通过信号量来同步两个进程,确保他们不会同时访问buffer.txt,而对于信号量的操作还需要wait.sh和signal.sh脚本,除此之外还需要一个初始化脚本init.sh来进行初始化信号量,初始化缓冲区文件,运行生产者和消费者脚本等操作。

代码实现:

init.sh

#!/bin/bash

chmod +x producer.sh consumer.sh wait.sh signal.sh

# 初始化信号量
echo "1" > free_semaphore.txt
echo "10" > space_semaphore.txt
echo "0" > data_semaphore.txt

# 创建/初始化缓冲区文件
echo "" > buffer.txt

# 在后台运行生产者和消费者脚本
./producer.sh &
./consumer.sh &

producer.sh

#!/bin/bash

while true; do
    # 等待缓冲区中有可用空间
    ./wait.sh space_semaphore.txt

    # 生产数据(生成一个随机字符)
    data=$(head /dev/urandom | tr -dc 'a-zA-Z' | head -c 1)

    # 获取缓冲区锁
    ./wait.sh free_semaphore.txt

    # 将数据追加到缓冲区
    echo $data >> buffer.txt
    echo "生产:$data"

    # 释放缓冲区锁
    ./signal.sh free_semaphore.txt

    # 增加数据计数
    ./signal.sh data_semaphore.txt

done

consumer.sh

#!/bin/bash

while true; do
    # 等待缓冲区中有可用数据
    ./wait.sh data_semaphore.txt

    # 获取缓冲区锁
    ./wait.sh free_semaphore.txt

    # 消费数据(从缓冲区中读取并删除第一个字符)
    data=$(tail -n 1 buffer.txt)
    echo "消费:$data"
    sed -i '$d' buffer.txt


    # 释放缓冲区锁
    ./signal.sh free_semaphore.txt

    # 减少数据计数
    ./signal.sh space_semaphore.txt


done

signal.sh

#!/bin/bash

file=$1

# 生成唯一的锁文件名,基于文件名
lockfile="${file}.lock"

# 将锁文件名的字符串形式转换为文件描述符
exec {unique_fd}>"$lockfile"

# 使用 flock 来获取锁

flock -x $unique_fd
    
echo $(( $(cat $file) + 1 )) > $file
    
flock -u $unique_fd



wait.sh

#!/bin/bash

file=$1

# 生成唯一的锁文件名,基于文件名
lockfile="${file}.lock"

# 将锁文件名的字符串形式转换为文件描述符
exec {unique_fd}>"$lockfile"


while [ $(cat $file) -le 0 ]; do
    sleep 1
done


flock -x $unique_fd

echo $(( $(cat $file) - 1 )) > $file

flock -u $unique_fd
 



kill.sh

pkill -f './consumer.sh'
pkill -f './producer.sh'
pkill -f './wait.sh'
pkill -f './signal.sh'
rm -f buffer.txt file.lock
rm -f data_semaphore.txt data_semaphore.txt.lock
rm -f free_semaphore.txt free_semaphore.txt.lock


详细思路:

首先是init.sh,初始化信号操作

free_semaphore.txt是互斥信号量,确保生产者和消费者同时只能有一个进程访问buffer,space_semaphore.txt表示buffer的当前容量,data_semaphore.txt,表示当前buffer中的数据个数。生产者每生产一个资源到buffer,data_semaphore.txt就会加一,space_semaphore.txt减一,当space_semaphore.txt为0时,表示当前buffer已满,那么生产者就无法再生产,消费者同理。

然后是初始化缓冲区文件

如果没有buffer.txt文件则会先创建。

然后是运行生产者和消费者脚本

为了方便一点还在前面加上了

接下来是生产者和消费者

由上面伪代码我们可以看出,生产者和消费者中需要用到wait和signal对信号量进行操作,所以我们先完成wait和signal

对于wait.sh和signal.sh我们要保证它的原子性,这里使用文件锁flock来实现

wait.sh

                             

signal.sh

这里以信号量文件名来生成锁文件名,同时以锁文件名来生成文件描述符,这可以保证不同进程(wait.sh和signal.sh)对同一个信号量的更改是互斥的。也就是说,同一时刻只能有一个wait.sh的进程或signal.sh的进程对一个信号量进行更改。

wait.sh中如果传入的信号量小于0,就会被sleep,(注意这个对信号量的判定语句要放在flock之前,如果放在flock之后就会产生死锁。)如果信号量大于0,就将其减一。

Signal.sh将传入的信号量加一。

然后回去写生产者和消费者脚本

producer.sh

consumer.sh

生产者生产数据

从系统中的/dev/urandom设备中读取数据,并删除非字母字符,保留字符字母集,并且从处理过的字符字母集中取前一个字符。

获取到缓冲区锁之后将数据添加到buffer

这里将新的数据也就是字符以整行的形式添加到buffer,与后面消费者以整行形式删除相呼应。

之后释放缓冲区锁,并且将信号量data加一,表示buffer中的数据加一。

之后是消费者,先进入缓冲区,然后消费资源

然后释放缓冲区锁,再将sapce信号量加一,表示buffer中可用空间加一。

最后kill.sh来结束进程

《计算机操作系统》课程设计 题 目: 生产者---消费者问题 专 业: 软件工程 年 级: 2010级 小组成员: A B 指导教师: 时 间: 地 点: 2012年 5 月 摘要 生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区 的线程——即所谓的"生产者"和"消费者"——在实际运行时会发生的问题生产者的主要作 用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区 消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也 不会在缓冲区中空时消耗数据。 生产者消费者模式是通过一个容器来解决生产者消费者的强耦合问题生产者和消 费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不 用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队 列里取,阻塞队列就相当于一个缓冲区,平衡了生产者消费者的处理能力。 目录 1. 概述 4 2. 课程设计任务及要求 4 2.1 设计任务 4 2.2 设计要求 4 2.3 分工日程表 4 3. 算法及数据结构 4 3.1算法的总体思想 4 3.2 生产者模块 4 3.3 消费者模块 6 4. 程序设计与实现 7 4.1 程序流程图 7 4.2 程序代码 9 4.3 实验结果 14 5. 结论 16 6. 收获、体会和建议 16 6.1收获 16 7. 参考文献 17 1. 概述 本课题设计是完成了"操作系统原理"课程进行的一次全面的综合训练,通过这次课程 设计,充分检验学生对课程的掌握程度和熟练情况,让学生更好的掌握操作系统的原理 及其实现方法,加深对课程的基础理论和算法的理解,加强学生的动手能力。 2. 课程设计任务及要求 2.1 设计任务 通过研究Linux 的进程机制和信号量实现生产者消费者问题的并发控制. 说明:有界缓冲区内设有20个存储单元,放入/取出的数据项设定为1- 20这20个整型数。 2.2 设计要求 (1)每个生产者消费者有界缓冲区进行操作后,实时显示有界缓冲区的全部内容 、当前指针位置和生产者/消费者的标识符。 (2)生产者消费者各有两个以上。 (3)多个生产者或多个消费者之间须有共享对缓冲区进行操作的函数代码。 提示:(1) 有界缓冲区可用数组实现。 2.3 分工日程表 " "周三下午 "周四上午 "周四下午 "周五上午 "周五下午 " "A "分析题目 "讨论,分工"编写代码 "测试系统 "编写文档 " "B "分析题目 "讨论,分工"编写代码 "添加备注 "完善系统 " 3. 算法及数据结构 3.1算法的总体思想 在同一个进程地址空间内执行的两个线程。 生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。 消费者线程从缓冲区中获得物品,然后释放缓冲区。 当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者 线程释放出一个空缓冲区。当消费者线程消费物品时,如果没有满的缓冲区,那么消费 者线程将被阻塞,直到新的物品被生产出来。 3.2 生产者模块 3.2.1 功能 在同一个进程地址空间内执行的两个线程。生产者线程生产物品,然后将物品放 置在一个空缓冲区中供消费者线程消费。当生产者线程生产物品时,如果没有空缓冲 区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。 3.2.2 数据结构 producer_semaphore//生产者的资源信号量(初始值为缓冲区的大小) Buffer[pn] //有界缓冲区 Pn ///缓冲区目标位置 MAX_BUFFER//缓冲区上限 buffer_mutex//互斥信号量 Wait()//等待操作,用于申请资源 Signal()//信号操作,用于释放资源 Sleep()//挂起 3.2.3 算法 "void *producer_thread(void *tid){ " "pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL); " "/* 设置状态,PTHREAD_CANCEL_ENABLE是正常处理cancel信号*/ " "while(1){ " "sem_wait(&producer_semaphore); /*等待,需要生存*/ " "srand((int)time(NULL)*(int)tid); " "sleep(rand()%2+1); /*一个或两个需要生产*/ " "while((produce_pointer+1)%20==consume_pointer); /*指
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值