2011년 1월 16일 일요일

linux 노트북에서 suspend와 hibernation 사용하기

[출처] How to suspend and hibernate a laptop under Linux
By Manolis Tzanidakis on June 06, 2006 (8:00:00 AM)

* Advanced Configuration & Power Interface(ACPI)
ACPI4Linux(리눅스를 위한 ACPI)는 리눅스 버전 2.6.15 이후의 버전에서 지원한다.

* Suspend
ACPI의 S3 상태(Suspend-to-RAM)은 RAM을 제외한 모든 시스템이 low-power상태로 들어간다.
Suspend-to-RAM 상태를 지원하는지 안하는 체크하기

#cat /sys/power/state

위의 명령어가 'mem'을 리턴하면 지원하는 것이고 안하면
kernel configuration파일 (/usr/src/linux-`uname -r`/.config 어거나 /boot/config-`uname -r`일 것이다.)
에서 CONFIG_ACPI_SLEEP항목을 선택하자.
ACPI가 지원하더라도 버그가 있어서 ACPI를 지원하지 못할 수 도 있다.
만약 그러한 경우라면 Advanced Power Management(APM)을 사용하면 된다.
보통 apmd(the Linux APM Daemon)의 데몬형태로 실행되고 있을 것이다.
apmd를 설치하고 apm -z 명령어로 suspend 모드로 전환할 수 있다.
하지만 hibernate는 지원하지 않는다.
명령행에서 다음과 같이 실행하면

echo -n mem > /sys/power/state

laptop이 suspend로 전환된다. 하지만 복구할 시 아마도 검은 화면만 나올 지도 모른다.
이러한 문제점을 고려해서 shell script를 만들어서 사용하는 것이 더 낳다.

/usr/local/sbin/suspend.sh을 만들고 다음과 같은 내용을 추가하자.

===========================================================================
#!/bin/sh
# discover video card's ID
ID=`lspci | grep VGA | awk '{ print $1 }' | sed -e 's@0000:@@' -e 's@:@/@'`

# 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

# 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
echo -n mem > /sys/power/state

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

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

# remove temporary file
rm -f $TMP_FILE
=============================================================================

X서버 configuration 파일(/etc/X11/xorg.conf 이거나 /etc/X11/XF86Config-4)의
video 장치 섹션에 Option "VBERestore" "true"를 추가한다.

=============================================================================
Section "Device"
Identifier "intel_855gm"
Driver "i810"
BusID "PCI:0:2:0"
Option "VBRestore" "true"
EndSection
=============================================================================

그리고 마지막으로 suspend.sh 스크립트를 실행가능한 상태로 만들어 준다.
#chmod -x /usr/local/sbin/suspend.sh

복구하기는 Laptop 모델에 따라서 Fn키나 power 버튼을 누르면된다.
그리고 네트워크를 down시키거나 up 시키는 작업을
echo -n mem > /sys/power/state이 들어 있는 라인 전후에 넣어서 실행할 수 있다.

* Hibernate 설정하기
Hibernate 기능은 ACPI State S4 혹은 Suspend-to-disk로 알려져 있다.
Suspend-to-RAM가 마찬가지로 동작하지만 모든 데이터가 하드 디스크에 저장된다.
이 상태는 어떤 전력도 소비되지 않기 때문에 강력한 절전기능을 제공한다.
리눅스에서는 Hibernate기능을 세 가지 방법이 있다.

1. swsusp; 커널을 한부부으로 동작한다.
2. uswsusp; 사용자 영역에서 동작하지만 아직 준비되지 않은 기능이다.
3. Software Suspend(suspend2); 상태를 주기적으로 점검하기 위해서 가끔식 실행된다.

리눅스 커널에는 Software Suspend가 포함되지 않고 있다는 문제점이 있다.
그레서 manual patching과 커널 컴파일이 필요하다.
Gentoo 사용자들은 suspend2-sources 패키지를 사용하면된다.
다른 패키지 사용자들은 가장 최근 커널을 다운받고 patch for suspend2를 적용하면된다.

===============================================================================
#cd /usr/src
#wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.15.tar.bz2 \
http://www.suspend2.net/downloads/all/suspend2-2.2-rc16-for-2.6.15.tar.bz2
#tar jxvpf linux-2.6.15.tar.bz2; tar jxvpf suspend2-2.2-rc16-for-2.6.15.tar.bz2
#cd linux-2.6.15
#../suspend2-2.2-rc16-for-2.6.15/apply
===============================================================================

그리고 커널 옵션중에
Power management options (ACPI, APM) ---> Suspend2 ---> Swap Writer
에 당신의 swap 파티션을 추가하고
Cryptographic options ---> LZF compression algorithm
을 추가하자.
Swap Writer를 선택하면 suspend2는 모든 데이터를 swap 영역에 쓸것이다.
그레서 RAM의 용량의 최소한 두 배이상의 swap 영역이 확보되도록 하자.
물론 "File Writer"를 선택해서 하드디스크의 파일에 저장하는 방법을 사용하는 것도 있다.
하지만 swap영역을 사용하는 방법이 좀 더 쉽기 때문에 swap에 저장하는 방법을 사용하는 방법을 추천한다.

