android進(jìn)程間通信之System Property

android進(jìn)程間通信一般用到三種:

1.system property 系統(tǒng)屬性,可以對整個(gè)系統(tǒng)全局共享,所以可以達(dá)到進(jìn)程間共享的目的

2.socket通信,很多framework 框架層與system之間通信用這個(gè),比如vold與mountservice、NetworkManagementService與netd、NsdService與netd。系統(tǒng)framework 框架層有實(shí)現(xiàn)了NativeDaemonConnector供大家調(diào)用。

3.AIDL、鼎鼎大名的AIDL,Android Interface definition language的縮寫,是android最常用的進(jìn)程間通信方式,從android 系統(tǒng)中可以找到很多這樣的例子。他的優(yōu)點(diǎn)很多,比如可定義接口,只要按照標(biāo)準(zhǔn),可以很容易的用自定義接口實(shí)現(xiàn)進(jìn)程間通信,傳輸參數(shù)不受限制,這是上面兩種不具備的優(yōu)勢。

當(dāng)然肯定很多朋友會(huì)說還有廣播啊,廣播也能實(shí)現(xiàn)進(jìn)程間的通信,但是他只能局限在框架層和應(yīng)用。無法與中間件實(shí)現(xiàn)廣播通信。

1.屬性鍵值對

今天我們介紹第一種,最簡單也很實(shí)用的進(jìn)程間通信方式。這些屬性可能是有些資源的使用狀態(tài),進(jìn)程的執(zhí)行狀態(tài),系統(tǒng)的特有屬性。。。

屬性系統(tǒng)是android的一個(gè)重要特性。每個(gè)屬性是一個(gè)鍵值對(key/value pair),其類型都是字符串。但給它的缺點(diǎn)也很明顯,只能傳輸簡單的參數(shù)。

可以通過命令adb shell :

getprop查看android設(shè)備上所有屬性狀態(tài)值?;蛘呤褂胹etprop設(shè)置某個(gè)屬性的狀態(tài)。

特別屬性 :

如果屬性名稱以“ro.”開頭,那么這個(gè)屬性被視為只讀屬性。一旦設(shè)置,屬性值不能改變。

如果屬性名稱以“persist.”開頭,當(dāng)設(shè)置這個(gè)屬性時(shí),其值也將寫入/data/property。

如果屬性名稱以“net.”開頭,當(dāng)設(shè)置這個(gè)屬性時(shí),“net.change”屬性將會(huì)自動(dòng)設(shè)置,以加入到最后修改的屬性名。

(這是很巧妙的。 netresolve模塊的使用這個(gè)屬性來追蹤在net.*屬性上的任何變化。)

屬性“ ctrl.start ”“ ctrl.stop ”是用來啟動(dòng)和停止服務(wù)。每一項(xiàng)服務(wù)必須在/init.rc中定義.系統(tǒng)啟動(dòng)時(shí),與init守護(hù)進(jìn)程將解析init.rc和啟動(dòng)屬性服務(wù)。一旦收到設(shè)置“ ctrl.start ”屬性的請求,屬性服務(wù)將使用該屬性值作為服務(wù)名找到該服務(wù),啟動(dòng)該服務(wù)。這項(xiàng)服務(wù)的啟動(dòng)結(jié)果將會(huì)放入“ init.svc.<服務(wù)名>“屬性中??蛻舳藨?yīng)用程序可以輪詢那個(gè)屬性值,以確定結(jié)果。開機(jī)動(dòng)畫就是這么實(shí)現(xiàn)的。

2.framework訪問系統(tǒng) 屬性

framework通過SystemProperties接口操作系統(tǒng)屬性,所以在java層大家都可以使用該類來獲取或者設(shè)置系統(tǒng)屬性。SystemProperties通過JNI調(diào)用訪問系統(tǒng)屬性。

代碼路徑frameworks\base\core\java\android\os\ SystemProperties.java:

public class SystemProperties {

//JNI

private static native String native_get(String key, String def);

privatestaticnativevoidnative_set(String key, String def);

public static String get(String key, String def) {

?return native_get(key, def);?

}

public static void set(String key, String val) {

?native_set(key, val);?

}?

}

Jni代碼位置:

\frameworks\base\core\jni\android_os_SystemProperties.cpp

實(shí)現(xiàn)是在\bionic\libc\bionic\system_properties.c中:

int __system_property_get(constchar*name,char*value) {

//數(shù)據(jù)已經(jīng)存儲(chǔ)在內(nèi)存中__system_property_area__ 等待讀取完返回

const prop_info *pi = __system_property_find(name);

return __system_property_read(pi,0, value);?

}

進(jìn)程啟動(dòng)后數(shù)據(jù)已經(jīng)將系統(tǒng)屬性數(shù)據(jù)讀取到相應(yīng)的共享內(nèi)存中,保存在全局變量__system_property_area__;

進(jìn)程之間都是獨(dú)立的,系統(tǒng)屬性數(shù)據(jù)是如何讀取到當(dāng)前進(jìn)程空間中的呢?后續(xù)介紹。

設(shè)置屬性異步socket通信:

int __system_property_set(constchar*key,constchar*value) {

? ?msg.cmd = PROP_MSG_SETPROP;?

? strlcpy(msg.name, key,sizeofmsg.name);?

? strlcpy(msg.value, value,sizeofmsg.value);?

? err = send_prop_msg(&msg);

?}

static int send_prop_msg(prop_msg *msg) {

? ?//sokcet 通信 /dev/socket/property_service

? ?s = socket(AF_LOCAL, SOCK_STREAM,0);?

? ?connect(s, (structsockaddr *) &addr, alen)?

? ?send(s, msg,sizeof(prop_msg),0)

? ? close(s);

}

