【BES2500x系列 -- RTX5操作系统】深入探索CMSIS-RTOS RTX -- 同步与通信篇 -- 消息队列和邮箱处理 --(四)
💌 所属专栏:【BES2500x系列】
😀 作 者:我是夜阑的狗🐶
🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询!
💖 欢迎大家:这里是CSDN,我总结知识的地方,喜欢的话请三连,有问题请私信 😘 😘 😘
您的点赞、关注、收藏、评论,是对我最大的激励和支持!!!🤩 🤩 🤩
文章目录
- 前言
- 1 介绍
- 2 功能特性
- 3 同步与通信
- 3.1 通信
- 4 同步与通信
- 4.1 消息队列
- 4.1.1 定义
- 4.1.2 创建
- 4.1.3发送消息
- 4.2 邮箱处理
- 4.2.1 定义
- 4.2.2 创建
- 4.2.3 发送/释放邮件
- 4.2.4 获取邮件
- 总结
前言
大家好,又见面了,我是夜阑的狗🐶,本文是专栏【BES2500x系列】专栏的第4篇文章;
今天开始学习BES2500x系列的一天💖💖💖,开启新的征程,记录最美好的时刻🎉,每天进步一点点。
专栏地址:【BES2500x系列】, 此专栏是我是夜阑的狗对BES2500x系列开发过程的总结,希望能够加深自己的印象,以及帮助到其他的小伙伴😉😉。
如果文章有什么需要改进的地方还请大佬不吝赐教👏👏。
1 介绍
在嵌入式系统中,同步和通信是确保系统内各个组件协调工作的两个核心概念。它们对于实现高效、可靠的嵌入式应用至关重要。前面已经讲过同步概念了,接下来对通信概念进行简要说明。话不多说,那接下来就学习 RTX
系统中通信机制都有哪些吧,让我们原文再续,书接上回吧。😉
2 功能特性
在实时操作系统(RTOS)中,任务管理和同步通信是关键组件,它们确保系统的高效和有序执行。本文将探讨这些概念,特别是线程管理、信号量、互斥锁、消息队列和邮箱处理。
- 任务管理:RTX提供任务创建、调度和优先级管理,确保任务按照优先级及时执行。
- 同步与通信:包括信号量、互斥锁、消息队列和邮箱,促进任务间的同步和数据交换。
- 内存管理:内存池和动态内存分配,有效管理有限的系统资源。
- 定时器服务:虚拟和硬件定时器,支持周期性任务和一次性事件触发。
- 中断处理:保证中断服务的快速响应,同时保持任务的上下文安全。
- 线程安全:通过内核级保护机制,防止多线程环境下的数据竞争和死锁。
3 同步与通信
3.1 通信
通信是指嵌入式系统中不同组件或任务之间交换信息的过程。有效的通信机制对于分布式系统和多处理器系统尤为重要。嵌入式系统中常用的通信方式包括:
序号 | 方法 | 说明 |
---|---|---|
1 | 消息队列(Message Queues) | 任务间通过发送和接收带有数据的消息来通信,支持异步通信。 |
2 | 管道(Pipes) | 一种半双工的数据传输方式,常用于进程间的通信。 |
3 | 共享内存(Shared Memory) | 多个任务可以直接读写同一块内存区域,效率高但需要同步机制来避免冲突。 |
4 | 总线(Buses) | 如 I2C 、SPI 、UART 等硬件接口,用于设备间的数据传输。 |
5 | 远程过程调用(RPC) | 允许程序调用网络中另一台计算机上的子程序,模拟本地调用。 |
6 | 中断(Interrupts) | 硬件触发的事件,用于通知 CPU 处理紧急或外部事件,是一种快速的通信方式。 |
同步和通信机制的选择取决于嵌入式系统的具体需求,包括实时性、资源限制、复杂度以及系统的可靠性要求。合理设计同步和通信策略,是保证嵌入式系统高效稳定运行的关键。
4 同步与通信
4.1 消息队列
消息队列允许线程间安全地传递固定大小的消息,提供了异步通信的方式。
4.1.1 定义
消息队列允许线程安全地发送和接收固定大小的数据块。队列维护发送和接收的顺序。一般在文件开头会看到这样的定义:osMessageQDef
。
- 代码
// 定义一个名为app_test1_queue的消息队列,可存储128个uint32_t类型的元素。
osMessageQDef(app_test1_queue, 128, uint32_t);// 声明一个osMessageQId类型的变量app_test1_queue_id,用于保存消息队列的句柄。
// 在程序运行时,需要通过调用相关API初始化并获取有效的句柄值。
osMessageQId app_test1_queue_id = NULL;
这段代码首先使用 osMessageQDef
宏定义了一个名为 app_test1_queue
的消息队列,它可以存储128个32位无符号整数。然后声明了一个变量 app_test1_queue_id
,用于存储消息队列的标识符(句柄),初始值设为 NULL
。在实际应用中,需要通过操作系统提供的API来初始化这个消息队列,并将返回的句柄赋值给app_test1_queue_id
。
/*** 定义一个消息队列。* * 这个宏用于静态定义一个消息队列,它会创建一个静态队列控制块和一个用于存储消息的数据缓冲区。* * @param name 消息队列的名称。* @param queue_sz 队列中能容纳的消息数量。* @param type 消息队列中每条消息的数据类型。*/
#define osMessageQDef(name, queue_sz, type) \
static StaticQueue_t os_mq_cb_##name; \
static uint32_t os_mq_data_##name[(queue_sz) * sizeof(type)]; \
const osMessageQDef_t os_messageQ_def_##name = \
{ (queue_sz), \{ NULL, 0U, (&os_mq_cb_##name), sizeof(StaticQueue_t), \(&os_mq_data_##name), sizeof(os_mq_data_##name) } }
此宏定义了三个静态变量:一个静态队列控制块,一个消息数据数组,和一个用于OS的消息队列定义结构体。这个结构体包含了队列的大小、指针到静态队列控制块和消息数据数组的地址,以及这些数组的大小。这使得在系统运行时能够直接使用这个消息队列而无需动态分配内存。
- 参数/函数讲解
序号 | 参数/函数 | 说明 |
---|---|---|
1 | osMessageQId | 声明变量,用于存储消息队列的标识符(句柄),初始值设为NULL。 |
2 | osMessageQDef | 定义了静态变量:静态队列控制块,消息数据数组和用于OS的消息队列定义结构体 |
4.1.2 创建
通过 osMessageQueueCreate()
函数创建消息队列,指定队列容量和消息大小。
- 代码
/*** 初始化app_test1_queue消息队列。** 这个函数负责创建名为app_test1_queue的消息队列,并将成功创建的句柄保存到全局变量app_test1_queue_id。* 如果消息队列创建失败,它会记录错误信息并返回-1。** @return* - 0: 消息队列创建成功。* - -1: 创建消息队列失败。*/
static int32_t app_test1_queue_init(void)
{// 使用osMessageCreate函数创建消息队列,并将句柄保存到全局变量app_test1_queue_id = osMessageCreate(osMessageQ(app_test1_queue), NULL);// 检查创建是否成功,如果失败则打印错误信息并返回-1if (app_test1_queue_id == NULL) {TRACE(0, "Failed to Create app_test_thread1_queue");return -1;}// 创建成功,返回0return 0;
}
这段代码定义了一个名为 app_test1_queue_init
的静态函数,用于初始化之前定义的消息队列app_test1_queue
。它通过调用o sMessageCreate
函数创建消息队列,并检查返回的句柄是否有效。如果创建失败,它会记录错误信息并返回 -1 ;否则,返回 0 表示成功。
- 参数/函数讲解
序号 | 参数/函数 | 说明 |
---|---|---|
1 | osMessageCreate | 创建消息队列 |
4.1.3发送消息
使用 osMessageQueueSend()
或 osMessageQueuePut()
函数向队列发送消息。
- 代码
/*** 尝试向app_test1_queue中发送消息。** 此函数检查消息队列是否有足够的空间接收至少6条消息。如果队列有足够空间,* 它将向队列中放入一个值为0xFF的消息,不设置优先级。** 注意:这个函数没有处理消息队列满的情况,因此在队列满时不会阻塞。*/
void app_test1_queue_put(void)
{// 检查消息队列是否有超过5个空闲槽位if (osMessageGetSpace(app_test1_queue_id) > 5) {// 向消息队列app_test1_queue_id中插入一个值为0xFF的消息,优先级设为0osMessagePut(app_test1_queue_id, 0xFF, 0);}
}
这个函数 app_test1_queue_put
尝试将一个值为 0xFF
的消息放入名为 app_test1_queue
的消息队列中。首先,它检查队列是否有足够的空间容纳至少6个新消息。如果满足条件,就调用 osMessagePut
将消息放入队列,否则不做任何操作。注意,这个函数没有处理队列已满的情况,所以如果队列已满,消息将不会被发送,也不会阻塞调用线程。
- 参数/函数讲解
序号 | 参数/函数 | 说明 |
---|---|---|
1 | osMessageGetSpace | 检查消息队列的空闲槽位 |
2 | osMessagePut | 将消息放入队列 |
4.2 邮箱处理
邮箱是用于线程间交换结构化数据的对象池。每个邮箱包含一组预先分配的内存块,线程可以申请、发送和接收这些内存块。
4.2.1 定义
一般在文件开头会看到这样的定义:osMailQDef
。
- 代码
osMailQDef (app_test1_mailbox, APP_TEST1_MAX_MAILBOX, APP_TEST1_MAIL);
/*** app_test1_mailbox: 邮箱队列定义** 使用osMailQDef宏定义一个名为'app_test1_mailbox'的邮箱队列,最大邮件数为APP_TEST1_MAX_MAILBOX,* 邮件类型为APP_TEST1_MAIL。*/// 邮箱队列ID,用于后续操作
static osMailQId app_test1_mailbox_id = NULL;/*** app_test1_mail_alloc - 分配并初始化一个APP_TEST1_MAIL类型的邮件** @param mail 指向邮件指针的指针,用于存放新分配的邮件地址。** 返回值: 成功分配时返回0,失败则返回非0值。** 此函数为内部使用,负责从'app_test1_mailbox'邮箱队列中分配一个新的邮件,并将其地址存储在* 输入参数'mail'指向的变量中。具体实现省略。*/
static int app_test1_mail_alloc(APP_TEST1_MAIL** mail)
{// ...
}
osMailQDef
定义了一个名为 app_test1_mailbox
的邮箱队列,用于存储 APP_TEST1_MAIL
类型的数据。APP_TEST1_MAX_MAILBOX
定义了邮箱队列可容纳的最大邮件数量。这个邮箱队列可以用于多线程或任务之间的数据通信,确保数据安全地传递。
/*** 定义一个邮箱队列。* * 该宏用于静态定义一个邮箱队列以及相关的OS邮箱队列结构体。它为指定的邮箱队列分配内存,* 并初始化OS邮箱队列结构体。* * @param name 邮箱队列的名称。* @param queue_sz 邮箱队列中邮件的最大数量。* @param type 邮件中元素的类型。*/
#define osMailQDef(name, queue_sz, type) \
static uint32_t os_mailQ_m_##name[3+((sizeof(type)+3)/4)*(queue_sz)]; \
osMailQDef_t os_mailQ_def_##name = \
{ {(queue_sz), sizeof(type), (os_mailQ_m_##name)}, NULL, {NULL} }
在上述宏定义中:
(1) 第一部分定义了一个静态数组 os_mailQ_m_##name
,用于存储邮箱队列中的邮件。数组大小根据邮件类型 type
的大小和队列大小 queue_sz
动态计算得出。
(2) 第二部分定义了一个 osMailQDef_t
类型的结构体 os_mailQ_def_##name
,其中包含了邮箱队列的配置信息,如队列大小、邮件类型大小以及邮件存储区的指针。
- 参数/函数讲解
序号 | 参数/函数 | 说明 |
---|---|---|
1 | osMailQDef | 定义了的邮箱队列,用于存储 APP_TEST1_MAIL 类型的数据 |
2 | app_test1_mailbox_id | 是一个全局变量,用于存储邮箱队列的标识符,方便后续操作 |
3 | app_test1_mail_alloc | 用于从 app_test1_mailbox 中分配一个新的邮件,并将分配的邮件地址通过参数 mail 返回 |
4 | os_mailQ_m_##name | 用于存储邮箱队列中的邮件 |
5 | osMailQDef_t | 定义结构体,其中包含了邮箱队列的配置信息 |
4.2.2 创建
通过 osMailQCreate()
函数创建邮箱,指定邮箱的大小和数据类型。
- 代码
/*** app_test1_mailbox_init - 初始化app_test1_mailbox邮箱队列** @return: 成功初始化时返回0,失败则返回-1。** 此函数用于初始化之前定义的'app_test1_mailbox'邮箱队列。它调用osMailCreate函数创建邮箱队列,* 并将返回的邮箱ID存储在全局变量'app_test1_mailbox_id'中。如果创建失败,函数会输出错误信息* "Failed to Create app_test_thread1_mailbox",并返回-1表示初始化失败。*/
static int32_t app_test1_mailbox_init(void)
{app_test1_mailbox_id = osMailCreate(osMailQ(app_test1_mailbox), NULL);if (app_test1_mailbox_id == NULL) {TRACE(0, "Failed to Create app_test_thread1_mailbox");return -1;}return 0;
}
这个函数 app_test1_mailbox_init
负责初始化之前通过 osMailQDef
宏定义的 app_test1_mailbox
邮箱队列。如果初始化成功,它将返回0;如果失败(即无法创建邮箱队列),它会打印错误信息并返回-1。
- 参数/函数讲解
序号 | 参数/函数 | 说明 |
---|---|---|
1 | osMailCreate | 创建邮箱队列 |
4.2.3 发送/释放邮件
使用 osMailQAlloc()
分配邮箱中的空间,然后用 osMailPut()
发送邮件。
- 代码
/*** app_test1_mail_send - 发送一个APP_TEST1_MAIL类型的邮件到app_test1_mailbox** @param mail 需要发送的邮件对象指针。** 返回值: 成功发送时返回0,失败则返回非0值。** 此函数用于将一个APP_TEST1_MAIL类型的邮件对象发送到'app_test1_mailbox'邮箱队列中。* 具体实现省略,可能涉及到邮箱队列的同步原语以保证线程安全。*/
static int app_test1_mail_send(APP_TEST1_MAIL* mail)
{// ...
}/*** app_test1_mail_free - 释放app_test1_mailbox中的一个邮件对象** @param mail_p 已分配的邮件对象指针。** 返回值: 成功释放时返回0,失败则返回非0值。** 此函数用于释放'app_test1_mailbox'邮箱队列中已分配的一个邮件对象,以便于后续再使用。* 具体实现省略,可能涉及邮箱队列的同步原语以保证线程安全。*/
static int app_test1_mail_free(APP_TEST1_MAIL* mail_p)
{// ...
}
- 参数/函数讲解
序号 | 参数/函数 | 说明 |
---|---|---|
1 | app_test1_mail_send | 用于向 app_test1_mailbox 邮箱队列中发送邮件 |
2 | app_test1_mail_free | 用于向 app_test1_mailbox 邮箱队列中释放已分配的邮件 |
4.2.4 获取邮件
线程通过 osMailGet()
函数获取邮件,可以选择等待或立即返回。
- 代码
/*** @brief 获取应用测试1的邮件对象* * @description 该函数从内部数据结构中获取一个`APP_TEST1_MAIL`类型的邮件对象。* 如果邮件可用,它将分配内存并填充邮件内容,然后将其指针返回。* * @param[out] mail_p 指向接收`APP_TEST1_MAIL`结构体指针的指针。* 如果成功获取邮件,此参数将被设置为有效邮件对象的指针。* * @return 成功获取邮件对象返回0,否则返回非0错误代码:* -1:邮件队列为空* -2:内存分配失败* 其他值:可能表示其他错误情况** @note 实现应考虑线程安全,可能需要加锁来保护数据结构。* 如果队列为空,可以选择阻塞等待,直到有新邮件到达。*/
static int app_test1_mail_get(APP_TEST1_MAIL** mail_p)
{// 实现获取邮件对象的逻辑,包括检查队列、分配内存、填充邮件内容等// ...if (/* 邮件队列为空或分配内存失败等错误条件 */) {return -1; // 或者 -2}return 0; // 成功获取邮件
}
app_test1_mail_get
函数用于从 app_test1_mailbox
邮箱队列中取出一个邮件对象。当邮箱队列为空时,函数可能阻塞等待,直到有新的邮件可供消费。函数返回0表示成功获取邮件,非0值表示队列为空或出现错误。具体实现细节被省略,实际操作中可能需要考虑线程同步问题。
- 参数/函数讲解
序号 | 参数/函数 | 说明 |
---|---|---|
1 | app_test1_mail_get | 用于从邮箱队列中取出一个邮件对象 |
总结
感谢观看,这里就是 同步与通信篇 – 消息队列和邮箱处理,如果觉得有帮助,请给文章点个赞吧,让更多的人看到。🌹 🌹 🌹
也欢迎你,关注我。👍 👍 👍
原创不易,还希望各位大佬支持一下,你们的点赞、收藏和留言对我真的很重要!!!💕 💕 💕 最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!下期再见。🎉
更多专栏订阅:
😀 【LeetCode题解(持续更新中)】
🥇 【恒玄BES】
🌼 【鸿蒙系统】
💎 【蓝牙协议栈】
🎃 【死机分析】
👑 【Python脚本笔记】
🚝 【Java Web项目构建过程】
💛 【微信小程序开发教程】
⚽ 【JavaScript随手笔记】
🤩 【大数据学习笔记(华为云)】
🦄 【程序错误解决方法(建议收藏)】
🔐 【Git 学习笔记】
🚀 【软件安装教程】
订阅更多,你们将会看到更多的优质内容!!
相关文章:

【BES2500x系列 -- RTX5操作系统】深入探索CMSIS-RTOS RTX -- 同步与通信篇 -- 消息队列和邮箱处理 --(四)
💌 所属专栏:【BES2500x系列】 😀 作 者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! Ὁ…...

电信NR零流量小区处理
【摘要】随着目前网络建设逐步完善,5G用户的不断发展,针对零流量小区的分析及处理存在着必要性,零流量小区的出现既是用户分布及行为的直观体现,也是发展用户的一个指引,同时也能发现设备的一些故障。一个站点的能够带…...

ArcTs布局入门03——层叠布局(Stack)
如果你也对鸿蒙开发感兴趣,加入“Harmony自习室”吧! 扫描下面的二维码关注公众号。 1、概述 叠布局(StackLayout)用于在屏幕上预留一块区域来显示组件中的元素,提供元素可以重叠的布局。层叠布局通过Stack容器组件实…...

C语言之线程的学习
线程属于某一个进程 共同点:都能并发 线程共享变量,进程不共享。 多线程任务中,其中某一个线程调用了exit了,其他线程会跟着一起退出 如果是特定的线程就调用pthread_exit 失败返回的是错误号 下面也是...

HT8691 内置升压模块的D类音频功率放大器芯片IC
一般描述 HT8691是一款内置升压模块的D类音频功率放大器。内置的升压模块可通过外置电阻调节升压值,即使是锂电池供电,在升压至6.5V时,10%THDN,4Ω负载条件下能连续输出5.5W功率;升压至7V,3Ω负载条件下则能连续输出7.0W功率。其支持外部设置…...

和小红书一起参会! 了解大模型与大数据融合的技术趋势
在过去的两年中,“大模型”无疑成为互联网行业的焦点话题,曾经炙手可热的大数据架构似乎淡出公众视野。然而,大数据领域并未停滞不前,反而快速演进,传统依赖众多开源组件的大数据平台正逐步过渡到以融合与简化为核心特…...

【vocabulary in use (elementary)】7 Feeling
happy 高兴 sad 伤心 angry 生气 upset 丧气 cold 冷 hot 热 thirsty 口渴 hungry 饿 well 很好 ill 生病 tired 累了 surprised 惊讶 关于喜欢的表达: like to do 偶尔一次喜欢 like doing 一直喜欢的 outdoor activities 户外运动 be keep on doing 坚持做 be fo…...

Keil5 ST-LINK setting闪退问题解决
1. 官网下载新版驱动文件 MDK uVision crashes when using ST-Link debugger 2. 解压替换 STLinkUSBDriver6.1.2.0Signed 我的库文件目录: D:\Tool\Keil5\ARM\STLink...

熟练掌握Docker及linux常用命令排查线上问题。熟悉Git, Maven等项目管理及构建工具,熟悉微服务中基于Jenkins的CI/CD
掌握Docker、Linux命令、项目管理及构建工具,以及CI/CD流程是现代软件开发和运维的关键技能。以下是对这些技能的概述和一些实践建议: ### Docker - **概述**:Docker是一个开源的容器化平台,允许开发者打包应用及其依赖到一个可移…...

78.Vue 3 重用性模态框组件
模态框是大多数 Web 应用程序中的基本构建块。虽然最初实现起来可能看起来有点棘手,但实际上,使用 Vue 和一些 Flexbox 技巧,这不仅可行,而且非常简单。 让我们一起实现一个基础的模态框组件。 架构如下: AppModal.vue…...

《昇思25天学习打卡营第9天|onereal》
继续学习昨天的 基于MindNLPMusicGen生成自己的个性化音乐 生成音乐 MusicGen支持两种生成模式:贪心(greedy)和采样(sampling)。在实际执行过程中,采样模式得到的结果要显著优于贪心模式。因此我们默认启…...

Wireshark - tshark支持iptables提供数据包
tshark现在的数据包获取方式有两种,分别是读文件、网口监听(af-packet原始套接字)。两种方式在包获取上,都是通过读文件的形式;存在文件io操作,在专门处理大流量的情境下, 我们复用wireshark去做…...

快团团团长如何批量退款可自定义退款金额(批量退差价)?
快团团团长如何批量退款可自定义退款金额(批量退差价)? 在售后处理中,经常会出现需要给某一商品退差价的场景,因此在批量退款时需要自定义退款金额。现快团团已支持批量退自定义金额,操作方法和注意事项如…...

MySQL——事务ACID原则、脏读、不可重复读、幻读
什么是事务 要么都成功,要么都失败 一一一一一一一 1. SQL执行:A给B转账 A 1000 ---->200 B 200 2. SQL执行:B收到A的钱 A 800 B 400 一一一一一一一 将一组SQL放在一个批次中去执行~ 事务原则:ACI…...

洗衣机水龙头要买有止逆阀的,多花几十元能省掉几万,值了
问大家一下,你家洗衣机水龙头用的是什么样的? 可能有业主会说我家买的是纯铜的,质量挺好的。 如果你家选的洗衣机水龙头仅仅是纯铜的,并没有其他的功能,你还是选做错了。 因为洗衣机水龙头…...

Android 蓝牙开发全面指南
Android 平台的蓝牙功能提供了丰富的API和工具,使开发者能够轻松实现从基本连接到复杂数据交换的各种蓝牙功能。蓝牙技术已经成为智能手机和其他设备间通信的重要方式,尤其在物联网和智能家居应用中有广泛应用。 关键词总结 Android 蓝牙开发涉及多个关…...

Hadoop3:Yarn框架的三种调度算法
一、概述 目前,Hadoop作业调度器主要有三种:FIFO、容量(Capacity Scheduler)和公平(Fair Scheduler)。Apache Hadoop3.1.3默认的资源调度器是Capacity Scheduler。 CDH框架默认调度器是Fair Scheduler。 …...

JDBC链接kerberos认证的impala数据库报错问题解决
先上代码 public static Connection connectToImpala() {try {log.info("ketTabPath:" ketTabPath);log.info("krb5Path:" krb5Path);System.setProperty("java.security.krb5.conf", krb5Path);System.setProperty("sun.security.krb5.…...

firewalld(2)安装、配置文件、规则查询
安装firewalld 我使用的操作系统是debian 12,并没有安装firewalld。 通过apt install firewalld安装firewalld firewalld 本身是一个服务(firewalld.service),可以通过 systemctl 进行启动、停止和重启,而iptables 本身并不是一个…...

施耐德全新EtherCAT运动控制器M310介绍
在制造业的蓬勃发展下,高性能运动控制器成为提升生产效率、保障产品质量的关键设备之一。M310是施耐德电气新一代高性能运动控制器,它基于Intel X86硬件平台和Codesys V3.5 SP19软件平台开发,支持EtherCAT总线,拥有强大算力、高易…...

Springboot Mybatis 多数据源配置以及使用
在Spring Boot中配置MyBatis的多数据源是一个常见需求,尤其是在需要连接多个数据库时,下面是详细的步骤指南。 引入依赖 首先,在你的pom.xml文件中添加Spring Boot、MyBatis和数据库连接的相关依赖。例如,如果你使用的是MySQL数…...

Android启动时间分析
在Android启动过程中,“NHLOS” 和 “LK” 是两个与启动时间相关的术语,它们分别指的是: 各阶段时间 I Minidump: Enabled with max number of regions 200 I KPI : Bootloader start count = 59264 I KPI : Bootloader end count = 101746 I KPI : Boo…...

智能洗车管理系统设计
智能洗车管理系统设计的核心在于整合先进的信息技术与自动化设备,以提升洗车服务的效率、降低成本并增强客户体验。以下是一个概括性的设计框架: 1. 系统需求分析 用户需求:了解车主对于快速、便捷、高质量洗车服务的需求。业务需求…...

vue3弹窗usehook
说明 个人记录保存。 import {ref} from "vue";export default function useDialog(opts) {const visible ref(false)const loading ref(false)const open (v) > {visible.value truetypeof opts.onOpen "function" && opts.onOpen(v)}c…...

上帝之眼(BEVSee):多相机间无需标定,将各自目标统一到同一坐标系下(代码开源,提供数据集)
Abstract 我们解决了一个新的问题,即在鸟瞰视角(BEV)中无需预先给定相机校准的多视角相机和目标注册问题。这将多视角目标注册问题提升到一个新的无需校准的阶段,从而极大地缓解了许多实际应用中的限制。然而,这是一个…...

imagesc函数 纵坐标翻转 colormap “set” “jet“
纵坐标默认上小下大 翻转: 在Matlab中,使用imagesc函数绘制的图像的纵坐标默认是从上到下递增的,即下面的值较大,上面的值较小。如果想要翻转纵坐标,使之从上到下递增,可以通过设置坐标轴的YDir属性为’n…...

Postman接口测试工具的原理及应用详解(二)
本系列文章简介: 在当今软件开发的世界中,接口测试作为保证软件质量的重要一环,其重要性不言而喻。随着前后端分离开发模式的普及,接口测试已成为连接前后端开发的桥梁,确保前后端之间的数据交互准确无误。在这样的背景下,Postman作为一款功能强大、易于使用的接口测试工…...

IPython脚本加载秘籍:探索脚本魔法的艺术
IPython脚本加载秘籍:探索脚本魔法的艺术 IPython,这个强大的交互式Python解释器,不仅提供了丰富的交互式编程功能,还允许用户加载和运行Python脚本。这一功能极大地扩展了IPython的实用性,使得用户可以在IPython环境…...

使用shell脚本进行clang-tidy静态代码分析
文章目录 0. 引言1. 完整检测脚本代码 clang-tidy-check.sh1.1 流程图1.2 脚本功能概述 2. 该脚本优缺点 0. 引言 clang-tidy 是基于 Clang 的工具,提供了丰富的代码检查功能,可以根据用户配置文件进行定制化的检查和规则定义。 之前的文章《使用 Clang…...

PHP和phpSpider:如何应对网站变动导致的数据爬取失败?
php和phpspider:如何应对网站变动导致的数据爬取失败? 导语: 网络爬虫是一种自动化程序,用于从网站上获取数据并进行处理。PHP是一种广泛使用的编程语言,而phpSpider是一个基于PHP的开源网络爬虫框架。然而࿰…...