IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 进程间通信(十二)——System V 共享内存 -> 正文阅读

[C++知识库]进程间通信(十二)——System V 共享内存

System V 共享内存

通信原理

  • 多个进程共享物理内存的同一块区域(通常被称为“段” :segment)
  • 抛弃了内核“代理人”角色,让两个进程直接通过一块内存通信

System V 共享内存

通信原理

  • 多个进程共享物理内存的同一块区域(通常被称为“段” :segment)
  • 抛弃了内核“代理人”角色,让两个进程直接通过一块内存通信

共享内存 VS 消息队列/管道

优势

  • 减少了内存拷贝(从用户空间拷贝到内核、从内核拷贝到用户空间)
  • 减少了2次系统调用,提高了系统性能

使用System V 共享内存

操作流程

  • 获取共享内存对象的ID
  • 将共享内存映射至本进程虚拟空间的某个区域
  • 不同进程通过对这块共享内存进行读写、传输数据
  • 当进程不再使用这块共享内存时,解除映射关系
  • 当没有进程再需要这块共享内存时,删除它

使用共享内存

相关API

  • 获取共享内存对象的ID:int shmget(key_t key, size_t size, int shmflg);
  • 映射共享内存:void *shmat(int shmid, const void *shmaddr, int shmflg);
  • 解除内存映射:int shmdt(const void *shmaddr);
  • 设置内存对象:int shmctl(int shmid, int cmd, struct shmid_ds *buf);
  • 查看IPC对象信息:ipcs -m

相关API

获取共享内存对象的ID

shmget函数负责创建或打开共享内存段

  • 函数原型:int shmget(key_t key, size_t size, int shmflg);
  • 函数功能:创建或打开一个共享内存对象
  • 函数参数:
    • key:IPC对象的键值,一般为IPC_PRIVATE或ftok返回的key值
    • Size:共享内存大小,一般为内存物理页的整数倍
    • shmflg:
      • IPC_CREAT:如果不存在与指定的key对应的段,那么就创建一个新段
      • IPC_EXCL:若key指定的内存存在且指定了IPC_CREAT,返回EEXIST错误
      • SHM_HUGETLB:使用巨页(huge page)
    • 返回值:共享内存的标识符ID

attach共享内存——使用共享内存

shmget函数,不过是在茫茫内存中创建了或找到了一块共享内存区域,但是这块内存和进程尚没有任何关系。

想使用该共享内存,必须先把共享内存引入进程的地址空间,这就是attach操作。

  • 函数原型:void *shmat(int shmid, const void *shmaddr, int shmflg);
  • 函数功能:将shmid标识的共享内存引入到当前进程的虚拟地址空间
  • 函数参数
    • shmid:共享内存的IPC对象ID

    • shmaddr:

      • 若为NULL:共享内存会被attach到一个合适的虚拟地址空间,建议使用NULL
      • 不为NULL:系统会根据参数及地址边界对齐等分配一个合适的地址

      第二个参数是用来指定将共享内存放到虚拟地址空间的什么位置的。

    • 大部分的普通青年都会将第二个参数设置为NULL,表示用户并不在意,一切交由内核做主

    • shmflg:

      • IPC_RDONLY:附加只读权限,不指定的话默认是读写权限
      • IPC_REMAP: 替换位于shmaddr处的任意既有映射:共享内存段或内存映射
      • SHM_RND : 将shmaddr四舍五入为SHMMLBA字节的倍数
  • 返回值:共享内存段的地址
  • shmat如果调用成功,则返回进程虚拟地址空间内的一个地址。如果失败,就会返回(void*)-1

detach共享内存——分离共享内存

shmdt函数仅仅是使进程和共享内存脱离关系,并未删除共享内存。shmdt函数的作用是将共享内存的引用计数减1。如前所述,只有共享内存的引用计数为0时,调用shmctl函数的IPC_RMID命令才会真正地删除共享内存。

  • 函数原型:int shmdt(const void *shmaddr);
  • 函数功能:解除内存映射,将共享内存分离出当前进程的地址空间
  • 函数参数:
    • shmaddr:共享内存地址
  • TIPS:
    • 通过fork创建的子进程会继承父进程所附加的共享内存段,父子进程可以通过共享内存进行IPC通信。
    • 在exec系统调用中,所有附加的共享内存段都会被分离
    • 函数shmdt仅仅是使进程和共享内存脱离关系,将共享内存的引用计数减1,并未删除共享内存
    • 当共享内存的引用计数为0时,调用shmctl的IPC_RMID命令才会删除共享内存

设置共享内存属性

  • 函数原型:int shmctl(int shmid, int cmd, struct shmid_ds *buf);
  • 函数功能:获取/设置共享内存对象属性
  • 当cmd为IPC_STAT和IPC_SET时,需要用到第三个参数
  • 函数参数:
    • shmid:共享内存对象ID
    • cmd:
      • 当cmd为IPC_STAT和IPC_SET时,需要用到第三个参数
      • IPC_STAT: 用于获取shmid对应的共享内存的信息
      • IPC_SETIPC_SET也只能修改shm_perm中的uid、gid及mode
      • IPC_RMID:可以通过如下方式删除共享内存段:如果共享内存的引用计数shm_nattch等于0,则可以立即删除共享内存。
    • buf:
      • 将该内存对象关联的shmid_ds数据结构拷贝到参数buf中

编程方式

  1. 创建
  2. 映射
  3. 读写
  4. 解除映射
  5. 销毁

共享内存share memory写端

int main(int argc, char *argv[])
{
	key_t key = ftok(".", 588);
	int shm_id = shmget(key, 4096, IPC_CREAT|0666 );
	printf("shm_id:%d\n", shm_id);

	/* Automatic allocation */
	char *shm_p = shmat(shm_id, NULL, 0);
	memset(shm_p, 0, sizeof(shm_p));

	fgets(shm_p, 4096, stdin);

	sleep(30);
	shmctl(shm_id, IPC_RMID, NULL);

	return 0;
}

共享内存share memory读端

int main(int argc, char *argv[])
{
 	key_t key = ftok(".", 588);
	int shm_id= shmget(key, 4096, 0666);

	char *shm_p = shmat(shm_id, NULL, 0);
	printf("from share memory:%s\n", shm_p);

	shmdt(shm_p);

	return 0;
}

共享内存的通信限制

  • SHMMNI:系统所能创建的共享内存的最大个数,IPCMIN:32768
  • SHMMIN:一个共享内存段的最小字节数4096
  • SHMMAX:一个共享内存段的最大字节数33554432
  • SHMALL:系统中共享内存的分页总数2097152
  • SHMSEG:一个进程允许attch的共享内存段的大小个数

共享内存通信特点

  • 共享内存抛弃了“内核代理人”角色,提升了系统性能
  • 需要进程本身维护共享内存的各种问题:同步、互斥....
  • 一般需要信号量、互斥锁、文件锁等配合使用,在各个进程之间在高效通信的同时,防止发送数据的践踏,破坏
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-15 22:13:21  更:2022-03-15 22:16:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 4:43:43-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码