System V进程间通信---消息队列

一、消息队列模型
消息队列是消息的链式队列,下图即为消息队列模型…
这里写图片描述

1、消息队列的基本属性

struct msqid_ds
{
struct msqid_ds {
struct ipc_perm msg_perm;
struct msg msg_first; / first message on queue,unused */
struct msg msg_last; / last message in queue,unused */
__kernel_time_t msg_stime; /* last msgsnd time */
__kernel_time_t msg_rtime; /* last msgrcv time */
__kernel_time_t msg_ctime; /* last change time */
unsigned long msg_lcbytes; /* Reuse junk fields for 32 bit */
unsigned long msg_lqbytes; /* ditto */
unsigned short msg_cbytes; /* current number of bytes on queue */
unsigned short msg_qnum; /* number of messages in queue */
unsigned short msg_qbytes; /* max number of bytes on queue */
__kernel_ipc_pid_t msg_lspid; /* pid of last msgsnd */
__kernel_ipc_pid_t msg_lrpid; /* last receive pid */
};

2、创建消息队列

在我们使用消息队列之前,需要使用msgget函数创建该消息队列,其函数申明如下:

extern int msgget (key_t key , int msgflg) ;

key:函数ftok的返回值或IPC_PRIVATE。
msgflag: IPC_CREAT:创建新的消息队列。 IPC_EXCL:与IPC_CREAT一同使用,表示如果要创建的消息队列已经存在,则返回错误。 IPC_NOWAIT:读写消息队列要求无法满足时,不阻塞。返回值: 调用成功返回队列标识符,否则返回-1.

3、发送消息到消息队列与从消息队列进行消息的接收

发送函数:
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

接收函数:
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

msqid:消息队列的识别码。

msgp:指向消息缓冲区的指针,此位置用来暂时存储发送和接收的消息,是一个用户可定义的通用结构,形态如下
struct msgbuf {
long mtype; /* 消息类型,必须 > 0 */
char mtext[1]; /* 消息文本 */
};

msgsz:消息的大小。

msgtyp:消息类型
msgtyp等于0 则返回队列的最早的一个消息。
msgtyp大于0,则返回其类型为mtype的第一个消息。
msgtyp小于0,则返回其类型小于或等于mtype参数的绝对值的最小的一个消息。

msgflg:这个参数依然是是控制函数行为的标志,取值可以是:0,表示忽略;IPC_NOWAIT,如果消息队列为空,则返回一个ENOMSG,并将控制权交回调用函数的进程。如果不指定这个参数,那么进程将被阻塞直到函数可以从队列中得到符合条件的消息为止。如果一个client 正在等待消息的时候队列被删除,EIDRM 就会被返回。如果进程在阻塞等待过程中收到了系统的中断信号,EINTR 就会被返回。MSG_NOERROR,如果函数取得的消息长度大于msgsz,将只返回msgsz 长度的信息,剩下的部分被丢弃了。如果不指定这个参数,E2BIG 将被返回,而消息则留在队列中不被取出。当消息从队列内取出后,相应的消息就从队列中删除了。

二、应用实例
发送端进程:

/*
 *利用消息队列进行通信的消息发送端
 */

#include<stdio.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<string.h>

/*
 *定义消息结构体
 */
struct msgbuf
{
    long type ; //消息类型
    char ptr[128] ; //消息缓冲区
} ;


int main(int argc , char* argv[])
{
    key_t key ;
    key = ftok(argv[1] , 100) ; //创建约定通信的键值key 

    int msgid ;
    msgid = msgget(key , IPC_CREAT | 0600) ; //进行消息队列的创建

    pid_t pid ;
    pid = fork() ; //创建用于信息发送的子进程

    if(pid == 0) //进行消息发送
    {
        while(1) //循环发送
        {
            printf("please input msg to send : ") ;
            char buf[128] ;
            fgets(buf , 128 , stdin) ;
            struct msgbuf *ptr = malloc(sizeof(struct msgbuf)) ;

            //进行消息的设置
            ptr->type = 1 ;
            memset(ptr->ptr , '\0' , 128) ;
            memcpy(ptr->ptr , buf , strlen(buf)) ;

            msgsnd(msgid , ptr , sizeof(struct msgbuf) , 0) ; //进行消息的发送


            free(ptr) ;
        }
    }else
    {
        //进行接收到的消息的定义
        struct msgbuf{
            long type ;
            char ptr[1024] ; 
        } ;

        while(1) //进行消息的循环接收
        {
            struct msgbuf mybuf ;
            memset(&mybuf , '\0' , sizeof(mybuf)) ; //进行清空

            msgrcv(msgid , &mybuf , 1024 , 2 , 0) ; //进行消息的接收

            printf("recv msg : %s \n" , mybuf.ptr) ;            
        }   
    }

    return 0 ;
}

接收端进程:

/*
 *利用消息队列进行通信的消息接收端
 */

#include<stdio.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<string.h>

/*
 *定义消息结构体
 */
struct msgbuf
{
    long type ; //消息类型
    char ptr[128] ; //消息缓冲区
} ;

int main(int argc , char* argv[])
{
    key_t key ;
    key = ftok(argv[1] , 100) ; //创建约定通信的键值key 

    int msgid ;
    msgid = msgget(key , IPC_CREAT | 0600) ; //进行消息队列的创建

    pid_t pid ;
    pid = fork() ; //创建用于信息发送的子进程

    if(pid == 0) //进行消息发送
    {
        while(1) //循环发送
        {
            printf("please input msg to send : ") ;
            char buf[128] ;
            fgets(buf , 128 , stdin) ;
            struct msgbuf *ptr = (struct msgbuf*)malloc(sizeof(struct msgbuf)) ;

            //进行消息的设置
            ptr->type = 2 ;
            memset(ptr->ptr , '\0' , 128) ;
            memcpy(ptr->ptr , buf , strlen(buf)) ;

            msgsnd(msgid , ptr , sizeof(struct msgbuf) , 0) ; //进行消息的发送
            free(ptr) ;
        }
    }else
    {
        //进行接收到的消息的定义
        struct msgbuf{
            long type ;
            char ptr[1024] ; 
        } ;

        while(1) //进行消息的循环接收
        {
            struct msgbuf mybuf ;
            memset(&mybuf , '\0' , sizeof(mybuf)) ; //进行清空

            msgrcv(msgid , &mybuf , 1024 , 1 , 0) ; //进行消息的接收

            printf("recv msg : %s \n" , mybuf.ptr) ;            
        }   
    }

    return 0 ;
}

可以查看结果如下:
发送端:
这里写图片描述

接收端:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值