博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux编程基础之进程间通信之五:消息队列
阅读量:4195 次
发布时间:2019-05-26

本文共 3947 字,大约阅读时间需要 13 分钟。

一、消息队列的概述

消息队列,列就是一些消息的列表。用户可以从消息队列中添加消息和读取消息等。从这点上看,消息队列具有一定的FIFO 特性,但是它可以实现消息的随机查询,比FIFO 具有更大的优势。同时,这些消息又是存在于内核中的,由“队列ID”来标识。

二、消息队列的一般使用原理和函数说明

1、一般使用原理

消息队列的实现包括创建或打开消息队列、添加消息、读取消息和控制消息队列这4 种操作。其中创建或打开消息队列使用的函数是msgget(),这里创建的消息队列的数量会受到系统消息队列数量的限制;添加消息使用的函数是msgsnd()函数,它把消息添加到已打开的消息队列末尾;读取消息使用的函数是msgrcv(),它把消息从消息队列中取走,与FIFO 不同的是,这里可以指定取走某一条消息;最后控制消息队列使用的函数是msgctl(),它可以完成多项功能。

2、常用函数的说明

a、获得或者创建消息队列的函数

int msgget(key_t key, int msgflg)
        key : 消息队列的键值,多个进程可以通过它访问同一个消息队列,其中有个特殊值IPC_PRIVATE。它用于创建当前进程的私有消息队列

        msgflg : 权限标志位

        返回值:成功返回消息队列ID,失败返回-1

b、添加一个消息到消息队列

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg)
        msgid : 消息队列的队列ID

        msgp : 指向消息结构的指针。该消息结构msgbuf 通常为:

struct msgbuf{long mtype; /* 消息类型,该结构必须从这个域开始 */char mtext[1]; /* 消息正文 */}
        msgsz : 消息正文的字节数(不包括消息类型指针变量)

        msgflg :IPC_NOWAIT 若消息无法立即发送(比如:当前消息队列已满),函数会立即返回;0:msgsnd 调阻塞直到发送成功为止

        返回值:成功返回0,失败返回-1

c、从消息队列中取出一个消息

int msgrcv(int msgid, void *msgp, size_t msgsz, long int msgtyp, int msgflg)
        msgid : 消息队列的队列ID

        msgp : 消息缓冲区, 同于msgsnd()函数的msgp

        msgsz : 消息正文的字节数(不包括消息类型指针变量)

        msgtype : 0:接收消息队列中第一个消息;大于0:接收消息队列中第一个类型为msgtyp 的消息;小于0:接收消息队列中第一个类型值不小于msgtyp 绝对值且类型值又最小的消息

        msgflg : MSG_NOERROR:若返回的消息比msgsz 字节多,则消息就会截短到msgsz 字节,且不通知消息发送进程;IPC_NOWAIT 若在消息队列中并没有相应类型的消息可以接收,则函数立即返回;0:msgsnd()调用阻塞直到接收一条相应类型的消息为止;

        返回值:成功返回0,失败返回-1

d、消息队列的控制函数

int msgctl (int msgqid, int cmd, struct msqid_ds *buf )
        msqid : 消息队列的队列ID

        cmd : IPC_STAT:读取消息队列的数据结构msqid_ds,并将其存储在buf 指定的地址中;IPC_SET:设置消息队列的数据结构msqid_ds 中的ipc_perm 域(IPC 操作权限描述结构)值。这个值取自buf 参数;IPC_RMID:从系统内核中删除消息队列

        buf : 描述消息队列的msgqid_ds 结构类型变量

        返回值:成功返回0,失败返回-1

三、测试

编写一个消息队列的测试例程:

msg_rcv.c :创建一个消息队列,并不断的将消息队列中的消息读取出来,没有消息就阻塞等待,接收到quit消息就退出

msg_snd.c : 创建一个消息,将消息添加到消息队列,消息的信息从用户空间传入

msg_rcv.c的具体实现如下:

