day29 消息队列
概念
将信息打包成结点储存在内核缓存区中,进程通过访问内核实现通信
特点
数据打包成节点(数据类型,数据文本)
满足队列的思想(先进先出)
在读取后,数据会被删除
消息队列是全双工通信机制
消息队列不随着进程结束而结束,需要手动删除或重启
消息队列的函数
ftok
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
功能:把pathname 和proj_id转换为秘钥的
参数: const char *pathname:路径以及文件名 (随便但是需要存在)
int proj_id:可以写整数,字符(随便)
返回值: 成功返回秘钥,失败返回-1,跟新errno,注意秘钥和stat有关 key=proj_id(低8位)+设备号(低8位)+inode(低16位)
key=ftok(路径,随意写)
msgget
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
功能:创建消息队列
参数:key_t key 密钥,ftok申请
int msgflg: IPC_CREAT|0664:如果消息队列不存在则创建,如果存在忽略
IPC_CREAT| IPC_EXCL | 0664:如果消息队列不存在则创建,如果存在报错EEXIST. 最后几位表示权限,所以实际使用是需要根权限的
返回值: 成功返回消息队列id,失败返回-1,更新新errno
msqid=msgget(密钥,选择)
msgsnd
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
功能:发送信息
参数:
int msqid 消息队列id const void *msgp 消息包 size_t msgsz 消息包内容大小 int msgflg 是否阻塞 0阻塞
IPC_NOWAIT:非阻塞函数报错EAGAIN
返回值:成功返回0,失败返回-1,更新errno
msgrcv
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
功能:接收信息
参数:
int msqid 消息队列id const void *msgp 消息包 size_t msgsz 消息包内容大小 long msgtyp =0 第一条消息 >0 读取类型等于msgtyp的第一条信息
<0:读取小于等于msgtype绝对值的第一条信息
int msgflg 是否阻塞 0阻塞
IPC_NOWAIT:非阻塞函数报错EAGAIN
返回值:成功返回成功读取的字节个数,失败返回-1,更新errno
msgctl
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
功能:消息队列控制(删除,获取,修改信息)
参数:
int msqid | 消息队列id |
int cmd | 操作指令 IPC_STAT:获取消息队列内核数据的 IPC_SET:修改消息队列数据 IPC_RMID:删除消息队列 ,第三个可以被忽略 |
struct msqid_ds *buf | 该指针存储获取以及修改对应内核的数据 |
返回值:成功返回0,失败返回-1
队列属性
struct msqid_ds {struct ipc_perm msg_perm; /* 拥有者和权限 */time_t msg_stime; /* 最新一次向消息队列中发送数据的时间 */time_t msg_rtime; /* 最新一次消息队列接受数据的时间 */time_t msg_ctime; /* 最新一次操作消息队列的时间 */unsigned long __msg_cbytes; /* 当前队列中已用的字节数 */msgqnum_t msg_qnum; /* 当前队列中消息的个数*/msglen_t msg_qbytes; /* 队列的最大容量,默认是16K */pid_t msg_lspid; /* 最后一次向消息队列中发送消息的进程id号 */pid_t msg_lrpid; /* 最后一次从消息队列中取消息的进程id号 */};
对第一个成员的介绍
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; /* 队列号 */};
速记
函数 | 功能 | 用法 | 参数 | 返回值 |
ftok | 密钥生成 | key=ftok(路径,任意数字/字符) | const char *pathname int proj_id | 成功返回密钥,失败返回-1,更新errno |
msgget | 消息队列创建 | msgid=msgget(密钥,选项| 权限) | 选项 IPC_CREAT|0664 创建,存在忽略 IPC_CREAT| IPC_EXCL | 0664 创建,存在报错 | 成功返回队列id,失败返回-1,更新errno |
msgsnd | 发送消息 | msgsnd(队列id,消息包,消息包内容大小,阻塞选项) | 阻塞选项 满了时 0为阻塞 IPC_NOWAIT为非阻塞 直接报错 EAGAIN | 成功为0,失败为-1,更新errno |
msgrcv | 接收消息 | msgrcv(队列id,消息包,消息包内容大小,消息类型,阻塞选项) | 消息类型 >0 该类型消息的第一个消息 =0 无所谓类型 队列第一个 <0 绝对值类型中最小的那一个 | 成功返回读取的字节数,失败为-1,更新errno |
msgctl | 消息控制 | msgctl(队列id,控制选项,接收容器) | 控制选项 IPC_STAT 获取队列数据 IPC_SET 修改队列数据 IPC_RMID 删除消息队列 ,第三个可以被忽略 | 成功返回0,失败返回-1,更新errno |