【Linux】消息隊列

一、消息隊列

1.消息隊列提供了一個從一個進程向另外一個進程發送一塊數據的方法。
2.每個數據塊都被認爲是有一個類型,接受者進程的數據塊可以有不同的類型值。
3.消息隊列也有管道一樣的不足,就是每個消息的最大長度是有上限的(MSGMAX),每個消息隊列的總的字節數是有上限的(MSGMNB),系統上消息隊列的總數也有一個上限(MSGMNI)。


IPC對象數據結構:
這裏寫圖片描述

消息隊列結構:
這裏寫圖片描述

二、消息隊列函數:

1.msgget函數:
這裏寫圖片描述
2.mstctl函數:
這裏寫圖片描述
3.msgsnd函數:
這裏寫圖片描述
這裏寫圖片描述
4.msgrcv函數:
這裏寫圖片描述
注:
這裏寫圖片描述


三、代碼示例

查看與刪除消息隊列的命令:
(1)查看已創建的消息隊列:
ipcs -q
(2)刪除已存在的消息隊列
ipcrm -q 163840(消息隊列的標識符) ( 刪除一個消息隊列 )
ipcrm -a (刪除所有創建了的消息隊列)

【comm.h】

#ifndef _COMM_H_
#define _COMM_H_

#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<string.h>

#define PATHNAME "."   //"."表示當前目錄
#define PROJ_ID 0x6666   //權限設置 6(文件類型)|6(擁有者權限rw-)|6(用戶組權限rw-)|6(其他的權限rw-)

#define SERVER_TYPE 1    //TYPE必須設置成一個大於0的數
#define CLIENT_TYPE 2

struct msgbuf{
    long mtype;
    char mtext[1024];
};

int createMsgQueue();   //創建消息隊列
int getMsgQueue();     //代開消息隊列
int destoryMsgQueue(int msgid);  //銷燬一個存在的消息隊列
int sendMsg(int msgid,int who,char* msg);   //向消息隊列發送信息
int recvMsg(int msgid,int recvType,char out[]);   //從消息隊列中讀取數據

#endif

【comm.c】

#include"comm.h"

//success -->(>0)  falied -->(-1)

static int commMsgQueue(int flags)
{
    key_t _key=ftok(PATHNAME,PROJ_ID);   //通過ftok獲取一個唯一標識符
    if(_key<0)
    {
        perror("fotk");
        return -1;
    }

    int msgid=msgget(_key,flags);
    if(msgid<0)
        perror("msgget");

    return msgid;
}
int createMsgQueue()
{
    return commMsgQueue(IPC_CREAT|IPC_EXCL|0666);  //IPC_CREAT如果存在,打開它,如果不存在創建一個;
                                                  //IPC_EXCL 如果消息隊列不存在,看不見,如果存在失敗。
}

int getMsgQueue()
{
    return commMsgQueue(IPC_CREAT);
}

int destoryMsgQueue(int msgid)
{
    if(msgctl(msgid,IPC_CREAT,NULL)<0)
    {
        perror("msgctl");
        return -1;
    }
    return 0;
}

int sendMsg(int msgid,int who,char* msg)
{
    struct msgbuf buf;
    buf.mtype=who;
    strcpy(buf.mtext,msg);

    if(msgsnd(msgid,(void *)&buf,sizeof(buf.mtext),0)<0)
    {
        perror("msgsnd");
        return -1;
    }
    return 0;
}
int recvMsg(int msgid,int recvType,char out[])
{
    struct msgbuf buf;
    if(msgrcv(msgid,(void*)&buf,sizeof(buf.mtext),recvType,0)<0)
    {
        perror("msgrcv");
        return -1;
    }
    strcpy(out,buf.mtext);
    return 0;
}

【server.c】

#include"comm.h"

int main()
{
    int msgid=createMsgQueue();

    char buf[1024];
    while(1)
    {
        buf[0]=0;
        recvMsg(msgid,CLIENT_TYPE,buf);   //從消息隊列中讀取數據
        printf("client# %s\n",buf);

        printf("Please Enter#");
        fflush(stdout);
        size_t s=read(0,buf,sizeof(buf));
        if(s>0)
        {
            buf[s-1]=0;
            sendMsg(msgid,SERVER_TYPE,buf);     //向消息隊列發送信息
            printf("send done,wait recv...\n");
        }
    }
    destoryMsgQueue(msgid);   //銷燬一個已存在的消息隊列
    return 0;
}

【client.c】

#include"comm.h"

int main()
{
    int msgid=getMsgQueue();

    char buf[1024];
    while(1)
    {
        buf[0]=0;
        printf("Please Enter# ");
        fflush(stdout);
        size_t s=read(0,buf,sizeof(buf));
        if(s>0)
        {
            buf[s-1]=0;
            sendMsg(msgid,CLIENT_TYPE,buf);
            printf("send done,wait recv...\n");
        }

        recvMsg(msgid,SERVER_TYPE,buf);
        printf("server# %s\n",buf);
    }
    return 0;
}
發佈了70 篇原創文章 · 獲贊 92 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章