動態內存池設計與環形緩沖區實現詳解

一、動態內存池設計

在嵌入式系統中,頻繁使用 mallocfree 會導致內存碎片和性能問題。動態內存池通過預分配固定大小的內存塊,并統一管理分配與釋放,顯著提高內存使用效率和實時性。

1. 核心設計思路

  • 預分配內存:將內存劃分為多個固定大小的塊(例如 32、64、128 字節)。
  • 空閑塊管理:通過鏈表維護空閑塊,分配時從鏈表取塊,釋放時歸還鏈表。
  • 避免碎片:固定塊大小消除外部碎片,鏈表管理消除內部碎片。

2. 代碼實現

// 內存池結構體定義
typedef struct {uint8_t *pool;          // 內存池起始地址uint16_t block_size;    // 每個塊的大小uint16_t total_blocks;  // 總塊數void **free_list;       // 空閑塊鏈表(指針數組)uint16_t free_count;    // 空閑塊數量
} MemoryPool;// 初始化內存池
void mempool_init(MemoryPool *mp, uint8_t *buffer, uint16_t block_size, uint16_t total_blocks) {mp->pool = buffer;mp->block_size = block_size;mp->total_blocks = total_blocks;mp->free_list = (void**)buffer;mp->free_count = total_blocks;// 初始化空閑鏈表(每個塊存儲下一個塊的地址)for (int i = 0; i < total_blocks; i++) {void **block = (void**)(buffer + i * block_size);if (i == total_blocks - 1) *block = NULL;else *block = (void*)(buffer + (i + 1) * block_size);}
}// 分配內存塊
void *mempool_alloc(MemoryPool *mp) {if (mp->free_count == 0) return NULL; // 無空閑塊void *block = mp->free_list;          // 取出第一個空閑塊mp->free_list = *((void**)block);     // 更新鏈表頭mp->free_count--;return block;
}// 釋放內存塊
void mempool_free(MemoryPool *mp, void *block) {*((void**)block) = mp->free_list; // 將塊插入鏈表頭部mp->free_list = block;mp->free_count++;
}

3. 應用場景

  • FreeRTOS 任務通信:為隊列、信號量等動態對象提供預分配內存。
  • 傳感器數據處理:固定大小的數據包(如藍牙指令幀)直接分配內存塊。

二、環形緩沖區(RTOS任務通信)

環形緩沖區(Circular Buffer)是一種高效的數據結構,適用于生產者(如傳感器任務)和消費者(如控制任務)之間的異步通信,避免數據覆蓋并減少鎖競爭。?

1. 核心設計思路

  • 循環存儲:讀寫指針通過取模運算循環移動,覆蓋舊數據時自動丟棄。
  • 線程安全:在RTOS中,使用互斥鎖(如FreeRTOS的xSemaphoreTake/xSemaphoreGive)保護緩沖區操作。

2. 代碼實現

// 環形緩沖區結構體定義
typedef struct {uint8_t *buffer;        // 緩沖區起始地址uint16_t size;          // 緩沖區總大小uint16_t head;          // 寫指針(生產者)uint16_t tail;          // 讀指針(消費者)SemaphoreHandle_t mutex;// FreeRTOS互斥鎖
} RingBuffer;// 初始化環形緩沖區
void ringbuf_init(RingBuffer *rb, uint8_t *buffer, uint16_t size) {rb->buffer = buffer;rb->size = size;rb->head = rb->tail = 0;rb->mutex = xSemaphoreCreateMutex(); // 創建互斥鎖
}// 寫入數據(生產者任務)
bool ringbuf_push(RingBuffer *rb, uint8_t data) {xSemaphoreTake(rb->mutex, portMAX_DELAY); // 獲取鎖uint16_t next_head = (rb->head + 1) % rb->size;if (next_head == rb->tail) { // 緩沖區滿xSemaphoreGive(rb->mutex);return false;}rb->buffer[rb->head] = data;rb->head = next_head;xSemaphoreGive(rb->mutex);return true;
}// 讀取數據(消費者任務)
bool ringbuf_pop(RingBuffer *rb, uint8_t *data) {xSemaphoreTake(rb->mutex, portMAX_DELAY); // 獲取鎖if (rb->tail == rb->head) { // 緩沖區空xSemaphoreGive(rb->mutex);return false;}*data = rb->buffer[rb->tail];rb->tail = (rb->tail + 1) % rb->size;xSemaphoreGive(rb->mutex);return true;
}

