ESP-ADF外设子系统深度解析:esp_peripherals组件架构与核心设计(存储类外设之SPIFFS)

目录

  • ESP-ADF外设子系统深度解析:esp_peripherals组件架构与核心设计(存储类外设之SPIFFS)
    • 1. 简介
    • 2. 模块概述
      • 功能定义
      • 架构位置
      • 核心特性
    • SPIFFS外设
      • SPIFFS外设概述
        • SPIFFS外设层次架构图
      • SPIFFS外设API和数据结构
        • 外设层API
        • 公共API
        • 内部API
        • 内部数据结构
      • SPIFFS外设配置选项
        • 典型配置示例
      • SPIFFS外设初始化流程
        • 外设层初始化过程(periph_spiffs.c)
        • 挂载过程(periph_spiffs_mount)
        • SPIFFS外设完整初始化时序图
      • SPIFFS外设销毁流程
        • 卸载过程(periph_spiffs_unmount)
        • SPIFFS外设销毁时序图
      • SPIFFS外设事件处理
        • SPIFFS外设事件类型
        • 事件发送机制
        • SPIFFS外设事件处理流程图
        • 应用程序事件处理示例

ESP-ADF外设子系统深度解析:esp_peripherals组件架构与核心设计(存储类外设之SPIFFS)

版本信息: ESP-ADF v2.7-65-gcf908721


1. 简介

ESP-ADF存储类外设为应用层提供了对SD卡、SPIFFS等多种存储设备的统一管理和接入方式,极大简化了存储设备的初始化、挂载、卸载以及事件通知流程。通过标准化的外设接口和事件机制,应用程序可以方便地感知和处理存储介质的插拔、挂载状态变化等事件,无需关心底层驱动和文件系统的具体实现细节。

存储类外设作为ESP-ADF外设子系统的重要组成部分,支持多种主流存储介质,并与外设事件系统深度集成,能够满足音频应用对文件系统高可靠性和易用性的需求。


2. 模块概述

功能定义

存储类外设主要实现以下功能:

  • 统一管理SD卡、SPIFFS等存储介质的初始化、挂载和卸载流程
  • 对外提供标准化的事件通知接口,便于应用层感知存储状态变化
  • 支持多种挂载模式和灵活的配置参数,适应不同硬件和业务需求
  • 通过esp_peripherals事件机制,实现存储外设与应用层的解耦,提升系统健壮性和可维护性

架构位置

存储类外设位于硬件文件系统驱动(如SDMMC、SPIFFS驱动)与应用层之间,作为外设子系统的派生模块,负责对底层存储驱动的封装和统一管理。其架构位置如下图所示:

应用程序
ESP外设子系统
存储类外设
SD卡外设
SPIFFS外设
SDMMC/SPI驱动
SPIFFS驱动

核心特性

  • 多种存储类型支持:支持SD卡(SPI、SD 1线/4线/8线等模式)和SPIFFS文件系统,满足多样化的存储需求。
  • 自动检测与挂载:具备自动检测存储介质插拔、自动挂载和卸载文件系统的能力,提升系统易用性。
  • 统一事件模型:所有存储外设均采用统一的事件模型和接口,便于应用层集中处理。
  • 灵活配置参数:支持根目录、挂载模式、最大文件数、挂载失败自动格式化等可配置参数,适应不同场景。
  • 与事件系统集成:与esp_peripherals事件系统深度集成,实现存储状态变化的实时通知和回调处理。

SPIFFS外设

SPIFFS外设概述

SPIFFS (SPI Flash File System) 外设是ESP-ADF框架中用于管理片上SPI Flash存储的组件,提供了文件系统功能,可用于存储配置文件、音频数据等。SPIFFS外设通过ESP-IDF的SPIFFS组件实现,支持文件系统挂载、卸载和基本文件操作。

