NetBSD Advent Calendar 2024 5日目の記事です。今日はNetBSD-10で追加されたカーネルモジュールサンプルを紹介しようと思います。
新たに追加されたカーネルモジュールサンプル
NetBSD-10の/usr/src/sys/modules/examplesを見ると、カーネルモジュールの新しいサンプルがいくつか追加されています。ざっと確認すると、以下のサンプルが追加されているようです。これらのサンプルを(分かる範囲で)見てゆこうと思います。
- current_time
- ddbping
- fopsmapper
- ping_block
- pollpal
current_timeモジュール
さっそくカーネルモジュールをビルドして試してみます。 make
してmodload(8)、modload(8)を実行します。
# cd /usr/src/sys/modules/examples/current_time/
# make
/usr/src/tooldir.NetBSD-10.0-amd64/bin/x86_64--netbsd-gcc -O2 -g -std=gnu99 -Wall -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith -Wno-sign-compare -Wsystem-headers -Wno-traditional -Wa,--fatal-warnings -Wreturn-type -Wswitch -Wshadow -Wcast-qual -Wwrite-strings -Wextra -Wno-unused-parameter -Wno-sign-compare -Wold-style-definition -Wsign-compare -Wformat=2 -Wno-format-zero-length -Werror -Wno-address-of-packed-member -Wno-pointer-sign -Wno-attributes -Wno-type-limits -ffreestanding -fno-strict-aliasing -mno-red-zone -mno-mmx -mno-sse -mno-avx -msoft-float -mcmodel=kernel -fno-omit-frame-pointer -I/usr/src/common/include --sysroot=/ -I/usr/src/common/include -nostdinc -I. -I/usr/src/sys/modules/examples/current_time -isystem /usr/src/sys -isystem /usr/src/sys/arch -isystem /usr/src/sys/../common/include -D_KERNEL -D_MODULE -DSYSCTL_INCLUDE_DESCR -DKDTRACE_HOOKS -c current_time.c -o current_time.o.o
/usr/src/tooldir.NetBSD-10.0-amd64/bin/nbctfconvert -L VERSION -o current_time.o current_time.o.o && rm -f current_time.o.o
# link current_time/current_time.kmod
/usr/src/tooldir.NetBSD-10.0-amd64/bin/x86_64--netbsd-gcc --sysroot=/ -Wl,--warn-shared-textrel -Wl,-z,relro -nostdlib -r -Wl,-T,/usr/src/sys/../sys/modules/xldscripts/kmodule,-d -Wl,-Map=current_time.kmod.map -o current_time.kmod current_time.o
/usr/src/tooldir.NetBSD-10.0-amd64/bin/nbctfmerge -t -L VERSION -o current_time.kmod current_time.o
#
# cd /usr/src/sys/modules/examples/current_time/
root@nbsd2024test current_time # ls
CVS/ current_time.c current_time.o x86@
Makefile current_time.kmod i386@ xen@
amd64@ current_time.kmod.map machine@
#
# modload ./current_time.kmod
# modunload current_time
コンソールには以下の表示となり、現在時刻がフォーマットされて出力されています。
ソースコードは/usr/src/sys/modules/examples/current_time/current_time.cにあり、 modload
でカーネルモジュールがロードされた際に print_current_time()
が呼ばれています。
66 static int
67 current_time_modcmd(modcmd_t cmd, void *arg __unused)
68 {
69 switch (cmd) {
70 case MODULE_CMD_INIT:
71 printf("current_time example module loaded.\n");
72 print_current_time();
73 break;
74 case MODULE_CMD_FINI:
75 printf("current_time example module unloaded.\n");
76 break;
77 default:
78 return ENOTTY;
79 }
80
81 return 0;
82 }
print_current_time()
の実装を見てみます。 getmicrotime()
でUNIXエポック秒を取得し、 clock_secs_to_ymdhms()
で年・月・日といった値に変換するようです。
45 static void
46 print_current_time(void)
47 {
48 struct timeval tv;
49 struct clock_ymdhms dt;
50 const char *w_day[] = {
51 "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
52 "Friday", "Saturday"
53 };
54
55 getmicrotime(&tv);
56 clock_secs_to_ymdhms(tv.tv_sec, &dt);
57
58 printf("Current Time: %s, %04" PRIu64 "/%02" PRIu8 "/%02" PRIu8
59 " %02" PRIu8 ":%02" PRIu8 ":%02" PRIu8 " UTC\n",
60 w_day[dt.dt_wday], dt.dt_year, dt.dt_mon, dt.dt_day, dt.dt_hour,
61 dt.dt_min, dt.dt_sec);
62 }
関数のコメントを見てみます。"the kernel doesn't have the notion of local timezones."(カーネルはローカルタイムゾーンの概念を持っていない)とあり、改めて先ほどの実行結果を見るとたしかに GMT/UTC
な時刻になっています。
36 /*
37 * Function print_time() fetches the epoch seconds/unix time from the
38 * getmicrotime() function and sends its to clock_secs_to_ymdhms(..) in
39 * dev/clock_subr to parse it into readable date and time format and print it.
40 *
41 * Please note that the current time is printed in GMT/UTC because the kernel
42 * doesn't have the notion of local timezones.
43 */
訳:
print_time()はgetmicrotime()から取得したUNIXエポック秒を取得し、/usr/src/sys/dev/clock_subr.cに
あるclock_secs_to_ymdhms()でパースし、フォーマットされたものを表示します。
カーネルにはローカルタイムゾーンの概念が無いため、表示される時間はGMT/UTCであることに注意してください。
ユーザランド側のタイムゾーンが JST
であっても、カーネル内では GMT/UTC
として処理されているようです。
まとめ
現在時刻を取得するカーネルモジュールサンプルを見てみました。個人的にカーネル内ではローカルタイムゾーンを持たないのは知らなかったので知見が増えました。カーネル内部では GMT/UTC
であっても、ユーザランド側でローカルタイムゾーンに変更すればよいので特に問題はない(逆にカーネル側でタイムゾーンを意識すると複雑になる)という話なのかもしれません。そう考えると、 ja_JP.UTF-8
といったロケールなどの概念もカーネル側には存在しないのかもしれません(調べてないので真偽不明…)。