当前位置: 首页 > news >正文

使用Posix共享内存区实现进程间通信

使用Posix共享内存区实现进程间通信

使用Posix共享内存区通常涉以下步骤:

  • 进程A 调用shm_open 创建共享内存区
  • 进程A调用ftruncate修改共享内存区大小
  • 进程A 调用mmap将共享内存区映射到进程地址空间ptrA
  • 进程A 使用ptrA对共享内存区进程更改
  • 进程B 使用shm_open打开已有共享内存区
  • 进程B 调用fstat获取共享内存区大小
  • 进程B 调用mmap将共享内存区映射到进程地址空间ptrB
  • 进程B 使用ptrB对共享内存区进行更改
  • 最后由进程A/B调用shm_unlink删除共享内存区
1、shm_open 创建/打开共享内存区

shm_open调用成功后返回共享内存区的文件描述符, 并在/dev/shm目录下生成相应的文件。

shm_open函数声明包含在文件 sys/mman.h 中;

#include <sys/mman.h>
#include <sys/stat.h>        /* For mode constants */
#include <fcntl.h>           /* For O_* constants */int shm_open(const char *name, int oflag, mode_t mode);

oflag的值包含在文件 fcntl.h


#define O_RDONLY     00   //只读
#define O_WRONLY     01   //只写
#define O_RDWR       02   //可读可写
#define O_CREAT      0100 //创建
#define O_EXCL       0200 //如果共享内存区已存在则返错误

mode的值包含在文件sys/stat.h


#define	S_IRUSR	__S_IREAD	/* Read by owner.  */
#define	S_IWUSR	__S_IWRITE	/* Write by owner.  */
#define	S_IXUSR	__S_IEXEC	/* Execute by owner.  */#define	S_IRGRP	(S_IRUSR >> 3)	/* Read by group.  */
#define	S_IWGRP	(S_IWUSR >> 3)	/* Write by group.  */
#define	S_IXGRP	(S_IXUSR >> 3)	/* Execute by group.  */#define	S_IROTH	(S_IRGRP >> 3)	/* Read by others.  */
#define	S_IWOTH	(S_IWGRP >> 3)	/* Write by others.  */
#define	S_IXOTH	(S_IXGRP >> 3)	/* Execute by others.  */
2、ftruncate修改内存区大小

ftruncate包含在头文件unistd.h

/* Truncate the file FD is open on to LENGTH bytes.  */int ftruncate (int __fd, __off_t __length)
fd:shm_ope返回的描述符
length:共享内存区的大小
3、fstat获取文件大小

fstat包含在头文件sys/stat.h

在打开已存在的共享内存区时,可以用fstat获取共享内存区的大小。


/* Get file attributes for the file, device, pipe, or socketthat file descriptor FD is open on and put them in BUF.  */
int fstat (int __fd, struct stat *__buf)
fd:shm_open返回的描述符
stat.st_size是共享内存区的大小
4、mmap将共享内存区映射到进程地址空间

mmap包含在头文件mman.h


void *mmap (void *__addr, size_t __len, int __prot,int __flags, int __fd, __off_t __offset)
参数
__addr: 映射到进程的地址,直接传入NULL就行。
__len: 共享内存区的大小。__prot: 权限
PROT_READ   可读
PROT_WRITE  可写
PROT_EXEC   可执行__flags:映射方式
MAP_SHARED: 当前进程所做的修改其他进程可见 
MAP_PRIVATE:当前进程所做的修改其他进程不可见__fd: shm_open返回的描述符 
__offset:偏移量,一般都传入0
5、shm_unlink删除共享内存区

shm_unlink和shm_open在同一文件中,用于删除共享内存区。

/* Remove shared memory segment.  */
int shm_unlink (const char *__name);
6、练习
  • 进程shmserver创建共享内存区shmtest,并创建子进程等待其他进程向shmtest中写入数据。
  • 进程shmcli向共享内存区shmtest写入数据,并给进程shmserver发送信号。
  • 进程shmserver取出共享内存区shmtest中的数据并输出到窗口。

cond_h.h

