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

系统编程-消息队列

消息队列

目录

消息队列

引入

一、消息队列的特点

二、使用指令查看消息队列

三、使用消息队列进行通信的步骤

1、获取键值

2、创建或获取消息队列 id

3、使用消息队列进行数据的传输

4、msgrcv -- 从消息队列中读取数据

5、消息队列的多种操作函数


引入

-- 进程间通信 (IPC)是指在不同进程之间传播或交换信息。IPC的方式通常有管道(包括无名管道和命名管道)、消息队列、信号量、共享存储、Socket、Streams等。

-- 这章讲消息队列

  • 相当于系统级别的链表(系统开着,消息队列在。系统关,消息队列关)-- 所有进程都可使用

  • 多个进程间进行数据传输           -- 消息队列

一、消息队列的特点

-- 类似于管道

  • (1)先进先出,数据读出来会从消息队列中消失。

  • (2)要进行消息的读取,必须有消息否则会读阻塞。

  • (3)消息队列满了,会产生写阻塞。

  • (4)有消息类型之分,用来确定读取的消息类型

-- 消息队列可以解决的问题:多个进程间进行数据的传输

二、使用指令查看消息队列

-- 指令:ipcs

  • ipas可以查看系统下的system V的状态 

    alt text

-- 指令:ipcs -q 只查看消息队列 

alt text

-- 消息队列的相关信息:

  • 键值:获取消息队列 id 的唯一标识符,一个键值对应一个消息队列的 id,是八位的十六进制,例如 0x12345678

  • msqid:用于区分不同的消息队列 也代表该消息队列的号(id)

  • 拥有者:谁创建的

  • 权限:对该消息队列的操作权限
    例:666 可读可写

  • 已用字节数:消息队列中一共存放了多少个字节的信息

  • 消息:存放了消息的个数


三、使用消息队列进行通信的步骤

alt text

1、获取键值

(1)函数获取:

-- 函数头文件

  • #include <sys/types.h>
  • #include <sys/ipc.h>

-- 函数原型

  • key_t ftok(const char *pathname, int proj_id)

-- 函数的作用:

  • 通过传入的参数来获取指定的键值(ftok的两个参数一样,获取的键值就一样)

-- 函数的参数:

  • pathname:必须是存在的路径
  • proj_id:0~255

-- 函数的返回值:

  • 会根据函数的参数来返回一个键值

alt text

(2)自己定义:

  • #define my_key 0x12345678

-- 键值的作用:

  • 一样的键值可以让不同进程来获取到同一个消息队列的id号
  • 一个键值对应一个id号,是一一对应的。具有唯一性。

2、创建或获取消息队列 id

-- 函数头文件

  • #include <sys/types.h>
  • #include <sys/ipc.h>
  • #include <sys/msg.h>

-- 函数原型

  • int msgget(key_t key, int msgflg)

-- 函数的作用:

  • 创建或获取消息队列的 id 用于进程间通信

-- 函数的参数:

  • key:键值 相同的键值可以获取相同的消息队列 id
  • msgflg:固定填写    IPC_CREAT|0666

-- 函数的返回值:

  • 成功返回 消息队列的 id >= 0
  • 失败返回 -1

alt text

alt text

3、使用消息队列进行数据的传输

-- 收发的数据类型必须为结构体

-- 函数的头文件

  • #include <sys/types.h>
  • #include <sys/ipc.h>
  • #include <sys/msg.h>

-- 函数原型

  • int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

-- 函数的作用:

  • 向指定的消息队列中发送一条消息

-- 函数的参数:

  • msqid:要将消息发送到哪一个消息队列中去

  • msgsz:填写 mtext 的大小 ,填写:第二个参数的结构体大小 - 8

  • msgflg:填0是阻塞发送,如果消息队列空间不够,会阻塞,直到有空间可以进行写入
    -- IPC_NOWAIT 非阻塞发送

  • msgp:发送的消息的首地址

-- 这里必须要用结构体 需要自己在程序中定义(发送和接收的结构体必须定义的一模一样)

struct msgbuf {
    long mtype;
    /* message type, must be > 0 */
    char mtext[1];
    /* message data */
    xxxx;
    .....;
};

-- 结构体中的第一个成员必须为 long 类型,赋值时必须给大于 0 的值

-- 函数的返回值:

  • 成功返回 0
  • 失败返回 -1
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>

#define key 0x12345678

