Linux下的简单生产、消费模型的实现(上)

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

生产消费模型是信号量的最典型的应用实例。然而实际操作系统中PV操作并不是如理想模型那样方便使用的,这里以Linux为例描述了生产、消费模型的实现方法,同时涉及了Linux下共享内存、信号量的基本操作。如有不正确之处,请大家指正,谢谢! 

一、Linux下信号量的建立

要建立一个信号量,首先要给信号量一个主键,即给信号量命名。Linux下的信号量与Windows有很大的不同,Windows以一个字符串来命名一个信号量,而Linux则以一个t_key类型的数值命名一组信号量。为了方便调试一般我们会在公共头文件中,以宏定义的方式进行信号量的命名,比如 

#define KEY_MUTEX ((key_t) 403040914 )

Linux下信号量集合的新建使用如下库函数

#include <sys/sem.h>
int semget(key_t key, int nsems, int semflg); 

其中key就是前文所说的主键,nsems是集合中包含的元素个数,semflg则是用于新建信号量的重要参数,比如访问控制权限。返回值是以key为主键的信号量标号,若返回-1说明产生了操作错误。具体参数的说明请看http://www.opengroup.org/onlinepubs/007908799/xsh/semget.html

为了方便理解与操作,这里我们需要建立的是仅有一个元素的公有信号量集。代码如下 

id = semget(KEY_MUTEX, 1, IPC_CREAT|0660); 

其中,一定要注意0660最高位的0不能省略,因为这是一个八进制数,代表rw-rw----的访问控制。 

二、信号量的初始化

信号量建立之后必须要进行初始化,在Linux信号的基本控制使用统一的API函数: 

#include <sys/sem.h>
int semctl(int semid, int semnum, int cmd, ...);

其中semnum是集合中元素的序号(以0开始计算);cmd则是需要进行的控制命令,在sys/sem.h 头文件中有宏定义,我们使用的是设置值SETVAL;附加参数可以接受如下的联合体(需要用户自行定义)。具体说明见http://www.opengroup.org/onlinepubs/007908799/xsh/semctl.html

union semun
{
    int val;                  /* value for SETVAL */
    struct semid_ds *buf;     /* buffer for IPC_STAT, IPC_SET */
    unsigned short *array;    /* array for GETALL, SETALL */
                                  /* Linux specific part: */
    struct seminfo *__buf;    /* buffer for IPC_INFO */
};

这里我们假设要将信号量集中第一个元素(也是唯一一个元素)赋初值1,使用如下代码

union semun un;
un.val = 1;
semctl(id, 0, SETVAL, un);

三、信号量的PV操作

在教科书里PV操作是两个完全不同的操作,但是在Linux系统中PV操作则在形式上统一为一个API函数。而且由于Linux下信号量集合的特点,一个调用可以同时作用于多个信号量元素中。函数原型如下:

#include <sys/sem.h>
int semop(int semid, struct sembuf *sops, size_t nsops);  

其中sops是一个sembuf结构体类型的数组,数组的每一个元素就是对一个信号量的操作,nsops则指出了数组的长度(操作的个数)。此结构体有三个成员

short sem_num 信号量元素序号(0起始)
short sem_op 操作数值
short sem_flg 操作标记

对于P操作有sem_op=-1,对于V操作有sem_op=1。操作之后,若信号量小于零则semop()调用被挂起直到大于等于0时才返回。我使用wait()release()两个函数分别实现了P操作和V操作:

void wait(int id)
{
    struct sembuf buf;
    buf.sem_num = 0;
    buf.sem_op = -1;
    buf.sem_flg = SEM_UNDO;
    semop(id, &buf, 1);
}

void release(int id)
{
    struct sembuf buf;
    buf.sem_num = 0;
    buf.sem_op = 1;
    buf.sem_flg = SEM_UNDO;
    semop(id, &buf, 1);
}

至于信号量的删除,亦是使用semctl()调用,但是由于涉及收到SIGKILL信号后的处理所以不作详细介绍了。