#define COUNT 10typedef struct shm_block
{pthread_mutex_t mutex;pthread_cond_t  cond;int arr[COUNT];int nput;int nread;int ncount;
}shm_block;void shm_block_init(shm_block* shm)
{pthread_mutexattr_t attr;            pthread_mutexattr_init(&attr);pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);  pthread_mutex_init(&shm->mutex, &attr);pthread_mutexattr_destroy(&attr);pthread_condattr_t cond_attr;pthread_condattr_init(&cond_attr);pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED);pthread_cond_init(&shm->cond, &cond_attr);pthread_condattr_destroy(&cond_attr);bzero(shm->arr, sizeof(shm->arr));shm->ncount  = 0;shm->nput    = 0;shm->nread   = 0;
}

shm_server.c

#include<unistd.h>
#include<pthread.h>
#include<mqueue.h>
#include<sys/mman.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<stdio.h>
#include<string.h>
#include<errno.h>
#include<strings.h>
#include<wait.h>
#include"cond_h.h"int main(int argc, char* argv[])
{   if (argc != 2){printf("shmcreate [shmname]\n");return 0;}shm_block shm;shm_block_init(&shm);int shmfd = shm_open(argv[1], O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR);if (shmfd == -1){printf("%d : %s\n",__LINE__, strerror(errno));return -1;}printf("create shared memory %s. \n", argv[1]);if (ftruncate(shmfd, sizeof(shm_block)) < 0){printf("%d : %s\n",__LINE__, strerror(errno));return -1;}shm_block* pBlock =  (shm_block*)mmap(NULL, sizeof(shm_block), PROT_WRITE|PROT_READ, MAP_SHARED, shmfd, 0);if (NULL == pBlock){printf("%d : %s\n",__LINE__, strerror(errno));return -1;}close(shmfd);memcpy(pBlock, &shm, sizeof(shm));int pid = fork();if (pid == 0){int fd = shm_open(argv[1], O_RDWR, S_IRUSR|S_IWUSR);if (fd < 0){printf("%d : %s\n",__LINE__, strerror(errno));return -1;}struct stat st;fstat(fd, &st);printf("%d: st_size = %d\n", __LINE__, st.st_size);shm_block *p = (shm_block*)mmap(NULL, st.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);if (NULL == p){printf("%d : %s\n",__LINE__, strerror(errno));return -1;}while (1){pthread_mutex_lock(&p->mutex);while (p->ncount <= 0)pthread_cond_wait(&p->cond, &p->mutex);int value = p->arr[p->nread];p->ncount--;p->nread++;p->nread %= COUNT; pthread_mutex_unlock(&p->mutex);printf("%d: p->nread:%d, arr[nread] : %d\n",__LINE__, p->nread, value);}munmap(p, st.st_size);close(fd);return 0;}int stat_loc = 0;waitpid(pid, &stat_loc, 0);munmap(pBlock, sizeof(shm));if (WIFEXITED(stat_loc)) printf("Child process exited with status: %d\n", WEXITSTATUS(stat_loc));return 0;
}

shm_cli.c

#include<sys/mman.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<pthread.h>
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<errno.h>
#include"cond_h.h"int main(int argc, char *argv[])
{if (argc != 3){printf("cond_put <shmname> <value>");return -1;}char *shmname = argv[1];int   value   = atoi(argv[2]);int   shmfd   = shm_open(shmname, O_RDWR, 0);if (-1 == shmfd){printf("%d: %s\n", __LINE__, strerror(errno));return -1;}shm_block* p =  (shm_block*)mmap(NULL, sizeof(shm_block), PROT_READ|PROT_WRITE, MAP_SHARED, shmfd, 0);if (NULL == p){printf("%d: %s\n", __LINE__, strerror(errno));return -1;}close(shmfd);pthread_mutex_lock(&p->mutex);do{if (p->ncount == COUNT)break;p->arr[p->nput] = value;printf("count: %d,  nput: %d, nread: %d,arr[nput]:%d\n", p->ncount, p->nput, p->nread,value);p->nput         = (p->nput + 1) % COUNT;p->ncount++;if (p->ncount == 1)pthread_cond_signal(&p->cond);} while (0);pthread_mutex_unlock(&p->mutex);close(shmfd);return 0;
}

使用方法:


