本を読む

読書やコンピュータなどに関するメモ

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()の中でセットされる
	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://ameblo.jp/boat-gals/

コメントの投稿

管理者にだけ表示を許可する

トラックバック

http://emasaka.blog65.fc2.com/tb.php/625-2560592f

 | HOME | 

Categories

Recent Entries

Recent Comments

Recent Trackbacks

Appendix

emasaka

emasaka

フリーター。
連絡先はこのへん

Monthly


FC2Ad