关于进程间通信的总结(IPC)
一:三个问题
进程间通信简单的说有三个问题。第一个问题是一个进程如何把信息传递给另一个。第二个要处理的问题是是,要确保两个或更多的的进程在关键互动中不会出现交叉(即是进程互斥的问题),第三个问题是与正确的顺序有关(即是进程之间的同步问题)。
二:信号量及PV操作
解决互斥进入临界区分为两种解决方案,软件解决方案和硬件解决方案,软件解决方案有Peterson解法,硬件解决方案有TSL指令, XCHG指令等。上述的解决方案都有忙等待的缺点,并且主要是用来解决互斥问题。
信号量是一种解决进程同步的解决方案,同时信号量也可以当作互斥量来使用。使用信号量来解决进程同步问题也是编程中使用较多的方法。使用信号量解决进程同步比较经典的问题是生产者消费者问题。Linux代码演示如下。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h> #define N 5 // 消费者或者生产者的数目
#define M 10 // 缓冲数目
//int M=10;
int in = 0; // 生产者放置产品的位置
int out = 0; // 消费者取产品的位置 int buff[M] = { 0 }; // 缓冲初始化为0,开始时没有产品 sem_t empty_sem; // 同步信号量,当满了时阻止生产者放产品
sem_t full_sem; // 同步信号量,当没产品时阻止消费者消费
pthread_mutex_t mutex; // 互斥信号量,一次只有一个线程访问缓冲 int product_id = 0; //生产者id
int prochase_id = 0; //消费者id
//信号处理函数
void Handlesignal(int signo){
printf("程序退出%d\n",signo);
exit(0);
}
/* 打印缓冲情况 */
void print() {
int i;
printf("产品队列为");
for(i = 0; i < M; i++)
printf("%d", buff[i]);
printf("\n");
} /* 生产者方法 */
void *product() {
int id = ++product_id;
while(1) {//重复进行
//用sleep的数量可以调节生产和消费的速度,便于观察
sleep(2); sem_wait(&empty_sem);
pthread_mutex_lock(&mutex); in= in % M;
printf("生产者%d在产品队列中放入第%d个产品\t",id, in); buff[in]= 1;
print();
++in; pthread_mutex_unlock(&mutex);
sem_post(&full_sem);
}
} /* 消费者方法 */
void *prochase() {
int id = ++prochase_id;
while(1) {//重复进行
//用sleep的数量可以调节生产和消费的速度,便于观察
sleep(5); sem_wait(&full_sem);
pthread_mutex_lock(&mutex); out= out % M;
printf("消费者%d从产品队列中取出第%d个产品\t",id, out); buff[out]= 0;
print();
++out; pthread_mutex_unlock(&mutex);
sem_post(&empty_sem);
}
} int main() {
printf("生产者和消费者数目都为5,产品缓冲为10,生产者每2秒生产一个产品,消费者每5秒消费一个产品,Ctrl+退出程序\n");
pthread_t id1[N];
pthread_t id2[N];
int i;
int ret[N];
//结束程序
if(signal(SIGINT,Handlesignal)==SIG_ERR){//按ctrl+C产生SIGINT信号
printf("信号安装出错\n");
}
// 初始化同步信号量
int ini1 = sem_init(&empty_sem, 0, M);//产品队列缓冲同步
int ini2 = sem_init(&full_sem, 0, 0);//线程运行同步
if(ini1 && ini2 != 0) {
printf("信号量初始化失败!\n");
exit(1);
}
//初始化互斥信号量
int ini3 = pthread_mutex_init(&mutex, NULL);
if(ini3 != 0) {
printf("线程同步初始化失败!\n");
exit(1);
}
// 创建N个生产者线程
for(i = 0; i < N; i++) {
ret[i]= pthread_create(&id1[i], NULL, product, (void *) (&i));
if(ret[i] != 0) {
printf("生产者%d线程创建失败!\n", i);
exit(1);
}
}
//创建N个消费者线程
for(i = 0; i < N; i++) {
ret[i]= pthread_create(&id2[i], NULL, prochase, NULL);
if(ret[i] != 0) {
printf("消费者%d线程创建失败!\n", i);
exit(1);
}
}
//等待线程销毁
for(i = 0; i < N; i++) {
pthread_join(id1[i], NULL);
pthread_join(id2[i],NULL);
}
exit(0);
}
在线程中也可以使用条件量解决生产者消费者问题,具体代码演示参考我的另一篇博客使用条件量解决生产者消费者问题。
三:管程
为了更易于编写正确的程序,Brinch Hansen (1973)和Hoare(1974)提出了一种高级同步原语,称为管程(monitor)。在下面的介绍中我们会发现,他们两人提出的方案略有不同。一个管程是一个由过程、变量及数据结构等组成的一个集合,它们组成一个特殊的模块或软件包。进程可在任何需要的时候调用管程中的过程,但它们不能在管程之外声明的过程中直接访问管程内的数据结构。C、C++不支持管程,Java语言支持管程。
四:其他通信方式
与管程和信号量有关的另一个问题是是,这些机制否是设计用来解决访问公共内存的一个或多个CPU上的互斥问题的。通过将信号量放在共享内存并用TSL或XCHG指令来保护他们,可以避免竞争。如果一个分布式系统具有多个CPU,并且每个CPU拥有自己的私有内存,他们通过一个局域网相连,那么这些源于将失效。这里的结论是信号量太低级,而管程在少数几个编程语言之外又无法使用,并且,这些源于均未提供机器见信息的交换方法。所以还需要其他办法。
1.消息传递
2.屏障
关于进程间通信的总结(IPC)的更多相关文章
- 四十九、进程间通信——System V IPC 之消息队列
49.1 System V IPC 介绍 49.1.1 System V IPC 概述 UNIX 系统存在信号.管道和命名管道等基本进程间通讯机制 System V 引入了三种高级进程间通信机制 消息 ...
- linux 进程间通信机制(IPC机制)一总览
1.作用:进程间通信机制(Inter Process Communication,IPC),这些IPC机制的存在使UNIX在进程通信领域手段相当丰富,也使得程序员在开发一个由多个进程协作的任务组成的系 ...
- 进程间通信之XSI IPC
XSI IPC源自于系统V的IPC功能. 有三种IPC我们称作XSI IPC,即消息队列.信号量以及共享存储器,它们之间有很多相似之处. 1.标识符和键 每个内核中的IPC结构(消息队列.信号量或共享 ...
- 五十、进程间通信——System V IPC 之共享内存
50.1 共享内存 50.1.1 共享内存的概念 共享内存区域是被多个进程共享的一部分物理内存 多个进程都可把该共享内存映射到自己的虚拟内存空间.所有用户空间的进程若要操作共享内存,都要将其映射到自己 ...
- linux 进程间通信机制(IPC机制)一消息队列
消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法.每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构.我们可以通过发送消息来避免命名管道的同步和阻塞问题.但是消息 ...
- 五十一、进程间通信——System V IPC 之进程信号量
51.1 进程信号量 51.1.1 信号量 本质上就是共享资源的数目,用来控制对共享资源的访问 用于进程间的互斥和同步 每种共享资源对应一个信号量,为了便于大量共享资源的操作引入了信号量集,可对所有信 ...
- linux 进程间通信机制(IPC机制)- 管道
一,定义: 管道又可以分为无名管道和命名管道,两者的用途是不一样的. 无名管道PIPE:主要用于具有亲缘关系的进程之间的通信,无名管道的通信是单向的,只能由一段到另外一段:无名管道是临时性的,完成通信 ...
- 【IPC第二个进程间通信】管道Pipe
IPC进程间通信+管道Pipe IPC(Inter-Process Communication,进程间通信). 管道用于进程间共享数据,事实上质是共享内存 ...
- 进程间通信 IPC(Inter-Process Communication)
目录 一.管道 二.FIFO 三.消息队列 四.信号量 五.共享存储 六.网络IPC:套接字 一.管道 管道是进程间通信中最古老的方式,所有UNIX都提供此种通信机制.管道有以下两种局限性: 历史 ...
- Windows下进程间通信及数据共享
进程是装入内存并准备执行的程序,每个进程都有私有的虚拟地址空间,由代码.数据以及它可利用的系统资源(如文件.管道等)组成. 多进程/多线程是Windows操作系统的一个基本特征.Microsoft W ...
随机推荐
- js实现自己定义鼠标右键-------Day45
又是周末了,只是事实上这在国外应该算是一周的開始吧,无论怎么说,今天是在歇息,放松我紧绷的神经,放松我有些疲惫的精神,昨晚上要裂了般的头疼,仿佛全部的数据都在脑子字面飞舞旋转,伴着一阵阵的恶心,当时把 ...
- PHP.6-PHP环境搭建(Windows环境下)-LAMP
PHP环境搭建(Windows环境下)-LAMP Windows系统上分别独立安装Apache2.PHP5.MySQL5和phpMyAdmin等几个软件.独立安装的好处是可以自由选择这些组件的具体版本 ...
- mysql中文乱码的完美解决方案
问题描述: mysql插入中文时显示为乱码或"?"号 解决方案: 修改mysql的my.ini配置 [mysql] default_character_set=utf8 [mysq ...
- 常用html演示模板
--学习测试新的css,js,经常用到test.html,在这里放一个: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transition ...
- Bash循环分类介绍
方法一: #!/bin/bash ` do #code here echo $i done 方法二:C语言风格 #!/bin/bash ; i<=; i++)) do printf " ...
- ie6/7/8中span右浮动折行问题的解决方案
浮动标准: W3C CSS 2.1 规范文档里对于浮动元素与非浮动行内元素相邻时的情况有如下解释.以下是关键段落: A floated box is shifted to the left or ri ...
- 关于Eclipse的Save时的自定义操作
Eclipse中Save+S的时候会包含很多其他操作.例如代码格式化,自动导入或者删除jar包等等. 如果修改代码的时候不想让Eclipse做这些操作,有两种方法. 第一: 用一个文本编辑器打开这个文 ...
- 关于Object[]数组强转成Integer[]类型的数组.
为什么不能由Object[]数组强转成Integer[]数组. Object[] ins= { new Integer(0), new Integer(1), new Integer(2), new ...
- applicationContext-mail.xml 模板
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...
- 【推公式】UVa 10995 - Educational Journey
1A~,但后来看人家的代码好像又写臭了,T^T... Problem A: Educational journey The University of Calgary team qualified f ...