unlink /dev/shm/shmtest
gcc shm_server.c -lrt -lpthread -o shmserver
./shmserver shmtest

gcc shm_cli.c -lrt -lpthread -o shmcli
./shmcli  shmtest 33
./shmcli  shmtest 34
./shmcli  shmtest 35

shmserver输出:


create shared memory shmtest. 
60: st_size = 144
83: p->nread:1, arr[nread] : 33
83: p->nread:2, arr[nread] : 34
83: p->nread:3, arr[nread] : 35

相关文章:

使用Posix共享内存区实现进程间通信

使用Posix共享内存区实现进程间通信 使用Posix共享内存区通常涉以下步骤: 进程A 调用shm_open 创建共享内存区进程A调用ftruncate修改共享内存区大小进程A 调用mmap将共享内存区映射到进程地址空间ptrA进程A 使用ptrA对共享内存区进程更改进程B 使用shm_open打开已有共享内存…...

家政预约小程序12服务详情

目录 1 修改数据源2 创建页面3 搭建轮播图4 搭建基本信息5 显示服务规格6 搭建服务描述7 设置过滤条件总结 我们已经在首页、分类页面显示了服务的列表信息&#xff0c;当点击服务的内容时候需要显示服务的详情信息&#xff0c;本篇介绍一下详情页功能的搭建。 1 修改数据源 在…...

【C语言】指针详细解读2

1.const 修饰指针 1.1 const修饰变量 变量是可以修改的&#xff0c;如果把变量的地址交给⼀个指针变量&#xff0c;通过指针变量的也可以修改这个变量。 但是如果我们希望⼀个变量加上⼀些限制&#xff0c;不能被修改&#xff0c;怎么做呢&#xff1f;这就是const的作⽤。 #in…...

MongoDB 聚合

