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

RTOS之邮箱

邮箱

邮箱 (Mailbox) 服务是实时操作系统中一种常用的线程间通信机制。它提供了一种高效、低开销的消息传递方式,允许线程之间交换固定大小的数据。

1. 邮箱的应用场景

考虑一个简单的示例:线程 1 负责检测按键状态并将状态信息发送出去,线程 2 接收按键状态信息并根据按键状态控制 LED 的亮灭。在这种场景下,线程 1 可以将按键状态作为邮件发送到邮箱,线程 2 从邮箱中读取邮件并执行相应的 LED 控制操作。

此外,邮箱服务也支持多线程发送。例如,存在三个线程,线程 1 发送按键状态,线程 2 发送 ADC 采样数据,而线程 3 则根据接收到的邮件类型执行不同的操作。

2. 邮箱的工作机制

RT-Thread 的邮箱服务用于线程间的异步通信,其特点是开销较低,效率较高。邮箱中的每封邮件只能存储固定大小的数据,在 32 位系统中,这个大小为 4 字节(正好可以容纳一个指针)。邮箱可以被看作是一个消息交换中心。线程或中断服务例程将 4 字节的邮件发送到邮箱中,而一个或多个线程可以从邮箱中接收这些邮件并进行处理。

邮箱工作示意图
邮箱工作示意图

邮件发送操作分为非阻塞和阻塞两种模式。非阻塞模式的邮件发送可安全应用于中断服务例程中,是线程、中断服务例程和定时器向线程发送消息的有效方式。邮件接收操作通常可能是阻塞的,这取决于邮箱中是否有邮件以及接收时设置的超时时间。当邮箱为空且超时时间不为 0 时,邮件接收操作会变为阻塞模式。在这种情况下,邮件接收操作只能由线程执行。

  • 邮件发送: 当线程向邮箱发送邮件时,如果邮箱未满,邮件会被复制到邮箱中。如果邮箱已满,发送线程可以选择设置超时时间并进入等待状态,直到邮箱有空闲位置,或直接返回 -RT_EFULL 错误。如果发送线程选择等待,当邮箱中的邮件被接收而空出空间时,等待的发送线程会被唤醒并继续发送。

  • 邮件接收: 当线程从邮箱接收邮件时,如果邮箱为空,接收线程可以选择等待直到收到新的邮件,或设置超时时间。当超时时间到达,邮箱仍未收到邮件时,等待的接收线程会被唤醒并返回 -RT_ETIMEOUT 错误。如果邮箱中有邮件,接收线程会将邮箱中的 4 字节邮件复制到接收缓存区中。

3. 邮箱控制块

在 RT-Thread 中,邮箱控制块是用于管理邮箱的数据结构,用结构体 struct rt_mailbox 表示。另一种 C 表达方式 rt_mailbox_t 表示邮箱的句柄,其本质是一个指向 struct rt_mailbox 结构体的指针。邮箱控制块的详细定义如下:

struct rt_mailbox
{

    struct rt_ipc_object parent;

    rt_uint32_t* msg_pool;       /* 邮箱缓冲区的起始地址 */
    rt_uint16_t size;            /* 邮箱缓冲区的大小(邮件数量) */

    rt_uint16_t entry;           /* 邮箱中邮件的数目 */
    rt_uint16_t in_offset;       /* 邮箱缓冲区的写入偏移量 */
    rt_uint16_t out_offset;      /* 邮箱缓冲区的读取偏移量 */
    rt_list_t suspend_sender_thread; /* 发送线程的挂起等待队列 */
};
typedef struct rt_mailboxrt_mailbox_t;

rt_mailbox 对象继承自 rt_ipc_object,由 IPC 容器进行管理。

4. 邮箱的管理方式

邮箱控制块结构体中包含邮箱管理的关键参数。对邮箱的操作包括:创建/初始化、发送邮件、接收邮件以及删除/脱离邮箱。

邮箱相关接口
邮箱相关接口
4.1 创建和删除邮箱
4.1.1 创建动态邮箱

可以使用 rt_mb_create() 函数动态创建一个邮箱对象:

rt_mailbox_t rt_mb_create(const char* name, rt_size_t size, rt_uint8_t flag);

此函数首先从对象管理器中分配一个邮箱对象,然后动态分配一块内存空间用于存储邮件,该内存空间大小为 size * 4 字节。接着,初始化邮件计数和发送偏移量。rt_mb_create() 函数的参数和返回值说明如下:

