Linux 基础入门操作 第九章 进程之间通讯共享内存

embedded/2024/9/24 12:43:13/

9.4 共享内存

速度最快,效率最高的进程间通信方式,进程之间直接访问内存,而不是通过传送数据。但是使用共享内存需要自己提供同步机制。

9.4.1 创建函数

int shmget(key_t key, size_t size, int shmflg);

第一个参数,与信号量的 semget 函数一样,程序需要提供一个参数 key(非 0 整数),它有效地为共享内存段命名,shmget 函数成功时返回一个与 key 相关的共享内存标识符(非负整数),用于后续的共享内存函数。调用失败返回-1。

不相关的进程可以通过该函数的返回值访问同一共享内存,它代表程序可能要使用的某个资源,程序对所有共享内存的访问都是间接的,程序先通过调用 shmget 函数并提供一个键,再由系统生成一个相应的共享内存标识符(shmget 函数的返回值),只有 shmget 函数才直接使用信号量键,所有其他的信号量函数使用由semget 函数返回的信号量标识符。

第二个参数,size 以字节为单位指定需要共享的内存容量

第三个参数,shmflg 是权限标志,它的作用与 open 函数的 mode 参数一样,如果要想在 key 标识的共享内存不存在时,创建它的话,可以与 IPC_CREAT 做或操作。共享内存的权限标志与文件的读写权限一样,举例来说,0644,它表示允许一个进程创建的共享内存被内存创建者所拥有的进程向共享内存读取和写入数据,同时其他用户创建的进程只能读取共享内存。

9.4.2 启动函数

第一次创建完共享内存时,它还不能被任何进程访问,shmat 函数的作用就是用来启动对该共享内存的访问,并把共享内存连接到当前进程的地址空间。

void *shmat(int shm_id, const void *shm_addr, int shmflg);

第一个参数,shm_id 是由 shmget 函数返回的共享内存标识。
第二个参数,shm_addr 指定共享内存连接到当前进程中的地址位置,通常为空,表示让系统来选择共
享内存的地址。
第三个参数,shm_flg 是一组标志位,通常为 0。
调用成功时返回一个指向共享内存第一个字节的指针,如果调用失败返回-1

9.4.3 分离函数

该函数用于将共享内存从当前进程中分离。注意,将共享内存分离并不是删除它,只是使该共享内存对当前进程不再可用。

int shmdt(const void *shmaddr);

参数 shmaddr 是 shmat 函数返回的地址指针,调用成功时返回 0,失败时返回-1.

9.4.4 控制函数

与信号量的 semctl 函数一样,用来控制共享内存,它的原型如下:

int shmctl(int shm_id, int command, struct shmid_ds *buf);

第一个参数,shm_id 是 shmget 函数返回的共享内存标识符。
第二个参数,command 是要采取的操作,它可以取下面的三个值:
IPC_STAT:把 shmid_ds 结构中的数据设置为共享内存的当前关联值,即用共享内存的当前关联值覆盖 shmid_ds 的值。
IPC_SET:如果进程有足够的权限,就把共享内存的当前关联值设置为 shmid_ds 结构中给出的值
IPC_RMID:删除共享内存段
第三个参数,buf 是一个结构指针,它指向共享内存模式和访问权限的结构

shmid_ds 结构至少包括以下成员:
struct shmid_ds
{
uid_t shm_perm.uid;
uid_t shm_perm.gid;
mode_t shm_perm.mode;
};

9.4.5 案例

使用 shmget()函数创建一个共享内存区域,在这个共享内存区域中写入字符串”welcome to mrdoft“,然后在父子进程中分别读取共享内存中的数据,进而实现进程间的数据交换。

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
int main()
{int shmid;int proj_id;key_t key;int size;char *addr;pid_t pid;key = IPC_PRIVATE;shmid = shmget(key,1024,IPC_CREAT|0660);//创建共享内存,返回共享内存区域的标识符if(shmid == -1){perror("create share memory failed!");return 1;}
addr = (char *)shmat(shmid,NULL,0); //获得共享内存的地址
if(addr == (char *)(-1)){
printf("cannot attach %s\n",strerror(errno));
return 1;
}
printf("share memory segment's address:%p\n",addr);//打印共享内存地址
strcpy(addr,"welcome to mrsoft"); //复制字符串到共享内存
pid = fork(); //创建子进程
if(pid == -1){
perror("error");
return 1;
}
else if(pid == 0){
printf("child process string is' %s'\n",addr); //子进程读取共享内存的内容
_exit(0);
}
else{
wait(NULL);
printf("parent process string is '%s'\n",addr); //父进程读取共享内存的内容
if(shmdt(addr) == -1){ //分离共享内存区域
perror("release failed\n");
return 1;
}
if(shmctl(shmid,IPC_RMID,NULL) == -1){ //删除共享内存区域
perror("failed");
return 1;
}
}
}

