linux 內核 隊列 kfifo

在模塊裏嘗試自己實現了個隊列, 在多進程(內核裏應該叫做多線程吧)操作時會出問題。

也曾嘗試解決遇到的問題,但由於自己內核開發功夫上籤,最終還是失敗了 ....

後來還是採取了內核的實現 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*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



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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章