消息隊列

一 、消息隊列含義 : 及消息的列表,用戶可以從消息隊列中添加消息和讀取消息,可以隨機查詢。消息隊列是存在於內核中的,由“隊列ID”來標識。

二、應用 :消息隊列的實現包括創建或打開消息隊列、添加消息、讀取消息和控制消息隊列這 4 種操作。

  1. 創建或打開消息隊列 int msgget(key_t key,int msgflg)

    參數:
    key:消息隊列的鍵值,多個進程可以通過它訪問同一個消息隊列。其中有個特殊值IPC_PRIVATE,
    它用於創建當前進程的私有消息隊列。
    msgflg:權限標誌位,可以取值 IPC_CREAT - 如果消息隊列對象不存在,則創建之,否則則進行打開操作;IPC_EXCL - 和IPC_CREAT 一起使用(用”|”連接),如果消息對象不存在則創建之,否則產生一個錯誤並返回。

    返回值:成功-消息隊列ID 出錯- -1
    2.添加消息 int msgsnd(int msgqid,const void* msgp,size_t msgsz,int msgflg)

    參數:
    msgqid : 消息隊列ID
    msgp:指向消息結構的指針,該消息結構msgbuf通常爲
    struct msgbuf
    {
    long mtype;/消息類型,該結構必須從這個域開始/
    char mtext[n];/消息正文/
    }
    msgsz:消息正文的字節數(不包括嘻嘻類型指針變量)
    msgflg:IPC_NOWAIT - 若消息無法立即發送(比如:消息隊列已滿),函數會立即返回; 0 - 阻塞到發送成功爲止。

    返回值:成功 - 0 出錯- -1
    3.讀取消息 int msgrcv(int msgqid,void* msgp,size_t msgsz,int msgtyp,int msgflg)

    參數:
    msgqid:消息隊列ID
    msgp:消息緩衝區,同於msgsnd()函數的msgp
    msgsz:消息正文的字節數
    msgtyp:0 —— 接收消息隊列中第一個消息 大於0– 接收消息隊列中第一個類型爲msgtyp的消息 小於0–接收消息隊列中第一個類型值不小於msgtyp絕對值且類型值又最小的消息
    msgflg:MSG_NOERROR-若返回的消息比msgsz字節多,則消息就會截短到msgsz字節,且不通知消息發送進程
    IPC_NOWAIT-若在消息隊列中並沒有相應類型的消息可以接收,則函數立即返回
    0- 阻塞到接收一條相應類型的消息爲止

    返回值:成功-0 出錯 - -1
    4.控制消息隊列 int msgctl(int msgqid,int cmd,struct msqid_ds*buf)

    參數:
    msgqid:消息隊列的隊列ID
    cmd:IPC_STAT-讀取消息隊列的數據結構msqid_ds,並將其存儲在buf指定的地址中 IPC_SET-設置消息隊列的數據結構msqid_ds中的ipc_perm,這個值取自buf參數 IPC_RMID:從系統中內核中刪除消息隊列
    buf:描述消息隊列的msqid_ds結構類型變量
    struct msqid_ds
    {
    struct msqid_ds {
    struct ipc_perm msg_perm;
    struct msg msg_first; / first message on queue,unused */
    struct msg msg_last; / last message in queue,unused */
    __kernel_time_t msg_stime; /* last msgsnd time */
    __kernel_time_t msg_rtime; /* last msgrcv time */
    __kernel_time_t msg_ctime; /* last change time */
    unsigned long msg_lcbytes; /* Reuse junk fields for 32 bit */
    unsigned long msg_lqbytes; /* ditto */
    unsigned short msg_cbytes; /* current number of bytes on queue */
    unsigned short msg_qnum; /* number of messages in queue */
    unsigned short msg_qbytes; /* max number of bytes on queue */
    __kernel_ipc_pid_t msg_lspid; /* pid of last msgsnd */
    __kernel_ipc_pid_t msg_lrpid; /* last receive pid */
    };
    三、使用實例
    消息隊列接收msgrcv.c

#define BUFFER_SIZE 512
struct message
{
    long msg_type;
    char msg_text[BUFFER_SIZE];
};

int main()
{
    int qid;
    key_t key;
    struct message msg;

    /*根據不同的路徑和關鍵字產生標準的 key*/
    if ((key = ftok(".", 'a')) == -1)
    {
        perror("ftok");
        exit(1);
    }

    /*創建消息隊列*/
    if ((qid = msgget(key, IPC_CREAT|0666)) == -1)
    {
        perror("msgget");
        exit(1);
    }
    printf("Open queue %d\n", qid);

    do
    {
        /*讀取消息隊列*/
        memset(msg.msg_text, 0, BUFFER_SIZE);
        if(msgrcv(qid,(void*)&msg,BUFFER_SIZE,0,0)<0)
        {
            perror("msgrcv");
            exit(1);
        }
        printf("The message from process %d : %s", msg.msg_type, msg.msg_text);
    }while(strncmp(msg.msg_text,"quit",4));

    /*從系統內核中移走消息隊列 */
    if ((msgctl(qid, IPC_RMID, NULL)) < 0)
    {
        perror("msgctl");
        exit(1);
    }
    exit(0);

}

消息隊列發送 msgsnd.c

#define BUFFER_SIZE 512

sturct message
{
    long msg_type;
    char msg_text[BUFFER_SIZE];
};


int main()
{
    int qid;
    key_t key;
    struct message msg;

    /*根據不同的路徑和關鍵字產生標準的 key*/
    if ((key = ftok(".", 'a')) == -1)
    {
        perror("ftok");
        exit(1);
    }

    /*創建消息隊列*/
    if((qid=msgget(key,IPC_CREATE|0666)) == -1)
    {
        perror("msgget");
        exit(1);
    }
    printf("Open queue %d\n",qid);

    while(1)
    {
        printf("Enter some message to the queue:");
        if((fgets(msg.msg_text, BUFFER_SIZE, stdin)) == NULL)
        {
            puts("no message");
            exit(1);
        }
        msg.msg_type = getpid();

        /*添加消息到消息隊列*/
        if ((msgsnd(qid, &msg, strlen(msg.msg_text), 0)) < 0)
        {
            perror("message posted");
            exit(1);
        }
        if (strncmp(msg.msg_text, "quit", 4) == 0)
        {
        break;
        }
    }
    exit(0);
}

開啓量個console,分別運行./msgsnd和./msgrcv, msgsnd中發送quit,兩個進程都退出。
msgsnd
這裏寫圖片描述
msgrcv
這裏寫圖片描述

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