参数描述
name邮箱名称。
size邮箱容量,即邮箱可以存储的邮件数量。
flag邮箱标志,取值可以为 RT_IPC_FLAG_FIFORT_IPC_FLAG_PRIORT_IPC_FLAG_FIFO 表示先进先出, RT_IPC_FLAG_PRIO 表示优先级调度。
返回值描述
RT_NULL创建失败。
邮箱对象的句柄创建成功,返回邮箱对象的句柄(邮箱控制块指针)。

注意: RT_IPC_FLAG_FIFO 属于非实时调度方式,除非应用程序非常在意先进先出,且清楚地知道所有涉及该邮箱的线程将变为非实时线程,否则建议使用 RT_IPC_FLAG_PRIO,以保证线程的实时性。

4.1.2 删除动态邮箱

当使用 rt_mb_create() 创建的邮箱不再使用时,应该调用 rt_mb_delete() 函数删除邮箱以释放系统资源:

rt_err_t rt_mb_delete(rt_mailbox_t mb);

删除邮箱时,如果存在挂起在该邮箱上的线程,内核会先唤醒所有挂起线程(返回错误码 -RT_ERROR),然后释放邮箱使用的内存,最后删除邮箱对象。rt_mb_delete() 函数的参数和返回值说明如下:

参数描述
mb邮箱对象的句柄。
返回值描述
RT_EOK删除成功。
4.2 初始化和脱离邮箱
4.2.1 初始化静态邮箱

可以使用 rt_mb_init() 函数初始化静态邮箱对象:

rt_err_t rt_mb_init(rt_mailbox_t mb,
                    const char* name,
                    void* msgpool,
                    rt_size_t size,
                    rt_uint8_t flag)
;

rt_mb_create() 不同,静态邮箱对象的内存是由编译器在编译时分配的,通常位于读写数据段或未初始化数据段。rt_mb_init() 需要传入用户已经分配好的邮箱控制块、缓冲区指针、邮箱名称和邮箱容量(邮件数量)。rt_mb_init() 函数的参数和返回值说明如下:

参数描述
mb邮箱对象的句柄(邮箱控制块指针)。
name邮箱名称。
msgpool邮箱缓冲区指针。
size邮箱容量,即邮箱可以存储的邮件数量。
flag邮箱标志,取值可以为 RT_IPC_FLAG_FIFORT_IPC_FLAG_PRIORT_IPC_FLAG_FIFO 表示先进先出, RT_IPC_FLAG_PRIO 表示优先级调度。
返回值描述
RT_EOK初始化成功。

size 参数指定的邮箱容量,实际上是 msgpool 指向的缓冲区可以容纳的邮件数量。如果 msgpool 指向的缓冲区的字节数为 N,则邮箱容量应为 N / 4

4.2.2 脱离静态邮箱

可以使用 rt_mb_detach() 函数将静态初始化的邮箱对象从内核对象管理器中脱离:

rt_err_t rt_mb_detach(rt_mailbox_t mb);

rt_mb_detach() 会先唤醒所有挂起在该邮箱上的线程(线程返回错误码 -RT_ERROR),然后将邮箱对象从内核对象管理器中移除。rt_mb_detach() 函数的参数和返回值说明如下:

参数描述
mb邮箱对象的句柄。
返回值描述
RT_EOK脱离成功。
4.3 发送邮件

线程或中断服务程序可以使用 rt_mb_send() 函数向邮箱发送邮件:

rt_err_t rt_mb_send(rt_mailbox_t mb, rt_uint32_t value);

发送的邮件可以是任意 32 位格式的数据,例如整数值或指向缓冲区的指针。当邮箱已满时,发送线程或中断程序将收到 -RT_EFULL 返回值。rt_mb_send() 函数的参数和返回值说明如下:

参数描述
mb邮箱对象的句柄。
value邮件内容 (32 位数据)。
返回值描述
RT_EOK发送成功。
-RT_EFULL邮箱已满。
4.4 等待方式发送邮件

可以使用 rt_mb_send_wait() 函数以等待方式向指定邮箱发送邮件:

rt_err_t rt_mb_send_wait(rt_mailbox_t mb,
                      rt_uint32_t value,
                      rt_int32_t timeout)
;

rt_mb_send_wait()rt_mb_send() 的区别在于增加了超时等待功能。如果邮箱已满,发送线程会根据 timeout 参数等待,直到邮箱有空闲位置或超时。如果超时时间到达仍没有空闲位置,发送线程将被唤醒并返回错误码 -RT_ETIMEOUTrt_mb_send_wait() 函数的参数和返回值说明如下:

参数描述
mb邮箱对象的句柄。
value邮件内容。
timeout超时时间。
返回值描述
RT_EOK发送成功。
-RT_ETIMEOUT超时。
-RT_ERROR发送失败。
4.5 发送紧急邮件

可以使用 rt_mb_urgent() 函数发送紧急邮件:

