<small id="vrfqa"><code id="vrfqa"></code></small>

    1. <ruby id="vrfqa"><table id="vrfqa"></table></ruby>

      
      
        <strong id="vrfqa"></strong>
        1. 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性色生活片久久无

            <small id="vrfqa"><code id="vrfqa"></code></small>

            1. <ruby id="vrfqa"><table id="vrfqa"></table></ruby>

              
              
                <strong id="vrfqa"></strong>