Linux电源管理--PM QoS

什么是PM QoS

QoS全称叫做Quality of Service,直译过来就是“服务质量”的含义。既然它是服务质量,自然需要有两个主体对象:一个服务方(servicer),一个请求服务方(requester)。PM QoS framework针对两种对象分别提供了电源管理的基础框架和接口。 那么在电源管理的范畴内要如何理解服务质量呢?实际上在这里,服务的定义是请求方对于某一个性能的需求,比如:cpu dma的延迟时间需求,网络延迟时间需求,网络吞吐量需求,内存带宽需求。(

这些性能需求理所当然会影响到电源管理行为,随着当下设备越来越先进,电源管理行为也越来越复杂,如何确保一个设备的电源管理行为不影响到系统的性能需求呢?这就是PM QoS被创造出来的初衷,它就提供了这种交互机制,以求设备在不影响应用性能需求的基础上最多的节省功耗。

假如没有PM QoS,常规的电源管理行为很简单,比如:suspend、hibernate、resume。但是这些都无法做到更精细的电源控制,无法根据特定的应用场景而触发不同的电源管理行为,当然也会有一些子系统实现了更精细的控制,比如CPU Freq、CPU Idle等一些子系统可以根据场景进行一些调节行为,这些子系统存在一些弊端:
1.这种子系统不能适用于其他设备驱动,通用性不够好
2.尝试把电源控制策略policy和driver分开存放,导致维护上更复杂

那么PM QoS就做出了一个通用的框架基础,理论上所有的设备驱动都可以去使用它来调节自己的电源管理策略,并且还把电源控制策略和设备驱动都放在内核层,更加容易维护。

PM QoS的实现

PM QoS 定义了两个框架,分别针对:

  1. PM QoS classes framework:通用的性能需求cpu_dma_latency,network_latency, network_throughput,memory_bandwidth.)
  2. PM QoS per-device framework:每个设备(per device)的性能需求。
  • PM QoS classes

这个框架针对每个通用性能参数都对应实现了一个misc设备,并且暴露对应的设备文件到应用层。针对上述的每个性能参数,内核都有一个请求链表与之关联,每个请求方发起的请求都会被加入到对应链表,而框架负责计算出来一个最终有效值,一般为这个链表中的最大值或者最小值。而对于服务提供方来说,需要根据系统中对性能的需求来做出相应的电源管理行为。有一点需要理解的是,服务提供方只是根据系统的性能需求尽可能去满足,但是并不表示系统中的需求一定会得到满足。比如说网络延迟的需求,默认网络延迟需求为2000ms,当某个app想要获取10ms的网络延迟需求时,网络设备会接收到该请求做出相应的调节,假如该网络设备最大的能力也无法确保延迟都在10ms以内,那么怎么办?实际结果是此网络设备就会一直按照最大能力去工作,不再做功耗的限制,尽自己最大的能力,如果还无法满足那就是客观原因了,不能再责备于设备驱动。

对于请求者来说,可以使用如下的内核API来对某个class进行请求:

API For requester:

void pm_qos_add_request(handle, param_class, target_value);
void pm_qos_update_request(handle, new_target_value);
void pm_qos_remove_request(handle);

除了内核的请求,用户进程也可以使用设备文件提交请求,对应的设备文件:

/dev/[cpu_dma_latency, network_latency, network_throughput]

当设备文件保持打开状态时,请求才会生效,如果关闭了设备文件,那么进程对应的请求也会随着删除。
请求值是直接写入设备文件的,格式为一个10字节的char数组,以0x开头,比如"0x12345678"。

对于服务提供方,需要获取请求,当请求发生变化时接收到通知,因此内核提供了如下一些API:

API For server:
int pm_qos_request(param_class);
int pm_qos_add_notifier(param_class, notifier);
int pm_qos_remove_notifier(int param_class, notifier);

第一个API用于主动获取qos链表中综合后的有效值,后两个分别是用于添加请求通知回调和删除请求通知回调。

  • PM per-device QoS

对于每个设备都有3个 QoS list,分别用于表示resume latency、active state latency tolerance(ms)、PM QoS flags。这三个性能指标分别表示,唤醒延迟时间,活跃状态的延迟容差时间,PM QoS flag一般用于表示电源管理的一些限制操作,比如是否允许下电等。

对于请求者来说,可以使用如下的内核API来请求:

API For requester:

int dev_pm_qos_add_request(device, handle, type, value);
int dev_pm_qos_add_ancestor_request(dev, handle, type, value);
int dev_pm_qos_update_request(handle, new_value);
int dev_pm_qos_remove_request(handle);

//以下API用于生成sysfs用于用户空间使用resume latency
int dev_pm_qos_expose_latency_limit(device, value);
void dev_pm_qos_hide_latency_limit(device);
//以下API用于生成sysfs用于用户空间使用qos flag
int dev_pm_qos_expose_flags(device, value);
void dev_pm_qos_hide_flags(device);

对于服务提供方,需要获取请求,当请求发生变化时接收到通知,因此内核提供了如下一些API:

API For server:

s32 dev_pm_qos_read_value(device);
enum pm_qos_flags_status dev_pm_qos_flags(device, mask);
int dev_pm_qos_add_notifier(device, notifier);
int dev_pm_qos_remove_notifier(device, notifier);

对于notifier接口只是用于resume latency device PM QoS。其他两个qos list不会有notifier发出。

最后解答一个疑问:什么是活跃状态的延迟容差时间(active state latency tolerance) ?
当下的一些器件会存在有多种运行模式,其中有些器件可能会在正常工作间隙立马进入低功耗模式,虽然系统没有进入休眠,但是器件依然可以在不工作时进入省电模式以节省功耗。那么这可能会带来一些延迟问题导致总线上的一些通信协议无法满足时序要求,因此加了这个qos参数。

发布了234 篇原创文章 · 获赞 78 · 访问量 23万+

猜你喜欢

转载自blog.csdn.net/rikeyone/article/details/103307724
QOS
今日推荐