SPIFFS外设实现分为两个层次:

  1. 外设层:负责将SPIFFS集成到ESP-ADF外设系统中,处理事件分发和生命周期管理。

    • 头文件:components/esp_peripherals/include/periph_spiffs.h
    • 实现文件:components/esp_peripherals/periph_spiffs.c
  2. 底层驱动层:由ESP-IDF的SPIFFS组件提供,负责实际的文件系统操作。

    • ESP-IDF组件:esp_spiffs
SPIFFS外设层次架构图
底层驱动层 esp_spiffs
外设层 periph_spiffs.c
调用
调用
设置
设置
设置
调用
调用
调用
调用
操作
发送
发送
通知
通知
esp_vfs_spiffs_register
periph_spiffs_mount
esp_vfs_spiffs_unregister
periph_spiffs_unmount
SPI Flash
_spiffs_init
periph_spiffs_init
_spiffs_run
_spiffs_destroy
ESP-ADF应用
esp_periph_create
SPIFFS_STATUS_MOUNTED事件
SPIFFS_STATUS_UNMOUNTED事件

SPIFFS外设API和数据结构

外设层API

源文件components/esp_peripherals/include/periph_spiffs.hcomponents/esp_peripherals/periph_spiffs.c

公共API
// SPIFFS外设初始化函数
esp_periph_handle_t periph_spiffs_init(periph_spiffs_cfg_t* spiffs_config);// 检查SPIFFS是否已挂载
bool periph_spiffs_is_mounted(esp_periph_handle_t periph);// SPIFFS配置结构体
typedef struct {const char* root;               // 文件系统挂载点const char* partition_label;    // SPIFFS分区标签size_t max_files;               // 同时打开的最大文件数bool format_if_mount_failed;    // 挂载失败时是否自动格式化
} periph_spiffs_cfg_t;// SPIFFS事件类型
typedef enum {SPIFFS_STATUS_UNKNOWN,          // 未知状态SPIFFS_STATUS_MOUNTED,          // SPIFFS挂载成功SPIFFS_STATUS_UNMOUNTED,        // SPIFFS卸载成功SPIFFS_STATUS_MOUNT_ERROR,      // SPIFFS挂载错误SPIFFS_STATUS_UNMOUNT_ERROR,    // SPIFFS卸载错误
} periph_spiffs_event_id_t;
内部API
// SPIFFS挂载函数(在源码中有外部接口)
esp_err_t periph_spiffs_mount(esp_periph_handle_t periph);// SPIFFS卸载函数(在源码中有外部接口)
esp_err_t periph_spiffs_unmount(esp_periph_handle_t periph);
内部数据结构
// SPIFFS外设内部结构体 (定义在periph_spiffs.c中)
typedef struct {char *root;                     // 挂载点路径char *partition_label;          // 分区标签size_t max_files;               // 最大文件数bool format_if_mount_failed;    // 挂载失败是否格式化bool is_mounted;                // 挂载状态
} periph_spiffs_t;

SPIFFS外设配置选项

SPIFFS外设通过periph_spiffs_cfg_t结构体提供以下配置选项:

配置项说明默认值示例值
root文件系统挂载点,即访问SPIFFS文件系统的基础路径“/spiffs”“/data”
partition_labelSPIFFS分区标签,用于指定使用哪个分区NULL(使用第一个SPIFFS分区)“storage”
max_files同时打开的最大文件数,受ESP32内存限制510
format_if_mount_failed挂载失败时是否自动格式化分区falsetrue
典型配置示例
periph_spiffs_cfg_t spiffs_cfg = {.root = "/spiffs",                  // 挂载到/spiffs路径.partition_label = NULL,            // 使用默认SPIFFS分区.max_files = 5,                     // 最多同时打开5个文件.format_if_mount_failed = true      // 挂载失败时自动格式化
};

注意:设置format_if_mount_failed为true可能导致数据丢失,但可以解决文件系统损坏的问题。在生产环境中应谨慎使用此选项。

SPIFFS外设初始化流程

