环形缓冲区的设计与实现

环形缓冲区实现(C语言) 提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录前言一、pandas是什么?二、使用步骤1.引入库2.读入数据总结欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 阅读详情

转载至:http://blog.youkuaiyun.com/wanxiao009/article/details/5519514

环形缓冲区是嵌入式系统中十分重要的一种数据结构,比如在一个视频处理的机制中,环形缓冲区就可以理解为数据码流的通道,每一个通道都对应着一个环形缓冲区,这样数据在读取和写入的时候都可以在这个缓冲区里循环进行,程序员可以根据自己需要的数据大小来决定自己使用的缓冲区大小。

    环形缓冲区,顾名思义这个缓冲区是环形的,那么何谓环形这个意思也很好理解,就是用一个指针去访问该缓冲区的最后一个内存位置的的后一位置时回到环形缓冲区的起点。类似一个环一样。这样形容就很好理解了,当然有办法实现了。我在这里采用了2种方式实现了环形缓冲区,一个是用数组的方法,一个是用链表的方法。

    数组是一块连续的内存,所以顺序访问时只要根据下标的增加而增加,但是最后一个元素之后需要回到起始位置,这就需要我们对这个地方进行特殊处理。只要最后一个地址访问结束能顺利回到起始地址,这个缓冲区就可以实现。代码如下:


[cpp] view plain copy
print?

    /* File name: ringbuf.c 
     * Author   : wanxiao 
     * Function :Implement a circular buffer,  
                 you can read and write data in the buffer zone. 
     */  
      
    #include <stdio.h>     
        
    #define MAXSIZE 8     
        
    int ringbuf[MAXSIZE];     
    int readldx=0;  
    int writeldx=0;  
      
    int next_data_handle(int addr)     
    {     
        return (addr+1) == MAXSIZE ? 0:(addr+1) ;     
    }     
        
    int write_data(int data)  
    {  
        int i;  
        *(ringbuf+writeldx) = data;  
        writeldx = next_data_handle(writeldx);  
        for(i=0;i<MAXSIZE;i++)  
        {  
            printf("%4d",*(ringbuf+i));  
            if(MAXSIZE-1 == i)  
                printf("/n");  
        }  
    }  
      
    int read_data()  
    {  
        printf("read data is : %d/n",*(ringbuf+readldx));  
        readldx = next_data_handle(readldx);  
    }  
        
    int main(int argc , char **argv)     
    {     
        int data;     
        char cmd;  
      
        do{     
            printf("select:/nw/t--write/nr/t--read/nq/t--quit/n");     
            scanf("%s",&cmd);     
        
            switch(cmd)     
            {     
                case 'w' :     
                    printf("please input data:");     
                    scanf("%d",&data);     
                    write_data(data);     
                    break;     
                case 'r' :     
                    data = read_data();     
                    break;     
                case 'q' :     
                    printf("quit/n");     
                    break;     
                default :     
                    printf("Command  error/n");     
            }     
        }while(cmd != 'q');     
        return 0;     
    }  

链表实现,实际上就是一个单向循环链表。这个方法的优点是不需要最后一个元素进行特殊处理,但是实现起来比数组稍微麻烦一点,单思路还是很清晰简单的。代码如下:

    #include <stdio.h>  
    #include <stdlib.h>  
      
      
    typedef struct signal_loop_chain  
    {  
        int data;  
        struct signal_loop_chain *next;  
    }NODE;  
      
    NODE *Create_loop_chain(int n)  
    {  
        int i;  
        NODE *head , *previous , *current ;  
        previous = (NODE *)malloc(sizeof(NODE));  
        if(previous == NULL)  
            exit(1);  
      
        previous->data =0;  
        previous->next = NULL;  
        head = previous ;  
      
        for(i=0 ; i<n ; i++)  
        {  
            current = (NODE*)malloc(sizeof(NODE));  
            if(current == NULL)  
                exit(1);  
      
    //      scanf("%d",¤t->data);  
            current->next = head;  
            previous->next = current;  
            previous = current ;  
        }  
        return head ;  
    }  
      
    int Show(NODE *head)  
    {  
        NODE *current;  
        current = head->next ;  
        printf("List:/n");  
        while(current != head)  
        {  
            printf("%4d",current->data);  
            current = current->next;  
        }  
        printf("/n");  
    }  
      
    int read_buf(NODE *head)  
    {  
        NODE *current;  
        current = head->next;  
        while(1)  
        {  
            printf("read number is %d/n",current->data);  
            current = current->next;  
            sleep(1);  
        }  
      
    }  
      
    int write_buf(NODE *head)  
    {  
        NODE *current;  
        int i = 0;  
        current = head->next;  
        while(1)  
        {  
            current->data = i++;  
            printf("write number is %d/n",current->data);  
            current = current->next;  
            sleep(1);  
        }  
    }  
      
    int main(int argc , char **argv)  
    {  
        int num;  
        char cmd;  
        NODE *head;  
        printf("please input node_num /n");  
        scanf("%d",&num);  
        head = Create_loop_chain(num);  
        printf("The ringbuf was found/n");  
        Show(head);  
      
        while(1){  
            printf("please select r or w/n");  
            scanf("%c",&cmd);  
      
            if(cmd == 'r'){  
                read_buf(head);  
                Show(head);  
            }  
              
            if(cmd == 'w'){  
                write_buf(head);  
                Show(head);  
            }  
              
        }  
        return 0;  
    }  

