system V消息队列的使用

来源:互联网 发布:数据交换平台etl 编辑:程序博客网 时间:2024/06/05 02:29

    最近在学习网络,主要是《UNIX网络编程》这本书,现在给大家分享以下我在学习消息队列这一部分的心得和体会,如果有不足之处希望大家批评指正。

    大家知道linux中支持Posix消息队列和System V消息队列,这里主要给大家介绍System V消息队列。下文所说的消息队列均尾System V消息队列。

     消息队列应用于进程之间的通讯,是一条由消息构成的队列但是其也是由消息构成的链表封装来的,消息队列是由消息队列标识符来标志,具有足够特权的任何进程都可以给消息队列中放置消息,当然也可以从消息队列中读出消息。

     我们首先来看有关消息队列的函数:

     首先有关消息队列的头文件#include<sys/msg.h>

    1. int msgget(key_t key, int oflg);

这个函数用来创建或者访问一个已经存在的消息队列,它的返回值为int型即为消息队列的标示符,如果访问或者创建成功则其标识符不小于0,如果出错则为-1;参数中key一般为ftok函数的返回值,该返回值主要生成一个IPC健,而oflg是书写权限的组合一般创建消息队列一般输入IPC_CREAT|IPC_EXCL|0666;

     2. int msgsnd(int msqid, const void *ptr, size_t length, int flag);

这个函数用来给消息队列中写入消息,它的的返回值是int型,而其中的msqid即位上述msgget函数的返回值即是消息队列的标示符,ptr是一个结构指针(即是该消息队列内部一个节点的结构),其结构一般为

    struct msgbuf{

        long mtypel;

        char mtext[1];     //其中元素个数可为任意值但是小于256;

}Msg;

而length参数即为mtext的长度加一(当然要加上结束符' \0 '),而flag可以为多种选择可以为0,也可以是IPC_NOWAIT(这个标志使msgsnd调用非阻塞);写数据时你可以先将消息输入到Msg类型结构定义的结构体的 mtext中;

    3.ssize_t  msgrcv(int msqid, void *ptr, size_t length, long type, int flag);

可知其返回值为ssize_t类型(关于该类型的解释可以看http://demo.netfoucs.com/bytxl/article/details/39083887);

该函数如果成功则返回读入缓冲区中数据的字节数,失败则返回-1;其中msqid和ptr与上述函数中的这两个参数相同,length即为mtext中数据的大小,而type主要是希望从所给队列中读出什么样的信息(以我的看法认为该参数主要是为了区别不同进程对消息队列的收发正常,在后边的程序中大家就可以看到。)flag参数该参数一般用0就可以。

    4 int msgctl(int msqid , int cmd , struct msqid_ds *buf);

该函数即为对消息队列的控制函数,如果执行成功则返回0如果失败则返回-1,msqid参数同上述参数相同不做解释,cmd指你向该函数传入的命令,该函数提供了三个传入的命令分别是IPC_RMID(从系统中删除该消息队列),IPC_SET,IPC_STAT.后两个参数一般运用的不多所以不过多解释。

   现在我们看一个进程之间通过消息队列通信的程序

            

首先这个程序可以看为搭建了一个类似服务器的样子Ser我们可以看到首先通过ftok得到了一个IPC键,再通过msgget得到了消息队列的标示符,我们再通过Msg msg创建了一个结构体变量,最后通过msgsnd来写消息,通过msgrcv来读消息,可以看到在程序开始我们首先定义了MSGSND,MSGRCV通过这个可以看到服务器发送的消息大小类型为MSGSND,接受的消息大小为MSGRCV。

现在我们在来看搭建一个类似客户端的程序代码


      可以看到前边的编程基本与Ser的编写相似但是不同的可以看到在客户端程序cli的编写中可以看到对MSGSND和MSGRCV的赋值是相反的,这就是我们说的在消息接受函数msgrcv函数中对type参数的应用,可以看到ser发送的是2这个大小的数,而接收的是1大小的数,在cli中发送的却是1大小的数,接收的却是2大小的数,而且这两个程序是同步运行所以我们通过程序知道在ser程序给消息队列写入消息之前cli的读取消息的函数一直等待的是一个2大小的数,而ser写入之后cli就会读取,同时ser写入消息之后在等待读如1大小的数,这样就形成了一个同步的体制,我们来看一下程序的运行结果

可以看到cli在等待ser 输入消息,而ser在等待你输入消息我们来看一下ser输入消息后的结果

现在cli已经接收到ser发送的消息,同时ser在等待cli发送的消息。

    我对消息队列的理解就是这样,希望大家把更好的意见给我,大家也可以一起共同探讨,谢谢。

0 0