struct student
{
	long mtype;  -- 第一个数据类型必须是long型
	int id;
	char name[20];
};

int main()
{

	//key_t  key = ftok("/home/pimouren/learn", 55);
	printf("%x\n",key);
	
	int id = msgget(key,IPC_CREAT|0666);
	if(id == -1)
	{
		perror("msgget");
		return -1;
	}
	printf("id = %d\n",id);
	
	struct student stu;
	printf("请输入学生的学号!\n");
	scanf("%d",&stu.id);
	printf("请输入学生的名字!\n");
	scanf("%s",stu.name);
	
	int  mm = msgsnd(id, &stu,sizeof(stu)-8, 0);
	if(mm == -1)
	{
		perror("msgsnd");
		return -1;
	}
	
	
	return 0;
}

alt text

-- 再次向消息队列中写入数据,已用字节数发生改变

alt text

4、msgrcv         -- 从消息队列中读取数据

-- 函数头文件

  • #include <sys/types.h>
  • #include <sys/ipc.h>
  • #include <sys/msg.h>

-- 函数的原型

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

-- 函数的作用:

  • 从消息队列中进行数据的读取

-- 函数的参数:

  • msqid:要从哪一个消息队列读取消息
  • msgp:读取到的消息保存的首地址
  • msgsz:要读取的消息字节数,填写结构体大小 - 8
  • msgtyp:要接受的消息类型

"> 0"
-- 接收指定的消息类型中的第一条消息
"0"
-- 接收消息队列中的第一条消息
"<0"
-- 接收小于 msgtyp 绝对值的消息类型
例如 填写-3, |-3| == 3 ,那么可以读取 1 或2 的消息类型

  • msgflg: 0 阻塞接收 如果没有 msgtyp 指定消息类型会一直阻塞 直到有该消息类型来到 IPC_NOWAIT 非阻塞

-- 函数的返回值:

  • 成功返回 实际读取到的字节数
  • 失败返回 -1

alt text

alt text

alt text

5、消息队列的多种操作函数

-- 函数头文件

  • #include <sys/types.h>
  • #include <sys/ipc.h>
  • #include <sys/msg.h>

-- 函数原型

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

-- 函数的作用:

  • 对消息队列进行多种操作 例如:获取消息队列的信息, 更改消息队列设置, 删除消息队列

-- 函数的参数:

  • msqid:消息队列的 id 你要对哪一个消息队列进行操作
  • cmd:要进行的具体操作

IPC_STAT 获取消息队列的信息
IPC_SET 更改消息队列的设置
IPC_RMID 删除消息队列
当 cmd 为 IPC_RMID 时 第三个参数给 NULL buf:结构体指针 用于传出和设置消息队列属性

-- 函数的返回值:

  • 成功 返回 0
  • 失败 返回 -1

-- 这个函数主要用来删除消息队列

alt text

-- 使用指令删除消息队列

  • 指令:ipcrm -q msgid

alt text


http://www.kler.cn/a/284860.html

相关文章:

  • Electron 项目启动外部可执行文件的几种方式
  • 除了 Postman,还有什么好用的 API 调试工具吗
  • 中文书籍对《人月神话》的引用(161-210本):微软的秘密
  • Docker入门系列——Docker-Compose
  • Python网络爬虫与数据采集实战——什么是网络爬虫
  • 力扣 LeetCode 142. 环形链表II(Day2:链表)
  • 力扣2116.判断一个括号字符串是否有效
  • Qt_信号槽机制
  • 计算机网络概述(网络结构)
  • MYSQL——聚合查询
  • B树及其Java实现详解
  • 续:MySQL的半同步模式
  • APO 新发版支持Skywalking Agent接入
  • unity的问题记录(信息管理)
  • 【Java设计模式】责任链模式:构建强大的请求处理机制
  • 技术成神之路:设计模式(十二)模板方法模式
  • SQL存储过程:数据库编程的瑞士军刀
  • Java中的注解(Annotation)
  • 谷粒商城实战笔记-269~271-商城业务-订单服务-bug修改
  • Python3遍历文件夹下的文件
  • AI编码新时代:免费人工智能助手Blackbox AI
  • Spring Boot 集成 JdbcTemplate(盘它!)
  • 使用WSL在Windows上安装Linux
  • 【微信小程序】SpringBoot集成微信小程序(多小程序集成)
  • opencv/c++的一些简单的操作(入门)
  • 趣味算法------多重背包问题