以上都是针对单进程而言。对于系统,尤其是嵌入式Linux系统中,缓冲区的保护机制就变得尤为重要了,因为我们的数据时不停的在读写,内存不停的变化,如果牵扯到多任务(多进程,多线程),我们就需要加锁对其进行保护措施。这里我在链表的实现下加了信号量加以保护。以上都是针对单进程而言。对于系统,尤其是嵌入式Linux系统中,缓冲区的保护机制就变得尤为重要了,因为我们的数据时不停的在读写,内存不停的变化,如果牵扯到多任务(多进程,多线程),我们就需要加锁对其进行保护措施。这里我在链表的实现下加了信号量加以保护。


    #include <stdio.h>  
    #include <stdlib.h>  
    #include <pthread.h>  
    #include <semaphore.h>  
      
    sem_t mutex;  
      
    typedef struct signal_loop_chain  
    {  
        int data;  
        struct signal_loop_chain *next;  
    }NODE;  
      
    NODE *Create_loop_chain(int n)  
    {  
        int i;  
        NODE *head , *previous , *current ;  
        previous = (NODE *)malloc(sizeof(NODE));  
        if(previous == NULL)  
            exit(1);  
      
        previous->data =0;  
        previous->next = NULL;  
        head = previous ;  
      
        for(i=0 ; i<n ; i++)  
        {  
            current = (NODE*)malloc(sizeof(NODE));  
            if(current == NULL)  
                exit(1);  
      
            current->next = head;  
            previous->next = current;  
            previous = current ;  
        }  
        return head ;  
    }  
      
    int Show(NODE *head)  
    {  
        NODE *current;  
        current = head->next ;  
        printf("List:/n");  
        while(current != head)  
        {  
            printf("%4d",current->data);  
            current = current->next;  
        }  
        printf("/n");  
    }  
      
    int read_buf(NODE *head)  
    {  
        NODE *current;  
        current = head->next;  
        while(1)  
        {  
            sem_wait(&mutex);  
            printf("read number is %d/n",current->data);  
            current = current->next;  
            sem_post(&mutex);  
            sleep(2);  
        }  
      
    }  
      
    int write_buf(NODE *head)  
    {  
        NODE *current;  
        int i = 0;  
        current = head->next;  
        while(1)  
        {  
            sem_wait(&mutex);  
            current->data = i++;  
            printf("write number is %d/n",current->data);  
            current = current->next;  
            sem_post(&mutex);  
            sleep(1);  
        }  
    }  
      
    int main(int argc , char **argv)  
    {  
        int num,ret;  
        char cmd;  
        NODE *head;  
        pthread_t id1,id2;  
      
        ret = sem_init(&mutex ,0,1);  
        if(ret != 0){  
            perror("sem_init error");  
        }  
        printf("please input node_num /n");  
        scanf("%d",&num);  
        head = Create_loop_chain(num);  
        printf("The ringbuf was found/n");  
        Show(head);  
      
        ret = pthread_create(&id1,NULL,(void *)write_buf,head);  
        ret = pthread_create(&id2,NULL,(void *)read_buf,head);  
      
        pthread_join(id1,NULL);  
        pthread_join(id2,NULL);  
          
      
        return 0;  
    }  




环形缓冲区优点及实现 使用环形缓冲区时存放sensor的x和y位置时,读与写互不干扰:读数据根据读指针读取,只有TaskReadPosition任务能够修改读指针位置;写数据使用写指针写数据,只有TaskWritePosition任务能够修改写指针的位置。环形缓冲区所有的push和pop操作都是在一个固定的存储空间内进行,相比队列方式,少掉了对于缓冲区元素所用存储空间的分配、释放。这是环形缓冲区的一个主要优势。环形缓冲区是一种特殊的缓冲区,其读指针和写指针都指向同一个缓冲区,通过移动指针来实现数据的读取和写入。 阅读详情

