标准linu休眠和唤醒机制分析(二)

2024-04-22 17:48

本文主要是介绍标准linu休眠和唤醒机制分析(二),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

三、pm_test属性文件读写

int pm_test_level = TEST_NONE;

 

static const char * const  pm_tests[__TEST_AFTER_LAST] = {

       [TEST_NONE] = "none",

       [TEST_CORE] = "core",

       [TEST_CPUS] = "processors",

       [TEST_PLATFORM] = "platform",

       [TEST_DEVICES] = "devices",

       [TEST_FREEZER] = "freezer",

};

// core >> processors >> platform >> devices >> freezer, 控制范围示意

cat pm_test的时候最终会调用函数pm_test_show(),在终端上打印出上面数组中的字符串,当前的模式用[]表示出来。

echo devices > pm_test的时候会最终调用到函数pm_test_store()中去,该函数中设置全局变量pm_test_level的值,可以是0-5,分别代表上none ~ freezer。该全局变量会在后面的suspend和resume中被引用到。

memchr函数说明:

原型:extern void *memchr(void *buf, char ch, unsigned int count);

用法:#include <string.h>   

功能:从buf所指内存区域的前count个字节查找字符ch。   

说明:当第一次遇到字符ch时停止查找。如果成功,返回指向字符ch的指针;否则返回NULL。

 

四、state属性文件

power_attr(state)宏定义了一个struct kobj_attribute结构体state_attr:

static struct kobj_attribute state_attr = {  

       .attr = {

              .name = __stringify(state),

              .mode = 0644,      

       },

       .show     = state_show,

       .store      = state_store,

}

kobj_attribute结构体封装了struct attribute结构体,新建属性文件是依据struct attribute结构体。最终通过函数kobj_attr_show和kobj_attr_store回调到实际的show和store函数(kobject.c)。

 

state_show()函数主要是显示当前系统支持哪几种省电模式。

static ssize_t state_show(struct kobject *kobj,  struct kobj_attribute *attr,  char *buf)

{

       char *s = buf;

#ifdef CONFIG_SUSPEND  //def

       int i;

 

       for (i = 0; i < PM_SUSPEND_MAX; i++) {

              if (pm_states[i] && valid_state(i))

                     s += sprintf(s,"%s ", pm_states[i]);

       }

#endif

#ifdef CONFIG_HIBERNATION       // undef, don't support STD mode

       s += sprintf(s, "%s/n", "disk");

#else

       if (s != buf)

              /* convert the last space to a newline */

              *(s-1) = '/n';

#endif

       return (s - buf);

}

 

@ kernel/include/linux/suspend.h

#define PM_SUSPEND_ON              ((__force suspend_state_t) 0)

#define PM_SUSPEND_STANDBY  ((__force suspend_state_t) 1)

#define PM_SUSPEND_MEM           ((__force suspend_state_t) 3)

#define PM_SUSPEND_DISK           ((__force suspend_state_t) 4)

#define PM_SUSPEND_MAX           ((__force suspend_state_t) 5)

 

@ kernel/kernel/power/suspend.c

const char *const pm_states[PM_SUSPEND_MAX] = {

#ifdef CONFIG_EARLYSUSPEND    // android修改了标准linux的休眠唤醒机制,增加了eraly suspendlate resume机制,如果是android内核,则这个宏是需要定义的。

       [PM_SUSPEND_ON]          = "on",

#endif

       [PM_SUSPEND_STANDBY]     = "standby",

       [PM_SUSPEND_MEM]      = "mem",

};

该函数中值得注意的地方应该是valid_state(i),这个函数是用户配置的支持省电模式的验证函数,如果没有这个验证过程,cat时候打印出来的模式则是on standby mem,给上层用户的使用造成困扰。

那这个valid_state()函数在哪里定义的呢?一般定义于文件kernel/kernel/power/suspend.c

static struct platform_suspend_ops   *suspend_ops;

void suspend_set_ops(struct platform_suspend_ops *ops) // 该函数调用见后面

{

       mutex_lock(&pm_mutex);

       suspend_ops = ops;

       mutex_unlock(&pm_mutex);

}

bool valid_state(suspend_state_t state)

{

       return suspend_ops && suspend_ops->valid && suspend_ops->valid(state);

}

 

而实际平台的platform_suspend_ops结构体一般都是在文件arch/arm/mach-xxxx/pm.c中进行定义,对于mtk的平台是文件mtkpm.c,如下:

@ kernel/include/linux/suspend.h

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);

       void (*end)(void);

       void (*recover)(void);

};

经过后面的代码分析,得出了如下结论:

休眠唤醒过程依次会执行的函数是:beginprepareprepare_late,enter,wakefinishend同颜色的函数执行了恰好相反的工作。休眠的时候代码执行是停留在函数enter中,wake之后也是从suspend的时候停留的地方继续运行。

至于recover函数貌似只有在pm_test处于devices的模式下,才会被调用到。

 

@ kernel/arch/arm/mach-mt6516/mtkpm.c

static struct platform_suspend_ops mtk_pm_ops = {

       .valid      = mtk_pm_state_valid,

       .begin            = mtk_pm_begin,

       .prepare  = mtk_pm_prepare,

       .enter            = mtk_pm_enter,

       .finish           = mtk_pm_finish,

       .end        = mtk_pm_end,

};

static int mtk_pm_state_valid(suspend_state_t pm_state)

{

    return pm_state == PM_SUSPEND_MEM ;

}

void mtk_pm_init(void)

{

       _Chip_PM_init();

    /* Register and set suspend operation */

    suspend_set_ops(&mtk_pm_ops);

}  

