这里是基于android7.1 kernel4.4的内核代码下:
kfifo是内核里面的一个first in first out数据结构,它采用环形循环队列(ringbuffer)的数据结构来实现;它提供一个无边界的字节流服务,最重要的一点是,它使用并行无锁编程技术,即当它用于只有一个入队线程和一个出队线程的场景时,两个线程可以并发操作,而不需要任何加锁行为,就可以保证kfifo的线程安全。
下面这里是我在跟amlogic android7.1 ir驱动代码时候看到的fifo的简单调用,这里只是拿来举例:
#include //添加头文件
struct remote_raw_handle {
struct list_head list;
struct remote_dev *dev;
struct task_struct *thread;
struct kfifo_rec_ptr_1 kfifo;/* fifo for the pulse/space durations */ ,定义kfifo_rec类型
spinlock_t lock;
enum raw_event_type last_type;
unsigned long jiffies_old;
unsigned long repeat_time;
unsigned long max_frame_time;
};
ret = kfifo_alloc(&dev->raw->kfifo, sizeof(struct remote_raw_event)*max_remote_event_size, gfp_kernel); //分配kfifo内存和初始化
retval = kfifo_len(&raw->kfifo); //返回fifo中可用的字节数
if (kfifo_in(&dev->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev)) //把数据存入fifo中,也就是入队列sizeof(*ev)个字节到fifo中。返回成功copy的个数
retval = kfifo_out(&raw->kfifo, &ev, sizeof(ev)); //从fifo获取一些数据, 也就是出队列sizeof(ev)个字节到ev中。返回成功copy的个数。
kfifo_free(&dev->raw->kfifo); //释放fifo占用
一些常用接口介绍:
首先定义一个fifo结构体:这里可以这样定义:struct kfifo fifo
/*
* define compatibility "struct kfifo" for dynamic allocated fifos
*/
struct kfifo __struct_kfifo_ptr(unsigned char, 0, void);
/*
* define kfifo_rec types
*/
struct kfifo_rec_ptr_1 __struct_kfifo_ptr(unsigned char, 1, void);
struct kfifo_rec_ptr_2 __struct_kfifo_ptr(unsigned char, 2, void);
/**
* kfifo_len - returns the number of used elements in the fifo
* @fifo: address of the fifo to be used
*/
kfifo_len(fifo) //返回fifo中使用的元素数量
/**
* kfifo_avail - returns the number of unused elements in the fifo
* @fifo: address of the fifo to be used
*/
kfifo_avail(fifo) //返回fifo中未使用元素的数量
/**
* kfifo_in - put data into the fifo
* @fifo: address of the fifo to be used
* @buf: the data to be added
* @n: number of elements to be added
*
* this macro copies the given buffer into the fifo and returns the
* number of copied elements.
*
* note that with only one concurrent reader and one concurrent
* writer, you don't need extra locking to use these macro.
*/
kfifo_in(fifo, buf, n) //将buf的n个数据放入fifo,返回复制元素的数量n
/**
* kfifo_out - get data from the fifo
* @fifo: address of the fifo to be used
* @buf: pointer to the storage buffer
* @n: max. number of elements to get
*
* this macro get some data from the fifo and return the numbers of elements
* copied.
*
* note that with only one concurrent reader and one concurrent
* writer, you don't need extra locking to use these macro.
*/
kfifo_out(fifo, buf, n) //从fifo中得到n个buf的数据,返回复制元素的数量n
/**
* kfifo_to_user - copies data from the fifo into user space
* @fifo: address of the fifo to be used
* @to: where the data must be copied
* @len: the size of the destination buffer
* @copied: pointer to output variable to store the number of copied bytes
*
* this macro copies at most @len bytes from the fifo into the
* @to buffer and returns -efault/0.
*
* note that with only one concurrent reader and one concurrent
* writer, you don't need extra locking to use these macro.
*/
kfifo_to_user(fifo, to, len, copied) //将数据从fifo复制到用户空间
/**
* kfifo_from_user - puts some data from user space into the fifo
* @fifo: address of the fifo to be used
* @from: pointer to the data to be added
* @len: the length of the data to be added
* @copied: pointer to output variable to store the number of copied bytes
*
* this macro copies at most @len bytes from the @from into the
* fifo, depending of the available space and returns -efault/0.
*
* note that with only one concurrent reader and one concurrent
* writer, you don't need extra locking to use these macro.
*/
kfifo_from_user(fifo, from, len, copied) //将一些来自用户空间的数据放入fifo
fifo环形工作队列使用说明举例:
int ret=0;
int data_count = 0;
unsigned char tempbuf[1024] = {
0};
struct kfifo fifo;
ret = kfifo_alloc(&fifo, 1024, gfp_kernel);//分配1024个大小的空间,并初始化。
if(ret) //返回值为非0,代表出错。
return error;
data_count = kfifo_len(&fifo);//查看fifo空间里的元素个数。
data_count = kfifo_avail(fifo);//查看fifo空间里空闲的个数。
data_count = kfifo_in(&fifo,(void *)(tempbuf),10);//入队列10个字节到fifo中。返回成功copy的个数。
data_count = kfifo_out(&fifo,(void *)(tempbuf),10);//出队列10个字节到tempbuf中。返回成功copy的个数。
ret = kfifo_to_user(&fifo, (void *)_usr,10,&copied);//出队列10个字节到用户空间,copied为copy成功的字节数。
ret = kfifo_from_user(&fifo, (void *) _usr, 10, &copied);// 从用户空间copy 10个字节到队列中,copied为copy成功的字节数。