天天看點

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

繼續閱讀