Linux(高級編程)7————進程間通信3(消息隊列)

1.消息隊列什麼?
首先我們在學習數據結構後應該對隊列有了一個確切的理解,那麼在Linux下進程間通信(System V進程間通信)就有這麼一種機制。**消息隊列概念:**也叫報文隊列,其實就是一個消息的鏈表,發送的數據就是帶有類型的數據塊。
2.消息隊列特性:
1.消息隊列是操作系統在內核爲我們創建的一個隊列。
2.數據傳輸:用戶組織一個帶有類型的數據塊,添加到隊列中,其他進程從隊列中讀取特定類型的數據。
3.消息隊列是全雙工(可讀可寫)。關於全雙工對照着半雙工去理解即可。
4.消息隊列的生命週期隨內核。
3.消息隊列的操作步驟:
1.創建/打開消息隊列。
2.發送數據/接收數據
3.釋放消息隊列。
4.消息隊列各步驟函數原型:

  • 創建/或打開消息隊列:
int msgget(key_t key, int msgflg);

參數:
key:內核中消息隊列的標識。
msgflg:IPC_CREAT 不存在時創建消息隊列,存在時則打開。
IPC_EXCL與IPC_CREAT同用時,若存在則報錯。
mode權限。
返回值:成功時返回消息隊列句柄;失敗時返回-1;
**注意:**key可以通過函數ftok生成
ftok函數原型:

 key_t ftok(const char *pathname, int proj_id);

ftok通過文件的inode節點號與proj_id計算得到一個key值。不過這樣會存在一個缺點:當這個文件被刪除或丟失的時候,這個消息隊列再通過這樣的方式就有可能找不到了。

  • 發送消息:
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

參數:
msqid:操作句柄msgget返回值。
msgp:結構體masgbuf,用戶自定義,描述msg類型、以及msg正文。
msgsz:發送數據的大小即就是sizeof(mtext)大小。
msgflg:標誌選項。
返回值:成功返回發送的實際字節數,失敗返回:-1。

 struct msgbuf {
              long mtype;       /* message type, must be > 0 */			
               char mtext[1];    /* message data */
           };
  • 接收消息:
 ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
               int msgflg);

參數:
msqid:操作句柄msgget返回值。
msgp:結構體masgbuf,用戶自定義,描述msg類型、以及msg正文。
msgsz:期望接收數據的大小。
msgflg:標誌選項。0表示如果接收的數據大於msgsz時,接收數據自動截斷,否則不截斷。
返回值:成功返回發送的實際字節數,失敗返回:-1。

  • 消息隊列的釋放:
int msgctl(int msqid, int cmd, struct msqid_ds *buf);

參數:
msqid:消息隊列操作句柄。
cmd:操作選項,常用IPC_RMID,用於刪除消息隊列。
buf:用於保存消息隊列的信息,不需要則可以忽略(NULL)。
返回值:成功0,失敗返回-1。
瞭解這些接口及使用方法就可以直接上代碼了
還是server&client通信
server.c:

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

#define KEY 0x123456
#define C 1
#define S 2
//存儲消息的結構體
struct msgbuf
{
	long mtype;
	char mtext[1024];
};

int main()
{
	//1.打開/創建消息隊列
	int msgid = msgget(KEY,IPC_CREAT|0664);
	struct msgbuf buf;
	while(1)
	{
		printf("please wait the client request...\n");
		//server端接收數據
		msgrcv(msgid,&buf,1024,C,0);
		printf("client say:");
		fflush(stdout);
		printf("%s\n",buf.mtext);	
		printf("server enter#:");
		fflush(stdout);
		scanf("%s",&buf.mtext);
		//server端發送數據
		buf.mtype = S;
		msgsnd(msgid,&buf,strlen(buf.mtext),0);

	}
	//server端刪除消息隊列
	msgctl(msgid,IPC_RMID,NULL);
	return 0;
}

client.c:

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

#define KEY 0x123456
#define C 1
#define S 2
//存儲消息的結構體
struct msgbuf
{
	long mtype;
	char mtext[1024];
};

int main()
{
	//1.打開消息隊列
	int msgid = msgget(KEY,IPC_CREAT|0664);
	struct msgbuf buf;
	while(1)
	{
		printf("client enter#:");
		fflush(stdout);
		scanf("%s",&buf.mtext);
		//client發送消息
		buf.mtype = C;
		msgsnd(msgid,&buf,strlen(buf.mtext),0);
		printf("please the server respond...\n");
		msgrcv(msgid,&buf,1024,S,0);
		printf("server say:");
		fflush(stdout);
		printf("%s\n",buf.mtext);
	}
	return 0;
}

運行效果展示:
server端:
在這裏插入圖片描述
client端:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章