• Linux IPC 消息队列


     管道和FIFO是字节流,没有消息边界。

    1. Posix 消息队列

    /* mq_open - open a message queue */
    #include <fcntl.h> /* For O_* constants */ #include <sys/stat.h> /* For mode constants */ #include <mqueue.h> mqd_t mq_open(const char *name, int oflag); mqd_t mq_open(const char *name, int oflag, mode_t mode, struct mq_attr *attr);
    /*  mq_send, mq_timedsend - send a message to a message queue */ #include
    <mqueue.h> int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio); #include <time.h> #include <mqueue.h> int mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned msg_prio, const struct timespec *abs_timeout);
    /* mq_receive, mq_timedreceive - receive a message from a message queue */ #include
    <mqueue.h> ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio); #include <time.h> #include <mqueue.h> ssize_t mq_timedreceive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio, const struct timespec *abs_timeout);
    /* mq_getattr, mq_setattr - get/set message queue attributes */
    #include <mqueue.h>
    int mq_getattr(mqd_t mqdes, struct mq_attr *attr); int mq_setattr(mqd_t mqdes, struct mq_attr *newattr, struct mq_attr *oldattr); struct mq_attr { long mq_flags; /* Flags: 0 or O_NONBLOCK */ long mq_maxmsg; /* Max. # of messages on queue */ long mq_msgsize; /* Max. message size (bytes) */ long mq_curmsgs; /* # of messages currently in queue */ };
    /* mq_notify - register for notification when a message is available */
    int mq_notify(mqd_t mqdes, const struct sigevent *sevp);

    /* mq_unlink - remove a message queue */
    int mq_unlink(const char *name); Link with
    -lrt.

    Posix消息队列注意事项

    1. mq_setattr只能修改mq_flags为阻塞或非阻塞,其他的参数只能通过mq_open在建立消息队列时指定

    2. mq_receive每次都返回队列中最高优先级的最早消息

    3. mq_notify支持注册一个信号或者线程,在一个消息被加入到一个空队列时发送信息或者激活线程(System V消息队列不提供类似的形式)

    2. System V 消息队列

    /* msgget - get a System V message queue identifier */
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    
    int msgget(key_t key, int msgflg);
    
    /* ftok - convert a pathname and a project identifier to a System V IPC key */
    #include <sys/types.h>
    #include <sys/ipc.h>
    
    key_t ftok(const char *pathname, int proj_id);
    
    /* msgrcv, msgsnd - System V message queue operations */
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    
    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);
    
    /* msgctl - System V message control operations */
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    
    int msgctl(int msqid, int cmd, struct msqid_ds *buf);
    
    struct msqid_ds {
                   struct ipc_perm msg_perm;     /* Ownership and permissions */
                   time_t          msg_stime;    /* Time of last msgsnd(2) */
                   time_t          msg_rtime;    /* Time of last msgrcv(2) */
                   time_t          msg_ctime;    /* Time of last change */
                   unsigned long   __msg_cbytes; /* Current number of bytes in queue (nonstandard) */
                   msgqnum_t       msg_qnum;     /* Current number of messages in queue */
                   msglen_t        msg_qbytes;   /* Maximum number of bytes allowed in queue */
                   pid_t           msg_lspid;    /* PID of last msgsnd(2) */
                   pid_t           msg_lrpid;    /* PID of last msgrcv(2) */
    };

    System V消息队列注意事项

    1. msgsnd的flag参数可以指定为IPC_NOWAIT。IPC_NOWAIT标志使得此次msgsnd操作为非阻塞:如果没有新消息的存放空间,函数立即返回一个EAGIN错误,出现这种情况的情形如下:

    a. 在该消息队列中已经有太多的字节(对应struct msqid_ds中的msg_qbytes)

    b. 在系统范围内存在太多的消息

    如果出现上述两个条件之一,且msgsnd未指定IPC_NOWAIT标志,那么调用线程被投入睡眠,直到:

    a. 具备存放新消息的空间

    b. 指定的消息队列被消除了(这种情况下msgsnd返回ERMID错误)

    c. 调用线程被某个捕获的信号中断(这种情况msgsnd返回EINTR错误)

     

    2. msgrcv的flag参数也可以指定为IPC_NOWAIT,还有另一个标志 MSG_NOERROR:当所接收的消息数据部分大于msgrcv的length参数,如果设置了MSG_NOERROR,数据被截断,msgrcv函数不会出错;如果没有设置该标志,msgrcv函数返回E2BIG错误。

     

    3. msgctl的cmd可以取值如下:

    IPC_RMID: 删除指定队列

    IPC_SET: 支持设置指定队列的 msgid_ds结构体中的 msg_prem.uid, msg_prem.gid, msg_prem.mode 和 msg_qbytes

    IPC_STAT: 返回指定队列的msgid_ds 结构

     

    4. system V 消息队列的限制

    可以查看proc/sys/kernel/文件夹下的msgmax  msgmni  msgmnb

    也可以通过ipcs  -l 命令查看:

    ubuntu: ipcs -l
    
    ------ Shared Memory Limits --------
    max number of segments = 4096
    max seg size (kbytes) = 32768
    max total shared memory (kbytes) = 8388608
    min seg size (bytes) = 1
    
    ------ Semaphore Limits --------
    max number of arrays = 128
    max semaphores per array = 250
    max semaphores system wide = 32000
    max ops per semop call = 32
    semaphore max value = 32767
    
    ------ Messages Limits --------
    max queues system wide = 1717                 系统范围内的消息队列最大数量:msgmni
    max size of message (bytes) = 8192            每个消息的最大字节数:msgmax
    default max size of queue (bytes) = 16384   每个消息队列上的最大字节数:msgmnb
  • 相关阅读:
    Java Servlet(十):JSTL核心标签库
    Java Servlet(九):转发请求与重定向请求区别
    Java tomcat启动失败(Servlet3.0 Web Project):A child container failed during start
    快速安装服务
    Java Servlet(八):EL自定义函数
    Java Servlet(七):JavaWeb MVC 操作(jdk7+tomcat7+eclipse)
    新版mysql(mysql-5.7.12-winx64)安装
    oracle之 oradebug 命令用法
    Linux 绑定双网卡
    Linux 之 NTP 服务 服务器
  • 原文地址:https://www.cnblogs.com/xiaokuang/p/4613363.html
Copyright © 2020-2023  润新知