linux进程的电源管理

  • 腾讯主机安全(CWP)利用机器学习为用户提供黑客入侵检测和漏洞风险预警等安全防护服务,主要包括密码破解阻断、异常登录审计、木马文件查杀、高危漏洞检测等安全功能,解决当前服务器面临的主要网络安全风险,帮助企业构建服务器安全防护体系。

  1. 待机、睡眠与休眠的区别?
  2. Android开发者官网当中提到“idle states”,该如何理解,这个状态会对设备及我们的程序造成何种影响?
  3. 进入Doze模式中的idle状态,我们的程序还能运行吗?
  4. 手机睡眠之后,为何我们写Alarm程序、来电显示程序依旧会生效?

如果你也有以上疑问,那么本文会对你解开疑惑有一定的帮助

要理解第一个问题,得先从ACPI(高级配置与电源接口)说起,ACPI是一种规范(包含软件与硬件),用来供操作系统应用程序管理所有电源接口。

ACPI将计算机系统的状态划分为四个全局状态(G0-G3),共7个状态,其中G0对应S0;G1将低功耗状态细分为四个状态,对应S1-S4;G2、G3代表关机状态分别对应S5、S6。

CPU与RAM供电正常,但CPU不执行指令

比S1更深的一个睡眠层次,这种模式通常不采用

Soft Off,CPU、外设等断电,但电源依旧会为部分极低耗设备供电

这里只需要对ACPI的七个状态有个大致了解即可,下一节会有具体的例子来说明各个状态。

Linux系统电源状态

在Linux操作系统中,将电源划分为如下几个状态:

挂起到内存,俗称待机、睡眠(Sleep),进入该状态,系统的主要工作如下:

1、将系统当前的运行状态等数据保存在内存中,此时仍需要向RAM供电,以保证后续快速恢复至工作状态

2、冻结用户态的进程和内核态的任务(进入内核态的进程或内核自己的task)

3、关闭外围设备,如显示屏、鼠标等,中断唤醒外设不会关闭,如电源键

Standby也属于睡眠的一种方式,属于浅睡眠。该模式下CPU并未断电,依旧可以接收处理某些特定事件,视具体设备而定,恢复至正常工作状态的速度也比STR更快,但也更为耗电。举个例子来说,以该方式进入睡眠时,后续通过点击键盘也能将系统唤醒。而以mem进入的睡眠为深度睡眠,只能通过中断唤醒设备唤醒系统,如电源键(此时按电源键,不会经过正常的开机流程的BIOS、BOOTLOAD等),此时按键盘是无法唤醒系统的。

挂起到硬盘,俗称休眠(Hibernation)将系统当前的运行状态等数据保存到硬盘上,并自动关机。下次开机时便从硬盘上读取之前保存的数据,恢复到休眠关机之前的状态。

譬如在休眠关机时,桌面打开了一个应用,那么下一次开机启动时,该应用也处于打开状态。而正常的关机-开机流程,该应用是不会打开的。

在新版内核中,进程freeze的功能被单独抽离出来作为一个电源状态,该状态仅仅是冻结进程,并不会使系统进入低功耗状态(如切断CPU时钟源、关闭外设供电等)。

其中状态4就是STD,所谓的休眠状态(Hibernation)

至此,我们可以知道,睡眠与休眠是2个不同的概念,睡眠属于STR,而休眠属于STD,切勿混为一谈。

网上也有很多关于“Android休眠”的文章,事实上,Android手机压根儿就不支持休眠模式。

查看Linux支持的电源模式

#查看系统支持的电源模式
 

看来Ubuntu-17.0.4版本是不支持休眠功能了,state当中并没有disk,执行休眠命令也提示找不到。

在公司测试Ubuntu-16.0.4是支持休眠的,休眠时会将当前RAM中的数据保持至swap分区,以供后续恢复。

查看Android支持的电源模式

这里我使用的是模拟器查看的,真机也一样,Android手机是不支持休眠模式的,休眠模式需要一块与RAM大小一致存储空间,这在移动设备上可是个不小的开销。

Linux系统运行的基础是基于进程调度,实际上内核调度的线程(task),内核并不会区分线程与进程,都将他们当做一个线程(task)来处理;当所有的进程都没事儿干的时候,系统就会启用idle进程,使系统进入低功耗状态(如关闭一些服务、模块功能,降低CPU工作频率等),即idle状态,以达到省电的目的。

idle状态又可以划分为不同的层级,以MTK的芯片为例,通常划分为以下几个状态:

亮屏 Idle 模式,该模式下与正常工作状态差别不大,唯一的区别就cpu处于空闲状态

浅度 Idle 模式,cpu处于 WFI(wait for interrupt),屏幕熄灭,同时关闭一些不需要的服务及模块,注意此状态cpu的时钟源与RTC模块是工作正常的,此时是可以通过TimerTask的定时触发激活系统的,TimerTask依赖于CPU的RTC模块,而Alarm则依赖于PMIC的RTC模块

