当前位置:网站首页>POSIX共享内存
POSIX共享内存
2022-06-21 16:19:00 【拉松】
本文参考《嵌入式Linux开发教程》和《Linux/UNIX系统编程手册》。
共享内存概述
共享内存是允许两个不相关的进程访问同一个逻辑内存的进程间通信方法,是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式。
不同进程之间的共享内存通常安排为同一段物理内存。进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由用 C语言 malloc()分配的内存一样。两个进程使用共享内存的通信机制如图所示。
POSIX 共享内存区涉及四个主要步骤:
1.指定一个名字参数调用 shm_open,以创建一个新的共享内存区对象(或打开一个已经存在的共享内存区对象);
2.调用 mmap 把这个共享内存区映射到调用进程的地址空间;
3.调用 munmap() 取消共享内存映射;
4.调用 shm_unlink()函数删除共享内存段。
在编译 POSIX 共享内存应用程序时需要加上-lrt 参数。
打开或创建一个共享内存区
shm_open()函数用来打开或者创建一个共享内存区,两个进程可以通过给 shm_open()函数传递相同的名字以达到操作同一共享内存的目的。
int shm_open(const char *name, int oflag, mode_t mode);
函数成功返回创建或打开的共享内存描述符,与文件描述符作用相同,供后续操作使用,失败则返回-1。
删除共享内存
当使用完共享内存后,需要将其删除,以便释放系统资源,可通过 shm_unlink()函数完成。
int shmunlink(const char *name);
函数成功返回 0,否则返回-1。参数 name 为共享内存的名字。
设置共享内存大小
创建一个共享内存后,其默认大小为 0,所以需要设置该共享内存的大小。
int ftruncate(int fd, off_t length);
函数成功返回 0,失败返回-1。参数 fd 为需要调整的共享内存或者文件的描述符,length 为需要调整的大小。
映射共享内存
创建共享内存后,需要将这块内存区域映射到调用进程的地址空间中,可通过 mmap()函数来完成。
void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
函数成功返回映射后指向共享内存的虚拟地址,失败返回 MAP_FAILED 值。
取消共享内存映射
已经建立的共享内存映射,可通过 munmap()函数来取消。
int munmap(void *addr, size_t length);
参数 addr 为 mmap()函数返回的地址,length 是映射的字节数。取消映射后再对映射地址访问会导致调用进程收到 SIGSEGV 信号。
共享内存范例
程序清单write.c与程序清单read.c两个范例实现了两个无关进程间使用共享内存进行通信的功能。一个进程往共享内存起始地址写入一个整形数据12,另一个进程则检测该区域的数据,如果不是12,继续等待,直到数据变化为12。
程序清单write.c所示代码完成共享内存写操作,先创建共享内存,设置大小并完成映射,随后往共享内存起始地址写入一个值为12 的整形数据,最后取消和删除共享内存。
[email protected]r-virtual-machine:~/workspace/test$ cat write.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#define SHMSIZE 10 //共享内存大小,10 字节
#define SHMNAME "shmtest" //共享内存名称
int main()
{
int fd;
char *ptr;
/* 创建共享内存 */
fd = shm_open(SHMNAME, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
if (fd<0) {
perror("shm_open error");
exit(-1);
}
/* 设置共享内存大小*/
ftruncate(fd, SHMSIZE); //设置大小为 SHMSIZE
/*映射共享内存*/
ptr = mmap(NULL, SHMSIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (ptr == MAP_FAILED) {
perror("mmap error");
exit(-1);
}
*ptr = 0x12; //往起始地址写入 12
munmap(ptr, SHMSIZE); //取消映射
shm_unlink(SHMNAME); //删除共享内存
return 0;
}
程序清单read.c所示范例为读共享内存,首先创建共享内存,然后设置大小并映射共享内存,最后检测共享内存首字节数据是否为12,如果不是,继续等待,否则打印显示,并取消和删除共享内存。
[email protected]-virtual-machine:~/workspace/test$ cat read.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#define SHMSIZE 10 //共享内存大小,10 字节
#define SHMNAME "shmtest" //共享内存名称
int main()
{
int fd;
char *ptr;
/*创建共享内存 */
fd = shm_open(SHMNAME, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if (fd < 0) {
perror("shm_open error");
exit(-1);
}
/*映射共享内存*/
ptr = mmap(NULL, SHMSIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (ptr == MAP_FAILED) {
perror("mmap error");
exit(-1);
}
/* 设置共享内存大小 */
ftruncate(fd, SHMSIZE);
while (*ptr != 0x12) {
//读起始地址,判断值是否为12
sleep(1); //不是12,继续读取
}
printf("ptr : %d\n", *ptr); //数据是12,打印显示
munmap(ptr, SHMSIZE); //取消内存映射
shm_unlink(SHMNAME); //删除共享内存
return 0;
}
下图为运行结果截图,共享内存的读进程先在后台运行,它循环等待写进程对共享内存做修改。当写进程完成修改后,读进程将检测到共享内存单元的值发生了变化,然后打印出来并退出。
[email protected]-virtual-machine:~/workspace/test$ gcc read.c -o read -lrt
[email protected]-virtual-machine:~/workspace/test$ gcc write.c -o write -lrt
[email protected]-virtual-machine:~/workspace/test$ ./read &
[1] 3752
[email protected]-virtual-machine:~/workspace/test$ ./write
[email protected]-virtual-machine:~/workspace/test$ ptr : 18
[1]+ Done ./read
[email protected]-virtual-machine:~/workspace/test$
边栏推荐
- Your cache folder contains root-owned files, due to a bug in npm ERR! previous versions of npm which
- Google play application signature key certificate, upload signature certificate difference
- Jetpack compose status promotion (II)
- 数字经济王宁教你如何正确地选择短期投资
- regular expression
- 我被变相降薪了
- list的使用
- Accélérer le déploiement de l'application Native Cloud et compléter l'authentification de compatibilité entre Yanrong yrcloudfile et Tianyi Cloud
- Clickhouse learning notes 2: basic use tutorial
- Viewing technological changes through Huawei Corps (IV): interactive media (Music)
猜你喜欢

Technical architecture of large websites | information encryption technology and key security management

Are the two flame retardant standards of European furniture en 597-1 and en 597-2 the same?

Pingcap was selected as the "voice of customers" of Gartner cloud database in 2022, and won the highest score of "outstanding performer"

aws elastic beanstalk入门之简介
![[Oracle] is there a](/img/21/3c481be79a4f19b06a2a93ded4159f.png)
[Oracle] is there a "time" data type in oracle-- Research on Oracle data types

ViT杀疯了,10+视觉Transformer模型详解

大型网站技术架构 | 应用服务器安全防御

From demand to open source, how to look at it with new eyes?

C语言与Lua的交互(实践二)

Analysis of 43 cases of MATLAB neural network: Chapter 27 prediction of LVQ Neural Network - face orientation recognition
随机推荐
BFS与DFS
Are the two flame retardant standards of European furniture en 597-1 and en 597-2 the same?
Stack awareness - stack overflow instance (ret2libc)
PingCAP 入选 2022 Gartner 云数据库“客户之声”,获评“卓越表现者”最高分
What is the difference between IEC62133 and EN62133? Which items are mainly tested?
稳若磐石的焱融 SaaS 服务平台背后,是数据生态的崛起
List集合转为逗号拼接的字符串
Bm22 compare version number
加速雲原生應用落地,焱融 YRCloudFile 與天翼雲完成兼容性認證
超分之RLSP
Live broadcast platform development, live broadcast of each category and single example design display
Jetpack compose status promotion (II)
AttributeError: module ‘cv2‘ has no attribute ‘gapi_ wip_ gst_ GStreamerPipeline‘
在线直播系统源码,实现进入页面就去请求列表接口并触底分页加载
Jetpack compose management status (I)
Addition of 3DE grid coordinate points and objects
焱融科技 YRCloudFile 与安腾普完成兼容认证,共创存储新蓝图
EtherCAT igh 'Fatal Sync Error'——0x002C,0x001A
PTA L3-032 关于深度优先搜索和逆序对的题应该不会很难吧这件事 (30 分)
Jetpack compose phase