屬性系統(tǒng)是Android的一個重要特性,屬性由屬性名稱和鍵值組成的一段字符串,又稱鍵值對,用于記錄系統(tǒng)設(shè)置或進程信息交換。屬性在整個系統(tǒng)全局可見,每個進程可通過property_get/property_set獲取和設(shè)置屬性。本篇主要介紹移植版本的Property大致流程。
Property機制主要由服務(wù)端進程與客戶端進程組成。property服務(wù)端進程用于初始化存儲屬性的共享空間、監(jiān)聽客戶端請求、增加屬性鍵值對和更新屬性對應(yīng)鍵值等功能??蛻舳藶槭褂肞roperty的應(yīng)用進程,主要通過調(diào)用poperty_set和property_get集來實現(xiàn)設(shè)置和獲取屬性鍵值。
移植版本Property與Android原生Property使用方法有一些區(qū)別:
(1) Android是在init進程初始化Property服務(wù)端。移植版本則將Property服務(wù)端設(shè)計為獨立進程,在開機啟動時啟用Property服務(wù)。如此設(shè)計的優(yōu)點在于,將Property服務(wù)設(shè)計為獨立的模塊,便于各個應(yīng)用移植和使用。
(2) Android在使用Property機制時會核對使用進程Selinux權(quán)限,在進程使用property_set/property_get時,會先審核使用進程是否擁有訪問該屬性權(quán)限。移植版本Property則省去Selinux權(quán)限。
(3) 移植版本Property是在Android KitKat4.4基礎(chǔ)上移植而來,其內(nèi)部實現(xiàn)細節(jié)可能與4.4版本之后有所出入。
API介紹服務(wù)端:
本部分代碼接口無需特殊關(guān)注,只需將編譯的bin文件(Property_service)放入起始服務(wù)后臺運行即可。Property服務(wù)端代碼執(zhí)行順序需優(yōu)先于客戶端。
客戶端:
客戶端代碼主要功能為設(shè)置和獲取Property鍵值,以下為對外開放的接口。
設(shè)置Property
/*
* @description: 設(shè)置或增加屬性鍵值
* @param - key: 需設(shè)置的屬性名。
* @param - value: 屬性名對應(yīng)的鍵值。
* @return: 0 on success,< 0 on failure
*/int property_set(const char *key, const char *value)
獲取Property
/*
* @description: 獲取屬性鍵值字符串
* @param - key: 需獲取的屬性名。
* @param - value: 屬性名對應(yīng)的鍵值。
* @param - default_value: 若獲取失敗,則使用此默認鍵值
* @return: 成功返回屬性值長度,獲取錯誤返回0
*/int property_get(const char *key, char *value, const char *default_value)
/*
* @description:用于獲取bool類型的屬性,失敗返回默認值default_value
*/int8_t property_get_bool(const char *key, int8_t default_value)
/*
* @description:用于獲取64位類型的屬性,失敗返回默認值default_value
*/int64_t property_get_int64(const char *key, int64_t default_value)
/*
* @description:用于獲取32位類型的屬性,失敗返回默認值default_value
*/int32_t property_get_int32(const char *key, int32_t default_value)
注:系統(tǒng)中存在的key字符長度最大為32,value字符長度最大為92。如有越過,會導(dǎo)致異常情況。
特殊類型屬性:
“ro.”前綴:?“ro.”前綴,只讀屬性。僅會被設(shè)置一次,即當(dāng)設(shè)置此屬性發(fā)現(xiàn)其屬性名已經(jīng)存在,則此次設(shè)置不會生效,返回-1。
“persist.”前綴:?“persist.”前綴,保留屬性。當(dāng)服務(wù)端接收到persist屬性設(shè)置請求時,會在/data/property目錄下建立對應(yīng)的屬性文件,并將鍵值存儲到此文件中。如此一來即可實現(xiàn)鍵值掉電存儲功能。
實現(xiàn)機制流程:簡單的介紹,Property機制運作流程可以簡單的概括為以下幾步:
- PropertyService服務(wù)啟動,初始化共享內(nèi)存,加載若干屬性腳本中默認屬性內(nèi)容;
- 將系統(tǒng)中所有屬性內(nèi)容(key/value)存入系統(tǒng)共享內(nèi)存,創(chuàng)建socket,并持續(xù)監(jiān)聽客戶端socket請求;
- 系統(tǒng)中各個客戶進程將共享內(nèi)存(只讀權(quán)限)映射到自己的內(nèi)存空間,可直接讀取屬性內(nèi)容;
- 系統(tǒng)僅有Property Service (屬性服務(wù))可修改和增加屬性值;
- 各個客戶進程僅有讀取屬性權(quán)限,如需修改屬性,需通過socket方式向Property Service發(fā)出修改請求,由Property Service統(tǒng)一修改;
- 屬性鍵值內(nèi)容以字典樹的形式存儲于共享內(nèi)存中(二叉樹)。
Property機制示意圖:
代碼分析:
- Property Service:Property服務(wù)端實現(xiàn)內(nèi)容主要包括兩部分:存儲屬性值共享內(nèi)存(mmap + 二叉樹)和建立通信(socket)。?共享機制:將文件映射兩次到內(nèi)存,第一次為可讀可寫權(quán)限,句柄為property service服務(wù);第二次為只讀權(quán)限,句柄為client服務(wù)。?通信機制:服務(wù)端建立socket通信,持續(xù)監(jiān)聽并處理客戶端請求。
- Property Client:
客戶端功能主要為設(shè)置屬性和獲取屬性。其中獲取屬性可直接讀取共享內(nèi)存即可;設(shè)置屬性則需要向服務(wù)端發(fā)送申請,由服務(wù)端將屬性鍵值對設(shè)置到共享內(nèi)存。property_set流程:
property_get流程:
使用示例在使用之前先在后臺執(zhí)行服務(wù)端程序property_service(可放到開機啟動腳本)。
image.png
注:在一次開機中只允許執(zhí)行一次property_service。若希望在property_service出現(xiàn)異常,手動重新執(zhí)行,需先刪除共享文件"dev/__properties__"。
顯示系統(tǒng)設(shè)置的屬性:
手動設(shè)置屬性:
總結(jié)- 本篇主要記錄移植Android Property機制過程以及對其原理的簡要分析,Property可實現(xiàn)多進程之間的數(shù)據(jù)交互功能。
- Property機制主要使用了socket、mmap和二叉樹的技巧,學(xué)習(xí)其整體的設(shè)計可為后續(xù)工作開發(fā)增加知識儲備。
最后
用心感悟,認真記錄,寫好每一篇文章,分享每一框干貨。愿每一篇文章不負自己,不負看客!文章所有實現(xiàn)代碼,均可在后臺發(fā)送關(guān)鍵字獲取。
?猜你喜歡
? ????詳解 | Linux系統(tǒng)是如何實現(xiàn)存儲并讀寫文件的???
? ????C++打怪 之 vector??
更多文章內(nèi)容包括但不限于C/C++、Linux、開發(fā)常用神器等,可進入開源519公眾號聊天界面回復(fù)“文章目錄” 或者 菜單欄選擇“文章目錄”查看。
本文摘自 :https://blog.51cto.com/u