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.pswp.cn/news/902444.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/902444.shtml
英文地址,請注明出處:http://en.pswp.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;選擇測試管理軟件、自動化測試工具、模擬軟件和開發調試工具等。…