Day33
IPC对象
共享内存、消息队列、信号量
为了多个进程能够在同一个IPC对象会合,引用了键,每个IPC对象都与一个键相关联,由内核维护,键作为该对象的外部名,键的类型为key_t,在<sys/types.h>中被定义为int
#include <sys/ipc.h>
key_t ftok(const char* pathname, int proj_id);
功能:合成键
参数: pathname 一个真实的路径名
proj_id 项目ID,通常用于区分不同的 IPC 对象,仅低8位有效,取0~255 之间的数
返回值:成功返回可用于创建IPC对象的键,失败返回-1
共享内存
两个或者更多的进程共享一块由系统内核维护的内存区域
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
功能:key 键
size 字节数,自动按页取整
shmflg 创建标志
0 获取,不存在即失败
IPC_CREAT 创建,不存在即创建,已存在即获取
IPC_EXCL 排它,不存在即创建,已存在即失败,要和IPC_CREAT一起按位或用实现功能
通过位或组合读写权限(0664之类的)
返回值:成功返回共享内存ID,失败返回-1
#include <sys/shm.h>
void* shmat(int shmid, void const* shmaddr, int shmflg);
功能:加载共享内存,将物理内存中的共享内存映射到进程用户空间的虚拟内存中
参数:shmid 共享内存的ID
shmaddr 映射到共享内存的虚拟内存起始地址,取NULL,由系统自动选择
shmflg 加载标志
- 以读写方式使用共享
SHM_RDONLY 以只读方式使用共享内存
返回值:成功返回共享内存的起始地址,失败返回-1
#include <sys/shm.h>
int shmdt(void const* shmaddr);
功能:卸载共享内存
参数:shmaddr 共享内存的起始地址
返回值:成功返回0,失败返回-1
⭐shmat函数会使共享内存的加载计数加一,shmdt则是减一
#include <sys/shm.h>
int shmctl(int shmid, IPC_RMID, NULL);
功能:销毁共享内存
参数:shmid 共享内存对象ID
返回值:成功返回0,失败返回-1
⭐销毁共享内存是做一个销毁标志,禁止任何进程对该共享内存形成新的加载,现有加载仍然保存,当加载计数降为0才会真的销毁
共享内存编程模型图
消息队列
消息队列是一个由内核维护的先进先出的消息链表队列,单个节点有四个部分组成:下条消息的指针、消息类型、数据长度、消息数据
读写数据就是增删节点,除了先进先出还可以按照消息类型进程读取
相比其他IPC机制,消息队列的优势:
流量控制:阻塞型,系统资源短缺时发送消息的进程会进入睡眠状态,条件满足后会继续发 送
面向记录:每一个消息都是完整的信息单元,而不是管道那种字节流
类型过滤:支持按类型提取消息
天然同步:空队列不可读,满队列不可写,不发则不收
系统限制
可发送消息字节数上限:8192
单条队列消息总字节数上限:16k
全系统总消息队列数上限:16
全系统消息总字节数上限:256k
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
功能:创建新的或获取已有的消息队列
参数:key 键
msgflg 创建标志
0 获取,不存在即失败
IPC_CREAT 创建,不存在即创建,已存在即获取
IPC_EXCL 排它,不存在即创建,已存在即失败,要和IPC_CREAT一起按位或用实现功能
通过位或组合读写权限(0664之类的)
返回值:成功返回消息队列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在消息达到上限时则不会阻塞,而是返回-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,取IPC_NOWAIT在没有消息时则不会阻塞,而是返回-1,errno为EAGAIN,有MSG_NOERROR时,类型匹配而消息数据太长则只截取前面msgsz位,其余丢失,如果不包含MSG_NOERROR则不处理该消息并直接返回-1,errno为E2BIG
msgtyp 消息类型
0 提取消息队列第一条消息
>0 若msgflg参数不包含MSG_EXCEPT位,则提取消息队列位第一条类型为msgtyp 的消息,若msgflg参数包含MSG_EXCEPT位,则提取消息队列位第一条类型 不为msgtyp的消息
<0 提取消息类型小于等于msgflg绝对值的消息,消息类型越小越优先被提取
返回值:成功返回实际接收到的消息数据字节数,失败返回-1
#include <sys/msg.h>
int msgctl(int msgid, IPC_RMID, NULL);
功能:销毁消息队列
参数:,msgid 消息队列ID
返回值:成功返回0是,失败返回-1
消息队列通信编程模型
IPC命令
查看系统中的IPC对象
ipcs -s 共享内存
ipcs -q 消息队列
ipcs -s 信号量集
ipcs -a 所有
删除系统中的IPC对象
ipcrm -m 删除共享内存
ipcrm -q 删除消息队列
ipcrm -s 删除信号量集