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

目录

题目:

设计思路:

代码实现:

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来结束进程

  • 33
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值