SPIFFS外设的初始化流程主要关注ESP-ADF框架中的外设层实现,该层负责将SPIFFS文件系统集成到ESP-ADF的外设系统中。虽然SPIFFS外设最终会调用ESP-IDF提供的底层文件系统API,但本节主要分析ESP-ADF中的外设封装实现。

外设层初始化过程(periph_spiffs.c)

外设层初始化主要通过periph_spiffs_init函数(位于periph_spiffs.c)完成,主要包括以下步骤:

  1. 创建外设句柄:调用esp_periph_create函数创建外设句柄
  2. 分配内部数据结构:分配periph_spiffs_t结构体内存
  3. 设置配置参数:设置挂载点、分区标签、最大文件数和挂载失败处理策略
  4. 注册回调函数:设置初始化、运行和销毁回调函数
// 文件:components/esp_peripherals/periph_spiffs.c
esp_periph_handle_t periph_spiffs_init(periph_spiffs_cfg_t *spiffs_cfg)
{// 1. 创建外设句柄esp_periph_handle_t periph = esp_periph_create(PERIPH_ID_SPIFFS, "periph_spiffs");AUDIO_MEM_CHECK(TAG, periph, return NULL);// 2. 分配内部数据结构periph_spiffs_t *spiffs = audio_calloc(1, sizeof(periph_spiffs_t));AUDIO_MEM_CHECK(TAG, spiffs, {audio_free(periph);return NULL;});// 3. 设置配置参数// 设置挂载点if (spiffs_cfg->root) {spiffs->root = audio_strdup(spiffs_cfg->root);} else {spiffs->root = audio_strdup("/spiffs");}// 设置分区标签if (spiffs_cfg->partition_label) {spiffs->partition_label = audio_strdup(spiffs_cfg->partition_label);} else {spiffs->partition_label = NULL;}// 设置最大文件数if (spiffs_cfg->max_files < SPIFFS_DEFAULT_MAX_FILES) {spiffs->max_files = SPIFFS_DEFAULT_MAX_FILES;} else {spiffs->max_files = spiffs_cfg->max_files;}// 设置挂载失败处理策略spiffs->format_if_mount_failed = spiffs_cfg->format_if_mount_failed;AUDIO_MEM_CHECK(TAG, spiffs->root, {audio_free(spiffs);audio_free(periph);return NULL;});// 4. 注册回调函数esp_periph_set_data(periph, spiffs);esp_periph_set_function(periph, _spiffs_init, _spiffs_run, _spiffs_destroy);return periph;
}

当外设被添加到外设集合并启动时,会调用_spiffs_init函数(位于periph_spiffs.c),该函数负责挂载SPIFFS文件系统:

// 文件:components/esp_peripherals/periph_spiffs.c
static esp_err_t _spiffs_init(esp_periph_handle_t self)
{// 调用挂载函数return periph_spiffs_mount(self);
}
挂载过程(periph_spiffs_mount)

SPIFFS外设的挂载过程通过periph_spiffs_mount函数完成,主要包括以下步骤:

  1. 验证外设句柄:确保传入的是有效的SPIFFS外设句柄
  2. 获取SPIFFS配置:从外设数据中获取SPIFFS配置
  3. 准备ESP-VFS配置:将外设配置转换为ESP-VFS配置
  4. 注册并挂载SPIFFS:调用ESP-IDF的esp_vfs_spiffs_register函数
  5. 获取分区信息:如果挂载成功,获取并打印分区大小信息
  6. 发送挂载事件:根据挂载结果发送相应的事件
