内核中的kfifo的例子

  关于内核的kfifo介绍,可参考http://www.cnblogs.com/Anker/p/3481373.html

咱玩一点理论性没这么强的东西,先那个例子来跑一下就知道是怎么回事了。这里以内核下的samples/kfifo/record-example.c为例

/*
 * Sample dynamic sized record fifo implementation
 *
 * Copyright (C) 2010 Stefani Seibold <stefani@seibold.net>
 *
 * Released under the GPL version 2 only.
 *
 */

#include <linux/init.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/mutex.h>
#include <linux/kfifo.h>

/*
 * This module shows how to create a variable sized record fifo.
 */

/* fifo size in elements (bytes) */
#define FIFO_SIZE	128

/* name of the proc entry */
#define	PROC_FIFO	"record-fifo"

/* lock for procfs read access */
static DEFINE_MUTEX(read_lock);

/* lock for procfs write access */
static DEFINE_MUTEX(write_lock);

/*
 * define DYNAMIC in this example for a dynamically allocated fifo.
 *
 * Otherwise the fifo storage will be a part of the fifo structure.
 */
#if 0
#define DYNAMIC
#endif

/*
 * struct kfifo_rec_ptr_1 and  STRUCT_KFIFO_REC_1 can handle records of a
 * length between 0 and 255 bytes.
 *
 * struct kfifo_rec_ptr_2 and  STRUCT_KFIFO_REC_2 can handle records of a
 * length between 0 and 65535 bytes.
 */

#ifdef DYNAMIC
struct kfifo_rec_ptr_1 test;

#else
typedef STRUCT_KFIFO_REC_1(FIFO_SIZE) mytest;

static mytest test;
#endif

static const char *expected_result[] = {
	"a",
	"bb",
	"ccc",
	"dddd",
	"eeeee",
	"ffffff",
	"ggggggg",
	"hhhhhhhh",
	"iiiiiiiii",
	"jjjjjjjjjj",
};

static int __init testfunc(void)
{
	char		buf[100];
	unsigned int	i;
	unsigned int	ret;
	struct { unsigned char buf[6]; } hello = { "hello" };

	printk(KERN_INFO "record fifo test start\n");

	kfifo_in(&test, &hello, sizeof(hello));

	/* show the size of the next record in the fifo */
	printk(KERN_INFO "fifo peek len: %u\n", kfifo_peek_len(&test));

	/* put in variable length data */
	for (i = 0; i < 10; i++) {
		memset(buf, 'a' + i, i + 1);
		kfifo_in(&test, buf, i + 1);
	}

	/* skip first element of the fifo */
	printk(KERN_INFO "skip 1st element\n");
	kfifo_skip(&test);

	printk(KERN_INFO "fifo len: %u\n", kfifo_len(&test));

	/* show the first record without removing from the fifo */
	ret = kfifo_out_peek(&test, buf, sizeof(buf));
	if (ret)
		printk(KERN_INFO "%.*s\n", ret, buf);

	/* check the correctness of all values in the fifo */
	i = 0;
	while (!kfifo_is_empty(&test)) {
		ret = kfifo_out(&test, buf, sizeof(buf));
		buf[ret] = '\0';
		printk(KERN_INFO "item = %.*s\n", ret, buf);
		if (strcmp(buf, expected_result[i++])) {
			printk(KERN_WARNING "value mismatch: test failed\n");
			return -EIO;
		}
	}
	if (i != ARRAY_SIZE(expected_result)) {
		printk(KERN_WARNING "size mismatch: test failed\n");
		return -EIO;
	}
	printk(KERN_INFO "test passed\n");

	return 0;
}

static ssize_t fifo_write(struct file *file, const char __user *buf,
						size_t count, loff_t *ppos)
{
	int ret;
	unsigned int copied;

	if (mutex_lock_interruptible(&write_lock))
		return -ERESTARTSYS;

	ret = kfifo_from_user(&test, buf, count, &copied);

	mutex_unlock(&write_lock);

	return ret ? ret : copied;
}

