seq_file


seq_fileはobject単位で管理されているリソースを、シーケンシャルとして参照させる事で、カーネルのリスト管理されているリソースをvfs下のシーケンシャルread/writeで参照するproc等での利用を目的とした機能です。以下は、その機能に特化したサンプルです。

seq_next()の引数m, void *v, loff_t *posは、読み込まれたobjectと、そのインデックス(読み込まれたobjectの数)で、*vはobjectがリスト管理されている場合等に参照されることになります。

do_mmap()は、seq_read()の第二引数のバッファは、ファイルオペレーションのreadコールバック関数を想定して故、ユーザ空間である必要があります。

seq_open()は、seq_operationsコールバックをhoge_file.private_datに設定する事で、fileオペレーションでseq_operationsコールバックを介しての参照が可能となります。なお、.showコールバックは表示というのでなく、目的とするobjectを seq_file->bufに複写します。
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/seq_file.h>
#include <linux/uaccess.h>
#include <linux/string.h>
#include <linux/mman.h>
#include <linux/moduleparam.h>

static struct file hoge_file;
static  char    hoge_data[10][10];
static  int     size;
module_param(size, int, 0);

static int seq_show(struct seq_file *m, void *v)
{
       return seq_printf(m, "%s:", (char *)v);
}

static void *seq_start(struct seq_file *m, loff_t *pos)
{
       return hoge_data[*pos];
}

static void *seq_next(struct seq_file *m, void *v, loff_t *pos)
{
       if(*pos >= 9) {
               return NULL;
       }
       return hoge_data[++*pos];
}

static void seq_stop(struct seq_file *m, void *p)
{
       seq_puts(m, "[end]\n");
}

static const struct seq_operations hoge_op = {
       .start  = seq_start,
       .next   = seq_next,
       .show   = seq_show,
       .stop   = seq_stop
};

void    hogedata_init(void)
{
      int     i;

       for (i = 0; i < 10; i++) {
               sprintf(hoge_data[i], "hoge%d", i+1);
       }
}

static int __init seq_hoge_init(void)
{
       long    addr;
       loff_t  pos = 0;

       hogedata_init();

       addr = do_mmap(NULL, 0, 4012,
                 PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE, 0);
       seq_open(&hoge_file, &hoge_op);
       seq_read(&hoge_file, (char __user *)addr, size, &pos);

       printk((char *)addr);
       return 0;
}

static void seq_hoge_exit(void)
{
       seq_release(NULL, &hoge_file);
}
module_init(seq_hoge_init);
module_exit(seq_hoge_exit);
実行結果
[root@localhost lkm]# insmod seq_hoge.ko size=100
[root@localhost lkm]# dmesg
[  643.296579] hoge1:hoge2:hoge3:hoge4:hoge5:hoge6:hoge7:hoge8:hoge9:hoge10:[end]

[root@localhost lkm]# insmod seq_hoge.ko size=10
[root@localhost lkm]# dmesg
[  693.053244] hoge1:hoge
読込みサイズで全objectを読み込めない時、[end]が表示されていませんが、.stopコールバックはコールされ、seq_file.buffには設定されていますが(バッファは4K単位)、ユーザ空間バッファへ転送する時に転送されません。

実際のファイルシステム下の実装は、ファイルオペレーションのopenコールバック関数にseq_open()を、readコールバック関数にseq_read()を設定します。


最終更新 2015/01/19 00:36:03 - north
(2015/01/17 12:37:21 作成)


検索

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