最近做无线网络在系统多次休眠唤醒后是否正常的测试,但每次休眠后都需要手动点击键盘来唤醒系统,显而易见的这种方法需要人来值守,很不放便。

此时便想是否有做自动唤醒的程序,毕竟这种需求也挺正常的,应该有人已经做过了。因此就开始查找自动唤醒的方法,果然就发现了 rtcwake 这个程序,这个程序是让系统进入休眠模式并在指定的时间后唤醒。立刻便觉得这个程序很神奇,然后就去看它的源码来找出它的实现方式,这边发现了本文的主题 RTC 子系统。

RTC 子系统

RTC 子系统在目录 /sys/class/rtc/ 下,会根据设备创建对应的目录,需要在内核中开启支持,配置如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
CONFIG_HPET_EMULATE_RTC=y
CONFIG_PM_TRACE_RTC=y
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HCTOSYS=y
CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
# CONFIG_RTC_DEBUG is not set
# RTC interfaces
CONFIG_RTC_INTF_SYSFS=y
CONFIG_RTC_INTF_PROC=y
... ()

debian/ubuntu 的系统可以在 /boot/config-$(uname -r) 查看内核的编译选项,=archlinux= 可以在 /proc/config.gz 查看。

RTC 目录下的文件含义可以在 sysfs-class-rtc 中查看。

wakealarm

RTC 目录中的 wakealarm 文件内容便是下次触发唤醒时间的时间,默认这个文件是没有值的。文件的内容需要设置是时间的秒数,可以向下面这样设置:

1
# echo $(date +%s --date 'now + 1 minutes') > /sys/class/rtc/rtc0/wakealarm

这就表示在 1 minute 后触发唤醒事件。

所以做休眠唤醒测试的流程如下:

  1. 设置下次唤醒的时间到 wakealarm
  2. 休眠系统
  3. wakealarm 唤醒后,开始做一些期望的事情(如检查系统是否正常),然后继续执行步骤 =1=,就这样一直循环,直至满足条件后终止

1 分钟待机一次,唤醒后检查系统是否正常:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/bash

function os_check {
    return 0
}

function do_suspend {
    echo $(date +%s --date 'now + 1 minutes') | sudo tee /sys/class/rtc/rtc0/wakealarm
    systemctl suspend
}

while true; do
    do_suspend
    # wait for joining suspend
    sleep 5

    ret=os_check
    if [[ $ret == -1 ]] ; then
        echo "OS check failure, exit..."
        exit -1
    fi
done

/proc/driver/rtc

这个文件记录了 rtc 的详细信息,如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
rtc_time        : 03:48:01
rtc_date        : 2019-08-06
alrm_time       : 03:03:11
alrm_date       : 2019-08-06
alarm_IRQ       : no
alrm_pending    : no
update IRQ enabled      : no
periodic IRQ enabled    : no
periodic IRQ frequency  : 1024
max user IRQ frequency  : 64
24hr            : yes
periodic_IRQ    : no
update_IRQ      : no
HPET_emulated   : no
BCD             : yes
DST_enable      : no
periodic_freq   : 1024
batt_status     : okay

FAQ

  • 设置无效?首先检查内涵是否开启了 rtc 支持,如果支持就检查时间标准是否是 UTC=,=localtime 时间标准时设置 wakealarm 是不生效的,内容一直是空的。通过 timedatectl 命令可以查询和设置时间标准。

参考文档