生产者和消费者(linux) 生产者和消费者同步条件变量条件变量的接口简单实现一个生产者和一个消费者模型 同步 同步保证了每个执行流可以合理的访问每个临界资源 同步的作用 当存在临界资源的时候,就直接获取临界资源;没有资源的时候,进行线程等待,等待其他线程让出临界资源,然后再通知等待线程。 等待线程之间再进行抢占式执行。 条件变量 当一个线程互斥的访问一个变量的时候,可能会出现在其他线程改变状态之前,他自己只能进行等待状... 阅读详情

相关推荐

Linux内核中实现生产者与消费者(避免无效唤醒)

本文关注的重点是,避免内核线程的无效唤醒,并且主要是关注消费者线程的设计。 因此,为了省事,这里关与生产者,消费者本身的处理流程可能不够严密。 1. 生产者 一个内核线程,每生产一个商品后,就唤醒消费者,然后自己睡眠1秒钟。 2. 消费者 一个内核线程,每当被唤醒后,就消费商品,然后进入睡眠。 对于消费者线程的这种设计,有几个好处:响应快,平时不占任何cpu。 但这种

无忧老猪 2025

Linux生产消费者问题的实现

利用互斥锁和计数信号完成生产消费者问题 一组生产者进程和一组消费者进程共享一个初始为空、大小为n的缓冲区,只有缓冲区没满时,生产者才把消息放入到缓冲区,否则必须等待;只有缓冲区不空时,消费者才能从中取出消息,否则必须等待。由于缓冲区是临界资源,它只允许一个生产者放入消息,或者一个消费者从中取出消息。 生产者和消费者对缓冲区互斥访问是互斥关系,同时生产者和消费者又是一个相互协作的关系,只有生产生产之后,消费者才能消费,他们又是同步关系。 信号量设置:信号量mutex作为互斥信号量,它用于控制互斥访问缓冲池,互斥信号量初值为1;信号量full用于记录当前缓冲池中“满”缓冲区数,初值为0。信号量empty用于记录当前缓冲池中“空”缓冲区数,初值为n。 主函数负责接收参数,初始化信号量,创建生产者线程,创建消费者线程,睡眠一段时间后,结束程序

谈谈我对Linux下“生产者/消费者线程模型”的理解

生产消费者线程模型常常用于网络编程,即一个线程监听事件发生(生产者,例如产生“收到数据”事件),其他线程来处理事件(消费者,例如处理收到的数据)比较笨的办法是: 消费者线程不停地loop等待数据,当生产者线程发现收到数据时,找一个线程(先不讨论找线程的策略),把“收到数据”这一事件告诉消费者线程。消费者线程会在下一个loop对这个事件进行处理,处理完毕后,继续loop,直到下一个事件到来。但这么

xocoder's coding life 3361

【二分查找】456:132 模式枚举3

给你一个整数数组 nums ,数组中共有 n 个整数。132 模式的子序列 由三个整数 nums[i]、nums[j] 和 nums[k] 组成,并同时满足:i < j < k 和 nums[i] < nums[k] < nums[j] 。 如果 nums 中存在 132 模式的子序列 ,返回 true ;否则,返回 false 。

闻缺陷则喜何志丹 1277

leetcode . 132 模式(单调栈-java)

给你一个整数数组 nums ,数组中共有 n 个整数。132 模式的子序列 由三个整数 nums[i]、nums[j] 和 nums[k] 组成,并同时满足:i < j < k 和 nums[i] < nums[k] < nums[j]。如果 nums 中存在 132 模式的子序列 ,返回 true;否则,返回 false。示例 1:输入:nums = [1,2,3,4]输出:false解释:序列中不存在 132 模式的子序列。示例 2:输入:nums = [3,1,4,2]

SP_1024的博客 523

Linux系统编程——多线程[下]:生产消费模型&信号量&线程池

本篇介绍了基于阻塞队列的生产消费模型和基于环形队列的生产消费模型,并且简要分析了生产消费模型的特点,并讨论了为什么生产消费模型能够带来高效率。最后提到了池化计技术,并实现了线程池。

weixin_59913110的博客 1536

【关于Linux中----生产消费模型

