訊息傳遞

進程通信的方法包括共享數據結構、訊息佇列等。訊息傳遞是進程間傳遞數據的方法。訊息佇列有傳送原語和接收原語。UNIX/Linux訊息傳遞的編程有所不同。

訊息傳遞是進程間數據傳遞的一種方法,進程採用訊息(message)的方法,由傳送進程向接收進程的訊息佇列傳送一個訊息,接收進程在合適的時候取出。

因此,UNIX系統的訊息傳遞就是訊息佇列,在進程通信中可不使用共享地址空間的方式通信。 訊息佇列又稱為直接訊息傳遞,而信箱稱為間接訊息傳遞。信箱不能算是傳送進程的,也不能算是接收進程的,這與訊息佇列不同。訊息佇列必須由接收進程,有時候是傳送進程向作業系統申請,因此屬於這兩個進程之一。

原語

訊息佇列的原語包括傳送原語和接收原語,具有原子性,不可分割。

1.數據結構

把訊息緩衝作為進程通信工具,首先由Hansan提出,並在RC4000系統實現,廣泛套用在系統內進程之間的通信。
訊息緩衝的數據結構是訊息緩衝區,其描述為:
typemessagebuffer=record
sender:訊息傳送者名
size:訊息長度
text:訊息正文
next:指向下一個訊息緩衝區的指針
end
為實現訊息緩衝通信,還應在PCB中增加一些數據項,包括兩種信號量,其描述為:
typeprocesscontrolblock=record
…….
mq:訊息佇列隊首指針
mutex:訊息佇列的互斥信號量,訊息佇列是臨界資源
Sm:訊息佇列的計數信號量,傳送進程和接收進程同步
……
end

2. 傳送原語

首先在進程的地址空間設定一個傳送區a,再填寫相關內容,然後調用傳送原語send(receiver,message)把訊息傳送到接收進程的訊息佇列PCB(B).mq中。傳送原語描述如下:
proceduresend(receiver,a)
begin
getbuf(a.size,i);根據傳送區a的長度申請訊息緩衝區i
i.sender:=a.sender;
i.size:=a.size;
i.text:=a.text;
i.next:=0;
getid(PCBset,receiver,j);獲得接收進程內部標識符j
P(j.mutex);
insert(j.mq.i);
V(j.mutex);
V(j.sm);
end

3. 接收原語

接收進程從自己的訊息佇列中摘下第一個訊息緩衝區,並將它複製到指定的訊息接收區b內,b在接收進程的地址空間內。所以訊息佇列並不在進程的地址空間中。
procedurereceiver(b)
begin
j:=internalname;
P(j.sm);
P(j.mutex);
move(j.mq,i);
V(j.mutex);
b.sender:=i.sender;
b.size:=i.size;
b.text:=i.text;
end

UNIX System V訊息佇列

訊息佇列提供一種機制允許進程不必通過共享地址空間實現通信和同步,允許進程以訊息的形式傳遞數據。

1.數據結構

訊息緩衝區的數據結構:
structmymsh{
longmtype;//訊息類型
charmtext[];//訊息正文,可以是一個結構
}
訊息的數據結構
structmsg_msg{
structlist_headm_list;
longm_type;//訊息類型
intm_ts;//訊息大小
structmsg_message*next;//下一個訊息位置
void*security;//真正訊息位置
}
訊息佇列的數據結構

2. 系統調用

(1)創建一個訊息佇列
#include<sys/types.h>
#include<sys/msg.h>
intmsgget(key_tkey,intmsgflg);
返回值:成功,返回訊息佇列標識符;錯誤,返回-1。
第一個參數是IPC——PRIVATE或者ftok()返回的一個鍵。Msgflg參數是訊息佇列許可權,可標記為OR(|),IPC_CREAT,IPC_EXCL等。

(2)傳送訊息
intmsgsnd(intmsqid,void*msgp,size_tmsgsz,intmsgflg);
返回值:成功返回0,錯誤返回-1。
參數1:指定的訊息佇列標識符,由msgget()生成。參數2用戶定義的緩衝區,參數3:訊息長度,參數4:越界處理。
將新的訊息傳送到接收進程訊息佇列中。

(3)接收訊息
ssize_tmsgrcv(intmsqid,void*msgp,size_tmaxmagsz,longmsgtyp,intmsgflg)
返回值:成功接收的字元數,錯誤返回-1。
參數1:從哪一個訊息佇列中讀取訊息,參數2:讀取訊息的緩衝區。參數4:訊息類型。
接收進程從訊息佇列取走訊息。

3.訊息佇列編程

struct msgmbuf

{

long msg type;

char msg_text[512];

};

main()

{

int qid;

key_t key;
int len;

struct msgmbuf msg;

if((key=ftok(".",a))==-1)

{

printf("ftok fail\n");

exit(-1);

}

if(qid=msgget(key,IPC_CREAT|0666))==-1)

{

printf("msgget fail\n");

exit(-2);

}

printf("the message quene is %d\n",qid);

puts("please input the message:");

if((fgets((&msg)->msg_text,512,stdin))==NULL)

{

puts("no message");

exit(-3);

}

msg.msg_type=getpid();

len=strlen(msg.msg.text);

if((msgsnd(qid,&msg,len,0))<0) //向訊息佇列中發訊息,注意這個程式是簡化的程式,並沒有向接收進程的訊息佇列發訊息

{

printf("msgsndfail\n");

exit(-4);

}

if((msgrcv(qid,&msg,512,0,0))<0) //讀訊息佇列的訊息

{

printf(“msgrcv fail\n");

exit(-5);

}

printf("reading message:%s\n",(&msg)->msg_text);//顯示輸出訊息內容

if((msgctl(qid,IPC_RMID,NULL))<0)

{

printf("msgctl fail\n");

exit(-6);

}

exit(0);

}

4.常用命令

顯示系統中所有的訊息佇列
$>ipcs–q
$>./svmsg_lsaw
Linux系統最多有16個訊息佇列,每個訊息最大為8192位元組。

相關詞條

相關搜尋

熱門詞條

聯絡我們