美文网首页
Linux内核睡眠唤醒状态

Linux内核睡眠唤醒状态

作者: 小田BSP | 来源:发表于2021-06-14 22:40 被阅读0次

    一、系统睡眠状态

    Linux内核支持四种系统睡眠状态即:mem、standby、freeze and disk

    可通过文件/sys/power/state进行读写访问,区别如下:

    Label ACPI State 说明 State 功耗 唤醒
    freeze Suspend-To-Idle 冻结用户空间,将所有I/O设备进入低功耗状态,处理器进入空闲状态 S0 最高 最快
    standby Power-On Suspend 冻结用户空间,将所有I/O设备进入低功耗状态,关闭非引导CPU,暂停系统 S1 较高 较快
    mem Suspend-to-RAM(STR) 将系统和设备状态保存到内存(处在自刷新模式,已保留其内容),所有设备进入低功耗模式 S2 较低 较慢
    disk Suspend-to-disk(STD) 类似STR,将内存内容写入到磁盘, S3 最低 最慢

    二、睡眠状态说明

    RockPI 4A单板Debian系统Linux 4.4内核中,查看电源状态,仅支持freeze和mem两种。

    root@linaro-alip:/sys/power# cat state
    freeze mem
    

    原因:

    1、Platform驱动只实现了mem类型的suspend

    2、只有在hibernation可用时,才支持STD

    1、psci初始化流程

    /**
     * suspend_valid_only_mem - Generic memory-only valid callback.
     *
     * Platform drivers that implement mem suspend only and only need to check for
     * that in their .valid() callback can use this instead of rolling their own
     * .valid() callback.
     */
    int suspend_valid_only_mem(suspend_state_t state)
    {
        return state == PM_SUSPEND_MEM;
    }
    
    static const struct platform_suspend_ops psci_suspend_ops = {
        .valid          = suspend_valid_only_mem, ## 判读有效状态,仅支持mem状态
        ...
    };
    
    static void __init psci_init_system_suspend(void)
    {
        int ret;
        ...
        if (ret != PSCI_RET_NOT_SUPPORTED)
            suspend_set_ops(&psci_suspend_ops);  ### 设置global suspend method table
    }
    

    suspend_set_ops()函数赋值数组pm_states实现如下:

    /**
     * suspend_set_ops - Set the global suspend method table.
     * @ops: Suspend operations to use.
     */
    void suspend_set_ops(const struct platform_suspend_ops *ops)
    {
        suspend_state_t i;
        int j = 0;
    
        lock_system_sleep();
    
        suspend_ops = ops;
        for (i = PM_SUSPEND_MEM; i >= PM_SUSPEND_STANDBY; i--)
            ## 1、此处判断valid状态,只有mem满足
            if (valid_state(i)) {
                pm_states[i] = pm_labels[j++];
            } else if (!relative_states) {  ## 2、standby状态,置NULL
                pm_states[i] = NULL;
                j++;
            }
    
        
        pm_states[PM_SUSPEND_FREEZE] = pm_labels[j]; ## 3、freeze状态
    
        unlock_system_sleep();
    }
    

    2、power state显示

    /sys/power/state文件显示的内容,通过state_show()函数实现,该函数最终显示数组pm_states的内容。

    static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
                  char *buf)
    {
        char *s = buf;
    #ifdef CONFIG_SUSPEND
        suspend_state_t i;
    
        for (i = PM_SUSPEND_MIN; i < PM_SUSPEND_MAX; i++)
            if (pm_states[i])
                s += sprintf(s,"%s ", pm_states[i]);
    
    #endif
        if (hibernation_available())  ### hibernation_available()为true,才支持STD
            s += sprintf(s, "disk ");
        if (s != buf)
            /* convert the last space to a newline */
            *(s-1) = '\n';
        return (s - buf);
    }
    

    参考:

    Documentation/power/states.txt

    相关文章

      网友评论

          本文标题:Linux内核睡眠唤醒状态

          本文链接:https://www.haomeiwen.com/subject/gzhaeltx.html