• /sys/power/state


    kernel/power/main.c中:

    /**
     *	state - control system power state.
     *
     *	show() returns what states are supported, which is hard-coded to
     *	'standby' (Power-On Suspend), 'mem' (Suspend-to-RAM), and
     *	'disk' (Suspend-to-Disk).
     *
     *	store() accepts one of those strings, translates it into the 
     *	proper enumerated value, and initiates a suspend transition.
     */
    static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
    			  char *buf)
    {
    	char *s = buf;
    #ifdef CONFIG_SUSPEND
    	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
    	s += sprintf(s, "%s
    ", "disk");
    #else
    	if (s != buf)
    		/* convert the last space to a newline */
    		*(s-1) = '
    ';
    #endif
    	return (s - buf);
    }
    
    static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
    			   const char *buf, size_t n)
    {
    #ifdef CONFIG_SUSPEND
    #ifdef CONFIG_EARLYSUSPEND
    	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);
    	len = p ?

    p - buf : n; /* First, check if we are requested to hibernate */ if (len == 4 && !strncmp(buf, "disk", len)) { error = hibernate(); goto Exit; } #ifdef CONFIG_SUSPEND 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 if (state == PM_SUSPEND_ON || valid_state(state)) { error = 0; request_suspend_state(state); } #else error = enter_state(state); if (error) { suspend_stats.fail++; dpm_save_failed_errno(error); } else suspend_stats.success++; #endif } #endif Exit: return error ? error : n; } power_attr(state);

    state_show()和state_store()即是用户层/sys/power/state的读写操作,power_attr属性的分析见博文:点击打开链接
    state_show()显示了支持写入到/sys/power/state的字符串,它能够是:on, mem, standby, disk。

    相应代码中的:

    typedef int __bitwise suspend_state_t;
    
    #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_MAX		((__force suspend_state_t) 4)

    state_store()即是写入操作:

    它先推断是否是“disk“, 再比較是否是pm_states数组中的一个,pm_states定义在kernel/power/Suspend.c中:

    const char *const pm_states[PM_SUSPEND_MAX] = {
    #ifdef CONFIG_EARLYSUSPEND
    	[PM_SUSPEND_ON]		= "on",
    #endif
    	[PM_SUSPEND_STANDBY]	= "standby",
    	[PM_SUSPEND_MEM]	= "mem",
    };

    在android中定义了CONFIG_EARLYSUSPEND,所以进入了kernel/power/Earlysuspend.c中的request_suspend_state函数:

    void request_suspend_state(suspend_state_t new_state)
    {
    	unsigned long irqflags;
    	int old_sleep;
    
    	spin_lock_irqsave(&state_lock, irqflags);
    	old_sleep = state & SUSPEND_REQUESTED;
    	if (debug_mask & DEBUG_USER_STATE) {
    		struct timespec ts;
    		struct rtc_time tm;
    		getnstimeofday(&ts);
    		rtc_time_to_tm(ts.tv_sec, &tm);
    		pr_info("request_suspend_state: %s (%d->%d) at %lld "
    			"(%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)
    ",
    			new_state != PM_SUSPEND_ON ? "sleep" : "wakeup",
    			requested_suspend_state, new_state,
    			ktime_to_ns(ktime_get()),
    			tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
    			tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec);
    	}
    	if (!old_sleep && new_state != PM_SUSPEND_ON) {
    		state |= SUSPEND_REQUESTED;
    		queue_work(suspend_work_queue, &early_suspend_work);
    	} else if (old_sleep && new_state == PM_SUSPEND_ON) {
    		state &= ~SUSPEND_REQUESTED;
    		wake_lock(&main_wake_lock);
    		queue_work(suspend_work_queue, &late_resume_work);
    	}
    	requested_suspend_state = new_state;
    	spin_unlock_irqrestore(&state_lock, irqflags);
    }
    

    这段代码的意思是当进入suspend前运行early_suspend_work,当从suspend状态恢复后运行late_resume_work。

    这个文件里定义了它们:

    static DECLARE_WORK(early_suspend_work, early_suspend);
    static DECLARE_WORK(late_resume_work, late_resume);

    early_suspend()将运行驱动程序中使用register_early_suspend()注冊了的suspend()函数。

    late_resume()将运行驱动程序中使用register_early_suspend()注冊了的resume()函数。




  • 相关阅读:
    sqlplus登录用户hang住
    ORACLE_19c用户密码登录失败的问题以及ORA-28040
    索引瘦身_oracle_11g
    Linux内存大页设置
    C++ 总体内容(2)
    C++ 总体内容(1)
    vector中erase的用法
    NGUI中的Tween的委托使用
    IOS Android支持中文与本地文件的读取写入
    Unity人工智能学习—确定性AI算法之追踪算法二
  • 原文地址:https://www.cnblogs.com/mfmdaoyou/p/7106804.html
Copyright © 2020-2023  润新知