1. 共享内存简介

共享内存主要用于不同进程之间相互通信,因为操作的是同一块地址,不需要内核和用户层之间数据拷贝,属于最快的进程间通信方式,不过,为了防止读写冲突,一般需要额外的同步手段。之前介绍了SystemV共享内存的使用方式,今天介绍下Posix共享内存。Posix 共享内存API主要有这几个,shm_open,用于获取或者创建一个共享内存文件描述符,ftruncate,用于设置共享内存的大小,新建的共享内存大小为0,mmap,用于将共享内存文件映射到进程的虚拟地址空间,其实共享内存真正核心的工作主要在于mmap,不过mmap是另外一个话题,暂时不讨论。munmap,和mmap作用相反。shm_unlink,移除共享内存。close关闭shm_open获取的文件描述符,通常mmap之后就可以关闭了。fstat获取共享内存的信息,比如大小。下面介绍下相关API接口

2. API接口

2.1 创建共享内存

#include <sys/mman.h>
#include <sys/stat.h> /* For mode constants */
#include <fcntl.h> /* For O_* constants *//**
* @brief 创建或获取已存在的共享内存
*
* @params name 共享内存名字,以斜杠开头'/',不超过NAME_MAX(255)字符
* @params oflag O_RDONLY| O_RDWR| O_CREAT| O_EXCL| O_TRUNC
* @params mode 设置一些权限,通常使用0即可
*
* @returns 成功返回文件描述符,失败返回-1
**/int shm_open(const char *name, int oflag, mode_t mode);

2.2 设置共享内存大小

#include <unistd.h>
#include <sys/types.h>/**
* @brief 修改fd的大小
*
* @returns 成功返回0,失败返回-1
**/int ftruncate(int fd, off_t length);

2.3 查询共享内存文件大小

#include <unistd.h>
#include <sys/types.h>/**
* @brief 查询fd的信息
* @param fd 要查询的文件描述符
* @param buf 用于保存查询结果的buffer
* @returns 成功返回0,失败返回-1
**/struct stat {dev_t     st_dev;     /* ID of device containing file */ino_t     st_ino;     /* inode number */mode_t    st_mode;    /* protection */nlink_t   st_nlink;   /* number of hard links */uid_t     st_uid;     /* user ID of owner */gid_t     st_gid;     /* group ID of owner */dev_t     st_rdev;    /* device ID (if special file) */off_t     st_size;    /* total size, in bytes */blksize_t st_blksize; /* blocksize for file system I/O */blkcnt_t  st_blocks;  /* number of 512B blocks allocated */time_t    st_atime;   /* time of last access */time_t    st_mtime;   /* time of last modification */time_t    st_ctime;   /* time of last status change */
};int fstat(int fd, struct stat *buf);

2.4 映射共享内存

#include <sys/mman.h>/**
* @brief 映射共享内存到进程自身虚拟地址空间
*
* @params addr 映射到的地址,通常设置为NULL,表示内核自己选择合适地址。
* @params length 映射的共享内存大小
* @params prot 保护标志位,可选PROT_EXEC| PROT_READ| PROT_WRITE| PROT_NONE
* @params flags 可选
* MAP_SHARED,共享模式,修改对其它进程可见
* MAP_PRIVATE 私有映射,对共享内存的修改对其它进程不可见。
* @params fd 被映射的共享内存文件描述符
* @params offset 文件偏移值,通常填0
* @returns 成功返回共享内存地址,失败返回-1
**/void *mmap(void *addr, size_t length,int prot, int flags ,int fd, off_t offset);/**
* @brief 删除mmap的映射
*
* @params addr 映射到的地址
* @params length 映射的共享内存大小
* @returns 成功返回0址,失败返回-1
**/int munmap(void *addr, size_t length);

2.5 删除共享内存

#include <sys/mman.h>
#include <sys/stat.h> /* For mode constants */
#include <fcntl.h> /* For O_* constants *//**
* @brief 删除共享内存,只有当所有进程都取消映射后才销毁它
*
* @params name 共享内存名字
*
* @returns 成功返回0,失败返回-1
**/int shm_unlink(const char *name);# 编译加上 -lrt选项
Link with -lrt.

3. 共享内存示例

这里仅简单读写,没有考虑同步。

3.1 写共享内存

#include <sys/mman.h>
#include <sys/stat.h> /* For mode constants */
#include <fcntl.h> /* For O_* constants */
#include <error.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <string.h>#define SHM_NAME "/shm0"
#define SHM_SIZE 4096int main(int argc, char** argv)
{if (argc < 2){printf("Usage: ./shm_write msg\n");return -1;}// 创建或打开已存在的共享内存int shm_fd = shm_open(SHM_NAME, O_RDWR|O_CREAT, 0);if (shm_fd == -1){perror("shm_open error");return -1;}// 设置共享内存大小if (ftruncate(shm_fd, SHM_SIZE)){perror("ftruncate error");return -1;}// 映射共享内存char* buffer = (char *)mmap(NULL, SHM_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, shm_fd, 0);if (buffer == (char *)MAP_FAILED){perror("mmap error");return -1;}// 关闭共享内存文件描述符,并不影响映射close(shm_fd);// 写共享内存strncpy(buffer, argv[1], strlen(argv[1]));// 删除共享内存//shm_unlink(shm_fd);return 0;
}

3.2 读共享内存

