浅尝辄止6-Linux基础-消息队列

消息队列是Linux提供的另一个进程通信方法,它源自System V,所以跟典型的用read/write的那些机制长得不一样。

消息队列相关系统调用的手册

mstget(2) msgsnd(2) msgrcv(2) msgctl(2)


消息队列和管道很相似,也是类似于创建、收发、关闭这样的过程。
下面代码模拟了两个用消息队列通信的进程。

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

struct msg_st{
    long mtype;
    char mtext[BUFSIZ];
};

int main(int argc, char **argv){
    key_t key = ftok(".", 0);
    int pid = fork();
    if (pid > 0){
        //父进程扮演[发]消息的角色
        int id = msgget(key, 0777 | IPC_CREAT);
        if (id < 0){
            printf("error@%d, %s\n", __LINE__, strerror(errno));
        }
        if (id >= 0){
            struct msg_st data = {1, "hello world!"};
            sleep(1);//故意推迟发送,以便看到接收端的阻塞
            printf("before\tsend\n");
            if (msgsnd(id, (void*)&data, sizeof("hello world!"), 0) < 0){
                printf("error@%d, %s\n", __LINE__, strerror(errno));
            }
            printf("after \tsend\n");
        }
        waitpid(pid,NULL,0);
    }
    else if (pid == 0){
        //子进程扮演[收]消息的角色
        struct msg_st data;
        int id = msgget(key, 0777 | IPC_CREAT);
        int n;
        if(id < 0){
            printf("error@%d, %s\n", __LINE__, strerror(errno));
            exit(-1);
        }
        printf("before\treceive\n");
        if ((n = msgrcv(id, (void*)&data, BUFSIZ, 0, 0)) <= 0){
            printf("error@%d, %s\n", __LINE__, strerror(errno));
            exit(-1);
        }
        printf("after \treceive\n");
        printf("receive: type=%ld, text=[%s]\n", data.mtype, data.mtext);

        if (msgctl(id, IPC_RMID, 0) < 0){
            printf("error@%d, %s\n", __LINE__, strerror(errno));
            exit(-1);
        }
        printf("delete message queue.\n");
        exit(0);
    }
    return 0;
}

编译和输出

#gcc test.c -o test && ./test
before  receive
before  send
after   send
after   receive
receive: type=1, text=[hello world!]
delete message queue.

从打印的顺序可以看出,接收是阻塞的。其实发送也是阻塞的,但要在消息队列满的时候才会发生。关于阻塞行为,可以用IPC_NOWAIT这个flag控制。

补充

  • 队列多少是多呢?消息能有多长?
意义
MSGMNI 系统最大消息队列数
MSGMNB 单个消息队列最大字节数
MSGMAX 单个消息最大字节数
  • 消息队列与管道相比有什么不同
    消息队列的收发更灵活,一个消息队列就可以分频道,收发都可以选频道,struct msg_st的mtype成员可以当做这个频道。

消息队列还有什么有趣的用途?

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 不知怎么对社交产生了厌倦,又或许从未喜欢过,一直处在被动局面。 厌恶,也鄙视着那些热衷于此的人,看...
    嘘_请安静听阅读 1,566评论 0 1
  • 文献标题: Overview of KLEE’s main command-line options 文献作者:...
    owhereg阅读 5,443评论 0 0