rt_err_t rt_mb_urgent(rt_mailbox_t mb, rt_ubase_t value);

发送紧急邮件的操作与普通发送邮件类似。不同之处在于,发送紧急邮件时,邮件会被直接插入到邮件队列的头部,这样接收者就可以优先接收到紧急邮件并及时处理。rt_mb_urgent() 函数的参数和返回值说明如下:

参数描述
mb邮箱对象的句柄。
value邮件内容。
返回值描述
RT_EOK发送成功。
-RT_EFULL邮箱已满。
4.6 接收邮件

接收线程可以使用 rt_mb_recv() 函数从邮箱接收邮件:

rt_err_t rt_mb_recv(rt_mailbox_t mb, rt_uint32_t* value, rt_int32_t timeout);

当邮箱中有邮件时,接收线程会立即读取邮件并返回 RT_EOK。否则,接收线程会根据 timeout 参数决定,要么挂起在邮箱的等待队列上,要么直接返回。如果设置了超时时间,在指定时间内仍未收到邮件,则会返回 -RT_ETIMEOUT 错误。 rt_mb_recv() 函数的参数和返回值说明如下:

参数描述
mb邮箱对象的句柄。
value指向邮件存储位置的指针。
timeout超时时间。
返回值描述
RT_EOK接收成功。
-RT_ETIMEOUT超时。
-RT_ERROR接收失败。
5. 邮箱使用示例

以下示例模拟一个“外卖点餐系统”,其中:

  • “顾客”线程 (customer_thread): 模拟顾客点餐,并将订单发送到邮箱。
  • “餐厅”线程 (restaurant_thread): 模拟餐厅接收订单,并根据订单内容进行处理。
#include <rtthread.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define THREAD_PRIORITY         10
#define THREAD_STACK_SIZE       1024
#define THREAD_TIMESLICE        5

/* 邮箱控制块 */
static struct rt_mailbox order_mb;
/* 邮箱内存池 */
static char order_mb_pool[128];


/* 定义一个订单结构体 */
typedef struct
{

    char dish[32];
    int quantity;
    char note[64];
} Order;


/* 顾客线程 */
static void customer_thread_entry(void *parameter)
{
    Order my_order;
    int order_count = 0;

    while (order_count < 3)
    {
        order_count++;
        rt_kprintf("顾客: 准备订单 #%d...\n", order_count);

        // 模拟顾客点餐
        if(order_count == 1)
        {
        strcpy(my_order.dish, "宫保鸡丁");
        my_order.quantity = 2;
        strcpy(my_order.note, "不要太辣!");
        }
        else if(order_count == 2)
        {
            strcpy(my_order.dish, "麻婆豆腐");
            my_order.quantity = 1;
            strcpy(my_order.note, "多加点辣!");

        }
        else
        {
           strcpy(my_order.dish, "蛋炒饭");
            my_order.quantity = 3;
            strcpy(my_order.note, "加鸡蛋!");

        }
        // 将订单复制到堆区,避免栈数据失效
         Order *order_ptr = (Order*)rt_malloc(sizeof(Order));
        if(order_ptr == RT_NULL)
        {
            rt_kprintf("顾客: 内存分配失败!\n");
            continue;
        }
        memcpy(order_ptr,&my_order,sizeof(Order));
        // 发送订单到邮箱
        if (rt_mb_send(&order_mb, (rt_uint32_t)order_ptr) == RT_EOK)
        {
             rt_kprintf("顾客: 订单 #%d 发送给餐厅: %s, 数量: %d\n",
                       order_count, order_ptr->dish, order_ptr->quantity);
        }
        else
        {
            rt_kprintf("顾客: 发送订单给餐厅失败!\n");
              rt_free(order_ptr); // 释放内存
        }


        // 模拟顾客等待其他顾客点餐
          rt_thread_mdelay(rt_tick_from_millisecond(1000));
    }

    rt_kprintf("顾客: 今天就到这里了!\n");

}


/* 餐厅线程 */
static void restaurant_thread_entry(void *parameter)
{
    Order *received_order;
    int order_received = 0;

    while (1)
    {
        // 从邮箱中接收订单
        if (rt_mb_recv(&order_mb, (rt_uint32_t *)&received_order, RT_WAITING_FOREVER) == RT_EOK)
        {
           order_received++;
           rt_kprintf("餐厅: 收到订单 #%d! 菜品: %s, 数量: %d, 备注: %s\n",
                       order_received, received_order->dish, received_order->quantity, received_order->note);
           // 模拟餐厅处理订单(这里只是打印消息)
            rt_thread_mdelay(rt_tick_from_millisecond(500));

             // 处理完订单后释放内存
            rt_free(received_order);

        }
    }
}


