嵌入式学习——进程间通信方式(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 and
                                           SHM_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;
	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值