Improved ways to suspend and hibernate a laptop under Linux

上一篇 / 下一篇  2008-04-10 21:21:56 / 个人分类:Linux

Last June I wrote aboutsuspending and hibernating laptops under Linux. Since then a few things have changed -- thankfully, for the better -- so it's time to revisit the subject. Also, a few readers have responded offering suggestions for improving the suspend shell scrīpt I wrote back then, and I've incorporated these suggestions in a new version; unfortunately most of the comments are anonymous, so I can't give proper credit to their authors.

The most important change since the last article is that laptops with multi-core CPUs are now the de facto standard. Intel Core Duo and Core2 Duo processors not only offer Symmetric Multiprocessing (SMP) functionality to mobile users but also consume less power, and thus produce less heat, than their predecessors.

These new multi-core CPUs are supported by the Linux kernel, but you need a fairly recent version to fully utilize them in SMP mode. Suspend-to-RAM with SMP enabled works in kernel versions 2.6.18 onwards, but it's not 100% stable with occasional crashes on resume. Another problem I faced on a Core Duo system is the occasional miscalculation of the remaining battery life; the battery level might be at 70% one minute and then at 40% the next, and then back to 70%. However, things are greatly improved in kernel version 2.6.20 -- marked as release candidate now -- and if you own a multi-core laptop you should upgrade your kernel.

In the last article I mentioned the three available solutions for hibernating your system: swsusp (part of the kernel),uswsusp(an implementation of swsusp running in user space mode), andsuspend2. I used the latter since it was the most stable and reliable method at the time. Suspend2 is a great piece of software, but it's not part of the Linux kernel, so it requires manual patching and kernel compilation.

The good news is that uswsusp is now stable, well integrated with kernel versions 2.6.17 onwards, and supported by most major Linux distributions. Debian (Etch and Sid) and Ubuntu (Edgy Eft and Feisty Fawn) users can install the uswusp package, enter their swap space partition when asked by the package manager, and then runs2diskto hibernate their laptop, as long as they run the stock kernel provided by their distribution.

Suspend scrīpt revisited and automation

Some readers suggested that the scrīpt I wrote for the previous article should store the system time to the hardware clock during suspend and then restore it from the hardware on resume to avoid clock skew problems. Actually, I useOpenNTPDon my systems to synchronize the clock over the network, so I've never faced such problems. Nevertheless it's a nice suggestion. Another reader with better knowledge of sed than me offered a way to discover the PCI ID of the video card using a single sed command instead of the combination of grep, awk, and sed I used; writing elegant shell scrīpts is a form of art, so this goes in the new version of the suspend scrīpt too.

I've also added the option to suspend or hibernate based on a given argument; you can now runsuspend.sh suspendfor suspend-to-RAM andsuspend.sh hibernatefor hibernation.

Here is the new and improved suspend scrīpt. Paste it as /usr/local/sbin/suspend.sh and make it executable withchmod +x /usr/local/sbin/suspend.sh.

#!/bin/sh

# discover video card's ID
ID=`lspci | sed -e '/VGA/!d' -e 's/ .*//' -e 's@0000:@@' -e 's@:@/@' -eq`

# securely create a temporary file
TMP_FILE=`mktemp /var/tmp/video_state.XXXXXX`
trap 'rm -f $TMP_FILE' 0 1 15

# switch to virtual terminal 1 to avoid graphics
# corruption in X
chvt 1

# synchronize system clock with hardware
hwclock --directisa --localtime --systohc

# write all unwritten data (just in case)
sync

# dump current data from the video card to the
# temporary file
cat /proc/bus/pci/$ID > $TMP_FILE

# suspend or hibernate
case "$1" in
  suspend)   echo -n mem > /sys/power/state ;;
  hibernate) s2disk  ;;
esac

# restore video card data from the temporary file
# on resume
cat $TMP_FILE > /proc/bus/pci/$ID

# synchronize hardware clock with system
hwclock --directisa --localtime --hctosys

# switch back to virtual terminal 7 (running X)
chvt 7

# remove temporary file
rm -f $TMP_FILE

I've tested this scrīpt on Debian Sid and Ubuntu Edgy Eft. Uswsusp offers the s2ram for suspending to RAM, but it didn't work correctly during my tests, so I stuck to the trusted ACPI method.

If your laptop has a GeForce video card and you use the proprietary Nvidia drivers, you don't need to store the video card data in a temporary file and restore it on resume, so remove those lines from the scrīpt. You need to follow some extra steps however. First of all, make sure to install the latest version of the 9xxx series of the Nvidia drivers (8xxx drivers don't suspend correctly) and load the nvidia kernel module with theNVreg_Mobile=1option. Also, in the device section in /etc/X11/xorg.conf, add this line:Option "NvAGP" "1".

At this point I need to apologize to owners of ATI Radeon-based laptops; since I don't own one myself I can't help you any further.

Now, let's automate suspending or hibernating when closing the lid based on whether the AC adapter is present or not using acpid; i.e. suspend when the AC adapter is connected and hibernate when not. First create the /etc/acpi/events/lid file based on the instruction on the previous article, then paste the following as /etc/acpi/actions/lid.sh and make that file executable.

#!/bin/sh
if grep -q off-line /proc/acpi/ac_adapter/AC/state; then
  /usr/local/sbin/suspend.sh hibernate
else
  /usr/local/sbin/suspend.sh suspend
fi

Note that on your laptop the AC adapter might be called something different in the /proc file system, so adjust the scrīpt accordingly.

To automate things even further we'll have acpid hibernate the laptop automatically when the battery percentage level reaches 4%. Create the following files for handling battery events and actions:

/etc/acpi/events/battery

event=battery.*
action=/etc/acpi/actions/battery.sh

/etc/acpi/actions/battery.sh

#!/bin/sh
if grep -q on-line /proc/acpi/ac_adapter/AC/state; then
  exit 0
fi

BAT_DIR=/proc/acpi/battery/BAT0
FULL_BAT=`grep 'last full capacity' ${BAT_DIR}/info | awk '{ print $4 }'`
CUR_BAT=`grep 'remaining capacity' ${BAT_DIR}/state | awk '{ print $3 }'`
AVG=`expr $(expr ${CUR_BAT} \* 100) / ${FULL_BAT}`

if [ "$AVG" -le "4" ]; then
  /usr/local/sbin/suspend.sh hibernate
fi

Again, adjust the value of BAT_DIR to match your setup and make the second file executable withchmod +x /etc/acpi/actions/battery.sh. Start the acpid daemon and you're done.

Conclusion

Some readers might argue that this article is useless, since the last version of their favorite distribution does all these things automatically on their laptop. Sure, things have improved, but still they're not perfect; for example, Ubuntu Edgy Eft still doesn't resume my IBM ThinkPad R50e and Sony VAIO VGN-FE21M out of the box. However, distribution and kernel developers are not the ones to blame; the ACPI specification is largely misused by manufacturers. This article along, with sites such asTuxMobilandLinux on Laptops, could be useful for successfully running Linux on your laptop.


TAG: Linux

 

评分:0

我来说两句

日历

« 2024-03-19  
     12
3456789
10111213141516
17181920212223
24252627282930
31      

数据统计

  • 访问量: 141951
  • 日志数: 180
  • 图片数: 2
  • 文件数: 2
  • 书签数: 15
  • 建立时间: 2008-03-15
  • 更新时间: 2012-04-17

RSS订阅

Open Toolbar