天天看點

Linux程序間通信---消息隊列1. 消息隊列

1. 消息隊列

消息隊列就是一個連結清單, 存于核心之中

特點 :

  • 具有特定的格式以及優先級
  • 消息讀取之後, 仍然存在消息隊列中 (不同于管道通信)
  • 實作消息的随機查詢, 可以按照類型查詢
  • 可以實作雙方互相通訊(不同于管道通信)

相關API函數 :

#include <sys/msg.h>
//建立/擷取消息隊列  成功傳回id  失敗-1
int msgget(key_t key, int msgflg);
//第一個參數: 索引值,以此來查找隊列; 第二個參數:打開方式,一般設定為 IPC_CREAT|0777

//發送消息  成功傳回0 失敗傳回-1
int msgsnd(int msgId, const void *msgp, size_t msgsz, int msgflg);
//第一個參數: 消息隊列id号,第二個參數:要發送的内容, 
//第三個參數: 發送消息的大小,第四個參數通常采用預設方式,即設定為0

//接收消息
ssize_t msgrcv(int msgId, void* msgp, size_t msgsz, long msqtyp, int msgflg);
//第二個參數:讀取消息的緩存區, 第三個參數:緩存區的大小, 
//第四個參數:消息的類型(一般為整型),第五個參數通常采用預設接收方式,即設定為0

//控制消息隊列,一般用于删除  成功傳回0 失敗傳回-1
int msgctl(int msgid, int cmd, struct msgid_ds *buf);
//第二個參數: 常用模式為 IPC_RMID(移除建立的隊列), 
           
注: 确定key值時,通常采用 ftok() 函數進行确定, 并且在使用 msgsnd()和msgget() 函數時應線構造一個結構體
//key值的确定
#include <sys/types.h>
#include <sys/ipc.h>

key_t ftok(const char *pathname, int proj_id);
//第一個參數: 指定的檔案名  第二個參數: 子序号, 通常取 1-255整型數

//msgsnd()和msgget() 函數時應線構造一個結構體
struct msgbuf
{
	long mtype;
	char mtext[128];
};
           

具體執行個體代碼 :

①從隊列擷取資訊

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

struct msgbuf     //先定義結構體
{
	long mtype;            //消息隊列的類型
	char mtext[128];       //消息隊列内容
};

int main()
{
	int msgId;
	struct msgbuf readBuf;	

	key_t key;
	key = ftok(".", 1);                     //通過ftok()擷取key值

	msgId = msgget(key, IPC_CREAT|0777);    //建立/擷取消息隊列的id号
	if(msgId == -1)                         //判斷是否擷取成功
	{
		printf("get que failure\n");	
	}	

	//從消息隊列中擷取資訊  
	msgrcv(msgId, &readBuf, sizeof(readBuf.mtext),888,0);  //888表示消息隊列的信号, 0表示預設讀取方式
	printf("get message: %s from que\n",readBuf.mtext);

	//擷取資訊後,進行回報,也就是可以寫資訊到隊列
	struct msgbuf sendBuf = {999,"thank you"};
	msgsnd(msgId, &sendBuf, strlen(sendBuf.mtext),0);
	
	msgctl(msgId, IPC_RMID, NULL);   //删除建立的隊列,防占用記憶體

	return 0;
}
           

②發送資訊到隊列

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

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

int main()
{
	int msgId;
	struct msgbuf sendBuf = {888, "hello world"};	//定義發送的類型以及内容

	key_t key;
	key = ftok(".", 1);                             //通過ftok()擷取key值

	msgId = msgget(key, IPC_CREAT|0777);
	if(msgId == -1)
	{
		printf("get que failure\n");	
	}	

	//發送資訊到隊列
	msgsnd(msgId, &sendBuf, strlen(sendBuf.mtext),0);  //0表示預設不堵塞
	
	//定義readBuf 進行接收來自隊列的回報資訊
	struct msgbuf readBuf;

	msgrcv(msgId, &readBuf, sizeof(readBuf.mtext),999,0); //999要和上端代碼一緻
	printf("return  %s from que\n",readBuf.mtext);
	
	msgctl(msgId, IPC_RMID, NULL);

	return 0;
}
           

兩段代碼可以實作不同程序間的通信,而且可以滿足互相通訊(即可以進行回報以及接收回報)

注: 發送資訊和讀取資訊時,應保證 key 值相同, 以及消息類型 type 相同

繼續閱讀