#include <sys/mman.h>
#include <sys/stat.h> /* For mode constants */
#include <fcntl.h> /* For O_* constants */
#include <error.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>#define SHM_NAME "/shm0"
#define SHM_SIZE 4096int main()
{// 创建或打开共享内存int shm_fd = shm_open(SHM_NAME, O_RDWR|O_CREAT, 0);if (shm_fd == -1){perror("shm_open error");return -1;}// 获取共享内存大小,读取的时候要用struct stat stat={0};if (fstat(shm_fd, &stat)){perror("fstat error");return -1;}// 映射共享内存,大小为上一步获取的大小char* buffer = (char*)mmap(NULL, stat.st_size, PROT_READ, MAP_SHARED, shm_fd, 0);if (buffer == (char *)MAP_FAILED){perror("mmap error");return -1;}// 关闭文件描述符close(shm_fd);// 读取共享内存printf("Read Msg:%s\n", buffer);// 删除共享内存shm_unlink(SHM_NAME);return 0;
}

3.3 编译&运行

default:gcc -o shm_read shm_read.c -lrtgcc -o shm_write shm_write.c -lrt
clean:rm -rf shm_write shm_read

4. 参考文档

https://www.man7.org/linux/man-pages/man7/mq_overview.7.html

================================================================================================

Linux应用程序、内核、驱动、后台开发交流讨论群(745510310),感兴趣的同学可以加群讨论、交流、资料查找等,前进的道路上,你不是一个人奥^_^。...

Linux进程间通信六 Posix 共享内存简介与示例相关推荐

  1. linux进程间通信:POSIX 共享内存

    文章目录 思维导图 通信原理 优势 POSIX 共享内存 编程接口 编程案例 思维导图 之前学习过sysemV 的共享内存的实现及使用原理,参考linux进程间通信:system V 共享内存 POS ...

  2. linux进程间通信之Posix共享内存用法详解及代码举例

    Posix共享内存有两种非亲缘进程间的共享内存方法: 1).  使用内存映射文件,由open函数打开,再由mmap函数把返回的文件描述符映射到当前进程空间中的一个文件. 2). 使用共享内存区对象,由 ...

  3. Linux进程间通信四 Posix 消息队列简介与示例

    目录 1. Posix 消息队列简介 2. API接口 2.1 创建或打开消息队列 2.2 发送消息 2.3 接收消息 2.4 获取.设置消息队列属性 2.5 关闭消息队列 2.6 删除消息队列 2. ...

  4. Linux进程间通信一 System V 共享内存简介与示例

    目录 1. System V共享内存简介 2. API介绍 2.0 key_t和标识符 2.1  创建system v共享内存 2.2 映射共享内存并使用 2.3 取消共享内存映射 2.4 控制共享内 ...

  5. Linux进程间通信三 System V 信号量简介与示例

    1. System V信号量简介 SystemV信号量主要用于解决生产者和消费者问题,一个信号量能够控制多个资源,说它是信号量集也不为过. 2. API接口介绍 2.1 创建或打开信号量集 #incl ...

  6. 【Linux 应用编程】进程管理 - 进程间通信IPC之共享内存 mmap

    IPC(InterProcess Communication,进程间通信)是进程中的重要概念.Linux 进程之间常用的通信方式有: 文件:简单,低效,需要代码控制同步 管道:使用简单,默认阻塞 匿名 ...

  7. Linux IPC实践(10) --Posix共享内存

    1. 创建/获取一个共享内存 #include <sys/mman.h> #include <sys/stat.h> /* For mode constants */ #inc ...

  8. 共享内存简介和mmap 函数

    一.共享内存简介 共享内存区是最快的IPC形式,这些进程间数据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据. 即每个进程地址空间都有一个共享存储器的映射区,当这块区 ...

  9. mmap内存映射、system V共享内存和Posix共享内存

    linux内核支持多种共享内存方式,如mmap内存映射,Posix共享内存,以system V共享内存.当内核空间和用户空间存在大量数据交互时,共享内存映射就成了这种情况下的不二选择.它能够最大限度的 ...

最新文章

  1. 流程快速开发平台,工作流引擎中间件,工作质量考核设计
  2. Java jdbctemplate赋值_Spring 之 Spring JdbcTemplate的使用
  3. NYOJ 595 乱七八糟
  4. MySQL主从复制的原理:IO用于交互 SQL用于解析执行;主bin-log 从relay-log;
  5. Object C学习笔记19-枚举(转)
  6. 解决设备升级至Android 4.2.2之后,可以连接但无法调试的问题
  7. 线程也不是越多越好,多少是好?
  8. spark 查看yarn日志_spark周边项目之Livy
  9. 最小可用ID(4种方法,详细讲解)
  10. C++ string替换指定字符
  11. 情感在语文教育中的作用
  12. Filter 过滤器使用
  13. 使用Java解牛客网六一儿童节
  14. 性能测试监控TP50、TP99、TP999含义(99分位延时的含义)
  15. c语言 青蛙上台阶问题
  16. PTA 病毒感染检测 (15分)
  17. 分形、大自然的分形几何、数据可视化、Python绘图
  18. 常用docker镜像
  19. 【swust.oj_1088】我们的征途是星辰大海
  20. 联通C网彩信群发的问题

热门文章

  1. C# 关闭正在执行的文件
  2. Assessing systemic risk due to fire sales spillover through maximum entropy network reconstruction
  3. python paramiko_python中的paramiko模块
  4. 4.5 搭建深层神经网络块-深度学习-Stanford吴恩达教授
  5. TCL with SNPS file existsfile rename/copy redirect lsearch split
  6. 【笔记】微软onedirve云存储使用小结
  7. MySQL查询获取行号rownum
  8. 铁路交通系统安全堪忧:丹麦国家铁路运营商DSB和RENA售票网站接连受创
  9. 《MVC 系列》- 控制器数据传递
  10. 详解linux系列之sendmail邮箱服务的安装及配置