- 浏览: 34074 次
最新评论
Linux与Android休眠唤醒对比(一)
2012年01月15日
Linux休眠(suspend) 的简单介绍
在Linux 中(PC 和嵌入式系统), 休眠主要分三个主要的步骤:
1,冻结用户态进程和内核态任务.
2,调用注册的设备的suspend 的回调函数.
顺序是按照注册顺序
3,休眠核心设备和使CPU 进入休眠态冻结进程是内核把进程列表中所有的进程的状态都设置为停止, 并且保存下所有进程的上下文. 当这些进程被解冻的时候, 他们是不知道自己被冻结过的, 只是简单的继续执行. 如何让Linux 进入休眠呢? 用户可以通过读写sys 文件/sys /power/state 是实现控制系统进入休眠. 比如
# echo standby > /sys/power/state
命令系统进入休眠. 也可以使用
# cat /sys/power/state
来得到内核支持哪几种休眠方式.
Linux 休眠与唤醒(一)
相关的文件:
你可以通过访问 Linux 内核网站来得到源代码, 下面是文件的路径:
linux_soruce/kernel/power/main.c
linux_source/kernel/arch/xxx/mach-xxx/pm.c
linux_source/driver/base/power/main.c
接下来让我们详细的看一下Linux 是怎么休眠/ 唤醒的. Let's going to see how these happens.
main.c文件是整个框架的入口, 用户可以通过读写sys 文件/sys/power/state 实现控制系统进入低功耗状态. 用户对于/sys/power/state 的读写会调用到main.c 中的state_store(), 用户可以写入const char * const pm_states[] 中定义的字符串, 比如“on ”, “mem ”, “standby ”, “disk ”.
然后state_store() 会调用enter_state(), 它首先会检查一些状态参数, 然后同步文件系统. 下面是代码:
static int enter_state(suspend_state_t state)
{
int error;
if (!valid_state(state))
return-ENODEV;
if(!mutex_trylock(&pm_mutex))
return-EBUSY;
printk(KERN_INFO "PM:Syncingfilesystems ... ");
sys_sync();
printk("done.");
pr_debug("PM:Preparingsystem for %s sleep", pm_states[state]);
error = suspend_prepare();
if (error)
gotoUnlock;
if (suspend_test(TEST_FREEZER))
gotoFinish;
pr_debug("PM: Entering%ssleep", pm_states[state]);
error=suspend_devices_and_enter(state);
Finish:
pr_debug("PM:Finishingwakeup.");
suspend_finish();
Unlock:
mutex_unlock(&pm_mutex);
return error;
}
准备, 冻结进程
当进入到suspend_prepare() 中以后, 它会给suspend 分配一个虚拟终端来输出信息pm_prepare_console(), 然后广播一个系统要进入suspend 的Notify---pm_notifier_call_chain(), 关闭掉用户态的helper 进程usermodehelper_disable(), 然后一次调用suspend_freeze_processes() 冻结所有的进程, 这里会保存所有进程当前的状态, 也许有一些进程会拒绝进入冻结状态, 当有这样的进程存在的时候, 会导致冻结失败, 此函数就会放弃冻结进程, 并且解冻刚才冻结的所有进程.suspend_thaw_processes()和usermodehelper_enable()。
static int suspend_prepare(void)
{
int error;
unsigned int free_pages;
if (!suspend_ops||!suspend_ops->enter)
return-EPERM;
pm_prepare_console();
error=pm_notifier_call_chain(PM_SUSPEND_PREPARE);
if (error)
gotoFinish;
error =usermodehelper_disable();
if (error)
gotoFinish;
if(suspend_freeze_processes()) {
error= -EAGAIN;
gotoThaw;
}
free_pages=global_page_state(NR_FREE_PAGES);
if (free_pageserror= -ENOMEM;
printk(KERN_ERR"PM:No enough memory");
}
}
if (!error)
return0;
Thaw:
suspend_thaw_processes();
usermodehelper_enable();
Finish:
pm_notifier_call_chain(PM_POST_SUSPEND);
pm_restore_console();
return error;
}
让外设进入休眠
现在, 所有的进程( 也包括workqueue[queue_work()]/kthread) 都已经停止了, 内核态任务有可能在停止的时候握有一些信号量, 所以如果这时候在外设里面去解锁这个信号量有可能会发生死锁, 所以在外设的suspend() 函数里面作lock/unlock 锁要非常小心, 这里建议设计的时候就不要在suspend() 里面等待锁. 而且因为suspend 的时候, 有一些Log 是无法输出的, 所以一旦出现问题, 非常难调试.
然后kernel 在这里会尝试释放一些内存.
最后会调用suspend_devices_and_enter() 来把所有的外设休眠, 在这个函数中, 如果平台注册了suspend_pos( 通常是在板级定义中定义和注册), 这里就会调用suspend_ops->begin(), 然后driver/base/power/main.c 中的device_suspend()->dpm_suspend() 会被调用, 他们会依次调用驱动的suspend() 回调来休眠掉所有的设备.
当所有的设备休眠以后, suspend_ops->prepare() 会被调用, 这个函数通常会作一些准备工作来让板机进入休眠. 接下来Linux, 在多核的CPU 中的非启动CPU 会被关掉, 通过注释看到是避免这些其他的CPU 造成race condion, 接下来的以后只有一个CPU 在运行了.
suspend_ops 是板级的电源管理操作, 通常注册在文件arch/xxx/mach-xxx/pm.c 中.
接下来,suspend_enter() 会被调用, 这个函数会关闭arch irq, 调用device_power_down(), 它会调用suspend_late() 函数, 这个函数是系统真正进入休眠最后调用的函数, 通常会在这个函数中作最后的检查. 如果检查没问题, 接下来休眠所有的系统设备和总线, 并且调用suspend_pos->enter() 来使CPU 进入 省电状态. 这时候, 就已经休眠了. 代码的执行也就停在这里了.
int suspend_devices_and_enter(suspend_state_t state)
{
int error, ftrace_save;
if (!suspend_ops)
return-ENOSYS;
if (suspend_ops->begin){
error=suspend_ops->begin(state);
if(error)
gotoClose;
}
suspend_console();
ftrace_save=__ftrace_enabled_save();
suspend_test_start();
error=device_suspend(PMSG_SUSPEND);
if (error) {
printk(KERN_ERR"PM: Somedevices failed to suspend");
gotoRecover_platform;
}
suspend_test_finish("suspenddevices");
if(suspend_test(TEST_DEVICES))
gotoRecover_platform;
if(suspend_ops->prepare) {
error=suspend_ops->prepare();
if(error)
gotoResume_devices;
}
if(suspend_test(TEST_PLATFORM))
gotoFinish;
error =disable_nonboot_cpus();
if (!error&&!suspend_test(TEST_CPUS))
suspend_enter(state);
enable_nonboot_cpus();
Finish:
if (suspend_ops->finish)
suspend_ops->finish();
Resume_devices:
suspend_test_start();
device_resume(PMSG_RESUME);
suspend_test_finish("resumedevices");
__ftrace_enabled_restore(ftrace_save);
resume_console();
Close:
if (suspend_ops->end)
suspend_ops->end();
return error;
Recover_platform:
if (suspend_ops->recover)
suspend_ops->recover();
goto Resume_devices;
}
Resume唤醒
如果在休眠中系统被中断或者其他事件唤醒, 接下来的代码就会开始执行, 这个唤醒的顺序是和休眠的循序相反的, 所以系统设备和总线会首先唤醒, 使能系统中断, 使能休眠时候停止掉的非启动CPU, 以及调用suspend_ops->finish(), 而且在suspend_devices_and_enter() 函数中也会继续唤醒每个设备, 使能虚拟终端, 最后调用suspend_ops->end().
在返回到enter_state() 函数中的, 当suspend_devices_and_enter() 返回以后, 外设已经唤醒了, 但是进程和任务都还是冻结状态, 这里会调用suspend_finish() 来解冻这些进程和任务, 而且发出Notify 来表示系统已经从suspend 状态退出, 唤醒终端.
到这里, 所有的休眠和唤醒就已经完毕了, 系统继续运行了.
发表评论
-
C#基础语法总结
2012-01-20 10:59 587C#基础语法总结 2012年01月14日 第一部分 基 ... -
C段错误总结
2012-01-20 10:59 705C段错误总结 2012年01月07日 最近一段时间在li ... -
一个极其简单的在线C#IDE例子(zz)
2012-01-20 10:59 1928一个极其简单的在线C#IDE例子(zz) 19小时前 五 ... -
C语言
2012-01-20 10:58 753C语言 2011年10月02日 ... -
c#日期格式转换大全-望穿秋水-博客园
2012-01-20 10:58 1482c#日期格式转换大全-望 ... -
疑难问题 HTML Parsing Error解决方案
2012-01-19 15:54 5947疑难问题 HTML Parsing Error解决方案 20 ... -
[main] python 6140 C:\cygwin\bin\python.exe: *** fatal error - unable to remap
2012-01-19 15:54 1308[main] python 6140 C:\cygwin\bi ... -
Unix网络编程代码 第16章 非阻塞式I/O
2012-01-19 15:54 1046Unix网络编程代码 第16章 非阻塞式I/O 2012年0 ... -
牵着ta的手一起走
2012-01-17 05:39 587牵着ta的手一起走 2011 ... -
陈慧琳是女性的心灵鸡汤
2012-01-17 05:39 662陈慧琳是女性的心灵鸡汤 2011年11月25日 ... -
北京自考专科接考本科要分清专业类别
2012-01-17 05:39 756北京自考专科接考本科 ... -
新目标英语八年级上册unit9 sectionA 1a-grammar导学案
2012-01-17 05:39 726新目标英语八年级上册unit9 sectionA 1a-gra ... -
符合用户体验是获得好的关键词排名的关键
2012-01-17 05:39 664符合用户体验是获得好 ... -
普贤行愿品讲记第七卷
2012-01-16 04:33 568普贤行愿品讲记第七卷 ... -
黄帝内经篇
2012-01-16 04:33 546黄帝内经篇 2012年01月04日 [b][/b] -
《中国不高兴》与王小波
2012-01-16 04:33 552《中国不高兴》与王小 ... -
回朋友:修行的概念一定要正确!理通就通了百分之七(1--10)
2012-01-16 04:33 630回朋友:修行的概念一定 ... -
【转】 通灵居士果卿谈自己诵大悲咒的神奇感应
2012-01-16 04:33 13347【转】 通灵居士果卿谈 ...
相关推荐
Linux Kernel and Android 休眠与唤醒 Linux Kernel and Android 休眠与唤醒
休眠/唤醒在嵌入式Linux中是非常重要的部分,嵌入式设备尽可能的进入休眠状 态来延长电池的续航时间.这篇文章就详细介绍一下Linux中休眠/唤醒是如何工作 的, 还有Android中如何把这部分和Linux的机制联系起来的.
android_和linux的休眠唤醒机制
android和linux的休眠唤醒机制.pdf
android和linux的休眠唤醒机制借鉴.pdf
转载: 文章介绍了linux和android休眠唤醒过程 包括过程中涉及到的文件和函数
休眠/唤醒在嵌入式Linux中是非常重要的部分,嵌入式设备尽可能的进入休眠状 态来延长电池的续航时间.这篇文章就详细介绍一下Linux中休眠/唤醒是如何工作 的, 还有Android中如何把这部分和Linux的机制联系起来的.
5.2.2 Android休眠 141 5.2.3 Android唤醒 144 5.3 ashmem驱动程序 145 5.4 pmem驱动程序 148 5.5 alarm驱动程序 149 5.5.1 alarm简析 149 5.5.2 alarm驱动程序的实现 150 ...
5.2.2 Android休眠 141 5.2.3 Android唤醒 144 5.3 ashmem驱动程序 145 5.4 pmem驱动程序 148 5.5 alarm驱动程序 149 5.5.1 alarm简析 149 5.5.2 alarm驱动程序的实现 150 ...
5.2.2 Android休眠 141 5.2.3 Android唤醒 144 5.3 ashmem驱动程序 145 5.4 pmem驱动程序 148 5.5 alarm驱动程序 149 5.5.1 alarm简析 149 5.5.2 alarm驱动程序的实现 150 ...
唤醒锁 Wakelock是Flutter插件,可让您保持设备屏幕清醒,即防止屏幕进入Hibernate状态。 支持平台 平台 wakelock支持 安卓 :check_mark_button: 的iOS :check_mark_button: 网页 :check_mark_button: 苹果...