读runtime_pm.txt有感
来源:互联网 发布:如何制作淘宝网店图片 编辑:程序博客网 时间:2024/06/13 18:00
/****************推荐播客******************/
//http://www.wowotech.net/sort/pm_subsystem
http://blog.csdn.net/bingqingsuimeng/article/category/1228414
echo standby > /sys/power/state命令系统进入休眠。也可以使用
# cat /sys/power/state来得到内核支持哪几种休眠方式。
用户对于/sys/power/state 的读写会调用到 main.c中的state_store()
echo "mem" > /sys/power/state 然后state_store()会调用enter_state(),它首先会检查一些状态参数,然后同步文件系统。
state_store // kernel/power/main.c
error = pm_suspend(state); // kernel/power/main.c
enter_state // kernel/power/suspend.c
if (!valid_state(state));
suspend_prepare
suspend_freeze_processes //冻结所有的进程
freeze_processes
freeze_kernel_threads
if (error) thaw_processes(); //一些进程会拒绝进入冻结状态,当有这样的进程存在的时候,会导致冻结失败,
此函数就会放弃冻结进程,并且解冻刚才冻结的所有进程。
suspend_devices_and_enter //把所有的外设休眠
suspend_ops->begin //通知平台代码,以便让其作相应的处理
suspend_console //主要是hold住一个lock ----/kernel/printk.c
dpm_suspend_start
//dpm_list链表通过device_pm_list()->list_add_tail向链表内添加内容
dpm_prepare //调用所有设备的prepare函数--通过链表dpm_list同suspend类似
device_prepare(dev, state) if (dev->pm_domain) callback = dev->pm_domain->ops.prepare;
else if (dev->type && dev->type->pm) callback = dev->type->pm->prepare
else if (dev->bus && dev->bus->pm) callback = dev->bus->pm->prepare
else if (dev->class && dev->class->pm) callback = dev->class->pm->prepare
dpm_suspend
device_suspend
__device_suspend
if (dev->pm_domain) callback = pm_op(&dev->pm_domain->ops, state) else if (dev->type ) callback = pm_op(dev->type->pm, state);
else if (dev->class) callback = pm_op(dev->class->pm, state)
else if (dev->bus) callback = pm_op(dev->bus->pm, state)
suspend_enter //以上都是准备工作,这句使系统进入指定的电源状态
suspend_ops->prepare() //通知平台代码,以便让其在即将进行状态切换之时,再做一些处理(需要的话)
dpm_suspend_end(PMSG_SUSPEND)
dpm_suspend_late(state); 调用所有设备的->suspend_late
//这里的noirq,是通过禁止所有的中断线的形式,而不是通过关全局中断的方式
dpm_suspend_noirq(state); 调用所有设备的->suspend_noirq
suspend_ops->prepare_late() 通知平台代码,以便让其在最后关头,再做一些处理
disable_nonboot_cpus(); 禁止所有的非boot cpu
arch_suspend_disable_irqs(); 关全局中断
error = syscore_suspend(); //suspend system core
if(!error ) { pm_wakeup_pending(); 检查一下这段时间内,是否有唤醒事件发生,如果有就要终止suspend
suspend_ops->enter(state); } //进行状态切换。这时,系统应该已经suspend了*******************
suspend_finish();
suspend_thaw_processes(); //恢复所有的用户空间进程和内核线程。
pm_notifier_call_chain(PM_POST_SUSPEND); //发送suspend结束的通知
pm_restore_console(); //将console切换回原来的
当所有的设备休眠以后,suspend_ops->prepare()会被调用,这个函数通常会作一些准备工作来让板机进入休眠。
suspend_ops 是板级的电源管理操作,通常注册在文件 arch/xxx/mach-xxx/pm.c 中。接下来,suspend_enter()会被调用,这个函数会关闭arch irq,调用 device_power_down(),它会调用suspend_late()函数,这个函数是系统真正进入休眠最后调用的函数,通常会在这个函数中作最后的检查。如果检查没问题,接下来休眠所有的系统设备和总线,并且调用 suspend_pos->enter() 来使CPU进入省电状态。
struct device /linux/include/linux/device.c
{
……
struct dev_pm_domain *pm_domain;
{
struct dev_pm_ops ops;
{
int (*prepare)(struct device *dev);
void (*complete)(struct device *dev);
int (*suspend)(struct device *dev);
int (*resume)(struct device *dev);
int (*freeze)(struct device *dev);
int (*thaw)(struct device *dev);
int (*poweroff)(struct device *dev);
int (*restore)(struct device *dev);
int (*suspend_late)(struct device *dev);
int (*resume_early)(struct device *dev);
int (*freeze_late)(struct device *dev);
int (*thaw_early)(struct device *dev);
int (*poweroff_late)(struct device *dev);
int (*restore_early)(struct device *dev);
int (*suspend_noirq)(struct device *dev);
int (*resume_noirq)(struct device *dev);
int (*freeze_noirq)(struct device *dev);
int (*thaw_noirq)(struct device *dev);
int (*poweroff_noirq)(struct device *dev);
int (*restore_noirq)(struct device *dev);
int (*runtime_suspend)(struct device *dev);
int (*runtime_resume)(struct device *dev);
int (*runtime_idle)(struct device *dev);
}
}
……
}
struct platform_suspend_ops {
int (*valid)(suspend_state_t state);
int (*begin)(suspend_state_t state);
int (*prepare)(void);
int (*prepare_late)(void);
int (*enter)(suspend_state_t state);
void (*wake)(void);
void (*finish)(void);
bool (*suspend_again)(void);
void (*end)(void);
void (*recover)(void);
};
电源状态切换时,这些回调的调用时机,从侧面帮助理解。如下(只介绍和suspend功能有关的,struct dev_pm_ops简称D,struct platform_suspend_ops简称P):
内核态任务有可能在停止的时候握有一些信号量,所以如果这时候在外设里面去解锁这个信号量有可能会发生死锁,所以在外设的suspend()函数里面作lock/unlock锁要非常小心,这里建议设计的时候就不要在suspend()里面等待锁。
The PM core always checks which callback to use in the order given above, so the priority order of callbacks from high to low is: PM domain, device type, class and bus type.
按以下顺序调用callback:PM domain, device type, class and bus type.
在蜗蜗使用的Linux 3.10.29版本的内核中,电源管理有关的Source code分别位于:
- kernel/power/ *
- drivers/power/
- drivers/base/power/*
- drivers/cpuidle/*
- drivers/cpufreq/*
- drivers/devfreq/*
- include/linux/power_supply.h
- include/linux/cpuidle.h
- include/linux/cpufreq.h
- include/linux/cpu_pm.h
- include/linux/device.h
- include/linux/pm.h
- include/linux/pm domain.h
- include/linux/pm runtime.h
- include/linux/pm wakeup.h
- include/linux/suspend.h
- Documentation/power/*.txt
- 读runtime_pm.txt有感
- 读 有感
- 读有感
- 读有感
- 读txt
- 读君主论有感
- 读领导力有感
- 读Chris Crawford 有感.
- 读“狼图腾”有感
- 读《打败麦肯锡》有感
- 读《深入浅出MFC》有感
- 关于读有感.
- 读《埃利森传》有感
- 读程序员人生有感
- 读富兰克林有感
- 读《白鹿原》有感
- 读blog有感
- 读博有感!转贴
- Linux系统的安装
- xcode6中, 游戏界面设置为竖屏
- 拉依达准则剔除数据异常
- 基于Chrome、Java、WebSocket、WebRTC实现浏览器视频通话
- c#学习之路: CheckForIllegalCrossThreadCalls = false 是干嘛的?
- 读runtime_pm.txt有感
- VS2010快速修改MFC的图标
- java 中JSON数据特殊字符的处理
- achartengine之折线图
- 利用CLI向Oracle NoSQL存数据----包含数组
- 4.多线程学习--操作线程的中断机制
- windows下搭建爬虫框架scrapy
- 织梦DedeCMS文章按日期时间归档分类插件
- query去两边空格,兼容ie