正确使用循环缓冲区API

时间:2018-12-17 14:13:54

标签: kernel linux-kernel buffer

我需要更正circ_buf.cthese long errors吗?

最常见的错误是错误:一元``*”(具有“ int”)的无效类型参数

有关更多背景信息,请参见此reddit thread

/*
 * Filename: circ_buf.c
 * Version: 1.0
 * Description: A circular buffer using API from 
 * https://github.com/torvalds/linux/blob/master/Documentation/core-api/circular-buffers.rst
 */

#include <linux/slab.h>
#include <linux/circ_buf.h>
#include "circ_queue.h"

#define DEBUG 1

#ifdef DEBUG
#define DEBUG_MSG(...) printk(__VA_ARGS__)
#else
#define DEBUG_MSG(...)
#endif

struct item {
    unsigned int val1; // event number
    unsigned int val2; // relevant value tied to the event number
};

struct circ_buf * init_circ_queue(int len)
{
    struct circ_buf * q;
    spinlock_t head_tail_lock;

    q = kzalloc(sizeof(struct circ_buf), GFP_KERNEL);
    if (q == NULL) {
        DEBUG_MSG(KERN_ERR "Not enough memory to allocate circ_queue");
        return NULL;
    }

    spin_lock(&head_tail_lock);

    q->head = 0;
    q->tail = 0;

    spin_unlock(&head_tail_lock);

    // creates an array of length 'len' where each array location can store a struct * item
    q->buf = (char *) kzalloc(len*sizeof(struct item)*sizeof(unsigned int), GFP_KERNEL);  

    if (q->buf == NULL) {
        DEBUG_MSG(KERN_ERR "Not enough memory to allocate circ_queue array");
        return NULL;
    }

    return q;
}

inline int push_circ_queue(struct circ_buf * buffer, unsigned int val1, unsigned int val2)
{
    struct item *item;
    unsigned long head;
    unsigned long tail;
    spinlock_t producer_lock;

    spin_lock(&producer_lock);

    head = buffer->head;
    /* The spin_unlock() and next spin_lock() provide needed ordering. */
    tail = READ_ONCE(buffer->tail);

    if (CIRC_SPACE(head, tail, CIRC_BUFF_SIZE) >= 1) 
    {
        /* insert one item into the buffer */
        item->val1 = val1;
        item->val2 = val2;
        memcpy(&buffer[head], &item, 1);

        smp_store_release(buffer->head,
                          (head + 1) & (CIRC_BUFF_SIZE - 1));

        /* wake_up() will make sure that the head is committed before
         * waking anyone up */
        //wake_up(consumer);

        spin_unlock(&producer_lock);

        return 0;
    }

    else 
    {
        spin_unlock(&producer_lock); // still need to unlock even unused

        return 1; // not enough buffer space
    }
}

inline int pop_circ_queue(struct circ_buf * buffer, unsigned int * val1, unsigned int * val2)
{
    struct item *item;
    unsigned long head;
    unsigned long tail;
    spinlock_t consumer_lock;   

    spin_lock(&consumer_lock);

    /* Read index before reading contents at that index. */
    head = smp_load_acquire(buffer->head);
    tail = buffer->tail;

    if (CIRC_CNT(head, tail, CIRC_BUFF_SIZE) >= 1) 
    {
        /* extract one item from the buffer */
        memcpy(&item, &buffer[tail], 1);
        val1 = &item->val1;
        val2 = &item->val2;

        /* Finish reading descriptor before incrementing tail. */
        smp_store_release(buffer->tail,
                          (tail + 1) & (CIRC_BUFF_SIZE - 1));

        spin_unlock(&consumer_lock);

        return 0;
    }

    else 
    {
        spin_unlock(&consumer_lock); // still need to unlock even unused

        return 1; // not enough buffer space
    }
}

void free_circ_queue(struct circ_buf * q)
{
    if (q == NULL)
        return;

    kfree(q->buf);
    kfree(q);
}

0 个答案:

没有答案