誤解
わははは。どっかにメモリ割り当ててそこの値を出力させれば云々と考えておったのですが、loadavg とかどうやってんだろ、と思いつつソースツリーをナメてみたらありました。
どうやら読み出しの度に都度計算をしている模様。たしかにその方が早いわな。
むむ
ええと順を追って話をすると、昨晩のエントリでヒッカカった箇所ですな。fs/proc/generic.c にて定義されている proc_create 関数。proc_dir_entry な領域を作って最低限の属性の設定をしているのみ。ええとファイルの実体は? ってトコで思考が完全停止していた。
ただ、酔っ払いながら以下のコンテンツを探し出してもいた。さっき見つけた。
ぢつはソースを色々と弄って fs/proc/generic.c の proc_file_read 関数の中に記述されている_How to be a proc read function_というナニにはいきついていました。
結局
量的に少ないナニについては read_proc に登録されている手続きの中で云々。簡単なサンプルが Documentation/DocBook/procfs_example.c にある。
static int proc_read_jiffies(char *page, char **start, off_t off, int count, int *eof, void *data) { int len; len = sprintf(page, "jiffies = %ld\n", jiffies); return len; }
最初の引数が指す領域に sprintf してあげて領域の length を戻せば良いらしい。昨晩作ったナニを修正して以下なカンジ??
#include <linux/module.h> // required by all modules #include <linux/kernel.h> // required by printk() #include <linux/seq_file.h> // required by struct seq_operations #include <linux/fs.h> // required by struct file_operations #include <linux/proc_fs.h> // required by {create, remove}_proc_entry #include <linux/init.h> MODULE_LICENSE("GPL"); static int proc_read_yamanetoshi(char *page, char **start, off_t off, int count, int *eof, void *data) { int len; len = sprintf(page, "yamanetoshi\n"); return len; } // Start/Init function static int yamanetoshi_init(void) { struct proc_dir_entry *entry; entry = create_proc_entry("yamanetoshi", 0, NULL); if (entry) { entry->read_proc = proc_read_yamanetoshi; } return 0; } // End/Cleanup function static void yamanetoshi_exit(void) { remove_proc_entry("yamanetoshi", NULL); } module_init(yamanetoshi_init); module_exit(yamanetoshi_exit);
なるほどねー。これ、debug 用途でモジュール作ってカーネルの変数を云々なソレがとても簡単にできる仕掛けになっているのが分かる。
# そんなコトしなくても殆どの変数が /proc で覗けるハズですが
ちなみに
色々探してる時に loadavg のナニが、と思い立って fs/proc/proc_misc.c に行きついてたりもします。これと fs/proc/generic.c のコメントを併せて読むと良いか、と言いつつ以下が fs/proc/proc_misc.c の該当部分ッス。
static int proc_calc_metrics(char *page, char **start, off_t off, int count, int *eof, int len) { if (len <= off+count) *eof = 1; *start = page + off; len -= off; if (len>count) len = count; if (len<0) len = 0; return len; } static int loadavg_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { int a, b, c; int len; a = avenrun[0] + (FIXED_1/200); b = avenrun[1] + (FIXED_1/200); c = avenrun[2] + (FIXED_1/200); len = sprintf(page,"%d.%02d %d.%02d %d.%02d %ld/%d %d\n", LOAD_INT(a), LOAD_FRAC(a), LOAD_INT(b), LOAD_FRAC(b), LOAD_INT(c), LOAD_FRAC(c), nr_running(), nr_threads, current->nsproxy->pid_ns->last_pid); return proc_calc_metrics(page, start, off, count, eof, len); }
精査のログについては別途エントリ投入します。