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

Linux16-进程间的通信--共享内存

12.4共享内存

共享内存是一种高效的进程间通信(IPC)机制,允许多个进程访问同一块物理内存区域,从而实现快速的数据共享。

核心特性

  • 高性能:进程直接读写内存,无需系统调用开销
  • 零拷贝:数据不需要在内核和用户空间之间复制

需要同步机制:多个进程同时访问时需要信号量等同步工具

  • 内核持久性:共享内存段独立于进程存在,除非显式删除

12.4.1共享内存相应函数

我们使用shmget函数来创建共享内存:

int shmget(key_t key,size_t,int shmflg);
  •  key :共享内存键值,可以使用 ftok() 生成或 IPC_PRIVATE 
  •  size :共享内存段大小(字节)
  •  shmflg :权限标志,如 IP  C_CREAT | 0666 

我们使用shmat函数映射到物理内存段:

void *shmat(int shmid,const void* shmaddr,int shmflg);
  • shmid 共享内存标识符
  • shmaddr:指定映射地址通常设为NULL
  • shmflg:访问模式如SHM)RDONLY只读 可为0
  • 返回值为指向共享内存的指针

我们使用shmdt函数来分离共享内存:

int shmdt(const void *shmaddr);
  • 返回值-1为分离失败

我们使用shmctl来控制共享内存:

int shmctl(int shmid,int cmd,struct shmid_ds *buf);
  • shmid 共享内存标识符

cmd:

  •  IPC_RMID :删除共享内存段
  •  IPC_STAT :获取状态信息
  •  IPC_SET :设置参数

 struct shmid_ds  是Linux内核中用于描述共享内存段状态的数据结构,定义在  <sys/shm.h>  头文件中。

struct shmid_ds {struct ipc_perm shm_perm; /* 操作权限结构 */int shm_segsz; /* 段大小(字节) */__kernel_time_t shm_atime; /* 最后附加时间 */__kernel_time_t shm_dtime; /* 最后分离时间 */__kernel_time_t shm_ctime; /* 最后修改时间 */__kernel_ipc_pid_t shm_cpid; /* 创建者进程ID */__kernel_ipc_pid_t shm_lpid; /* 最后操作进程ID */unsigned short shm_nattch; /* 当前附加计数 */unsigned short shm_unused; /* 兼容性填充 */void *shm_unused2; /* 保留字段 */void *shm_unused3; /* 保留字段 */};

1. 权限控制结构 - shm_perm

struct ipc_perm {key_t __key; /* 共享内存键值 */uid_t uid; /* 所有者有效用户ID */gid_t gid; /* 所有者有效组ID */uid_t cuid; /* 创建者有效用户ID */gid_t cgid; /* 创建者有效组ID */unsigned short mode; /* 权限模式 */unsigned short __seq; /* 序列号 */};

作用:控制对共享内存段的访问权限,类似于文件权限控制。

2. 大小信息 - shm_segsz

  • 类型: int 
  • 含义:共享内存段的大小,以字节为单位
  • 示例:如果创建时指定大小为1024字节,则 shm_segsz 值为1024

3. 时间戳信息

成员

类型

含义

 shm_atime 

 __kernel_time_t 

最后一个进程附加(attach)到该共享内存的时间

 shm_dtime 

 __kernel_time_t 

最后一个进程分离(detach)的时间

 shm_ctime 

 __kernel_time_t 

共享内存段最后修改(创建或权限变更)的时间

4. 进程标识信息

成员

类型

含义

 shm_cpid 

 __kernel_ipc_pid_t 

创建该共享内存段的进程ID

 shm_lpid 

 __kernel_ipc_pid_t 

最后对该共享内存执行操作的进程ID

 shm_nattch 

 unsigned short 

当前附加到该共享内存段的进程数量

12.4.2共享内存示例

生产者a.c代码:

#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/shm.h>#include "sem.h"int main(){int shmid = shmget((key_t)1234, 128, IPC_CREAT | 0600);if (shmid == -1){exit(1);}char *s = shmat(shmid, NULL, 0);if (s == (char *)-1){exit(1);}while (1){printf("input: ");fgets(s, 127, stdin);if (strncmp(s, "end", 3) == 0){break;}}shmdt(s);}

消费者b.c代码:

#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/shm.h>#include "sem.h"int main(){int shmid = shmget((key_t)1234, 128, IPC_CREAT | 0600);if (shmid == -1){exit(1);}char *s = shmat(shmid, NULL, 0);if (s == (char *)-1){exit(1);}while (1){if (strncmp(s, "end", 3) == 0)break;printf("read: %s", s);sleep(1);}shmdt(s);shmctl(shmid, IPC_RMID, NULL);}

运行结果:

