• 【Linux】进程间通信之消息队列


    系列目录

    进程间通信——共享内存

    进程间通信——信号量

    进程间通信——管道 

    文章目录

    一、概念

    二、消息队列函数

    1.msgget

    2.magsnd

    3.msgrcv

    4.msgctl

    三、掌握消息队列操作


    一、概念

    • 提供了一种从另一种进程发送一个数据块的方法。而且每个数据块都被认为含有一个类型,接收进程可以独立的接收含有不同类型值的数据块。
    • 可以在两个不相关的进程之间传递数据
    • 例如进程a向消息队列中添加消息,进程b可以通过消息队列a的标识符与a访问同一块消息队列,此时b在消息队列中接收a发送的消息,已读(被接收到)的消息”离开“消息队列,被读取过后的消息不会存在在消息队列中,而未读消息保存在消息队列中。
    • 有两种情况会导致消息队列的阻塞:1.进程对空的消息队列进行读取。2.进程读取的消息队列与已有消息类型不匹配(也就是,消息队列有123消息,进程访问4类型的消息肯定就会阻塞)。
    • 进程访问完消息队列会结束进程,但是消息队列会一直在,它不跟进程之间没有绝对的共存。
    • 消息队列存放在内核中,物理内存上,重启系统后消息队列会消失。
    • 进程可读取”0“号消息队列的消息,”0“号消息的含义是当进程读取消息时不要区分消息的类型,有什么读什么。

    二、消息队列函数

    头文件

    #include

    函数: 

    1. int msgctl(int msqid,int cmd,struct msqid_ds *buf);
    2. int msgget(key_t key,int msgflg);
    3. int msgrcv(int msqid,void *msg_ptr,size_t msg_sz,long int msgtype,int msgflg);
    4. int msgsnd(int msqid,const void *msg_ptr,size_t msg_sz,int msgflg);

    1.msgget

    int msgget(key_t key,int msgflg);
    • 作用:用来创建和访问一个消息队列
    • IPC_PRIVATE创建私有队列
    • 参数:
      • 第二个参数msgflg是由9个权限标志组成。IPC_CREAT创建消息队列
    • 返回值:成功时返回一个正整数,即队列标识符,失败返回-1

    2.magsnd

    int msgsnd(int msqid,const void *msg_ptr,size_t msg_sz,int msgflg);
    • 作用:用来把消息添加到消息队列中
    • 消息的结构受到两个方面的约束。首先,它的长度必须小于系统规定的上限,其次,它必须以一个长整型成员变量开始,接收函数将用这个成员变量来确定消息的类型,如下,把消息结构定义为:
      1. struct my_message{
      2. long int message_type;
      3. ...
      4. };
    • 参数:
      • 第一个参数msqid是由msgget函数返回的消息队列标识符
      • 第二个参数msg_ptr是一个指向准备发送消息的指针
      • 第三个参数msg_sz是msg_ptr指向的消息长度
      • 第四个参数msgflg控制在当前消息队列满或队列消息达到系统范围的限制时及将要发生的事情
    • 返回值:成功时返回0,失败返回-1,如果调用成功,消息数据的一份副本被放到消息队列中。

    3.msgrcv

    int msgrcv(int msqid,void *msg_ptr,size_t msg_sz,long int msgtype,int msgflg);
    
    • 作用:从一个消息队列中获取消息
    • 参数:
      • 第一个参数msqid是由msgget函数返回的消息队列标识符
      • 第二个参数msg_ptr是一个指向准备发送消息的指针
      • 第三个参数msg_sz是msg_ptr指向的消息长度
      • 第四个参数msgtyoe是一个长整数,实现一种简单形式的接收优先级
      • 第五个参数msgflg控制在当前消息队列满或队列消息达到系统范围的限制时及将要发生的事情
    • 返回值:成功时msgrcv函数返回放到接收缓冲区中的字符数,消息被复制到由msg_ptr指向的用户分配的缓存区中,删除消息队列的对应消息,失败时返回-1。

    4.msgctl

    int msgctl(int msqid,int cmd,struct msqid_ds *buf);
    • 作用:与共享内存中的控制函数相似
    • 结构体struct msqid_ds:
      1. struct msqid_ds{
      2. uid_t msg_perm.uid;
      3. uid_t msg_perm.gid;
      4. mode_t msg_perm.mode;
      5. };
    • 参数:
      • 第一个参数msqid是由msgget函数返回的消息队列标识符
      • 第二个参数command是将要采取的动作
    • 返回值:成功时返回0,失败时返回-1

    三、掌握消息队列操作

    通过代码掌握消息队列是如何发送与接收消息

    在消息队列中添加消息:

    message.c:发送消息”hello1",该进程运行一次,就会有1个“hello1"被添加入消息队列中。

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. //定义消息
    7. struct mess
    8. {
    9. long type;
    10. char data[128];
    11. };
    12. int main()
    13. {
    14. int msgid=msgget((key_t)1235,IPC_CREAT|0600);//添加一次,后面再使用就是获取消息
    15. if(msgid==-1)
    16. {
    17. exit(0);
    18. }
    19. struct mess dt;
    20. dt.type=1;
    21. strcpy(dt.data,"hello1");
    22. //1号消息内容hello1
    23. msgsnd(msgid,(void*)&dt,128,0);//标志位0
    24. //消息队列不用移除
    25. }

    如下图所示,对message.c编译为mess,执行该文件1次,执行ipcs命令查看发现消息队列被添加一次

    在消息队列中读取消息

    编译message1.c读取消息队列中消息:

    1. #include
    2. #include
    3. #include
    4. #include
    5. struct mess
    6. {
    7. long type;
    8. char data[128];
    9. };
    10. int main()
    11. {
    12. int msgid=msgget((key_t)1235,IPC_CREAT|0600);
    13. if(msgid==-1)
    14. {
    15. exit(0);
    16. }
    17. struct mess dt;
    18. msgrcv(msgid,(void*)&dt,128,1,0);
    19. printf("%s",dt.data);
    20. }

    如下图所示,对message1.c编译为mess1,执行该程序,发现a1写入的”hello1“被读取输出在屏幕上。

  • 相关阅读:
    Linux用户/用户组管理
    dify-on-wechat中涉及企业微信几个函数解析
    外包干了4年,技术退步明显.......
    【Android】SVGAPlayer的使用介绍
    《银行法律法规》三、银行管理——4、资本管理
    线程池的使用方式以及差别
    【C++】C 语言 和 C++ 语言中 const 关键字分析 ( const 关键字左数右指原则 | C 语言中常量的原理和缺陷 | C++ 语言中常量原理 - 符号表存储常量 )
    对Excel表中归类的文件夹进行自动分类
    vue+Ts+element组件封装
    001:vue3 实现自定义指令v-copy复制
  • 原文地址:https://blog.csdn.net/qq_53830608/article/details/127811659