Linux进程间通信4——消息队列

目录

1.原理

2.消息队列的系统调用

2.1 msgget

2.2 msgsnd

2.3 msgrcv

2.4 msgctl

3.消息队列的使用——代码演示

4.结论


1.原理

2.消息队列的系统调用

2.1 msgget

用于创建或者获取一个消息队列。成功返回消息队列ID,失败返回-1。

int msgget(key_t key,int msqflg);

msqflg:IPC_CREAT

 

2.2 msgsnd

用于发送一条消息。成功返回0,失败返回-1。

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

msqid:消息队列的id,因为系统中可能有多个消息队列,这id指明往哪个消息队列中添加数据;

msqp:往消息队列中添加的结构体,消息结构为:

struct msgbuf
{
    long mtype;//消息类型,必须大于0(或者说>=1,0代表顺位接收),长整型,比如图中的1,2
    char mtext[1];//消息数据,用户自己定义,可以是任何类型;这里存放消息数据
};

msqsz:指定mtext中有效数据的长度。注意:仅仅指接收的数据的大小,不包含消息类型的大小;

msqflg:标志位,一般设置为0,可以设置IPC_NOWAIT,比如消息队列满了,是阻塞还是失败返回呢?给0代表消息满了自动阻塞,设置IPC_NOWAIT意思是当整个消息队列满的时候会立即返回(no wait),返回一个失败而已。

2.3 msgrcv

用来接收一条消息,成功返回mtext中接收到的数据长度,失败返回-1。

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

msgp:接收消息的结构体,一般约定好,写入什么,接收什么结构体。

msgsz:接收消息的大小,大于等于发送的消息大小,一般和发送的消息大小一样。

msgtyp:指定接收的消息类型(图中的1和2),类型可以为0,为0表示不区分消息类型,按顺位接收消息。

msgflg:一般设置为0,可以设置为IPC_NOWAIT。设置为IPC_NOWAIT,意思是当整个消息队列空的时候会立即返回(no wait),返回一个失败而已;设置为0,意思是当整个消息队列空的时候会阻塞。

2.4 msgctl

用于控制消息队列,也就是对消息队列做一个控制,可以设置消息队列,也可以移除消息队列;成功返回0,失败返回-1。

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

cmd:IPC_RMID

buf:设置或者获取消息队列需要的一个结构体,如果删除就直接给一个NULL。

注:当创建一个消息队列的时候,只要不移除这个消息队列,它就会一直在,除非重启系统。

或者人为删除:ipcrm -q id

3.消息队列的使用——代码演示

进程a发送一条消息,进程b读取消息。

//a.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/msg.h>
#include <string.h>
struct mess
{
    long type;
    char buff[128];
};

int main()
{
    int msgid=msgget((key_t)1234,IPC_CREAT|0600);
    assert(msgid!=-1);

    struct mess dt; 
    dt.type=1;
    strcpy(dt.buff,"hello1");
    msgsnd(msgid,&dt,128,0);
    exit(0);
}
//b.c
include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/msg.h>
#include <string.h>
struct mess
{
    long type;
    char buff[128];
};

int main()
{
    int msgid=msgget((key_t)1234,IPC_CREAT|0600);
    assert(msgid!=-1);

    struct mess dt; 
    msgrcv(msgid,&dt,128,1,0);
    printf("read mess:%s\n",dt.buff);

    exit(0);
}

运行结果:

4.结论

1)没有0号消息,0表示顺位接收,不管什么类型的消息都接收,因为没有0号消息,只有>=1的消息。

2)可以使用ipcrm删除队列,也可以在程序中删除。

方法一:

查看命令:ipcs  -q/-m/-s  

删除命令:ipcrm  -q/-m/-s  id

方法二:

msgctl(msgid,IPC_RMID,NULL);

3)如果设置成IPC_NOWAIT,没有消息不等待

if(msgrcv(msgid,&dt,128,1,IPC_NOWAIT)==-1)
{
    printf("no mess\n");
}
else
{
    printf("read:%s\n",dt.buff);
}

修改后b.c代码:

//b.c
include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/msg.h>
#include <string.h>
struct mess
{
    long type;
    char buff[128];
};

int main()
{
    int msgid=msgget((key_t)1234,IPC_CREAT|0600);
    assert(msgid!=-1);

    struct mess dt; 
    if(msgrcv(msgid,&dt,128,1,IPC_NOWAIT)==-1)
    {
        printf("no mess\n");
    }
    else
    {
        printf("read:%s\n",dt.buff);
    }

    exit(0);
}

修改后运行结果: 

4)消息队列在内存中创建。 

  • 18
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值