http://www.ppmy.cn/embedded/116098.html

相关文章

基于物联网技术的智能运动检测仪设计(微信小程序)(230)

文章目录 一、前言1.1 项目介绍【1】开发背景【2】项目实现的功能【3】项目硬件模块组成1.2 设计思路【1】整体设计思路【2】整体构架1.3 项目开发背景【1】选题的意义【2】可行性分析【3】参考文献【4】摘要【5】项目背景1.4 开发工具的选择【1】设备端开发【2】微信小程序开发…

Oracle事物

在 Oracle 中&#xff0c;当你开启一个事务&#xff08;例如&#xff0c;通过执行 BEGIN 语句或直接执行 DML 语句如 INSERT 、 UPDATE 或 DELETE &#xff09;时&#xff0c;以下行为会发生&#xff1a; 1. **行级锁**&#xff1a;当你修改数据时&#xff08;例如&#xff0c…

Python基础学习(3)

目录 一&#xff0c;函数 1&#xff0c;函数的定义 2&#xff0c;函数的参数 1&#xff0c;默认值 2&#xff0c;传参 3&#xff0c;返回值 4&#xff0c;变量的作用域 5&#xff0c;函数的调用 二&#xff0c;常用数据结构 1&#xff0c;列表 列表的定义 列表的特性…

828华为云征文|华为云Flexus X实例docker部署最新Appsmith社区版,搭建自己的低代码平台

828华为云征文&#xff5c;华为云Flexus X实例docker部署最新Appsmith社区版&#xff0c;搭建自己的低代码平台 华为云最近正在举办828 B2B企业节&#xff0c;Flexus X实例的促销力度非常大&#xff0c;特别适合那些对算力性能有高要求的小伙伴。如果你有自建MySQL、Redis、Ng…

Blender软件三大渲染器Eevee、Cycles、Workbench对比解析

Blender 是一款强大的开源3D制作平台&#xff0c;提供了从建模、雕刻、动画到渲染、后期制作的一整套工具&#xff0c;广泛应用于电影、游戏、建筑、艺术等领域。 渲染101云渲染云渲6666 相比于其他平台&#xff0c;如 Autodesk Maya、3ds Max 或 Cinema 4D&#xff0c;Blende…

Ubuntu的基本用法与指令(为后面学习ROS打基础)

目录 0.声明&#xff1a;此博客的部分内容来自B站up主 机器人工匠阿杰&#xff0c;欢迎大家前往up主视频区学习&#xff08;本人正在跟随此up主的视频学习无人机的部分相关知识&#xff09; 1.win空格&#xff08;切换中英文&#xff09; 2.终端指令 1.ls&#xff1a;显示主…

RabbitMQ08_保证消息可靠性

保证消息可靠性 一、生产者可靠性1、生产者重连机制&#xff08;防止网络波动&#xff09;2、生产者确认机制Publisher Return 确认机制Publisher Confirm 确认机制 二、MQ 可靠性1、数据持久化交换机、队列持久化消息持久化 2、Lazy Queue 惰性队列 三、消费者可靠性1、消费者…

第二讲 数据结构

链表 单链表 单链表的用途在于编写领接表&#xff0c;领接表的用途在于存储图和树 826. 单链表 - Acwing题库 数据结构&#xff1a; e[N]&#xff1a;用于存储节点的值的数组。ne[N]&#xff1a;作为“下一个”指针的数组&#xff0c;用于连接节点。e[]和ne[]是通过下标关联…