static ssize_t fifo_read(struct file *file, char __user *buf,
						size_t count, loff_t *ppos)
{
	int ret;
	unsigned int copied;

	if (mutex_lock_interruptible(&read_lock))
		return -ERESTARTSYS;

	ret = kfifo_to_user(&test, buf, count, &copied);

	mutex_unlock(&read_lock);

	return ret ? ret : copied;
}

static const struct file_operations fifo_fops = {
	.owner		= THIS_MODULE,
	.read		= fifo_read,
	.write		= fifo_write,
	.llseek		= noop_llseek,
};

static int __init example_init(void)
{
#ifdef DYNAMIC
	int ret;

	ret = kfifo_alloc(&test, FIFO_SIZE, GFP_KERNEL);
	if (ret) {
		printk(KERN_ERR "error kfifo_alloc\n");
		return ret;
	}
#else
	INIT_KFIFO(test);
#endif
	if (testfunc() < 0) {
#ifdef DYNAMIC
		kfifo_free(&test);
#endif
		return -EIO;
	}

	if (proc_create(PROC_FIFO, 0, NULL, &fifo_fops) == NULL) {
#ifdef DYNAMIC
		kfifo_free(&test);
#endif
		return -ENOMEM;
	}
	return 0;
}

static void __exit example_exit(void)
{
	remove_proc_entry(PROC_FIFO, NULL);
#ifdef DYNAMIC
	kfifo_free(&test);
#endif
}

module_init(example_init);
module_exit(example_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Stefani Seibold <stefani@seibold.net>");


内核的打印为

<6>[(1975-10-08 17:34:05.583932503 UTC)] record fifo test start
<6>[(1975-10-08 17:34:05.583974429 UTC)] fifo peek len: 6
<6>[(1975-10-08 17:34:05.583995170 UTC)] skip 1st element
<6>[(1975-10-08 17:34:05.584013244 UTC)] fifo len: 65
<6>[(1975-10-08 17:34:05.584031021 UTC)] a
<6>[(1975-10-08 17:34:05.584047318 UTC)] item = a
<6>[(1975-10-08 17:34:05.584063614 UTC)] item = bb
<6>[(1975-10-08 17:34:05.584078281 UTC)] item = ccc
<6>[(1975-10-08 17:34:05.584093095 UTC)] item = dddd
<6>[(1975-10-08 17:34:05.584109688 UTC)] item = eeeee
<6>[(1975-10-08 17:34:05.584124799 UTC)] item = ffffff
<6>[(1975-10-08 17:34:05.584141392 UTC)] item = ggggggg
<6>[(1975-10-08 17:34:05.584156651 UTC)] item = hhhhhhhh
<6>[(1975-10-08 17:34:05.584173836 UTC)] item = iiiiiiiii
<6>[(1975-10-08 17:34:05.584189243 UTC)] item = jjjjjjjjjj
<6>[(1975-10-08 17:34:05.584205540 UTC)] test passed


写个进程(kfifo_write)去写kfifo

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <semaphore.h>
#include <pthread.h>
#include <string.h>

#define DEVICE_NAME "/proc/record-fifo"
#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0])) 
static const char *expected_result[] = {
	"a",
	"bb",
	"ccc",
	"dddd",
	"eeeee",
	"ffffff",
	"ggggggg",
	"hhhhhhhh",
	"iiiiiiiii",
	"jjjjjjjjjj",
};

int main(void)
{	
    
	
	int fd;
	int ret;
	int i;
	fd=open(DEVICE_NAME,O_RDWR);
	if(fd<0)
	{
		printf("open kfifo err!");
		return -1;
	}

	while(1)
	{	
		for(i=0;i<ARRAY_SIZE(expected_result);i++)
		{
			ret=write(fd,expected_result[i],strlen(expected_result[i]));
			printf("the size of array[%d])=%d\n",i,strlen(expected_result[i]));	
			if(ret<0)
			printf("write err!\n");		 
			sleep(2);
		    printf("----kfifo write---\n");
		}
	}
	return 0;
}

写个进程(kfifo_read)去读kfifo

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <semaphore.h>
#include <pthread.h>
#include <string.h>

#define DEVICE_NAME "/proc/record-fifo"
#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0])) 
static const char *expected_result[] = {
	"a",
	"bb",
	"ccc",
	"dddd",
	"eeeee",
	"ffffff",
	"ggggggg",
	"hhhhhhhh",
	"iiiiiiiii",
	"jjjjjjjjjj",
};

int main(void)
{		
	int fd;
	int ret;
	int i;
	char *buf;
	fd=open(DEVICE_NAME,O_RDWR);
	if(fd<0)
	{
		printf("open kfifo err!");
		return -1;
	}
	buf=malloc(10);
	if(buf<0)
		return -1;
	while(1)
	{
	
		
			ret=read(fd,buf,10);
			if(ret<0)
				printf("read kfifo err!\n");
			else if(ret==0)
				printf("no kfifo read!\n");
			else
				{
				printf("----kfifo read---\n");
				buf[ret]='\0';
				printf("read length is %d,and the string is %s\n",ret,buf);	
				} 
			sleep(1);	    
	}
	return 0;
}


同时写个Makefile,将驱动和应用同时编译出来

ifeq ($(KERNELRELEASE),)  
KERNELDIR ?= /home/w/xxxx/kernel/
DBG_CROSS_COMPILE ?= /home/w/xxxxx/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-
EXTRA_LIBS += -lpthread -static
CC=arm-linux-gnueabi-gcc
EXEC1 =  kfifo_write
OBJS1 =  kfifo_write.o
EXEC2 =  kfifo_read
OBJS2 =  kfifo_read.o
PWD :=$(shell pwd)  
all: $(EXEC1) $(EXEC2) modules
$(EXEC1): $(OBJS1)
	$(CC) $(LDFLAGS) -o $@ $(OBJS1)  $(EXTRA_LIBS)
$(EXEC2): $(OBJS2)
	$(CC) $(LDFLAGS) -o $@ $(OBJS2)  $(EXTRA_LIBS)
modules:  
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules  
modules_install:  
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install  
clear:  
	rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions modules.order  Module.symvers  *.elf *.elf2flt *.gdb *.o 
else  
     obj-m:= kfifo.o  
endif


先运行kfifo_read,再运行kfifo_write,打印信息为

root@android:/system # ./kfifo_write                                           
the size of array[0])=1
----kfifo write---
the size of array[1])=2
----kfifo write---
the size of array[2])=3
----kfifo write---
the size of array[3])=4
----kfifo write---
the size of array[4])=5
----kfifo write---
the size of array[5])=6
----kfifo write---
the size of array[6])=7
----kfifo write---
the size of array[7])=8
----kfifo write---
the size of array[8])=9
----kfifo write---
the size of array[9])=10
----kfifo write---
the size of array[0])=1
----kfifo write---
the size of array[1])=2
----kfifo write---

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

