基于linux内核kfifo修改的环形缓冲区的C++程序

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>

#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define RING_BUFFER_INIT_CAP 4096
#define LOG_DEBUG printf("\n%s:%d\n", __FUNCTION__, __LINE__)

class RingBuffer
{
public:
    RingBuffer(uint32_t cap);
    ~RingBuffer();

    uint32_t data_len(void);
    void     clear(void);
    uint32_t push(uint8_t *buffer, uint32_t size);
    uint32_t pop(uint8_t *buffer, uint32_t size);

private:
    uint8_t* buffer;
    uint32_t cap;
    uint32_t write;
    uint32_t read;
    uint32_t get_power2(uint32_t n);
};

uint32_t RingBuffer::pop(uint8_t* buffer, uint32_t size)
{
    if(!buffer)
    {
        return 0;
    }

    uint32_t len = 0;
    size = MIN(size, this->data_len());
    len = MIN(size, this->cap - (this->read & (this->cap - 1)));
    memcpy(buffer, this->buffer + (this->read & (this->cap - 1)), len);

    memcpy((uint8_t *)buffer + len, this->buffer, size - len);

    this->read += size;
    printf("pop data len = %d\n", size);
    return size;
}

uint32_t RingBuffer::push(uint8_t *buffer, uint32_t size)
{
    if(!buffer)
    {
        return 0;
    }

    uint32_t len = 0;
    size = MIN(size, this->cap - this->data_len());
    len = MIN(size, this->cap - (this->write & (this->cap - 1)));
    memcpy(this->buffer + (this->write & (this->cap - 1)), buffer, len);

    memcpy(this->buffer, (uint8_t *)buffer + len, size - len);
    
    this->write += size;
    printf("push data len = %d\n", size);
    return size;
}

void RingBuffer::clear(void)
{
    this->read = 0;
    this->write = 0;
    printf("rb clear\n");
}

uint32_t RingBuffer::data_len(void)
{
    return (this->write - this->read);
}

uint32_t RingBuffer::get_power2(uint32_t n)
{
    uint32_t power_of_2 = 1;
    if(n)
    {
        if(n & (n - 1))
        {
            while (n > power_of_2)
            {
                power_of_2 <<= 1;
            }
        }
        else
        {
            power_of_2 = n;
        }
    }
    else
    {
        power_of_2 = RING_BUFFER_INIT_CAP;
    }

    return power_of_2;
}

RingBuffer::RingBuffer(uint32_t cap)
{
    this->cap = get_power2(cap);
    this->read = 0;
    this->write = 0;
    this->buffer = (uint8_t*)malloc(this->cap);
    if(!this->buffer)
    {
        //exception
    }
    printf("rb ctor this->cap = %d\n", this->cap);
}

RingBuffer::~RingBuffer()
{
    if(this->buffer)
    {
        free(this->buffer);
        printf("rb xtor\n");
    }
}

参照《巧夺天工的kfifo(修订版)》

参照《Ring Buffer介绍》

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
**内核环形缓冲区主要用于在读者线程和写者线程并发执行的场景下,实现免锁的安全读写,由内核Linux的KFIFO机制来管理缓冲区的使用情况**。这种缓冲区是一种具有固定大小、头尾相连的缓冲区的数据结构,适合用于缓存数据流。 内核环形缓冲区,也称为环形队列或循环缓冲区,是一种重要的数据结构,其基本概念是缓冲区形成一个环状,尾部与头部相连。当数据写入缓冲区并达到其最大容量时,新的数据会覆盖最早写入的数据,从而实现缓冲区的循环使用。这种结构特别适合于需要频繁读取和写入的数据流场景,例如网络设备驱动、音视频设备驱动等模块中。 环形缓冲区的一个主要优势在于其能够实现免锁的安全读写。在多线程的环境中,传统的缓冲区需要通过加锁机制来避免数据的竞态条件。然而,锁的使用会增加系统的开销并可能引起性能问题。环形缓冲区的设计允许多个线程同时对其进行读写操作而不会产生冲突,从而避免了使用锁的需求。 环形缓冲区由于其结构的特性,能够高效地管理缓冲区的使用情况。因为它是头尾相接的,所以当一个数据被读取后,对应的空间就可以立即用于存储新数据,无需像普通缓冲区那样移动大量数据来腾出空间。 综上所述,内核环形缓冲区在操作系统内核中扮演着重要角色,不仅提供了一种高效的数据缓存方法,还解决了多线程环境下的数据同步问题。它广泛应用于网络设备驱动、音视频设备驱动等模块,有效地提升了系统的性能和稳定性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值