【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)I2CSPIUART等硬件接口,用于设备间的数据传输。
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的消息队列定义结构体。这个结构体包含了队列的大小、指针到静态队列控制块和消息数据数组的地址,以及这些数组的大小。这使得在系统运行时能够直接使用这个消息队列而无需动态分配内存。

  • 参数/函数讲解
序号参数/函数说明
1osMessageQId声明变量,用于存储消息队列的标识符(句柄),初始值设为NULL。
2osMessageQDef定义了静态变量:静态队列控制块,消息数据数组和用于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);

    // 检查创建是否成功,如果失败则打印错误信息并返回-1
    if (app_test1_queue_id == NULL) {
        TRACE(0, "Failed to Create app_test_thread1_queue");
        return -1;
    }

    // 创建成功,返回0
    return 0;
}

  这段代码定义了一个名为 app_test1_queue_init 的静态函数,用于初始化之前定义的消息队列app_test1_queue 。它通过调用o sMessageCreate 函数创建消息队列,并检查返回的句柄是否有效。如果创建失败,它会记录错误信息并返回 -1 ;否则,返回 0 表示成功。

  • 参数/函数讲解
序号参数/函数说明
1osMessageCreate创建消息队列
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的消息,优先级设为0
        osMessagePut(app_test1_queue_id, 0xFF, 0);
    }
}

  这个函数 app_test1_queue_put 尝试将一个值为 0xFF 的消息放入名为 app_test1_queue 的消息队列中。首先,它检查队列是否有足够的空间容纳至少6个新消息。如果满足条件,就调用 osMessagePut 将消息放入队列,否则不做任何操作。注意,这个函数没有处理队列已满的情况,所以如果队列已满,消息将不会被发送,也不会阻塞调用线程。

  • 参数/函数讲解
序号参数/函数说明
1osMessageGetSpace检查消息队列的空闲槽位
2osMessagePut将消息放入队列

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,其中包含了邮箱队列的配置信息,如队列大小、邮件类型大小以及邮件存储区的指针。

  • 参数/函数讲解
序号参数/函数说明
1osMailQDef定义了的邮箱队列,用于存储 APP_TEST1_MAIL 类型的数据
2app_test1_mailbox_id是一个全局变量,用于存储邮箱队列的标识符,方便后续操作
3app_test1_mail_alloc用于从 app_test1_mailbox 中分配一个新的邮件,并将分配的邮件地址通过参数 mail 返回
4os_mailQ_m_##name用于存储邮箱队列中的邮件
5osMailQDef_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。

  • 参数/函数讲解
序号参数/函数说明
1osMailCreate创建邮箱队列
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)
{
    // ...
}
  • 参数/函数讲解
序号参数/函数说明
1app_test1_mail_send用于向 app_test1_mailbox 邮箱队列中发送邮件
2app_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值表示队列为空或出现错误。具体实现细节被省略,实际操作中可能需要考虑线程同步问题。

  • 参数/函数讲解
序号参数/函数说明
1app_test1_mail_get用于从邮箱队列中取出一个邮件对象

<<【系列文章索引】>>

请添加图片描述


总结

  感谢观看,这里就是 同步与通信篇 – 消息队列和邮箱处理,如果觉得有帮助,请给文章点个赞吧,让更多的人看到。🌹 🌹 🌹

在这里插入图片描述

  也欢迎你,关注我。👍 👍 👍

  原创不易,还希望各位大佬支持一下,你们的点赞、收藏和留言对我真的很重要!!!💕 💕 💕 最后,本文仍有许多不足之处,欢迎各位认真读完文章的小伙伴们随时私信交流、批评指正!下期再见。🎉

更多专栏订阅:

  • 😀 【LeetCode题解(持续更新中)】

  • 🥇 【恒玄BES】

  • 🌼 【鸿蒙系统】

  • 💎 【蓝牙协议栈】

  • 🎃 【死机分析】

  • 👑 【Python脚本笔记】

  • 🚝 【Java Web项目构建过程】

  • 💛 【微信小程序开发教程】

  • 【JavaScript随手笔记】

  • 🤩 【大数据学习笔记(华为云)】

  • 🦄 【程序错误解决方法(建议收藏)】

  • 🔐 【Git 学习笔记】

  • 🚀 【软件安装教程】



