トップページ (2hr)

Linux 日記
  Linux日記08~
  Linux日記2006
  Linux日記2005
  Linux日記2004
  Linux日記2003
  Linux日記2002 (3hr)
  Linuxカーネル
  + メモ ... (3p)
   勉強会
    第〇回
    第一回・予習
    第一回
    第二回・予習
    第二回
    カーネルparamsのR/W

アートでいこう(笑)!
  イラスト日記08〜 (6dy)
  イラスト日記2005
  イラスト日記2004
  イラスト日記2003
  アイコン描こうぜ

UCC(梅丘自転車部)
  活動ログ2003
  活動ログ2001
  活動ログ2000
  その他
  ワシの愛車

自動車関連
  FD3S日記05~
  S202日記2004
  S202日記2003
  S202日記2002
  S202給油等記録
  S202掲示板 (1hr)

自宅前カメラ
EZweb/PCSV用
プロフィール
社会科ノート 2004
社会科ノート 2003
全角半角変換
自家用リンク
視聴予定表
メモ

W/O index
カーネルパラメータの読み書き技法

カーネル内のパラメータの読み書きができれば、recompile なしに ユーザごとの環境へのカスタムも可能となります。それは、カーネルの状態のモニタで あるから、カーネル開発時のデバッグにも使えます。 そのような便宜を供する機能の一つとして、sysctl() システムコールや procfs などが あります。


sysctl() について

sysctl() というシステムコールがありました。今でもあるけど。

sysctl() とは、システム(要はカーネル)のパラメータを 読み書きするためのシステムコールであり、機能的に procfs と 完全にダブります。ごく単純な sysctl() ラッパとして、 その名もズバリの sysctl コマンドがあります。バッチ処理も 可能です。

$ /sbin/sysctl -a
sunrpc.nlm_debug = 0
sunrpc.nfsd_debug = 0
sunrpc.nfs_debug = 0
sunrpc.rpc_debug = 0
dev.md.speed-limit = 100
dev.cdrom.check_media = 0

  ... 中略 ...

kernel.version = #1 SMP Mon Sep 4 17:19:47 JST 2000
kernel.osrelease = 2.2.16-3smp
kernel.ostype = Linux

で、以下のようなスクリプトを書いてみる、と。

#!/bin/sh
tmp1=/tmp/sysctl-$$
tmp2=/tmp/proc-$$
sudo sysctl -a | sed -e 's/ .*//' -e 's/\./\//g' | \
 sort | uniq > $tmp1
for file in `find /proc/sys -type f`
do
  if sudo test -r $file
  then
    echo $file
  fi
done | sed -e 's/\/proc\/sys\///' | sort > $tmp2
diff -uNr $tmp1 $tmp2
rm -f $tmp1 $tmp2
以下、その結果。
--- /tmp/sysctl-23210 Mon Nov  6 18:06:12 2000
+++ /tmp/proc-23210   Mon Nov  6 18:06:12 2000
@@ -151,6 +151,7 @@
 net/ipv4/neigh/lo/unres_qlen
 net/ipv4/route/error_burst
 net/ipv4/route/error_cost
+net/ipv4/route/flush
 net/ipv4/route/gc_elasticity
 net/ipv4/route/gc_interval
 net/ipv4/route/gc_min_interval

基本的に、/proc/sys 以下の構造は、sysctl() の key の階層構造と同一です。 唯一きれいにならないのは、/proc/sys/net/ipv4/route/flush は write only なのに、permission が 0644 になっているからです。 エラーになるだけなので、実害はないですけれど。

でも気持ち悪いな。じゃあ 0200 にしてしまおう。