相关推荐

多核通信中的环形缓冲区设计与实现

环形缓冲区作为多核处理器间通信(IPC)的核心数据结构,通过共享内存机制实现高效数据交换。其FIFO特性与循环复用设计解决了传统队列频繁内存分配的问题,配合自旋锁、信号量等同步机制确保多核环境下的数据一致性。在嵌入式系统和Linux内核中,分片式与连续式两种实现各有优势:前者适合变长消息处理,后者则提供更高吞吐量。缓存行对齐、内存屏障等优化手段能显著提升性能,这些技术在实时系统、网络数据包处理等场景中具有重要应用价值。

weixin_31720909的博客 473

C++ 环形缓冲区(队列)简单实现

1. 说明 在实际工作中,如果数据流量过大,可以先把数据接收到数据缓冲区中,处理之后再取出。我们定义的包协议可以采用定长包,可以采用不定长度的包,环形缓冲区都能处理。 2. 使用场景 2.1 生产消费的场所 在 “生产者--消费者”模式中,往往会用到这种环形缓冲区的功能。 2.2 线程间高速通信的场所 3. 使用的局限性 主要适用于单向传输。不太适用于双向传输的情形。 4. 代码展示 CircleBuffer.h #pragma once # include <stdint.h&

thequitesunshine007的博客 3107

RTOS环境下线程安全环形缓冲区设计与实现

环形缓冲区(Ring Buffer)是一种基于固定大小内存实现高效生产者-消费者通信的基础数据结构,其核心原理依赖于头尾指针的模运算或位掩码环形索引机制。在实时操作系统(RTOS)中,传统裸机 RingBuffer 因缺乏对任务抢占、中断嵌套及多上下文共享内存的保护,极易引发竞态条件与数据损坏。引入互斥量(Mutex)等同步原语后,可构建具备确定性行为、可预测延迟的线程安全缓冲区,显著提升嵌入式系统的可靠性与可维护性。该技术广泛应用于UART中断收发解耦、多传感器数据聚合、DMA零拷贝传输等典型场景,尤其适

weixin_42607969的博客 522

Delphi版 环形无锁缓冲(二)