// 文件:components/esp_peripherals/periph_spiffs.c
esp_err_t periph_spiffs_mount(esp_periph_handle_t periph)
{// 1. 验证外设句柄VALIDATE_SPIFFS(periph, ESP_FAIL);// 2. 获取SPIFFS配置periph_spiffs_t *spiffs = esp_periph_get_data(periph);// 3. 准备ESP-VFS配置esp_vfs_spiffs_conf_t conf = {.base_path = spiffs->root,.partition_label = spiffs->partition_label,.max_files = spiffs->max_files,.format_if_mount_failed = spiffs->format_if_mount_failed};// 4. 注册并挂载SPIFFSesp_err_t ret = esp_vfs_spiffs_register(&conf);if (ret != ESP_OK) {if (ret == ESP_FAIL) {ESP_LOGE(TAG, "Failed to mount or format filesystem");} else if (ret == ESP_ERR_NOT_FOUND) {ESP_LOGE(TAG, "Failed to find SPIFFS partition");} else {ESP_LOGE(TAG, "Failed to initialize SPIFFS (%d)", ret);}return ESP_FAIL;}// 5. 获取分区信息if (ret == ESP_OK) {ESP_LOGD(TAG, "Mount SPIFFS success");spiffs->is_mounted = true;size_t total = 0, used = 0;ret = esp_spiffs_info(conf.partition_label, &total, &used);if (ret != ESP_OK) {ESP_LOGE(TAG, "Failed to get SPIFFS partition information (%d)", ret);} else {ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used);}// 6. 发送挂载成功事件return esp_periph_send_event(periph, SPIFFS_STATUS_MOUNTED, NULL, 0);} else if (ret == ESP_ERR_INVALID_STATE) {ESP_LOGD(TAG, "Periph SPIFFS handle already mounted!");return ESP_OK;} else {// 发送挂载失败事件esp_periph_send_event(periph, SPIFFS_STATUS_MOUNT_ERROR, NULL, 0);spiffs->is_mounted = false;ESP_LOGE(TAG, "Mount SPIFFS error!");return ESP_FAIL;}
}
SPIFFS外设完整初始化时序图

下图展示了SPIFFS外设从应用程序调用到底层驱动完成初始化的完整流程:

应用程序 periph_spiffs_init (periph_spiffs.c) esp_periph库 _spiffs_init (periph_spiffs.c) periph_spiffs_mount (periph_spiffs.c) esp_vfs_spiffs_register (esp_spiffs) periph_spiffs_init(spiffs_cfg) esp_periph_create(PERIPH_ID_SPIFFS, "periph_spiffs") periph 分配 periph_spiffs_t 结构体 设置挂载点、分区标签等参数 esp_periph_set_data(periph, spiffs) esp_periph_set_function(periph, _spiffs_init, _spiffs_run, _spiffs_destroy) periph 当外设被添加到外设集合并启动时 _spiffs_init(self) periph_spiffs_mount(self) esp_periph_get_data(self) spiffs 准备esp_vfs_spiffs_conf_t配置 esp_vfs_spiffs_register(&conf) 挂载结果 esp_spiffs_info(partition_label, &total, &used) 分区信息 esp_periph_send_event(SPIFFS_STATUS_MOUNTED) esp_periph_send_event(SPIFFS_STATUS_MOUNT_ERROR) alt [挂载成功] [挂载失败] 挂载结果 初始化结果 应用程序 periph_spiffs_init (periph_spiffs.c) esp_periph库 _spiffs_init (periph_spiffs.c) periph_spiffs_mount (periph_spiffs.c) esp_vfs_spiffs_register (esp_spiffs)

SPIFFS外设销毁流程

SPIFFS外设的销毁流程主要通过_spiffs_destroy函数(位于periph_spiffs.c)完成,主要包括以下步骤:

  1. 验证外设句柄:确保传入的是有效的SPIFFS外设句柄
  2. 卸载SPIFFS:调用periph_spiffs_unmount函数卸载SPIFFS文件系统
  3. 释放资源:释放挂载点、分区标签和SPIFFS结构体内存
