rtc wakeup
Linux RTC驱动模型分析之rtc-sysfs.c - 嵌入式Linux中文站
rtcwake: /dev/rtc0 not enabled for wakeup events - Raspberry Pi Forums
(8条消息)Linux时间系统之RTC时间 - u013686019的专栏 - CSDN博客
使用rtcwake定时唤醒linux
目录
最近下载一批资料,但是由于网络不太好,下载的速度太慢,只有凌晨的时候下载速度会快一点,因此就想写一个定时任务在凌晨三点自动开始下载。
但是另一方面我也不希望电脑一直开着,这样太浪费电了...
经过一番搜索,最终让我发现了这一工具: rtcwake
测试本机是否支持定时唤醒
我们都知道,让linux定时关机或者定时休眠是一件很简单的事情,只需要通过 at
或 cron
设置好定时执行关机或休眠程序即可,基本上任何电脑都能够做到这一点。
但是如果想反过来,想在指定的时间让电脑自动启动就需要硬件和驱动的支持了。
我们可以通过下面命令来测试一下计算机是不是支持定时唤醒:
sudo rtcwake -m standby -s 10
rtcwake -m freeze -s 10
正常情况下该命令会休眠到内存,然后10秒后又被唤醒。
rtcwake使用方法
rtcwake其实包括两个动作,第一个动作是休眠或关机,第二个动作是定时唤醒。
设置关机/休眠模式
我们使用 -m mode
来设置rtcwake的关机/休眠模式,理论上 mode
的可选值包括:
- standby
- 待机状态,节省的电源比较少,但是唤醒速度很快
- freeze
- 所有进程被冻结,所有设备暂停运行,但系统依然在运行。该模式需要linux3.9以上的支持
- mem
- 休眠到内存,除了内存以外的大部分机器部件都进入断电状态。 这种休眠状态恢复速度特别快,但由于内存中的数据并没有被保存下来,因此这个状态的系统并没有进入真正意义上的休眠状态,还在持续耗电。
- disk
- 休眠到磁盘, 这种休眠状态恢复速度特别快,但由于内存中的数据并没有被保存下来,因此这个状态的系统并没有进入真正意义上的休眠状态,还在持续耗电。这种情况下系统可以完全断电,但由于要保存/读取系统状态到/从交换空间,因此速度会比较慢.
- off
- 这就不是休眠了,而是直接关机
- no
- 不进行休眠或关机,只设置唤醒时间
- disable
- 取消上一次设置的定时唤醒
- show
- 显示设置的定时唤醒信息
但事实上,本机可能不会支持所有的mode,我们可以通过 --list-modes
选项来查看本机支持的关机/休眠模式
rtcwake --list-modes
freeze mem disk off no on disable show `设置定时唤醒时间
有三种格式来设置定时唤醒时间:
使用
--date 特定时间
来明确指定哪个特定时间唤醒,这个特定时间
的格式可以是:
- YYYYMMDDhhmmss
- YYYY年MM月DD日hh时mm分ss秒
- YYYY-MM-DD hh:mm:ss
- YYYY年MM月DD日hh时mm分ss秒
- YYYY-MM-DD hh:mm
- YYYY年MM月DD日hh时mm分00秒
- YYYY-MM-DD
- YYYY年MM月DD日00时00分00秒
- hh:mm:ss
- 今天的hh时mm分ss秒
- hh:mm
- 今天的hh时mm分00秒
- tomorrow
- 明天的00时00分00秒
- +5min
- 5分钟后
使用
-s N
指定N
秒后唤醒使用
-t N
, 其中N
为1970-01-01 00:00 UTC
开始计数的秒钟数关于硬件时钟的说明
rtcwake命令默认根据
/etc/adjtime(man adjtime_config)
中的第三行信息(UTC或LOCAL)来判断硬件时钟是按照UTC还是本地时间来设置的.
但是你可以通过-u/--utc
来强制要求rtcwake命令将硬件时钟看成是UTC时间,或者通过-l/--local
选项来将硬件时钟看成是本地时间。
甚至可以通过-A/--adjfile file
来指定另一个adjtime
文件供rtcwake
命令判断。
rtcwake
1.功能作用
rtcwake 是利用电脑主板上带的rtc来作为定时基准,在给定的时间唤醒处于待机或休眠状态的电脑。2.位置
/usr/sbin/rtcwake3.格式用法
rtcwake [options]4.主要参数
-d, –device
select rtc device (rtc0|rtc1|…)
-n, –dry-run does everything, but suspend
-l, –local RTC uses local timezone
-m, –mode使用的模式
standby 普通待机模式,为默认选项,对应 ACPI state S1
mem 待机到内存,即除内存之外把其他设备都进入低功耗模式,对应 ACPI state S3
disk 待机到硬盘,即休眠,把电脑的当前状态保存到硬盘,几乎不消耗外部电源,对应 ACPI state S4
off 通过条用系统的关机命令来休眠,对应 ACPI state S5
-s, –secondsseconds to sleep
-t, –time在具体某个时间唤醒
-u, –utc RTC uses UTC
-v, –verbose 显示详细的运行状态信息
-V, –version 显示版本信息5.应用实例
a、电脑进入休眠模式,并在2个小时(7200秒)后自动唤醒
sudo rtcwake -m disk -s 7200b、电脑进入休眠,并在09:00这个时刻唤醒
sudo rtcwake -m disk -l -tdate -d 09:00 +%s
c、会让系统进入S3,睡20秒再自动唤醒
sudo rtcwake -v -s 20 -m mem
Linux内核电源管理模块提供了4种不同的休眠模式 mem , standby , freeze , 和disk
可以使用下面的命令使内核进入低功耗模式
echo mem > /sys/power/state
echo standby > /sys/power/state
echo freeze > /sys/power/stateecho disk > /sys/power/state
echo +100 > /sys/class/rtc/rtc0/wakealarm
可以使用RTC唤醒.
RTC 子系统
RTC 子系统在目录 /sys/class/rtc/ 下,会根据设备创建对应的目录,需要在内核中开启支持,配置如下:
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 文件内容便是下次触发唤醒时间的时间,默认这个文件是没有值的。文件的内容需要设置是时间的秒数,可以向下面这样设置:echo $(date +%s --date 'now + 1 minutes') > /sys/class/rtc/rtc0/wakealarm
这就表示在 1 minute 后触发唤醒事件。
所以做休眠唤醒测试的流程如下:设置下次唤醒的时间到 wakealarm 中
休眠系统
被 wakealarm 唤醒后,开始做一些期望的事情(如检查系统是否正常),然后继续执行步骤 1,就这样一直循环,直至满足条件后终止FAQ
设置无效?
首先检查内核是否开启了 rtc 支持,如果支持就检查时间标准是否是 UTC,localtime 时间标准时设置 wakealarm 是不生效的,内容一直是空的。通过 timedatectl 命令可以查询和设置时间标准。作者:jouyouyun
链接:https://www.jianshu.com/p/8b3ff24ca3d4
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。// From <linux/rtc.h> struct rtc_time type rtcTime struct { tmSec uint32 tmMin uint32 tmHour uint32 tmMday uint32 tmMon uint32 tmYear uint32 tmWday uint32 tmYday uint32 tmIsdst uint32 } const ( // iocREAD and friends are from <linux/asm-generic/ioctl.h> iocREAD = uintptr(2) iocNRBITS = uintptr(8) iocNRSHIFT = uintptr(0) iocTYPEBITS = uintptr(8) iocTYPESHIFT = iocNRSHIFT + iocNRBITS iocSIZEBITS = uintptr(14) iocSIZESHIFT = iocTYPESHIFT + iocTYPEBITS iocDIRSHIFT = iocSIZESHIFT + iocSIZEBITS // rtcRDTIMENR and friends are from <linux/rtc.h> rtcRDTIMENR = uintptr(0x09) rtcRDTIMETYPE = uintptr(112) ) func rtcReadTime() rtcTime { f, err := os.Open("/dev/rtc0") if err != nil { log.Fatalf("Failed to open /dev/rtc0: %v", err) } defer f.Close() result := rtcTime{} arg := uintptr(0) arg |= (iocREAD << iocDIRSHIFT) arg |= (rtcRDTIMETYPE << iocTYPESHIFT) arg |= (rtcRDTIMENR << iocNRSHIFT) arg |= (unsafe.Sizeof(result) << iocSIZESHIFT) _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, f.Fd(), arg, uintptr(unsafe.Pointer(&result))) if errno != 0 { log.Fatalf("RTC_RD_TIME failed: %v", errno) } return result }