02_data_struct_ringbuffer

1. ringbuffer的基本概念

在C语言中,环形缓冲区(Ring Buffer),也称为循环缓冲区或循环队列,是一种常见的数据结构,用于在固定大小的连续内存空间中实现高效的数据读写操作。

环形缓冲区具有以下特点:

* 内存布局:环形缓冲区通常由一个固定大小的数组和两个指针构成,分别指向缓冲区的读取位置和写入位置。

* 循环性质:当读写指针到达缓冲区的边界时,它们会“循环”回到缓冲区的开头,形成一个环。

* 读写操作:数据可以从缓冲区的前端读取,也可以从后端写入,读写指针会相应地移动。

环形缓冲区的优势包括:

* 空间利用率高:由于数据的覆盖写入,环形缓冲区无需频繁地进行内存分配和释放。

* 操作效率高:读取和写入操作可以通过简单的指针操作来实现,效率较高。

2. ringbuffer的代码实现

下面是一个简单的环形缓冲区的示例实现:

// 测试文件的目录:
// Z:\2023-VSCODE-PRO\C++\C_Test_Demo_CMake\data_struct\ringbuffer_01.c
#include <stdio.h>
#define BUFFER_SIZE 10

typedef struct 
{
    int buffer[BUFFER_SIZE];
    int readIndex;
    int writeIndex;
} RingBuffer;

void init(RingBuffer* ringBuffer) 
{
    ringBuffer->readIndex = 0;
    ringBuffer->writeIndex = 0;
}

int isEmpty(RingBuffer* ringBuffer) 
{
    return ringBuffer->readIndex == ringBuffer->writeIndex;
}

int isFull(RingBuffer* ringBuffer) 
{
    return (ringBuffer->writeIndex + 1) % BUFFER_SIZE == ringBuffer->readIndex;
}

int write(RingBuffer* ringBuffer, int data) 
{
    if (isFull(ringBuffer)) 
    {
        // 缓冲区已满,无法写入新数据
        return -1;
    }
    
    ringBuffer->buffer[ringBuffer->writeIndex] = data;
    ringBuffer->writeIndex = (ringBuffer->writeIndex + 1) % BUFFER_SIZE;
}

int read(RingBuffer* ringBuffer) 
{
    if (isEmpty(ringBuffer)) 
    {
        // 缓冲区为空,无法读取数据
        return -1;
    }
    
    int data = ringBuffer->buffer[ringBuffer->readIndex];
    ringBuffer->readIndex = (ringBuffer->readIndex + 1) % BUFFER_SIZE;
    return data;
}

int main(int argc, char* argv[])
{
    RingBuffer buffer;
    int i;
    int data;

    // 初始化buffer
    init(&buffer);

    // 写buffer
    for(i = 0; i < 11; i++)
    {
        if(write(&buffer,i) == -1)
        {
            printf("buffer is full!\n");
        }
    }
    
    // 读buffer
    for (i = 0; i < 11; i++) 
    {
        data = read(&buffer);
        if(data == -1)
        {
             printf("Buffer is empty!\n");
        }
        else
        {
              printf("Data: %d\n", data);
        }
    }

    return 0;

}

 在这个示例中,我们定义了一个结构体 RingBuffer,包含一个固定大小的数组 buffer,以及读取位置 readIndex 和写入位置 writeIndex。使用 init 函数来初始化环形缓冲区。

isEmptyisFull 函数用于检查缓冲区是否为空或已满。write 函数用于向缓冲区写入数据,如果缓冲区已满,则无法写入新数据。read 函数用于从缓冲区读取数据,如果缓冲区为空,则无法读取数据。

通过这些函数,我们可以方便地进行环形缓冲区的读写操作。

需要注意的是,由于环形缓冲区的特性,当缓冲区已满时,写入新数据将会覆盖原有的数据。同样,当缓冲区为空时,读取数据将会返回一个特定的标识(例如示例中的 -1)。

希望这个示例能够帮助你和我理解C语言下环形缓冲区的概念!

测试程序运行结果如下:

 

未完待续...

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是完整的队列操作代码,包括驱动的初始化和退出函数: ``` #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/slab.h> struct msg { int data; int complete; }; struct ring_buffer { int head; int tail; struct msg *data; int size; unsigned int capacity; }; struct ring_buffer *ring_buffer_init(unsigned int capacity) { struct ring_buffer *rbuf = kmalloc(sizeof(struct ring_buffer), GFP_KERNEL); rbuf->capacity = capacity; rbuf->head = rbuf->size = 0; rbuf->tail = capacity - 1; rbuf->data = kmalloc(rbuf->capacity * sizeof(struct msg), GFP_KERNEL); printk(KERN_DEBUG "ring_buffer create successfully!\n"); return rbuf; } int ring_buffer_is_empty(struct ring_buffer *rbuf) { return (rbuf->size == 0); } int ring_buffer_is_full(struct ring_buffer *rbuf) { return (rbuf->size == rbuf->capacity); } void ring_buffer_in(struct ring_buffer *rbuf, struct msg msg) { if (ring_buffer_is_full(rbuf)) { return; } rbuf->tail = (rbuf->tail + 1) % rbuf->capacity; rbuf->data[rbuf->tail] = msg; rbuf->size = rbuf->size + 1; } struct msg ring_buffer_out(struct ring_buffer *rbuf) { struct msg rsv_msg; if (ring_buffer_is_empty(rbuf)) { pr_info("buffer is empty!\n"); rsv_msg.complete = -1; return rsv_msg; } rsv_msg = rbuf->data[rbuf->head]; rbuf->head = (rbuf->head + 1) % rbuf->capacity; rbuf->size = rbuf->size - 1; return rsv_msg; } void destroy_ring_buffer(struct ring_buffer *rbuf) { kfree(rbuf->data); kfree(rbuf); } static int __init my_driver_init(void) { struct ring_buffer *rbuf = ring_buffer_init(10); struct msg msg1 = {1, 0}; struct msg msg2 = {2, 0}; struct msg msg3 = {3, 0}; ring_buffer_in(rbuf, msg1); ring_buffer_in(rbuf, msg2); ring_buffer_in(rbuf, msg3); struct msg out1 = ring_buffer_out(rbuf); struct msg out2 = ring_buffer_out(rbuf); struct msg out3 = ring_buffer_out(rbuf); printk(KERN_DEBUG "out1: %d, out2: %d, out3: %d\n", out1.data, out2.data, out3.data); destroy_ring_buffer(rbuf); return 0; } static void __exit my_driver_exit(void) { printk(KERN_DEBUG "my_driver exit\n"); } module_init(my_driver_init); module_exit(my_driver_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("A simple example Linux module."); MODULE_VERSION("0.01"); ``` 上面的代码在驱动初始化函数中创建了一个容量为 10 的环形队列,然后向队列中插入了三个元素,接着连续地从队列中取出三个元素并打印,最后在驱动退出函数中销毁了队列。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值