#include 
#include
#include
#include
#include
#include
/* 定义消息的大小 */#define MESSAGE_SIZE 256/* 定义一个结构体作为消息的基本单元 */struct msgbuf { long mtype; /* message type, must be > 0 */ char mtext[MESSAGE_SIZE]; /* message data */};/* 消息队列的接收端,接收从发送端发送过来的消息 * */int main(void){ key_t key; int msgid; int ret; struct msgbuf msg; /* 构造一个消息队列的键值 */ key = ftok(".", 0x03); if(-1 == key) { printf("ftok error!\n"); return -1; } /* 创建一个消息队列 */ msgid = msgget(key, 0666 | IPC_CREAT); if(-1 == msgid) { printf("msgget error!\n"); return -1; } /* 不停的接收从发送端发来的消息,收到: quit 退出 */ while(1) { /* 初始化消息单元 */ memset(msg.mtext, 0, MESSAGE_SIZE); /* 从消息队列中取出第一个消息 */ ret = msgrcv(msgid, &msg, MESSAGE_SIZE, 0, 0); if(-1 == ret) { printf("msgrcv error!\n"); return -1; } /* 打印接收来的消息 */ printf("message form : %ld, message : %s\n", msg.mtype, msg.mtext); /* 判断接收到的消息是否是 : quit */ if(strncmp(msg.mtext, "quit", 4) == 0) { printf("quit!!!\n"); goto out; } }out: /* 将消息队列从系统中移除 */ ret = msgctl(msgid, IPC_RMID, NULL); if(-1 == ret) { printf("msgctl error!\n"); return -1; } return 0;}
msg_snd.c的具体实现如下:

#include 
#include
#include
#include
#include
#include
/* 定义消息的大小 */#define MESSAGE_SIZE 256/* 定义一个结构体作为消息的基本单元 */struct msgbuf { long mtype; /* message type, must be > 0 */ char mtext[MESSAGE_SIZE]; /* message data */};/* 消息队列的发送端,发送一条消息给接收端 * usage : msg_snd
*/int main(int argc, char *argv[]){ key_t key; int msgid; int ret; struct msgbuf msg; if(2 != argc) { printf("usage : %s
\n", argv[0]); return -1; } /* 构造一个消息队列的键值 */ key = ftok(".", 0x03); if(-1 == key) { printf("ftok error!\n"); return -1; } /* 获得或者创建一个消息队列 */ msgid = msgget(key, 0666 | IPC_CREAT); if(-1 == msgid) { printf("msgget error!\n"); return -1; } /* 初始化消息缓冲区 */ memset(msg.mtext, 0, MESSAGE_SIZE); /* 构造一个消息单元 */ msg.mtype = getpid(); // 设置消息类型为当前进程的pid strcpy(msg.mtext, argv[1]); // 将用户输入的消息写入消息队列中 /* 将消息添加到消息队列 */ ret = msgsnd(msgid, &msg, strlen(msg.mtext), 0); if(-1 == ret) { printf("msgsnd error!\n"); return -1; } /* 打印发送消息的信息 */ printf("pid : %ld, message : %s\n", msg.mtype, msg.mtext); return 0;}
编译并运行结果如下所示:

你可能感兴趣的文章
flex 滚动条问题
查看>>
软件开发管理中的博奕论
查看>>
计算机认证考试种类
查看>>
SQL in和exists 比较
查看>>
社会性网络服务(SNS)研究
查看>>
鼠标DarkField技术
查看>>
傻傻的我
查看>>
实时内存数据库的数据管理
查看>>
Sonar代码质量管理平台
查看>>
Checkstyle, PMD, Findbugs对比
查看>>
网站成功的三十三个法则
查看>>
Memcache基础教程
查看>>
程序员能力矩阵
查看>>
主流浏览器内核概览
查看>>
交大研究生,就一个字牛
查看>>
Android开发之ADB使用
查看>>
Android模拟器使用模拟SD卡
查看>>
Redis入门教程
查看>>
Google code上利用SVN托管代码
查看>>
技术的发展与互联网的发展
查看>>