12.18. 高级电源管理 - APM

12.18.1. Linux 兼容性检查

首先阅读 Battery-Powered-mini-HOWTO

为了使 APM 工作,机器的固件必须实现 APM 规范。Linux 支持标准版本 1.0 到 1.2。为了与 Linux 配合使用,APM BIOS 必须支持 32 位保护模式连接。

要显示有关系统上 APM BIOS 的信息,您可以运行 dmesg | grep apm 命令或查看/proc/apm文件。

12.18.2. 简介

APM 支持包括两个部分:内核支持和用户空间支持。

12.18.2.1. 内核支持

您需要一个内核,其中已编译了 APM 驱动程序,并使用了适当的内核配置选项。目前,大多数发行版都没有发布启用 APM 驱动程序的内核,因此您可能需要使用启动选项启用该驱动程序,或者编译自定义内核。请参阅 Kernel-HOWTO 或您的发行版手册以了解详细信息。

APM 驱动程序可以模块化,但不建议这样做,因为如果 APM 驱动程序在初始化时不存在,许多驱动程序将禁用其 APM 功能。

可用的 APM 选项有(请参阅Documentation/Configure.help内核源代码树中的文件以了解更多详细信息)

  • CONFIG_APM_IGNORE_USER_SUSPEND 只是针对某些 NEC Versa M 系列笔记本电脑的解决方法。

  • CONFIG_APM_DO_ENABLE 在启动时启用 APM 功能。

  • CONFIG_APM_CPU_IDLE 如果内核没有任务要执行,则使 CPU 进入省电模式。

  • CONFIG_APM_DISPLAY_BLANK 某些笔记本电脑可以使用此选项在 Linux 虚拟控制台的屏幕保护程序使屏幕空白时关闭 LCD 背光。请注意,这仅供虚拟控制台屏幕保护程序使用,并且在使用 X Window 系统时不会关闭背光。

  • CONFIG_APM_POWER_OFF 在使用 halt 时完全关闭机器。此功能在大多数笔记本电脑上都能正常工作。

  • CONFIG_APM_IGNORE_MULTIPLE_SUSPEND 只是针对 IBM™ ThinkPad 560 的解决方法。

  • CONFIG_APM_IGNORE_SUSPEND_BOUNCE 只是针对 Dell Inspiron 3200 和其他笔记本电脑的解决方法。

  • CONFIG_APM_RTC_IS_GMT 以格林威治标准时间格式存储时间。实际上建议在 BIOS 中的实时时钟 (RTC) 中存储 GMT。

  • CONFIG_APM_ALLOW_INTS 解决某些笔记本电脑(例如许多较新的 IBM™ ThinkPad)的挂起到磁盘的一些问题。

  • CONFIG_SMP 对称多处理支持。这支持具有多个 CPU 的系统。如果您有一个只有单个 CPU 的系统,例如大多数个人计算机,则为 N。尽管默认值似乎为 Y。因此,如果您没有意识到,则可能会启用它。我收到报告称,启用 SMP 支持会干扰 APM。因此,对于像笔记本电脑这样的单 CPU 机器,当您选择 N 时,您处于安全的一侧。

根据内核文档文件,APM 驱动程序的功能Documentation/Configure.help:“系统时间将在 USER RESUME 操作后重置,/proc/apm设备将提供电池状态信息,并且用户空间程序将收到 APM 事件(例如,电池状态更改)的通知。”

12.18.2.2. 用户空间支持

最重要的用户空间实用程序是 apmd,一个处理 APM 事件的守护进程。

如果您运行 2.2.x 或更高版本的内核并想进行实验,Gabor Kuti <seasons_AT_falcon.sch.bme.hu> 制作了一个内核补丁,允许您将任何 Linux 系统休眠到磁盘,即使您的计算机 APM BIOS 不直接支持它。依我拙见,如果您的笔记本电脑提供了一个功能键来直接调用挂起模式,您就不需要此功能。

请参阅 Battery Powered Linux Mini-HOWTO 以获取详细信息。

以下是 apmd 可以执行的操作

  • apmd(8): 不时地将电池状态记录到 syslog,并运行一个代理脚本,该脚本可以在挂起之前或恢复之后采取操作

  • apm(1): 打印当前电池状态或挂起计算机

  • apmsleep(1): 将机器挂起有限的时间

  • xapm(1x): 为 X11 提供电池电量计

  • libapm.a: 用于编写 APM 应用程序的库

某些 APM 固件无法正确恢复混音器设置,这可能会导致机器恢复后音乐中出现尖叫声。一种解决方案是设置代理脚本,使其在恢复后调用混音器应用程序。

来自 apmsleep(1) 手册页:某些计算机,尤其是笔记本电脑,可以使用实时时钟 (RTC) 芯片从低功耗挂起到 DRAM 模式唤醒。Apmsleep 可用于设置 RTC 中的闹钟时间并进入挂起或待机模式。来自 RTC 的中断会导致计算机唤醒。该程序通过等待内核时间的跳跃来检测此事件,并成功终止。如果在一分钟内未发生时间跳跃,或者出现问题,则退出值将为非零。Apmsleep 是 apmd 包的一部分。

