2013年7月31日 星期三

Linux 電源供應的系統資訊

在筆記型電腦或是使用藍牙裝置時,系統上面都會有電源供應的資訊。

只要在 /sys/devices 底下找尋 power_supply 的目錄就可以找到。

如下所示:

u@u:/sys/devices$ find -name power_supply | while read path; do ls -l $(dirname $path); done
total 0
lrwxrwxrwx 1 root root    0 Jul 31 17:42 driver -> ../../../../../../../../../../bus/hid/drivers/apple
drwxr-xr-x 3 root root    0 Jul 31 17:38 hidraw
-r--r--r-- 1 root root 4096 Jul 31 17:42 modalias
drwxr-xr-x 2 root root    0 Jul 31 17:39 power
drwxr-xr-x 3 root root    0 Jul 31 17:39 power_supply
-r--r--r-- 1 root root 4096 Jul 31 17:42 report_descriptor
lrwxrwxrwx 1 root root    0 Jul 31 17:38 subsystem -> ../../../../../../../../../../bus/hid
-rw-r--r-- 1 root root 4096 Jul 31 17:38 uevent
total 0
lrwxrwxrwx 1 root root    0 Jul 31 17:42 driver -> ../../../../../../../../../../bus/hid/drivers/magicmouse
drwxr-xr-x 3 root root    0 Jul 31 17:39 hidraw
-r--r--r-- 1 root root 4096 Jul 31 17:42 modalias
drwxr-xr-x 2 root root    0 Jul 31 17:39 power
drwxr-xr-x 3 root root    0 Jul 31 17:39 power_supply
-r--r--r-- 1 root root 4096 Jul 31 17:42 report_descriptor
lrwxrwxrwx 1 root root    0 Jul 31 17:39 subsystem -> ../../../../../../../../../../bus/hid
-rw-r--r-- 1 root root 4096 Jul 31 17:39 uevent
total 0
lrwxrwxrwx 1 root root    0 Jul 31 17:42 driver -> ../../../../../../bus/acpi/drivers/battery
-r--r--r-- 1 root root 4096 Jul 31 17:42 hid
-r--r--r-- 1 root root 4096 Jul 31 17:42 modalias
-r--r--r-- 1 root root 4096 Jul 31 17:42 path
drwxr-xr-x 2 root root    0 Jul 31 17:39 power
drwxr-xr-x 3 root root    0 Jul 31 17:36 power_supply
lrwxrwxrwx 1 root root    0 Jul 31 17:36 subsystem -> ../../../../../../bus/acpi
-rw-r--r-- 1 root root 4096 Jul 31 17:36 uevent
total 0
lrwxrwxrwx 1 root root    0 Jul 31 17:42 driver -> ../../../../../../bus/acpi/drivers/ac
-r--r--r-- 1 root root 4096 Jul 31 17:42 hid
-r--r--r-- 1 root root 4096 Jul 31 17:42 modalias
-r--r--r-- 1 root root 4096 Jul 31 17:42 path
drwxr-xr-x 2 root root    0 Jul 31 17:39 power
drwxr-xr-x 3 root root    0 Jul 31 17:36 power_supply
lrwxrwxrwx 1 root root    0 Jul 31 17:36 subsystem -> ../../../../../../bus/acpi
-rw-r--r-- 1 root root 4096 Jul 31 17:36 uevent

所以可以從 driver 這個 symbolic link 看出每個電源供應是屬於哪些裝置。

另外也可以使用指令來監測 udev 裡面關於 power_supply 的訊息。

如下所示:

u@u:~$ udevadm monitor --subsystem-match=power_supply                                                                                                                                                      
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent

KERNEL[65.358427] change   /devices/pci0000:00/0000:00:1a.0/usb3/3-1/3-1:1.0/bluetooth/hci0/hci0:13/0005:05AC:030D.0002/power_supply/hid-AB:CD:EF:12:34:56-battery (power_supply)
UDEV  [65.398449] change   /devices/pci0000:00/0000:00:1a.0/usb3/3-1/3-1:1.0/bluetooth/hci0/hci0:13/0005:05AC:030D.0002/power_supply/hid-AB:CD:EF:12:34:56-battery (power_supply)
KERNEL[81.032204] change   /devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0c/PNP0C0A:00/power_supply/BAT1 (power_supply)
UDEV  [81.033615] change   /devices/LNXSYSTM:00/device:00/PNP0A08:00/device:0c/PNP0C0A:00/power_supply/BAT1 (power_supply)

