QoS(Quality Of Service,服務(wù)質(zhì)量),一般在網(wǎng)絡(luò)報(bào)文中,某個(gè)報(bào)文的優(yōu)先級(jí)比較高則優(yōu)先傳輸,例如我們覺(jué)得微信聊天比看網(wǎng)頁(yè)更重要,我們就可以提高微信報(bào)文的等級(jí)即服務(wù)質(zhì)量QoS,來(lái)提供好的網(wǎng)絡(luò)服務(wù)解決延遲、網(wǎng)絡(luò)阻塞等問(wèn)題。
在電源管理里面的策略就各種governor,例如什么時(shí)候進(jìn)入cpuidle、什么時(shí)候DevFreq等,這些策略是很單一的,算法也都是很單調(diào)的,未考慮到消費(fèi)者的實(shí)際需求,那怎么樣把用戶的需求也在電源管理里面生效呢?
答案就是在governor中引入QoS,在governor中會(huì)去查QoS的策略,綜合起來(lái)進(jìn)行決策。
1. 系統(tǒng)框架介紹
1.1 功耗控制可能影響用戶體驗(yàn)的一些痛點(diǎn)
而且功耗管理會(huì)引入對(duì)性能的缺點(diǎn),主要兩方面:
延時(shí)(latency)增加:時(shí)間的開(kāi)銷,尤其是在恢復(fù)的過(guò)程中需要時(shí)間。比如,系統(tǒng)喚醒需要經(jīng)過(guò)各驅(qū)動(dòng)的恢復(fù),power domain的上電過(guò)程也有時(shí)間開(kāi)銷。
吞吐量(Throughput)減少:低功耗也會(huì)帶來(lái)算力的影響,會(huì)降低算力及網(wǎng)路的吞吐量。比如,cpu dvfs、cpu hotplug、cpu idle等會(huì)影響到cpu算力。
比如在usb傳輸?shù)臅r(shí)候把dma給限制了,導(dǎo)致傳輸速率下降,這些是用戶不希望看到的。
又比如延時(shí)和性能開(kāi)銷,影響到用戶的體驗(yàn),比如界面操作不流暢、卡頓,響應(yīng)時(shí)間過(guò)長(zhǎng)。
這就像蘋(píng)果手機(jī)很流暢,優(yōu)先響應(yīng)用戶的需求,安卓可能更高效但是有點(diǎn)卡,用戶就覺(jué)得屏幕劃不動(dòng)了。但是很明顯蘋(píng)果手機(jī)更有市場(chǎng),用戶體驗(yàn)才是王道!
在面對(duì)用戶場(chǎng)景的情況下,我們需要在策略中考慮到用戶使用感受。在用戶眼里更多的看中應(yīng)用服務(wù),而且不是一味的強(qiáng)調(diào)功耗低,為了核心業(yè)務(wù)和用戶體驗(yàn)是可以適當(dāng)?shù)臓奚牡模?a target="_blank">產(chǎn)品做出來(lái)最終還是要用戶用的,技術(shù)再好,功耗再低,不滿足用戶習(xí)慣就是0.
如果把Linux PM當(dāng)做一種服務(wù),那么他對(duì)其他模塊的影響就類比為服務(wù)的質(zhì)量,要滿足其他指標(biāo)不受到影響的情況下最大化的省電,這才是最終目標(biāo)。那么這里PM QoS的作用就是定義一套框架,以滿足系統(tǒng)(如設(shè)備驅(qū)動(dòng)等)對(duì)QoS的期望為終極目標(biāo),通俗的講:根據(jù)實(shí)際場(chǎng)景,這些期望可以描述為:xxx不大于某個(gè)值等等。
1.2 QoS框架
PM QOS使用constraint(約束)作為指標(biāo),用于各模塊對(duì)PM的訴求及限制。當(dāng)前系統(tǒng)的指標(biāo)主要有兩類,分別對(duì)應(yīng)兩個(gè)PM QOS framework。
系統(tǒng)級(jí)constraint:包括cpu&dma latency(5.4內(nèi)核),它的實(shí)際意義是,當(dāng)產(chǎn)生一個(gè)事件之后(如一個(gè)中斷),CPU或DMA的響應(yīng)延遲。例如有些CPU的串口控制器,只有幾個(gè)byte的FIFO,當(dāng)接收數(shù)據(jù)時(shí),CPU或DMA必須在FIFO填滿前,將數(shù)據(jù)讀走,否則就可能丟失數(shù)據(jù)或者降低數(shù)據(jù)的傳輸速率。由PM QoS classes framework管理,定義在kernel/power/qos.c中。
設(shè)備級(jí)constraint:包括從低功耗狀態(tài)resume的latency、active狀態(tài)的latency和一些QoS flag(如是否允許power off)。由per-device PM QoS framework管理,定義在drivers/base/power/qos.c。
整個(gè)PM QOS框架分為三部分:
需求方:各service、各driver。他們根據(jù)自己的功能需求,提出系統(tǒng)或某些功能的QOS約束,比如cpu&dma latency。
框架層:PM QOS framework,包含PM QOS classes、per device PM QOS。向需求方提供request的add、modify、remove等接口,用于管理QoS requests。對(duì)需求方的約束進(jìn)行分類,計(jì)算出極值,比如cpu&dma latency不小于某個(gè)值。向執(zhí)行方提供request value的查詢接口。PM QoS classes framework位于kernel/power/qos.c中,負(fù)責(zé)系統(tǒng)級(jí)別的PM QoS管理,通過(guò)misc設(shè)備(/dev/cpu_dma_latency),向用戶空間程序提供PM QoS的request、modify、remove功能,以便滿足各service對(duì)PM QoS的需求。per-device PM QoS framework位于drivers/base/power/qos.c中,負(fù)責(zé)per-device的PM QoS管理。
執(zhí)行方:power management的機(jī)制,比如cpuidle、cpu dvfs等。需要滿足由框架層根據(jù)需求方提供的約束計(jì)算的極值,才能執(zhí)行相應(yīng)的低功耗機(jī)制。
2. 用戶空間操作流程
2.2 用戶空間數(shù)據(jù)結(jié)構(gòu)和API
struct pm_qos_object { struct pm_qos_constraints *constraints; struct miscdevice pm_qos_power_miscdev; char *name; };
struct pm_qos_object,在給每個(gè)class定義pm_qos_constraints結(jié)構(gòu)體的同時(shí)也為每個(gè)class定義了miscdev變量,用于給用戶空間提供接口。
這些接口主要實(shí)現(xiàn)各類PM QoS需求的匯總和計(jì)算極值的工作:add/update/remove等,并且提供接口給到用戶空間process,用于用戶空間的QoS需求,另外還提供了一些notifier API,用于跟蹤指定的PM QoS的變化。
主要API:
void pm_qos_add_request(struct pm_qos_request *req,int pm_qos_class, s32 value)
1)用于向PM QoS framework添加一個(gè)QoS請(qǐng)求,主要是根據(jù)指定的pm_qos_class,向pm_qos_class鏈表中插入一個(gè)新的pm_qos_request節(jié)點(diǎn),并且更新target value。
void pm_qos_update_request(struct pm_qos_request *req,s32 new_value)
void pm_qos_update_request_timeout(struct pm_qos_request *req, s32 new_value, unsigned long timeout_us)//在update的基礎(chǔ)上多出來(lái)一個(gè)定時(shí)器,用于特定需求的延遲更新
2) pm_qos_update_request/pm_qos_update_request_timeout,如果應(yīng)用場(chǎng)景變化需要滿足不同的要求(比如串口波特率變大,相應(yīng)的響應(yīng)延遲需要變小),則需要調(diào)用該接口來(lái)更新相應(yīng)的qos請(qǐng)求。函數(shù)體的主要部分pm_qos_update_target和Add相似,這里就不再介紹。
3) pm_qos_remove_request,如果對(duì)該class沒(méi)有需求,則可以調(diào)用該接口將請(qǐng)求移除。
4) 借助misc設(shè)備向用戶空間提供的接口(open/read/write等),調(diào)用的接口和上面提到的add/remove等類似,這里就不再贅述。
5) pm_qos_add_notifier/ pm_qos_remove_notifier,有部分實(shí)體(如cpuidle,比較關(guān)注cpu_dma_latency的指標(biāo))會(huì)比較關(guān)注某一個(gè)pm qos class的target value的變化,kernel提供了這樣一個(gè)notifier的機(jī)制,該實(shí)體可以通過(guò)pm_qos_add_notifier接口添加一個(gè)notifier,這樣當(dāng)value變化時(shí),framework便會(huì)通過(guò)notifier的回調(diào)函數(shù),通知該實(shí)體。
需求方:
執(zhí)行方:
2.1 struct pm_qos_constraints
struct pm_qos_constraints { struct plist_head list; s32 target_value;/* Do not change to 64 bit */ s32 default_value; s32 no_constraint_value; enum pm_qos_type type; struct blocking_notifier_head *notifiers; }; struct pm_qos_request { struct plist_node node; int pm_qos_class; struct delayed_work work; /* for pm_qos_update_request_timeout */ };
struct pm_qos_request用于request的add/update/remove等操作。
struct pm_qos_constraints,pm qos約束,用于抽象某一個(gè)特定的PM QoS class。
target_value、default_value,分別是該指標(biāo)的目標(biāo)值(滿足所有需求的value,可以是極大值或者極小值等,某一個(gè)指標(biāo)關(guān)注的是極大值還是極小值在初始化的時(shí)候已經(jīng)確定),默認(rèn)值(該指標(biāo)的默認(rèn)值,通常是0,表示沒(méi)有限制)。
3. 初始化流程
static int __init pm_qos_power_init(void) { for (i = PM_QOS_CPU_DMA_LATENCY; i < PM_QOS_NUM_CLASSES; i++) { ret = register_pm_qos_misc(pm_qos_array[i], d); if (ret < 0) { printk(KERN_ERR "pm_qos_param: %s setup failed ", pm_qos_array[i]->name); return ret; } }
系統(tǒng)支持的QOS類型:
enum { PM_QOS_RESERVED = 0, PM_QOS_CPU_DMA_LATENCY, PM_QOS_NETWORK_LATENCY, PM_QOS_NETWORK_THROUGHPUT, PM_QOS_MEMORY_BANDWIDTH, /* insert new class ID */ PM_QOS_NUM_CLASSES, };
debugfs_create_file()會(huì)創(chuàng)建sysfs供用戶空間調(diào)用。
4. DMA舉例
例如啟動(dòng)攝像頭的時(shí)候,我們系統(tǒng)即便在省電的情況下,也需要cpu_dma允許的延遲時(shí)間不能超過(guò)50us,否則影響畫(huà)面質(zhì)量。
drivers/media/platform/via-camera.c中
pm_qos_add_request:在啟動(dòng)camera的時(shí)候,這里請(qǐng)求了一個(gè)cpu_dma_latency的指標(biāo),為50us,即camera driver申請(qǐng)的cpu_dma允許的延遲時(shí)間不能超過(guò)50us
cpuidle初始化的時(shí)候會(huì)調(diào)用:
static inline void latency_notifier_init(struct notifier_block *n) { pm_qos_add_notifier(PM_QOS_CPU_DMA_LATENCY, n); }
PM_QOS_CPU_DMA_LATENCY變化的時(shí)候會(huì)通知cpuidle
在進(jìn)行cpuidle決策的時(shí)候,例如ladder governor中,
static int ladder_select_state(struct cpuidle_driver *drv, struct cpuidle_device *dev) { struct ladder_device *ldev = this_cpu_ptr(&ladder_devices); struct ladder_device_state *last_state; int last_residency, last_idx = ldev->last_state_idx; int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
pm_qos_request()函數(shù)會(huì)獲取target_value,根據(jù)這個(gè)值來(lái)決定進(jìn)行什么級(jí)別的idle。
對(duì)于cpuidle idle來(lái)說(shuō),一般有C1~C3幾個(gè)等級(jí),在C3等級(jí)的退出延遲時(shí)間是57us(不同平臺(tái)會(huì)有差別),那么這里camera driver需求的50us容忍延遲就可以讓cpuidle退到C2 idle等級(jí)(即前面章節(jié)提到的執(zhí)行方需要確保自身的行為滿足這些pm qos的需求),就不會(huì)導(dǎo)致上面說(shuō)的DMA transfer gets corrupted的問(wèn)題了。
后記
內(nèi)核版本有時(shí)候差異也挺大的,一個(gè)機(jī)制,特別是小眾的可能會(huì)有更新,我們?cè)谡?a href="http://www.1cnz.cn/soft/special/" target="_blank">資料的時(shí)候,就需要注意這點(diǎn),找到合適的學(xué)習(xí)資料。不過(guò)主要的思想是不變的,變的就是結(jié)構(gòu)體定義,api函數(shù)的調(diào)用流程等。
審核編輯:湯梓紅
-
電源管理
+關(guān)注
關(guān)注
115文章
6177瀏覽量
144447 -
內(nèi)核
+關(guān)注
關(guān)注
3文章
1372瀏覽量
40278 -
網(wǎng)絡(luò)
+關(guān)注
關(guān)注
14文章
7553瀏覽量
88731
原文標(biāo)題:電源管理入門(mén)-15 PM QoS
文章出處:【微信號(hào):OS與AUTOSAR研究,微信公眾號(hào):OS與AUTOSAR研究】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論