订阅更多,你们将会看到更多的优质内容!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/764350.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

面向航天器大数据安全传输的发布/订阅系统设计

源自&#xff1a;系统工程与电子技术 作者&#xff1a;覃润楠 彭晓东 谢文明 惠建江 冯渭春 姜加红 注&#xff1a;若出现无法显示完全的情况&#xff0c;可 V 搜索“人工智能技术与咨询”查看完整文章 摘 要 针对航天器试验任务过程监控的在轨故障诊断状态检测、健…

5款简洁干净,功能强悍,专注实用的软件

​ 电脑上的各类软件有很多&#xff0c;除了那些常见的大众化软件&#xff0c;还有很多不为人知的小众软件&#xff0c;专注于实用功能&#xff0c;简洁干净、功能强悍。 1.音量控制利器——EarTrumpet ​ EarTrumpet是一款专为Windows用户设计的音量控制软件。它允许用户轻松…

等保测评应该选择什么样的SSL证书

选择适合等保测评的SSL证书&#xff0c;需考虑证书的加密强度、认证机制以及是否满足国家相关的密码技术要求 1、证书类型&#xff1a;应选择符合国家或行业标准的SSL证书&#xff0c;这些证书通常采用RSA、DSA或ECC等国际认可的加密算法。同时&#xff0c;考虑到国内特定的合规…

【C语言】常见的字符串函数

©作者:末央&#xff06; ©系列:C语言初阶(适合小白入门) ©说明:以凡人之笔墨&#xff0c;书写未来之大梦 目录 strlen函数模拟实现 strstr子串查找函数模拟实现 strtok字符串分割 strlen函数 strlen函数是一个用于求字符串长度的库函数。它的参数是被求长度的字…

免费分享:2000-2021年全国分省250mNDVI数据集(附下载方法)

NDVI (Normalized Difference Vegetation Index)归一化植被指数&#xff0c;又称标准化植被指数。是目前应用最广泛的植被指数&#xff0c;与植被的分布呈线性相关&#xff0c;是植被生长状态和空间分布的最佳指示因子&#xff0c;也是遥感估算植被覆盖度(FVC&#xff0c;Fract…

VMware Workstation 安装 Centos 虚拟机

1. 下载 VMware Workstation 直接上网找官网下载即可 2. 下载 Centos 镜像 阿里巴巴开源镜像站-OPSX镜像站-阿里云开发者社区 3.打开 VMware 创建虚拟机 3.1点击创建虚拟机 3.2 选择自定义安装 3.3 选择使用 Workstation 的版本 版本越高兼容性越低但性能越好&#xff0c;一…

APP性能测试

1、性能测试分类&#xff1a;&#xff08;CPU&#xff0c;内存&#xff0c;流量&#xff0c;时间&#xff08;启动耗时计算&#xff09;&#xff0c;电量&#xff0c;流畅度&#xff08;帧率&#xff09;&#xff09;&#xff0c;稳定性&#xff08;崩溃&#xff0c;闪退&#…

[数据库原理]数据库设计(er图)

xtu期末是机试&#xff0c;所以图形表示有点不同 实体之间的关系&#xff1a; 多对多&#xff1a;可以生成一个新的关系模型一对一&#xff1a;两边都要关联一对多、多对一 &#xff1a;一的主键可以作为多的外键 如有错误&#xff0c;欢迎指正&#xff01;&#xff01;&#x…

年轻人「入侵」厂货电商:泼天的富贵or甜蜜的烦恼?

【潮汐商业评论/原创】 “明天我们带个黑色塑料袋&#xff0c;假装是批发拿货的&#xff0c;看看能不能淘到好货。这个批发‘黑话’你也学一下&#xff0c;别到时候露馅。” Paula正兴冲冲地跟Grace计划去服装批发市场“消费”。 只不过&#xff0c;与以往普通进店客人身份不…

瀚高数据库2024最新版_6.0.4_Windows版安装使用---国产瀚高数据库工作笔记007

首先去下载安装包: 下载的是企业版,可以试用一年 首先安装的时候,直接,下一步下一步就可以了 注意要用administrator去安装. 下载以后一步步去安装就可以了 ,桌面上会出现 但是连接不上,并且, 如果从管理工具中,找到服务 cmd services.msc 打开以后,找到瀚高服务,但是…

