• linux 消息队列


    消息队列是在两个进程间传递二进制数据的方法。每个数据块都有一个类型,接受方可以根据类型来有选择地接受数据,不需要像管道一样必须按照先进先出的顺序。

    linux消息队列有四个系统调用:msgget, msgsnd, msgrcv, msgctl

    msgget

           #include <sys/types.h>
           #include <sys/ipc.h>
           #include <sys/msg.h>
    
           int msgget(key_t key, int msgflg);

     

    创建/获取一个消息队列。key是唯一键值,标识一个全局唯一的消息队列。msgflg指定权限

    成功时返回一个正整数,是消息队列的标识符。失败返回-1,并设置errno

    msgsnd

    int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

     

    把一条消息添加到消息队列中。

    msqid 是 msgget 返回的标识符。

    msgp 指针指向一个准备发送的数据,必须使用这个结构体:

    /* Template for struct to be used as argument for `msgsnd' and `msgrcv'.  */
    struct msgbuf
      {
        __syscall_slong_t mtype;    /* type of received/sent message */
        char mtext[1];      /* text of the message */
      };

     

    mtype指定消息类型,必须是一个正整数。mtext是消息数据。

    参数msgsz是mtext的长度,这个值可以是0,表示没有数据

    参数msgflg 是控制msgsnd的行为。通常设置为 IPC_NOWAIT ,即是以非阻塞的方式发送消息。默认情况下,如果发送消息时,消息队列满了,则 msgsnd 将阻塞。如果 IPC_NOWAIT 被设置,则 msgsnd 将立刻返回并设置 erno 为 EAGAIN.

    成功时返回0,失败返回-1,并设置errno

    msgrcv

    ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
                          int msgflg);

    从消息队列中获取消息。

    msgp 是 struct msgbuf类型的指针,msgsz 指定消息数据部分的长度

    msgtyp 指定接受哪种类型的消息:

    msgtyp 定于0, 读取消息队列中第一个消息

    msgtyp 大于0, 读取消息队列中第一个类型为msgtyp的消息

    msgtyp 小于0, 读取消息队列中第一个类型值比msgtyp的绝对值小的消息。

    参数msgflg 控制msgrcv的行为。可取下列值按位或运算:

    IPC_NOWAIT。如果消息队列没有消息,则 msgrcv 调用立即返回并设置errno 为 ENOMSG

    MSG_EXCEPT. 如果msgtyp大于0, 接受消息队列中第一个不是msgtyp类型的消息

    MSG_NOERROR。如果消息数据部分长度超过了 msgsz,将它截断。

    函数成功时,返回接受的mtext长度。失败返回-1,并设置errno

    msgctl

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

      设置消息队列的属性。

    struct msqid_ds 结构体定义为:

    /* Obsolete, used only for backwards compatibility and libc5 compiles */
    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 */
    };

     

    msqid 是消息队列标识符。cmd 指定要执行的命令,其中

    IPC_STAT.将消息队列关联的内核数据结构复制到 buf 中

    IPC_RMID.立即删除消息队列标识符。唤醒所有等待读消息和写消息的进程(这些调用立即返回,并设置errno为 EIDRM)

    还有其他命令,这里没有全部列举

    函数失败返回-1

     

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <sys/wait.h>
    #include <sys/msg.h>
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <unistd.h>
    
    
    struct msgbuf_
    {
        long mtype;
        char mtext[64];
    };
    
    int main()
    {
        int msgid = msgget(0, 0666);
    
        pid_t pid = fork();
        if (pid > 0)
        {
            struct msgbuf_ bufsnd = {8, "send data type 8"};
            if (-1 == msgsnd(msgid, &bufsnd, strlen(bufsnd.mtext), 0))
            {
                fprintf(stderr, "msgsnd: %d, %s
    ", errno, strerror(errno));
                exit(1);
            }
    
            bufsnd.mtype = 9;
            strcpy(bufsnd.mtext, "this type is 9");
            if (-1 == msgsnd(msgid, &bufsnd, strlen(bufsnd.mtext), 0))
            {
                fprintf(stderr, "msgsnd: %d, %s
    ", errno, strerror(errno));
                exit(1);
            }
    
            waitpid(pid, NULL, 0);
            if (-1 == msgctl(msgid, IPC_RMID, NULL))
            {
                fprintf(stderr, "msgctl: %d, %s
    ", errno, strerror(errno));
                exit(1);
            }
        }
        else if (0 == pid)
        {
            struct msgbuf_ bufrcv;
    
            int lenrcv = msgrcv(msgid, &bufrcv, 64, 9, 0);
            if (lenrcv < 0)
            {
                fprintf(stderr, "msgrcv: %d, %s
    ", errno, strerror(errno));
                exit(1);
            }
            printf("recv len=%d, type=%ld: %s
    ", lenrcv, bufrcv.mtype, bufrcv.mtext);
    
            memset(&bufrcv, 0, sizeof(bufrcv));
            lenrcv = msgrcv(msgid, &bufrcv, 64, 8, 0);
            if (lenrcv < 0)
            {
                fprintf(stderr, "msgrcv: %d, %s
    ", errno, strerror(errno));
                exit(1);
            }
            printf("recv len=%d, type=%ld: %s
    ", lenrcv, bufrcv.mtype, bufrcv.mtext);
        }
    
        return 0;
    }

     

  • 相关阅读:
    生成token和获取token
    python异常处理
    获取文件路径
    批量导出和批量安装第三方模块
    python操作从数据库中获取数据的接口
    centos中开机时如何自启动samba服务器
    MSSQL 创建自定义异常
    MSSQL 生成拼音码
    MSSQL FOR MXL PATH 运用(转载)
    MSSQL旋转和反旋转的例子
  • 原文地址:https://www.cnblogs.com/zuofaqi/p/9651345.html
Copyright © 2020-2023  润新知