linux进程间通信(六)----消息队列篇

一 what
消息队列也是进程间通信的一种通信方式,在内核中创建一个消息队列对象,不同的进程中,通过msgid来访问这个消息队列实现进程间通信

   |---|            |---|
   | A |            | B |
   |---|            |---|

------------------------------------

        |-------------|
        |             |    消息队列
        |-------------|

-------------------------------------

之前在介绍管道的时候,管道也是一个队列,它是一个顺序队列,那么这个队列和消息队列有什么区别呢?
消息队列是一个链式队列
相关函数

1. 创建或者打开消息队列的函数 msgget
    所需头文件:
           #include <sys/types.h>
           #include <sys/ipc.h>
           #include <sys/msg.h>
    原型: int msgget(key_t key, int flag)
    参数: key 和消息队列关联的key值
           flag 消息队列的访问权限
    返回值: 成功,消息队列ID,出错 -1
2. 关闭: msgctl
    原型: int msgctl(int msgqid, int cmd, struct msqid_ds *buf)
    参数: msgqid 消息队列ID
           cmd IPC_STAT 读取消息队列的属性,并将其保存在buf指向的缓冲区中
               IPC_SET  设置消息队列的属性,这个值取自buf参数
               IPC_RMID 从系统中删除消息队列
           buf 消息缓冲区
    返回值: 成功 0,出错 -1
3. 发送: msgsnd
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
    原型: int msgsnd(int msgqid, const void *msgp, size_t size, int flag)
    参数: msgqid 消息队列ID
           msgp 指向消息的指针,常用消息结构msgbuf如下
           struct msgbuf {
               long mtype;        //消息类型
               char mtext[N];     //消息正文
           };
           size 消息正文的字节数
           flag IPC_NOWAIT 消息没有发送完成也会立即返回
                0: 直到发送完成函数才会返回
    返回值: 成功 0,出错 -1
4. 读取: msgrcv
    原型: int msgrcv(int msgqid, void *msgp, size_t size, long msgtype, int flag)
    参数: msgqid 消息队列ID
           msgp 接收消息的缓冲区
           size 要接收消息的字节数
           msgtype  0 接收消息队列中第一个消息
                    大于0 接收消息队列中第一个类型为msgtype的消息
                    小于0 接收消息队列中类型值不大于msgtype的绝对值且类型值又最小的消息
           flag IPC_NOWAIT 没有消息,会立即返回
                0: 若无消息则会一直阻塞
                
    返回值: 成功 接收消息的长度,出错 -1

二 how

  1. 创建消息队列
#include "stdio.h"
#include "stdlib.h"
#include <unistd.h>
#include "sys/types.h"
#include <sys/msg.h>
#include "signal.h"
#include "string.h"

int main(int argc, char *argv[])
{
    int msgid;

    msgid = msgget(IPC_PRIVATE, 0777);
    if (msgid < 0) {
        printf("create msg queue fail\n");
        return -1;
    }
    printf("create msg queue sucess, msgid = %d\n", msgid);
    system("ipcs -q");

    return 0;
}
  1. 利用消息队列实现进程间通信
    发送函数
#include "stdio.h"
#include "stdlib.h"
#include <unistd.h>
#include "sys/types.h"
#include <sys/msg.h>
#include "signal.h"
#include "string.h"

struct msgbuf {
    long type;        //消息类型
    char voltage[124];     //消息正文
    char ID[4];
};

int main(int argc, char *argv[])
{
    int msgid, readret, key;
    struct msgbuf sendbuf;

    key = ftok("./a.c", 'a');
    if (key < 0){
        printf("create key fail\n");
        return -1;
    }
    msgid = msgget(key, IPC_CREAT|0777);
    if (msgid < 0) {
        printf("create msg queue fail\n");
        return -1;
    }
    printf("create msg queue sucess, msgid = %d\n", msgid);
    system("ipcs -q");

    // write message queue
    sendbuf.type = 100;
    while(1) {
        memset(sendbuf.voltage, 0, 124);  //clear send buffer
        printf("please input message:\n");
        fgets(sendbuf.voltage, 124, stdin);
        //start write msg to msg queue
        msgsnd(msgid, (void *)&sendbuf, strlen(sendbuf.voltage), 0);
    }

    return 0;
}

接收函数

#include "stdio.h"
#include "stdlib.h"
#include <unistd.h>
#include "sys/types.h"
#include <sys/msg.h>
#include "signal.h"
#include "string.h"

struct msgbuf {
    long type;        //消息类型
    char voltage[124];     //消息正文
    char ID[4];
};

int main(int argc, char *argv[])
{
    int msgid, key;
    struct msgbuf readbuf;

    key = ftok("./a.c", 'a');
    if (key < 0){
        printf("create key fail\n");
        return -1;
    }
    msgid = msgget(key, IPC_CREAT|0777);
    if (msgid < 0) {
        printf("create msg queue fail\n");
        return -1;
    }
    printf("create msg queue sucess, msgid = %d\n", msgid);
    system("ipcs -q");

    // read message queue
    while(1) {
        memset(readbuf.voltage, 0, 124);  //clear recv buffer
        //start read msg to msg queue
        msgrcv(msgid, (void *)&readbuf, 124, 100, 0);
        printf("recv data from message queue:%s", readbuf.voltage);
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值