3. 應用場景

  • 傳感器數據緩沖:如智能小車項目中,紅外傳感器數據通過環形緩沖區傳遞至控制任務。
  • 通信協議解析:藍牙指令幀按字節寫入緩沖區,消費者任務解析完整幀后處理。

三、結合FreeRTOS的實戰示例?

在六足機器人項目中,動態內存池和環形緩沖區的典型應用如下:?

1. 動態內存池管理舵機指令

// 定義舵機指令內存池(每個指令占4字節)
#define SERVO_CMD_SIZE 4
#define MAX_SERVO_CMDS 10
uint8_t servo_cmd_pool[MAX_SERVO_CMDS * SERVO_CMD_SIZE];
MemoryPool servo_mempool;// 初始化內存池
mempool_init(&servo_mempool, servo_cmd_pool, SERVO_CMD_SIZE, MAX_SERVO_CMDS);// 任務中分配指令內存
void vServoTask(void *pvParameters) {while (1) {uint8_t *cmd = (uint8_t*)mempool_alloc(&servo_mempool);if (cmd != NULL) {// 生成舵機指令并發送generate_servo_cmd(cmd);send_servo_cmd(cmd);mempool_free(&servo_mempool, cmd); // 釋放內存}vTaskDelay(pdMS_TO_TICKS(10));}
}

2.?環形緩沖區傳遞目標坐標

// 定義目標坐標緩沖區
#define DETECTION_BUFFER_SIZE 20
uint8_t detection_buffer[DETECTION_BUFFER_SIZE];
RingBuffer detection_rb;// 初始化緩沖區
ringbuf_init(&detection_rb, detection_buffer, DETECTION_BUFFER_SIZE);// 傳感器任務寫入數據
void vSensorTask(void *pvParameters) {while (1) {uint8_t data = read_sensor_data();ringbuf_push(&detection_rb, data); // 寫入緩沖區vTaskDelay(pdMS_TO_TICKS(5));}
}// 控制任務讀取數據
void vControlTask(void *pvParameters) {while (1) {uint8_t data;if (ringbuf_pop(&detection_rb, &data)) {process_detection_data(data); // 處理數據}vTaskDelay(pdMS_TO_TICKS(5));}
}

3.總結

  • 動態內存池:通過預分配和鏈表管理,解決內存碎片問題,適用于固定大小對象的頻繁分配(如通信協議幀)。
  • 環形緩沖區:通過循環存儲和互斥鎖保護,實現高效任務間通信,適用于流式數據傳輸(如傳感器數據)。
  • FreeRTOS集成:結合互斥鎖和任務調度機制,確保線程安全和實時性。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/72110.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/72110.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/72110.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

015--基于STM32F103ZET6的智能風扇設計

1.實物視頻演示 智能風扇演示視頻 2.程序代碼講解 STM32F103ZET6智能風扇_嗶哩嗶哩_bilibili 3源代碼獲取 https://download.csdn.net/download/weixin_41011452/90440545

【洛谷貪心算法】P1106刪數問題

這道題可以使用貪心算法來解決&#xff0c;核心思路是盡量讓高位的數字盡可能小。當我們逐步刪除數字時&#xff0c;會優先刪除高位中相對較大的數字。具體做法是從左到右遍歷數字序列&#xff0c;當發現當前數字比它后面的數字大時&#xff0c;就刪除當前數字&#xff0c;直到…

開源PDF解析工具olmOCR

olmOCR 是由 Allen Institute for Artificial Intelligence (AI2) 的 AllenNLP 團隊開發的一款開源工具&#xff0c;旨在將PDF文件和其他文檔高效地轉換為純文本&#xff0c;同時保留自然的閱讀順序。它支持表格、公式、手寫內容等。 olmOCR 經過學術論文、技術文檔和其他文檔…

基因型—環境兩向表數據分析——品種生態區劃分

參考資料&#xff1a;農作物品種試驗數據管理與分析 用于品種生態區劃分的GGE雙標圖有兩種功能圖&#xff1a;試點向量功能圖和“誰贏在哪里”功能圖。雙標圖的具體模型基于SD定標和h加權和試點中心化的數據。本例中籽粒產量的GGE雙標圖僅解釋了G和GE總變異的53.6%&#xff0c;…

HTTP~文件 MIME 類型

MIME&#xff08;Multipurpose Internet Mail Extensions&#xff09;類型&#xff0c;即多用途互聯網郵件擴展類型&#xff0c;是一種標準&#xff0c;用來表示文檔、文件或字節流的性質和格式。最初是為了在電子郵件系統中支持非 ASCII 字符文本、二進制文件附件等而設計的&a…

降維攻擊!PCA與隨機投影優化高維KNN

引言&#xff1a;高維數據的“冰山困境” 假設你正在處理一個電商平臺的商品圖片分類任務&#xff1a;每張圖片被提取為1000維的特征向量&#xff0c;100萬條數據的距離計算讓KNN模型陷入“維度地獄”——計算耗時長達數小時&#xff0c;且內存占用超過10GB。 破局關鍵&#…

Rust 是什么

Rust 是什么 Rust 是一種由 Mozilla 開發的系統級編程語言,它于 2010 年首次亮相,在 2015 年發布 1.0 版本,此后迅速發展并受到廣泛關注。 內存安全:Rust 最大的亮點之一是它在編譯階段就能夠避免常見的內存錯誤,如空指針引用、數據競爭和內存泄漏等。它通過所有權(Owne…

網絡變壓器的主要電性參數與測試方法(2)

Hqst盈盛&#xff08;華強盛&#xff09;電子導讀&#xff1a;網絡變壓器的主要電性參數與測試方法&#xff08;2&#xff09;.. 今天我們繼續來看看網絡變壓器的2個主要電性參數與它的測試方法&#xff1a; 1. 線圈間分布電容Cp:線圈間雜散靜電容 測試條件:100KHz/0.1…

UniApp 中封裝 HTTP 請求與 Token 管理(附Demo)

目錄 1. 基本知識2. Demo3. 拓展 1. 基本知識 從實戰代碼中學習&#xff0c;上述實戰代碼來源&#xff1a;芋道源碼/yudao-mall-uniapp 該代碼中&#xff0c;通過自定義 request 函數對 HTTP 請求進行了統一管理&#xff0c;并且結合了 Token 認證機制 請求封裝原理&#xff…

初階數據結構習題【3】(1時間和空間復雜度)——203移除鏈表元素

1. 題目描述 力扣在線OJ——移除鏈表元素 給你一個鏈表的頭節點 head 和一個整數 val &#xff0c;請你刪除鏈表中所有滿足 Node.val val 的節點&#xff0c;并返回 新的頭節點 。 示例1&#xff1a; 輸入&#xff1a;head [1,2,6,3,4,5,6], val 6 輸出&#xff1a;[1,2,3…

互聯網+房產中介+裝修設計+物料市場+智能家居一體化平臺需求書

一、項目概述 1.1 項目背景 隨著互聯網技術的飛速發展以及人們生活品質的顯著提升&#xff0c;傳統房產交易、裝修設計、家居購物等領域暴露出諸多問題。信息不對稱使得用戶難以獲取全面準確的信息&#xff0c;在房產交易中可能高價買入或低價賣出&#xff0c;裝修時可能遭遇…

15.13 AdaLoRA自適應權重矩陣微調:動態秩調整的智能革命

AdaLoRA自適應權重矩陣微調:動態秩調整的智能革命 一、技術架構解析 #mermaid-svg-u3TfE3YrkeWSjem2 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-u3TfE3YrkeWSjem2 .error-icon{fill:#552222;}#mermaid-svg-u3…

P9231 [藍橋杯 2023 省 A] 平方差

P9231 [藍橋杯 2023 省 A] 平方差 - 洛谷 題目描述 給定 L,R&#xff0c;問 L≤x≤R 中有多少個數 x 滿足存在整數 y,z 使得 xy2?z2。 輸入格式 輸入一行包含兩個整數 L,R&#xff0c;用一個空格分隔。 輸出格式 輸出一行包含一個整數滿足題目給定條件的 x 的數量。 輸…

【GenBI優化】提升text2sql準確率:建議使用推理大模型,增加重試

引言 Text-to-SQL&#xff08;文本轉 SQL&#xff09;是自然語言處理&#xff08;NLP&#xff09;領域的一項重要任務&#xff0c;旨在將自然語言問題自動轉換為可在數據庫上執行的 SQL 查詢語句。這項技術在智能助手、數據分析工具、商業智能&#xff08;BI&#xff09;平臺等…

<el-cascader時只取最后一級數據

在用cascader時只取最后一級數據傳給后端 組件的屬性emitPath: false就可以做到&#xff0c;取值就是最后一級傳給后端。并且后端放回的id 也直接可以做回顯 <el-cascaderv-model"Type":options"Options":props"{ value: id, label: label, chil…

`maturin`是什么:matu rus in python

maturin是什么 maturin 是一個用于構建和發布 Rust 編寫的 Python 綁定庫的工具。它簡化了將 Rust 代碼集成到 Python 項目中的過程,支持創建不同類型的 Python 包,如純 Python 包、包含 **Rust (系統編程語言)**擴展模塊的包等。以下為你詳細介紹 maturin 的相關信息并舉例…

流媒體網絡協議全解析:從實時傳輸到自適應流,如何選擇最優方案?

一、歷史發展與協議提出者 流媒體協議的發展與互聯網技術迭代緊密相關,主要分為三個階段: 早期專有協議(1990s-2000s) RTSP/RTP 提出者:RealNetworks(RTSP初始推動者),后由IETF標準化(RFC 2326)。背景:1996年推出,用于視頻監控和點播系統,基于UDP傳輸媒體流,支持…

mysql架構查詢執行流程(圖解+描述)

目錄 mysql架構查詢執行流程 圖解 描述 mysql架構查詢執行流程 圖解 描述 用戶連接到數據庫后&#xff0c;由連接器處理 連接器負責跟客戶端建立連接、獲取權限、維持和管理連接 客戶端發送一條查詢給服務器 服務器先檢查查詢緩存&#xff0c;如果命中緩存&#xff0c;則立…

【QT問題】Ubantu環境下解決已經下載好的qt怎么添加或卸載其他組件

1、找到自己qt的安裝目錄->雙擊打開MaintenanceTool.exe 2、點擊next進去&#xff0c;此時需要登錄qt賬戶&#xff08;如果沒有去官網注冊一個&#xff0c;很快且免費&#xff09; 我這里隨便填的賬號&#xff0c;如果是正確的下面next就能夠點擊。 這里隨便提一下&#xf…

CS50 使用 Python 進行人工智能簡介-“騎士與流氓”謎題

如何使用邏輯推理來解決“騎士與騙子”&#xff08;Knights and Knaves&#xff09;類型的邏輯難題。具體來說&#xff0c;任務是根據每個角色的陳述推理出他們是“騎士”還是“騙子”。 任務背景&#xff1a; 騎士與騙子問題&#xff1a;每個角色要么是騎士&#xff0c;要么是…