// 文件:components/esp_peripherals/periph_spiffs.c
static esp_err_t _spiffs_destroy(esp_periph_handle_t self)
{// 1. 验证外设句柄VALIDATE_SPIFFS(self, ESP_FAIL);esp_err_t ret = ESP_OK;// 2. 卸载SPIFFSret |= periph_spiffs_unmount(self);if (ret != ESP_OK) {ESP_LOGE(TAG, "Failed to unmount SPIFFS");}// 3. 释放资源periph_spiffs_t *spiffs = esp_periph_get_data(self);audio_free(spiffs->root);if (spiffs->partition_label != NULL) {audio_free(spiffs->partition_label);}audio_free(spiffs);return ret;
}
卸载过程(periph_spiffs_unmount)

SPIFFS外设的卸载过程通过periph_spiffs_unmount函数完成,主要包括以下步骤:

  1. 验证外设句柄:确保传入的是有效的SPIFFS外设句柄
  2. 获取SPIFFS配置:从外设数据中获取SPIFFS配置
  3. 卸载SPIFFS:调用ESP-IDF的esp_vfs_spiffs_unregister函数
  4. 发送卸载事件:根据卸载结果发送相应的事件
// 文件:components/esp_peripherals/periph_spiffs.c
esp_err_t periph_spiffs_unmount(esp_periph_handle_t periph)
{// 1. 验证外设句柄VALIDATE_SPIFFS(periph, ESP_FAIL);// 2. 获取SPIFFS配置periph_spiffs_t *spiffs = esp_periph_get_data(periph);// 3. 卸载SPIFFSint ret = esp_vfs_spiffs_unregister(spiffs->partition_label);// 4. 发送卸载事件if (ret == ESP_OK) {ESP_LOGD(TAG, "Unmount SPIFFS success");spiffs->is_mounted = false;return esp_periph_send_event(periph, SPIFFS_STATUS_UNMOUNTED, NULL, 0);} else {esp_periph_send_event(periph, SPIFFS_STATUS_UNMOUNT_ERROR, NULL, 0);ESP_LOGE(TAG, "Unmount SPIFFS error!");spiffs->is_mounted = false;return ESP_FAIL;}return ESP_OK;
}
SPIFFS外设销毁时序图

下图展示了SPIFFS外设从销毁开始到完全释放资源的完整流程:

应用程序 esp_periph库 _spiffs_destroy (periph_spiffs.c) periph_spiffs_unmount (periph_spiffs.c) esp_vfs_spiffs_unregister (esp_spiffs) 当外设被从外设集合中移除或销毁时 _spiffs_destroy(self) periph_spiffs_unmount(self) esp_periph_get_data(self) spiffs esp_vfs_spiffs_unregister(partition_label) 卸载结果 esp_periph_send_event(SPIFFS_STATUS_UNMOUNTED) esp_periph_send_event(SPIFFS_STATUS_UNMOUNT_ERROR) alt [卸载成功] [卸载失败] 卸载结果 释放挂载点内存 释放分区标签内存 释放SPIFFS结构体内存 销毁结果 应用程序 esp_periph库 _spiffs_destroy (periph_spiffs.c) periph_spiffs_unmount (periph_spiffs.c) esp_vfs_spiffs_unregister (esp_spiffs)

SPIFFS外设事件处理

SPIFFS外设的事件处理机制相对简单,主要通过_spiffs_run函数(位于periph_spiffs.c)实现。与其他外设不同,SPIFFS外设的_spiffs_run函数并不处理任何事件,只是简单地返回ESP_OK

// 文件:components/esp_peripherals/periph_spiffs.c
static esp_err_t _spiffs_run(esp_periph_handle_t self, audio_event_iface_msg_t *msg)
{return ESP_OK;
}

这是因为SPIFFS外设主要在初始化和销毁阶段通过periph_spiffs_mountperiph_spiffs_unmount函数发送事件,而不需要在运行时处理额外的事件。

SPIFFS外设事件类型

SPIFFS外设定义了以下事件类型(位于periph_spiffs.h):

