消息队列2
来源:互联网 发布:linux用来干什么 编辑:程序博客网 时间:2024/05/08 14:47
说明:只供学习交流,装载请注明出处
六,msgsnd函数
创建完消息队列后,为了通过消息队列进行进程间的通信,信息的发送方必须向消息队列发送信息。信息的接收方需要从消息队列中接收消息。发送消息和接收消息使用的函数分别是msgsnd函数和msgrcv函数。msgsnd函数的具体信息如下表:
msgsnd函数
头文件
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
函数原型
int msgsnd(int msqid, const void *msgp,
size_t msgsz, int msgflg);
返回值
成功
失败
是否设置errno
0
-1
是
说明:msgsnd函数用于向消息队列中发送消息。参数msqid为要将消息发送到的消息队列。参数msgp为指向msgbuf结构体的指针,其定义如下:
struct msgbuf
{
longmtype; //消息类型,可以为大于0的任意整数
char mtext[1]; //消息文本,文本的大小由msgsnd函数中的参数msgsz确定
};
参数msgsz为所发送消息的字节数。msgflg可以为0(忽略该参数)或使用IPC_NOWAIT。
如果消息队列中有足够的空间,msgsnd函数立即返回,并将msgp指向的消息添加到指定消息队列中。消息队列可容纳的最大消息量在msg_bytes中给出,该值在创建消息队列时被初始化为MSGMNB,当然可以通过msgctl函数修改该限制。
如果消息队列已经达到了最大消息量,msgsnd函数将阻塞(参数msgflg没有使用IPC_NOWAIT情况下,如果使用了该参数,msgsnd将调用失败,同时,将errno设置为EAGAIN),直到消息队列中有足够的空间。
成功调用msgsnd函数后,将更新msqid_ds结构体中的如下成员:
msg_lspid:调用进程的进程号。
msg_qnum:加1
msg_stime:设置为当前的时间。
错误信息:
EACCES:调用msgsnd函数的进程没有向消息队列发送消息的权限。
EAGAIN:消息队列达到最大信息量,同时msgflg中使用了IPC_NOWAIT参数。
EFAULT:msgp指向的非法地址空间。
EIDRM:消息队列被删除。
EINTR:msgsnd函数调用被信号中断。
EINVAL:非法的msqid值、mtype为负数或msgsz不合法(小于0或大于系统规定的MSGMAX值)。
ENOMEM:系统空间不足。
实例:
程序为使用msgsnd函数的实例。程序首先调用msgsnd函数,向消息队列中发送消息,然后,调用msgctl函数来获得消息队列的相关信息,以确认消息队列中是否存在发送来的消息。具体代码如下:
#include <stdio.h>#include <sys/ipc.h>#include <sys/msg.h>#include <sys/types.h>#include <string.h>typedef struct{long mtype;char mtext[BUFSIZ];}msg_info;//创建消息队列int creat_msg_queue(){key_t key;int proj_id;int msqid;struct msqid_ds buffer;proj_id = 3;key = ftok("./hello", proj_id);if (key == -1){perror("Cannot generate the IPC key");return (-1);}msqid = msgget(key, IPC_CREAT|0660);if (msqid == -1){perror("Cannot create message queue resource");return (-1);}return (msqid);}//给指定消息队列发送消息int send_msg(int msqid, char *msg){int result;msg_info buf;buf.mtype = 100;strcpy(buf.mtext, msg);result = msgsnd(msqid, &buf, strlen(msg), 0);if (result == -1){perror("Cannot send message to the message queue");}return (result);}//显示消息队列的信息int show_msg_queue_stat(int msqid){struct msqid_ds buffer;int flg;flg = msgctl(msqid, IPC_STAT, &buffer);if (flg == -1){perror("Cannot get status of the message queue");return (-1);}printf("======Message Queue Info======\n");printf("effective user of id : %d\n", buffer.msg_perm.uid);printf("effective group of id : %d\n", buffer.msg_perm.gid);printf("message queue's creator user id : %d\n", buffer.msg_perm.cuid);printf("message queue's creator user id : %d\n", buffer.msg_perm.cgid);printf("access mode : %x\n", buffer.msg_perm.mode);printf("Maximum number of bytes allowed in message queue: %d\n", (int)buffer.msg_qbytes);printf("Current number of bytes in message queue(non-standard) : %d\n",(long unsigned int)buffer.__msg_cbytes);printf("Current number of message in message queue : %d\n",(msgqnum_t)buffer.msg_qnum);return (0);}int main(void){int msqid;if (msqid = creat_msg_queue()<0){printf("Create msg queue fail\n");return (-1);}if (send_msg(msqid, "test message") < 0){printf("Send message failure\n");return (-1);}if (show_msg_queue_stat(msqid) < 0){printf("Show message queue fail\n");return (-1);}return (0);}运行结果:[root@localhost test]# ./msgsnd ======Message Queue Info======effective user of id : 0effective group of id : 0message queue's creator user id : 0message queue's creator user id : 0access mode : 1b0Maximum number of bytes allowed in message queue: 65536Current number of bytes in message queue(non-standard) : 12Current number of message in message queue : 1[root@localhost test]# ipcs -q------ Message Queues --------key msqid owner perms used-bytes messages 0x03021077 0 root 660 12 1 [root@localhost test]#
七,msgrcv函数
要接收消息队列中的消息,需要使用msgrcv函数。该函数的具体信息如下表:
头文件
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
函数原型
size_t msgrcv(int msqid, void *msgp,
long msgtyp, int msgflg);
返回值
成功
失败
是否设置errno
收到消息的字节数
-1
是
函数功能:msgrcv函数从msgid代表的消息队列中读取一个消息,并将消息存储在msgp指向的缓冲结构中。该缓冲结构的定义类似于msgbuf结构体。
参数说明:msqid为要成中读取消息的消息队列标识符;msgp为指向消息内容的指针;msgsz为msgbuf结构体中mtext成员的长度(即消息内容的长度);msgtyp为请求的消息类型,如果msgtyp为0,消息队列中的第一条消息将被读取,而不管类型。如果msgtyp大于0,消息队列中同类型的消息将被读取。如果在msgflg中设置了MSG_RXCEPT位,将读取出指定类型的其他消息。如果msgtyp小于0,将读取绝对值小于msgtyp的消息; msgflg为指定的处理方式,可以取一下值:
IPC_NOWAIT:如果没有满足条件的消息,调用立即返回,此时,errno为ENOMSG。
IPC_EXCEPT:与msgtyp>0配合使用,返回队列中第一个类型不为msgtyp的消息。
IPC_NOERROR:如果队列中满足条件的消息内容大于所请求的msgsz字节,则把该消息截断,截断部分将丢失。
如果消息队列中没有要获得的消息类型(有参数msgtyp指定),且msgflg参数没有设置IPC_NOWAIT位,msgrcv函数将处于阻塞状态,直到以下情况发生:
(1):消息队列中收到了进程要获得的消息。
(2):消息队列被删除,msgrcv系统调用失败。
(3):调用过程中接收到了中断。
当成功获得所需消息后,将更新msqid_ds结构体中的如下成员:
msg_lrpid:被设置成调用msgrcv函数的进程。
msg_qnum:减1。
msg_rtime:被设置成系统当前时间。
错误信息:
E2BIG:接收到消息的长度超过参数msgsz中指定的长度,同时,参数msgflg没有设置MSG_NOERROR位。
EACCES:进程无读取消息队列中消息的权限。
EAGAIN:消息队列中无所要获得类型的消息,且msgflg没有设置IPC_NOWAIT位。
EFAULT:参数msgp执行非法地址空间。
EIDRM:当进程处于阻塞状态等待要获得类型的消息时,消息队列被删除。
EINTR:当进程处于阻塞状态等待要获得类型的消息时,接收到信号。
EINVAL:非法的msqid值或msgsz小于0。
ENOMSG:msgflg中指定了IPC_NOWAIT位,而消息队列中没有要获取的消息。
实例:
程序通过调用msgrcv函数实现了读取消息队列中指定消息的功能。读取消息队列中信息的函数为recv_msg,函数的参数意义如下:
(1):msqid:消息队列标识符。
(2):msg_type:消息类型,该消息类型与调用时发送的类型要一致。
(3):msg:接收到消息内容将保存在该指针的空间中。
具体代码如下:
#include <stdio.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>#include <string.h>typedef struct {long mtype;char mtext[BUFSIZ];}msg_info;int recv_msg(int msqid, int msg_type, char *msg){int result;msg_info buffer;result = msgrcv(msqid, &buffer, BUFSIZ, msg_type, 0);if (result == -1){perror("Cannot receive message from the queue");}strcpy(msg, buffer.mtext);return (result);}int main(int argc, char *argv[]){char buf[BUFSIZ] = {'\0'};int msqid;int msg_type;int result;if (argc != 3){printf("Usage: %s msqid message_type");return (-1);}msqid = atoi(argv[1]);msg_type=atoi(argv[2]);result = recv_msg(msqid, msg_type, buf);if (result == -1){printf("Cannot get message\n");return (-1);}else{printf("Message queue id: %d message type : %d message : %s\n",msqid, msg_type, buf);}return (0);}运行结果:[root@localhost test]# ./msgrcv 0 100Message queue id: 0 message type : 100 message : test message[root@localhost test]# ipcs -q------ Message Queues --------key msqid owner perms used-bytes messages 0x03021077 0 root 660 0 0 [root@localhost test]#
- 消息队列-2
- 消息队列2
- Kafka#2:消息队列
- 消息队列2
- 17 消息队列2
- 消息队列(2):消息存哪里了?
- 3.2.2 队列消息和非队列消息
- RabbitMQ消息队列(2):工作队列之消息分发机制
- 3.2.2 队列消息和非队列消息
- 分布式消息队列(2)
- 2-19 消息队列通信
- 消息队列
- 消息队列
- 消息队列
- 消息队列
- 消息队列
- 消息队列
- 消息队列
- android面试题2
- Intel Xeon正式进化十核心
- NYOJ 题目528 找球号(三)
- matlab 记录
- 【设计模式】观察者
- 消息队列2
- unity3d连接mysql的各种问题及解决
- C/C++ const 详解
- 【协议识别】Wireshark重要过滤条件
- Spring bean 实现生命周期的三种解决方案
- 要做的事
- 英特尔推出8核服务器处理器X7500系列
- zoj2913 Bus Pass
- 数据结构之链表概念