当前位置: 首页 > news >正文

嵌入式学习——进程间通信方式(4)—— 消息队列

一、基本概念

        消息队列是一个进程向另一个进程发送一个数据块,每个数据块都含有一个类型,接收方可以接收自己想要的消息类型。

        消息队列、信号的区别:信号能承载的数据量较小,而队列能够存放大量自定义的数据。

        消息队列、管道的区别:

        ① 、有名管道和消息队列都可以通过不同进程传输数据,都是要发送和接收数据,但是有名管道利用的是read()、write()函数,而消息队列则是通过msgsnd()、msgrev()。

        ②、管道只能传输无字节流的数据,而消息队列可以支持各种类型的数据,有格式的字节流

        ③、消息队列可以选择想要读取的数据,可以根据消息类型来接收,而管道只能按数据流读取出来(像水管一样)。 

二、基本流程

        1)创建或获取一个消息队列对象

    int msgget(key_t key, int msgflg);

key:不同的进程可以通过访问相同的key,来操作同一个消息队列,实现数据的传输,其中可以利用宏IPC_PRIVATE,这个宏的取值为0,创建当前进程的私有消息队列。

msgflg:创建消息队列模式的参数

        O_CREAT:如果不存在相同key的消息队列,则创建一个;如果存在相同的消息队列,则返回标识符msqid。一般在创建时与0600进行位运算   O_CREAT | 0600,给创建的文件指定一个权限。

        O_CREAT | O_EXCL:表示如果这个key在内核存在一个消息队列则返回一个错误描述,如果不存在则创建一个。

        2)封装消息的结构体

struct msgbuf {long mtype;       /* 消息类型必须大于0 */char mtext[1];    /* 消息内容,可以是其他任何类型*/};

        3)发送、接收消息队列

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,int msgflg);

        msqid:就是创建消息队列时返回的标识符

        msgp:封装消息的结构体

        msgsz:封装消息结构体的大小,不包含消息类型占用的4个字节,即mtext的长度。

        msgflg:如果为0则表示:当消息队列满时,msgsnd()函数将会阻塞,直到消息能写进消息队列; 如果为IPC_NOWAIT则表示:当消息队列已满的时候,msgsnd()函数不等待立即返回; 如果为IPC_NOERROR:若发送的消息大于size字节,则把该消息截断,截断部分将被丢弃,且不通知发送进程。

        4)销毁消息队列

int msgctl(int msqid, int cmd, struct msqid_ds *buf);

msqid:消息队列的标识符。

cmd:常用的控制命令如下:

                        IPC_RMID:删除该消息队列

                        IPC_STAT:获取属性权限,放到buf中

                        IPC_SET:设置属性信息为buf指向的内容。

                        IPC_INFO:获得关于消息队列的系统限制值信息。

                        SHM_INFO:获得系统为消息队列消耗的资源信息。

buf:在释放共享内存时,为NULL即可。

struct shmid_ds {struct ipc_perm shm_perm;    /* Ownership and permissions */size_t          shm_segsz;   /* Size of segment (bytes) */time_t          shm_atime;   /* Last attach time */time_t          shm_dtime;   /* Last detach time */time_t          shm_ctime;   /* Last change time */pid_t           shm_cpid;    /* PID of creator */pid_t           shm_lpid;    /* PID of last shmat(2)/shmdt(2) */shmatt_t        shm_nattch;  /* No. of current attaches */...};​
struct ipc_perm {key_t          __key;    /* Key supplied to shmget(2) */uid_t          uid;      /* Effective UID of owner */gid_t          gid;      /* Effective GID of owner */uid_t          cuid;     /* Effective UID of creator */gid_t          cgid;     /* Effective GID of creator */unsigned short mode;     /* Permissions + SHM_DEST andSHM_LOCKED flags */unsigned short __seq;    /* Sequence number */};​

三、代码示例

1)发送端的代码

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <stdlib.h>
//封装消息结构体
struct msgget
{long mtype;char mdata[128];
};int main()
{key_t key = ftok("/bin/bash",1);//创建消息队列int msqid = msgget(key,IPC_CREAT | 0600);if(msqid == -1){perror("create msqid failed");return -1;}struct msgget message;message.mtype = 1;strcpy(message.mdata,"hello,new friend");//发送消息队列int ret = msgsnd(msqid,&message,sizeof(message.mdata),0);if(ret == -1){perror("message send failed");}printf("send message success\n");return 0;}

2)接收端的代码

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>//封装消息结构体
struct msgget
{long mtype;char mdata[128];
};int main()
{key_t key = ftok("/bin/bash",1);//创建消息队列int msqid = msgget(key,IPC_CREAT | 0600);if(msqid == -1){perror("create msqid failed");return -1;}struct msgget message;//接收消息队列int ret = msgrcv(msqid,&message,sizeof(message.mdata),0,0);if(ret == -1){perror("message send failed");}printf("收到的消息是:%s\n",message.mdata);//销毁消息队列msgctl(msqid,IPC_RMID,NULL);return 0;}


http://www.mrgr.cn/news/38759.html

相关文章:

  • Ruby 多线程
  • 基于baidu的云函数实现隐藏c2真实地址
  • 助农扶贫微信小程序+ssm论文ppt源码调试讲解
  • 服务器分类极简理解
  • Kafka快速实战与基本原理详解
  • 【数据结构】链表(2)
  • Performance Analysis Kit简介
  • (undone) 阅读 MapReduce 论文笔记
  • 【JUC并发编程系列】深入理解Java并发机制:深入剖析AbstractQueuedSynchronizer的底层机制(九、AQS底层实现原理)
  • 【图像生成大模型imagen】细节逼真富有创造力
  • javaScript中如何实现函数缓存,案例解析
  • 【一篇文章理解Java中多级缓存的设计与实现】
  • 「漏洞复现」九块九付费进群系统 wxselect SQL注入漏洞
  • 华为OD机试真题---猜字谜
  • 深入理解C语言编译器优化
  • 机器学习与深度学习的技术比较
  • Java中的数据合并与拆分:使用Stream API实现数据的灵活处理
  • 大厂面试:2024年虾皮Java开发面试题及参考答案(5万字长文)
  • CKA考题和注意事项
  • 问:进程/线程上下文切换场景及相关概念?