kfifo(その2)


kfifo(その1)のサンプルで、kfifoにかかる部分のみを抜き出したものです。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kfifo.h>

#define FIFO_SIZE       32

static DECLARE_KFIFO(test, unsigned char, FIFO_SIZE);

static int __init testfunc(void)
{
    unsigned char   buf[6];
    unsigned char   i, j;
    unsigned int    ret;

    kfifo_in(&test, "hello", 5);
    for (i = 0; i != 10; i++)
        kfifo_put(&test, &i);

    i = kfifo_out(&test, buf, 5);
    printk(KERN_INFO "buf: %.*s\n", i, buf);
    printk(KERN_INFO "queue len: %u\n", kfifo_len(&test));
    for (j = 0; j != 10; j++) {
        ret = kfifo_get(&test, &i);
        printk(KERN_INFO "item = %d\n", i);
    }
    return 0;
}

static int __init example_init(void)
{
       INIT_KFIFO(test);
       if (testfunc() < 0) {
               return -EIO;
       }

       return 0;
}

static void __exit example_exit(void)
{
}

module_init(example_init);
module_exit(example_exit);
MODULE_LICENSE("GPL");

[root@localhost lkm]# dmesg
  :
[48442.749592] buf: hello
[48442.749985] queue len: 10
[48442.750644] item = 0
[48442.750976] item = 1
[48442.751359] item = 2
[48442.751641] item = 3
[48442.751954] item = 4
[48442.752224] item = 5
[48442.752652] item = 6
[48442.753036] item = 7
[48442.753396] item = 8
[48442.753673] item = 9
DECLARE_KFIFOマクロでfifo構造体を定義します。
struct __kfifo {
       unsigned int    in;
       unsigned int    out;
       unsigned int    mask;
       unsigned int    esize;
       void            *data;
};

#define DECLARE_KFIFO(fifo, type, size) STRUCT_KFIFO(type, size) fifo

#define STRUCT_KFIFO(type, size) \
       struct __STRUCT_KFIFO(type, size, 0, type)

#define __STRUCT_KFIFO(type, size, recsize, ptrtype) \
{ \
       __STRUCT_KFIFO_COMMON(type, recsize, ptrtype); \
       type            buf[((size < 2) || (size & (size - 1))) ? -1 : size]; \
}
buf[((size < 2) || (size & (size - 1))) ? -1 : size]  は、配列宣言の負のインデックスはコンパイル時エラーとなり、sizeは2以上で2の倍数のみを可能としています。
#define __STRUCT_KFIFO_COMMON(datatype, recsize, ptrtype) \
       union { \
               struct __kfifo  kfifo; \
               datatype        *type; \
               char            (*rectype)[recsize]; \
               ptrtype         *ptr; \
               const ptrtype   *ptr_const; \
       }
で、static DECLARE_KFIFO(test, unsigned char, FIFO_SIZE)の苛苛するような込み入った実装の結果は、
static struct {
       union {
               struct __kfifo kfifo;
               unsigned char *type;
               char (*rectype)[0];
               unsigned char *ptr;
               const unsigned char *ptr_const;
       };
       unsigned char buf[((32 < 2) || (32 & (32 - 1))) ? -1 : 32];
} test;
INIT_KFIFOマクロで上記構造体を初期化します。このマクロはDECLARE_KFIFOの構造体のunionメンバーのstruct __kfifo kfifoを設定することにあります。

__is_kfifo_ptrマクロは、fifoのサイズがstruct __kfifoのサイズと同じなら、unsigned char bufを有していないということで、 __kfifo->data=NULL,有しているなら__kfifo->data=kfifo->buffとなります。
__kfifo->in    書き込み位置
__kfifo->out   読み込み位置
__kfifo->mask  バッファーのエレメント数
__kfifo->esize バッファーのエレメントサイズ
__kfifo->data  バッファー

#define INIT_KFIFO(fifo) \
(void)({ \
       typeof(&(fifo)) __tmp = &(fifo); \
       struct __kfifo *__kfifo = &__tmp->kfifo; \
       __kfifo->in = 0; \
       __kfifo->out = 0; \
       __kfifo->mask = __is_kfifo_ptr(__tmp) ? 0 : ARRAY_SIZE(__tmp->buf) - 1;\
       __kfifo->esize = sizeof(*__tmp->buf); \
       __kfifo->data = __is_kfifo_ptr(__tmp) ?  NULL : __tmp->buf; \
})

#define __is_kfifo_ptr(fifo)    (sizeof(*fifo) == sizeof(struct __kfifo))
kfifo_inマクロはnバイトfifoからのデータをbuffに取得します。__recsize = sizeof(*__tmp->rectype)は__kfifo->inと同値です。__recsize=0ならfifoの先頭から__kfifo_in、そうでないならオフセットとして__kfifo_in_rで取得します。DECLARE_KFIFOマクロで定義すると、第二引数分のバッファが確保されます。
#define kfifo_in(fifo, buf, n) \
({ \
       typeof((fifo) + 1) __tmp = (fifo); \
       typeof((buf) + 1) __buf = (buf); \
       unsigned long __n = (n); \
       const size_t __recsize = sizeof(*__tmp->rectype); \
       struct __kfifo *__kfifo = &__tmp->kfifo; \
       if (0) { \
               typeof(__tmp->ptr_const) __dummy __attribute__ ((unused)); \
               __dummy = (typeof(__buf))NULL; \
       } \
       (__recsize) ?\
       __kfifo_in_r(__kfifo, __buf, __n, __recsize) : \
       __kfifo_in(__kfifo, __buf, __n); \
})
補足
       union { \
               struct __kfifo  kfifo; \
               datatype        *type; \
               char            (*rectype)[recsize]; \
               ptrtype         *ptr; \
               const ptrtype   *ptr_const; \
       }
のunionとしているkfifo以降のメンバーの取り扱いが良くわかりません。

最終更新 2013/08/12 16:25:14 - north
(2013/08/12 16:25:14 作成)


検索

アクセス数
3698081
最近のコメント
コアダンプファイル - sakaia
list_head構造体 - yocto_no_yomikata
勧告ロックと強制ロック - wataash
LKMからのファイル出力 - 重松 宏昌
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
Adsense
広告情報が設定されていません。