linux内核kfifo例子,linux内核入门之kfifo介绍(1)

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的定义和实现分别在和文件中.

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

#include

#include

#include

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值