linux内核入门之kfifo介绍(1)
2013-11-03 14:44
609 查看
1.介绍
kfifo是Linux内核一个通用的队列实现,它提供了两个主要操作:入队(in)和出队(out).kfifo对象维护了两个offset:in offset和out offset.in offset指示了下次入队的位置,而out offset指示了下次出队的位置.
入队(in)操作将数据从队列的in offset位置复制到队列中,完成后,in offset的值会加上数据的长度.出队(out)操作将数据从队列的out offset位置复制出来,完成后将out offset的值减去数据的长度.当out offset等于in offset,表明队列为空.当in offset等于队列的长度,表明队列已满.
kfifo的定义和实现分别在<linux/kfifo.h>和<kernel/kfifo.c>文件中.
2.kfifo操作
a.创建队列
动态创建:
int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask);
该函数创建和初始化一个size字节的kfifo队列.成功,返回0;出错则返回负error code.
使用自己定义的buffer,使用kfifo_init函数:
void kfifo_init(struct kfifo *fito, void *buffer, unsigned int size);
该函数创建和初始化一个以buffer为内存空间的队列.
使用kfifo_alloc和kfifo_init时,size必须是2的幂.
静态声明:
DECLARE_KFIFO(name, size);
INIT_KFIFO(name);
这两个宏创建一个名称为name,大小为size字节的队列.同上,size必须是2的幂.
b.入队
usinged int kfifo_in(struct kfifo *fifo, const void *from, unsigned int len);
该函数从from中复制len个字节的数据到fifo队列.成功则返回入队的字节数.如果fifo的可用空间小于len,则只复制可用空间的字节长度.因此返回值可能小于len或为0(没有复制任何数据).
c.出队
unsigned int kfifo_out(struct kfifo *fifo, void *to, unsigned int len);
该函数从队列中复制最多len个字节的数据到to.成功则返回已复制数据的长度.如果队列的数据少于len,则返回值可能len.
数据出队后将不能再次访问.
unsigned int kfifo_out_peek(struct kfifo *fifo, void *to, unsigned int len, unsigned offset);
该函数从列表的offset位置开始获取len字节的数据,但队列的数据仍然可以再次访问,out offset没有被更改.
d.获取队列大小
static inline unsigned int kfifo_size(struct kfifo *fifo);
该函数返回队列的空间总大小.
static inline unsigned int kfifo_len(struct kfifo *fifo);
该函数返回队列中已入队字节数.
static inline unsigned int kfifo_avail(struct kfifo *fifo);
该函数返回队列的可用空间的大小.
static inline int kfifo_is_empty(struct kfifo *fifo);
该函数测试kfifo是否为空.
static inline int kfifo_is_full(struct kfifo *fifo);
该函数测试kfifo是否已满.
e.重置和销毁队列
static inline void kfifo_reset(struct kfifo *fifo);
该函数重置队列.
void kfifo_free(struct kfifo *fifo);
该函数销毁用kfifo_alloc()创建的队列.
3.示例
a.目录结构
|--kfifo_test.c
|--Makefile
b.源代码
文件kfifo_test.c:
文件Makefile:
kfifo是Linux内核一个通用的队列实现,它提供了两个主要操作:入队(in)和出队(out).kfifo对象维护了两个offset:in offset和out offset.in offset指示了下次入队的位置,而out offset指示了下次出队的位置.
入队(in)操作将数据从队列的in offset位置复制到队列中,完成后,in offset的值会加上数据的长度.出队(out)操作将数据从队列的out offset位置复制出来,完成后将out offset的值减去数据的长度.当out offset等于in offset,表明队列为空.当in offset等于队列的长度,表明队列已满.
kfifo的定义和实现分别在<linux/kfifo.h>和<kernel/kfifo.c>文件中.
2.kfifo操作
a.创建队列
动态创建:
int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask);
该函数创建和初始化一个size字节的kfifo队列.成功,返回0;出错则返回负error code.
使用自己定义的buffer,使用kfifo_init函数:
void kfifo_init(struct kfifo *fito, void *buffer, unsigned int size);
该函数创建和初始化一个以buffer为内存空间的队列.
使用kfifo_alloc和kfifo_init时,size必须是2的幂.
静态声明:
DECLARE_KFIFO(name, size);
INIT_KFIFO(name);
这两个宏创建一个名称为name,大小为size字节的队列.同上,size必须是2的幂.
b.入队
usinged int kfifo_in(struct kfifo *fifo, const void *from, unsigned int len);
该函数从from中复制len个字节的数据到fifo队列.成功则返回入队的字节数.如果fifo的可用空间小于len,则只复制可用空间的字节长度.因此返回值可能小于len或为0(没有复制任何数据).
c.出队
unsigned int kfifo_out(struct kfifo *fifo, void *to, unsigned int len);
该函数从队列中复制最多len个字节的数据到to.成功则返回已复制数据的长度.如果队列的数据少于len,则返回值可能len.
数据出队后将不能再次访问.
unsigned int kfifo_out_peek(struct kfifo *fifo, void *to, unsigned int len, unsigned offset);
该函数从列表的offset位置开始获取len字节的数据,但队列的数据仍然可以再次访问,out offset没有被更改.
d.获取队列大小
static inline unsigned int kfifo_size(struct kfifo *fifo);
该函数返回队列的空间总大小.
static inline unsigned int kfifo_len(struct kfifo *fifo);
该函数返回队列中已入队字节数.
static inline unsigned int kfifo_avail(struct kfifo *fifo);
该函数返回队列的可用空间的大小.
static inline int kfifo_is_empty(struct kfifo *fifo);
该函数测试kfifo是否为空.
static inline int kfifo_is_full(struct kfifo *fifo);
该函数测试kfifo是否已满.
e.重置和销毁队列
static inline void kfifo_reset(struct kfifo *fifo);
该函数重置队列.
void kfifo_free(struct kfifo *fifo);
该函数销毁用kfifo_alloc()创建的队列.
3.示例
a.目录结构
|--kfifo_test.c
|--Makefile
b.源代码
文件kfifo_test.c:
#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/kfifo.h> void prt_kfifo_size(struct kfifo *fifo) { printk(KERN_INFO "kfifo size : %u bytes\n", kfifo_size(fifo)); printk(KERN_INFO "kfifo len : %u bytes\n", kfifo_len(fifo)); printk(KERN_INFO "kfifo avail : %u bytes\n", kfifo_avail(fifo)); } static int test_init(void) { struct kfifo fifo; int ret; int i; int buf[1024]; int nbytes; ret = kfifo_alloc(&fifo, 1024, GFP_KERNEL); if (ret)/*some error happened*/ return ret; for (i = 0; i < 32; i++) { kfifo_in(&fifo, &i, sizeof(i)); } prt_kfifo_size(&fifo); nbytes = kfifo_out_peek(&fifo, buf, 1024, 0); printk(KERN_INFO "peek : %d bytes\n", nbytes); for (i = 0; i < nbytes/sizeof(int); i++) { printk(KERN_INFO "%d ", buf[i]); } printk(KERN_INFO "\n======= after peek =======\n"); prt_kfifo_size(&fifo); nbytes = kfifo_out(&fifo, buf, sizeof(int)); printk(KERN_INFO "out : %d bytes\n", nbytes); printk(KERN_INFO "\n======= after out =======\n"); prt_kfifo_size(&fifo); kfifo_free(&fifo);/*must do this*/ return 0; } static void test_exit(void) { } module_init(test_init); module_exit(test_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("ice"); /* kfifo size : 1024 bytes kfifo len : 128 bytes kfifo avail : 896 bytes peek : 128 bytes 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 ======= after peek ======= kfifo size : 1024 bytes kfifo len : 128 bytes kfifo avail : 896 bytes out : 4 bytes ======= after out ======= kfifo size : 1024 bytes kfifo len : 124 bytes kfifo avail : 900 bytes */
文件Makefile:
obj-m := kfifo_test.o KERNELDIR ?= /lib/modules/`uname -r`/build PWD := `pwd` default: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
相关文章推荐
- linux内核入门之list介绍(1)
- Linux内核入门之内核基础知识介绍
- spring mvc入门教程(一)概念介绍
- SD卡中FAT32文件格式快速入门(图文详细介绍)
- Dubbo系列之——Dubbo入门介绍
- CSS入门介绍
- Webservice介绍,CXF入门程序
- HTML5之SVG 2D入门3—文本与图像及渲染文本介绍
- 工作流术语及入门知识介绍
- linux内核驱动入门的第一个实验:globalvar驱动
- HTTP协议(1)入门-协议介绍
- Servlet第一篇【介绍Servlet、HTTP协议、WEB目录结构、编写入门Servlet程序、Servlet生命周期】
- URLRewriter最简单入门介绍 URLRewriter相关资源
- [转贴]ArcObject入门介绍
- OpenStack入门修炼之KVM介绍及安装(3)
- Asp.Net控件开发(1)---入门介绍
- Scala基础入门(十一 ) Vector集合容器使用介绍
- JellyBean的VSync与三级buffer的入门介绍(外文翻译)
- 过滤器第一篇【介绍、入门、简单应用】
- 介绍Jersey-Jersey入门