linux消息队列

创建
创建一个新的或打开一个已经存在的消息队列

int msgget(key_t key, int msgflg);

key:消息队列关联的键
msgflg:
IPC_CREAT如果内核中没有此队列,则创建
IPC_EXCL和IPC_CREAT一起使用时,如果队列已经存在,则创建失败
返回值:消息队列标识值

写入/读取
写入、读取消息队列

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);

struct msgbuf
{
    long mtype;       /* message type, must be > 0 */
    char mtext[1];    /* message data */
};

msgp:指向msgbuf的指针
msgtyp:消息类型
msgtyp等于0,返回队列的最早的一个消息
msgtyp大于0,返回其类型为mtype的第一个消息
msgtyp小于0,返回其类型小于或等于mtype参数的绝对值的最小的一个消息
msgflg:
IPC_NOWAIT,如果消息队列为空,则返回ENOMSG;如果不指定这个参数,那么进程将被阻塞直到函数可以从队列中得到符合条件的消息为止
MSG_EXCEPT,返回队列中第一个类型不为msgtyp的消息
MSG_NOERROR,如果函数取得的消息长度大于msgsz,将只返回msgsz 长度的信息,剩下的部分被丢弃了;如果不指定这个参数,E2BIG 将被返回,而消息则留在队列中不被取出

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) */
};

struct ipc_perm
{
    key_t          __key;       /* Key supplied to msgget(2) */
    uid_t          uid;         /* Effective UID of owner */
    gid_t          gid;         /* Effective GID of owner */
    uid_t          cuid;        /* Effective UID of creator */
    gid_t          cgid;        /* Effective GID of creator */
    unsigned short mode;        /* Permissions */
    unsigned short __seq;       /* Sequence number */
};

cmd:
IPC_STAT,读取消息队列的数据结构msqid_ds
IPC_SET,设置消息队列的数据结构msqid_ds
IPC_RMID,从系统内核中移除消息队列

举例

struct msgbuf
{
    long mtype;       /* message type, must be > 0 */
    char mtext[1024]; /* message data */
};

int msqid = msgget((key_t)123, IPC_CREAT);
if(msqid < 0)
{
    perror("msgget.");
    return msqid;
}

struct msgbuf sbuf = {0};
sbuf.mtype = 1; //设置类型
char *text = "hello furong."; //填写数据
memcpy(sbuf.mtext, text, strlen(text));

if(fork() == 0)
{
    while(1)
    {
        if(msgsnd(msqid, &sbuf, sizeof(struct msgbuf), IPC_NOWAIT) < 0)
        {
            perror("msgsnd.");
        }
        sleep(1);
    }
}   

struct msgbuf rbuf = {0};
while(1)
{   
    memset(&rbuf, 0, sizeof(rbuf));
    if(msgrcv(msqid, &rbuf, sizeof(struct msgbuf), 0, 0) < 0)
    {
        perror("msgrcv.");
        sleep(1);
    }
    puts(rbuf.mtext);
}

msgctl(msqid, IPC_RMID, 0);

命令

# ipcs -q //消息队列
posted @   thomas_blog  阅读(95)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示