1. 程式人生 > 其它 >Linux訊息佇列---程序之間通訊

Linux訊息佇列---程序之間通訊

技術標籤:linux系統程式設計學習

Linux訊息佇列—程序間通訊

訊息佇列

  1. 訊息佇列也是在記憶體中開闢的區域,有一定的大小限制
  2. 訊息佇列的通訊是將訊息打包放入訊息佇列中,其他程序可以從訊息佇列中提取訊息
  3. 當訊息佇列滿的時候傳送訊息函式可能阻塞(設定:0)
  4. 訊息結構中第一個必須是long型別,作為訊息型別(具體賦值自己定義)
  5. 訊息結構體中除了第一個long型別的資料,其他的都是訊息正文
  6. 訊息佇列建立後也不會隨程序銷燬,需要手動刪除
  7. 訊息佇列中一次只能傳送或接收1條訊息
  8. 如果想正確接收訊息,那麼傳送和接收訊息的結構體要一致
  9. 在訊息接收的時候並不是嚴格的先進先出,可以指明接受的訊息型別

int msgget(key_t key, int flag);

標頭檔案:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
功能 : 建立或開啟一個訊息佇列
引數 : key
flag :開啟訊息佇列的許可權
IPC_CREAT : 建立一個ipc物件
IPC_EXCL : 如果這個物件已經存在則返回errno = EEXIST
mode: 建立許可權
返回值 : 成功 返回一個訊息佇列id 失敗 -1

int msgsnd(int msqid, const void *msgp, size_t size, int flag); ----》 傳送訊息的時候記得要指明訊息型別

標頭檔案:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
功能: 向訊息佇列中存入訊息
引數: msgid
msgp : 指向要傳送的訊息
struct msgbuf{
long msgtype; //表明訊息的型別
char buf[64]; //訊息內容
};
size : 傳送訊息的正文大小 sizeof(struct msgbuf) - sizeof(long)
flag : IPC_NOWAIT 訊息沒有傳送完成函式也會立即返回。
0:直到傳送完成函式才返回
返回值 成功 返回0 失敗 -1

int msgrcv(int msgid, void* msgp, size_t size, long msgtype, int flag);
標頭檔案:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
功能 : 從訊息佇列中獲取一個訊息
引數 : msgid
msgp : 指向訊息結構體
size ; 接收的結構體正文大小 sizeof(struct msgbuf) - sizeof(long)
msgtype : 0:接收訊息佇列中第一個訊息。
大於0:接收訊息佇列中第一個型別為msgtyp的訊息.
小於0:接收訊息佇列中型別值不小於 msgtyp的絕對值 且型別值又最小的訊息。
flag : 0:若無訊息函式會一直阻塞
IPC_NOWAIT:若沒有訊息,程序會立即返回ENOMSG。
返回值 0 -1

int msgctl ( int msgqid, int cmd, struct msqid_ds *buf );
標頭檔案:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
功能 : 控制訊息佇列
引數 : msgid
cmd : 命令 (參照共享記憶體)
IPC_STAT:讀取訊息佇列的屬性,並將其儲存在buf指向的緩衝區中。
IPC_SET:設定訊息佇列的屬性。這個值取自buf引數。
IPC_RMID:從系統中刪除訊息佇列。
buf : 訊息佇列屬性結構體
返回值 成功:0 失敗:-1

檢視和刪除訊息佇列的命令:

ipcs -q //檢視訊息佇列的狀態
ipcrm -q id //刪除一個訊息佇列

下面就看看具體的例子:
檢視訊息佇列:
在這裡插入圖片描述

現在系統裡面不存在建立的訊息佇列,下面編寫兩個demon程式:

//msgqueuerecv.c
#include<stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <unistd.h>
#define ERROR -1
#define OK 0
#define MSGSIZE 128
typedef struct  msgbuf{
	long  msgtype;   //表明訊息的型別
	char buf[MSGSIZE];    //訊息內容
}S_MSGBUF;
int main(void){
    char *pkey="aaron";    //指定key值
    key_t key = *(int *)pkey;
    int msgid;
    S_MSGBUF sbuf;
    msgid=msgget(key,IPC_CREAT|0666);  //建立訊息佇列ID
    if(ERROR==msgid){
        printf("msgget error\n");
        return ERROR;
    }

    while(1){
        memset(&sbuf,0,sizeof(sbuf));
        sbuf.msgtype=1;
        msgrcv(msgid,&sbuf,MSGSIZE,sbuf.msgtype,0);  //接收訊息
        if(strncmp(sbuf.buf,"quit",4)==OK){
            break;
        }else{
            printf("%s\n",sbuf.buf);
        }
       // sleep(1);
    }

    int ret=msgctl(msgid,IPC_RMID,NULL);  //刪除訊息佇列
    if(ret==ERROR){
        printf("msgctl delete fail\n");
    }else{
        printf("bye bye\n");
    }

    return OK;
}
//msgqueuesend.c
#include<stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <unistd.h>
#define ERROR -1
#define OK 0
#define MSGSIZE 128
typedef struct  msgbuf{
	long  msgtype;   //表明訊息的型別
	char buf[MSGSIZE];    //訊息內容
}S_MSGBUF;
int main(void){
    char *pkey="aaron";  //指定key值
    key_t key = *(int *)pkey;
    int msgid;
    S_MSGBUF sbuf;
    msgid=msgget(key,IPC_CREAT|0666);  //建立訊息佇列ID
    if(ERROR==msgid){
        printf("msgget error\n");
        return ERROR;
    }

    while(1){
        memset(&sbuf,0,sizeof(sbuf));
        fgets(sbuf.buf,MSGSIZE,stdin);
        sbuf.msgtype=1;
        msgsnd(msgid,&sbuf,MSGSIZE,IPC_NOWAIT);  //傳送訊息
        if(strncmp(sbuf.buf,"quit",4)==OK){
            break;
        }
        sleep(1);
    }
    return OK;
}

編譯兩個程式:
在這裡插入圖片描述

執行msgqueuesend程式,然後檢視是否有新的訊息佇列建立:
在這裡插入圖片描述
有一個擁有者是book的訊息佇列被建立了,現在訊息佇列中的訊息數為0,我們寫幾個訊息看看是什麼效果
在這裡插入圖片描述
在這裡插入圖片描述

發現訊息佇列中的數字有了變化,我們分別寫了三條訊息,然後呢,訊息的位置顯示是3,我們建立的每個訊息佇列的大小為128位元組,然後3個就是384位元組。
那接下來,我們讀取佇列中的訊息,看看結果是什麼樣子:
在這裡插入圖片描述
在這裡插入圖片描述
訊息已經被讀出來了,並且列印了出來,然後再看看訊息佇列的數字,已經變為0了,以上就是兩個獨立的程序通過訊息佇列的方式,進行簡單的訊息互動傳遞。