進程間通信(2)消息隊列

消息隊列也是一種用於進程間通信的方式,它放在計算機內核中,並由消息隊列表示符(類比文件描述符)標識,它由操作系統維護。

消息隊列的特點:

1>它支持進程間雙向無阻塞的通信。

2>它是面向消息傳遞的。

3>它的生命週期是隨計算機內核的。

下圖列出了消息隊列的最大消息的一些數據。

650) this.width=650;" src="http://s2.51cto.com/wyfs02/M01/7E/E0/wKioL1cLoKHwIIQaAAFjL6kb1TM351.png" title="無標題.png" width="500" height="126" border="0" hspace="0" vspace="0" style="width:500px;height:126px;" alt="wKioL1cLoKHwIIQaAAFjL6kb1TM351.png" />

在創建一個消息隊列時需要這幾個函數:

int msgget(key_t key, int msgflg);

key:由ftok函數創建

msgflg:有ICP_CREAT和ICP_ECXL兩個宏參數,第一個參數爲新創建一個如果系統中有則返回這個id,第二個參數一般和第一個組合使用爲了新創建一個。

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

該函數第一個參數是指定的路徑,第二個參數可由用戶自定義一個數,返回一個由這個參數組成的一個數。

每個隊列創建好都有一個 msqid_ds與其關聯

650) this.width=650;" src="http://s3.51cto.com/wyfs02/M00/7E/E2/wKiom1cLnWrQkeh2AAHNQ9Vxa0c858.png" title="無標題.png" width="705" height="480" border="0" hspace="0" vspace="0" style="width:705px;height:480px;" alt="wKiom1cLnWrQkeh2AAHNQ9Vxa0c858.png" />

上面的一個數據結構就是消息隊列所維護的結構體,而下面那個結構體則是每一個IPC都要維護的一個結構。


int msgctl(int msqid, int cmd, struct msqid_ds *buf);

msgctl是用於在消息隊列結束時做的一些工作,第二個參數cmd會有一些不同的宏參數來讓它執行不同的功能。

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

msgsnd用於發送消息,msgp是一個結構體,原型如下:

  struct msgbuf {
               long mtype;       /* message type, must be > 0 */
               char mtext[1];    /* message data */
           };

msgbuf中的mtype是用於標識接受的是來自誰的消息或者是誰發送的消息,mtext則適用於存放消息的數組了。

msgflg用於指定消息以什麼方式傳輸---IPC_NOWAIT(消息已滿會返回錯誤,類似於非阻塞傳輸),如果沒有設置或設置爲零則以阻塞方式發送,

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);

msgtyp>0時返回以msgtyp標識的第一條消息

msgtyp==0時返回消息隊列中的第一條消息

msgtyp<小於0時返回絕對值等於msgtyp標識的消息若消息有若干個則返回類型最小的消息


下面是一個簡單的阻塞方式的消息隊列;

.h

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<sys/types.h>
 4 #include<sys/ipc.h>
 5 #include<sys/msg.h>
 6 #include<string.h>
 7 
 8 #define _PATH_ "."
 9 #define _PROJECT_ID_ 0x6666
 10 #define _MAX_BUF_ 1024  
 11 #define _SERVER_ID_ 1
 12 #define _CLIENT_ID_ 2
 13 
 14 typedef struct msgvp
 15 {
 16     long mtype;
 17     char mmsg_buf[_MAX_BUF_];
 18 }msgvp;
  19 static int comm_msgget(int flag)
  20 {
  21     key_t key=ftok(_PATH_,_PROJECT_ID_);
  22     if(ftok<0)
  23     {
  24         perror("ftok");
  25         exit(1);
  26     }   
  27     int msg_id=msgget(key,flag);
  28     if(msg_id<0)
  29     {
  30         perror("msg_id");
  31         exit(1);
  32     }   
  33     return msg_id;
  34 }   
  35 
  36 int get_msgid()
  37 {
  38     umask(0);
  39     int msg_id=comm_msgget(IPC_CREAT|IPC_EXCL|0666);
  40     return msg_id;
  41 }   
  42 
  43 int use_msgid()
    44 {
    45     int msg_id=comm_msgget(IPC_CREAT);
    46     return msg_id;
    47 }
    48 
    49 void msg_receive(int msg_id,msgvp*msg_vp,int msgvp_size,long mstype)
    50 {
    51     memset(msg_vp->mmsg_buf,'\0',sizeof(msg_vp->mmsg_buf));
    52     if(msgrcv(msg_id,msg_vp,msgvp_size,mstype,0)<0)
    53     {
    54         perror("msgsve");
    55     }
    56 }
    57 
    58 void msg_send(int msg_id,msgvp*msg_vp,int msgvp_size,char *str,int msgtype)
    59 {
    60     memset(msg_vp->mmsg_buf,'\0',sizeof(msg_vp->mmsg_buf));
    61     strcpy(msg_vp->mmsg_buf,str);
    62     msg_vp->mtype=msgtype;
    63     if(msgsnd(msg_id,msg_vp,msgvp_size,0)<0)
    64     {
    65         perror("msgsnd");
    66     }
    67 }
    68 
    69 void msg_distory(int msg_id)
    70 {
    71     if(msgctl(msg_id,IPC_RMID,0)<0)
    72     {
    73             perror("msgctl");
    74     }
    75 }

server.c

  1 #include"comm.h"
  2 
  3 
  4 int main()
  5 {
  6     int msg_id=get_msgid();
  7     msgvp serve;
  8     char my_buf[_MAX_BUF_];
  9     while(1)
 10     {
 11         sleep(5);
 12         msg_receive(msg_id,&serve,sizeof(serve),_CLIENT_ID_);
 13         printf("client:%s",serve.mmsg_buf);
 14 
 15         printf("please write to client:");
 16         fflush(stdout);
 17         int size=read(0,my_buf,_MAX_BUF_);
 18         if(size>0)
 19         {
 20                 my_buf[size]='\0';
 21         }
 22         msg_send(msg_id,&serve,sizeof(serve),my_buf,_SERVER_ID_);
 23     }
 24 
 25     msg_tory();
 26     return 0;
 27 }
~                                                                                                               
"server.c" 27L, 443C                                                                          1,16         全部

client.c

   

  1 
  2 #include"comm.h"
  3 
  4 
  5 int main()
  6 {
  7     int msg_id=use_msgid();
  8     msgvp client;
  9     char my_buf[_MAX_BUF_];
 10     while(1)
 11     {
 12         printf("please write to server:");
 13         fflush(stdout);
 14         int size=read(0,my_buf,_MAX_BUF_);
 15         if(size>0)
 16         {
 17             my_buf[size]='\0';
 18         }
 19         msg_send(msg_id,&client,sizeof(client),my_buf,_CLIENT_ID_);
 20 
 21 
 22         sleep(5);
 23         msg_receive(msg_id,&client,sizeof(client),_SERVER_ID_);
 24         printf("server:%s",client.mmsg_buf);
 25 
 26     }
 27     return 0;
 28 }
"client.c" 28L, 441C                                                                          1,0-1        全部

                 


本文出自 “痕跡” 博客,請務必保留此出處http://wpfbcr.blog.51cto.com/10696766/1762765

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