标签: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