在模块里尝试自己实现了个队列, 在多进程(内核里应该叫做多线程吧)操作时会出问题。 也曾尝试解决遇到的问题,但由于自己内核开发功夫上签,最终还是失败了 .... 后来还是采
在模块里尝试自己实现了个队列, 在多进程(内核里应该叫做多线程吧)操作时会出问题。
也曾尝试解决遇到的问题,但由于自己内核开发功夫上签,最终还是失败了 ....
后来还是采取了内核的实现 kfifo(include/linux/kfifo.h), kfifo在 linux 标准内核>=2.6.10 添加, 这里标准内核是因为 RHEL4 的内核版本是2.6.9(小于2.6.10)但是也有此数据结构,然后标准内核(www.kernel.org) <2.6.10 就没有此数据结构了
写了个简单的实现如下:
-
#include <linux/init.h>
-
#include <linux/module.h>
-
#include <linux/kfifo.h>
-
#include <linux/err.h>
-
#define STR_LEN 64
-
#define KFF_LEN 512*256
-
struct kfifo *my_kfifo = NULL;
-
spinlock_t my_fifo_lock;
-
static int my_put(int num)
-
{
-
int i;
-
char buff[STR_LEN];
-
for(i=0; i<num; i++)
-
{
-
sprintf(buff,"My data: %d ...", i);
-
if(kfifo_put(my_kfifo, buff, STR_LEN) <= 0)
-
{
-
printk("<2>""%s failed\n", buff);
-
}
-
}
-
return num;
-
}
-
-
static int my_get(void)
-
{
-
char buff[STR_LEN];
-
while(kfifo_len(my_kfifo) > 0)
-
{
-
if(kfifo_get(my_kfifo, buff, STR_LEN) <= 0)
-
{
-
printk("<2>""kfifo_get failed\n");
-
}
-
printk("<2>""%s\n", buff);
-
}
-
return 0;
-
}
-
-
static int __init my_init(void)
-
{
-
printk("<2>""Init kfifo\n");
-
spin_lock_init(&my_fifo_lock);
-
my_kfifo = kfifo_alloc(KFF_LEN, GFP_KERNEL, &my_fifo_lock);
-
if(IS_ERR(my_kfifo))
-
{
-
printk("<2>""kfifo_alloc failed\n");
-
return -1;
-
}
-
my_put(10);
-
my_get();
-
-
return 0;
-
}
-
-
static void __exit my_exit(void)
-
{
-
kfifo_free(my_kfifo);
-
printk("<2>""Exit kfifo\n");
-
}
-
-
module_init(my_init);
-
module_exit(my_exit);
-
MODULE_LICENSE("GPL");
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kfifo.h>
#include <linux/err.h>
#define STR_LEN 64
#define KFF_LEN 512*256
struct kfifo *my_kfifo = NULL;
spinlock_t my_fifo_lock;
static int my_put(int num)
{
int i;
char buff[STR_LEN];
for(i=0; i<num; i++)
{
sprintf(buff,"My data: %d ...", i);
if(kfifo_put(my_kfifo, buff, STR_LEN) <= 0)
{
printk("<2>""%s failed\n", buff);
}
}
return num;
}
static int my_get(void)
{
char buff[STR_LEN];
while(kfifo_len(my_kfifo) > 0) // the number of bytes available in the FIFO ? 好像不对吧
{
if(kfifo_get(my_kfifo, buff, STR_LEN) <= 0)
{
printk("<2>""kfifo_get failed\n");
}
printk("<2>""%s\n", buff);
}
return 0;
}
static int __init my_init(void)
{
printk("<2>""Init kfifo\n");
spin_lock_init(&my_fifo_lock);
my_kfifo = kfifo_alloc(KFF_LEN, GFP_KERNEL, &my_fifo_lock); // 128k
if(IS_ERR(my_kfifo))
{
printk("<2>""kfifo_alloc failed\n");
return -1;
}
my_put(10);
my_get();
return 0;
}
static void __exit my_exit(void)
{
kfifo_free(my_kfifo);
printk("<2>""Exit kfifo\n");
}
module_init(my_init);
module_exit(my_exit);
MODULE_LICENSE("GPL");
Makefile:
ifneq ($(KERNELRELEASE),)
-
obj-m := kfifo.o
-
else
-
PWD ?= $(shell pwd)
-
KVERSION := $(shell uname -r)
-
all:
-
make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
-
clean:
-
make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean
-
endif
ifneq ($(KERNELRELEASE),)
obj-m := kfifo.o
else
PWD ?= $(shell pwd)
KVERSION := $(shell uname -r)
all:
make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean
endif
kfifo_alloc(...) 第一个参数限制了队列最大为 512*256 (128k)
因为 kfifo_alloc 使用了 kmalloc 分配内存, 而 kfree 不能分配 > 128K 的内存空间
下文采用另一种方法分配了 > 128k 内存的 kfifo
static int __init my_init(void)
-
{
-
printk("<2>""Init kfifo\n");
-
spin_lock_init(&my_fifo_lock);
-
ptr = (char*)vmalloc(KFF_LEN*128);
-
if(IS_ERR(ptr))
-
{
-
printk("<2>""vmalloc failed\n");
-
return -1;
-
}
-
my_kfifo = kfifo_init(ptr, KFF_LEN*128, GFP_KERNEL, &my_fifo_lock);
-
if(IS_ERR(my_kfifo))
-
{
-
printk("<2>""kfifo_alloc failed\n");
-
return -1;
-
}
-
my_put(32768);
-
my_get();
-
-
return 0;
-
}
-
-
static void __exit my_exit(void)
-
{
-
kfree(my_kfifo);
-
vfree(ptr);
-
printk("<2>""Exit kfifo\n");
-
}
static int __init my_init(void)
{
printk("<2>""Init kfifo\n");
spin_lock_init(&my_fifo_lock);
ptr = (char*)vmalloc(KFF_LEN*128); //分配了16M内存
if(IS_ERR(ptr))
{
printk("<2>""vmalloc failed\n");
return -1;
}
my_kfifo = kfifo_init(ptr, KFF_LEN*128, GFP_KERNEL, &my_fifo_lock); // 初始化16M的队列
if(IS_ERR(my_kfifo))
{
printk("<2>""kfifo_alloc failed\n");
return -1;
}
my_put(32768);
my_get();
return 0;
}
static void __exit my_exit(void)
{
kfree(my_kfifo);
vfree(ptr);
printk("<2>""Exit kfifo\n");
}
关于 kfifo_len
-
-
-
-
static inline unsigned int __kfifo_len(struct kfifo *fifo)
-
{
-
return fifo->in - fifo->out;
-
}
-
-
-
-
-
-
static inline unsigned int kfifo_len(struct kfifo *fifo)
-
{
-
unsigned long flags;
-
unsigned int ret;
-
-
spin_lock_irqsave(fifo->lock, flags);
-
-
ret = __kfifo_len(fifo);
-
-
spin_unlock_irqrestore(fifo->lock, flags);
-
-
return ret;
-
}
/**
* __kfifo_len - returns the number of bytes available in the FIFO, no locking version
* @fifo: the fifo to be used.
*/
static inline unsigned int __kfifo_len(struct kfifo *fifo)
{
return fifo->in - fifo->out;
}
/**
* kfifo_len - returns the number of bytes available in the FIFO
* @fifo: the fifo to be used.
*/
static inline unsigned int kfifo_len(struct kfifo *fifo)
{
unsigned long flags;
unsigned int ret;
spin_lock_irqsave(fifo->lock, flags);
ret = __kfifo_len(fifo);
spin_unlock_irqrestore(fifo->lock, flags);
return ret;
}
源码中kfifo_len() 的说明是:
kfifo_len - returns the number of bytes available in the FIFO
意思好像是说返回FIFO可用的字节数, 其实呢个人觉得返回的是FIFO中的数据长度
随着出队操作,此值在不断减小,直至 0
这么说此处的 available 应该是 available data