MongoDB 中聚合(aggregate)主要用于处理数据(诸如统计平均值&#xff0c;求和等)&#xff0c;并返回计算后的数据结果。 有点类似 SQL 语句中的 count(*)。 aggregate() 方法 MongoDB中聚合的方法使用aggregate()。 语法 aggregate() 方法的基本语法格式如下所示&#xff1…...

LabVIEW涡轮诊断系统

一、项目背景与行业痛点 涡轮机械是发电厂、航空发动机、石油化工等领域的核心动力设备&#xff0c;其运行状态直接关系到生产安全与经济效益。据统计&#xff0c;涡轮故障导致的非计划停机可造成每小时数十万元的经济损失&#xff0c;且突发故障可能引发严重安全事故。传统人…...

机器学习在地震预测中的应用

## 1. 机器学习与地震预测 地震是自然界的一种极端灾害&#xff0c;其发生常常给人们的生命和财产带来极大的威胁。虽然科学家们一直在寻求可靠的方法来预测地震&#xff0c;但由于地震预测本身的复杂性&#xff0c;长期以来难以取得根本性突破。然而&#xff0c;近年来&#x…...

总结11..

#include <stdio.h> #include <string.h> #define MAXN 1001 #define MAXM 1000001 int n, m; char maze[MAXN][MAXN]; int block[MAXN][MAXN]; // 标记每个格子所属的连通块编号 int blockSize[MAXN * MAXN]; // 记录每个连通块的大小 int dx[] {0, 0, 1, -1};…...

c++ 定点 new 及其汇编解释

&#xff08;1&#xff09; 代码距离&#xff1a; #include <new> // 需要包含这个头文件 #include <iostream>int main() {char buffer[sizeof(int)]; // 分配一个足够大的字符数组作为内存池int* p new(&buffer) int(42); // 使用 placement new…...

Linux 传输层协议 UDP 和 TCP

UDP 协议 UDP 协议端格式 16 位 UDP 长度, 表示整个数据报(UDP 首部UDP 数据)的最大长度如果校验和出错, 就会直接丢弃 UDP 的特点 UDP 传输的过程类似于寄信 . 无连接: 知道对端的 IP 和端口号就直接进行传输, 不需要建立连接不可靠: 没有确认机制, 没有重传机制; 如果因…...

springCload快速入门

原作者&#xff1a;3. SpringCloud - 快速通关 前置知识&#xff1a; Java17及以上、MavenSpringBoot、SpringMVC、MyBatisLinux、Docker 1. 分布式基础 1.1. 微服务 微服务架构风格&#xff0c;就像是把一个单独的应用程序开发为一套小服务&#xff0c;每个小服务运行在自…...

从 HTTP/1.1 到 HTTP/3:如何影响网页加载速度与性能

一、前言 在最近使用Apipost时&#xff0c;突然注意到了http/1.1和http/2&#xff0c;如下图&#xff1a; 在我根深蒂固的记忆中&#xff0c;对于http的理解还停留在TCP协议、三次握手。由于我的好奇心&#xff0c;于是触发了我被动“开卷”&#xff0c;所以有了这篇文章&…...

人工智能导论-第3章-知识点与学习笔记

参考教材3.2节的内容&#xff0c;介绍什么是自然演绎推理&#xff1b;解释“肯定后件”与“否定前件”两类错误的演绎推理是什么意义&#xff0c;给出具体例子加以阐述。参考教材3.3节的内容&#xff0c;介绍什么是文字&#xff08;literal&#xff09;&#xff1b;介绍什么是子…...

游戏引擎 Unity - Unity 下载与安装

Unity Unity 首次发布于 2005 年&#xff0c;属于 Unity Technologies Unity 使用的开发技术有&#xff1a;C# Unity 的适用平台&#xff1a;PC、主机、移动设备、VR / AR、Web 等 Unity 的适用领域&#xff1a;开发中等画质中小型项目 Unity 适合初学者或需要快速上手的开…...

鼠标拖尾特效

文章目录 鼠标拖尾特效一、引言二、实现原理1、监听鼠标移动事件2、生成拖尾元素3、控制元素生命周期 三、代码实现四、使用示例五、总结 鼠标拖尾特效 一、引言 鼠标拖尾特效是一种非常酷炫的前端交互效果&#xff0c;能够为网页增添独特的视觉体验。它通常通过JavaScript和C…...

4 前置技术(下):git使用

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言 前言...

从零开始:用Qt开发一个功能强大的文本编辑器——WPS项目全解析

文章目录 引言项目功能介绍1. **文件操作**2. **文本编辑功能**3. **撤销与重做**4. **剪切、复制与粘贴**5. **文本查找与替换**6. **打印功能**7. **打印预览**8. **设置字体颜色**9. **设置字号**10. **设置字体**11. **左对齐**12. **右对齐**13. **居中对齐**14. **两侧对…...

解决国内服务器 npm install 卡住的问题

在使用国内云服务器时&#xff0c;经常会遇到 npm install 命令执行卡住的情况。本文将分享一个典型案例以及常见的解决方案。 问题描述 在执行以下命令时&#xff1a; mkdir test-npm cd test-npm npm init -y npm install lodash --verbose安装过程会卡在这个状态&#xf…...

DeepSeek 的含金量还在上升

大家好啊&#xff0c;我是董董灿。 最近 DeepSeek 越来越火了。 网上有很多针对 DeepSeek 的推理测评&#xff0c;除此之外&#xff0c;也有很多人从技术的角度来探讨 DeepSeek 带给行业的影响。 比如今天就看到了一篇文章&#xff0c;探讨 DeepSeek 在使用 GPU 进行模型训练…...

使用 Docker(Podman) 部署 MongoDB 数据库及使用详解

在现代开发环境中&#xff0c;容器化技术&#xff08;如 Docker 和 Podman&#xff09;已成为部署和管理应用程序的标准方式。本文将详细介绍如何使用 Podman/Docker 部署 MongoDB 数据库&#xff0c;并确保其他应用程序容器能够通过 Docker 网络成功连接到 MongoDB。我们将逐步…...

大模型训练(6):张量并行

0 英文缩写 Pipeline Parallelism&#xff08;PP&#xff09;流水线并行Tensor Parallel&#xff08;TP&#xff09;张量并行Data Parallelism&#xff08;DP&#xff09;数据并行Distributed Data Parallelism&#xff08;DDP&#xff09;分布式数据并行Zero Redundancy Opti…...

2021年中国村级行政区划边界矢量数据|行政村 + 社区|全国60万+单元|SHP格式、WGS84坐标

&#x1f50d; 数据简介 本数据集 2021年左右的中国村级行政区划边界矢量数据。 总计 超60万个村级单元&#xff0c;是目前公开可获取的最精细、最权威的全国村级边界数据之一&#xff0c;适用于乡村振兴、基层治理、人口空间化、公共服务设施布局、学术研究等高精度需求场景。…...

基于STM32与ADC的锂电池电量监测系统设计

1. 锂电池电量监测为什么需要STM32和ADC&#xff1f; 做嵌入式开发的朋友应该都遇到过这样的需求&#xff1a;设备用锂电池供电&#xff0c;需要实时显示剩余电量。比如手持设备、智能家居控制器或者无人机&#xff0c;电量显示都是刚需功能。但锂电池的特性决定了直接测量电量…...

Midjourney 图像到图像转换:真实人物与动漫的一致性与多样场景选择

Midjourney 拥有强大的图像到图像转换能力。本文将手把手教你如何在我们的 AceDataCloud 网站 上将照片切换到任何动漫场景&#xff0c;同时保持角色的一致性。 通过以下步骤&#xff0c;我们可以轻松实现角色一致性。 接下来&#xff0c;我们看一下效果&#xff0c;原始图像如…...

深度剖析:synchronized 底层实现原理(JVM 视角)

一、Java对象内存布局的深度拆解原文提到了对象头&#xff0c;这里补充64位JVM的完整对象布局和对齐填充的底层原因。1.1 64位JVM的完整对象结构text┌─────────────────────────────────────────────┐ │ 对象头…...

nanomsg性能基准测试终极指南:不同消息大小下的吞吐量对比分析

nanomsg性能基准测试终极指南&#xff1a;不同消息大小下的吞吐量对比分析 【免费下载链接】nanomsg nanomsg library 项目地址: https://gitcode.com/gh_mirrors/na/nanomsg nanomsg是一个轻量级、高性能的消息传递库&#xff0c;专为解决常见的通信模式而设计。作为na…...

Apache Sedona 使用教程

Apache Sedona 使用教程 项目介绍 Apache Sedona 是一个用于大规模空间数据处理的分布式计算系统。它基于 Apache Spark&#xff0c;提供了高效的空间数据处理能力&#xff0c;支持多种空间数据类型和操作。Sedona 旨在为大数据环境下的地理空间分析提供强大的支持&#xff0c;…...

Medusa小程序:微信、支付宝等小程序平台对接的完整指南

Medusa小程序&#xff1a;微信、支付宝等小程序平台对接的完整指南 【免费下载链接】medusa 项目提供了构建数字商务所需的组件和服务&#xff0c;旨在简化和加速电子商务平台的开发工作流程。 项目地址: https://gitcode.com/GitHub_Trending/me/medusa Medusa是一个强…...

【深度解析】DeepSeek API 悄然分叉:开发者该如何正确评估与接入最新大模型?

摘要 本文基于近期 DeepSeek API 更新及官方文档变更&#xff0c;从「API 版本 ≠ Web/App 版本」这一关键细节出发&#xff0c;梳理大模型多版本部署策略背后的技术与成本逻辑&#xff0c;并给出基于兼容 OpenAI 协议的实战接入示例&#xff08;使用 claude‑sonnet‑4‑6&…...

HunyuanVideo-Foley音效生成:支持SMPTE时间码对齐视频关键帧

HunyuanVideo-Foley音效生成&#xff1a;支持SMPTE时间码对齐视频关键帧 1. 产品概述 HunyuanVideo-Foley是一款专为影视后期制作设计的AI音效生成工具&#xff0c;其核心创新在于支持SMPTE时间码精确对齐视频关键帧。这意味着音效师可以基于视频时间轴上的特定帧&#xff0c…...

Ollama + DeepSeek + 芋道框架 + SearXNG 本地联网搜索完整教程

1. 环境准备与检查 在开始之前,请确保你的环境满足以下条件: 1.1 硬件要求 内存:建议至少8GB可用内存(运行7B模型需要约4-6GB) 硬盘:DeepSeek模型文件约4-5GB空间 CPU/GPU:如有NVIDIA GPU可加速推理(可选) 1.2 软件要求 操作系统:Windows 10/11、macOS、Linux均可 …...