【C语言】【Linux】【信号量 P.V操作】 生产者消费者问题实现

您所在的位置:网站首页 操作系统生产者与消费者问题 【C语言】【Linux】【信号量 P.V操作】 生产者消费者问题实现

【C语言】【Linux】【信号量 P.V操作】 生产者消费者问题实现

2024-07-14 10:26:41| 来源: 网络整理| 查看: 265

信号量简介

信号量 (Semaphore)是表示资源的实体,是一个与队列有关的整形变量,其值仅能由P、V操作来改变。公用信号量常用于实现进程间互斥,初始值通常设为1。私用信号量常用于用于实现进程间同步,初始值通常为0或n

P、V操作

当一个进程想要访问临界区资源时,它必须先执行P原语(系统态下执行的某些具有特定功能的程序段)操作将信号量sem减1。若sem>=0,则可以访问资源,否则进程挂起。当它完成对临界区资源操作后,执行V原语操作将sem加1,以释放资源。

sem初试值为1,所以任意进程执行完P操作后sem值变为0,该进程进入临界区。在此进程执行V操作之前,另一进程想要访问临界区,执行P操作后sem值变为-1,因此该进程阻塞。第一个进程执行V操作后,sem值变为0,从而第二个进程唤醒进入就绪队列。第二个进程执行V操作后,如果没有其它进程申请进入临界区,sem值恢复到初始值1。

生产者消费者问题

生产者-消费者问题是典型的PV操作问题。生产者的任务是生成一定量的数据放到缓冲区,并且重复此过程。消费者的任务会从缓冲区拿走数据,并且重复此过程。关键在于保证生产者不会在缓冲区满时继续生产,消费者不会在缓冲区为空时继续消费。缓冲区满时,生产者进程需要阻塞。缓冲区为空时,消费者进程需要阻塞。并且消费者生产这不能同时访问缓冲区。 信号量empy判断生产者是否还可以生产,信号量full判断是否还可以消费,信号量mutex用于互斥访问缓冲区。empty、full是私用信号量,用于进程同步,mutex是公用信号量,用于进程互斥。

//生产者进程 producer: 生产产品; p(empty); //空的时候信号量empty为缓冲区大小 p(mutex); 送产品进入缓冲区 v(mutex); v(full); //满的时候信号量0 //消费者进程 consumer: p(full); p(mutex); 从缓冲区取走产品 v(mutex); v(empty); 消费产品; C语言在Linux下的实现

创建PRODUCE个线程模拟生产者,CONSUMER个线程模拟消费者,一个数组模拟缓冲区情况。

宏定义(全局变量) #define PRODUCER 4 //生产者数量 #define CONSUMER 4 //消费者数量 #define BUFFER 8 //缓冲区大小 int producer_id = 0; int consumer_id = 0; int in = 0; int out = 0; int Buffer[BUFFER]; sem_t sem_empty; //同步信号量 sem_t sem_full; pthread_mutex_t mutex; //互斥信号量 void Signal_print(); //处理信号 void print(); //打印缓冲队列 void *producer(); //生产者 void *consumer(); //消费者 生产者代码 void *producer(){ int id = ++producer_id; while(1){ sleep(3); //调节速度 sem_wait(&sem_empty); //p(empty)操作 pthread_mutex_lock(&mutex); //p(mutex)操作 in %= BUFFER; printf("生产者%d将产品放入缓冲区队列第%d号 ",id,in+1); Buffer[in] = 1; print(); ++in; pthread_mutex_unlock(&mutex); //v(mutex)操作 sem_post(&sem_full); //v(full)操作 } } 消费者代码 void *consumer(){ int id = ++consumer_id; while(1){ sleep(3); sem_wait(&sem_full); pthread_mutex_lock(&mutex); out %= BUFFER; printf("消费者%d从缓冲区队列第%d号取走产品 ",id,out+1); Buffer[out] = 0; print(); ++out; pthread_mutex_unlock(&mutex); sem_post(&sem_empty); } } 运行结果

可以自行修改参数,模拟情景。 在这里插入图片描述

附录

关于其中用到的函数。在Linux下可以man查看函数的说明,pthread需要单独添加apt安装glibc-doc manpages-posix-dev

fork

创建一个子进程。

#include #include pid_t fork(void);

返回值:

On success, the PID of the child process is returned in the parent, and 0 is returned in the child. On failure, -1 is returned in the parent, no child process is created, and errno is set appropriately.

sem_init

初始化信号量。

#include int sem_init(sem_t *sem, int pshared, unsigned int value); Link with -pthread.

sem_init() initializes the unnamed semaphore at the address pointed to by sem. The value argument specifies the initial value for the semaphore. The pshared argument indicates whether this semaphore is to be shared between the threads of a process, or between processes. If pshared has the value 0, then the semaphore is shared between the threads of a process, and should be located at some address that is visible to all threads (e.g., a global variable, or a variable allocated dynami‐ cally on the heap). If pshared is nonzero, then the semaphore is shared between processes, and should be located in a region of shared memory (see shm_open(3), mmap(2), and shmget(2)). (Since a child created by fork(2) inherits its parent’s memory mappings, it can also access the semaphore.) Any process that can access the shared memory region can operate on the semaphore using sem_post(3), sem_wait(3), and so on. Initializing a semaphore that has already been initialized results in unde‐ fined behavior

返回值:

sem_init() returns 0 on success; on error, -1 is returned, and errno is set to indicate the error.

pthread_create

创建线程。

//Compile and link with -pthread. #include int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);

返回值:

On success, pthread_create() returns 0; on error, it returns an error num‐ ber, and the contents of *thread are undefined.

pthread_mutex_init int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);

A mutex has two possible states: unlocked (not owned by any thread), and locked (owned by one thread). A mutex can never be owned by two different threads simultaneously. A thread attempting to lock a mutex that is already locked by another thread is suspended until the owning thread unlocks the mutex first pthread_mutex_init initializes the mutex object pointed to by mutex accord‐ ing to the mutex attributes specified in mutexattr. If mutexattr is NULL, default attributes are used instead. pthread_mutex_init always returns 0. The other mutex functions return 0 on success and a non-zero error code on error.

附:开篇处下载链接需要3金币,如果实在需要又没有可以给我发邮件免费获取。


【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