kfifo的使用

linux的kfifo有以下注意点
1.当向fifo填充数据时称作put,这将会累加in字段,当向fifo取数据时称作get,这将会累加out字段。
2.对于只有一个生产者和一个消费者情形,可以不用对加锁,如有多个则需要加锁
3.当fifo缓冲区的size时2的次方时,kfifo->in % kfifo->size 可以转化为 kfifo->in & (kfifo->size – 1),否则不能。
4.in和out字段需要定义成无符号字段,当增加到最大值时,产生溢出从0就开始,以此循环使用
5.对于多个cpu,在每次读写in、out字段之前需要加内存屏障,1个cpu则不需要

下面是单核、一个生产者和一个消费者情形、buff size不是2的次方、1个cpu kfifo的例子

//filename:kfifo.c
#include "kfifo.h"

#define min(a,b) ((a) < (b) ? (a):(b))

int kFifoInit(kfifo_t *fifo, unsigned char *buffer, unsigned int size)
{
    if (!fifo)
        return -1;

    if(!buffer)
        return -1;

    fifo->buffer = buffer;
    fifo->size = size;
    fifo->in = fifo->out = 0;

    return 0;
}

unsigned int kFifoPut(kfifo_t *fifo, unsigned char *buffer, unsigned int len)
{
	unsigned int l;
 
	len = min(len, fifo->size - fifo->in + fifo->out);/*可能是缓冲区的空闲长度或者要写长度*/
 
	/* first put the data starting from fifo->in to buffer end*/
	//l = min(len, fifo->size - (fifo->in & (fifo->size -1)));
	l = min(len, fifo->size - (fifo->in % (fifo->size)));
	
	//memcpy((fifo->buffer + (fifo->in & (fifo->size -1))), buffer, l);
	memcpy((fifo->buffer + (fifo->in % (fifo->size))), buffer, l);
 
	/* then put the rest (if any) at the beginning of the buffer*/
	memcpy(fifo->buffer, buffer + l, len - l);

	fifo->in += len;
 
	return len;
}


unsigned int kFifoGet(kfifo_t *fifo, unsigned char *buffer, unsigned int len)
{
    unsigned int l;
 
    len = min(len, fifo->in - fifo->out); /*可读数据*/
 
    /* first get the data from fifo->out until the end of the buffer*/
    //l = min(len, fifo->size - (fifo->out & (fifo->size -1)));
    l = min(len, fifo->size - (fifo->out % (fifo->size)));
    //memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size -1)), l);
     memcpy(buffer, fifo->buffer + (fifo->out % (fifo->size)), l);
	
    /* then get the rest (if any) from the beginning of the buffer*/
    memcpy(buffer + l, fifo->buffer, len - l);
 
    fifo->out += len;
 
    return len;
}


unsigned int kFifoPeer(kfifo_t *fifo, unsigned char *buffer, unsigned int len)
{
    unsigned int l;
 
    len = min(len, fifo->in - fifo->out); /*可读数据*/
 
    /* first get the data from fifo->out until the end of the buffer*/
    //l = min(len, fifo->size - (fifo->out & (fifo->size -1)));
	l = min(len, fifo->size - (fifo->out % (fifo->size)));
    //memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size -1)), l);
	memcpy(buffer, fifo->buffer + (fifo->out % (fifo->size)), l);
 
    /* then get the rest (if any) from the beginning of the buffer*/
    memcpy(buffer + l, fifo->buffer, len - l);
  
    return len;
}


void kFifoReset(kfifo_t *fifo)
{
    fifo->in = fifo->out = 0;
}

unsigned int kFifoLen(kfifo_t *fifo)
{
    return fifo->in - fifo->out;
}


unsigned int kFifoAviable(kfifo_t *fifo)
{
    return fifo->size - kFifoLen(fifo);
}

//full 1
unsigned int kFifoFull(kfifo_t *fifo)
{
    return fifo->size == kFifoLen(fifo);
}

//empty 1
unsigned int kFifoEmpty(kfifo_t *fifo)
{
    return fifo->in == fifo->out;
}

//filename:kfifo.h
#ifndef _KFIFO_H_
#define _KFIFO_H_

#include "soc_types.h"
#include 
#include 
#include 
#include 

typedef struct kfifo 
{
    unsigned char *buffer;/* the buffer holding the data*/
    unsigned int size;/* the size of the allocated buffer*/
    unsigned int in;/* data is added at offset (in % size)*/
    unsigned int out;/* data is extracted from off. (out % size)*/
}kfifo_t;

extern int kFifoInit(kfifo_t *fifo, unsigned char *buffer, unsigned int size);
extern unsigned int kFifoPut(kfifo_t *fifo, unsigned char *buffer, unsigned int len);
extern unsigned int kFifoGet(kfifo_t *fifo, unsigned char *buffer, unsigned int len);
extern unsigned int kFifoPeer(kfifo_t *fifo, unsigned char *buffer, unsigned int len);
extern void kFifoReset(kfifo_t *fifo);
extern unsigned int kFifoLen(kfifo_t *fifo);
extern unsigned int kFifoAviable(kfifo_t *fifo);
extern unsigned int kFifoFull(kfifo_t *fifo); //full 1
extern unsigned int kFifoEmpty(kfifo_t *fifo); //empty 1

#endif

你可能感兴趣的:(算法与数据结构)