root@android:/system # ./kfifo_read                                            
no kfifo read!
no kfifo read!
no kfifo read!
no kfifo read!
no kfifo read!
no kfifo read!
no kfifo read!
no kfifo read!
no kfifo read!
no kfifo read!
no kfifo read!
no kfifo read!
no kfifo read!
no kfifo read!
no kfifo read!
no kfifo read!
no kfifo read!
no kfifo read!
----kfifo read---
read length is 1,and the string is a
no kfifo read!
----kfifo read---
read length is 2,and the string is bb
no kfifo read!
----kfifo read---
read length is 3,and the string is ccc
no kfifo read!
----kfifo read---
read length is 4,and the string is dddd
no kfifo read!
----kfifo read---
read length is 5,and the string is eeeee
no kfifo read!
----kfifo read---
read length is 6,and the string is ffffff
no kfifo read!
----kfifo read---
read length is 7,and the string is ggggggg
no kfifo read!
----kfifo read---
read length is 8,and the string is hhhhhhhh
no kfifo read!
----kfifo read---
read length is 9,and the string is iiiiiiiii
no kfifo read!
----kfifo read---
read length is 10,and the string is jjjjjjjjjj
no kfifo read!
----kfifo read---
read length is 1,and the string is a
no kfifo read!
----kfifo read---
read length is 2,and the string is bb