C# 验证PDF数字签名的有效性

数字签名作为PDF文档中的重要安全机制&#xff0c;不仅能够验证文件的来源&#xff0c;还能确保文件内容在传输过程中未被篡改。然而&#xff0c;如何正确验证PDF文件的数字签名&#xff0c;是确保文件完整性和可信度的关键。本文将详细介绍如何使用免费.NET控件通过C#验证PDF签…

【机器学习】机器学习的重要方法——线性回归算法深度探索与未来展望

欢迎来到 破晓的历程博客 引言 在数据科学日益重要的今天&#xff0c;线性回归算法以其简单、直观和强大的预测能力&#xff0c;成为了众多领域中的基础工具。本文将详细介绍线性回归的基本概念、核心算法&#xff0c;并通过五个具体的使用示例来展示其应用&#xff0c;同时探…

深入STM32的ADC世界:从理论到实践,打造精准数据采集系统

摘要: 在嵌入式系统中&#xff0c;模拟信号的采集与处理至关重要。本文将深入浅出地介绍STM32的ADC模块&#xff0c;结合实际项目&#xff0c;详细阐述ADC的工作原理、配置方法以及数据处理技巧&#xff0c;并辅以Mermaid图表和代码示例&#xff0c;助你轻松掌握ADC应用开发。 …

最小步数模型——AcWing 1107. 魔板

最小步数模型 定义 最小步数模型通常是指在某种约束条件下&#xff0c;寻找从初始状态到目标状态所需的最少操作或移动次数的问题。这类问题广泛存在于算法、图论、动态规划、组合优化等领域。具体来说&#xff0c;它涉及确定一个序列或路径&#xff0c;使得按照特定规则执行…

智能数字人直播带货软件源码系统 实现真人直播形象 带完整当然安装代码包以及搭建教程

系统概述 智能数字人直播带货软件源码系统&#xff0c;是一个集成了先进的人工智能、3D建模、语音合成、自然语言处理等技术于一体的创新平台。它旨在通过构建高度定制化的虚拟主播&#xff0c;为用户提供沉浸式、高效能的直播体验。与传统直播相比&#xff0c;该系统的核心优…

基于自回归超先验的有损图像压缩框架

文章信息 论文题目为《Joint Autoregressive and Hierarchical Priors for Learned Image Compression》&#xff0c;文章来自NIPS2018谷歌团队,是第一篇端到端图像压缩论文《variational image compression with a scale hyperprior》的改进版本&#xff0c;在《variational i…

Java 并发集合:CopyOnWrite 写时复制集合介绍

大家好&#xff0c;我是栗筝i&#xff0c;这篇文章是我的 “栗筝i 的 Java 技术栈” 专栏的第 016 篇文章&#xff0c;在 “栗筝i 的 Java 技术栈” 这个专栏中我会持续为大家更新 Java 技术相关全套技术栈内容。专栏的主要目标是已经有一定 Java 开发经验&#xff0c;并希望进…

【Qwen2部署实战】Qwen2初体验:用Transformers打造智能聊天机器人

系列篇章&#x1f4a5; No.文章1【Qwen部署实战】探索Qwen-7B-Chat&#xff1a;阿里云大型语言模型的对话实践2【Qwen2部署实战】Qwen2初体验&#xff1a;用Transformers打造智能聊天机器人3【Qwen2部署实战】探索Qwen2-7B&#xff1a;通过FastApi框架实现API的部署与调用4【Q…

IIC电平转换电路原理

一、电平转换的必要性 在IIC主从设备连接时&#xff0c;由于主从设备可能存在不同的电源电压&#xff08;如5V、3.3V、1.8V等&#xff09;&#xff0c;导致需要进行电平转换以确保正常通信。 二、电平转换电路的基本组成 电平转换电路通常包括上拉电阻、MOS管&#xff08;通常…

C++基础(二):C++入门(一)

C是在C的基础之上&#xff0c;容纳进去了面向对象编程思想&#xff0c;并增加了许多有用的库&#xff0c;以及编程范式 等。熟悉C语言之后&#xff0c;对C学习有一定的帮助&#xff0c;本篇博客主要目标&#xff1a; 1. 补充C语言语法的不足&#xff0c;以及C是如何对C语言设计…