|
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:
| |||||