深度idle模式,该模式下cpu的时钟源和hrtimer(高精度定时器模块(RTC))被关闭,所有进程(包括系统进程)被冻结,即进入上文所述的睡眠状态

idle进程是由原始进程(pid=0)在初始化init进程(pid=1)之后演变而来,可以说是init进程的祖先,关于其详细介绍可参考如下链接:

Device Idle属于Doze模式中概念,即指当手机屏幕熄屏、不充电、静置不动,有网友分析了源码,指出6.0手机需要静置1时4分30秒才能进入Doze模式。

系统不会扫描Wi-Fi

结合上文分析的cpu idle不难发现Doze模式中的idle状态在概念属于浅idle状态,只是关闭了一些特定服务和模块,并非立即进入睡眠,当然这个过程当中依旧有可能满足睡眠条件而进入睡眠状态,至于如何进入请参考下文【睡眠触发入口】一节。

Android采用linux内核,所以电源状态整体上是与linux操作系统相同,下图是Android的电源管理框架:

唤醒锁,一种锁机制,用于阻止系统进入睡眠状态,只要有应用获取到改锁,那么系统就无法进入睡眠状态。

该机制起初是早期Android为Linux内核打得一个补丁,并想合入到linux内核,但被Linux社区拒绝,后续Linux内核引入自己的Wakelock机制,Android系统也使用的是linux的Wakelock机制,所以该机制并非Android特有的机制。

Android系统提供了两种类型的锁,每一个类型又可分为超时锁与普通锁,超时锁,超时会自动释放,而普通锁则必需要手动释放:

阻止系统进入睡眠状态(STR)

阻止系统从idle进程进入那些具有较大中断时延、禁用了较多中断源的低功耗状态(睡眠除外),持有该类型的锁,不影响系统进入睡眠状态。自Android API-17(对应android linux内核版本3.4)移除了该类型的唤醒锁。

中断时延:计算机接收到中断信号到操作系统作出响应,并完成转入中断服务程序(ISR)的时间。

内核当中关于WakeLock的主要源码位于:

应用层提供的锁类型如下,这些锁都需要手动释放:

当我们应用层释放锁之后,它并不会马上消失。wakelock分为激活和非激活状态,非激活状态300S之内,无人在申请wakelock,那么它将从红黑二叉树,LRU链表当中删除,如此便可复用锁,节省系统开销。

wake_unlock,系统每释放一个锁,就会检查是否还存其他激活的wakelock,若不存在则执行Linux的标准suspend流程进入睡眠状态 在超时锁的超时回调函数,判断是否存在其他激活的wakelock,若不存在,则进入睡眠状态 autosleep机制,android 4.1引入该机制,亮屏时会向autosleep节点写入off,熄屏则会写入mem。Android一灭屏,就会尝试进入睡眠,失败之后系统处于idle进程超过一定时间,则又尝试进入睡眠,判断标准同上,若存在wakelock则进入失败

关于autosleep机制的内核源码分析,可以参考如下文章:

预挂起机制是Android特有的挂起机制, 这个机制作用是关闭一些与显示相关的外设,比如LCD背光、重力感应器、 触摸屏,但是其他外设如WIFI、蓝牙等模块等并未关闭。 此时,系统依旧可以处理事件,如音乐播放软件,息屏后依旧能播放音乐。 需要注意的是Early

迟唤醒机制,用于唤醒预挂起的设备

一般情况下,当我们息屏后,系统将先通过Early Suspend机制进入Idle状态,如果满足进入睡眠的条件(没有进程持有唤醒锁)则会通过Linux的Suspend机制进入Sleep(睡眠)状态。

内核源码流程分析可参考如下文章: 源码位于:

看到这儿,不知你是否疑问,既然系统睡眠了,CPU断电不执行指令了,为何我们定的Alarm会生效以及能接收到来电?

当AP进入睡眠,有来电时,Modem(调制解调器)将唤醒AP;而我们平时所用的Alarm在硬件上则是依赖PMIC(电源管理芯片)中的RTC模块,所以即使AP断电进入睡眠,我们定的闹钟依旧会生效。

若想更深入的了解,则可参考Android RIL机制相关的文章。

  1. 待机、睡眠与休眠的区别

实际上待机(standby)与睡眠(mem)属于不同模式,但现在大多操作系统都不支持待机模式了,我们也习惯将待机等同于睡眠,睡眠属于STR,休眠属于STD,Android手机不支持休眠!!!

  1. Android开发者官网当中提到“idle state”,该如何理解,这个状态会对设备及我们的程序造成何种影响

所谓的idle状态,就是指系统进入某个低功耗状态,以MTK为例,常见的状态有soidle、rgidle以及dpidle。rgidle只是限制我们程序使用某些模块,如Doze模式中不能访问网络;而dpidle则会冻结所有进程,系统进入睡眠。

  1. 进入Doze模式中的idle状态,我们的程序还能运行吗?