// SPIFFS事件类型
typedef enum {SPIFFS_STATUS_UNKNOWN,          // 未知状态SPIFFS_STATUS_MOUNTED,          // SPIFFS挂载成功SPIFFS_STATUS_UNMOUNTED,        // SPIFFS卸载成功SPIFFS_STATUS_MOUNT_ERROR,      // SPIFFS挂载错误SPIFFS_STATUS_UNMOUNT_ERROR,    // SPIFFS卸载错误
} periph_spiffs_event_id_t;

这些事件在SPIFFS外设的生命周期中的不同阶段被发送:

  1. SPIFFS_STATUS_MOUNTED:在periph_spiffs_mount函数中,当SPIFFS文件系统成功挂载后发送
  2. SPIFFS_STATUS_MOUNT_ERROR:在periph_spiffs_mount函数中,当SPIFFS文件系统挂载失败时发送
  3. SPIFFS_STATUS_UNMOUNTED:在periph_spiffs_unmount函数中,当SPIFFS文件系统成功卸载后发送
  4. SPIFFS_STATUS_UNMOUNT_ERROR:在periph_spiffs_unmount函数中,当SPIFFS文件系统卸载失败时发送
事件发送机制

SPIFFS外设通过esp_periph_send_event函数发送事件,该函数将事件发送到ESP-ADF的事件系统中,应用程序可以通过注册回调函数来处理这些事件。

// 挂载成功时发送事件
esp_periph_send_event(periph, SPIFFS_STATUS_MOUNTED, NULL, 0);// 挂载失败时发送事件
esp_periph_send_event(periph, SPIFFS_STATUS_MOUNT_ERROR, NULL, 0);// 卸载成功时发送事件
esp_periph_send_event(periph, SPIFFS_STATUS_UNMOUNTED, NULL, 0);// 卸载失败时发送事件
esp_periph_send_event(periph, SPIFFS_STATUS_UNMOUNT_ERROR, NULL, 0);
SPIFFS外设事件处理流程图

下图展示了SPIFFS外设事件的发送和处理流程:

卸载事件
外设销毁
事件处理
事件发送
外设初始化
1. 初始化
2. 设置回调
3. 调用
4. 调用
5a. 挂载成功
5b. 挂载失败
6. 事件分发
6. 事件分发
7. 调用
8. 调用
9a. 卸载成功
9b. 卸载失败
10. 事件分发
10. 事件分发
esp_periph_send_event
(SPIFFS_STATUS_UNMOUNTED)
esp_periph_send_event
(SPIFFS_STATUS_UNMOUNT_ERROR)
_spiffs_destroy
esp_periph_destroy
periph_spiffs_unmount
应用程序回调
esp_periph_send_event
(SPIFFS_STATUS_MOUNTED)
esp_periph_send_event
(SPIFFS_STATUS_MOUNT_ERROR)
_spiffs_init
esp_periph_start
periph_spiffs_mount
应用程序
periph_spiffs_init
esp_periph_set_function
应用程序事件处理示例

应用程序可以通过注册回调函数来处理SPIFFS外设发送的事件,示例如下:

