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

六十天Linux从0到项目搭建(第二十四天)(共享内存)

1 共享内存的管理机制详解

共享内存是最高效的进程间通信(IPC)方式之一,操作系统需要完善地管理系统中的所有共享内存资源。以下是共享内存的管理机制:

1. 共享内存的系统级管理

核心问题:系统需要同时管理多个共享内存段

解决方案

  • **"先描述,再组织"**的经典OS设计模式

  • 为每个共享内存段创建内核数据结构

  • 所有共享内存结构体被组织起来统一管理

2. 共享内存的内核数据结构(伪代码)

struct shmid_ds {
    struct ipc_perm shm_perm;  // 权限信息
    size_t shm_segsz;         // 共享内存大小
    time_t shm_atime;         // 最后attach时间
    time_t shm_dtime;         // 最后detach时间
    time_t shm_ctime;         // 最后change时间
    pid_t shm_cpid;          // 创建者PID
    pid_t shm_lpid;          // 最后操作PID
    unsigned short shm_nattch; // 当前attach的进程数
    // 指向实际物理内存的指针
    void *shm_internal;      
};

3. 共享内存的完整构成

共享内存 = 内核数据结构(struct shmid_ds) + 实际内存空间

4. 共享内存的生命周期管理

创建/获取共享内存

int shmget(key_t key, size_t size, int shmflg);
  • key:使用ftok()生成的唯一键值

  • size:共享内存大小

  • shmflg:权限标志(如IPC_CREAT)

生成key的方法

key_t ftok(const char *pathname, int proj_id);
  • pathname:存在的文件路径

  • proj_id:项目ID(1个字节,0-255)

附加/分离共享内存

void *shmat(int shmid, const void *shmaddr, int shmflg);
int shmdt(const void *shmaddr);

5. 系统如何管理多个共享内存

  1. 全局共享内存表:内核维护一个所有共享内存段的表

  2. 唯一标识:每个共享内存段有唯一的shmid

  3. 引用计数:跟踪有多少进程附加到该内存

  4. 生命周期

    • 显式删除:shmctl(shmid, IPC_RMID, NULL)

    • 当最后一个进程分离且显式标记删除时,内存才真正释放

6. 多进程使用共享内存的要点

  1. 不是只能一对进程使用:多个进程可以同时附加到同一共享内存

  2. 并发访问控制:需要额外同步机制(如信号量)保证数据一致性

  3. 系统限制:通过ipcs -l可查看系统允许的共享内存总量

示例:创建和使用共享内存

// 生成key
key_t key = ftok("/tmp/mem.key", 'A');

// 创建共享内存(1KB)
int shmid = shmget(key, 1024, IPC_CREAT | 0666);

// 附加到进程地址空间
char *shm_ptr = (char *)shmat(shmid, NULL, 0);

// 使用共享内存
strcpy(shm_ptr, "Hello Shared Memory!");

// 分离共享内存
shmdt(shm_ptr);

// 删除共享内存(通常由一个进程负责)
shmctl(shmid, IPC_RMID, NULL);

操作系统通过这种精细的管理机制,使得共享内存既高效又安全地被多个进程使用。

2 共享内存的生命周期与管理机制

1. Key与shmid的关系

Key

  • 内核中使用的标识符,由ftok()生成

  • 用于创建/获取共享内存时的"匹配键"

  • 类比:类似于文件的inode编号,是系统级的唯一标识

shmid

  • 共享内存段的实际句柄

  • shmget()返回,用于后续操作(shmat/shmdt等)

  • 类比:类似于文件描述符(fd),是进程级的操作句柄

2. 共享内存的生命周期特性

关键特性

  • 不随进程终止而释放:即使创建进程退出,共享内存依然存在

  • 随操作系统持续存在:直到显式删除或系统重启

  • 引用计数机制:通过shm_nattch记录当前附加的进程数

现象解释

  • 创建进程退出后共享内存仍然存在,这是设计使然

  • 允许多个无关进程在不同时间访问同一共享内存

3. 共享内存的管理方式

(1) 使用指令删除

ipcs -m              # 查看所有共享内存
ipcrm -m <shmid>     # 删除指定共享内存
ipcrm -M <key>       # 通过key删除共享内存

(2) 系统调用删除

#include <sys/shm.h>
shmctl(shmid, IPC_RMID, NULL);  // 标记删除共享内存

删除的实际行为

  1. 立即将共享内存标记为"待销毁"

  2. 当最后一个使用它的进程调用shmdt()分离后,内存才真正释放

  3. 新的shmget()调用将无法获取该共享内存

4. 生命周期管理的最佳实践

创建策略

// 推荐方式:确保创建全新的共享内存
shmid = shmget(key, size, IPC_CREAT | IPC_EXCL | 0666);
if(shmid == -1 && errno == EEXIST) {
    // 已存在则获取现有ID
    shmid = shmget(key, size, 0666);
}

删除策略

  1. 设计一个"清理进程"负责最终删除

  2. 或者使用atexit()注册退出时的清理函数

  3. 重要数据应配合信号量等同步机制

5. 内核实现原理

数据结构关系

用户层          内核层
shmid  ----> struct shmid_ds ---> 实际物理内存
                ↑
全局shm_table链表节点

生命周期控制

  • 创建:分配struct shmid_ds并加入全局链表

  • 使用:通过shmid找到对应结构体

  • 删除:从链表移除并标记,引用计数为0时释放内存

6. 与文件系统的对比

特性共享内存文件系统
标识符key/shmidinode/fd
生命周期显式删除或系统重启文件被unlink且无打开
访问方式直接内存访问read/write系统调用
同步需求必须额外同步部分由内核保证

共享内存的这种设计使其成为最高效但也最需要谨慎管理的IPC方式,开发人员必须明确管理其生命周期,避免造成内存泄漏。

相关文章:

  • 鸿蒙开发03样式相关介绍(二)
  • 《MOSFET:静电场中的无声刺客》
  • DirectX安装步骤(包含安装包)DirectX详细图文安装教程
  • LangChain 安装与环境搭建,并调用OpenAI与Ollama本地大模型
  • 31天Python入门——第17天:初识面向对象
  • Android设计模式之责任链模式
  • 小程序:富文本的处理
  • C 语言基础知识
  • windows与ubuntu双硬盘双系统安装及启动(全流程成功)
  • Linux中输入输出管理技巧
  • jmeter线程组高并发(详细讲解)
  • 微信小程序实现动态二维码海报生成与保存 | 高效便捷的前端方案
  • UE5学习笔记 FPS游戏制作33 游戏保存
  • 数据库中的函数:高效操作与灵活运用
  • nut-collapse折叠面板(案例)
  • OSPF协议(数据包刨析)
  • NLP高频面试题(二十七)——SFT有哪几种参数微调方法?有什么优缺点?
  • 开源守护,智护童年——幼儿园未成年行为与安全智能监控系统
  • 贪心算法(14)(java)无重叠区间
  • SSL提供了哪些安全服务
  • 电子书推送网站怎么做/微信引流的十个方法
  • 免费的网站app软件/备案查询网
  • 网络公司专业做网站/获客软件
  • 广西网站建设公司电话/互联网营销推广
  • 临沂网站制作平台/百度代理合作平台
  • 网站制作费可以做业务宣传费/建站软件