寫在前面
1.基本原則
先進先出(fifo),重複使用。
2.實現原理
環形緩衝區,顧名思義就是一段迴圈使用的一段記憶體。通過寫指標向「空白記憶體」(未寫入過或者已經被讀出的記憶體)寫入資料並記錄,讀指標從已寫的記憶體讀取資料並記錄,當指標訪問到記憶體最後乙個位置時,再折回第乙個記憶體位置,達到迴圈效果。
3.注意事項
1)環形緩衝區本質是「生產者消費者」模型,必須先有生產(寫)後有消費(讀),不可提前消費(讀);
2)注意程式效率問題,如果讀效率過低,導致「生產」過剩,從而覆蓋未讀出的資料,導致出錯,此時需增加環形緩衝區記憶體大小或者優化**效率;
3)單一執行緒訪問時是安全的,多執行緒訪問時,為保證資料安全性必須加互斥鎖機制;
4.應用場合
處理串列埠(rs232)接收資料命令:
串列埠中斷--->資料接收--->寫入環形緩衝區--->資料處理執行緒讀取環形緩衝區--->處理有效資料。
5.實現方式
標頭檔案
#ifndef _fifo_h_
#define _fifo_h_
#include #include typedef void (*lock_fun)(void);
typedef struct
_fifo_t;
extern void fifo_register(_fifo_t *pfifo, uint8_t *pfifo_buf, uint32_t size,
lock_fun lock, lock_fun unlock);
extern void fifo_release(_fifo_t *pfifo);
extern uint32_t fifo_write(_fifo_t *pfifo, const uint8_t *pbuf, uint32_t size);
extern uint32_t fifo_read(_fifo_t *pfifo, uint8_t *pbuf, uint32_t size);
extern uint32_t fifo_get_total_size(_fifo_t *pfifo);
extern uint32_t fifo_get_free_size(_fifo_t *pfifo);
extern uint32_t fifo_get_occupy_size(_fifo_t *pfifo);
#endif
原始檔
#include #include "fifo.h"
/** * @brief 註冊乙個fifo
* @param pfifo: fifo結構體指標
pfifo_buf: fifo記憶體塊
size: 長度
* @retval none
*/void fifo_register(_fifo_t *pfifo, uint8_t *pfifo_buf, uint32_t size,
lock_fun lock, lock_fun unlock)
/*** @brief 釋放fifo
* @param pfifo: fifo結構體指標
* @retval none
*/void fifo_release(_fifo_t *pfifo)
/*** @brief 往fifo寫資料
* @param pfifo: fifo結構體指標
pbuf: 待寫資料
size: 待寫資料大小
* @retval 實際寫大小
*/uint32_t fifo_write(_fifo_t *pfifo, const uint8_t *pbuf, uint32_t size)
free_size = fifo_get_free_size(pfifo);
if(free_size == 0)
if(free_size < size)
w_size = size;
if (pfifo->lock != null)
pfifo->lock();
while(w_size-- > 0)
pfifo->occupy_size++;
}if (pfifo->unlock != null)
pfifo->unlock();
return size;}
/** * @brief 從fifo讀資料
* @param pfifo: fifo結構體指標
pbuf: 待讀資料快取
size: 待讀資料大小
* @retval 實際讀大小
*/uint32_t fifo_read(_fifo_t *pfifo, uint8_t *pbuf, uint32_t size)
occupy_size = fifo_get_occupy_size(pfifo);
if(occupy_size == 0)
if(occupy_size < size)
if (pfifo->lock != null)
pfifo->lock();
r_size = size;
while(r_size-- > 0)
pfifo->occupy_size--;
}if (pfifo->unlock != null)
pfifo->unlock();
return size;}
/** * @brief 獲取fifo空間大小
* @param pfifo: fifo結構體指標
* @retval fifo大小
*/uint32_t fifo_get_total_size(_fifo_t *pfifo)
/*** @brief 獲取fifo空閒空間大小
* @param pfifo: fifo結構體指標
* @retval 空閒空間大小
*/uint32_t fifo_get_free_size(_fifo_t *pfifo)
/*** @brief 獲取fifo已用空間大小
* @param pfifo: fifo結構體指標
* @retval fifo已用大小
*/uint32_t fifo_get_occupy_size(_fifo_t *pfifo)
其中,注意點是環形緩衝區「滿」與「空」狀態處理,這裡使用了讀、寫指標的「翻轉」標識,即當讀、寫指標訪問到緩衝區最後位址時,訪問位址折回初始位址,此時做乙個翻轉標識;當讀位址和寫位址相等時,如果讀、寫翻轉標識相等,說明此時緩衝區為「空狀態」,否則緩衝區為「滿」狀態。
5.應用例子
註冊乙個512位元組大小環形緩衝區,然後往緩衝區寫入資料,接著讀出來。
#include "fifo.h"
static uint8_t buf_0[512];
static _fifo_t fifo_0;
int main(void)
; uint8_t r_data[10];
fifo_register(&fifo_0, buf_0, sizeof(buf_0), 0, 0);
fifo_write(&fifo_0, (const uint8_t*)w_data, sizeof(data));
fifo_read(&fifo_0, r_data, 1);
fifo_read(&fifo_0, &r_data[1], 2);
return 0;
}
環形緩衝區
include include include include include define buffsize 1024 1024 define min x,y x y x y pthread mutex t lock pthread mutex initializer struct cycle b...
環形緩衝區
define print buf size 16 1024 static char g pcnetprintbuf 環形緩衝區的首位址 static int g ireadpos 0 環形緩衝區讀的位置 static int g iwritepos 0 環形緩衝區寫的位置 intinit 判斷環形緩...
環形緩衝區
環形緩衝區要維護兩個索引,分別對應寫入端 w 和讀取端 r 寫入 push 的時候,先確保環沒滿,然後把資料複製到 w 所對應的元素,最後 w 指向下乙個元素 讀取 pop 的時候,先確保環沒空,然後返回 r 對應的元素,最後 r 指向下乙個元素。上述的操作並不複雜,不過有乙個小小的麻煩 空環和滿環...