int main(void)
{
    rt_err_t result;

    /* 初始化邮箱 */
    result = rt_mb_init(&order_mb,
                        "order_mb",
                        &order_mb_pool[0],
                        sizeof(order_mb_pool) / 4,
                        RT_IPC_FLAG_FIFO);

    if (result != RT_EOK)
    {
        rt_kprintf("邮箱初始化失败!\n");
        return -1;
    }

    /* 创建顾客线程 */
    rt_thread_t customer_thread = rt_thread_create("customer",
                                                     customer_thread_entry,
                                                     RT_NULL,
                                                     THREAD_STACK_SIZE,
                                                     THREAD_PRIORITY,
                                                     THREAD_TIMESLICE);

    if (customer_thread != RT_NULL)
    {
        rt_thread_startup(customer_thread);
    }

    /* 创建餐厅线程 */
    rt_thread_t restaurant_thread = rt_thread_create("restaurant",
                                                      restaurant_thread_entry,
                                                      RT_NULL,
                                                      THREAD_STACK_SIZE,
                                                      THREAD_PRIORITY,
                                                      THREAD_TIMESLICE);

    if (restaurant_thread != RT_NULL)
    {
        rt_thread_startup(restaurant_thread);
    }

    return 0;
}

实验现象:
邮箱使用示例实验现象
邮箱使用示例实验现象
6. 邮箱的应用场合

邮箱是一种简单高效的线程间消息传递方式。在 RT-Thread 中,邮箱可以传递一个 4 字节大小的邮件,并且邮箱具有一定的缓冲功能。邮箱的容量决定了它可以缓存的邮件数量。

由于邮箱每次只能传递 4 字节数据,所以它适用于传递小于等于 4 字节的消息。在 32 位系统中,4 字节恰好可以容纳一个指针,因此可以利用邮箱传递指向缓冲区的指针,从而间接实现传递较大的消息。例如:

struct msg
{

    rt_uint8_t *data_ptr;
    rt_uint32_t data_size;
};

当一个线程需要传递以上结构体 msg 时,可以先动态分配结构体,再将指向数据的指针 data_ptr 和数据块长度 data_size 写入,然后将指向这个结构体的指针作为邮件发送到邮箱中:

struct msgmsg_ptr;

msg_ptr = (struct msg*)rt_malloc(sizeof(struct msg));
msg_ptr->data_ptr = ...; /* 指向相应的数据块地址 */
msg_ptr->data_size = len; /* 数据块的长度 */
/* 发送这个消息指针给 mb 邮箱 */
rt_mb_send(mb, (rt_uint32_t)msg_ptr);

接收线程在接收邮件时,需要将接收到的指针转换为 struct msg* 类型,使用完成后,需要释放动态分配的内存:

struct msgmsg_ptr;
if (rt_mb_recv(mb, (rt_uint32_t*)&msg_ptr) == RT_EOK)
{
    /* 在接收线程处理完毕后,需要释放相应的内存块 */
    rt_free(msg_ptr);
}

好的,这次的内容就到这里啦

感谢你的阅读,欢迎点赞、关注、转发

我们,下次再见!

本文使用 markdown.com.cn 排版

相关文章:

RTOS之邮箱

邮箱 邮箱 (Mailbox) 服务是实时操作系统中一种常用的线程间通信机制。它提供了一种高效、低开销的消息传递方式&#xff0c;允许线程之间交换固定大小的数据。 1. 邮箱的应用场景 考虑一个简单的示例&#xff1a;线程 1 负责检测按键状态并将状态信息发送出去&#xff0c;线程…...

Linux setfacl 命令详解

文章目录 Linux setfacl 命令详解一、ACL 和 setfacl 简介二、基本语法三、常用操作1. 查看 ACL2. 为用户设置权限3. 为组设置权限4. 删除 ACL 条目5. 设置默认 ACL6. 递归设置 ACL 四、示例操作1. 创建示例目录和文件2. 设置 ACL3. 验证 ACL 五、注意事项六、总结 Linux setfa…...

OpenCV 学习记录:首篇

最近在学习机器视觉&#xff0c;希望能通过记录博客的形式来鞭策自己坚持学完&#xff0c;同时也把重要的知识点记录下来供参考学习。 1. OpenCV 介绍与模块组成 什么是 OpenCV&#xff1f; OpenCV (Open Source Computer Vision Library) 是一个开源的计算机视觉和机器学习软…...

Java游戏开发基础:从零开始制作一个简单的2D游戏