文章目录 一、生产消费模型 1.1概念的引入 1.2 321原则 二、条件变量 2.1概念的引入 2.2理解条件变量 2.3条件变量的使用 三、基于BlockingQueue的生产消费者模型 3.1BlockingQueue的介绍 3.2C++ queue模拟阻塞队列的生产消费模型 3.3对生产消费任务的模拟封装 四、遗留问题

Undefined__yu的博客 1276

Linux——生产消费者模型和信号量

为满的时候,生产消费同时到来1、生产者无法到临界区来,因为它申请信号量无法成功2、生产者和消费者同时来的时候,一定能保证消费者消费未来,生产消费的位置我们要想清楚1.其实就是队列中的下标2.一定是两个下标(生产者一个下标,消费者一个下标,他们互不影响)3.为空或者为满,下标相同。

m0_57249790的博客 1376

Linux下的消费者生产模型简单线程池的实现

本文主要会结束消费者生产模型,以及简单线程池的实现

Ly的博客 536

Linux下的简单生产消费模型实现(下)

生产消费模型生产者与消费者是互相独立进程,而各个进程的内存空间是相互独立的,因为我们需要为生产者与消费者建立一块共享内存区,用于保存生产出的“产品”。本文使用循环队列保存“产品”,队列为空时有head=tail=0struct sharebuf{    int buffer[MAX_BUFFER_SIZE];    int head;    int tail;};共享内存的命名与信号量的命名相同

Compass♂ 1216

学习笔记:linux系统下通过PV操作来实现简单生产消费者模型

2.在消费者读出字符后通过将文件指针前移(-1)然后再写入' '来实现删除字符的效果,注意因为生产者写入字符时是字符+'\n'(sprintf(str,"%d\n",i));所有当消费者打开文件时要将指针从SEEK_END前移两位(-2)否则无法读出有效字符,后续删除也会出错。1.要将整形数字转换成字符型再写入文件中,因为write直接写入整型数字是以二进制的形式写入,这样的文件是不可读的,即无法打开Store文件,报错:unknowType。

qq_62475475的博客 253

Linux多线程基础(6):信号量(实现简单生产者-消费者模型)

Linux多线程基础(6):信号量(实现简单生产者-消费者模型)

shnhe的博客 560

Linux探索学习】第三十二弹——生产消费模型:基于阻塞队列和基于环形队列的两种主要的实现方法

Linux探索学习】第三十二弹:基于阻塞队列的生产消费模型和基于环形队列的生产消费模型详解!!

2301_80220607的博客 3675

Linux操作系统7- 线程同步与互斥5(POSIX条件变量生产消费者模型的进一步使用)

Linux生产消费者模型的进一步使用,包含处理结构体数据,三线程两队列模型,多生产消费模型

yzc的博客 1036

linux线程同步--生产消费者模型

我们先回顾上节我们说到的互斥锁代码如下: #include<iostream> using namespace std; #include<unistd.h> #include<pthread.h> #define NUM 5 class Ticket { private: size_t tickets; pthread_mutex_t mutex; public: Ticket() :tickets(1000) //10.

qq_57283958的博客 818

Linux 线程:线程同步、生产消费者模型

Linux 线程同步、生产消费者模型

Han同学 1373

生产者和消费者

参考:http://www.kerneltravel.net/?p=494 1。procon.c #include #include #include #include MODULE_LICENSE("Dual BSD/GPL"); struct semaphore sem_producer;/*"生产需求证",在产品没有被消费的时候不能再进行生产*/ struct semaphore

jiantsing的专栏 473

Linux 和 Win下通用的 简单 生产消费者模型

c++11 实现生产消费者模型

DongGu‘s Programming 148

初识linux之线程同步与生产消费者模型

本文讲述了线程同步所需要的条件变量的概念及使用,以及在实际中比较常使用的消费者生产模型及以用阻塞队列模拟实现一个消费者生产模型

Masquerena114514的博客 907
上一篇: Delphi7到Delphi2006控件兼容性列表
下一篇: Linux下的简单生产、消费模型的实现(下)
melonliu
博客等级 码龄24年 2粉丝 11原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值