Ubuntu 9.04でノートPCを閉じたときにサスペンドするしくみ
とある飲み会の席で、「(CTWMの)DebianでThinkPadを閉じたときにサスペンドしてくれればいいのに」「あれ、この(GNOMEの)Ubuntu 9.04だと簡単にできるよ」という会話になったので、後からしくみを調べてみました。
結論としては、gnome-power-managerを中心に、halとかdbusとかのGNOMEを構成する機構を使いまくっているようです。
「Debian/etch で Gnome Power Managerをつかってサスペンドする」を参考にしながら、スクリプトやソースを眺めてみたので、あとから見返すためのメモを残しておきます。といっても、GNOMEではgnome-power-managerからDebiceKit-Powerに移行するとかいう話になっているようですが…
追記2009-06-15: 補足しておくと、これはUbuntu固有の話ではなくて、「Ubuntu 9.04時点でのGNOME」の話です。
GNOMEでの設定
- 「システム」 - 「設定」 - 「電源の管理」 - 「AC電源使用時」「バッテリー使用時」 - 「ノートPCを閉じたとき」で、「サスペンド状態にする」を選択
- gconfでいうと、以下の2つの値を"suspend"に
- /apps/gnome-power-manager/buttons/lid_ac
- /apps/gnome-power-manager/buttons/lid_battery
ノートPCを閉じたときのイベント
- acpidのLidボタンの設定を見たけど、これでサスペンドしてるわけではなさそう
$ cat /etc/acpi/events/lidbtn # /etc/acpi/events/lidbtn # Called when the user closes or opens the lid event=button[ /]lid action=/etc/acpi/lid.sh
- Lidボタンは/dev/input/event1からイベントを取れるらしい
$ grep Lid /var/log/kern.log
Jun 14 07:41:45 ubuntu01 kernel: [ 1.600622] input: Lid Switch as /devices/LNXSYSTM:00/device:00/PNP0C0D:00/input/input1
Jun 14 07:41:45 ubuntu01 kernel: [ 1.600977] ACPI: Lid Switch [LID]
$ sudo evtest /dev/input/event1
Input driver version is 1.0.0
Input device ID: bus 0x19 vendor 0x0 product 0x5 version 0x0
Input device name: "Lid Switch"
Supported events:
Event type 0 (Sync)
Event type 5 (?)
Event code 0 (?)
Testing ... (interrupt to exit)
^C
- それをhald-addon-inputが監視して、HAL経由でイベントを送っているみたい
$ ps ax | grep '[h]ald-addon-input' 3114 ? S 0:01 hald-addon-input: Listening on /dev/input/event2 /dev/input/event0 /dev/input/event4 /dev/input/event6 /dev/input/event1 /dev/input/event7
ボタンのイベントを受ける処理(src/gpm-manager.c)
- ここからgnome-power-managerの中身
- 上記のgconfのエントリは、src/gpm-conf.hでGPM_CONF_BUTTON_LID_ACとGPM_CONF_BUTTON_LID_BATTとして#defineされている
- それを参照しているのが、src/gpm-manager.cのlid_button_pressed()
- lid_button_pressed()はボタンイベントのコールバック関数button_pressed_cb()から呼ばれている
- button_pressed_cb()は、gpm_manager_init()の中でセットされる
- lid_button_pressed()はボタンイベントのコールバック関数button_pressed_cb()から呼ばれている
g_signal_connect (manager->priv->button, "button-pressed", G_CALLBACK (button_pressed_cb), manager);
- これで、ボタンのイベントからbutton_pressed_db()→lid_button_pressed()が呼ばれる?
- lid_button_pressed()は、manager_policy_do()でGPM_CONF_BUTTON_LID_ACやGPM_CONF_BUTTON_LID_BATTの値を取ってくる
- 取ってきた値がACTION_SUSPENDであれば、gpm_manager_action_suspend()を呼ぶ
- ACTION_SUSPENDは、gpm-prefs.hで#defineされている。実体は"suspend"という文字列
} else if (strcmp (action, ACTION_SUSPEND) == 0) {
gpm_manager_action_suspend (manager, reason);
権限をチェック(src/gpm-manager.c)
- gpm_manager_action_suspend()の中身
- GPM_CONF_CAN_SUSPENDで権限をチェックする
- GPM_CONF_CAN_SUSPENDは、gpm-conf.hで#deineされている。実体はGPM_CONF_DIR "/general/can_suspend"
- hal_gpower_can_suspend()で権限をチェックする
- libhal/libhal-gpower.cのhal_gdevice_get_bool()で、HALの"power_management.can_suspend"をチェックしている
$ hal-device | grep -F power_management.can_suspend
power_management.can_suspend = true (bool)
power_management.can_suspend_hybrid = false (bool)
$ cat /etc/dbus-1/system.d/hal.conf
(略)
<allow send_destination="org.freedesktop.Hal"
send_interface="org.freedesktop.Hal.Device.SystemPowerManagement"/>
(略)
- gpm_manager_is_inhibit_valid()でチェック
- 一連のチェックを通ったら、gpm_control_suspend()を呼び出す
HALへ(src/gpm-control.c)
- gpm_control_suspend()の中身
- gpm_control_allowed_suspend()で権限をチェック
- gpm_control_allowed_suspend()では、gpm_control_is_user_privileged()で"org.freedesktop.hal.power-management.suspend"をチェックしている
$ polkit-auth | grep -F org.freedesktop.hal.power-management.suspend org.freedesktop.hal.power-management.suspend
- gnome_keyring_lock_all_sync()を呼ぶ
- gpm_screensaver_lock()を呼ぶ
- gpm_networkmanager_sleep()を呼ぶ
- 最後にhal_gpower_suspend()を呼ぶ
HALにサスペンドのメッセージ(libhal/libhal-gpower.c)
- hal_gpower_suspend()の中身
- dbus_g_proxy_call()でHALに"Suspend"を送る
$ cat /usr/share/hal/fdi/policy/10osvendor/10-power-mgmt-policy.fdi
(略)
<append key="org.freedesktop.Hal.Device.SystemPowerManagement.method_names" type="strlist">Suspend</append>
<append key="org.freedesktop.Hal.Device.SystemPowerManagement.method_signatures" type="strlist">i</append>
<append key="org.freedesktop.Hal.Device.SystemPowerManagement.method_argnames" type="strlist">num_seconds_to_sleep</append>
<append key="org.freedesktop.Hal.Device.SystemPowerManagement.method_execpaths" type="strlist">hal-system-power-suspend</append>
(略)
- これにより、hal-system-power-suspendが実行されるっぽい
hal-system-power-suspend(/usr/lib/hal/scripts/linux/hal-system-power-suspend*)
- halパッケージに含まれるシェルスクリプト
- /usr/lib/hal/scripts/linux/hal-system-power-suspendから/usr/lib/hal/scripts/linux/hal-system-power-suspend-linuxをexecする
- /usr/lib/hal/scripts/linux/hal-system-power-suspend-linuxは/usr/sbin/pm-suspendを実行
pm-suspend(/usr/sbin/pm-suspend)
- pm-utilsパッケージに含まれる
- /usr/lib/pm-utils/bin/pm-actionへのシンボリックリンク
- pm-acitonは$0を見て動作が変わるシェルスクリプト
- pm-suspendとして呼ばれると、do_suspendを実行
- do_suspendは、sourceしている/usr/lib/pm-utils/pm-functionsで定義されている
do_suspend() { echo -n "mem" >/sys/power/state; }
コメント
コメントの投稿
トラックバック
http://emasaka.blog65.fc2.com/tb.php/625-2560592f

美紀といいます。
この度ブログを始めたので挨拶で
コメントさせて頂きました。
私のブログは競艇やギャンブルが主になっちゃうと
思いますが日常の事もいろいろ書いていくので
よかったらコメントください☆
http://ameblo.jp/boat-gals/