訳あって、Linux の shutdown コマンドの動作を追うことになりました。目的が達成できればいいので、自分の知りたいところだけですが。という訳で、以下備忘録です。対象のディストリビューションは Debian/GNU Linux です。
まず、/sbin/shutdown のソースコードがないと話にならないので探します。いろいろ調べてみると、Debian では shutdown コマンドもパッケージで管理されているようで、dpkg コマンドを使います。(こういうところは、NetBSD とかが好きだな。)
$ dpkg --search /sbin/shutdown
すると、shutdown は sysvinit というパッケージに納められていることが分かります。次のこのソースコードですが、もしウェブ上で閲覧できればいいのであれば、
で検索すれば見つかります。もしソースをダウンロードしたいのであれば、apt-get source コマンドでソースコードをダウンロードできます。
/sbin/shutdownコマンドですが、そこから /sbin/halt を呼んでいるようです。halt コマンドのソースも sysvinit パッケージに含まれています。最後に、halt は reboot() システムコールをします。ここからは、カーネルを覗きます。私の見ているバージョンは、3.18.38 です。
reboot() システムコールのソースコードですが、linux/kernel/sys.c の中で SYSCALL_DEFINE4(reboot, …) という形で定義されています。中を見ると、電源断を要求された場合には kernel_power_off() という関数を呼び出しています。kernel_power_off() は、machine_power_off() を呼び出します。
machine_power_off() は CPU アーキテクチャ依存です。ARM アーキテクチャの場合は、linux/arch/arm/kernel/process.c の中で定義されています。machine_halt() のほうは割込を禁止してから無限ループに入るだけですが、machine_power_off() では pm_power_off() という関数を呼び出します。これはプラットフォーム依存になりますが、Raspberry Pi では(← 先に言え?)、linux/arch/arm/mach-bcm2708/bcm2708.c の bcm2708_power_off() という関数が呼ばれ、低レベルな処理が実行されることが分かります。
実際には Raspberry Pi ではパワー断の機能はないらしく、ROM ブートローダーに分かるように記録をしているだけのようです。ここからは BCM2708 SoC のマニュアルがないと分からないので、おしまいにします。ま、ここまで分かれば私の用途には十分です。