返回首页

linux 内核 队列 kfifo

时间:2012-11-28 11:30来源:csdn 作者:cenziboy 点击:
在模块里尝试自己实现了个队列, 在多进程(内核里应该叫做多线程吧)操作时会出问题。 也曾尝试解决遇到的问题,但由于自己内核开发功夫上签,最终还是失败了 .... 后来还是采
  

在模块里尝试自己实现了个队列, 在多进程(内核里应该叫做多线程吧)操作时会出问题。

也曾尝试解决遇到的问题,但由于自己内核开发功夫上签,最终还是失败了 ....

后来还是采取了内核的实现 kfifo(include/linux/kfifo.h), kfifo在 linux 标准内核>=2.6.10 添加, 这里标准内核是因为 RHEL4 的内核版本是2.6.9(小于2.6.10)但是也有此数据结构,然后标准内核(www.kernel.org) <2.6.10 就没有此数据结构了

写了个简单的实现如下:

  1. #include <linux/init.h>   
  2. #include <linux/module.h>   
  3. #include <linux/kfifo.h>   
  4. #include <linux/err.h>   
  5. #define STR_LEN 64   
  6. #define KFF_LEN 512*256   
  7. struct kfifo *my_kfifo = NULL;  
  8. spinlock_t my_fifo_lock;  
  9. static int my_put(int num)  
  10. {  
  11.     int i;  
  12.     char buff[STR_LEN];  
  13.     for(i=0; i<num; i++)  
  14.     {  
  15.         sprintf(buff,"My data: %d ...", i);  
  16.         if(kfifo_put(my_kfifo, buff, STR_LEN) <= 0)  
  17.         {  
  18.             printk("<2>""%s failed\n", buff);  
  19.         }  
  20.     }  
  21.     return num;  
  22. }  
  23.   
  24. static int my_get(void)  
  25. {  
  26.     char buff[STR_LEN];  
  27.     while(kfifo_len(my_kfifo) > 0)  // the number of bytes available in the FIFO ? 好像不对吧   
  28.     {  
  29.         if(kfifo_get(my_kfifo, buff, STR_LEN) <= 0)  
  30.         {  
  31.             printk("<2>""kfifo_get failed\n");  
  32.         }  
  33.         printk("<2>""%s\n", buff);  
  34.     }  
  35.     return 0;  
  36. }  
  37.   
  38. static int __init my_init(void)  
  39. {  
  40.     printk("<2>""Init kfifo\n");  
  41.     spin_lock_init(&my_fifo_lock);  
  42.     my_kfifo = kfifo_alloc(KFF_LEN, GFP_KERNEL, &my_fifo_lock); // 128k   
  43.     if(IS_ERR(my_kfifo))  
  44.     {  
  45.         printk("<2>""kfifo_alloc failed\n");  
  46.         return -1;  
  47.     }  
  48.     my_put(10);  
  49.     my_get();  
  50.   
  51.     return 0;  
  52. }  
  53.   
  54. static void __exit my_exit(void)  
  55. {  
  56.     kfifo_free(my_kfifo);  
  57.     printk("<2>""Exit kfifo\n");  
  58. }  
  59.   
  60. module_init(my_init);  
  61. module_exit(my_exit);  
  62. 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  

 

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); //分配了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

/** 

  •  * __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
 

------分隔线----------------------------

  • 李老师
  • 李老师
  • 胡老师
  • 胡老师
合作伙伴
  • 武汉工程大学合作培训机构

  • 国家信息技术紧缺人才培养工程(NITE)

  • ARM公司全球授权培训中心

  • 国内首家Symbian授权培训

  • 微软全球嵌入式合作伙伴

  • Altera全球合作培训机构

在线客服
  • 客服热线:
    139-8620-3604
    159-2752-9536



  • 官方微信
  •  咨询微信二维码