目录 游戏开发概述 开发工具 项目结构 1. 创建游戏窗口 2. 游戏面板 解释&#xff1a; 3. 玩家类 解释&#xff1a; 4. 障碍物类 解释&#xff1a; 5. 游戏循环与碰撞检测 总结 在现代游戏开发中&#xff0c;Java被广泛应用于创建各种类型的游戏&#xff0c;特别是…...

入门STL(map/multiset)

目录 ​编辑 1.map 输入 输出 样例 输入 输出 解题代码&#xff1a; 2.multiset 输入 输出 样例 输入 输出 解题代码&#xff1a; 留下你的足迹吧&#xff01;谢谢。 1.map map函数是一个内置函数&#xff0c;它允许你对一个序列&#xff09;的每个元素应用…...

【mysql】1205 -Lock wait timeout exceeded; try restarting transaction

问题&#xff1a; mysql8执行SQL提示下面错误&#xff1a; 1205 -Lock wait timeout exceeded; try restarting transaction 1205-超过锁定等待超时&#xff1b;尝试重新启动事务 可能的原因&#xff1a; 事务冲突&#xff1a;多个事务同时尝试修改同一行数据&#xff0c;导…...

【开源免费】基于SpringBoot+Vue.JS在线宠物用品交易网站(JAVA毕业设计)

本文项目编号 T 092 &#xff0c;文末自助获取源码 \color{red}{T092&#xff0c;文末自助获取源码} T092&#xff0c;文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…...

postman读取文件执行

要从文件获取的变量 text 在pre-request 中写从文件获取数据的脚本。脚本实现了&#xff0c;设置了text默认值&#xff0c;从文件读取text列&#xff0c;将text存入环境变量 //获取text参数 var text "济南天气"; if(data.text){ text data.text } pm.environment.…...

UDP系统控制器_音量控制、电脑关机、文件打开、PPT演示、任务栏自动隐藏

UDP系统控制器(ShuiYX) 帮助文档 概述 本程序设计用于通过UDP协议接收指令来远程控制计算机的音量、执行特定命令和其他功能。为了确保程序正常工作&#xff0c;请确认防火墙和网络设置允许UDP通信&#xff0c;并且程序启动后会最小化到托盘图标。 命令格式及说明 音量控制…...

pydantic BaseModel

1. Pydantic 是什么&#xff1f; Pydantic 是一个Python库&#xff0c;主要用于数据验证和设置管理。它通过定义数据模型&#xff08;Model&#xff09;来确保输入数据的类型和结构符合预期。 Pydantic 的核心功能是基于Python的类型提示&#xff08;Type Hints&#xff09;&a…...

[创业之路-202]:任正非管理华为的思想与毛泽东管理党、军队、国家的思想的相似性与差异性

目录 一、相似性 1、指导思想 2、管理策略 3、危机意识与自我否定 4、理想主义与奋斗精神 二、差异性 1、哲学基础与思想倾向 2、管理方法与策略 3、组织文化与价值观 一、相似性 任正非管理华为的思想与毛泽东管理党、军队、国家的思想在多个方面存在相似性。 以下…...

【渗透测试】|brupsuit的使用

一、 1.1爆破模块&#xff1a; 1、将拦截发送到intruder模块 2、在intruder模块设置pyaload位置 3、选择攻击类型 4、 5、设置好攻击类型和payload集就可以点击开始攻击&#xff0c;点击后弹出具体攻击详情 6、【payloads】模块相关 6.1 payload集为【简单列表】 添加&…...

MySQL三大日志-Binlog

Binlog简介 Redo Log 是属于InnoDB引擎所特有的日志&#xff0c;而MySQL Server也有自己的日志&#xff0c;即 Binary log&#xff08;二进制日志&#xff09;&#xff0c;简称Binlog。Binlog是记录所有数据库表结构变更以及表数据修改的二进制日志&#xff0c;不会记录SELECT…...

vue.js 指令的修饰符

Vue.js 提供了一些指令修饰符&#xff0c;用于在指令的行为上添加额外的功能。下面详细解析一些常用的指令修饰符&#xff0c;并提供相应的代码实例。 .prevent&#xff1a;阻止默认事件 通过添加 .prevent 修饰符&#xff0c;可以阻止指令绑定的元素触发默认事件。 代码实例&a…...

重撸设计模式--代理模式

文章目录 定义UML图代理模式主要有以下几种常见类型&#xff1a;代理模式涉及的主要角色有&#xff1a;C 代码示例 定义 代理模式&#xff08;Proxy Pattern&#xff09;属于结构型设计模式&#xff0c;它为其他对象提供一种代理以控制对这个对象的访问。 通过引入代理对象&am…...

“从零到一:揭秘操作系统的奇妙世界”【操作系统系统调用】