最後就是 Freedesktop 有一個 UPower 專案,專門用來提供底層電源資訊的介面給桌面應用程式來使用。

如果是在 GNOME 桌面環境底下就是 gnome-settings-daemon 與 gnome-power-manager 透過 DBus 來使用 UPower 以提供圖形介面給桌面使用者使用。

2013年7月22日 星期一

GRUB2 的除錯訊息

GRUB2 的除錯很麻煩,因為有些問題只會在特定硬體上發生,所以無法使用其它軟體模擬的方式進行,不過還好 GRUB2 本身就內建一個除錯訊息的環境變數就叫做 debug

在 Debian/Ubuntu 底下可以直接修改 /boot/grub/grub.cfg 在最前面加上 set debug=all 就可以在執行 GRUB2 時將所有的除錯訊息都列印在電腦螢幕上面,不過更好的方式是在 /etc/grub.d/ 底下建立一個 shell script 來 echo 出 set debug=all

只是這種作法只能使用在 GRUB2 去硬碟上面讀取 /boot/grub/grub.cfg 之後的除錯訊息,另外就是除錯訊息本身太多太雜,反而會有一種見林不見樹的感覺。

所以這個時候可以使用一些小技巧將 debug 訊息的分類 (category) 都找出來,然後去掉不想要的部份再使用在 debug 參數設定上面。

例如我們可以在 GRUB2 的原始碼裡面執行以下指令:

~/grub2-1.99$ grep grub_dprintf * -Irh | sed 's/[[:space:]]\+//g' | grep '^grub_dprintf("' | cut -d '"' -f 2 | sort -u | grep -v scripting | grep -v lexer | xargs echo | sed 's/ /,/g'
acpi,affs,ata,atkeyb,badram,bsd,btrfs,datetime,devalias,deviceiter,disk,drivemap,efi,efidisk,efiemu,elf,expand,fat,fb,fs,gettext,gpt,hostdisk,keystatus,linux,loader,memdisk,mmap,modules,multiboot_loader,ohci,partition,play,raid,reiserfs,reiserfs_blocktype,reiserfs_tree,relocator,scsi,uhci,usb,usb_keyboard,usbms,video,xnu,zfs

( 截取的方法也有很多可以參考此噗的討論 )

上面的指令將 scripting 跟 lexer 這兩個最囉唆的分類給去掉了,所以 GRUB2 的設定變成 set debug=acpi,affs,ata,atkeyb,badram,bsd,btrfs,datetime,devalias,deviceiter,disk,drivemap,efi,efidisk,efiemu,elf,expand,fat,fb,fs,gettext,gpt,hostdisk,keystatus,linux,loader,memdisk,mmap,modules,multiboot_loader,ohci,partition,play,raid,reiserfs,reiserfs_blocktype,reiserfs_tree,relocator,scsi,uhci,usb,usb_keyboard,usbms,video,xnu,zfs 就可以少掉很多訊息了。

另外就是去修改 GRUB2 原始碼加上自己的除錯訊息,像是:

grub_dprintf ("debug", "Your debug messages here\n");

然後重編 GRUB2 再安裝到系統上,再使用 set debug=debug 或是加到原本那一串長長的清單後面。

最後,linux 這個分類算是從 GRUB2 進入 Linux kernel 最重要的點,所以可以使用 set debug=linux 就可以看出系統是停在 GRUB2 裡面還是死在 Linux kernel 裡面。

還有最後的最後就是要將 /etc/default/grub 裡面的 GRUB_TERMINAL=console 打開,再執行 update-grub 才會有比較容易閱讀的除錯訊息,當然也許會有一些 Side Effect 的產生。

2019/12/19 補充:或是修改 grub-common 的 /etc/grub.d/40_custom 在最後加上 set debug=linux 再執行 sudo update-grub 就不用每次安裝更新 kernel 時,還要去編輯 /boot/grub/grub.cfg