• System V消息队列


    1. 概述

    System V消息队列使用消息队列标识符标识,和Posix消息队列一样,发送消息和接收消息的线程(进程)是相互独立、互不依赖的。
    对于系统中的每个消息队列,内核维护一个定义在sys/msg.h头文件中的结构,其中带注释的是我们需要关注的成员变量。

    struct msqid_ds
    {
        struct ipc_perm msg_perm;
        struct msg     *msg_first; //指向队列中第一条消息
        struct msg     *msg_last;  //指向队列中最后一条消息
        msglen_t       msg_cbytes; //消息队列当前第几个字节
        msgqnum_t      msg_qnum;   //消息队列当前第几条消息
        msglen_t       msg_qbytes; //消息队列允许的最大字节数,仅针对消息数据,不包括与每个消息关联的长整型消息类型
        pid_t          msg_lspid;
        pid_t          msg_lrpid;
        time_t         msg_stime;a
        time_t         msg_rtime;
        time_t         msg_ctime;
    };
    

    2. 消息队列API

    msgget

    msgget用于创建一个新的消息队列或访问一个已存在的消息队列,参数key和oflag的含义及使用方法和semget一样,不再赘述。

    //成功返回消息队列标识符,失败返回-1
    int msgget(key_t key, int oflag);
    

    msgsnd

    msgsnd用于向消息队列中添加一条消息。

    //成功返回0,失败返回-1
    int msgsnd(int msqid, const void *ptr, size_t length, int flag);
    

    参数说明:

    • msqid是msgget返回的标识符
    • ptr是一个由应用程序按如下模板定义的struct sembuf结构指针,只要保证第一个成员变量是long type即可,其后的数据部分可根据需要任意扩展
    struct msgbuf
    {
        long mtype;       /* message type, must be > 0 */
        char mtext[1];    /* message data */
    };
    
    • length是待发送消息的长度,即消息类型之后的用户自定义数据的长度,该长度可以是0
    • flag可以是0或者IPC_NOWAIT,一般设为0

    msgrcv

    msgrcv用于从消息队列中取出一条消息。

    //成功返回实际读入缓冲区的数据长度,失败返回-1
    int msgrcv(int msqid, void *ptr, size_t length, long type, int flag);
    

    参数说明:

    • msqid是msgget返回的标识符
    • ptr指向数据接收缓冲区,它应该和msgsnd的ptr具有同样的struct sembuf结构
    • length为缓冲区大小
    • type用于指定希望从消息队列中读出什么样的消息
    • flag可以是0、IPC_NOWAIT或MSG_NOERROR,一般设为0

    msgrcv第四个参数type用于指定希望从消息队列中读出什么样的消息,假设有消息队列中有三条消息:

    • 第一条消息的类型为100,长度为1
    • 第二条消息的类型为200,长度为2
    • 第二条消息的类型为300,长度为3

    那么:

    • type = 0:返回队列中第一个消息
    • type > 0:返回消息类型等于type的第一个消息
    • type < 0:返回消息类型 <= abs(type)的消息中类型值最小的第一个消息

    msgctl

    msgctl提供在一个消息队列上的各种控制操作。

    //成功返回0,失败返回-1
    int msgctl(int msqid, int cmd, struct msqid_ds *buf);
    

    msgctl支持三个cmd命令:

    • IPC_RMID:从系统中删除由msqid指定的消息队列,此时第三个参数被忽略,设为NULL即可
    • IPC_STAT:通过buf参数返回由msqid指定消息队列对应的msqid_ds结构
    • IPC_SET:通过buf参数返回由msqid指定消息队列对应的msqid_ds结构,但仅设置以下4个成员:msg_perm.uid、msg_perm.gid、msg_perm.mode和msg_perm.qbytes

    3. 简单的程序

    代码实现

    common.h

    #ifndef _COMMON_H_
    #define _COMMON_H_
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    
    #define FTOK_FILE          "/home/delphi/ftok.file"
    #define FTOK_ID            1
    
    #define MSG_RD_PERMISSION  0444
    #define MSG_WR_PERMISSION  0222
    #define MSG_RW_PERMISSION  (MSG_RD_PERMISSION | MSG_WR_PERMISSION)
    
    #define MAX_MSG_LEN        (8192 + sizeof(long))
    
    struct msgbuf
    {
        long type;
        char *data;
    };
    
    #endif
    

    msgcreate.c

    #include "common.h"
    
    int main()
    {
        key_t key = ftok(FTOK_FILE, FTOK_ID);
        int oflag = IPC_CREAT | MSG_RW_PERMISSION;
        int msgid = msgget(key, oflag);
    
        if (msgid >= 0)
        {
            printf("msgget create success, msgid = %d
    ", msgid);
        }
    
        return 0;
    }
    

    msgsnd.c

    #include "common.h"
    
    int main(int argc, char **argv)
    {
        int msgid;
        int msglen;
        long msgtype;
        struct msgbuf *msg;
    
        msgid   = msgget(ftok(FTOK_FILE, FTOK_ID), MSG_WR_PERMISSION);
        msglen  = atoi(argv[1]);
        msgtype = atol(argv[2]);
    
        msg = (struct msgbuf *)calloc(sizeof(long) + msglen, sizeof(char));
        msg->type = msgtype;
    
        msgsnd(msgid, msg, msglen, 0);
    
        return 0;
    }
    

    msgrcv.c

    #include "common.h"
    
    int main(int argc, char **argv)
    {
        int msgid;
        int rcvlen;
        long msgtype;
        struct msgbuf *msg;
    
        msgid   = msgget(ftok(FTOK_FILE, FTOK_ID), MSG_RD_PERMISSION);
        msgtype = atol(argv[1]);
        msg = (struct msgbuf *)calloc(MAX_MSG_LEN, 1);
    
        rcvlen = msgrcv(msgid, msg, MAX_MSG_LEN, msgtype, 0);
        printf("read %d bytes, type = %ld
    ", rcvlen, msg->type);
    
        return 0;
    }
    

    msgrmid.c

    #include "common.h"
    
    int main(int argc, char **argv)
    {
        int msgid = msgget(ftok(FTOK_FILE, FTOK_ID), 0);
        msgctl(msgid, IPC_RMID, 0);
    
        return 0;
    }
    

    代码测试

  • 相关阅读:
    浅谈线段树
    并查集最简单讲解
    mysql索引原理深度解析
    算法、数据结构可视化
    php算法题---对称的二叉树
    php算法题---连续子数组的最大和
    Jsoup一个简短的引论——采用Java抓取网页数据
    宏定义详细信息
    解决java.sql.SQLException: ORA-01789: query block has incorrect number of result columns
    BZOJ 2435 NOI2011 道路建设 BFS/DFS
  • 原文地址:https://www.cnblogs.com/songhe364826110/p/11546021.html
Copyright © 2020-2023  润新知