[Linux用户空间编程-2]:进程间通信 - 消息队列的使用

Posted 文火冰糖的硅基工坊

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Linux用户空间编程-2]:进程间通信 - 消息队列的使用相关的知识,希望对你有一定的参考价值。

作者主页(文火冰糖的硅基工坊):文火冰糖(王文兵)的博客_文火冰糖的硅基工坊_CSDN博客

本文网址:https://blog.csdn.net/HiWangWenBing/article/details/123373906


目录

第1章 概述

1.1 概述

1.2 消息队列的好处

第2章 Linux的消息队列库

2.1 所需头文件

2.2 消息队列的使用流程

第3章 主要的操作函数

3.1 ftok函数生成键值

3.2 msgget函数创建消息队列

3.3 msgsnd函数往消息队列发送消息

3.4 msgrcv函数从消息队列读取消息

3.5 msgctl函数对消息队列进行控制(包括删除)


第1章 概述

1.1 概述

消息队列,Unix的通信机制之一,可以理解为是一个存放消息(数据)容器。将消息写入消息队列,然后再从消息队列中取消息,一般来说是先进先出的顺序,也可是设定消息的优先级。

1.2 消息队列的好处

(1)用于不同进程之间传递大量保存在共享内存区的数据。

(2)可以用于不同进程之间通过消息体直接传递小数据。

(3)消息队列可以解决两个进程的读写速度不同(处理数据速度不同),系统耦合等问题,

(4)保存数据:消息队列里的消息哪怕进程崩溃了也不会消失。

第2章 Linux的消息队列库

2.1 所需头文件

#include<sys/msg.h>

消息队列、信号灯、共享内存常用在Linux服务端编程的进程间通信环境中,它们之间有这相似性的结构。

消息队列

信号灯

共享内存区

头文件

<sys/msg.h>

<sys/sem.h>

<sys/shm.h>

创建或打开IPC函数

msgget

semget

shmget

控制IPC操作的函数

msgctl

semctl

shmctl

IPC操作函数

msgsnd

msgrcv

semop

shmat

shmdt

2.2 消息队列的使用流程

①ftok函数生成键值,类似与文件操作符

②msgget函数创建消息队列

③msgsnd函数往消息队列发送消息

④msgrcv函数从消息队列读取消息

⑤msgctl函数进行删除/控制消息队列

第3章 主要的操作函数

3.1 ftok函数生成键值

(1)函数原型 :

key_t ftok(const char *path ,int id);

(2)说明:

ftok():系统IPC键值的格式转换函数。

(3)输入参数:

  •     path为一个已存在的路径名
  •     id为0~255之间的一个数值,代表项目ID,自己取

(4)返回值:

  • 成功返回键值(相当于32位的int)。出错返回-1

key值是消息队列的标识,类似于文件标识符。

(5)实例:

key_t key = ftok( “/tmp”, 66);

3.2 msgget函数创建消息队列

(1)函数原型 

int msgget(key_t key, int flag);

(2)说明

使用文件符标识key,向内核申请创建一个消息队列。

不同的进程之间,都可以通过该函数,获取特定消消息的标识。

不同进程间,通过可以key来标识相同的消息队列。

(3)输入参数

  •  key:为ftok生成的键值
  • flag为所需要的操作和权限,可以用来控制创建一个消息队列。

flag的值为IPC_CREAT:如果不存在key值的消息队列,且权限不为0,则创建消息队列,并返回一个消息队列ID。如果存在,则直接返回消息队列ID

flag的值为 IPC_CREAT | IPC_EXCL:如果不存在key值的消息队列,且权限不为0,则创建消息队列,并返回一个消息队列ID。如果存在,则产生错误。

(4)返回值:

成功返回消息队列ID;出错返回-1

(5)案例:

int id = msgget(key,IPC_CREAT|IPC_EXCL|0666);