【1】定义 系统调用是用户空间程序请求操作系统服务的一种机制。系统调用的调用程序运行在用户态&#xff0c;被调用程序运行在内核态。系统调用可以嵌套使用。系统调用是通过中断机制实现的&#xff0c;并且一个OS的所有系统调用都通过一个中断入口来实现参数通常通过寄存器传…...

MQTT协议常见问题

在MQTT协议中&#xff0c;发送DISCONNECT报文与在TCP层调用network_disconnect&#xff08;或类似的函数&#xff0c;具体名称可能因实现而异&#xff09;之间存在重要的关系&#xff0c;这涉及到协议的正确性和资源的正确释放。 ### MQTT DISCONNECT报文 MQTT DISCONNECT报文…...

ArcGIS计算土地转移矩阵

在计算土地转移矩阵时&#xff0c;最常使用的方法就是在ArcGIS中将土地利用栅格数据转为矢量&#xff0c;然后采用叠加分析计算&#xff0c;但这种方法计算效率低。还有一种方法是采用ArcGIS中的栅格计算器&#xff0c;将一个年份的地类编号乘以个100或是1000再加上另一个年份的…...

数据结构十大排序之(冒泡,快排,并归)

接上期&#xff1a; 数据结十大排序之&#xff08;选排&#xff0c;希尔&#xff0c;插排&#xff0c;堆排&#xff09;-CSDN博客 前言&#xff1a; 在计算机科学中&#xff0c;排序算法是最基础且最重要的算法之一。无论是大规模数据处理还是日常的小型程序开发&#xff0c;…...

MySql:基本查询

✨✨作者主页&#xff1a;嶔某✨✨ ✨✨所属专栏&#xff1a;MySql✨✨ 本文的代码中&#xff0c; [ ] 里面的都可以省略 在 MySQL 中&#xff0c;CRUD 是数据库操作的核心&#xff0c;代表以下四种基本操作&#xff1a; C&#xff08;Create&#xff09;&#xff1a;创建、插…...

28、基于springboot的房屋租赁系统

房屋是人类生活栖息的重要场所&#xff0c;随着城市中的流动人口的增多&#xff0c;人们对房屋租赁需求越来越高&#xff0c;为满足用户查询房屋、预约看房、房屋租赁的需求&#xff0c;特开发了本基于Spring Boot的房屋租赁系统。 本文重点阐述了房屋租赁系统的开发过程&…...

96 vSystem

vSystem系统 1 技术背景 网络虚拟化旨在构建出一套与网络底层物理拓扑相互独立的逻辑网络环境&#xff0c;提供给不同需求的用户使用。基于这种思想&#xff0c;诞生出了 VLAN 技术和 VPN 技术。近年来&#xff0c; 随着以 VMM&#xff08;Virtual Machine Monitor&#xff0c…...

[创业之路-197]:华为的发展路径启示

目录 前言&#xff1a; 一、由小公司走向大公司&#xff1a; 二、由农村包围城市&#xff1a; 三、由国内走向国际&#xff1a; 四、由代理商走向设备商&#xff0c;再到系统方案商&#xff0c;再到生态系统的搭建&#xff1a; 五、由随性到跟随&#xff0c;到赶超&#…...

两款Windows电脑便签,常用的电脑桌面便签小工具推荐

现在的职场环境中&#xff0c;效率高低会影响我们的去留以及晋升&#xff0c;而电脑便签无疑是提高效率的重要辅助工具。对于Windows电脑的用户来说&#xff0c;选择合适的电脑桌面便签小工具尤为重要。今天为大家推荐两款使用过且好用实用的Windows电脑便签&#xff0c;希望可…...

sql server索引优化语句

第一步 建一个测试表 --create table TestUsers --( -- Id int primary key identity(1,1), -- Username varchar(30) not null, -- Password varchar(10) not null, -- CreateDateTime datetime not null --)第二步 插入100w数据 大概1分钟执行时间 ----插入数据…...

从监控异常发现网络安全

前言 最近在前端异常监控系统中&#xff0c;发现一些异常信息&#xff0c;从中做了一些分析&#xff0c;得到一些体会&#xff0c;因此作文。 发现异常 某天早上打开监控系统发现&#xff0c;当天凌晨1点过测试环境有2个前端上报的异常&#xff0c;报错的原因都是由于没有获取…...

Android学习(七)-Kotlin编程语言-Lambda 编程

Lambda 编程 而 Kotlin 从第一个版本开始就支持了 Lambda 编程&#xff0c;并且 Kotlin 中的 Lambda 功能极为强大。Lambda 表达式使得代码更加简洁和易读。 2.6.1 集合的创建与遍历 集合的函数式 API 是入门 Lambda 编程的绝佳示例&#xff0c;但在开始之前&#xff0c;我们…...

