在模組裡嘗試自己實現了個隊列, 在多進程(核心裡應該叫做多線程吧)操作時會出問題。
也曾嘗試解決遇到的問題,但由於自己核心開發功夫上籤,最終還是失敗了 ....
後來還是採取了核心的實現 kfifo(include/linux/kfifo.h), kfifo在 linux 標準核心>=2.6.10 添加, 這裡標準核心是因為 RHEL4.8 的核心版本是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*256struct 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.oelsePWD ?= $(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) cleanendif
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