5.3 Linux 应用开发 进程(三)

一、共享内存(Shared Memory)

共享内存是最快的 IPC 方式,它将一段物理内存区域映射到不同进程的虚拟地址空间,让多个进程直接通过指针读写内存,无需数据拷贝。

1. 内存映射(mmap)

直接将文件或设备映射到进程虚拟内存中,实现进程间通信。

函数:

void *mmap(void *addr, size_t length, int port, int flags, int fd, off_t offset);

// 参数详解:
// addr:指定映射地址;通常填 NULL,由系统自动选择。
// length:映射字节数(必须 > 0),从 offset 开始计算。
// port(访问权限):
//    PROT_READ:可读
//    PROT_WRITE:可写
//    PROT_EXEC:可执行
//    PROT_NONE:不可访问
// flags(标志位):
//    MAP_SHARED:共享映射,数据会同步到文件,其他进程可见。
//    MAP_PRIVATE:私有映射,写时复制,修改不影响原文件。
//    MAP_ANONYMOUS:匿名映射,仅用于亲缘进程通信,不需要文件支持。
// fd:文件描述符;匿名映射填 -1。
// offset:文件偏移量,必须页对齐,通常为 0。
// 返回值:成功返回映射区地址;失败返回 MAP_FAILED。

解除映射:

int munmap(void *addr, size_t length); // 成功返回0,失败返回-1

2. 系统 V 共享内存(shm)

通过内核对象管理的共享内存段,支持非亲缘进程通信。

使用步骤:

  • 步骤 1:生成 Key(ftok):将文件路径和项目 ID 转换为 System V IPC Key。
key_t ftok(const char *path, int proj_id);

// path:可访问的文件路径。
// proj_id:项目 ID(0~255)。
// 作用:生成唯一的 Key,用于关联共享内存段。
  • 步骤 2:创建 / 打开共享内存(shmget)
int shmget(key_t key, int size, int shmflag);

// 参数:
//   key:由 ftok 生成,或 IPC_PRIVATE(仅用于亲缘进程)。
//   size:共享内存大小(字节),创建时指定,读取时填 0。
//   shmflag:权限标志
//      IPC_CREAT:创建,如果不存在。
//      IPC_EXCL:与IPC_CREAT连用,若已存在则报错。
//      权限掩码:如 0666。
//返回值:成功返回共享内存标识符(shmid);失败返回 -1。
  • 步骤 3:映射到用户空间(shmat):将内核中的共享内存段映射到进程虚拟地址空间。
void *shmat(int shmid, const void *shmaddr, int shmflag);

// 参数:
//   shmid:shmget 返回的标识符。
//   shmaddr:指定映射地址;填 NULL 由系统自动分配。
//   shmflag:权限
//      0:可读可写
//      SHM_RDONLY:只读
// 返回值:成功返回映射后的地址;失败返回 (void *)-1。
  • 步骤 4:解除映射(shmdt):断开进程与共享内存的关联(不会删除内核对象)。
int shmdt(void *shmaddr); // 成功返回0,失败返回-1
  • 步骤 5:删除共享内存对象(shmctl):从内核中删除共享内存段(当所有进程解除映射后才生效)。
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

// 参数:
//   shmid:共享内存标识符。
//   cmd:控制命令
//     IPC_RMID:标记删除共享内存段(最常用)。
//   buf:设置 / 获取信息;删除时填 NULL。
// 返回值:成功返回 0;失败返回 -1。

二、消息队列(Message Queue)

消息队列是内核维护的链式队列,通过 msqid_ds 结构体管理,包含 msg_first(指向第一个消息)和 msg_last(指向最后一个消息)。每个消息包含 4 个部分:next(链表指针)、type(消息类型)、length(长度)、data(数据)。

特性:消息被读取后会从队列中移除,支持按类型选择性读取,可用于非亲缘进程通信。

1. 核心函数详解:

(1) 打开 / 创建消息队列 msgget()

int msgget(key_t key, int flag);

// 参数说明:
//   key:由 ftok() 生成的 IPC 键值,用于唯一标识消息队列
//   flag:权限标志,常用 IPC_CREAT | 0666(有则打开,无则创

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

C++/嵌入式开发 秋招面经 文章被收录于专栏

一名985硕,在25年秋招中斩获多个C++/嵌入式开发Offer。本专栏将分享我的面经,涵盖C/C++、操作系统、计算机网络、ARM体系与架构、Linux应用/驱动开发、Qt、通信协议及开发工具链等核心内容。

全部评论

相关推荐

评论
2
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务