--- linux/net/ipv4/route.c.flush Mon Nov  6 18:16:30 2000
+++ linux/net/ipv4/route.c       Mon Nov  6 18:16:53 2000
@@ -1943,8 +1943,8 @@
 
 ctl_table ipv4_route_table[] = {
         {NET_IPV4_ROUTE_FLUSH, "flush",
-         &flush_delay, sizeof(int), 0644, NULL,
+         &flush_delay, sizeof(int), 0200, NULL,
          &ipv4_sysctl_rtcache_flush,
          &ipv4_sysctl_rtcache_flush_strategy },
         {NET_IPV4_ROUTE_MIN_DELAY, "min_delay",
          &ip_rt_min_delay, sizeof(int), 0644, NULL,

うん、オープンソースってすばらしい。


Miracle Linux Standard Edition 1.0 向けの改変点

以下は、MLSE-1.0 の kernel-2.2.16-3 の linux-2.2.16-proc-semopm.patch からの 抜粋です。semop(2) によって確保されるセマフォの個数の max 値の動的変更を 可能にします。

--- linux/kernel/sysctl.c.orig Mon Jul 10 08:17:21 2000
+++ linux/kernel/sysctl.c      Mon Jul 10 08:13:22 2000
@@ -49,6 +49,7 @@
 #endif
 #ifdef CONFIG_SYSVIPC
 extern int shmmax;
+extern int semopm;
 extern int shmall;
 extern int shmall_max;
 #endif
@@ -225,6 +226,8 @@
 #ifdef CONFIG_SYSVIPC
        {KERN_SHMMAX, "shmmax", &shmmax, sizeof (int),
         0644, NULL, &proc_dointvec},
+       {KERN_SEMOPM, "semopm", &semopm, sizeof (int),
+        0644, NULL, &proc_dointvec},
        {KERN_SHMALL, "shmall", &shmall, sizeof (int),
         0644, NULL, &proc_dointvec_minmax, &sysctl_intvec,
         NULL, &zero_value, &shmall_max},

これは、sysctl(2) と procfs の "sys" directory の双方に 反映されます。ほら簡単。


procfs エントリのつくりかた

sysctl() から離れて、少々 generic に、procfs のエントリの 作り方です。 しばらく見ない間に、えらく簡単になっていました。 このモジュールを insmod することで追加される ツリーは、以下のよう。

$ tree /proc/hoge_dir 
/proc/hoge_dir
|-- fuga_file
`-- hoge_file
 0: /* 
 1: gcc -D__KERNEL__ -DMODULE -Wall -O2 -DASSEMBLY -I/usr/include \
 2:  -c -o create_proc_entry.o create_proc_entry.c
 3: gcc -D__KERNEL__ -DMODULE -Wall -O2 -DASSEMBLY -I/usr/include \
 4:  -D__SMP__ -c -o create_proc_entry.o create_proc_entry.c
 5: */
 6: 
 7: #include <linux/autoconf.h>
 8: 
 9: #if defined(CONFIG_MODVERSIONS)
10: #include <linux/modversions.h>
11: #endif
12: 
13: #include <linux/kernel.h>
14: #include <linux/module.h>
15: #include <linux/proc_fs.h>
16: #include <asm/uaccess.h>
17: 
18: static int read_hoge(char * buf, char * * start,
19:  off_t offset, int length, int * eof, void * data ) {
20:   int len;
21:     /* You do not need to mind about "start", "offset", "length"
22:        and "eof" if the data is smaller than the size of a page.
23:        If the value of "start" is kept 0, the caller
24:        regards the data is smaller than the page. */
25:     len = 0;
26:     len += sprintf(buf + len, "hoge\n");
27:     return (len);
28: }
29: 
30: /* always null terminated */
31: static char sz_[65536] = "fuga\n";
32: 
33: static int read_fuga(char * buf, char * * start,
34:  off_t offset, int buf_len, int * eof, void * data ) {
35:     strncpy(buf, & (sz_[offset]), buf_len);
36:     (* start) = buf;
37:     if (((int) (strlen(sz_) - offset)) <= buf_len) {
38:         (* eof) = 1;
39:         buf_len = strlen(buf);
40:     }
41:     return (buf_len);
42: }
43: 
44: static int write_fuga(struct file * pfile, const char * buf,
45:  unsigned long input_length, void * data ) {
46:   static struct file * pfilePrev = (void *) 0;
47:   static int offset;
48:     if (pfile != pfilePrev) {
49:         offset = 0;
50:     }
51:     /* Oops! Though this works, why? */
52:     /* memcpy(& (sz_[offset]), buf, input_length); */
53:     copy_from_user(& (sz_[offset]), buf, input_length);
54:     offset += input_length;
55:     sz_[offset] = '\0';
56:     pfilePrev = pfile;
57:     return (input_length);
58: }
59: 
60: struct proc_dir_entry * pentry_dir_;
61: 
62: int init_module() {
63:   struct proc_dir_entry * pentry_file;
64:     pentry_dir_ = create_proc_entry(
65:      "hoge_dir", /* const char * name */
66:      S_IFDIR,    /* mode_t mode (/usr/include/linux/stat.h) */
67:      0 );        /* struct proc_dir_entry * parent */
68:     pentry_file = create_proc_entry("hoge_file", 0, pentry_dir_);
69:     if (pentry_file) {
70:         pentry_file->read_proc = read_hoge;
71:     }
72:     /* You can specify the name of the entry in the relative
73:        pathname from the root of procfs. */
74:     pentry_file = create_proc_entry("hoge_dir/fuga_file", 0, 0);
75:     if (pentry_file) {
76:         pentry_file->read_proc = read_fuga;
77:         pentry_file->write_proc = write_fuga;
78:     }
79:     return (0);
80: }
81: 
82: void cleanup_module() {
83:     remove_proc_entry(
84:      "hoge_file",   /* const char * name */
85:      pentry_dir_ ); /* proc_dir_entry * parent */
86:     remove_proc_entry("hoge_dir/fuga_file", 0);
87:     remove_proc_entry("hoge_dir", 0);
88: }
89: 


- ご意見・ご要望は、サイト管理者(那賀樹一郎 (Kiichiro NAKA) <knaka@ayutaya.com>)までお願いします。
- このサイトは、Turbolinux 上の Mozilla w3m でテストされています。Internet Explorer では未確認です
- 言うまでもありませんが、当サイトはリンクフリーです
- W3C の HTML チェックをかけたところ、ズタボロでした。頑張ったけど、ダメだこりゃ……