转:http://blog.csdn.net/yaozhiyi/article/details/7561759

一. 引子

时隔一年再次用到 cout 的时候,哥潸然泪下,这是一种久别重逢的感动,虽然基本忘光了。趁着有大把时间,再把生产者消费者问题巩固一下,用纯C吧。珍惜能写代码的幸福时光。
 

二. 分析

生产者和消费者问题是多个相互合作的进程之间的一种抽象。生产者和消费者之间的关系:
1.  对缓冲区的访问是互斥的。由于两者都会修改缓冲区,因此,一方修改缓冲区时,另一方不能修改,这就是互斥。
2.  一方的行为影响另一方。缓冲区不空,才能消费,何时不空?生产了就不空;缓冲区满,就不能生产,何时不满?消费了就不满。这是同步关系。
为了描述这种关系,一方面,使用共享内存代表缓冲区;另一方面,使用 互斥信号量 控制对缓冲区的访问,使用同步信号量描述两者的依赖关系。
 

三. 共享存储

共享存储是进程间通信的一种手段,通常,使用信号量同步或互斥访问共享存储。共享存储的原理是将进程的地址空间映射到一个共享存储段。在LINUX下,通过使用 shmget 函数创建或者获取共享内存。

1. 创建

1)不指定 KEY

// IPC_PRIVATE指出需要创建内存;

//SHM_SIZE 指出字节大小; 
//SHM_MODE 指出访问权限字如 0600表示,用户可以读写该内存
int shmget(key_t IPC_PRIVATE,size_t SHM_SIZE,int SHM_MODE);

2)指定KEY

//如果SHM_KEY指向的共享存储已经存在,则返回共享存储的ID; 
//否则,创建共享存储并返回其ID
int  shmget(key_t SHM_KEY,size_t SHM_SIZE,int SHM_MODE);
 

2. 访问

方法一

只需要共享存储的 ID 就可以通过  shmat  函数获得共享存储所占用的实际地址。因此,可以在父进程的栈中用变量存放指向共享存储的指针,那么 fork 之后,子进程就可以很方便地通过这个指针访问共享存储了。

方法二

如果进程之间并没有父子关系,但是协商好了共享存储的 KEY , 那么在每个进程中,就可以通过 KEY 以及 shmget 函数获得共享存储的 I D , 进而通过 shmat 函数获得共享存储的实际地址,最后访问。
 
在我的实现中,我把生产者实现为父进程,消费者实现为子进程,并通过方法一实现进程之间共享内存。

四. 信号量集

信号量有两种原语 P 和 V ,P 锁定资源,V 释放资源。LINUX 下的使用信号量集合的接口特别复杂。我所用到的函数如下:

1. 创建或者获取信号量集合

// IPC_PRIVATE 表示创建信号量集, NUM_OF_SEM表示该集合中有多少信号量; FLAGS复杂不追究
semget(IPC_PRIVATE, NUM_OF_SEM, FLAGS );
// SEM_KEY 是 key_t 类型
//如果 SEM_KEY 代表的信号量集存在,则返回信号量集的ID
//如果不存在,则创建信号量集并返回ID
semget(SEM_KEY, NUM_OF_SEM,FLAGS);
 

2. 初始化信号量

创建的过程并未指定信号量的初始值,需要使用 semctl 函数指定。
semctl(int semSetId , int semIdx , int cmd, union semun su);
 
其中 semSetId 是指信号量集的 ID , semIdx 指信号量集中某个信号量的索引(从零开始), 如果是要设置信号量的值, 填 SETVAL 即可, 为了设置信号量的值,可以指定su.val为索要设置的值。
我在 UBUNTU 下使用 union semun 编译时总报错:
invalid use of undefined type ‘union semun’

 

据说是 Linux 下删除了 semun 的定义。可以通过自定义 semun 解决:

 

五. 代码分解

1. 头文件

2. 信号量

共需要三个信号量:
第一个信号量用于限制生产者必须在缓冲区不满时才能生产,是同步信号量
第二个信号量用于限制消费者必须在缓冲区有产品时才消费,是同步信号量
第三个信号量用于限制生产者和消费者在访问缓冲区时必须互斥,是互斥信号量
 
创建信号量集合,semget
封装对信号量集中的某个信号量的值的+1或者-1操作

3. 使用共享内存

4. 生产过程

5. 消费过程

六. 代码全文

