通过共享内存进行通信(嵌入式学习)

news/2024/11/28 12:59:52/

通过共享内存进行通信

  • 概念
  • 特点
  • 函数
  • 示例代码

概念

在Linux中,共享内存是一种进程间通信(IPC)机制,允许多个进程共享同一块内存区域。这种通信方式可以提供高效的数据传输,特别适用于需要频繁交换数据的场景。
在这里插入图片描述

IO间进程通信请点击这里——》IO进程间的通信详解(嵌入式学习)

IO进程间的通信详解(嵌入式学习)《——这里
IO进程间的通信详解(嵌入式学习)《——这里这里里

要在Linux中使用共享内存,需要以下步骤:

  1. 创建共享内存段:使用shmget系统调用创建一个共享内存段。该调用需要指定共享内存标识符、内存大小和权限等参数。如果共享内存已经存在,则可以使用shmget的返回值获取该共享内存段的标识符。

  2. 连接共享内存段:使用shmat系统调用将共享内存段连接到当前进程的地址空间中。shmat需要指定共享内存段的标识符和附加选项。成功连接后,shmat将返回指向共享内存段的指针。

  3. 使用共享内存:一旦连接到共享内存段,进程可以像使用普通内存一样使用共享内存。可以读取、写入数据,进行同步操作等。

  4. 分离共享内存段:当进程不再需要使用共享内存段时,可以使用shmdt系统调用将其与当前进程分离。这将使得共享内存段不再对该进程可见,但不会删除该共享内存段。

  5. 删除共享内存段:当所有进程都不再需要使用共享内存段时,可以使用shmctl系统调用删除该共享内存段。这将释放共享内存并将其从系统中删除。

要使用共享内存,需要包含<sys/ipc.h><sys/shm.h>头文件,并链接到-lrt库。

请注意,共享内存需要进程之间进行适当的同步和互斥操作,以避免竞态条件和数据损坏。通常,使用信号量或其他同步机制来控制对共享内存的访问。

特点

共享内存在进程间通信(IPC)中具有以下特点:

  1. 高效性:共享内存提供了一种高效的数据传输方式,因为数据直接存储在共享内存中,而不需要进行进程间的数据复制。这比其他IPC机制(如管道或消息队列)更快。

  2. 大容量:共享内存可以提供较大的内存空间供多个进程共享。这使得它特别适用于需要频繁交换大量数据的场景。

  3. 实时性:由于共享内存的直接访问性质,进程可以即时地读取和写入共享内存中的数据,使得共享内存在实时应用程序中非常有用。

  4. 简单性:相对于其他IPC机制,使用共享内存进行通信相对较简单。进程可以像访问本地内存一样直接读写共享内存,无需复杂的读取或写入操作。

  5. 零拷贝:共享内存的实现方式通常使用"零拷贝"技术,即数据从一个进程的地址空间传输到另一个进程的地址空间时,避免了数据的中间复制,提高了数据传输的效率。

然而,共享内存也存在一些注意事项:

  1. 同步问题:由于多个进程可以同时访问共享内存,必须进行适当的同步操作,以避免竞态条件和数据不一致的问题。通常使用信号量、互斥锁等同步机制来控制对共享内存的访问。

  2. 生命周期管理:在使用共享内存时,需要确保在合适的时间创建、连接、分离和删除共享内存段。如果没有适当管理共享内存的生命周期,可能会导致内存泄漏或无法访问共享内存的情况。

  3. 安全性:共享内存不提供进程间的安全性保护机制,因此必须确保对共享内存的访问受到适当的权限控制,防止未经授权的进程访问共享内存。

综上所述,共享内存是一种高效、快速的进程间通信机制,适用于需要高吞吐量和实时性的应用程序。但在使用时需要注意同步、生命周期管理和安全性等方面的问题。

函数

在Linux中,可以使用以下函数来操作共享内存:

  1. int shmget(key_t key, size_t size, int shmflg)

    • 该函数创建或打开一个共享内存段。
    • 参数key是用于标识共享内存段的键值。
    • 参数size指定共享内存段的大小。
    • 参数shmflg指定一些标志选项,例如权限和创建标志。
    • 返回值是共享内存段的标识符(非负整数),如果失败则返回-1。
  2. void *shmat(int shmid, const void *shmaddr, int shmflg)

    • 该函数将共享内存段连接到当前进程的地址空间。
    • 参数shmid是共享内存段的标识符。
    • 参数shmaddr指定要连接的地址,通常设置为NULL,让内核选择一个可用地址。
    • 参数shmflg指定一些标志选项,例如读写权限和标志。
    • 返回值是指向共享内存段的指针,如果失败则返回-1
  3. int shmdt(const void *shmaddr)

    • 该函数将共享内存段与当前进程分离。
    • 参数shmaddr是要分离的共享内存段的指针。
    • 返回值为0表示成功,-1表示失败。
  4. int shmctl(int shmid, int cmd, struct shmid_ds *buf)

    • 该函数用于控制共享内存段的属性。
    • 参数shmid是共享内存段的标识符。
    • 参数cmd指定要执行的命令,如删除共享内存段。
    • 参数buf是一个指向struct shmid_ds结构的指针,用于获取或设置共享内存段的属性。
    • 返回值为0表示成功,-1表示失败。

这些函数在<sys/ipc.h><sys/shm.h>头文件中声明。要使用共享内存,您还需要链接到-lrt库。

这只是共享内存函数的基本介绍,您可以参考相关文档和教程以获取更详细的信息和示例代码。

示例代码

以下是一个简单的示例代码,展示如何使用共享内存在两个进程之间进行通信:
在这里插入图片描述

进程A(写入数据到共享内存):

