简介
API
#include <linux/kfifo.h># 声明一个FIFO#define DEFINE_KFIFO(fifo, type, size)# 使用例子static struct device *mydemodrv_device;DEFINE_KFIFO(mydemo_fifo, char, 64);# 读数据#define kfifo_to_user(fifo, to, len, copied)# 写数据#define kfifo_from_user(fifo, from, len, copied)
使用例程
static struct device *mydemodrv_device;DEFINE_KFIFO(mydemo_fifo, char, 64);# 将数据读取到buf 中。kfifo_to_user(&mydemo_fifo, buf, count, &actual_readed);# 将数据从buf写入fifokfifo_from_user(&mydemo_fifo, buf, count, &actual_write);
代码分析
struct __kfifo {unsigned int in;unsigned int out;unsigned int mask;unsigned int esize;void *data; # 存放数据的指针};
#include "kfifo.h"DEFINE_KFIFO(mydemo_fifo, char, 64);# gcc -E test.c -o test.i
声明
# 将 DEFINE_KFIFO(mydemo_fifo, char, 64); 使用预处理以后的结果 test.i# 其中 rectype 这一个字段是struct __kfifo {unsigned int in;unsigned int out;unsigned int mask;unsigned int esize;void *data;};struct kfifo {union {struct __kfifo kfifo;unsigned char *type; # 存储类型const unsigned char *const_type; #char (*rectype)[0]; #void *ptr; #void const *ptr_const;};unsigned char buf[0];};struct kfifo_rec_ptr_1 {union {struct __kfifo kfifo;unsigned char *type;const unsigned char *const_type;char (*rectype)[1];void *ptr;void const *ptr_const;};unsigned char buf[0];};struct kfifo_rec_ptr_2 {union {struct __kfifo kfifo;unsigned char *type;const unsigned char *const_type;char (*rectype)[2];void *ptr;void const *ptr_const;};unsigned char buf[0];};static inline unsigned int __must_check__kfifo_uint_must_check_helper(unsigned int val) {return val;}static inline int __must_check __kfifo_int_must_check_helper(int val) {return val;}# 比较重要的是这里, 声明缓存区和前后指针struct {union {struct __kfifo kfifo;char *type;const char *const_type;char (*rectype)[0];char *ptr;char const *ptr_const;}; # 可以看到,Kfifio是由一个联合体组合成的,缓存区buf,以及 union 的联合体char buf[((64 < 2) || (64 & (64 - 1))) ? -1 : 64]; # 静态定义一个 64 字节的区域} mydemo_fifo = (typeof(mydemo_fifo)){{{ # 这里就是直接在声明一个结构体的时候定义并且初始化结构体。.in = 0,# 初始化的是 __kfifo 结构体里面的数据.out = 0,.mask = (sizeof(*&(mydemo_fifo)) == sizeof(struct __kfifo))? 0: ARRAY_SIZE((mydemo_fifo).buf) - 1,.esize = sizeof(*(mydemo_fifo).buf), # 前面使用的数组存储数组,表示数组的长度.data = (sizeof(*&(mydemo_fifo)) == sizeof(struct __kfifo))? NULL: (mydemo_fifo).buf,}}};
读数据
# kfifo_to_user(&mydemo_fifo, buf, count, &actual_readed); 预处理以后的数据__kfifo_uint_must_check_helper(({typeof((&mydemo_fifo) + 1) __tmp = (&mydemo_fifo);void __user *__to = (buf);unsigned int __len = (count);unsigned int *__copied = (&actual_readed);const size_t __recsize = sizeof(*__tmp->rectype);struct __kfifo *__kfifo = &__tmp->kfifo;(__recsize) ? __kfifo_to_user_r(__kfifo, __to, __len, __copied, __recsize): __kfifo_to_user(__kfifo, __to, __len, __copied);}));我们可以观察到,调用的是两个函数(or)extern int __kfifo_to_user_r(struct __kfifo *fifo, void __user *to,unsigned long len, unsigned int *copied,size_t recsize);或者extern int __kfifo_to_user(struct __kfifo *fifo, void __user *to,unsigned long len, unsigned int *copied);
__kfifo_to_user 函数
kfifo_to_user 函数将会调用 __kfifo_to_user来判断越界等操作。然后调用静态函数kfifo_copy_to_user来赋值数据。最终还是调用的 copy_to_user函数。
lib/kfifo.cint __kfifo_to_user(struct __kfifo *fifo, void __user *to,unsigned long len, unsigned int *copied)kfifo_copy_to_user(fifo, to, len, fifo->out, copied);copy_to_user(to, fifo->data + off, l);