(转)OS: 生产者消费者问题(多进程+共享内存+信号量)的更多相关文章

  1. OS: 生产者消费者问题(二) ---- 系统V IPC通信-信号量和共享内存

    在上一篇“OS: 生产者消费者问题(多进程+共享内存+信号量)”中提到的方法二: 如果进程之间并没有父子关系,但是协商好了共享存储的 KEY , 那么在每个进程中,就可以通过 KEY 以及 shmge ...

  2. 并发、并行、同步、异步、全局解释锁GIL、同步锁Lock、死锁、递归锁、同步对象/条件、信号量、队列、生产者消费者、多进程模块、进程的调用、Process类、

    并发:是指系统具有处理多个任务/动作的能力. 并行:是指系统具有同时处理多个任务/动作的能力. 并行是并发的子集. 同步:当进程执行到一个IO(等待外部数据)的时候. 异步:当进程执行到一个IO不等到 ...

  3. 多进程共享内存的MemoryStream

    文章转载于http://www.raysoftware.cn/?p=506 具体用处呢,有很多,比如多进程浏览器共享Cookie啦,多个进程传送点数据啦. 共享内存封装. 封装成了MemoryStre ...

  4. [OS] 生产者-消费者问题(有限缓冲问题)

    ·最简单的情形--(一个生产者 + 一个消费者 + 一个大小为1的有限缓冲) 首先来分析其中的同步关系: ·必须在生产者放入一个产品之后,消费者才能够从缓冲中取出产品来消费.·只有在消费者从缓冲区中取 ...

  5. 进程间通信机制(管道、信号、共享内存/信号量/消息队列)、线程间通信机制(互斥锁、条件变量、posix匿名信号量)

    注:本分类下文章大多整理自<深入分析linux内核源代码>一书,另有参考其他一些资料如<linux内核完全剖析>.<linux c 编程一站式学习>等,只是为了更好 ...

  6. Linux进程间通信 共享内存+信号量+简单样例

    每个进程都有着自己独立的地址空间,比方程序之前申请了一块内存.当调用fork函数之后.父进程和子进程所使用的是不同的内存. 因此进程间的通信,不像线程间通信那么简单.可是共享内存编程接口能够让一个进程 ...

  7. linux 共享内存 信号量 同步

    这篇文章将讲述别一种进程间通信的机制——信号量.注意请不要把它与之前所说的信号混淆起来,信号与信号量是不同的两种事物.有关信号的更多内容,可以阅读我的另一篇文章:Linux进程间通信——使用信号.下面 ...

  8. Linux线程编程之生产者消费者问题

    前言 本文基于顺序循环队列,给出Linux生产者/消费者问题的多线程示例,并讨论编程时需要注意的事项.文中涉及的代码运行环境如下: 本文假定读者已具备线程同步的基础知识. 一  顺序表循环队列 1.1 ...

  9. Linux线程编程之生产者消费者问题【转】

    转自:http://www.cnblogs.com/clover-toeic/p/4029269.html 前言 本文基于顺序循环队列,给出Linux生产者/消费者问题的多线程示例,并讨论编程时需要注 ...

随机推荐

  1. 关于respond.js

    作用:可以让ie8及以下支持css3的媒体查询. 有几个问题: 1.由于浏览器的安全机制,Respond.js 不能在通过 file:// 协议(打开本地HTML文件所用的协议)访问的页面上发挥正常的 ...

  2. CCPC-Wannafly 秦皇岛 day5训练总结

    训练总结 今天开局先上去看到了J,粗略(>_<)的看了下题意,然后就觉得应该是个dp 就开始写,思路是个三维dp,开的10000*10*10  觉得就不会爆,时间上也没问题,后面陆续wa了 ...

  3. Android代码学习--点击事件的几种写法

    由来:常规的写法参见<写一个apk>,每次点击按钮,按钮先查找文本框等元素,然后再操作,其实查找操作是很费时的操作,因此将该定义放到Activity的onCreate中:Oncreate只 ...

  4. 整合SSH

    Hibernate知识: 1.核心配置文件: 连接数据库信息.连接池配置 映射配置 Struts2: 1.相关操作: 创建方式: 写一个类,写上public String execute():方法 实 ...

  5. Django中ORM对数据库的增删改查操作

         前言 什么是ORM?  ORM(对象关系映射)指用面向对象的方法处理数据库中的创建表以及数据的增删改查等操作. 简而言之,就是将数据库的一张表当作一个类,数据库中的每一条记录当作一个对象.在 ...

  6. ArcGIS Runtime SDK for .NET (Quartz Beta)之连接ArcGIS Portal

    1. 介绍 ArcGIS Portal作为ArcGIS平台的中枢,在ArcGIS体系中起着至关重要的地位.在ArcGIS Runtime的新架构Quartz中添加了连接ArcGIS Portal(或A ...

  7. JS-动态加载

    var s = document.createElement('script'); s.setAttribute('src', ''); s.setAttribute('type', 'text/ja ...

  8. 用 Flask 来写个轻博客 (6) — (M)VC_models 的关系(one to many)

    Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 扩展阅读 前言 一对多 再一次 sync db How to use ...

  9. iiview Select 选择框打勾选中的内容label和展示的不一致

    Select选择框里加入了OptionGroup.option ; 以及input输入框支持模糊搜索: 不一致的原因:缺少  :label-in-value="true";官方文档 ...

  10. 阿里云epel源

    epel是个好东西,不过国外的速度实在是不能忍受.所以 有了这篇文章.1. 首先卸载以前装的epel以免影响 rpm -e epel-release 2. 下载阿里提供的epel wget -P /e ...