Linux进程间通信(IPC)-------消息队列

消息队列是进程间通信的一种方法,他有两个操作,一个进程来发送消息(也就是向内存中写入数据),另一个是获取消息(也就是另外一个进程在内存中读取数据)


下面来看消息队列的

创建,写入,读取等需要用到的函数

创建:msgget((key_t) key,int msgflg)          其中(key_t)key的话,我在管道,共享内存中都写过,key值没什么要求,大于零的32位整数就行,并且它是用来区分和别的消息队列的,所以key值别和其他消息队列重复就行

msgflg是个标志位,一般取IPC_CREAT :
如果消息队列对象不存在,则创建之,否则则进行打开操作;下面附上帮助手册

写入数据(发送消息):int msgsnd ( int msqid, struct msgbuf *msgp, int msgsz, int msgflg )

其中参数msqid就是上述创建的消息队列的id   

struct msgbuf *msgp这玩意就是结构体指针  该结构体就是消息体

msgsz就是消息体的大小

msgflg一般默认为0

读取数据(读取消息):size_t msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz, long type,int msgflg)

smqid就是创建的消息队列id  

struct msgbuf *msgp  结构体指针

size_t msgsz 就是存消息的大小

long type  就是消息的类型

int msgflg标志位,一般默认0

下面附上帮助手册:

上述那个结构体struct msgbuf就是消息体,type用来区分消息,你发送或者获取消息的类型,其类型必须是long

下面的char 的数组就是发送或者获取消息的最大内存(这里有一点要提一下,就是上面说到msgsnd中消息体大小,只算这个结构体中的char数组,龙不计算在内)

 下面来进行代码实现:发送端的编写

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/msg.h>

struct message
{
    long type;
    char buff[32];
};
 
int main()
{
    int msgid = msgget((key_t)1234,IPC_CREAT|0600);//0600是权限
    assert(msgid != -1);

    struct message me;
    me.type = 1;  //这块将消息类型定义为1
    strcpy(me.buff,"hello"); //向buff中写入hello

    msgsnd(msgid,(void*)&me,32,0); //向消息队列发送消息
 
}

对获取端的编写:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/msg.h>

struct message
{
    long type;
    char buff[32];
};
 
int main()
{
    int msgid = msgget((key_t)1234,IPC_CREAT|0600);//0600是权限
    assert(msgid != -1);

    struct message me;
    msgrcv(msgid,&me,32,1,0); //消息存储最多32  1是type类型  0是默认标志位
    printf("read msg:%s \n",me.buff);
 
}

下面附上运行截图(其中xiaoxi是发送消息,haha是获取消息)  那个已用字节数应该是32   因为xiaoxi这个发送端  我刚刚运行了下 ,所以叠加起来就是64

 然后ipcs -q是查看消息队列的使用情况的,键下面的4d2就是1234转换为16进制的值

然后我们将发送消息的消息的类型值由1改为2,获取端代码不变,我们再来看一下结果

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/msg.h>

struct message
{
    long type;
    char buff[32];
};
 
int main()
{
    int msgid = msgget((key_t)1234,IPC_CREAT|0600);//0600是权限
    assert(msgid != -1);

    struct message me;
    me.type = 2;  //这块将消息类型定义为1
    strcpy(me.buff,"hello"); //向buff中写入hello

    msgsnd(msgid,(void*)&me,32,0); //向消息队列发送消息
 
}

然后我们就会发现,获取端获取不了数据,一直在那块阻塞,因为类型不对,写入端写的是2类型,读取的是1类型

 因为类型不对,写入端写的是2类型,读取的是1类型,所以肯定是读取不了的,那么有没有什么办法让它可以读取呢,最笨的办法就是将读取端的消息类型改为2,这也是最常规的办法,下面我来弄一个很有意思的方法:

        将读取端msgrcv的消息类型改为0,也就是默认类型,这样的话,它就会接受所有的数据类型,下面我们来试一下:只改获取端,发送端代码不该,还是2类型

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/msg.h>

struct message
{
    long type;
    char buff[32];
};
 
int main()
{
    int msgid = msgget((key_t)1234,IPC_CREAT|0600);//0600是权限
    assert(msgid != -1);

    struct message me;
    msgrcv(msgid,&me,32,0,0); //消息存储最多32  1是type类型  0是默认标志位
    printf("read msg:%s \n",me.buff);
 
}

附上运行截图:

 然后删除消息队列msgctl(msgid,IPC_RMID,NULL)

将该代码写到获取端的末尾就好!

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/msg.h>

struct message
{
    long type;
    char buff[32];
};
 
int main()
{
    int msgid = msgget((key_t)1234,IPC_CREAT|0600);//0600是权限
    assert(msgid != -1);

    struct message me;
    msgrcv(msgid,&me,32,0,0); //消息存储最多32  1是type类型  0是默认标志位
    printf("read msg:%s \n",me.buff);
    
    if(msgctl(msgid,IPC_RMID,NULL) == -1)   //这块msgctl中的那个NULL参数还没搞明白  下次课过去问一下老师在评论区补一下
    {
        printf("delete error");
    }
 
}

这样执行下来就可以在程序执行完成之后,删除消息队列!

“加油呀  兄弟们  BAT  我来了”

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值