#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>#define SHM_SIZE 1024int main() {int shmid;key_t key;char *shm_ptr;// 生成共享内存的keykey = ftok("/tmp", 'R');if (key == -1) {perror("ftok");exit(1);}// 创建共享内存段shmid = shmget(key, SHM_SIZE, IPC_CREAT | 0666);if (shmid == -1) {perror("shmget");exit(1);}// 连接共享内存段到当前进程的地址空间shm_ptr = shmat(shmid, NULL, 0);if (shm_ptr == (char *)-1) {perror("shmat");exit(1);}// 写入数据到共享内存sprintf(shm_ptr, "Hello, shared memory!");// 分离共享内存段if (shmdt(shm_ptr) == -1) {perror("shmdt");exit(1);}return 0;
}

进程B(从共享内存中读取数据):

#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>#define SHM_SIZE 1024int main() {int shmid;key_t key;char *shm_ptr;// 获取共享内存的keykey = ftok("/tmp", 'R');if (key == -1) {perror("ftok");exit(1);}// 获取共享内存段的标识符shmid = shmget(key, SHM_SIZE, 0666);if (shmid == -1) {perror("shmget");exit(1);}// 连接共享内存段到当前进程的地址空间shm_ptr = shmat(shmid, NULL, 0);if (shm_ptr == (char *)-1) {perror("shmat");exit(1);}// 从共享内存中读取数据并打印printf("Message from shared memory: %s\n", shm_ptr);// 分离共享内存段if (shmdt(shm_ptr) == -1) {perror("shmdt");exit(1);}// 删除共享内存段if (shmctl(shmid, IPC_RMID, NULL) == -1) {perror("shmctl");exit(1);}return 0;
}

在这个示例中,进程A创建了一个大小为1024字节的共享内存段,并写入了一条消息到共享内存中。进程B通过共享内存的键获取到该共享内存段的标识符,并连接到当前进程的地址空间,然后读取共享内存中的数据并打印出来。最后,进程B从共享内存中分离,并使用shmctl函数将共享内存段删除。

请注意,在实际使用中,需要确保进程A和进程B以正确的顺序执行,以便正确地进行共享内存的创建、连接和分离。此外,需要进行适当的同步和互斥操作,以避免竞态条件和数据损坏。

编译和运行示例代码时,需要使用gcc编译器,并链接到-lrt库:

gcc processA.c -o processA -lrt
gcc processB.c -o processB -lrt

然后分别运行进程A和进程B:

./processA
./processB

进程B会输出从共享内存中读取的消息。


http://www.ppmy.cn/news/451436.html

相关文章

MNIST机器学习入门

引入所需库 import osimport cv2 import matplotlib.pyplot as plt import numpy as np import pandas as pd import tensorflow as tf from PIL import ImageMNIST数据集 下载MNIST数据集 mnisttf.keras.datasets.mnist (x_train, y_train), (x_test, y_test) mnist.load_…

随意取名取字php,给孩子取名可诗意莫随意

不仅是大名&#xff0c;如今孩子们的小名也是越来越有趣和多样化&#xff0c;年轻的妈妈们都想给孩子起一个有特点又不重样的小名。90后妈妈小卢笑着告诉记者&#xff1a;“我家孩子因为出生的时候6.66斤&#xff0c;又是在3月26日6时出生的&#xff0c;模样特别6&#xff0c;所…

elasticsearch安装部署教程

ELK介绍 本章节目的 了解什么是ELK 为什么要使用和学习ELK 1.什么是ELK ELK 是elastic公司提供的一套完整的日志收集以及展示的解决方案&#xff0c;是三个产品的首字母缩写&#xff0c;分别是ElasticSearch、Logstash 和 Kibana。 1.1E-ELASTICSEARCH ElasticSearch简称E…

Spring的学习1

Spring简介 Spring 春天 给软件行业带来了春天 2002年&#xff0c;首次推出Spring框架的雏形&#xff1a;interface21框架 Spring框架即以interface21框架为基础&#xff0c;经过重新设计&#xff0c;并不断丰富其内涵&#xff0c;于2004年3月24日&#xff0c;发布了1.0正式版…

企业舆情双十一优惠活动

广告关闭 2017年12月&#xff0c;云社区对外发布&#xff0c;从最开始的技术博客到现在拥有多个社区产品。未来&#xff0c;我们一起乘风破浪&#xff0c;创造无限可能。 优衣库的相关负责人表示此次合作保障了优衣库在“双十一狂欢购”等大型活动中用户的良好购物体验&#x…

Spring第两天学习笔记

org.springframework spring-webmvc 5.3.9 1、spring 1.1、简介 spring&#xff1a;春天 >给软件行业带来了春天 2002年,首次推出了spring框架的雏形:interface21 Spring框架即以interface21框架为基础,经过重新设计,并不断丰富其内涵,于2004年3月24日,发布了1.0正式版。…

伪造邮件钓鱼,要知道的秘密!

微信搜索逆锋起笔关注后回复编程pdf 领取编程大佬们所推荐的 23 种编程资料&#xff01; 邮件钓鱼入门到入土 在大型企业边界安全做的越来越好的情况下&#xff0c;不管是 APT 攻击还是红蓝对抗演练&#xff0c;钓鱼和水坑攻击被越来越多的应用。 一、邮件安全的三大协议 1.1 S…

成也IP败也IP,中日美盲盒经济背后不变的商业逻辑

2020年泡泡玛特传出要上市的消息&#xff0c;这也将盲盒经济推向风口。 除了泡泡玛特&#xff0c;今年刚上市的零售"新贵"名创优品就在近日推出品牌TOPTOY&#xff0c;正式进军潮玩市场。更不用说聚集了大量Z时代和二次元爱好者的b站以及拥有大量知名漫画、动漫IP的…