linux syscore suspend/resume方法

转载自 http://markzhang.cn
原文链接: http://www.markzhang.cn/blog/2014/04/09/linux-driver-suspend-orders/

syscore是Linux kernel定义的一个framework,我们可以将我们的驱动注册到syscore中去。syscore比较关键的就是syscore_ops这个结构:

struct syscore_ops {
  struct list_head node;
  int (*suspend)(void);
  void (*resume)(void);
  void (*shutdown)(void);
};

可以看到只有 suspend/resume/shutdown 这三个ops,所以看到这里大概也可以猜到了,注册到syscore中的驱动,其suspend函数是在所有其他驱动的suspend都调用过之后调用的,而其resume函数是在所有其他驱动的resume调用之前调用的。简单来说,syscore的驱动,suspend被晚调用保证其他驱动suspend的时候,syscore的驱动还活着;syscore的驱动,resume被很早调用,从而保证其他驱动resume的时候,syscore的驱动已经活着了。好绕。。。

要将驱动注册到syscore中很简单,调用函数:register_syscore_ops(&your_driver_syscore_ops); 就可以了。至于上面说到的syscore的suspend/resume的顺序,实现代码在这里:

error = syscore_suspend();
if (!error) {
  *wakeup = pm_wakeup_pending();
  if (!(suspend_test(TEST_CORE) || *wakeup)) {
      error = suspend_ops->enter(state);
      events_check_enabled = false;
  }
  syscore_resume();
}

以上代码来自函数:suspend_enter。可以看到当syscore_suspend被调用之后,就调用architecture dependent的 suspend_ops->enter 了,到这里整个系统就已经停下来了,进入suspend状态了。而当resume开始,suspend_ops->enter 返回之后,第一个被调用的就是 syscore_resume,所以上面那一段听起来好绕的逻辑就这么区区几行代码解释了。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一段内核代码,定期执行打印时间的任务,但是在系统休眠或panic时停止打印: ``` #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/time.h> #include <linux/timer.h> #include <linux/suspend.h> static struct timer_list my_timer; static void print_time(unsigned long data) { printk(KERN_INFO "Current time: %ld\n", (long)jiffies); mod_timer(&my_timer, jiffies + msecs_to_jiffies(1000)); // 1 second interval } static int __init my_init(void) { printk(KERN_INFO "Starting time printing task...\n"); setup_timer(&my_timer, print_time, 0); mod_timer(&my_timer, jiffies + msecs_to_jiffies(1000)); // start after 1 second return 0; } static void __exit my_exit(void) { del_timer_sync(&my_timer); printk(KERN_INFO "Stopping time printing task...\n"); } static int my_suspend(void) { del_timer_sync(&my_timer); return 0; } static int my_resume(void) { mod_timer(&my_timer, jiffies + msecs_to_jiffies(1000)); // resume after 1 second return 0; } static struct syscore_ops my_syscore_ops = { .suspend = my_suspend, .resume = my_resume, }; module_init(my_init); module_exit(my_exit); MODULE_LICENSE("GPL"); static int __init my_init(void) { printk(KERN_INFO "Starting time printing task...\n"); setup_timer(&my_timer, print_time, 0); mod_timer(&my_timer, jiffies + msecs_to_jiffies(1000)); // start after 1 second register_syscore_ops(&my_syscore_ops); return 0; } static void __exit my_exit(void) { unregister_syscore_ops(&my_syscore_ops); del_timer_sync(&my_timer); printk(KERN_INFO "Stopping time printing task...\n"); } static int my_suspend(void) { del_timer_sync(&my_timer); return 0; } static int my_resume(void) { mod_timer(&my_timer, jiffies + msecs_to_jiffies(1000)); // resume after 1 second return 0; } static struct syscore_ops my_syscore_ops = { .suspend = my_suspend, .resume = my_resume, }; module_init(my_init); module_exit(my_exit); MODULE_LICENSE("GPL"); ``` 这段代码在内核初始化时会注册一个定时器,每隔1秒打印一次当前时间。如果系统进入睡眠状态,定时器会被删除,直到系统恢复为止。如果系统panic,则定时器也会停止。为了处理系统休眠和恢复,这段代码还注册了一个syscore操作,用于在系统进入和退出休眠状态时启动和停止定时器。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值