kfifo 用户空间实现

按照linux内核对kfifo的实现,修改成用户空间的kfifo,kfifo是一个循环存储队列,队列是一个大块内存,通过in和out指针管理进和出队列。比较适合大小固定的数据存储。这里的实现没有加锁机制!内核kfifo原理,参考http://blog.csdn.net/linyt/article/details/5764312

kfifo头文件。

#ifndef _Linux_KFIFO_H
#define _Linux_KFIFO_H

#define __u32 unsigned long
#define __u64 unsigned long long

#define min(x,y) ((x) < (y) ? (x) : (y) )

#define max(x,y) ((x) > (y) ? (x) : (y) )
/*
static inline int fls(int x)
{
    int r;

    __asm__("bsrl %1,%0nt"
            "jnz 1fnt"
            "movl $-1,%0n"
            "1:" : "=r" (r) : "rm" (x));
    return r+1;
}

*/
static inline int fls(int x)
{
    int r = 32; 

    if (!x)
        return 0;
    if (!(x & 0xffff0000u)) {
        x <<= 16; 
        r -= 16; 
    }   
    if (!(x & 0xff000000u)) {
        x <<= 8;
        r -= 8;
    }   
    if (!(x & 0xf0000000u)) {
        x <<= 4;
        r -= 4;
    }   
    if (!(x & 0xc0000000u)) {
        x <<= 2;
        r -= 2;
    }   
    if (!(x & 0x80000000u)) {
        x <<= 1;
        r -= 1;
    }   
    return r;
}

static inline int fls64(__u64 x)
{
    __u32 h = x >> 32;
    if (h)
        return fls(h) + 32;
    return fls(x);
}

static inline unsigned fls_long(unsigned long l)
{
    if (sizeof(l) == 4)
        return fls(l);
    return fls64(l);
}

static inline unsigned long roundup_pow_of_two(unsigned long x)
{
    return 1UL << fls_long(x - 1);
}

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) */
};

struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size);
struct kfifo *kfifo_alloc(unsigned int size);
void kfifo_free(struct kfifo *fifo);
unsigned int __kfifo_put(struct kfifo *fifo, unsigned char *buffer, unsigned int len);
unsigned int __kfifo_get(struct kfifo *fifo, unsigned char *buffer, unsigned int len);

static inline void __kfifo_reset(struct kfifo *fifo)
{
    fifo->in = fifo->out = 0;
}

static inline void kfifo_reset(struct kfifo *fifo)
{

    __kfifo_reset(fifo);

}

static inline unsigned int kfifo_put(struct kfifo *fifo,
                     unsigned char *buffer, unsigned int len)
{
    unsigned int ret;

    ret = __kfifo_put(fifo, buffer, len);

    return ret;
}

static inline unsigned int kfifo_get(struct kfifo *fifo,
                     unsigned char *buffer, unsigned int len)
{
    unsigned int ret;

    ret = __kfifo_get(fifo, buffer, len);

    if (fifo->in == fifo->out)
        fifo->in = fifo->out = 0;


    return ret;
}

static inline unsigned int __kfifo_len(struct kfifo *fifo)
{
    return fifo->in - fifo->out;
}

static inline unsigned int kfifo_len(struct kfifo *fifo)
{
    unsigned int ret;

    ret = __kfifo_len(fifo);

    return ret;
}

#endif
kfifo实现

#include "kfifo.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size)
{
    struct kfifo *fifo;

    fifo = (struct kfifo *)malloc(sizeof(struct kfifo));
    if (!fifo)
        return NULL;

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

    return fifo;
}

struct kfifo *kfifo_alloc(unsigned int size)
{
    unsigned char *buffer;
    struct kfifo *ret;
    if (size & (size - 1)) {
        fprintf(stderr,"size > 0x80000000n");
        size = roundup_pow_of_two(size);
    }

    buffer = (unsigned char *)malloc(size);
    if (!buffer)
        return NULL;

    ret = kfifo_init(buffer, size);

    if ((unsigned long)ret <= 0)
    {
        free(buffer);
    }

    return ret;
}

void kfifo_free(struct kfifo *fifo)
{
    free(fifo->buffer);
    free(fifo);
}

unsigned int __kfifo_put(struct kfifo *fifo, unsigned char *buffer, unsigned int len)
{
    unsigned int l;

    len = min(len, fifo->size - fifo->in + fifo->out);

        l = min(len, fifo->size - (fifo->in & (fifo->size - 1)));
    memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l);
    memcpy(fifo->buffer, buffer + l, len - l);

    fifo->in += len;

    return len;
}

unsigned int __kfifo_get(struct kfifo *fifo,
             unsigned char *buffer, unsigned int len)
{
    unsigned int l;

    len = min(len, fifo->in - fifo->out);

    l = min(len, fifo->size - (fifo->out & (fifo->size - 1)));
    memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), l);

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

kfifo测试(来自网友的代码)
#define FIFO_LENGTH 4096
#include <stdio.h>
#include <pthread.h>
#include <strings.h>
#include <string.h>
#include "kfifo.h"
struct ll_param
{
    struct kfifo * fifo;
    int msg_len;
};

static struct ll_param fifo;

void thread_reader(void * param)
{
    int read_len=0;
    unsigned int counter=0;
    unsigned char buffer[FIFO_LENGTH];
    struct ll_param * p=(struct ll_param *)param;
    
    printf("nnn = %d\n", roundup_pow_of_two(5));    
    
    for(;;)
    {
        bzero(buffer, FIFO_LENGTH);
        read_len=kfifo_get(p->fifo, buffer, 25);
        if(read_len !=0 )
        {
            printf("Read len:%d, buffer is  :< %s >n\n", read_len, buffer);
        }
        else
        {
            counter++;
        }
        if(counter > 20)
        {
            break;
        }
        usleep(50000);
    }
}

void thread_writer(void * param)
{
    unsigned int write_len = 0;
    unsigned int counter = 0;
    unsigned char buffer[32];
    struct ll_param * p = (struct ll_param *)param;
    
    for(counter = 0; counter < 100; counter++)
    {
        bzero(buffer,32);
        sprintf((char *)buffer, "This is %d message.n", counter);
        write_len=kfifo_put(p->fifo, buffer, 25); //strlen((char *)buffer)
        usleep(100);
    }
}


int main(void)
{
    pthread_t pidr;
    pthread_t pidw;

    fifo.msg_len = 10;
    fifo.fifo = kfifo_alloc(FIFO_LENGTH);

    pthread_create(&pidw, NULL, (void *)thread_writer, &fifo);
    pthread_create(&pidr, NULL, (void *)thread_reader, &fifo);

    pthread_join(pidr, NULL);
    pthread_join(pidw, NULL);

    kfifo_free(fifo.fifo);
    printf("nGoodbye!n\n");
    return 0;
}

Makefile

CFLAGS = -O2  -Wall 
INCLUDE = -I /
CC =  gcc 
  

test:test.o  kfifo.o
	${CC} ${CFLAGS} test.o  kfifo.o -o $@ ${INCLUDE} -pthread

test.o:
	$(CC) -c test.c ${INCLUDE} -pthread
kfifo.o:
	$(CC) -c kfifo.c ${INCLUDE}
clean:
	rm -rf *.o test


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值