L15. 休眠唤醒

作者: 开源519 | 来源:发表于2020-08-16 11:27 被阅读0次

1.休眠方式

在内核中,休眠方式有很多种,可以通过下面命令查看

# cat /sys/power/state  //来得到内核支持哪几种休眠方式. 

常用的休眠方式有freeze,standby, mem, disk

  • freeze:     冻结I/O设备,将它们置于低功耗状态,使处理器进入空闲状态。唤醒最快,耗电比其它standby, mem,disk方式高。
  • standby:   除了冻结I/O设备外,还会暂停系统,唤醒较快,耗电比其它 mem, disk方式高
  • mem:       将运行状态数据存到内存,并关闭外设,进入等待模式,唤醒较慢,耗电比disk方式高
  • disk:         将运行状态数据存到硬盘,然后关机,唤醒最慢

示例:

 # echo standby > /sys/power/state  // 命令系统进入standby休眠.           

2.唤醒方式

当我们休眠时,如果想唤醒,则需要添加中断唤醒源,使得在休眠时,这些中断是设为开启的,当有中断来,则会退出唤醒,常见的中断源有按键,USB等。

3.底层实现

代码参考: kernel/drivers/input/keyboard/gpio_keys.c

static int __maybe_unused gpio_keys_suspend(struct device *dev)
{
……
    enable_irq_wake(irq);
……
    return 0;
}

static int __maybe_unused gpio_keys_resume(struct device *dev)
{
……
    disable_irq_wake(irq);
……
    return 0;
}

static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume);

static struct platform_driver gpio_keys_device_driver = {
    .probe      = gpio_keys_probe,
    .shutdown   = gpio_keys_shutdown,
    .driver     = {
        .name   = "gpio-keys",
        .pm = &gpio_keys_pm_ops,
        .of_match_table = gpio_keys_of_match,
        .dev_groups = gpio_keys_groups,
    }
};

注: 上面代码中,gpio_keys_suspend,gpio_keys_resume中没有直接出现enable_irq_wake和disable_irq_wake,但是最终是会调用这俩API。

通过实例发现:休眠唤醒的设计,只需要在gpio_keys_device_driver 中实例driver成员的pm成员。SIMPLE_DEV_PM_OPS是Linux封装的一层结构体:

#ifdef CONFIG_PM_SLEEP
#define SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \
    .suspend = suspend_fn, \
    .resume = resume_fn, \
    .freeze = suspend_fn, \
    .thaw = resume_fn, \
    .poweroff = suspend_fn, \
    .restore = resume_fn,
#else
#define SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn)
#endif

#define SIMPLE_DEV_PM_OPS(name, suspend_fn, resume_fn) \
const struct dev_pm_ops name = { \
    SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \
}

将源代码宏展开:

//static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume);
const struct dev_pm_ops name = { 
    .suspend = gpio_keys_suspend,
    .resume  = gpio_keys_resume,
}

3.总结

  1. 在实际应用中,需要按键实现休眠唤醒,只需要在platform_driver->driver->pm下实例suspend和resume成员函数即可。然后在suspend和resume中增加按键中断唤醒使能和按键唤醒失能。
  2. 流程:在linux要执行休眠时,换遍历一遍所有注册到内核驱动的suspend函数,执行suspend内部代码;在被唤醒时会遍历resume函数,执行内部代码。
  3. 至于为什么都要执行中断唤醒失能?网上的一种说法是如果在执行enable_irq_wake(irq)之前,中断已经处于可唤醒使能,会出现报错。所以在每次唤醒前先disable_irq_wake(irq),休眠时enable_irq_wake(irq)。
  4. 对于休眠唤醒,Linux内核实现起来很复杂,但是对于驱动开发来讲,使用起来较为方便,这也是操作系统的意义所在:严格的分层思想,复杂的流程由内核实现,并提供API供开发人员使用。学习内核的具体实现对编程功力有很大帮助,后续继续分章节介绍其内核休眠唤醒机制具体的内核实现流程。

参考文章:1.Linux电源管理-休眠与唤醒

如有技术交流需要,请关注“开源519”公众号。


开源519.jpg

相关文章

  • L15. 休眠唤醒

    1.休眠方式 在内核中,休眠方式有很多种,可以通过下面命令查看 常用的休眠方式有freeze,standby, m...

  • 唤醒休眠的神性

    西蒙经典语录〔原创〕 1.当情况变得令人窒息,正是生命向你指引最快捷的路径,给你臣服的机会,允许变化推动你的意识继...

  • 唤醒休眠的灵魂

    如果愛不能唤醒你, 那么生命就用痛苦来唤醒你; 如果痛苦不能唤醒你, 那么生命就用更大的痛苦来唤醒你; 如果更大的...

  • WIN10开启休眠功能

    休眠的好处,唤醒时回复休眠前的状态,且省电休眠该模式,系统会自动将内存中的数据全部转存到硬盘上一个休眠文件中,然后...

  • Android Alarm

    AlarmManager.RTC,硬件闹钟,不唤醒手机(也可能是其它设备)休眠;当手机休眠时不发射闹钟。 Alar...

  • Linux 自动唤醒

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

  • 诺亚方舟4

    (四) 休眠仓把我唤醒了,初醒的我顾不得调整状态,就爬出休眠仓向飞船的舷窗跑去,由于长时间的休眠后初醒,脑子还有些...

  • Ubuntu休眠后无法唤醒

    转自:https://blog.csdn.net/zaf0516/article/details/10310591...

  • Assign USB Controller无法唤醒系统

    当系统休眠后,无法通过键盘,鼠标唤醒系统。什么玩意!各种问题!

  • 在 Parallels Desktop 中,全屏模式使用 Win

    在Parallels Desktop中,全屏模式下使用Win7,如果Mac电脑自动休眠了,则无法再次唤醒了,唤醒时...

网友评论

    本文标题:L15. 休眠唤醒

    本文链接:https://www.haomeiwen.com/subject/izjtjktx.html