<progress id="jlsnq"><code id="jlsnq"></code></progress>

<strong id="jlsnq"><del id="jlsnq"></del></strong>
    <mark id="jlsnq"></mark>

    <legend id="jlsnq"><table id="jlsnq"></table></legend>
    <small id="jlsnq"></small>
  • <ruby id="jlsnq"><table id="jlsnq"></table></ruby>

      <strong id="jlsnq"></strong>

      24小時聯系電話:18217114652、13661815404

      中文

      您當前的位置:
      首頁>
      電子資訊>
      技術專題>
      環形緩沖區C語言實現

      技術專題

      環形緩沖區C語言實現



      一、環形緩沖區的特性
      1、先進新出
      2、當緩沖區被使用完,且又有新的數據需要存儲時,丟掉歷史最久的數據,保存較新數據
      現實中的存儲介質都是線性的,因此我們需要做一下處理,才能在功能上實現環形緩沖區


      算法說明:
      1、pHead和pTail分別是連續存儲介質的首地址和尾地址
      2、pTail - pHead 的值是環形緩沖區的總長度
      3、pValid 是使用區域的起始指針,取數據時的起點,當取數據時pValid要發生偏移
      4、pValidTail 是使用區域的的結尾指針,存數據時的起點,當存數據時,pValidTail要發生偏移
      5、現有長度為addLen字節要存入,當pValidTail + addLen > pTail 時(超出了緩沖區,這時就要繞到開頭pHead)
      int len1 = pTail - pValidTail;
      int len2 = addLen - len1;
      pValidTail = pHead + len2;//新的使用區的尾指針
      6、判斷總長度是否變更,即是否有數據覆蓋pValid所指向的區域,如果有,要偏移pValid

      下面是已驗證的代碼

      ringBuffer.h

      #ifndef RINGBUFFER_H_
      #define RINGBUFFER_H_
      typedef unsigned char u8;
      typedef unsigned int u32;

      void initRingbuffer(void);
      int wirteRingbuffer(u8* buffer,u32 len);
      int readRingbuffer(u8* buffer,u32 len);
      u32 getRingbufferValidLen(void);
      void releaseRingbuffer(void);

      #endif /* RINGBUFFER_H_ */



      ringBuffer.c:

      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
      #include <assert.h>
      #include "ringBuffer.h"
      #define BUFFER_SIZE  16   //緩沖區的長度,可以修改

      static u32 validLen;//已使用的數據長度
      static u8* pHead = NULL;//環形存儲區的首地址
      static u8* pTail = NULL;//環形存儲區的結尾地址
      static u8* pValid = NULL;//已使用的緩沖區的首地址
      static u8* pValidTail = NULL;//已使用的緩沖區的尾地址

      /*
       * 初始化環形緩沖區
       * 環形緩沖區這里可以是malloc申請的內存,也可以是Flash存儲介質
       * */
      void initRingbuffer(void)
      {
      if(pHead == NULL)
      {
      pHead = (u8*) malloc(BUFFER_SIZE);
      }
      pValid = pValidTail = pHead;
      pTail = pHead + BUFFER_SIZE;
      validLen = 0;
      }

      /*
       * function:向緩沖區中寫入數據
       * param:@buffer 寫入的數據指針
       * @addLen 寫入的數據長度
       * return:-1:寫入長度過大
       *   -2:緩沖區沒有初始化
       * */
      int wirteRingbuffer(u8* buffer,u32 addLen)
      {
      if(addLen > BUFFER_SIZE) return -2;
      if(pHead==NULL) return -1;
      assert(buffer);

      //將要存入的數據copy到pValidTail處
      if(pValidTail + addLen > pTail)//需要分成兩段copy
      {
      int len1 = pTail - pValidTail;
      int len2 = addLen - len1;
      memcpy( pValidTail, buffer, len1);
      memcpy( pHead, buffer + len1, len2);
      pValidTail = pHead + len2;//新的有效數據區結尾指針
      }else
      {
      memcpy( pValidTail, buffer, addLen);
      pValidTail += addLen;//新的有效數據區結尾指針
      }

      //需重新計算已使用區的起始位置
      if(validLen + addLen > BUFFER_SIZE)
      {
      int moveLen = validLen + addLen - BUFFER_SIZE;//有效指針將要移動的長度
      if(pValid + moveLen > pTail)//需要分成兩段計算
      {
      int len1 = pTail - pValid;
      int len2 = moveLen - len1;
      pValid = pHead + len2;
      }else
      {
      pValid = pValid + moveLen;
      }
      validLen = BUFFER_SIZE;
      }else
      {
      validLen += addLen;
      }

      return 0;
      }

      /*
       * function:從緩沖區內取出數據
       * param   :@buffer:接受讀取數據的buffer
       *     @len:將要讀取的數據的長度
       * return  :-1:沒有初始化
       *     >0:實際讀取的長度
       * */
      int readRingbuffer(u8* buffer,u32 len)
      {
      if(pHead==NULL) return -1;

      assert(buffer);

      if(validLen ==0) return 0;

      if( len > validLen) len = validLen;

      if(pValid + len > pTail)//需要分成兩段copy
      {
      int len1 = pTail - pValid;
      int len2 = len - len1;
      memcpy( buffer, pValid, len1);//第一段
      memcpy( buffer+len1, pHead, len2);//第二段,繞到整個存儲區的開頭
      pValid = pHead + len2;//更新已使用緩沖區的起始
      }else
      {
      memcpy( buffer, pValid, len);
      pValid = pValid +len;//更新已使用緩沖區的起始
      }
      validLen -= len;//更新已使用緩沖區的長度

      return len;
      }

      /*
       * function:獲取已使用緩沖區的長度
       * return  :已使用的buffer長度
       * */
      u32 getRingbufferValidLen(void)
      {
      return validLen;
      }

      /*
       * function:釋放環形緩沖區
       * */
      void releaseRingbuffer(void)
      {
      if(pHead!=NULL) free(pHead);
      pHead = NULL;
      }



      測試main函數:

      #include <stdio.h>
      #include <stdlib.h>
      #include "ringBuffer.h"
      // 主函數
      int main()
      {
      char c;
      int readLen;
      u8 readBuffer[10];
      //setvbuf(stdout,NULL,_IONBF,0); //pinrtf、putchar不能立馬輸出,打開此注釋
      initRingbuffer();

      printf("Please enter a line [blank line to terminate]> ");
      do{
      c=getchar();
      putchar(c);
      switch(c)
      {
      case 'Q':
      goto exit;
      break;
      case 'R':
      readLen = readRingbuffer(readBuffer,10);
      printf("readRingbuffer len:%d\n",readLen);
      if(readLen > 0){
      printf("readRingbuffer:");
      for(int i=0;i<readLen;i++){
      printf("%c ",(char)readBuffer[i]);
      }
      printf("\n");
      }
      break;
      default :
      if(c!='\n') wirteRingbuffer((u8*)&c,1);
      break;
      }
      }while (1);

      exit:
      releaseRingbuffer();
      printf("exit.\n");
          return 0;
      }


      測試文件下載地址:

      ringBuffer.h

      ringBuffer.c

      main.c



      
      
      
      
      
      
      本文原創初次發表在:https://blog.csdn.net/maowentao0416/article/details/81984269


      請輸入搜索關鍵字

      確定
      色鲁99热99re超碰精品_91精品一区二区三区无码吞精_亚洲国产欧洲综合997久久_一级a性色生活片久久无
      <progress id="jlsnq"><code id="jlsnq"></code></progress>

      <strong id="jlsnq"><del id="jlsnq"></del></strong>
        <mark id="jlsnq"></mark>

      <legend id="jlsnq"><table id="jlsnq"></table></legend>
      <small id="jlsnq"></small>
    1. <ruby id="jlsnq"><table id="jlsnq"></table></ruby>

        <strong id="jlsnq"></strong>