简介
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写入fifo
kfifo_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.c
int __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);