创建一个权限为0666(所有用户可读可写,具体查询linux权限相关内容)的消息队列,并返回一个整型的消息队列ID,如果key值已经存在有消息队列了,则出错返回-1(由IPC_EXCL控制

int id = msgget(key,IPC_CREAT|0666);

创建一个权限为0666(所有用户可读可写,具体查询linux权限相关内容)的消息队列,并返回一个消息队列ID,如果key值已经存在有消息队列了,则直接返回一个消息队列ID。

备注:消息id是后续系统消息通信的标识,类似与socket id。

3.3 msgsnd函数往消息队列发送消息

(1)函数原型

int msgsnd (int msgid, const void *ptr,size_t nbytes, int flag);

(2)功能说明

用于在不同的进程间发送消息,消息id消息队列的唯一标识,是有Linux管理的,不同的进程之间可以共享。进程间不需要指定进程ID号,需要通过消息ID号进行通信。

(3)入口参数说明

  • msgid: 为msgget返回的消息队列ID值
  • ptr:为消息结构体mymesg指针
  • nbytes:为消息结构体mymesg里的字符数组mtext大小,sizeof(mtext)
  • flag:值可以为0、IPC_NOWAIT

为0时,当消息队列满时,msgsnd将会阻塞,直到消息能写进消息队列或者消息队列被删除。

为IPC_NOWAIT时,当消息队列满了,msgsnd函数将不会等待,会立即出错返回EAGAIN

(4)返回值:

成功返回0;错误返回-1

(5)案例

例如:msgsnd(id, (void *)&ckxmsg,512,0);
 

3.4 msgrcv函数从消息队列读取消息

(1)函数原型:

ssize_t msgrcv(int msgid ,void *ptr,size_t nbytes,long type, int flag);

(2)入口参数:

  •     msgid:为msgget返回的消息队列ID值
  •     ptr:为消息结构体mymesg指针
  •     nbytes:为消息结构体mymesg里的字符数组mtext大小,sizeof(mtext)
  •     type:在结构体mymesg里我们定义了一个long int mtype,用于分辨消息的类型

这个类型非常重要,用于定点选择消息队列中的消息。

        type ==0 返回队列中的第一个消息

        type > 0 选择返回队列中消息类型为type的第一个消息

        type < 0 返回队列中消息类型值小于等于type绝对值的消息,如果这种消息有若干个,则取类型值最小的消息

  •     flag:可以为0、IPC_NOWAIT、IPC_EXCEPT

        为0时,阻塞式接收消息,没有该类型的消息msgrcv函数一直阻塞等待

        为IPC_NOWAIT时,如果没有返回条件的消息调用立即返回,此时错误码为ENOMSG

        为IPC_EXCEPT时,与msgtype配合使用返回队列中第一个类型不为msgtype的消息

(3)返回值:

成功返回消息数据部分的长度;错误返回-1

(4)案例

例如:msgrcv(id,(void *)&ckxmsg,512,1,0);
 

3.5 msgctl函数对消息队列进行控制(包括删除)

(1)函数原型

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

(2)入口参数

  •     msgid就是msgget函数返回的消息队列ID
  •     cmd有三个

IPC_RMID:删除消息队列

IPC_STAT:取此队列的msqid_ds结构,并将它存放在buf指向的结构中;

IPC_SET:改变消息队列的状态,把buf所指的msqid_ds结构中的uid、gid、mode复制到消息队列的msqid_ds结构内。

  •     buf就是结构体msqid_ds

(3)返回值

成功返回0;错误返回-1

(4)案例

例如:msgctl(id,IPC_RMID,NULL); 删除id号的消息队列

概述简单的操作就是删除消息队列了,也可以获取和改变消息队列的状态


作者主页(文火冰糖的硅基工坊):文火冰糖(王文兵)的博客_文火冰糖的硅基工坊_CSDN博客

本文网址:https://blog.csdn.net/HiWangWenBing/article/details/123373906

以上是关于[Linux用户空间编程-2]:进程间通信 - 消息队列的使用的主要内容,如果未能解决你的问题,请参考以下文章

[Linux用户空间编程-2]:进程间通信 - 消息队列的使用

[Linux用户空间编程-2]:进程间通信 - 消息队列的使用

Linux中进程间通信

Linux - 进程间通信 - 匿名管道

Linux 进程间通信 共享内存

Linux系统编程-进程间通信(共享内存)