{*******************************************************} { } { 环形无锁缓冲Delphi版 } { 2016.04.13 By Lance

wowlancelot的博客 646

linux网络编程--Circular Buffer(Ring Buffer) 环形缓冲区的设计与实现

1. 应用场景       网络编程中有这样一种场景:需要应用程序代码一边从TCP/IP协议栈接收数据(reading data from socket),一边解析接收的数据。具体场景例如:用户点击Youtube或优酷网站上的视频内容,这时用户PC上的播放软件就是一边接收数据一边对数据进行解码并播放的。这样的场景的存在如下约束: 1. 必须边接收数据,边对数据进行解析,不能等待到数据全部接收完

鱼思故渊的专栏 7899

C++高性能线程池核心:无锁环形缓冲区任务队列设计与实现

在并发编程中,线程池是管理多线程执行、提升系统吞吐量的关键技术组件。其核心原理在于复用线程资源,避免频繁创建销毁线程的开销。实现高性能线程池的关键在于其内部的任务队列,它直接决定了任务调度的效率和系统的响应能力。传统的互斥锁保护队列在高并发场景下容易成为性能瓶颈,引发锁竞争和线程空转。为此,工程实践中常采用无锁编程思想结合环形缓冲区数据结构来构建高性能队列,通过原子操作和内存序保证线程安全,同时利用连续内存布局提升CPU缓存命中率。这种技术方案能显著降低延迟、提高吞吐,广泛应用于网络服务器、游戏引擎、金融交

weixin_31155097的博客 231

(转载)环形缓冲区的实现原理(ring buffer) .

环形缓冲区的实现原理(ring buffer)     在通信程序中,经常使用环形缓冲区作为数据结构来存放通信中发送和接收的数据。环形缓冲区是一个先进先出的循环缓冲区,可以向通信程序提供对缓冲区的互斥访问。 1、环形缓冲区的实现原理 环形缓冲区通常有一个读指针和一个写指针。读指针指向环形缓冲区中可读的数据,写指针指向环形缓冲区中可写的缓

mrwangwang的专栏 1866

环形缓冲区设计原理与嵌入式高效实现

环形缓冲区(Circular Buffer)是一种经典的FIFO数据结构,广泛应用于实时系统中的数据流控与暂存。其核心原理是利用固定大小的线性内存空间配合模运算(或位运算优化)实现逻辑上的首尾相连,从而在O(1)时间复杂度内完成入队、出队和状态查询。该结构具备确定性延迟、零动态分配、无锁SPSC支持等技术价值,特别适合资源受限的嵌入式场景,如UART中断缓存、ADC DMA数据中转、RTOS轻量消息传递等。本文聚焦于幂次尺寸设计、无符号溢出指针运算、两段memcpy高效拷贝等关键工程实践,深入解析如何将理论

weixin_42584758的博客 112

C++环形缓冲区设计与实现:从原理到应用的全方位解析

C++环形缓冲区设计与实现:从原理到应用的全方位解析

探索C++编程的奥秘,分享深入的技术见解和实践,旨在激发读者创造力与解决问题的思维。 3626

Delphi实现的环形缓冲区(全文件)

Delphi实现的环形缓冲区,有详细的注释说明和示意图,请大家给提出更为高效,简单的改进意见。 添加可以自动扩展大小的功能

环形缓冲区实现

两种方式实现环形缓冲区,很实用,希望对你有帮助!

动态内存池设计与环形缓冲区实现详解

动态内存池通过预分配固定大小的内存块,并统一管理分配与释放。环形缓冲区是一种高效的数据结构,避免数据覆盖并减少锁竞争。

guilin 923

[cadence]Allegro STEP-3D模型导入、匹配、导出的方法及注意事项

如果 Avaliable里面没有和symbols对应的文件,说明没有对应的3D模型,这时候需要在你的step路径下创建y与 .dra 封装文件相同名称的。选择好 Output file 和 name 之后呢,点击 Export。首先打开Setup - Step Package Mapping。注意:路径中不能有中文名称,有的话你会发现不能导出,也不会报错。在路径下将下载或者自己做的 3D模型文件改名之后,重新打开。可在View -> 3D View。

LuDvei的博客 2万+

VecDeque的环形缓冲区设计:高效双端队列的底层实现

Rust标准库中的VecDeque采用环形缓冲区设计实现高效双端队列操作。其核心是通过头尾指针和模运算的巧妙结合,将线性内存空间逻辑化为环形结构,实现O(1)时间复杂度的插入删除。关键技术包括:2的幂次容量优化模运算为位操作、牺牲1个空间位简化判空逻辑、连续内存保证缓存友好性。该设计完美平衡了性能与内存安全,特别适合滑动窗口、任务队列等需要高效双端操作的场景,展现了系统级编程的精妙权衡。

Z19963413529的博客 1529

基于vivado实现FFT/IFFT

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录前言一、实现的功能二、配置1.调用DDS的IP核2.调用FFT的IP核三、结果分析1.调用DDS的IP核2.读入数据总结 前言 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。 提示:以下是本篇文章正文内容,下面案例可供参考 一、实现的功能 示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任

qq_45600102的博客 1万+

openEuler系统下安装Google Chrome浏览器全攻略(附依赖问题解决方案)

本文详细介绍了在openEuler系统上安装Google Chrome浏览器的完整指南,包括环境准备、多种安装方式、依赖问题解决方案及性能优化技巧。针对openEuler特有的软件生态和依赖管理机制,提供了实用的命令和配置方法,帮助用户克服安装过程中的常见障碍,实现流畅的Chrome使用体验。

hadoop5ranger的博客 1152

FreeCache环形缓冲区:ringbuf.go设计与实现原理

FreeCache是Go语言中一款零GC开销的高性能缓存库,其核心秘密武器就是**环形缓冲区**的设计。今天我们就来深入剖析ringbuf.go文件中的环形缓冲区实现原理,了解它是如何实现高效内存管理和零GC开销的。🚀 ## 什么是环形缓冲区? 环形缓冲区是一种固定大小的数据结构,当数据超过容量时,新数据会覆盖最旧的数据。它就像一个圆环,数据在环上循环写入,始终保持着最新的数据内容。 在F

gitblog_01131的博客 430

在armv8架构中,有哪些是serror

(3)、RAS(Reliability, Availability, and Serviceability)错误:一些对于系统的可靠性、可用性和可维护性有影响的错误可能会触发 SError。(2)、ECC(Error Correction Code)错误:在访问带有错误校验的内存(如ECC内存)时,如果发现错误校验失败,可能会产生SError。2、其实呢,大多数Serror都是实现定义的,真正实现的serror就没有多少个。Serror(也称System Error),是异步异常的一种,一般是来自。

baron-周贺贺-代码改变世界ctw 1013
上一篇: Linux U盘分区格式化 fdisk命令
下一篇: Android 用 libusb 操作 USB 设备,无须 root
葫芦娃二娃
博客等级 码龄15年 1850粉丝 69原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值