随笔小屋 Logo
首页
瞬间
反馈
随笔小屋 Logo
首页 瞬间 反馈
  1. 首页
  2. linux
  3. ipc

ipc

  • linux
  • 发布于 2025-10-14
  • 385 次阅读
flor
flor

合成键

#include <sys/ipc.h>
key_t ftok(const char* pathname, int proj_id);
功能:用于合成一个键
参数:pathname  一个真实存在的路径名
      proj_id  项目ID,仅低8位有效,取0到255之间的数
返回值:创建或获取IPC对象的键,失败返回-1

ftok函数用pathname参数调用stat函数,将其输出的stat结构体中的st_dev(设备ID)和st_ino(i节点号)成员与proj_id参数组合来生成键

参与生成键的是设备ID和节点号,而不是pathname参数字符串本身

设备ID和i节点号都至少是整型字长的数据,而键也是整型字长,再加上一个字节项目ID,在合成键的过程中难免会丢失一部分信息。因此有时候明明提供的是不同的路径,该函数返回的键却是一样的

共享内存

#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
功能:创建新的或获取已有的共享内存
参数:key  键
size  字节数,自动按页取整
shmflg:创建标志
        0          获取,不存在即失败
        IPC_CREAT  创建,不存在即创建,已存在即获取
        IPC_EXCL   排它,不存在即创建,已存在即失败
返回值:成功返回共享内存的ID,失败返回-1
#include <sys/shm.h>
void* shmat(int shmid, void const* shmaddr, int shmflg);
功能:加载共享内存,将物理内存中的共享区域映射到进程用户空间的虚拟内存中
参数:shmid 共享内存的ID
shmaddr 映射到共享内存的虚拟内存起始地址,取NULL由系统自动选择
shmflg:加载标志
         0           以读写方式使用共享
         SHM_RDONLY  以只读方式使用共享内存
返回值:成功返回共享内存的起始地址,失败返回(void*)-1
shmat函数每建立一个映射,系统内核中共享内存对象的加载计数加1
#include <sys/shm.h>
int shmdt(void const* shmaddr);
功能:卸载共享内存
参数:shmaddr 共享内存的起始地址
返回值:成功返回0,失败返回-1
shmdt函数卸载后系统内核中共享内存对象的加载计数减1
#include <sys/shm.h>
int shmctl(int shmid, IPC_RMID, NULL);
功能:销毁共享内存
参数:shmid  共享内存对象ID
返回值:成功返回0,失败返回-1
销毁共享内存。内核会做一个销毁标记,禁止形成新的加载,但保留已有加载。只有当其使用者们纷纷卸载,加载计数降为0时,共享内存才会真的被销毁
步骤 进程A 函数 进程B 步骤
1 创建共享内存 shmget 获取共享内存 1
2 加载共享内存 shmat 加载共享内存 2
3 使用共享内存 strcpy / printf / ... 使用共享内存 3
4 卸载共享内存 shmdt 卸载共享内存 4
5 销毁共享内存 shmctl — —

共享内存的地址空间通常被映射到堆和栈之间,速度快但缺乏足够的同步机制

消息队列

#include <sys/msg.h>
int msgget(key_t key, int msgflg);
功能:创建新的或获取已有的消息队列
参数:key  键
msgflg:创建标志
        0          获取,不存在即失败
        IPC_CREAT  创建,不存在即创建,已存在即获取
        IPC_EXCL   排它,不存在即创建,已存在即失败
返回值:成功返回消息队列的ID,失败返回-1
#include <sys/msg.h>
int msgsnd(int msgid, void const* msgp, size_t msgsz, int msgflg);
功能:发送消息
参数:msgid 消息队列的ID。
msgp: 指向一个包含消息类型和消息数据的结构体。该内存块的前4个字节必须是一个大于0的整数,代表消息类型,其后紧跟消息数据
msgsz: 期望发送消息数据(不含消息类型)的字节数
msgflg: 发送标志,一般取0即可
        IPC_NOWAIT  当消息达到上限时msgsnd不会阻塞等待,而是返回-1,同时errno为EAGAIN
返回值:成功返回0,失败返回-1
#include <sys/msg.h>
int msgrcv(int msgid, void* msgp, size_t msgsz, long msgtyp, int msgflg);
功能:接收消息
参数:msgid  消息队列的ID
msgp:指向一个结构体包含消息类型(4字节)和消息数据的内存
msgsz:期望接收消息数据(不含消息类型)的字节数
msgflg:接收标志,一般取0即可
msgtyp:消息类型
        0   提取消息队列的第一条消息
        >0  当 msgflg 参数不包含 MSG_EXCEPT 位,则提取消息队列的第一条类型为 msgtyp 的消息;若包含,则提取消息队列的第一条类型不为 msgtyp 的消息
        <0  提取消息队列中类型小于等于 msgtyp 绝对值的消息,类型越小的优先级越高
msgflg:接收标志,一般取 0 即可
        IPC_NOWAIT  没有可接收消息时msgrcv不会阻塞等待,而是返回-1(errno=ENOMSG)
        MSG_EXCEPT 跳过消息类型
        MSG_NOERROR  默认接收消息数据大于msgsz,函数失败返回-1(errno=E2BIG),包含后舍弃大于msgsz的字节数
返回值:成功返回实际接收到的消息数据字节数,失败返回 -1
#include <sys/msg.h>
int msgctl(int msgid, IPC_RMID, NULL);
功能:销毁消息队列
参数:msgid  消息队列的ID
返回值:成功返回0,失败返回-1
步骤 进程A 函数 进程B 步骤
1 创建消息队列 msgget 获取消息队列 1
2 发送接收消息 msgsnd / msgrcv 发送接收消息 2
3 销毁消息队列 msgctl — —

可发送消息字节数上限:8192
单条队列消息总字节数上限:16384 (16K)
全系统总消息队列数上限:16
全系统消息总字节数上限:262144 (256K = 16 x 16K)

查看系统中的IPC对象
ipcs -m (memory, 共享内存)
ipcs -q (message queue, 消息队列)
ipcs -s (semphore, 信号量集)
ipcs -a (all, 所有的)
删除系统中的IPC对象
ipcrm -m 删除共享内存
ipcrm -q 删除消息队列
ipcrm -s 删除信号量集

湘ICP备2025147565号-1
gongan beian 湘公网安备43102602000213号
CPU --% | 内存 0.00G/0.00G (0%) | 网络 无活动网卡
服务器资源占用 更新时间 --:--:--