标签:uc
1. 基本特点
1) 消息队列是一个由系统内核负责存储和管理,并通过消息队列标识引用的数据链表,消息队列 和有名管道fifo的区别在: 后者一次只能放一个包,而前者则可以放很多包,这样就能处理发包快,哪包慢的问题
2) 可以通过msgget函数创建一个新的消息队列, 或获取一个已有的消息队列。 通过msgsnd函数 (send)向消息队列的后端追加消息, 通过msgrcv(receive)函数从消息队列的前端提取消息。
3) 消息队列中的每个消息单元除包含消息数据外,还包含消息类型和数据长度。消息类型的存在意义:同一个消息队列处理不同类型的消息,比如现在处理存款和取款两种情况,我们就可以定义两种类型的数据而不是定义两条消息队列
4) 内核为每个消息队列,维护一个msqid_ds结构体形式的消息队列对象。
truct 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; // 消息队列能容纳的最大字节数
pid_t msg_lspid; // 最后发送进程PID
pid_t msg_lrpid; // 最后接收进程PID
};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; // 序列号
};
2. 常用函数
头文件 : #include <sys/msg.h>
1) 创建/获取消息队列
int msgget (key_t key, int msgflg);A. 该函数以key参数为键值创建消息队列,或获取已有的消息队列。
2) 向消息队列发送消息
int msgsnd (int msqid, const void* msgp,size_t msgsz, int msgflg);A. msgp参数指向一个包含消息类型和消息数据的内存块。该内存块的前4个字节必须是一个大于0的整数,代表消息类型,其后紧跟消息数据。消息数据的字节长度用msgsz参数表示。
注意:msgsz参数并不包含消息类型的字节数(4)。
B. 若内核中的消息队列缓冲区有足够的空闲空间(由内核参数设定),则此函数会将消息拷入该缓冲区并立即返回0,表示发送成功,否则此函数会阻塞,直到内核中的消息队列缓冲区有足够的空闲空间为止
C. 若msgflg参数包含IPC_NOWAIT位, 则当内核中的消息队列缓冲区没有足够的空闲空间时, 此函数不会阻塞,而是返回-1,errno为EAGAIN。
D. 成功返回0,失败返回-1。
3) 从消息队列接收消息
ssize_t msgrcv (int msqid, void* msgp, size_t msgsz,long msgtyp, int msgflg);A. msgp参数指向一个包含消息类型(4字节),和消息数据的内存块.
int msgctl (int msqid, int cmd, struct msqid_ds* buf);A. cmd取值:
B. 成功返回0,失败返回-1。
#include <stdio.h>
#include <string.h>
#include <sys/msg.h>
int main (void) {
printf ("创建消息队列...\n");
key_t key = ftok (".", 100);
if (key == -1) {
perror ("ftok");
return -1;
}
int msqid = msgget (key, 0644 | IPC_CREAT | IPC_EXCL);
if (msqid == -1) {
perror ("msqget");
return -1;
}
printf ("向消息队列(0x%08x/%d)发送数据...\n", key, msqid);
for (;;) {
printf ("> ");
struct {
long mtype;
char mtext[1024];
} msgbuf = {1234, ""};
gets (msgbuf.mtext);
if (! strcmp (msgbuf.mtext, "!"))
break;
if (msgsnd (msqid, &msgbuf, (strlen (msgbuf.mtext) + 1) *
sizeof (msgbuf.mtext[0]), 0) == -1) {
perror ("msgsnd");
return -1;
}
}
printf ("销毁消息队列(0x%08x/%d)...\n", key, msqid);
if (msgctl (msqid, IPC_RMID, NULL) == -1) {
perror ("msgctl");
return -1;
}
printf ("大功告成!\n");
return 0;
}
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/msg.h>
int main (void) {
printf ("获取消息队列...\n");
key_t key = ftok (".", 100);
if (key == -1) {
perror ("ftok");
return -1;
}
int msqid = msgget (key, 0);
if (msqid == -1) {
perror ("msgget");
return -1;
}
printf ("从消息队列(0x%08x/%d)接收消息...\n", key, msqid);
for (;;) {
struct {
long mtype;
char mtext[1024];
} msgbuf = {};
ssize_t msgsz = msgrcv (msqid, &msgbuf,
sizeof (msgbuf.mtext) - sizeof (msgbuf.mtext[0]), 1234,
MSG_NOERROR/* | IPC_NOWAIT*/);
if (msgsz == -1)
if (errno == EIDRM) {
printf ("消息队列(0x%08x/%d)已销毁!\n", key, msqid);
break;
}
else
if (errno == ENOMSG) {
printf ("现在没有消息,干点儿别的...\n");
sleep (1);
}
else {
perror ("msgrcv");
return -1;
}
else
printf ("%04d< %s\n", msgsz, msgbuf.mtext);
}
printf ("大功告成!\n");
return 0;
}
命令: ipcs -q 查看消息队列的信息
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:uc
原文地址:http://blog.csdn.net/meetings/article/details/47189525