中国人工智能学会技术白皮书

中国人工智能学会的技术白皮书具有多方面的重要作用&#xff0c;是极具权威性和价值的参考资料。 看看编委会和编写组的阵容&#xff0c;还是很让人觉得靠谱的 如何下载这份资料呢&#xff1f;下面跟着步骤来吧 步骤一&#xff1a;进入中国智能学会官网。百度搜索“中国智能学…...

【集合】Java 8 - Stream API 17种常用操作与案例详解

文章目录 Java8 Stream API 17种常用操作与案例详解1. collect()&#xff1a;将流中的元素收集到集合中2. filter()&#xff1a;根据条件过滤流中的元素3. map()&#xff1a;元素映射为另一个值4. forEach()&#xff1a;对流中的元素执行操作5. flatMap()&#xff1a;将流中的元…...

Spring(三)-SpringWeb-概述、特点、搭建、运行流程、组件、接受请求、获取请求数据、特殊处理、拦截器

文章目录 一、SpringWeb概述 二、SpringWeb特点 三、搭建SpringWeb&#xff08;在web项目中&#xff09; 1、导包 2、在web.xml文件中配置统一拦截分发器 DispatcherServlet 3、开启 SpringWEB 注解 4、处理器搭建 四、SpringWeb运行流程 五、SpringWeb组件 1、前端控…...

uni-app商品搜索页面

目录 一:功能概述 二:功能实现 一:功能概述 商品搜索页面,可以根据商品品牌,商品分类,商品价格等信息实现商品搜索和列表展示。 二:功能实现 1:商品搜索数据 <view class="search-map padding-main bg-base"> <view class…...

基于Spring Boot的远程教育网站

一、系统背景与意义 随着互联网技术的飞速发展和普及&#xff0c;远程教育已成为现代教育体系中的重要组成部分。它打破了时间和空间的限制&#xff0c;让学习者可以随时随地进行学习。基于Spring Boot的远程教育网站正是为了满足这一需求而设计的&#xff0c;它利用互联网技术…...

降低Mobx技术债问题-React前端数据流方案调研整理

我们现在主要是使用Mobx&#xff0c;但是Mobx的易于上手和灵活度也带来了很多预期以外的问题&#xff0c;随着项目的增长我们的代码技术债变得愈加沉重&#xff0c;不同的模块杂糅一起、单一store无限膨胀。 为此我们的调研是希望能找到一个更好的state配置、数据流的约定方案。…...

Linux通信System V:消息队列 信号量

Linux通信System V&#xff1a;消息队列 & 信号量 一、信号量概念二、信号量意义三、操作系统如何管理ipc资源&#xff08;2.36版本&#xff09;四、如何对信号量资源进行管理 一、信号量概念 信号量本质上就是计数器&#xff0c;用来保护共享资源。多个进程在进行通信时&a…...

STM32, GD32 cubemx CAN 低速率125kbps 报文丢失,解决了

用STM32 CUBEMX生成的GD32的 can程序&#xff0c;在500K波特率时可以正常使用&#xff0c;没有发现丢包&#xff0c;但速率降到250k和125k时&#xff0c;发送138帧数据&#xff0c;会丢失5个包。&#xff08;系统时钟168M&#xff0c;APB1的时钟42M&#xff09; 试了各种方法无…...

医疗服务品质提升:SSM 与 Vue 打造医院预约挂号系统方案

摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了医院预约挂号系统的开发全过程。通过分析医院预约挂号系统管理的不足&#xff0c;创建了一个计算机管理医院预约挂号系统的方案。文章介绍了医院预约挂号系统的系…...

在UE5中调用ImGui图形界面库

ImGui是一个小巧灵活、简洁美观的图形界面库 首先我们直接参考Github https://github.com/SLSNe/Unreal5-ImGui 把项目下载下来后 打开项目目录或者引擎目录 项目根目录/Plugins/ImGui/ 或 UE5引擎根目录/Engine/Plugins/ 如果没有Plugins文件夹就新建一个 把项目放里面…...

汇聚点滴启迪思维(三)

switch存在的问题 缺少default语句 ‌switch语句可以包含一个可选的default语句&#xff0c;用于处理没有与任何case标签匹配的情况。如果没有default语句&#xff0c;并且没有与表达式匹配的case标签&#xff0c;程序将不会执行任何操作。 除了case switch包含的大括号中间…...

C#代码实现把中文录音文件(.mp3 .wav)转为文本文字内容