Doze模式中的idle概念上属于rgidle状态,此时我们的程序是能运行的,只是不能访问网络等,但是在这个过程中,系统可能会满足进入睡眠条件,冻结所有进程,这样我们的程序就不会得到执行。 可以自己写个死循环的线程(普通线程,非looper线程),强制手机进入Doze的idle模式,你会发现你的程序依旧在执行,但是静置在哪儿一段时间后,你会发现你的线程被冻结,不会执行,当你点亮屏幕,你的线程又会继续工作。

  1. 手机睡眠之后,为何我们写Alarm程序、来电显示程序依旧会生效?

Android在硬件架构上将处理器分为AP与BP,应用程序运行与AP之中,睡眠只是将AP断电,BP(Modem)不会断电,当有来电时,BP将会唤醒AP。

Alarm在硬件上依赖的是Modem中的PMIC的RTC模块,而不是AP中的RTC模块,当定时器触发时,可以唤醒AP,使我们的Alarm程序依旧会得到执行

不论是现实生活中的渗透测试,还是 CTF 竞赛中的赛题,都经常会出现/proc这个目录,利用该目录中的一些子目录或者文件不仅可以获取有用的环境变量信息甚至可以直接Getshell

操作系统中的/proc是一个位于内存中的伪文件系统(或者叫做虚拟文件系统)。该目录下保存的不是真正的文件和目录,而是一些"运行时"的信息,例如系统内存、磁盘IO、设备挂载信息和硬件配置信息等。proc目录是一个控制中心,用户可以通过更改其中某些文件来改变内核的运行状态,proc目录也是内核提供给一个的查询中心,可以通过这些文件查看有关系统硬件及当前正在运行进程的信息。在

简单一点来讲,/proc目录就是保存在系统中的信息,其包含许多以数字命名的子目录,这些数字代表着当前系统正在运行进程的进程号,里面包含对应进程相关的多个信息文件

一般来说,在/proc目录下会存在以下的文件和目录

每一个 /proc/pid 目录中还存在一系列目录和文件, 这些文件和目录记录的都是关于 pid 对应进程的信息. 例如在 /proc/pid 的目录下存在一个 task 目录, 在 task 目录下又存在 task/tid 这样的目录, 这个目录就是包含此进程中的每个线程的信息, 其中的 tid 是内核线程的 tid, 通过 GETDENTS 遍历 /proc 就能够看到所有的 /proc/pid 的目录, 当然通过 ls -al /proc 的方式也可以看到所有的信息 proc 下面还有许多其他的文件记录了系统中的各种信息

高级电源管理(APM)版本信息及电池相关状态信息,通常由apm命令使用

用于诊断内存碎片问题的相关信息文件;

在启动时传递至内核的相关参数信息,这些信息通常由lilogrub等启动管理工具进行传递

处理器的相关信息的文件

系统上已安装的内核使用的密码算法及每个算法的详细信息列表

> 这是一个子目录,包含了当前进程打开的每一个文件,每一个条目都是一个文件描述符,这些文件描述符是指向实际文件的一个符号链接,即每个通过这个进程打开的文件都会显示在这里,可以通过`fd`目录里的文件获得指定进程打开的每个文件的路径以及文件内容 > `fd`的另一个用途在于:在`linux`系统中,当一个程序用`open()`打开了一个文件但最终没有关闭该文件,即使从外部删除这个文件,但是在`/proc`这个进程的`pid`目录下的`fd`文件描述符目录下还是会有这个文件的文件描述符,通过这个文件描述符可以得到被删除文件的内容 [+] 查看指定进程打开的某个文件的路径 [+] 查看指定进程打开的某个文件的内容

赛题中往往需要的都是当前进程中的有用信息,而在上述的操作中基本都是目标环境中指定的进程信息,这时可以通过/proc/self来获取当前进程的信息,相较于/proc/$pid/proc/self不仅能够更方便的获取本进程的信息,还可以避免在forkdaemon等情况下pid发生变化,感兴趣的话可以看看

[+] 获取当前启动进程的完整命令
[+] 获取目标当前进程环境的运行目录与目录里的文件
[+] 获得当前进程的可执行文件的完整路径
[+] 获取当前进程的环境变量信息
[+] 获取当前进程打开的文件内容
 

tip:当找不到网站路径的时候可以利用/proc/self/cwd目录来读取apache进程的php文件源码

 

打开题目界面只有一个登录框,随便输入点东西后发现url的形式可能存在任意文件读取,尝试后成功下载/etc/passwd

 

成功拿到当前文件的名字,使用/proc/self/cwd来获取文件内容

 
 

观察源代码后发现关键点:os.remove(SECRET_FILE),这里导致SECRET_FILE文件被删除了,结合上文分析可以知道,fd可以用来读取被删除的文件,所以只需要爆破id值就可以成功读取到被删除文件的内容,这里爆破出来的id=3

后面就是常规的步骤了,利用拿到的SECRET_FILE来反弹 shell 即可

 
 

  

我要回帖

更多关于 cpu供电相位控制 的文章