博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于进程间通信的总结(IPC)
阅读量:6584 次
发布时间:2019-06-24

本文共 3076 字,大约阅读时间需要 10 分钟。

一:三个问题

进程间通信简单的说有三个问题。第一个问题是一个进程如何把信息传递给另一个。第二个要处理的问题是是,要确保两个或更多的的进程在关键互动中不会出现交叉(即是进程互斥的问题),第三个问题是与正确的顺序有关(即是进程之间的同步问题)。

二:信号量及PV操作

解决互斥进入临界区分为两种解决方案,软件解决方案和硬件解决方案,软件解决方案有Peterson解法,硬件解决方案有TSL指令, XCHG指令等。上述的解决方案都有忙等待的缺点,并且主要是用来解决互斥问题。

信号量是一种解决进程同步的解决方案,同时信号量也可以当作互斥量来使用。使用信号量来解决进程同步问题也是编程中使用较多的方法。使用信号量解决进程同步比较经典的问题是生产者消费者问题。Linux代码演示如下。

#include 
#include
#include
#include
#include
#include
#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.屏障

转载于:https://www.cnblogs.com/FJuly/p/4730387.html

你可能感兴趣的文章
Android开发17——获取网络资源之XML数据
查看>>
Eclipse创建JavaWeb项目并部署到Mopaas平台
查看>>
华为AD+NPS+DHCP+MAC地址认证配置(二)华为篇
查看>>
Python开发购物车程序
查看>>
超大数据库的备份和恢复问题:分区表、文件组备份、部分还原
查看>>
WDS+MDT部署Windows7操作系统6—创建任务序列
查看>>
python+selenium+eclipse问题排查
查看>>
FFMPEG中最关键的结构体之间的关系
查看>>
Apache+Tomcat集群配置
查看>>
OneAPM x 腾讯 | OneAPM 技术公开课·深圳 报名:前端性能大作战!
查看>>
化解工程师与传输接口到传感器的第一次战争,让设计更容易
查看>>
不要宅要养生--程序员健康生活指北
查看>>
Ubuntu jdk环境变量配置 虚拟机vm
查看>>
加密和解密基础
查看>>
三元表达式
查看>>
架构设计:生产者/消费者模式 第2页:如何确定数据单元
查看>>
RHCS
查看>>
C# 获取文件MD5与SHA1
查看>>
【源资讯 第25期】一波开源项目将停止维护
查看>>
IO 多路服用模型
查看>>