我们有一个中文录音文件.mp3格式或者是.wav格式&#xff0c;如果我们想要提取录音文件中的文字内容&#xff0c;我们可以采用以下方法&#xff0c;不需要使用Azure Speech API 密钥注册通过离线的方式实现。 1.首先我们先在NuGet中下载两个包 NAudio 2.2.1、Whisper.net 1.7.3…...

第18篇 :深入剖析systemverilog中 randomize 再谈失败案例(六)

今天,我们再谈一随机失败案例,希望再次同大家续探讨这块内容。 一 案例分析 我们先看一例子,代码如下: 上述代码中,共有5处使用 randomize 随机。它们的随机对象都是类 helloworld_test 中的 rand shortint unsigned counter ; 其中,counter 被赋予初始数值 66 。 …...

(耗时4天制作)详细介绍macOS系统 本博文含有全英版 (全文翻译稿)

(耗时4天制作)详细介绍macOS系统 本博文含有全英版-CSDN博客 全篇英文 Introduction to the macOS System I. Overview of macOS macOS is a proprietary operating system developed by Apple Inc., primarily used for Macintosh (Mac) computers. It is the first comme…...

React与Vue的区别(相同点和不同点)

前言 JavaScript是世界上最流行的语言之一&#xff0c;React和Vue是JS最流行的两个框架。但各有优缺点&#xff0c;本文将详细对比两大框架 一、框架背景 React React是由Facebook开发的用于构建用户界面的JavaScript库&#xff0c;Facebook对市场上JavaScript MVC框架都不太…...

flutter --no-color pub get 超时解决方法

新建Flutter项目后&#xff0c;运行报错&#xff0c;需要执行pub get 点击Run ‘flutter pub get’ … … … 卡着&#xff0c;不动了&#xff0c;提示超时 是因为墙的问题 解决方案&#xff1a; 添加以下环境变量 变量名: PUB_HOSTED_URL 变量值: https://pub.flutter-io.cn …...

MacPorts 中安装高/低版本软件方式,以 RabbitMQ 为例

查询信息 这里以 RabbitMQ 为例&#xff0c;通过搜索得到默认安装版本信息&#xff1a; port search rabbitmq-server结果 ~/Downloads> port search rabbitmq-server rabbitmq-server 3.11.15 (net)The RabbitMQ AMQP Server ~/Downloads>获取二进制文件 但当前官网…...

启动报错java.lang.NoClassDefFoundError: ch/qos/logback/core/status/WarnStatus

报错信息图片 日志&#xff1a; Exception in thread "Quartz Scheduler [scheduler]" java.lang.NoClassDefFoundError: ch/qos/logback/core/status/WarnStatus先说我自己遇到的问题&#xff0c;我们项目在web设置了自定义的log输出路径&#xff0c;多了一个 / 去…...

本科阶段最后一次竞赛Vlog——2024年智能车大赛智慧医疗组准备全过程——11上位机与小车交互

本科阶段最后一次竞赛Vlog——2024年智能车大赛智慧医疗组准备全过程——11上位机与小车交互 ​ 根据上一节的配置&#xff0c;目前已经建立了通讯环境&#xff0c;接下来给大家带来上位机与小车交互 这一章节里面也有图片大家去地瓜开发者社区看对应文章吧链接...

harbor离线安装 配置https 全程记录

1. 下载harbor最新版本 下载网址: 找最新的版本: https://github.com/goharbor/harbor/releases/download/v2.11.2/harbor-offline-installer-v2.11.2.tgz 这里我直接使用迅雷下载, 然后上传 1.1解压 sudo tar -xf harbor-offline-installer-v2.11.2.tgz -C /opt/ 2. 配置Harb…...

使用生存分析进行游戏时间测量

标题&#xff1a;Playtime Measurement with Survival Analysis 作者&#xff1a;Markus Viljanen, Antti Airola, Jukka Heikkonen, Tapio Pahikkala 译者&#xff1a;游戏数据科学 1 游戏中的游戏时间 1.1 为什么游戏时间很重要 游戏分析在理解玩家行为方面变得越来越重…...

Fiddler勾选https后google浏览器网页访问不可用

一、说明 最近电脑重新安装系统后&#xff0c;之前的所有工具都需要重新安装和配置&#xff0c;有个项目需要抓包https包查看一下请求的内容&#xff0c;通过Fiddler工具&#xff0c;但是开启后&#xff0c;发现https的无法抓取&#xff0c;同时google浏览器也不无法访问互联网…...

【信息系统项目管理师】高分论文:论信息系统项目的成本管理(社区网格化管理平台系统)

更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 论文一、规划成本管理二、估算成本三、制定预算四、控制成本论文 2022年6月,我作为项目经理负责了XX市社区网格化管理平台系统集成项目建设,该项目投资金额512.5万元,建设周期12个月。该项目由XX市综治办发…...