Linux进程间利用消息队列发送数据

利用消息队列发送数据

消息队列学习笔记,代码和理论均来自网络,如有侵权联系删除。另外本人小白一枚,欢迎各位大佬指点。

消息队列理论知识

消息队列是Linux系统进程之间通信一种方式,除此之外,进程通信方式还有多种。本文仅讨论消息队列通讯方式。消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。

消息队列函数由msgget、msgctl、msgsnd、msgrcv四个函数组成。

具体函数参照及原型请参照下面博客介绍:
链接: https://blog.csdn.net/guoping16/article/details/6584024

下面是实际代码案例,相关的函数我会在代码下进行解释,适合小白观看,大神勿喷;

#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];
    int msgid = -1;
 
    // 建立消息队列
    msgid = msgget((key_t)1234, 0666 | IPC_CREAT);
   
    if (msgid == -1)
    {
        fprintf(stderr, "msgget failed error: %d\n", errno);
        exit(EXIT_FAILURE);
    }

    // 向消息队里中写消息,直到写入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);
    }
 
    exit(EXIT_SUCCESS);
}

分享一下我第一次看此代码不懂并且查找资料后的成果:

    msgid = msgget((key_t)1234, 0666 | IPC_CREAT);

根据上文链接中的理论可知,(key_t)1234是将1234类型强转为key_t型,并且0666的相关含义查找资料后得知:从左向右:
第一位:表示这是个八进制数 000
第二位:当前用户的经权限:6=110(二进制),每一位分别对就 可读,可写,可执行,6说明当前用户可读可写不可执行
第三位:group组用户,6的意义同上
第四位:其它用户,每一位的意义同上,0表示不可读不可写也不可执行

 fgets(buffer, BUFSIZ, stdin);

fgets函数语法(来自百度百科)
函数原型
char *fgets(char *str, int n, FILE *stream);
参数
str-- 这是指向一个字符数组的指针,该数组存储了要读取的字符串。
n-- 这是要读取的最大字符数(包括最后的空字符)。通常是使用以 str 传递的数组长度。
stream-- 这是指向 FILE 对象的指针,该 FILE 对象标识了要从中读取字符的流。

stdin函数语法(来自百度百科)
stdin; 从输入流stdin即输入缓冲区中读取7个字符到字符数组str中

参考网上的代码可以对此函数有更好的理解

# include <stdio.h>
int main(void)
{
    char str[20];  /*定义一个最大长度为19, 末尾是'\0'的字符数组来存储字符串*/
    printf("请输入一个字符串:");
    fgets(str, 7, stdin);  /*从输入流stdin即输入缓冲区中读取7个字符到字符数组str中*/
    printf("%s\n", str);
    return 0;
}

最后就是最重要的msgsnd函数本体了
msgsnd(msgid, (void *)&data, MAX_TEXT, 0) ;
参照上述链接中理论可以很轻松看懂,此函数的实参和理论中的形参一一对应即可,不再赘述;

然后是接收端代码

#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;   // 注意1
 
    // 建立消息队列
    msgid = msgget((key_t)1234, 0666 | IPC_CREAT);
    if (msgid == -1)
    {
        fprintf(stderr, "msgget failed width error: %d\n", errno);
        exit(EXIT_FAILURE);
    }
 
    // 从队列中获取消息,直到遇到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;
        }
    }
 
    // 删除消息队列
    if (msgctl(msgid, IPC_RMID, 0) == -1)
    {
        fprintf(stderr, "msgctl(IPC_RMID) failed\n");
    }
 
    exit(EXIT_SUCCESS);
}

代码解析大抵相同,都是按照函数原型赋予实参;
最后附上学习过程中搜索的一些文档链接供读者参考:
Linux进程间的通信方式和原理
链接: https://www.cnblogs.com/liugh-wait/p/8533003.html

消息队列内核结构和msgget、msgctl 函数
链接: https://www.cnblogs.com/alantu2018/p/8473070.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值