由运行结果可以发现当生产者不去改变映射段内容时,消费者仍在打印上次输入的内容,那么如何实现a输入一次,b打印一次呢,我们就要引入上此学习到的信号量。

a.c代码如下:

#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/shm.h>#include "sem.h"int main(){sem_init();int shmid = shmget((key_t)1234, 128, IPC_CREAT | 0600);if (shmid == -1){exit(1);}char *s = shmat(shmid, NULL, 0);if (s == (char *)-1){exit(1);}while (1){sem_p(0);printf("input: ");fgets(s, 127, stdin);if (strncmp(s, "end", 3) == 0){sem_v(1);break;}sem_v(1);}shmdt(s);}

b.c代码如下:

#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/shm.h>#include "sem.h"int main(){sem_init();int shmid = shmget((key_t)1234, 128, IPC_CREAT | 0600);if (shmid == -1){exit(1);}char *s = shmat(shmid, NULL, 0);if (s == (char *)-1){exit(1);}while (1){sem_p(1);if (strncmp(s, "end", 3) == 0)break;printf("read: %s", s);sleep(1);sem_v(0);}shmdt(s);sem_destroy();shmctl(shmid, IPC_RMID, NULL);}

运行结果:

可知实现a输入一次,b打印一次。

12.4.3总结

1. 同步机制必须

共享内存不提供进程间同步,需要配合其他机制:

// 通常需要信号量来同步访问#include <semaphore.h>sem_t *sem = sem_open("/mysem", O_CREAT, 0644, 1);// 写入前加锁sem_wait(sem);strcpy(shm_ptr, data);sem_post(sem);

2. 内存对齐和字节序

不同架构的机器可能有不同的字节序,需要处理兼容性。

3. 资源管理

  • 及时调用 shmdt() 分离内存
  • 使用 shmctl(IPC_RMID) 删除不再使用的共享内存
  • 避免内存泄漏

4. 系统限制

检查系统共享内存限制:

bash# 查看系统IPC限制ipcs -l# 查看当前共享内存段ipcs -m

共享内存架构类型

UMA(统一内存访问)

所有处理器共享一个统一的物理内存,每个处理器都可以均匀地访问内存中的任何数据。

NUMA(非统一内存访问)

内存被划分为多个节点,每个节点有一个本地内存。处理器可以快速访问本地内存中的数据,但访问远程内存时会有延迟。

共享内存是Linux进程间通信的最高效机制,核心要点包括:

  1. 高性能优势:直接内存访问,零拷贝设计
  1. 使用步骤:创建( shmget ) → 连接( shmat ) → 使用 → 分离( shmdt ) → 控制( shmctl )
  1. 同步必要性:必须配合信号量等同步机制防止数据竞争
  1. 资源管理:及时分离和删除,避免资源泄漏
  1. 架构选择:根据性能需求选择UMA或NUMA架构

掌握共享内存的使用对于开发高性能的多进程应用程序至关重要,特别是在需要处理大数据量或对性能要求极高的场景中。

http://www.dtcms.com/a/526575.html

相关文章:

  • 长沙企业网站建设分公司wordpress 调用全文
  • vs做网站示例中国室内设计网站有哪些
  • 男女做那个是的视频网站海曙网站设计建设
  • 装饰网站建设运营网页设计特效网站
  • 企业网站设计制作收费wordpress找人
  • 广东省建设厅的注册中心网站首页制作公司网站源代码怎么弄
  • 网站建设职员长沙设计网站多少钱
  • 佛山深圳建网站旅游网站的规划与建设开题报告
  • 淄博企业网站建设公司太原网站运营优化
  • 欧米茄官方手表价格湛江seo排名外包
  • 做网站都要买服务器吗京东物流网站建设策划书
  • 舆情分析报告seo 网站关键词
  • 自己做网站要会什么软件北京海淀公司注册
  • 南通网站建设制作中建建筑网站
  • 连云港建网站苏州市建设局招标网站首页
  • 做外贸的如何上国外网站旅游网站开发意义
  • asp做网站步骤建网站有什么好处
  • 加速进化发布Booster K1,打造AI时代的苹果公司
  • 北京南站属于哪个街道用dreammwea怎么做视频网站
  • 制作网站哪家强平面设计正规培训机构
  • 做旅游网站运营制作h5用什么软件比较好
  • 织梦网站程序下载ppt做杂志模板下载网站
  • 自己做视频网站收益怎么来本地建站工具
  • 南京做网站软件wordpress 优秀博客
  • 门户网站的发展趋势长沙房产交易中心官网
  • 电商网站模板引擎大于二高端网站建设
  • 网站建设文案策划上海网站建设报价表
  • 如何把网站能搜到南京环力建设有限公司网站
  • 门户网站营销公司管理网站首页
  • 建设银行开通网站查询密码开发区网站建设工作管理办法