消息队列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参数。

EFAULTmsgp指向的非法地址空间。

EIDRM:消息队列被删除。

EINTRmsgsnd函数调用被信号中断。

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为指向消息内容的指针;msgszmsgbuf结构体中mtext成员的长度(即消息内容的长度);msgtyp为请求的消息类型,如果msgtyp0,消息队列中的第一条消息将被读取,而不管类型。如果msgtyp大于0,消息队列中同类型的消息将被读取。如果在msgflg中设置了MSG_RXCEPT位,将读取出指定类型的其他消息。如果msgtyp小于0,将读取绝对值小于msgtyp的消息; msgflg为指定的处理方式,可以取一下值:

IPC_NOWAIT:如果没有满足条件的消息,调用立即返回,此时,errnoENOMSG

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

ENOMSGmsgflg中指定了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]#


 

 

 

 

 

 

 

原创粉丝点击