// SPIFFS事件处理回调函数
esp_err_t spiffs_event_handler(audio_event_iface_msg_t *event, void *context)
{esp_periph_handle_t periph = (esp_periph_handle_t)event->source;if (esp_periph_get_id(periph) == PERIPH_ID_SPIFFS) {switch (event->cmd) {case SPIFFS_STATUS_MOUNTED:ESP_LOGI(TAG, "SPIFFS已成功挂载");// 执行挂载成功后的操作break;case SPIFFS_STATUS_UNMOUNTED:ESP_LOGI(TAG, "SPIFFS已成功卸载");// 执行卸载成功后的操作break;case SPIFFS_STATUS_MOUNT_ERROR:ESP_LOGE(TAG, "SPIFFS挂载失败");// 处理挂载错误break;case SPIFFS_STATUS_UNMOUNT_ERROR:ESP_LOGE(TAG, "SPIFFS卸载失败");// 处理卸载错误break;default:break;}}return ESP_OK;
}// 注册事件处理回调
esp_periph_set_callback(set, spiffs_event_handler, NULL);

通过这种方式,应用程序可以在SPIFFS外设的生命周期中的不同阶段接收到相应的事件通知,并执行相应的操作。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Pandas】pandas DataFrame truediv

Pandas2.2 DataFrame Binary operator functions 方法描述DataFrame.add(other)用于执行 DataFrame 与另一个对象&#xff08;如 DataFrame、Series 或标量&#xff09;的逐元素加法操作DataFrame.add(other[, axis, level, fill_value])用于执行 DataFrame 与另一个对象&…

开发网页程序时预览时遇到跨域问题解决方法

CocosCreator 开发h5游戏要用接口、开发html程序网页程序在chrome中预览时都会遇到跨域问题,怎么办? 网上有很多方法,主要是通过服务器端去配置,但那个相对来说消弱安全问题,这个不建议,因为是开发,个人行业,我们知道问题所以,简单点就主要是通过chrome的参数来禁用: 关闭 Ch…

C语言main的参数;argc与argv

目录 前言 什么是命令行参数 argc与argv argc (Argument Count) argv (Argument Vector) 示例 前言 在C语言中&#xff0c;main函数的标准形式通常有两种&#xff1a; int main(void)int main(int argc, char *argv[]) 其中&#xff0c;argc 和 argv 是用于处理命令行参数…

实验一 进程控制实验

一、实验目的 1、掌握进程的概念&#xff0c;理解进程和程序的区别。 2、认识和了解并发执行的实质。 3、学习使用系统调用fork()创建新的子进程方法&#xff0c;理解进程树的概念。 4、学习使用系统调用wait()或waitpid()实现父子进程同步。 5、学习使用getpid()和getppi…

【Python Web开发】01-Socket网络编程01

文章目录 1.套接字(Socket)1.1 概念1.2 类型1.3 使用步骤 Python 的网络编程主要用于让不同的计算机或者程序之间进行数据交换和通信&#xff0c;就好像人与人之间打电话、发消息一样。 下面从几个关键方面通俗易懂地介绍一下&#xff1a; 1.套接字(Socket) 在 Python 网络编…

Git 配置 GPG 提交签名

使用 GPG 对 Git 提交进行签名&#xff0c;可以证明该提交确实是你本人提交的。这在团队协作和代码审核中非常有用&#xff0c;GitHub/GitLab 等平台也会显示 “Verified” 标签。 &#x1f9e9; 一、检查是否已安装 GPG gpg --version 如果未安装&#xff0c;可使用以下命令…

MySQL运维三部曲初级篇:从零开始打造稳定高效的数据库环境

文章目录 一、服务器选型——给数据库一个舒适的家二、系统调优——打造高性能跑道三、MySQL配置——让数据库火力全开四、监控体系——数据库的体检中心五、备份恢复——数据安全的最后防线六、主从复制——数据同步的艺术七、安全加固——守护数据长城 引言&#xff1a;从小白…

实践项目开发-hbmV4V20250407-跨平台开发框架深度解析与VSCode一站式开发实践

跨平台开发框架深度解析与VSCode一站式开发实践 在当今多端应用开发需求激增的背景下&#xff0c;跨平台开发框架成为了众多开发者的首选。本文将围绕React Native、Taro及其结合方案&#xff0c;以及Uni-app、MUI、Quasar等轻量级框架展开详细分析&#xff0c;并探讨如何在VS…

Android15沉浸式界面顶部有问题

Android15沉浸式界面顶部有问题 往往开发人员的手机没这么高级&#xff0c;客户或者老板的手机是Android15的。 我明明就设了状态栏透明&#xff0c;我的手机也没问题。但Android15是有问题的。 先看下有问题的界面&#xff1a; 解决方案&#xff1a; 处理1&#xff1a; if (…

uni-app 状态管理深度解析:Vuex 与全局方案实战指南

uni-app 状态管理深度解析&#xff1a;Vuex 与全局方案实战指南 一、Vuex 使用示例 1. 基础 Vuex 配置 1.1 项目结构 src/ ├── store/ │ ├── index.js # 主入口文件 │ └── modules/ │ └── counter.js # 计数器模块 └── main.js …

【STM32单片机】#11 I2C通信(软件读写)

主要参考学习资料&#xff1a; B站江协科技 STM32入门教程-2023版 细致讲解 中文字幕 开发资料下载链接&#xff1a;https://pan.baidu.com/s/1h_UjuQKDX9IpP-U1Effbsw?pwddspb 单片机套装&#xff1a;STM32F103C8T6开发板单片机C6T6核心板 实验板最小系统板套件科协 实验&…

每天一道面试题@第一天

1&#xff1a;TCP和UDP的区别&#xff0c;TCP为什么是三次握手&#xff0c;不是两次&#xff1f; 因为TCP是全双工协议&#xff0c;区别在于TCP可靠&#xff0c;UDP不可靠&#xff0c;效率更高。 详解&#xff1a; TCP&#xff08;传输控制协议&#xff09;和 UDP&#xff08;…

一款强大的实时协作Markdown工具 | CodiMD 9.6K ⭐

CodiMD 介绍 CodiMD 是一个开源的实时协作 Markdown 笔记工具&#xff0c;它允许用户在任何平台上共同编辑 Markdown 文档。核心功能是实时协作&#xff0c;它允许多个用户同时编辑同一个文档&#xff0c;并实时看到彼此的更改。支持实时渲染预览&#xff0c;支持超多的富文本格…

若依如何切换 tab 不刷新

方法 如上图配置 菜单中选是否缓存&#xff1a;缓存 资料 前端手册 |RuoYi:

【浙江大学DeepSeek公开课】回望AI三大主义与加强通识教育

回望AI三大主义与加强通识教育 一、人工智能三大主义二、人工智能发展历程三、从 ChatGPT 到 DeepSeek四、人工智能通识教育五、人工智能的挑战与未来 一、人工智能三大主义 符号主义 &#xff1a;逻辑推理&#xff0c;将推理视为计算过程。如苏格拉底三段论&#xff0c;通过前…

边缘计算全透视:架构、应用与未来图景

边缘计算全透视&#xff1a;架构、应用与未来图景 一、产生背景二、本质三、特点&#xff08;一&#xff09;位置靠近数据源&#xff08;二&#xff09;分布式架构&#xff08;三&#xff09;实时性要求高 四、关键技术&#xff08;一&#xff09;硬件技术&#xff08;二&#…

C++——多态、抽象类和接口

目录 多态的基本概念 如何实现多态 在C中&#xff0c;派生类对象可以被当作基类对象使用 编程示例 关键概念总结 抽象类 一、抽象类的定义 基本语法 二、抽象类的核心特性 1. 不能直接实例化 2. 派生类必须实现所有纯虚函数才能成为具体类 3. 可以包含普通成员函数和…

初级达梦dba的技能水准

在x86环境&#xff08;windows、linux&#xff09;安装单机软件&#xff0c;安装客户端创建过至少20套数据库&#xff0c;优化参数并更新过正式许可会用逻辑导出导入以及dmrman备份了解manager工具的使用配置sqllog日志&#xff0c;并能解释输出内容能够分析因磁盘空间不足、内…

监控页面卡顿PerformanceObserver

监控页面卡顿PerformanceObserver 性能观察器掘金 const observer new PerformanceObserver((list) > {}); observer.observe({entryTypes: [longtask], })

智能座舱测试内容与步骤

智能座舱的测试步骤通常包括以下环节&#xff1a; 1.测试环境搭建与准备 • 硬件需求分析&#xff1a;准备测试车辆、服务器与工作站、网络设备以及传感器和执行器模拟器等硬件设备。 • 软件需求分析&#xff1a;选择测试管理软件、自动化测试工具、模拟软件和开发调试工具等。…