天天看點

消息傳遞

消息傳遞是程序間資料傳遞的一種方法,程序采用消息(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位元組。

繼續閱讀