第06章 System V消息队列

6.1 概述

  • 对于系统中的每个消息队列,内核维护一个定义在
struct msqid_ds  "头结点" -> 表示一个“消息队列”
{
    struct ipc_perm  msg_perm; //该结构的r/w权限
    struct msg *msg_first;     //指向消息队列上的第一个消息
    struct msg *msg_last;      //指向消息队列上的最后一个消息   
    msglen_t  msg_cbytes;      //当前队列中消息的总字节数
    msgqnum_t msg_qnum;        //当前队列中消息的总数(struct msg结构体的总数)
    msglen_t msq_qbytes;       //队列中允许的最大字节数
    pid_t msg_lspid;           //最后发送消息的那个进程的id
    pid_t msg_lrpid;           //最后接收消息的那个进程的id
    time_t   msg_stime;        //最后发送消息的时间
    time_t   msg_rtime;        //最后接收消息的时间
    time_t   msg_ctime;        //最后修改消息结构体的时间
};

6.2 msgget 函数

  • msgget()用于创建一个新的消息队列或访问一个已存在的消息队列
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int msgget(key_t key, int msgflg);
  • 返回值是一个整数标识符,用来代指队列
  • key可以是ftok()的返回值,也可以是常值IPC_PRIVATE(保证产生一个唯一的对象)

6.3 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);
  • msqis是msgget返回的标识符
  • ptr是一个结构指针,定义在
struct msgbuf{
    long mtype; //消息类型,具体的类型的含义由程序设计者指定
    char mtext[]; //消息内容,可长可短★★★
};
  • msgflg: 发送标志:
    • (1) 0 阻塞模式(默认)
    • (2) IPC_NOWAIT 非阻塞模式,失败返回EAGAIN错误
  • msgsz: 消息内容长度,上述结构体数组mtext的实际大小
  • 成功返回0,失败返回-1,同时errno被设置

6.4 msgrcv()函数

  • 从消息队列中读一个消息
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);
  • msqid: 消息队列id
  • msgp:指向消息结构(就上述自定义的结构体),用来保存读取的消息。
  • msgsz: msgp指向的消息结构体,最多可以保存多少字节的消息。
  • msgtyp: 您想要读取的消息类型 (0为任意类型)
  • msgflg:
    • (1) 0 阻塞模式
    • (2) IPC_NOWAIT -> 非阻塞模式
  • 返回值:
    • 成功返回实际读入缓冲区中数据的字节数,失败返回-1, 同时errno被设置。

6.5 msgctl()函数

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
  • 该函数提供三个命令
    • IPC_RMID :删除由msqid指定的消息队列
    • IPC_SET :设置结构体中相应成员
    • IPC_STAT :返回所指定消息队列对应当前msqid_ds的结构

6.7 客户服务器例子

  • svmsg.h
#include    "unpipc.h"

/* Our own "messages" to use with pipes, FIFOs, and message queues. */

    /* 4want sizeof(struct mymesg) <= PIPE_BUF */
#define MAXMESGDATA (PIPE_BUF - 2*sizeof(long))

    /* 4length of mesg_len and mesg_type */
#define MESGHDRSIZE (sizeof(struct mymesg) - MAXMESGDATA)

struct mymesg {
  long  mesg_len;   /* #bytes in mesg_data, can be 0 */
  long  mesg_type;  /* message type, must be > 0 */
  char  mesg_data[MAXMESGDATA];
};

ssize_t  mesg_send(int, struct mymesg *);
void     Mesg_send(int, struct mymesg *);
ssize_t  mesg_recv(int, struct mymesg *);
ssize_t  Mesg_recv(int, struct mymesg *);
  • server_main.c
#include    "svmsg.h"

void    server(int, int);

int
main(int argc, char **argv)
{
    int     readid, writeid;

    readid = Msgget(MQ_KEY1, SVMSG_MODE | IPC_CREAT);
    writeid = Msgget(MQ_KEY2, SVMSG_MODE | IPC_CREAT);

    server(readid, writeid);

    exit(0);
}
  • client_main.c
#include    "svmsg.h"

void    client(int, int);

int
main(int argc, char **argv)
{
    int     readid, writeid;

        /* 4assumes server has created the queues */
    writeid = Msgget(MQ_KEY1, 0);
    readid = Msgget(MQ_KEY2, 0);

    client(readid, writeid);

        /* 4now we can delete the queues */
    Msgctl(readid, IPC_RMID, NULL);
    Msgctl(writeid, IPC_RMID, NULL);

    exit(0);
}
  • mesg_send.c
/* include mesg_send */
#include    "mesg.h"

ssize_t
mesg_send(int id, struct mymesg *mptr)
{
    return(msgsnd(id, &(mptr->mesg_type), mptr->mesg_len, 0));
}
/* end mesg_send */

void
Mesg_send(int id, struct mymesg *mptr)
{
    ssize_t n;

    if ( (n = msgsnd(id, &(mptr->mesg_type), mptr->mesg_len, 0)) == -1)
        err_sys("mesg_send error");
}
  • mesg_recv.c
/* include mesg_recv */
#include    "mesg.h"

ssize_t
mesg_recv(int id, struct mymesg *mptr)
{
    ssize_t n;

    n = msgrcv(id, &(mptr->mesg_type), MAXMESGDATA, mptr->mesg_type, 0);
    mptr->mesg_len = n;     /* return #bytes of data */

    return(n);              /* -1 on error, 0 at EOF, else >0 */
}
/* end mesg_recv */

ssize_t
Mesg_recv(int id, struct mymesg *mptr)
{
    ssize_t n;

    if ( (n = mesg_recv(id, mptr)) == -1)
        err_sys("mesg_recv error");
    return(n);
}

猜你喜欢

转载自blog.csdn.net/qq_36337149/article/details/81304854