linux系统——IPC进程通信之消息队列

一、定义

1、消息队列提供了一种在两个不相关的进程之间传递数据的简单有效的方法,与命名管道相比,消息队列的优势在于,它独立于发送和接收进程而存在,这消除了在同步命名管道的打开和关闭时可能产生的一些困难;
2、消息队列提供了进程间发送和接收数据块的方法,每个数据块都被认为含有一个类型,接收进程可以独立的接收含有不同类型值得数据块

与管道比,优点:
1)独立于发送和接收进程存在,避免了命名管道的同步和阻塞问题;
2)消息队列提供了方法来提前查看紧急消息
与管道比,相同点:
1)每个数据块都有一个最大长度的限制,系统中所有队列所包含的全部数据块的总长度有一个上限
3、linux系统有两个宏定义MSGMAX——定义了消息的最大长度,和MSGMNB——定义了队列的最大长度

二、相关函数

1、创建消息队列

linux系统——IPC进程通信之消息队列_第1张图片

2、把消息添加到消息队列中

linux系统——IPC进程通信之消息队列_第2张图片

3、从消息队列中获取消息

linux系统——IPC进程通信之消息队列_第3张图片

4、消息队列控制策略

linux系统——IPC进程通信之消息队列_第4张图片

三、队列实例

//Msg1.c接收消息
/* Here's the receiver program. */

#include 
#include 
#include 
#include 
#include 

#include 


struct my_msg_st {
    long int my_msg_type;//消息类型
    char some_text[BUFSIZ];//消息缓存
};

int main()
{
    int running = 1;
    int msgid;
    struct my_msg_st some_data;
    long int msg_to_receive = 0;//接收数据计数

/* First, we set up the message queue. */

    msgid = msgget((key_t)1234, 0666 | IPC_CREAT);//获取队列标识符

    if (msgid == -1) {
        fprintf(stderr, "msgget failed with error: %d\n", errno);
        exit(EXIT_FAILURE);
    }

/* Then the messages are retrieved from the queue, until an end message is encountered.
 Lastly, the message queue is deleted. */

    while(running) {
        if (msgrcv(msgid, (void *)&some_data, BUFSIZ,//接收消息
                   msg_to_receive, 0) == -1) {
            fprintf(stderr, "msgrcv failed with error: %d\n", errno);
            exit(EXIT_FAILURE);
        }
        printf("You wrote: %s", some_data.some_text);
        if (strncmp(some_data.some_text, "end", 3) == 0) {//结束循环
            running = 0;
        }
    }

    if (msgctl(msgid, IPC_RMID, 0) == -1) {
        fprintf(stderr, "msgctl(IPC_RMID) failed\n");
        exit(EXIT_FAILURE);
    }

    exit(EXIT_SUCCESS);
}
//Msg2.c发送消息
/* The sender program is very similar to msg1.c. In the main set up, delete the
 msg_to_receive declaration and replace it with buffer[BUFSIZ], remove the message
 queue delete and make the following changes to the running loop.
 We now have a call to msgsnd to send the entered text to the queue. */

#include 
#include 
#include 
#include 
#include 

#include 

#define MAX_TEXT 512

struct my_msg_st {
    long int my_msg_type;//消息类型
    char some_text[MAX_TEXT];//消息缓存
};

int main()
{
    int running = 1;
    struct my_msg_st some_data;
    int msgid;
    char buffer[BUFSIZ];

    msgid = msgget((key_t)1234, 0666 | IPC_CREAT);//创建消息队列,返回队列引用标识符, IPC_CREAT作用为即使传递的标志再用,也能成功调用

    if (msgid == -1) {
        fprintf(stderr, "msgget failed with error: %d\n", errno);
        exit(EXIT_FAILURE);
    }

    while(running) {
        printf("Enter some text: ");
        fgets(buffer, BUFSIZ, stdin);
        some_data.my_msg_type = 1;
        strcpy(some_data.some_text, buffer);

        if (msgsnd(msgid, (void *)&some_data, MAX_TEXT, 0) == -1) {//发送消息
            fprintf(stderr, "msgsnd failed\n");
            exit(EXIT_FAILURE);
        }
        if (strncmp(buffer, "end", 3) == 0) {//结束标志
            running = 0;
        }
    }

    exit(EXIT_SUCCESS);
}

你可能感兴趣的:(c,linux)