2001 年,Richard Gooch 编写了一个简单的 apmd 替代方案,该方案在 pmutils 包中可用。

另外,请查看 apmcd (apm 基于 crontab) ,网址为 ftp://ftp.binary9.net/pub/linux/ 。此工具由 Nicolas J. Leon <nicholas_AT_binary9.net> 编写。

12.18.3. 警告

如果您在同一台计算机上使用其他操作系统,请确保其“挂起”和“休眠”功能不会写入 Linux 使用的分区。

12.18.4. 故障排除

如果您的机器在 2.0.x 内核上工作正常,但在 2.2.x 系列上却不行,请采纳 Klaus Franken kfr_AT_klaus.franken.de 的建议:“2.2 中的默认设置已更改。在 init 脚本中搜索 halt 并将其更改为 halt -ppoweroff。如果您没有此选项,请参阅 man halt,您需要更新版本的 halt。”您可以在 SysVinit 包中找到它。

在某些新机器上(例如 HP Omnibook 4150 - 366 MHz 型号),当访问/proc/apm时,您可能会遇到内核错误 general protection fault: f000Stephen Rothwell 解释说:“这是您的 APM BIOS 尝试在保护模式下使用实模式段,即这是您的 BIOS 中的错误。.. 我们最近看到了一些这样的情况,除了所有其他情况都在 BIOS 中的断电代码中,我们可以在尝试断电之前返回到实模式来解决它。在这里我们无法做到这一点。”

根据内核文档Documentation/Configure.help:“当遇到看似随机的、奇怪的问题时,您应该尝试的其他一些事情

  1. 确保您有足够的交换空间并且已启用 swapon -s

  2. no-hlt 选项传递给内核。

  3. 在内核中打开浮点仿真,并将 no387 选项传递给内核。

  4. floppy=nodma 选项传递给内核。

  5. mem=4M 选项传递给内核(从而禁用除前 4 MB RAM 之外的所有内存)。

  6. 确保 CPU 没有超频(似乎不适合移动机器)。

  7. 阅读 sig11 FAQ

  8. 从您的 BIOS 设置中禁用缓存。

  9. 为显卡安装风扇或更换显卡 RAM(似乎不适合移动机器)。

  10. 为 CPU 安装更好的风扇(似乎不适合移动机器)。

  11. 更换 RAM 芯片(似乎不适合移动机器)。

  12. 更换主板(似乎不适合移动机器)。

12.18.5. APMPCMCIA

来自 PCMCIA-HOWTO:“如果您已配置内核以支持 APM,则 Card Services 可以编译为支持 APM(高级电源管理)。... 如果在您的系统上检测到兼容版本,则 PCMCIA 模块将自动配置为 APM。无论是否配置了 APM,您都可以在挂起笔记本电脑之前使用 cardctl suspend,并在恢复后使用 cardctl resume,以干净地关闭并重新启动您的 PCMCIA 卡。这对于正在使用的调制解调器不起作用,因为串行驱动程序无法保存和恢复调制解调器操作参数。APM 在某些系统上似乎不稳定。如果您在系统上遇到 APMPCMCIA 方面的问题,请在报告错误之前尝试将问题缩小到其中一个包。某些驱动程序,特别是 PCMCIA SCSI 驱动程序,无法从挂起/恢复循环中恢复。当使用 PCMCIA SCSI 卡时,始终在挂起系统之前使用 cardctl eject。”。

12.18.6. APM 和恢复 X Windows

某些机器的 APM 固件无法跨挂起保存和恢复显示控制器芯片寄存器。早期版本的 XFree86 X 服务器在恢复后无法正确恢复屏幕,Linux Laptops 解决了这个问题。但是,当代版本的 XFree86 大多做得很好。

有时 X 和 APM 不能顺利地协同工作。机器甚至可能挂起。Steve Rader 的建议:某些 Linux 系统在执行 apm -s 时 X11 服务器会挂起。遇到此问题的人可能希望切换到控制台虚拟终端,然后挂起 chvt 1; apm -s (以 root 用户身份),或者更合适的是 sudo chvt 1; sudo apm -s。我将这些命令放在一个脚本中,例如 my-suspend,然后执行 xapmload --click-command my-suspend

12.18.7. 软件挂起

软件挂起 实现了挂起机器的可能性。它不需要 APM。您可以通过按 Sysrq-d 或使用 swsuspshutdown -z(需要 sysvinit 补丁)来挂起您的机器。它创建一个映像,该映像保存在您的活动交换空间中。下次启动时,内核会检测到保存的映像,从中恢复内存,然后继续像您挂起之前一样运行。如果您不希望继续之前的状态,请使用 noresume 内核选项。

