实践了内核的数据结构kfifo记录下,其特点分析看了下这篇博客写的很详细。https://blog.csdn.net/zhoutaopower/article/details/86491852
fifo.c 实现kfifo的主干函数接口,但是很多有用的接口没有扩展,需要的时候再扩展。
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#include"fifo.h"#define min(a, b) \
({ \typeof(a) _a = (a); \typeof(b) _b = (b); \_a <= _b ? _a : _b \
})static inline int fls(int x)
{int position;int i;if(0 != x){for(i = (x >> 1), position = 0; i != 0; ++position)i >>= 1;}else{position = -1;}return position+1;
}static inline unsigned int roundup_pow_of_two(unsigned int x)
{return 1UL << fls(x - 1);
}int __kfifo_alloc(struct __kfifo *fifo, unsigned int size, size_t esize)
{/** round up to the next power of 2, since our 'let the indices* wrap' technique works only in this case.*/size = roundup_pow_of_two(size);fifo->in = 0;fifo->out = 0;fifo->esize = esize;if (size < 2) {fifo->data = NULL;fifo->mask = 0;return -1;}// fifo->data = kmalloc_array(esize, size, gfp_mask);fifo->data = malloc(esize*size);if (!fifo->data) {fifo->mask = 0;return -1;}fifo->mask = size - 1;return 0;
}int __kfifo_init(struct __kfifo *fifo, void *buffer, unsigned int size, size_t esize)
{size /= esize;size = roundup_pow_of_two(size);fifo->in = 0;fifo->out = 0;fifo->esize = esize;fifo->data = buffer;if (size < 2) {fifo->mask = 0;return -1;}fifo->mask = size - 1;return 0;
}void __kfifo_free(struct __kfifo *fifo)
{free(fifo->data);fifo->in = 0;fifo->out = 0;fifo->esize = 0;fifo->data = NULL;fifo->mask = 0;
}/** internal helper to calculate the unused elements in a fifo*/
static inline unsigned int kfifo_unused(struct __kfifo *fifo)
{return (fifo->mask + 1) - (fifo->in - fifo->out);
}static void kfifo_copy_in(struct __kfifo *fifo, const void *src, unsigned int len, unsigned int off)
{unsigned int size = fifo->mask + 1;unsigned int esize = fifo->esize;unsigned int l;off &= fifo->mask;if (esize != 1) {off *= esize;size *= esize;len *= esize;}l = min(len, size - off);memcpy(fifo->data + off, src, l);memcpy(fifo->data, src + l, len - l);/** make sure that the data in the fifo is up to date before* incrementing the fifo->in index counter*/
// smp_wmb();
}unsigned int __kfifo_in(struct __kfifo *fifo, const void *buf, unsigned int len)
{unsigned int l;l = kfifo_unused(fifo);if (len > l)len = l;kfifo_copy_in(fifo, buf, len, fifo->in);fifo->in += len;return len;
}static void kfifo_copy_out(struct __kfifo *fifo, void *dst,unsigned int len, unsigned int off)
{unsigned int size = fifo->mask + 1;unsigned int esize = fifo->esize;unsigned int l;off &= fifo->mask;if (esize != 1) {off *= esize;size *= esize;len *= esize;}l = min(len, size - off);memcpy(dst, fifo->data + off, l);memcpy(dst + l, fifo->data, len - l);/** make sure that the data is copied before* incrementing the fifo->out index counter*/
// smp_wmb();
}unsigned int __kfifo_out_peek(struct __kfifo *fifo,void *buf, unsigned int len)
{unsigned int l;l = fifo->in - fifo->out;if (len > l)len = l;kfifo_copy_out(fifo, buf, len, fifo->out);return len;
}unsigned int __kfifo_out(struct __kfifo *fifo,void *buf, unsigned int len)
{len = __kfifo_out_peek(fifo, buf, len);fifo->out += len;return len;
}
fifo.h
#include<stdio.h>
#include<stdlib.h>struct __kfifo {unsigned int in; // 入列的时候增加的位置unsigned int out; // 出列的时候增加的位置unsigned int mask; // 巧妙的 mask 设计,同时包含了数据的个数信息unsigned int esize; // 元素的大小void *data; // 数据
};int __kfifo_alloc(struct __kfifo *fifo, unsigned int size, size_t esize);
int __kfifo_init(struct __kfifo *fifo, void *buffer,unsigned int size, size_t esize);
void __kfifo_free(struct __kfifo *fifo);
unsigned int __kfifo_in(struct __kfifo *fifo, const void *buf, unsigned int len);
unsigned int __kfifo_out(struct __kfifo *fifo, void *buf, unsigned int len);
test.c
2024-04-07 记录#include<stdio.h>
#include<stdlib.h>
#include"fifo.h"typedef struct node
{int a;int b;
}node;int main()
{int esize = sizeof(node);int size = 8;void *buf = NULL;struct __kfifo fifo;int count;node aa;aa.a = 12;aa.b = 13;node bb;bb.a = 0;bb.b = 0;__kfifo_init(&fifo, buf, size, esize);__kfifo_alloc(&fifo, size, esize);count = __kfifo_in(&fifo, (void *)&aa, 1); //注意这里传参是node的数量,不是node的大小。一开始实践赋值了node的大小,会有内存溢出。printf("in count: %d.\n", count);count = __kfifo_out(&fifo, (void *)&bb, 1);printf("out count: %d.\n", count);printf("bb.a :%d, bb.b :%d.\n", bb.a, bb.b);return 0;
}