而函数mtk_pm_init()是在函数mt6516_init_irq()中调用。可以看出该平台只支持mem的省电模式。

 

state_store()函数:

static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,

                                         const char *buf, size_t n)

{

#ifdef CONFIG_SUSPEND // set

#ifdef CONFIG_EARLYSUSPEND    //对标准linux而言,这个宏不存在

       suspend_state_t state = PM_SUSPEND_ON;

#else

       suspend_state_t state = PM_SUSPEND_STANDBY;

#endif

       const char * const *s;

#endif

       char *p;

       int len;

       int error = -EINVAL;

 

       p = memchr(buf, '/n', n);

       len = p ? p - buf : n;

 

       /* First, check if we are requested to hibernate */

       if (len == 4 && !strncmp(buf, "disk", len)) {

              error = hibernate();       // 如果值是disk,那么进入STD模式,该模式暂不讨论

  goto Exit;

       }

 

#ifdef CONFIG_SUSPEND        // def

       for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) {

              if (*s && len == strlen(*s) && !strncmp(buf, *s, len))

                     break;

       }

       if (state < PM_SUSPEND_MAX && *s)

#ifdef CONFIG_EARLYSUSPEND

// androidlinux内核会定义该宏,首先进入eraly suspend模式

              if (state == PM_SUSPEND_ON || valid_state(state)) {

                     error = 0;

                     request_suspend_state(state);

              }

#else       // 标准linux内核直接enter_state()函数

              error = enter_state(state);    // kernel/kernel/power/suspend.c

#endif

#endif

 

 Exit:

       return error ? error : n;

}


这篇关于标准linu休眠和唤醒机制分析(二)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/926447

相关文章

一文带你理解Python中import机制与importlib的妙用

《一文带你理解Python中import机制与importlib的妙用》在Python编程的世界里,import语句是开发者最常用的工具之一,它就像一把钥匙,打开了通往各种功能和库的大门,下面就跟随小... 目录一、python import机制概述1.1 import语句的基本用法1.2 模块缓存机制1.

Redis主从/哨兵机制原理分析

《Redis主从/哨兵机制原理分析》本文介绍了Redis的主从复制和哨兵机制,主从复制实现了数据的热备份和负载均衡,而哨兵机制可以监控Redis集群,实现自动故障转移,哨兵机制通过监控、下线、选举和故... 目录一、主从复制1.1 什么是主从复制1.2 主从复制的作用1.3 主从复制原理1.3.1 全量复制

Redis缓存问题与缓存更新机制详解

《Redis缓存问题与缓存更新机制详解》本文主要介绍了缓存问题及其解决方案,包括缓存穿透、缓存击穿、缓存雪崩等问题的成因以及相应的预防和解决方法,同时,还详细探讨了缓存更新机制,包括不同情况下的缓存更... 目录一、缓存问题1.1 缓存穿透1.1.1 问题来源1.1.2 解决方案1.2 缓存击穿1.2.1

Java如何通过反射机制获取数据类对象的属性及方法

《Java如何通过反射机制获取数据类对象的属性及方法》文章介绍了如何使用Java反射机制获取类对象的所有属性及其对应的get、set方法,以及如何通过反射机制实现类对象的实例化,感兴趣的朋友跟随小编一... 目录一、通过反射机制获取类对象的所有属性以及相应的get、set方法1.遍历类对象的所有属性2.获取

MySQL中的锁和MVCC机制解读

《MySQL中的锁和MVCC机制解读》MySQL事务、锁和MVCC机制是确保数据库操作原子性、一致性和隔离性的关键,事务必须遵循ACID原则,锁的类型包括表级锁、行级锁和意向锁,MVCC通过非锁定读和... 目录mysql的锁和MVCC机制事务的概念与ACID特性锁的类型及其工作机制锁的粒度与性能影响多版本

Redis主从复制的原理分析

《Redis主从复制的原理分析》Redis主从复制通过将数据镜像到多个从节点,实现高可用性和扩展性,主从复制包括初次全量同步和增量同步两个阶段,为优化复制性能,可以采用AOF持久化、调整复制超时时间、... 目录Redis主从复制的原理主从复制概述配置主从复制数据同步过程复制一致性与延迟故障转移机制监控与维

Python 标准库time时间的访问和转换问题小结

《Python标准库time时间的访问和转换问题小结》time模块为Python提供了处理时间和日期的多种功能,适用于多种与时间相关的场景,包括获取当前时间、格式化时间、暂停程序执行、计算程序运行时... 目录模块介绍使用场景主要类主要函数 - time()- sleep()- localtime()- g

python写个唤醒睡眠电脑的脚本

《python写个唤醒睡眠电脑的脚本》这篇文章主要为大家详细介绍了如何使用python写个唤醒睡眠电脑的脚本,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 环境:win10python3.12问题描述:怎么用python写个唤醒睡眠电脑的脚本?解决方案:1.唤醒处于睡眠状

Redis连接失败:客户端IP不在白名单中的问题分析与解决方案

《Redis连接失败:客户端IP不在白名单中的问题分析与解决方案》在现代分布式系统中,Redis作为一种高性能的内存数据库,被广泛应用于缓存、消息队列、会话存储等场景,然而,在实际使用过程中,我们可能... 目录一、问题背景二、错误分析1. 错误信息解读2. 根本原因三、解决方案1. 将客户端IP添加到Re

Redis主从复制实现原理分析

《Redis主从复制实现原理分析》Redis主从复制通过Sync和CommandPropagate阶段实现数据同步,2.8版本后引入Psync指令,根据复制偏移量进行全量或部分同步,优化了数据传输效率... 目录Redis主DodMIK从复制实现原理实现原理Psync: 2.8版本后总结Redis主从复制实