天天看點

【Linux應用】程序間通信消息隊列1.前言2.API函數3.示例參與讨論

1.前言

程序間通信簡稱IPC(Inter process communication),程序間通信就是在不同程序之間傳播或交換資訊。

【Linux應用】程式間通信消息隊列1.前言2.API函數3.示例參與讨論

消息隊列是程序通信的一種方式,本質是一個存儲消息的連結清單,這些消息具有特定的格式及特定優先級。消息隊列是随核心持續的,隻有在核心重新開機,或者删除一個消息隊列時,該消息隊列才會真正地被删除。

2.API函數

#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok ( char *pathname, char proj ); /* f是file,k是key */
           

消息隊列的核心持續性要求每個消息隊列都要在系統範圍内有對應的唯一鍵值,可以使用ftok擷取鍵值。

int msgget(key_t key ,int msgflg );建立或打開消息隊列
           

與其他的IPC機制一樣,程式必須提供一個鍵來命名某個特定的消息隊列。msgflg是一個權限标志,表示消息隊列的通路權限,它與檔案的通路權限一樣。msgflg可以與IPC_CREAT做或操作,表示當key所命名的消息隊列不存在時建立一個消息隊列,如果key所命名的消息隊列存在時,IPC_CREAT标志會被忽略,而隻傳回一個辨別符。IPC_EXCL和IPC_CREAT一起使用,如果對應鍵值的消息隊列已經存在,則出錯,傳回-1。msgflg: IPC_CREAT|0666 如果不存在則建立。并且給權限

msg_ptr是一個指向準備發送消息的指針,但是消息的資料結構卻有一定的要求,指針msg_ptr所指向的消息結構一定要是以一個長整型成員變量開始的結構體,接收函數将用這個成員來确定消息的類型。是以消息結構要定義成這樣:

struct my_message {
    long int message_type;
    /* The data you wish to transfer */
};
           

msgid, msg_ptr, msg_st 的作用也函數msgsnd()函數的一樣。

msgtype 可以實作一種簡單的接收優先級。如果msgtype為0,就擷取隊列中的第一個消息。如果它的值大于零,将擷取具有相同消息類型的第一個資訊。如果它小于零,就擷取類型等于或小于msgtype的絕對值的第一個消息。

msgflg 用于控制當隊列中沒有相應類型的消息可以接收時将發生的事情。

3.示例

send:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/msg.h>
#include <errno.h>
 
#define MAX_TEXT 512
 
struct msg_st
{
    long int msg_type;
    char text[MAX_TEXT];
};
 
int main(int argc, char **argv)
{
    struct msg_st data;
    char   buffer[BUFSIZ];//8192
    int    msgid = -1;
    key_t  key;
 
    key = ftok(".", 'z');    //   路徑          id号
    if(key == -1)
    {
        printf("ftok error\n");
    }
    printf("key:%x\n",key);
 
    // 建立消息隊列
    msgid = msgget(key, IPC_CREAT | 0666);
    if (msgid == -1)
    {
        fprintf(stderr, "msgget failed width error: %d\n", errno);
        goto fail;
    }
 
    // 向消息隊裡中寫消息,直到寫入end
    while (1)
    {
        printf("Enter some text: \n");
        fgets(buffer, BUFSIZ, stdin);
        data.msg_type = 1; // 注意2
        strcpy(data.text, buffer);
 
        // 向隊列裡發送資料
        if (msgsnd(msgid, (void *)&data, MAX_TEXT, 0) == -1)
        {
            fprintf(stderr, "msgsnd failed\n");
            exit(EXIT_FAILURE);
        }
 
        // 輸入end結束輸入
        if (strncmp(buffer, "end", 3) == 0)
        {
            break;
        }
 
        sleep(1);
    }
fail:
    exit(EXIT_SUCCESS);
}
           

receive

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/msg.h>
#include <errno.h>
 
struct msg_st
{
    long int msg_type;
    char text[BUFSIZ];
};
 
int main(int argc, char **argv)
{
    int      msgid = -1;
    struct   msg_st data;
    long int msgtype = 0;
    key_t    key;
 
    key = ftok(".", 'z');    //   路徑          id号
    if(key == -1)
    {
        printf("ftok error\n");
    }
    printf("key:%x\n",key);
 
    // 建立消息隊列
    msgid = msgget(key, IPC_CREAT|0666);
    if (msgid == -1)
    {
        fprintf(stderr, "msgget failed width error: %d\n", errno);
        goto fail;
    }
 
    // 從隊列中擷取消息,直到遇到end消息為止
    while (1)
    {
        if (msgrcv(msgid, (void *)&data, BUFSIZ, msgtype, 0) == -1)
        {
            fprintf(stderr, "msgrcv failed width erro: %d", errno);
        }
 
        printf("You wrote: %s\n", data.text);
 
        // 遇到end結束
        if (strncmp(data.text, "end", 3) == 0)
        {
            break;
        }
    }
 
fail:
 
    exit(EXIT_SUCCESS);
}
           

參與讨論

==================================

新的文章内容和分享已更新在:

|工|·-·|重|·-·|号|:協定森林

==============================

繼續閱讀