系统睡眠模型是让整个系统休眠,而runtime是在系统正常工作的时候单独控制某个设备休眠和唤醒

1. runtime PM流程
怎样动态地打开或关闭设备的电源?最简单的方法:
在驱动程序里,在open函数中打开电源,在close函数中关闭电源

上述方法有一个缺点: 多个APP使用该设备时可能造成干扰
解决方法:给驱动添加使用计数值: 当该计数大于0时打开电源, 等于0时关闭电源

在应用程序运行过程中通过ioctl来关闭和启动电源

ioctl: alsa

runtime PM只是提供辅助函数, 比如:(内核文档runtime_pm.txt详细介绍了)
1. 增加计数/减少计数
2. 使能runtime pm电源管理

内核驱动示例: drivers\input\misc\bma150.c
pm_runtime_enable (在probe函数中)/ pm_runtime_disable (在remove函数中): 使能/禁止runtime PM, 修改disable_depth变量
pm_runtime_get_sync(在open函数中) / pm_runtime_put_sync (在close函数中): 增加/减小计数值, 并且让设备处于resume或suspend状态

在dev_pm_ops里提供3个回调函数: runtime_suspend, runtime_resume, runtime_idle

流程分析:
pm_runtime_get_sync
  __pm_runtime_resume(dev, RPM_GET_PUT);
    atomic_inc(&dev->power.usage_count); // 增加使用计数
    rpm_resume(dev, rpmflags); // resume重新运行设备
      if (dev->power.disable_depth > 0) retval = -EACCES; // 该变量初值为1,要使用runtime PM, 要先pm_runtime_enable去修改disable_depth 变量
      if (!dev->power.timer_autosuspends) // 为防止设备频繁地开关,可以设置timer_autosuspends,会等待一会,如果这段时间没动作才关闭,防止关闭后又马上打开
        pm_runtime_deactivate_timer(dev);//设置这段等待时间,上面的判读应该是是否启用该功能
      if (dev->power.runtime_status == RPM_ACTIVE) { // 如果设备已经是RPM_ACTIVE,就没必要再次resume,直接返回
      // 如果设备处于RPM_RESUMING/RPM_SUSPENDING, 等待该操作完成
      // Increment the parent's usage counter and resume it if necessary(如果有父亲,就唤醒它,并增加它的计数)
      // resume设备本身: 前面4个函数被称为 subsystem-level callback(子系统级别的回调函数)
      callback = dev->pm_domain->ops.runtime_resume; 或
      callback = dev->type->pm->runtime_resume; 或
      callback = dev->class->pm->runtime_resume; 或
      callback = dev->bus->pm->runtime_resume; 或

      callback = dev->driver->pm->runtime_resume;(设备级别的回调函数)
      retval = rpm_callback(callback, dev);//调用runtime_resume
      // 成功时,给父亲的child_count加1
      if (parent)
        atomic_inc(&parent->power.child_count);
      // 唤醒其他进程
      wake_up_all(&dev->power.wait_queue);
      // 如果resume失败, 让设备进入idle状态
      if (!retval)
        rpm_idle(dev, RPM_ASYNC);

pm_runtime_put_sync
  __pm_runtime_idle(dev, RPM_GET_PUT);//先进入空闲状态
    atomic_dec_and_test(&dev->power.usage_count) // 减小使用计数
    rpm_idle(dev, rpmflags); // 让设备进入idle状态
      rpm_check_suspend_allowed(dev); // 检查是否允许设备进入suspend状态
        if (dev->power.disable_depth > 0) //失败
        if (atomic_read(&dev->power.usage_count) > 0) // 当前的使用计数不是0,失败,表示当前有要用在使用
        if (!pm_children_suspended(dev)) // 如果的孩子不全部处于suspended(休眠), 失败
    if (dev->power.runtime_status != RPM_ACTIVE) // 如果设备本来就不处于RPM_ACTIVE,直接返回

    // 调用idle回调函数: 前4个是subsystem-level callback
    callback = dev->pm_domain->ops.runtime_idle; 或
    callback = dev->type->pm->runtime_idle; 或
    callback = dev->class->pm->runtime_idle; 或
    callback = dev->bus->pm->runtime_idle; 或
  
    callback = dev->driver->pm->runtime_idle;

    __rpm_callback(callback, dev);//调用runtime_idle

    wake_up_all(&dev->power.wait_queue);

bma150.c : i2c_bus_type(dev->bus总线结构体) -> pm_generic_runtime_idle -> pm_runtime_suspend ->__pm_runtime_suspend(dev, 0);-> rpm_suspend(dev, rpmflags);
如果设备不提供runtime_idle, 则最终会调用runtime_suspend

如何使用runtime PM:
1. 驱动程序提供接口,比如在open和close提供pm_runtime_get_sync, APP来调用open和close
2. echo on > /sys/devices/.../power/control // 导致control_store -> pm_runtime_forbid(dev); :
                              atomic_inc(&dev->power.usage_count);
                              rpm_resume(dev, 0);//唤醒

echo auto > /sys/devices/.../power/control // 导致control_store -> pm_runtime_allow(dev); :
                            atomic_dec_and_test(&dev->power.usage_count)
                            rpm_idle(dev, RPM_AUTO);//进入idle状态休眠

control_store函数在drivers/base/power/sysfs.c中

2. 修改驱动程序和使用
怎么修改?
参考内核驱动示例: drivers\input\misc\bma150.c
2.1 在dev_pm_ops里提供3个回调函数: runtime_suspend, runtime_resume, runtime_idle
2.2 对于runtime PM,默认状态下设备的状态是suspended, 如果硬件上它是运行状态,需要调用pm_runtime_set_active()来修改它的状态然后调用pm_runtime_enable()来使能runtime PM ,其使能后也是suspended休眠状态,所有需要设置状态为active
一般是在probe函数里调用上述函数
2.3 在对应的系统调用接口里调用: pm_runtime_get_sync / pm_runtime_put_sync : 增加/减小计数值, 并且让设备处于resume或suspend状态
2.4 在remove函数里调用pm_runtime_disable()

前提: 配置内核支持runtime PM
make menuconfig
  Power management options --->
    [*] Run-time PM core functionality

使用:
1.
echo on > /sys/devices/platform/mylcd/power/control(使用计数会加一)
echo auto > /sys/devices/platform/mylcd/power/control(使用计数会减一)

2. 在对应的系统调用接口里调用: pm_runtime_get_sync / pm_runtime_put_sync,那么就不用执行上面1中的休眠唤醒了

(我们执行fb_test /dev/fb0的时候其也执行了open和close,所有屏幕一闪而过)
3. autosuspend: 如果不想让设备频繁地开、关,可以使用autosuspend功能
驱动里: 执行pm_runtime_use_autosuspend来设置启动autosuspend功能,
put设备时, 执行这2个函数:
pm_runtime_mark_last_busy(&lcd_dev.dev);(更新power.last_busy的状态)
pm_runtime_put_sync_autosuspend(&lcd_dev.dev);(根据power.last_busy的状态启动定时器,一段时间后如果没有再次打开动作才休眠)

(pm_runtime_get_sync不需要改,open的时候应该马上上电运行)

用户空间, 执行以下命令设置时间值:
echo 2000 > /sys/devices/platform/mylcd/power/autosuspend_delay_ms

资料:
http://blog.csdn.net/bingqingsuimeng/article/category/1228414
http://os.chinaunix.net/a2006/0519/1002/000001002210.shtml
http://www.ednchina.com/ART_44010_29_0_TA_eeda337e_3.HTM?jumpto=view_welcomead_1408610592294

好文:
http://blog.csdn.net/bingqingsuimeng/article/details/7935414
http://blog.csdn.net/bingqingsuimeng/article/details/8197912
http://blog.sina.com.cn/s/blog_a6559d920101i52j.html

4、runtime电源管理模式(内核文档runtime_pm.txt有详细描述)的更多相关文章

  1. KVM内核文档阅读笔记

    KVM在内核中有丰富的文档,位置在Documentation/virtual/kvm/. 00-INDEX:整个目录的索引及介绍文档. api.txt:KVM用户空间API,所谓的API主要是通过io ...

  2. Linux内核官方文档atomic_ops.txt【摘自Linux 内核文档】

    摘自Linux内核文档 Documentation/atomic_ops.txt,不是本人原创 Semantics and Behavior of Atomic and Bitmask Operati ...

  3. Linux内核文档:如何写符合 kernel-doc 规范的注释

    简介 Linux内核使用 Sphinx 实现把 Documentation 目录下的 reStructuredText 文件转换为非常漂亮的文档.文档既可以通过 make htmldocs 转换成 H ...

  4. LINUX 内核文档地址

    Linux的man很强大,该手册分成很多section,使用man时可以指定不同的section来浏览,各个section意义如下: 1 - commands2 - system calls3 - l ...

  5. sqlserver打开对象资源管理器管理的帮助文档的快捷键

    sqlserver打开对象资源管理器管理的帮助文档的快捷键:Fn+F1

  6. Where is the kernel documentation?; Ubuntu 上如何安装 linux 内核文档;fedora 上如何安装linux内核文档?

    有时候,linux内核文档对我们很重要,我们可以在linux系统中安装,并及时查看: 参考链接:https://askubuntu.com/questions/841043/where-is-the- ...

  7. <JavaScript>“浏览器模式”和“文档模式”之间的区别

    只有IE浏览器中才会有“浏览器模式”和“文档模式”,兼容性视图涉及两个重要的功能便是“浏览器模式[browser mode]”和“文档模式[document mode]”,在IE8/IE9中按F12键 ...

  8. FastAdmin CMS 内容管理插件标签文档

    FastAdmin CMS 内容管理插件标签文档 在CMS插件中的前端视图模板中有大量使用了自定义标签,我们在修改或制作模板的时候可以方便快捷的使用自定义标签来调用我们相关的数据. 标签库位于/add ...

  9. 我的第一个python web开发框架(23)——代码版本控制管理与接口文档

    书接上一回,小白和老菜聊到代码的版本控制和接口文档 小白:为什么要做版本控制,我不弄版本控制不也完成了项目了吗?要做版本控制不是很麻烦,又要安装服务又要提交代码,代码又不是多人用开发,还要写文档... ...

随机推荐

  1. xml中控件调用构造方法

    系统控件view有三个构造方法,分别如下 public DrawView(Context context) { super(context); } public DrawView(Context co ...

  2. Scott Hanselman的问题-1

    Scott Hanselman的问题 .Net 程序员面试 C# 语言篇 (回答Scott Hanselman的问题)   过去几年都在忙着找项目,赶项目,没有时间好好整理深究自己在工作中学到的东西. ...

  3. 46.Express框架 GET 方法和POST 方法

    转自:http://www.runoob.com/nodejs/nodejs-express-framework.html GET 方法 以下实例演示了在表单中通过 GET 方法提交两个参数,我们可以 ...

  4. HDU 4007 Dave(离散化)

    Dave Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)Total Submis ...

  5. Linux 交换分区swap

    Linux 交换分区swap 一.创建和启用swap交换区 如果你的服务器的总是报告内存不足,并且时常因为内存不足而引发服务被强制kill的话,在不增加物理内存的情况下,启用swap交换区作为虚拟内存 ...

  6. 洛谷 P1981 表达式求值

    P1981 表达式求值 题目描述 给定一个只包含加法和乘法的算术表达式,请你编程计算表达式的值. 输入输出格式 输入格式: 输入文件为 expr.in. 输入仅有一行,为需要你计算的表达式,表达式中只 ...

  7. 【吴节操点评】中国企业SaaS应用深谙未来者寥寥数几 两极分化将加剧

    数年前,在国外企业级应用如火如荼的时候.国内却是一片空白.而现在企业SaaS应用市场,包含用友.金蝶.东软在内的三巨头.已经有数十家之多.相比美国3000亿美元的企业应用三巨头来说,中国企业应用前三甲 ...

  8. 阿里云 CentOS7.4 环境安装mysql5.7

    1. 删除默认安装的数据库,无所谓的请略过 据说CentOS7.x版本会默认安装mariadb数据库,我有点强迫症,故卸载之: rpm -qa|grep mariadb yum remove mari ...

  9. 用openssl生成含有中文信息的证书

    openssl 支持 ASCII 和 UTF-8 两种编码,应该可以制作中文证书. 在生成证书签发申请时,当输入中文则 openssl 报错,这是因为当前输入的字符是 ANSI 本地编码格式,超出了 ...

  10. Android学习笔记进阶14之像素操作

    在我们玩的游戏中我们会经常见到一些图像的特效,比如半透明等效果.要实现这种半透明效果其实并不难,需要我们懂得图像像素的操作. 不要怕,其实在Android中Bitmap为我们提供了操作像素的基本方法. ...