9:消息队列
9.1 ipc结构
struct ipc_perm
{
uid_t uid;
gid_t gid;
uid_t cuid;
gid_t cgid;
mode_t mode;
unsigned short seq;
key_t key;
}
9.2 消息队列结构
struct msqid_ds
{
struct ipc_perm msg_perm; 消息队列的访问权限
struct msg * msg_first; 第一个消息的指针
struct msg * msg_last; 最后一个消息的指针
msgqnum_t msg_qnum; 队列当前的消息个数
unsigned short msg_cbytes; 队列的消息字节数
msglen_t msg_qbytes; 队列可容纳的字节数
pid_t msg_lspid; 最后发送消息的进程号
pid_t msg_lrpid; 最后接收消息的进程号
time_t msg_stime; 最后发送消息的时间
time_t msg_rtime; 最后接收消息的时间
time_t msg_ctime; 最近修改消息队列的时间
};
msg 结构体的定义
struct msg
{
struct msg * msg_next; 指向队列中的下一条消息
long msg_type; 本条消息的类型
short msg_ts; 本条消息的长度
short msg_sport; 本条消息的数据地址
}
9.3 消息结构
struct msgbuf
{
long mtype; 消息类型
char mtext[1]; 消息数据(此处只是用char来举例)
}
9.4 消息队列的创建
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget (key_t key, int msgflg);
msgfla低9位指定访问权限,高9位指定消息队列的创建方式:
IPC_CREAT 创建消息队列,若果存在就打开消息队列
IPC_EXCL 与IPC_CREAT同用,创建一个不存在的消息队列
调用成功返回消息队列的标识符,否则-1.
例1:创建关键字为0x1234,访问权限为0666的消息队列
如果存在返回标识号
int msgid;
msgid = msgget(0x1234, 0666|IPC_CREAT);
例2:创建关键字为0x1234,访问权限为0666的消息队列
如果存在则报错
int msgid;
msgid = msgget(0x1234, 0666|IPC_CREAT|IPC_EXCL);
9.5 消息队列放送
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgsnd(int msgid,void *msgp,int msgsz,int msgflg);
msgsnd向消息队列msgid发送一条消息:
msgid指定了发送消息队列的标识号
msgp指向存储待发送消息内容的地址,
msgsz指定消息数据的长度(不包含消息类型的长度)
msgflg控制消息发送的方式,如果设置了IPC_NOWAIT采用非阻塞
9.6 消息队列发送模型
以阻塞方式向消息队列(关键字)为KEY中写入字符串"Hello UNIX!"
消息类型为TYPE:
1.定义消息结构
struct msgbuf
{
long mtype
char ctext[100];
};
2.打开(创建)消息队列
int msgid;
msgid = msgget(KEY, 0666|IPC_CREAT);
if(msgid < 0) 打开(创建消息)失败
3.组装消息
设置消息类型和拷贝消息数据
struct msgbuf buf;
buf.mtype = 100;
strcpy(buf.ctext, "Hello UNIX!");
4.发送消息
int ret;
ret = msgsnd(msgid, &buf, strlen(buf.ctext),0);
5.发送判断
if (ret == -1)
{
if(errno == EINTR)
信号中断,重新发送
else 系统错误
}
9.7 消息队列接收函数
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgrcv(int msgid,void *msgp,int msgsz,long msgtyp,int msgflg);
msgrcv从消息队列msgid中读取一条消息:
msgid指定了接收消息队列的标识号
msgp指向存接收消息内容的地址,
msgsz指定该缓冲区的最大容量(包含消息类型的长度)
msgtyp指定读取消息的类型:
0 读取队列中的第一个消息
正整数 读取队列中第一个类型为msgtyp的消息
负整数 读取队列中第一个类型小于或等于msgtyp的绝对值的消息
msgflg控制消息接收的方式:
IPC_NOWAIT 非阻塞方式读取消息
MSG_NOERROR 截断读取消息
调用成功返回接收到的字节数否则-1,并根据以下情况设置errno的值:
1.消息放送中队列被系统删除,返回-1,errno = EIDRM
2.如果msgflg设置了IPC_NOWAIT,当队列没有该消息时返回-1,errno=EAGAIN
3.如果msgflg没有设置IPC_NOWAIT当队列没有该消息时,一直等待
9.8 消息队列接收模型
以阻塞方式从消息队列(关键字为KEY)中接收一条消息
消息类型为TYPE:
1.定义消息结构
与发送消息中的结构相一致
2.打开(创建)消息队列
int msgid;
msgid = msgget(KEY, 0666|IPC_CREAT);
3.准备接收缓冲区
struct msgbuf buf;
memset(buf,0,sizeof(buf));
4.接收消息
int ret;
ret = msgrcv(msgid, &msg, sizeof(msg.ctext),TYPE,0);
5.接收判断
if (ret == -1)
{
if (errno == EINTR)
信号中断,重新接收
else 系统错误
}
9.9 消息队列的控制
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgctl(int msgid,int cmd,struct msgid_ds *buf);
cmd取值:
IPC_CMID: 删除消息队列msqid
IPC_STAT: 读取消息队列数据结构到buf
IPC_SET: 设置消息队列结构msgid_ds的成员
调用成功返回0,否则-1
9.1 ipc结构
struct ipc_perm
{
uid_t uid;
gid_t gid;
uid_t cuid;
gid_t cgid;
mode_t mode;
unsigned short seq;
key_t key;
}
9.2 消息队列结构
struct msqid_ds
{
struct ipc_perm msg_perm; 消息队列的访问权限
struct msg * msg_first; 第一个消息的指针
struct msg * msg_last; 最后一个消息的指针
msgqnum_t msg_qnum; 队列当前的消息个数
unsigned short msg_cbytes; 队列的消息字节数
msglen_t msg_qbytes; 队列可容纳的字节数
pid_t msg_lspid; 最后发送消息的进程号
pid_t msg_lrpid; 最后接收消息的进程号
time_t msg_stime; 最后发送消息的时间
time_t msg_rtime; 最后接收消息的时间
time_t msg_ctime; 最近修改消息队列的时间
};
msg 结构体的定义
struct msg
{
struct msg * msg_next; 指向队列中的下一条消息
long msg_type; 本条消息的类型
short msg_ts; 本条消息的长度
short msg_sport; 本条消息的数据地址
}
9.3 消息结构
struct msgbuf
{
long mtype; 消息类型
char mtext[1]; 消息数据(此处只是用char来举例)
}
9.4 消息队列的创建
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget (key_t key, int msgflg);
msgfla低9位指定访问权限,高9位指定消息队列的创建方式:
IPC_CREAT 创建消息队列,若果存在就打开消息队列
IPC_EXCL 与IPC_CREAT同用,创建一个不存在的消息队列
调用成功返回消息队列的标识符,否则-1.
例1:创建关键字为0x1234,访问权限为0666的消息队列
如果存在返回标识号
int msgid;
msgid = msgget(0x1234, 0666|IPC_CREAT);
例2:创建关键字为0x1234,访问权限为0666的消息队列
如果存在则报错
int msgid;
msgid = msgget(0x1234, 0666|IPC_CREAT|IPC_EXCL);
9.5 消息队列放送
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgsnd(int msgid,void *msgp,int msgsz,int msgflg);
msgsnd向消息队列msgid发送一条消息:
msgid指定了发送消息队列的标识号
msgp指向存储待发送消息内容的地址,
msgsz指定消息数据的长度(不包含消息类型的长度)
msgflg控制消息发送的方式,如果设置了IPC_NOWAIT采用非阻塞
9.6 消息队列发送模型
以阻塞方式向消息队列(关键字)为KEY中写入字符串"Hello UNIX!"
消息类型为TYPE:
1.定义消息结构
struct msgbuf
{
long mtype
char ctext[100];
};
2.打开(创建)消息队列
int msgid;
msgid = msgget(KEY, 0666|IPC_CREAT);
if(msgid < 0) 打开(创建消息)失败
3.组装消息
设置消息类型和拷贝消息数据
struct msgbuf buf;
buf.mtype = 100;
strcpy(buf.ctext, "Hello UNIX!");
4.发送消息
int ret;
ret = msgsnd(msgid, &buf, strlen(buf.ctext),0);
5.发送判断
if (ret == -1)
{
if(errno == EINTR)
信号中断,重新发送
else 系统错误
}
9.7 消息队列接收函数
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgrcv(int msgid,void *msgp,int msgsz,long msgtyp,int msgflg);
msgrcv从消息队列msgid中读取一条消息:
msgid指定了接收消息队列的标识号
msgp指向存接收消息内容的地址,
msgsz指定该缓冲区的最大容量(包含消息类型的长度)
msgtyp指定读取消息的类型:
0 读取队列中的第一个消息
正整数 读取队列中第一个类型为msgtyp的消息
负整数 读取队列中第一个类型小于或等于msgtyp的绝对值的消息
msgflg控制消息接收的方式:
IPC_NOWAIT 非阻塞方式读取消息
MSG_NOERROR 截断读取消息
调用成功返回接收到的字节数否则-1,并根据以下情况设置errno的值:
1.消息放送中队列被系统删除,返回-1,errno = EIDRM
2.如果msgflg设置了IPC_NOWAIT,当队列没有该消息时返回-1,errno=EAGAIN
3.如果msgflg没有设置IPC_NOWAIT当队列没有该消息时,一直等待
9.8 消息队列接收模型
以阻塞方式从消息队列(关键字为KEY)中接收一条消息
消息类型为TYPE:
1.定义消息结构
与发送消息中的结构相一致
2.打开(创建)消息队列
int msgid;
msgid = msgget(KEY, 0666|IPC_CREAT);
3.准备接收缓冲区
struct msgbuf buf;
memset(buf,0,sizeof(buf));
4.接收消息
int ret;
ret = msgrcv(msgid, &msg, sizeof(msg.ctext),TYPE,0);
5.接收判断
if (ret == -1)
{
if (errno == EINTR)
信号中断,重新接收
else 系统错误
}
9.9 消息队列的控制
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgctl(int msgid,int cmd,struct msgid_ds *buf);
cmd取值:
IPC_CMID: 删除消息队列msqid
IPC_STAT: 读取消息队列数据结构到buf
IPC_SET: 设置消息队列结构msgid_ds的成员
调用成功返回0,否则-1