淺談訊息佇列

wzm10455發表於2013-04-14

訊息佇列是系統核心地址空間中的一個內部的連結串列。

訊息可以按照順序傳送到佇列中,也可以以幾種不同的方式從佇列中讀取。

每一個訊息佇列用一個唯一的IPC識別符號表示。

資料結構msgbuf,此資料結構可以說是訊息資料的模板,雖然此使用者結構需要使用者自己定義。

在中,此資料結構的定義為:struct msgbuf{long mtype;char request_id;struct cilent_info;}

這裡的訊息型別欄位和前面的一樣,但資料結構的其餘部分則由其他一個的兩個欄位所代替,而其中的一個還是另外一個結構。

這就體現了訊息佇列的靈活之處。msgget()用於建立一個新的訊息佇列,或者存取一個已經存在的訊息佇列。

msgsnd()系統呼叫用於向佇列傳送一條訊息msgrcv()系統呼叫用於從訊息佇列中讀取一條訊息

這個今天下午複習了一下有關訊息佇列的知識,感覺就是它的識別度比較高,根據你的type來確定你要收發的資料,下面這個程式中編譯程msgtool後會生成一個a.out檔案

./a.out w 0 "hello"

再在另外一個終端下面輸入

./a.out r 0 這樣就能根據型別0來識別要寫入和輸出的資料

0可以換成其他的數字。


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#define MAX_SEND_SIZE 80

struct mymsgbuf{//定義結構體
    long mtype;
    char mtext[MAX_SEND_SIZE];
};

void send_message(int qid,struct mymsgbuf *qbuf,long type,char *text);
void read_message(int qid,struct mymsgbuf *qbuf,long type);
void remove_queue(int qid);
void change_queue_mode(int qid,char *mode);
void usage(void);

int main(int argc,char **argv)
{
    key_t key;
    int msgqueue_id;
    struct mymsgbuf qbuf;
    if(argc==1)
        usage();
    //系統建立IPC通訊 (訊息佇列、訊號量和共享記憶體) 時必須指定一個ID值。通常情況下,該id值通過ftok函式得到。
    key=ftok(".",'m');

    if((msgqueue_id=msgget(key,IPC_CREAT|0666))==-1)
    {
        perror("msgget");
        exit(1);
    }
    printf("message queue id = [%d] .\n",msgqueue_id);
    
    switch(tolower(argv[1][0]))
    {
        case 's':
            if(argc<4)
            {
                usage();
                break;    
            }    
            send_message(msgqueue_id,&qbuf,atol(argv[2]),argv[3]);//把字串轉換成長整型數
            break;
        case 'r':
            if(argc<3)
            {
                usage();
                break;
            }
            read_message(msgqueue_id,&qbuf,atol(argv[2]));
            break;
        case 'd':
                remove_queue(msgqueue_id);
            break;
        case 'm':
            if(argc<3)
            {
                usage();
                break;
            }
        default:usage();
            
    }
    return 0;
}

void send_message(int qid,struct mymsgbuf *qbuf,long type,char *text)
{
    //給佇列傳送訊息

    printf("sending a message....\n");
    qbuf->mtype=type;//賦數值型別
    strcpy(qbuf->mtext,text);
    
    if((msgsnd(qid,qbuf,strlen(qbuf->mtext)+1,0))==-1)
    {
        perror("msgsnd");
        exit(1);
    }
}


void read_message(int qid,struct mymsgbuf *qbuf,long type)
{
    printf("Reading a message...\n");
    qbuf->mtype=type;
    msgrcv(qid,qbuf,MAX_SEND_SIZE,type,0);
    printf("Type: %1d Text:%s \n",qbuf->mtype,qbuf->mtext);
}
void remove_queue(int qid)
{
    msgctl(qid,IPC_RMID,0);
}
void change_queue_mode(int qid,char *mode)
{
}
void usage(void)
{
    fprintf(stderr,"msgtool -A utility for thinkering with msg queues \n");
    fprintf(stderr,"USAGE:msgtool (s) end <type>> <>type> <>");
    fprintf(stderr,"(r)");
    fprintf(stderr,"(d)");
    fprintf(stderr,"(m)");
    exit(1);
}

相關文章