进程间通信之共享内存(简单介绍消息队列和信号量)(2)

简介: 最快的进程间通信方式,共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据

comm.c

#include "comm.h"
static int commShm(int size, int flags)
{
  key_t key = ftok(PATHNAME, PROJ_ID);
  if (key < 0) {
    perror("ftok");
    return -1;
  }
  int shmid = 0;
  if ((shmid = shmget(_key, size, flags)) < 0) {
    perror("shmget");
    return -2;
  }
  return shmid;
}
int destroyShm(int shmid)
{
  if (shmctl(shmid, IPC_RMID, NULL) < 0) {
    perror("shmctl");
    return -1;
  }
  return 0;
}
int createShm(int size)
{
  return commShm(size, IPC_CREAT | IPC_EXCL | 0666);
}
int getShm(int size)
{
  return commShm(size, IPC_CREAT);
}


server.c

#include "comm.h"
int main()
{
  int shmid = createShm(4096);
  char* addr = shmat(shmid, NULL, 0);
  sleep(2);
  int i = 0;
  while (i++ < 26) {
    printf("client# %s\n", addr);
    sleep(1);
  }
  shmdt(addr);
  sleep(2);
  destroyShm(shmid);
  return 0;
}

client.c

#include "comm.h"
int main()
{
  int shmid = getShm(4096);
  sleep(1);
  char* addr = shmat(shmid, NULL, 0);
  sleep(2);
  int i = 0;
  while (i < 26) {
    addr[i] = 'A' + i;
    i++;
    addr[i] = 0;
    sleep(1);
  }
  shmdt(addr);
  sleep(2);
  return 0;
}

结果演示

image.png

注意:共享内存没有进行同步与互斥!


image.png

特性:


1.最快的进程间通信方式

2.生命周期随内核(并不会随着打开的进程退出而被释放)


注意事项:


共享内存的访问操作存在安全问题(竞争访问出现数据二义问题)


补充:


1.共享内存的本质就是开辟一块物理内存, 让多个进程映射同-块物理内存到自己的地址空间进行访问,实现数据共享的。

2.共享内存的操作是非进程安全的,多个进程同时对共享内存读写是有可能会造成数据的交叉写入或读取,造成数据混乱

3.共享内存的删除操作并非直接删除,而是拒绝后续映射,只有在当前映射链接数为0时,表示没有进程访问了,才会真正被删除

4.共享内存生命周期随内核,只要不删除,就一-直存在于内核中,除非重启系统(当然这里指的是非手动操作,可以手动删除)


消息队列


详细可以参考这篇博客,我这里是简单总结了一下消息队列

功能:实现进程间的数据传输

本质:内核中的一个优先级队列

实现:多个进程通过访问同一一个消息队列,以添加数据节点和获取数据节点实现通信

image.png

总结:


1、采用消息队列通信比采用管道通信具有更多的灵活性,通信的进程不但没有血缘上的要求,也不需要进行同步处理。

2、消息队列是一种先进先出的队列型数据结构;

3、消息队列将输出的信息进行了打包处理,可以保证以消息为单位进行接收;

4、消息队列对信息进行分类服务,根据消息的类别进行分别处理。

5、提供消息数据自动拆分功能,同时不能接受两次发送的消息。

6、消息队列提供了不完全随机读取的服务。 7、消息队列提供了完全异步的读写服务。


信号量


(这里做简单介绍)

作用:用于实现进程间的同步与互斥

本质:是一个计数器+ pcb等待队列


P操作:对计数器进行-1操作,判断计数是否大于等于0,正确则返回;失败则阻塞,其中阻塞就是把它置位可中断休眠状态,挂到pcb等待对联中,直到被唤醒

V操作:对计数器进行+ 1操作,若计数器小于等于0,则唤醒一个等待的进程

同步实现:

通过计数器对共享资源进行计数,在获取资源之前,则进行P操作,计数满足访问条件则访问,若不满足则阻塞当产生一个资源,则进行V操作,唤醒阻塞的进程

互斥实现:

初始化计数器为1,表示资源只有一一个。

