<strike id="0k9r3"><p id="0k9r3"></p></strike>
  • <form id="0k9r3"></form>
    <nav id="0k9r3"></nav>
    <em id="0k9r3"><p id="0k9r3"></p></em>
  • <tr id="0k9r3"><source id="0k9r3"></source></tr>
    <form id="0k9r3"></form>
    <sub id="0k9r3"></sub>

      <sub id="0k9r3"><address id="0k9r3"></address></sub>
      1. <form id="0k9r3"></form>

        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


        請輸入搜索關鍵字

        確定
        国产在线视频在线