Linux進程間通信——消息隊列

1.概述

消息隊列是一種通過鏈表結構組織的一組消息。與其他兩種進程間通信(共享內存、信號量)相同,都存放在內核中。多個進程通過消息隊列的標識符對消息數據進行傳送,實現進程間通信。

2.消息隊列的相關操作

使用消息隊列實現進程間通信,需要首先用msgget()函數創建一個消息隊列,然後調用msgsnd()函數向該消息隊列中發送指定的消息,通過msgrcv()函數接收該消息,最後調用msgctl()函數對消息隊列進行指定的控制操作,這樣一個使用消息隊列實現進程間通信就實現了。
2.1 msgget()函數
該函數用於創建一個新的消息隊列或打開一個已經存在的消息隊列,該函數的定義爲:

#include <sys/tyoes.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);

參數說明:
key: 表示所創建的消息隊列的名字。
msgflg: 用於設置消息隊列的訪問權限,也可以表示該函數的操作類型。
如果該函數調用成功,返回值爲與參數key相關聯的標識符;如果調用失敗,則返回-1.
注意:創建消息隊列的函數msgget()中參數所遵循的原則與創建共享內存的shmget()函數類似。
2.2 msgsnd()函數
msgsnd()函數用於向消息隊列中發送消息,該函數定義如下:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgsnd(int msqid, const void* msgp, size_t msgsz, int msgflg);

msqid: 將信息發送到消息隊列的標識符。
msgp: 指向要發送的消息數據。
msgsz: 以字節數表示的消息數據的長度。
msgflg: 消息隊列滿時的處理方法,該參數可以是0或IPC_NOWAIT.
該函數調用成功返回0;失敗返回-1.
要發送的數據存放在msgbuf結構體中,使用msgp指針指向該類型引用消息數據的內容和消息的類型。msgbuf結構體定義如下:

struct msgbuf
{
	long mtype; /*消息類型,以大於0的整數表示*/
	char mtext[1]; /*消息內容*/
};

如果消息隊列中有足夠的空間,msgsnd()函數會立即返回,並實現發送消息到msgp指定的消息隊列中; 如果消息隊列已滿的話,msgflg參數沒有設置IPC_NOWAIT值,則msgsnd()將會阻塞;如果設置了IPC_NOWAIT值,則msgsnd()函數調用失敗,並返回-1,直到消息隊列中有空間時,函數才返回0.
2.3 msgrcv()函數
msgrcv()函數用於接收消息隊列中的消息數據,該函數定義如下:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
ssize_t msgrcv(int msqid, void* msgp, size_t msgsz, long msgtyp, int msgflg);

msqid: 從msqid標識符所代表得消息隊列中接收消息。
msgp: 指向存放消息數據的內存空間。
msgsz: 以字節數表示的消息數據的長度。
msgtyp: 讀取的消息數據的類型。
msgflg: 對讀取的消息數據不滿足情況的處理。
該函數調用成功時,返回0;如果調用失敗,返回-1.
2.4 msgctl()函數
該函數主要實現對消息隊列的控制操作,該函數定義如下:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgctl(int msqid, int cmd, struct maqid_ds* buf);

msgctl()函數實現對msqid標識符所指向的消息隊列進行控制,控制內容取決於參數cmd的取值。

命令 說明
IPC_STAT 把msqid_ds結構中的數據設置爲消息隊列的當前關聯值
IPC_SET 在進程有足夠權限的前提下,把消息隊列的當前關聯值設置爲msqid_ds數據結構中給出的值
IPC_RMID 刪除消息隊列

3.消息隊列實現進程間通信

在Linux系統中,使用msgget()函數創建一個消息隊列,通過msgsnd()函數發送兩次消息,第一次發送消息內容爲:“hello Linux!”,第二次發送的消息爲"Goodbye!"。接下來調用msgrcv()函數接收消息,這樣就實現了一個消息隊列的進程間通信。

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
    key_t key;
    int proj_id = 1;
    int msqid;
    char message1[] = {"Hello Linux!"};
    char message2[] = {"Goodbye!"};
    struct msgbuf
    {
	long msgtype; //消息類型
	char msgtext[1024]; //消息內容
    }snd, rcv;
    key = ftok("/root/process/mq", proj_id);
    if(key == -1)
    {
	perror("create key error!");
	return 1;
    }
    if((msqid = msgget(key, IPC_CREAT|0666)) == -1)
    {
	printf("msgget error!\n");
	exit(1);
    }
    snd.msgtype = 1;
    sprintf(snd.msgtext, message1);
    if(msgsnd(msqid, (struct msgbuf*) &snd, sizeof(message1)+1, 0) == -1)
    {
	printf("msgsnd error!\n");
	exit(1);
    }
    snd.msgtype = 2;
    sprintf(snd.msgtext,"%s", message2);
    if(msgsnd(msqid,(struct msgbuf*)&snd, sizeof(message2)+1, 0) == -1)
    {
    printf("msgrcv error!\n");
    exit(1);
    }
    if(msgrcv(msqid,(struct msgbuf*)& rcv, 80, 1, IPC_NOWAIT) == -1)
    {
	printf("msgrcv error!\n");
	exit(1);
    }
    printf("the received message: %s\n", rcv.msgtext);
    msgctl(msqid, IPC_RMID, 0); /*刪除新創建的消息隊列*/
    exit(0);
}

在這裏插入圖片描述

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