访问资源之前进行P操作;访问资源完毕之后进行V操作


目录
相关文章
|
27天前
麒麟系统mate-indicators进程占用内存过高问题解决
【10月更文挑战第7天】麒麟系统mate-indicators进程占用内存过高问题解决
119 2
|
2月前
|
存储 Linux 调度
深入理解操作系统:从进程管理到内存分配
【8月更文挑战第44天】本文将带你深入操作系统的核心,探索其背后的原理和机制。我们将从进程管理开始,理解如何创建、调度和管理进程。然后,我们将探讨内存分配,了解操作系统如何管理计算机的内存资源。最后,我们将通过一些代码示例,展示这些概念是如何在实际操作系统中实现的。无论你是初学者还是有经验的开发者,这篇文章都将为你提供新的视角和深入的理解。
|
4天前
|
消息中间件 存储 供应链
进程间通信方式-----消息队列通信
【10月更文挑战第29天】消息队列通信是一种强大而灵活的进程间通信机制,它通过异步通信、解耦和缓冲等特性,为分布式系统和多进程应用提供了高效的通信方式。在实际应用中,需要根据具体的需求和场景,合理地选择和使用消息队列,以充分发挥其优势,同时注意其可能带来的复杂性和性能开销等问题。
|
1月前
|
缓存 算法 调度
深入浅出操作系统:从进程管理到内存优化
本文旨在为读者提供一次深入浅出的操作系统之旅。我们将从进程管理的基本概念出发,逐步深入到内存管理的复杂世界,最终探索如何通过实践技巧来优化系统性能。文章将结合理论与实践,通过代码示例,帮助读者更好地理解操作系统的核心机制及其在日常技术工作中的重要性。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开一扇通往操作系统深层次理解的大门。
|
29天前
麒麟系统mate-indicators进程占用内存过高问题解决
【10月更文挑战第5天】麒麟系统mate-indicators进程占用内存过高问题解决
107 0
|
2月前
|
监控 Ubuntu API
Python脚本监控Ubuntu系统进程内存的实现方式
通过这种方法,我们可以很容易地监控Ubuntu系统中进程的内存使用情况,对于性能分析和资源管理具有很大的帮助。这只是 `psutil`库功能的冰山一角,`psutil`还能够提供更多关于系统和进程的详细信息,强烈推荐进一步探索这个强大的库。
41 1
|
2月前
|
缓存 Linux C语言
C语言 多进程编程(六)共享内存
本文介绍了Linux系统下的多进程通信机制——共享内存的使用方法。首先详细讲解了如何通过`shmget()`函数创建共享内存,并提供了示例代码。接着介绍了如何利用`shmctl()`函数删除共享内存。随后,文章解释了共享内存映射的概念及其实现方法,包括使用`shmat()`函数进行映射以及使用`shmdt()`函数解除映射,并给出了相应的示例代码。最后,展示了如何在共享内存中读写数据的具体操作流程。
|
2月前
|
Linux Windows
检测进程内存的活跃程度
检测进程内存的活跃程度
|
2月前
|
Linux
查看进程的内存使用信息
查看进程的内存使用信息
|
3月前
|
开发者 API Windows
从怀旧到革新:看WinForms如何在保持向后兼容性的前提下,借助.NET新平台的力量实现自我进化与应用现代化,让经典桌面应用焕发第二春——我们的WinForms应用转型之路深度剖析
【8月更文挑战第31天】在Windows桌面应用开发中,Windows Forms(WinForms)依然是许多开发者的首选。尽管.NET Framework已演进至.NET 5 及更高版本,WinForms 仍作为核心组件保留,支持现有代码库的同时引入新特性。开发者可将项目迁移至.NET Core,享受性能提升和跨平台能力。迁移时需注意API变更,确保应用平稳过渡。通过自定义样式或第三方控件库,还可增强视觉效果。结合.NET新功能,WinForms 应用不仅能延续既有投资,还能焕发新生。 示例代码展示了如何在.NET Core中创建包含按钮和标签的基本窗口,实现简单的用户交互。
66 0