软件挂起甚至可能比休眠更好,因为现在我可以挂起我的 Linux 系统,启动到 Microsoft Windows,执行一些非法操作并关闭,然后重新启动我的 Linux 设置,回到我离开时的状态!这是休眠无法做到的,因为休眠总是恢复您挂起时的最后状态,无论是 Microsoft Windows 还是 Linux。因此,如果我想切换到 Microsoft Windows 来玩游戏或做其他任何事情,我可以让我的 Linux 桌面保持原样,然后返回到我离开时的状态。

在最新的 2.6 内核中,SoftWareSuspend 是内核的一部分。您可以在电源管理部分找到它。但是也有 2.4 的反向移植版本可用。

自从最初的 Software Suspend 代码由 Gabor Kuti 和 Pavel Machek 于 1998 年编写以来,已经为 2.6 内核创建了三种不同的实现,所有实现都是同一原始代码库的分支。

TuxOnIce,以前称为 Software Suspend 2,具有很长的功能列表,包括通过按 Escape 键取消挂起、图像压缩以节省时间和空间、通用的插件架构以及对具有 Highmem、抢占和 SMP 的机器的支持。

12.18.8. 提示和技巧

12.18.8.1. 文本控制台上的电池状态

您可以使用以下条目在.bashrc中显示命令提示符上的电池电量。

12.18.8.1.1. 当使用 APM 时

export PS1="\$(cat /proc/apm | awk '{print \$7}') \h:\w\$ "

12.18.8.1.2. 当使用 ACPI 时

# Color the bash prompt in function of the percentage of battery
# with acpi subsystem.
# Based on the originally apm based script that has been posted
# on debian-laptop by 
# Jason Kraftcheck <kraftche at cae.wisc.edu>.
#
# This script is licensed under the GNU GPL version 2 or later,
# see /usr/share/common-licences/GPL on a Debian system or
# https://gnu.ac.cn/copyleft/gpl.html on the web.
 
# (c) 2003 Fabio 'farnis' Sirna <farnis at libero dot it>

function acpi_percent()
{
 if [ `cat /proc/acpi/battery/BAT0/state | grep present: |cut -d\  -f18` = "yes" ]; then
  {
   CAPACITY=`cat /proc/acpi/battery/BAT0/info |grep "design capacity:"|cut -d\  -f11`
   LEVEL=`cat /proc/acpi/battery/BAT0/state | grep remaining|cut -d\  -f8`
   ACPI_PERCENT=`echo $(( $LEVEL * 100 / $CAPACITY ))`
   if [ "$LEVEL" = "$CAPACITY" ]; then
    echo FULL
   else
    echo $ACPI_PERCENT%
   fi
  }
 else echo "NO BATTERY"
 fi
}

function acpi_charge()
{
 ACPI_CHARGE=`cat /proc/acpi/ac_adapter/AC/state | cut -d\  -f20`
 case $ACPI_CHARGE in
       *on-line*)
         ACPI_CHARGE="+" ;;
       *off-line*)
         ACPI_CHARGE="-" ;;
     esac
     echo $ACPI_CHARGE
}

function acpi_color()
   {
     if  [  "$(acpi_charge)"  =  "+"  ];  then
      {
       if [ `cat /proc/acpi/battery/BAT0/state | grep present: |cut -d\  -f18` = "no" ]; then
        echo  "0;31"
       else echo  "1;32"
      fi
     }
     else
       case  $(acpi_percent)  in
          10?%)  echo  "0;32"  ;;
           9?%)  echo  "0;32"  ;;
           8?%)  echo  "0;32"  ;;
           7?%)  echo  "0;32"  ;;
           6?%)  echo  "0;32"  ;;
           5?%)  echo  "0;32"  ;;
           4?%)  echo  "0;33"  ;;
           3?%)  echo  "0;33"  ;;
           2?%)  echo  "0;33"  ;;
           1?%)  echo  "0;31"  ;;
            ?%)  echo  "0;31;5"  ;;
             *)  echo  "0;35"  ;;

       esac
     fi
   }

function  acpi_color_prompt
   {
     PS1='\[\e[$(acpi_color)m\][$(acpi_charge)$(acpi_percent)][\t] \u:\w\$>\[\e[0;37m\] '
   }

   #  linux  console
   if  [  "$TERM"  =  "linux"  ];  then
     PROMPT_COMMAND=acpi_color_prompt
   fi

   function  echo_acpi
   {
     echo -n "($(acpi_charge)$(acpi_percent)) "
   }

12.18.8.2. Debian GNU/Linux

所有“正常”的 Debian GNU/Linux 内核都支持 APM,它们只需要在引导加载程序配置文件中添加 append 行(例如/etc/lilo.conf.

append="apm=on"

您可以在引导加载程序配置文件中使用以下参数(进行适当的更改)(例如/etc/lilo.conf来试验 ACPI 和 APM,当它们在同一个内核中编译时。同时使用 APM 和 ACPI 是行不通的,请参阅内核文档以了解详细信息。

append="acpi=off apm=on"