消息傳遞

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

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

原語

 消息隊列的原語包括髮送原語和接收原語,具有原子性,不可分割。

1.數據結構

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

2. 發送原語

首先在進程的地址空間設置一個發送區a,再填寫相關內容,然後調用發送原語send(receiver,message)把消息發送到接收進程的消息隊列PCB(B).mq中。發送原語描述如下:
  procedure send(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(PCB set,receiver,j);  獲得接收進程內部標識符j
       P(j.mutex);
       insert(j.mq.i);
       V(j.mutex);
       V(j.sm);
       end 
     

3. 接收原語

 
     接收進程從自己的消息隊列中摘下第一個消息緩衝區,並將它複製到指定的消息接收區b內,b在接收進程的地址空間內。所以消息隊列並不在進程的地址空間中。
    procedure receiver(b)
    begin
       j:=internal name;
       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.數據結構

 
 消息緩衝區的數據結構:
struct mymsh{
   long mtype;  //消息類型
   char mtext[];  //消息正文,可以是一個結構
}
消息的數據結構
struct msg_msg{
   struct list_head m_list;
   long m_type;  //消息類型
   int m_ts;  //消息大小
   struct msg_message* next;  //下一個消息位置
   void *security;       //真正消息位置
  }
消息隊列的數據結構

2. 系統調用

(1)創建一個消息隊列
   #include<sys/types.h>
   #include<sys/msg.h>
int msgget(key_t  key, int msgflg);
       返回值:成功,返回消息隊列標識符;錯誤,返回-1。
第一個參數是IPC——PRIVATE或者ftok()返回的一個鍵。Msgflg參數是消息隊列權限,可標記爲OR( | ),IPC_CREAT,IPC_EXCL等。

(2)發送消息
  int msgsnd(int msqid, void *msgp,size_t  msgsz, int msgflg);
  返回值:成功返回0,錯誤返回-1。
  參數1:指定的消息隊列標識符,由msgget()生成。參數2用戶定義的緩衝區,參數3:消息長度,參數4:越界處理。
   將新的消息發送到接收進程消息隊列中。

(3)接收消息
   ssize_t  msgrcv(int msqid, void *msgp,size_t maxmagsz,long msgtyp,int msgflg)
返回值:成功接收的字符數,錯誤返回-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("msgsnd fail\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字節。

發佈了42 篇原創文章 · 獲贊 24 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章