그리고 다음으로 hibernate-script(Debian에서 hibernate 패키지)를 설치하자.
(이 패키지는 모든 리눅스 배포판에서 지원하지는 않기 때문에
suspend2의 Web 패이지에서 최신버전을 다운로드하고 install.sh를 실행하자.)
설정파일은 /etc/hibernate/hibernate.conf이다. 자세한 옵션은 hibernate.conf man 패이지를 참조하고,
hibernate를 실행하자. 그리고 복구는 power버튼으로 할 수 있다.

* 자동 Hibernate
suspend나 hibernate를 스크립트로 실행하는 것은 가장 편한 방법은 아니다.
그레서 자동으로 실행하도록 하는것이 더 좋다.
laptop의 뚜껑을 덮을때 suspend로 진입하고 power 버튼을 눌러서 hibernate를 실행하도록 설정할 수 있다.
그렇게 하기 위해선 ACPI daemon인 acpid의 설치가 필요하다.
설치한후 자동실행을 설정하기위해서 daemon을 중지시키고 설정 디렉토리를 백업하자.

# mv /etc/acpi /etc/acpi.orig

그리고 두 개의 하위 디렉토리(events, actions)를 갖는 새로운 acpi 디렉토리를 만들자.

# mkdir -p /etc/acpi/{events,actions}

그럼 뚜껑과 전원 버튼 그리고 events를 다루는 파일들을 만들자.

/etc/acpi/events/lid
========================================================
event=button[ /]lid.*
action=/etc/acpi/actions/lid.sh
========================================================

/etc/acpi/events/pwrbtn
========================================================
event=button[ /]power
action=/etc/acpi/actions/pwrbtn.sh
========================================================

/etc/acpi/actions/lid.sh
========================================================
#!/bin/sh
/usr/local/sbin/suspend.sh
========================================================

/etc/acpi/actions/pwrbtn.sh
========================================================
#!/bin/sh
hibernate
========================================================

첫 번째 두 파일들은 전원 버튼을 누르거나 뚜껑이 닫힐때 실행하게될 deamon을 지시한다.
마찬가지로, 마지막 두 파일들은 실행가능 상태로 만들고, acpid deamon을 실행하자

# chmod +x /etc/acpi/actions/*

[번역] Improved ways to suspend and hibernate a laptop under Linux
By Manolis Tzanidakis on February 16, 2007 (8:00:00 AM)

.. multi-core CPU에 대한 사용하는 방법을 설명한다.

Suspend-to-RAM은 SMP모드에서 2.6.18이후의 버전에서 잘 작동한다.
하지만 경우에 따라서 복구가 100% 안정적이지 않다.
다른 문제점은 배터리 용량 표시 문제인데 2.6.20버전에서 개선되어 졌다.
지난 내용에서 언급한 hibernate 하는 세 가지 해결책을 제기했다;

swsusp (커널의 한 부분)
uswsusp (사용자 영역에서 작동하는 swsusp)
그리고 suspend2

이 중 가장 안정적이고 동시에 신뢰성있는 접근 방법을 제시하는
맨 마지막 방법에 대한 설명을 하였다.
Suspend2는 대부분 소프트웨어의 조각으로 이루어져 있다.
하지만, 리눅스 커널의 한 부분이 아니기 때문에 manual patch와 커널 컴파일이 필요하다.

이제는 uswsusp가 안정적이라는 좋은 소식이 있다. (2.6.17 이후에 탑재된)
가장 대중적인 리눅스 배포판인 Debian(Etch, Sid)그리고 Ubuntu(Edge Eft, Feisty Fawn)
사용자들은 uswsusp 패키지를 사용할 수 있다.
(패키지 매니저로 설치할때 swap 영역 파티션을 사용하도록 입력하자.)
그리고 hibernate를 수행하도록 s2disk를 실행하자.

* 재 방문한 Suspend 스크립트와 자동화
어떤 독자가 내가 지난 내용에서 작성한 스크립트가 suspend시 시스템 시간을 하드웨어에 저장해야 하고,
clock skew 문제를 피하기 위해서 resume시 하드웨어로 부터 시간을 복구해야한다고 제안하였다.
실제로, 나는 네트워크 상에서 시간을 동기화 하기위해서 OpenNTPD를 사용하기 때문에 이러한 문제들을 마주치지 못했다.
이러한 사항들을 기반으로 suspend와 hibernate하기위한 옵션을 추가한다.
suspend-to-RAM을 위해서 suspend.sh의 suspend를
hibernation을 위해선 suspend.sh의 hibernate를 수행한다.

/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
==============================================================================

위와 같이 편집하고 실행 가능한 상태로 변경하자.

# chmod +x /usr/local/sbin/suspend.sh

Debian Sid와 Ubuntu Edgy Eft에서 테스트 하였다.
Uswsusp는 suspend-to-RAM을 위해서 s2ram을 제공하지만,
테스트하는 동안에 잘 동작하지 않았기 때문에 ACPI를 통한 방법을 이용하였다.
만약 GeForce 비디오 카드를 사용하고 proprietary Nvidia 드라이버를 사용한다면,
temporary 파일에 비디오 카드 데이터를 저장하고 resume시 복구할 필요 없다.
그래서 이에 해당하는 라인은 제거했다.

/etc/acpi/actions/lid.sh
==============================================================================
#!/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
==============================================================================

# chmod +x /etc/acpi/actions/lid.sh

/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
==============================================================================

BAT_DIR에 해당하는 값은 여러분의 설정과 맞는지 확인하고 수정하자.

# chmod +x /etc/acpi/actions/battery.sh

댓글 없음:

댓글 쓰기