通過socket向property_service發(fā)送消息,property_service運(yùn)行在哪里呢?

3.Property Service創(chuàng)建服務(wù)端socket

Property Service在init進(jìn)程中,init進(jìn)程啟動(dòng)監(jiān)聽過程中:\system\core\init\Init.c

init property code

Property Service 是運(yùn)行在init守護(hù)進(jìn)程中。

先看看Property Service接收到消息后的處理。

4. Property Service 監(jiān)聽socket處理

Property Service監(jiān)聽socket消息的處理過程:

通過設(shè)置系統(tǒng)屬性啟動(dòng)/關(guān)閉Service

權(quán)限判斷:

所以如果想要應(yīng)用有權(quán)限啟動(dòng)/關(guān)閉某Native Service:

需要具有system/root權(quán)限,找到對應(yīng)應(yīng)用uid gid,將應(yīng)用名稱加入到control_perms列表中

處理消息 可以通過設(shè)置系統(tǒng)屬性 改變服務(wù)的執(zhí)行狀態(tài) start/stop:

連著前面就是ctr.start和ctr.stop系統(tǒng)屬性:用來啟動(dòng)和停止服務(wù)的。

例如:

// start boot animation

property_set("ctl.start", "bootanim");

在init.rc中表明服務(wù)是否在開機(jī)時(shí)啟動(dòng):

service adbd /sbin/adbd

classcore

disabled//不自動(dòng)啟動(dòng)

啟動(dòng)服務(wù)的時(shí)候會(huì)判斷:

修改系統(tǒng)屬性值:

看這個(gè)修改系統(tǒng)屬性權(quán)限表,配置系統(tǒng)權(quán)限可以查看system/core/include/private/android_filesystem_config.h:

指定了特定的用戶有用修改 帶有某些前綴的系統(tǒng)屬性值。

到這里基本就是Property對外的基本工作流程,Property Service內(nèi)部具體如何實(shí)現(xiàn),操作運(yùn)行,

跨進(jìn)程空想內(nèi)存等問題仍未清除是如何處理的。

5. 屬性系統(tǒng)設(shè)計(jì)

Property Service運(yùn)行在init進(jìn)程中,開機(jī)從屬性文件中加載到共享內(nèi)存中;設(shè)置系統(tǒng)屬性通過socket與Property Service通信。

Property Consumer進(jìn)程將存儲(chǔ)系統(tǒng)屬性值的共享內(nèi)存,加載到當(dāng)前進(jìn)程虛擬空間中,實(shí)現(xiàn)對系統(tǒng)屬性值的讀取。

Property Setter進(jìn)程修改系統(tǒng)屬性,通過socket向Property Service發(fā)送消息,更改系統(tǒng)屬性值。

6. 屬性系統(tǒng)實(shí)現(xiàn)

屬性系統(tǒng)設(shè)計(jì)的關(guān)鍵就是:跨進(jìn)程共享內(nèi)存的實(shí)現(xiàn)。

下面將看看屬性系統(tǒng)實(shí)現(xiàn)具體過程:

Init進(jìn)程執(zhí)行:

初始化Property Service\system\core\init\property_service.c

初始化共享內(nèi)存空間:

__system_property_area__

每個(gè)進(jìn)程都會(huì)使用此變量,指向系統(tǒng)屬性共享內(nèi)存區(qū)域,訪問系統(tǒng)屬性,很重要。

位于:\bionic\libc\bionic\system_properties.c中,屬于bionic庫。后面將介紹各進(jìn)程如何加載共享內(nèi)存。

將文件作為共享內(nèi)存映射到進(jìn)程空間內(nèi)存使用:

加載系統(tǒng)屬性默認(rèn)數(shù)據(jù)文件:

加上上面所述:Property Service Socket資源的創(chuàng)建,來監(jiān)聽socket通信連接設(shè)置系統(tǒng)屬性,

在Init進(jìn)程中Property Service完成了初始化。

將得到該內(nèi)存區(qū)域數(shù)據(jù)結(jié)構(gòu):

7. 進(jìn)程共享系統(tǒng)屬性內(nèi)存空間實(shí)現(xiàn)

Property Service運(yùn)行于init進(jìn)程中,將文件映射為創(chuàng)建一塊共享內(nèi)存空間,但在整個(gè)系統(tǒng)中,

其他進(jìn)程也能夠讀取這塊內(nèi)存映射到當(dāng)前進(jìn)程空間中,是如何實(shí)現(xiàn)的呢?

Service進(jìn)程啟動(dòng):將共享內(nèi)存空間fd size作為環(huán)境變量傳遞給新創(chuàng)建進(jìn)程

共享內(nèi)存空間fd size作為環(huán)境變量傳遞給新創(chuàng)建進(jìn)程后,將在何處使用呢?

將系統(tǒng)屬性內(nèi)存空間映射到當(dāng)前進(jìn)程虛擬空間:

進(jìn)程在啟動(dòng)時(shí),會(huì)加載動(dòng)態(tài)庫bionic libc庫:

\bionic\libc\bionic\libc_init_dynamic.c中:

void __attribute__((constructor)) __libc_preinit(void);

根據(jù)GCCconstructor/destructor屬性:

給一個(gè)函數(shù)賦予constructor或destructor,其中constructor在main開始運(yùn)行之前被調(diào)用,

destructor在main函數(shù)結(jié)束后被調(diào)用。如果有多個(gè)constructor或destructor,可以給每個(gè)constructor

或destructor賦予優(yōu)先級,對于constructor,優(yōu)先級數(shù)值越小,運(yùn)行越早。destructor則相反。

多個(gè)constructor需要加優(yōu)先級:

__libc_preinitbionic libc庫加載的時(shí)候會(huì)被調(diào)用:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容