-----------------------------------------------------------------------------------------------------------------------------------------------------------------


  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: kfifo是Linux内核一种用于缓冲数据的数据结构,用于协调生产者和消费者的操作。它通过环形队列的方式管理数据的读写,实现了高效的数据传输。 将kfifo移植到应用层,可以实现在用户空间也能利用kfifo提供的高效数据缓冲功能。 首先,我们需要在应用程序引入kfifo的头文件,并将其编译进应用程序的代码。 然后,我们可以通过以下步骤使用kfifo: 1. 初始化kfifo:使用kfifo_init函数进行初始化,指定缓冲区大小和数据类型。 2. 写入数据:使用kfifo_in函数将需要传输的数据写入到kfifo的缓冲区。 3. 读取数据:使用kfifo_out函数从kfifo的缓冲区读取需要的数据。 4. 判断缓冲区状态:使用kfifo_is_empty和kfifo_is_full函数可以判断缓冲区是否为空或已满。 通过移植kfifo到应用层,我们可以在用户空间更灵活地使用这个高效的数据结构。我们可以在应用程序使用kfifo来管理数据缓冲区,实现生产者和消费者之间的数据传输,并且可以根据需求进行扩展和修改。 总结起来,将kfifo移植到应用层,可以提供一个高效的缓冲区管理方式,有助于提高应用程序的数据传输效率和性能。 ### 回答2: kfifo是Linux内核用于实现无锁队列的一种数据结构。它具有高效、可靠和线程安全等优点,因此在应用层进行移植时也能发挥其特性。 首先,应用层移植kfifo需要将kfifo的源代码从内核提取出来,并进行相应的修改,以适应应用层的环境。这包括调整数据结构的定义和函数的接口,确保其与应用层代码的兼容性。 其次,在移植kfifo时,需要根据具体的应用场景和需求来调整kfifo的大小和配置。kfifo的大小应根据实际数据量进行设置,以充分利用内存资源并避免溢出或浪费。同时,还可以根据需要调整kfifo是否支持多线程并发操作。 在应用层使用kfifo时,可以通过调用kfifo提供的接口来实现队列的入队和出队操作。这包括向kfifo插入元素、从kfifo获取元素以及获取队列的状态等。同时,还可以根据需要进行扩展,以满足具体应用场景的要求。 移植kfifo到应用层还需要注意线程安全性和并发控制。由于应用层可能存在多个线程同时对kfifo进行读写操作,因此需要增加适当的同步机制,如锁或原子操作,以确保数据的一致性和线程的安全。 总之,kfifo的移植到应用层可以提供高效、可靠和线程安全的队列功能,适用于各种应用场景。但在移植过程需要注意调整数据结构、接口和配置,并根据具体需求增加适当的扩展和并发控制机制,以提供更好的性能和可靠性。 ### 回答3: kfifo是Linux内核的一个环形缓冲区实现,通常用于在内核进行高效的数据传输。要将kfifo移植到应用层,需要进行以下步骤: 1. 了解kfifo的基本原理:kfifo是一个循环队列,具有读写指针和缓冲区。数据按照FIFO(先进先出)原则在缓冲区传输。 2. 将kfifo相关的头文件和源代码复制到应用程序的源代码目录。 3. 修改kfifo源代码内核相关的部分,使其适应用户空间。这可能包括对内存分配函数和同步原语的更改。 4. 修改kfifo的接口,使其适应应用层的数据传输需求。对于内核的kfifo,其接口可能是以IO操作的形式提供的,而在应用层,可以使用API函数来替代。 5. 在应用层,使用相应的API函数来初始化kfifo对象,并进行读写操作。注意,在应用层需要自己实现同步机制来保证多线程环境下的数据一致性。 6. 根据应用程序的需求,对kfifo进行适当的修改和扩展。例如,可以添加自定义的数据类型,修改缓冲区大小,以及添加其他辅助函数。 7. 进行测试和调试,确保kfifo在应用层能够正常工作。可以编写相应的测试代码来验证kfifo的正确性和性能。 总结起来,将kfifo移植到应用层需要了解kfifo的原理和接口,进行必要的修改和调整,并进行测试和调试以保证其正常工作。移植后的kfifo可以在应用层用于高效的数据传输和缓冲处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值