Android開発のサービスマネージャ分析
7809 ワード
Android開発のサービスマネージャ分析
Androidシステムで最も多く使われる通信メカニズムはBinderで、Binderは主にClient、Server、ServiceManager、Binderドライバから構成されています.Client、Service、ServiceManagerはユーザースペースで実行され、Binderドライバはカーネルスペースで実行されます.コアコンポーネントはBinderドライバであり、ServiceManagerはClientまたはServicesで通信する前にServiceManagerに連絡するサポート管理機能を提供します.ServiceManagerは、サーバを管理し、Clientにサーバを照会する機能を提供するデーモンです.
ソースの場所:frameworks/base/cmds/servicemanager/service_manager.c
ここでmain関数には主に3つの機能があります.1)Binderデバイスファイルを開くには、まずこのstruct binder_を見てみましょう.state構造体struct binder_state{int fd;//ファイル記述子、/dev/binderデバイスvoid*mappedを開く;//デバイスファイル/dev/binderをプロセス空間の開始アドレスunsigned mapsizeにマッピングする;//メモリ空間のサイズをマッピングする};マクロ:#define BINDER_SERVICE_MANAGER(void*)0)は、ServiceManagerに対応するハンドルが0であり、表面自体がサーバ管理者であることを示します.他のServerプロセスハンドルの値は0より大きい.
2)Binderドライバ自身がBinderコンテキスト管理者であることを伝える
3)無線ループに入り、serverの役割を果たし、Clientの要求を待つ
まず、BinderがどのようにBinder伝達メッセージのデータ構造を組織しているかを見なければなりません.Binderドライバを呼び出すとvoid*ptr構造体が得られ、binder_に強制的に変換されます.txn*txn,そしてこのtxnに基づいてBinderの入出力構造体binder_を得た.io *bio.最後に,要求を処理しても返信を送信しても,このbio構造を処理する.我々のBinder通信のbinder構造はbinder_objectが組織しbinder_を指すio構造内data.まず、BinderがどのようにBinder伝達メッセージのデータ構造を組織しているかを見なければなりません.Binderドライバを呼び出すとvoid*ptr構造体が得られ、binder_に強制的に変換されます.txn*txn,そしてこのtxnに基づいてBinderの入出力構造体binder_を得た.io *bio.最後に,要求を処理しても返信を送信しても,このbio構造を処理する.我々のBinder通信のbinder構造はbinder_objectが組織しbinder_を指すio構造内data.
上のbinder_object構造体の内容は、私たちのコードのbio_に順次対応しています.get_uint32(msg); bio_get_string16(msg, &len); bio_get_string16(msg, &len); bio_get_ref(msg); 上のbinder_object構造体の内容は、私たちのコードのbio_に順次対応しています.get_uint32(msg); bio_get_string16(msg, &len); bio_get_string16(msg, &len); bio_get_ref(msg);
クライアントがサービスを追加する必要がある場合:SVC_MGR_ADD_SERVICE 1)まずbio_を呼び出すget_string 16()binder_からioでサービス名を取得します.2)bio_を呼び出すget_ref()binder_からioでサービスを受けるbinderエンティティstruct binder_object
3)do_を呼び出すadd_サービス()は、上のBinderエンティティ参照をサービスに書き込み、名前でグローバルチェーンテーブルに追加します.
クライアントがサービスを問い合わせる必要がある場合:1)bio_get_string 16()サービス名2)do_find_サービス()は、グローバルチェーンテーブルsvclistを巡回し、サービス名に基づいて対応するサービスを見つけて返します.2)bio_put_ref(reply, ptr);ここでreplyはクライアントに返す必要がある構造体であり,ptrはターゲットBinderエンティティを指す.
binderに戻るparse関数では、実行:binder_send_reply()はBinderドライバに通知します.
Androidシステムで最も多く使われる通信メカニズムはBinderで、Binderは主にClient、Server、ServiceManager、Binderドライバから構成されています.Client、Service、ServiceManagerはユーザースペースで実行され、Binderドライバはカーネルスペースで実行されます.コアコンポーネントはBinderドライバであり、ServiceManagerはClientまたはServicesで通信する前にServiceManagerに連絡するサポート管理機能を提供します.ServiceManagerは、サーバを管理し、Clientにサーバを照会する機能を提供するデーモンです.
init.rc servicemanager , zygote
service servicemanager /system/bin/servicemanager
class core
user system
group system
critical
onrestart restart zygote
onrestart restart media
onrestart restart surfaceflinger
onrestart restart drm
ソースの場所:frameworks/base/cmds/servicemanager/service_manager.c
int main(int argc, char** argv)
{
struct binder_state *bs;
void* svcmgr = BINDER_SERVICE_MANAGER;
bs = binder_open(128*1024);
binder_become_context_manager(bs);
svcmgr_handle = svcmgr;
binder_loop(bs, svcmgr_handler);
return 0;
}
ここでmain関数には主に3つの機能があります.1)Binderデバイスファイルを開くには、まずこのstruct binder_を見てみましょう.state構造体struct binder_state{int fd;//ファイル記述子、/dev/binderデバイスvoid*mappedを開く;//デバイスファイル/dev/binderをプロセス空間の開始アドレスunsigned mapsizeにマッピングする;//メモリ空間のサイズをマッピングする};マクロ:#define BINDER_SERVICE_MANAGER(void*)0)は、ServiceManagerに対応するハンドルが0であり、表面自体がサーバ管理者であることを示します.他のServerプロセスハンドルの値は0より大きい.
struct binder_state* binder_open(unsigned mapsize)
{
struct binder_state* bs;
bs = malloc(sizeof(*bs));
bs->fd = open("/dev/binder", O_RDWR);
bs->mapsize = mapsize;
bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
return bs;
}
Binder , 128K
2)Binderドライバ自身がBinderコンテキスト管理者であることを伝える
int binder_become_context_manager(struct binder_state *bs)
{
return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}
BINDER_SET_CONTEXT_MGR
3)無線ループに入り、serverの役割を果たし、Clientの要求を待つ
void binder_loop(struct binder_state bs, binder_handler func)
{
struct binder_write_read bwr;
unsigned readbuf[32];
bwr.write_size = 0;
bwr.write_consumed = 0;
bwr.write_buffer = 0;
readbuf[0] = BC_ENTER_LOOPER; // LOOPER
// ioctl , Binder servicemanager loop
binder_write(bs, readbuf, sizeof(unsigned));
for(;;) {
bwr.read_size = sizeof(readbuf);
bwr.read_consumed = 0;
bwr.read_buffer = (unsigned)readbuf;
// Binder , IPC
ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
// binder_parse
binder_parse(bs, 0, readbuf, bwr.read_consumed, func);
}
}
struct binder_write_read :
struct binder_write_read{
signed long write_size;
signed long write_consumed; // bytes consumed by driver
unsigned long write_buffer;
signed long read_size;
signed long read_consumed; // bytes consumed by driver
unsigned long read_buffer;
};
int binder_parse(struct binder_state *bs, struct binder_io *bio, uint32_t *ptr,
uint32_t size, binder_handler func)
{
uint32_t *end = ptr + (size / 4);
while(ptr < end) {
uint32_t cmd = *ptr++;
switch(cmd) {
......
case BR_TRANSACTOIN:{ //
struct bindeer_txn *txn = (void*) ptr;
if(func) {
unsigned rdata[256/4];
struct binder_io msg;
struct binder_io reply;
bio_init(&reply, rdata, sizeof(rdata), 4);
bio_init_from_txn(&msg, txn);
ret = func(bs, txn, &msg, &reply);
binder_send_reply(bs, &reply, txn->data, res);
}
ptr += sizeof(*txn) / sizeof(uint32_t);
break;
}
case BR_REPLY: { //
struct binder_txn *txn = (void*)ptr;
if(bio) {
bio_init_from_txn(bio, txn);
bio = 0;
}else {
// to free buffer
}
ptr += sizeof(*txn) / sizeof(uint32_t);
r = 0;
break;
}
case BR_DEAD_BINDER: {
struct binder_death* death = (void*)*ptr++;
death->func(bs, death->ptr);
break;
}
...
}
}
return r;
}
/* binder_parse binder bindeer_txn ,
binder_io msg, svcmgr_handler , binder_io reply,
reply 。*/
struc binder_io
{
char* data; // read/write
uint32_t *offs; //
uint32_t data_avail; // data
uint32_t offs_avail; //
char* data0; // data
uint32_t *offs0; // buffer
uint32_t flags;
uint32_t unused;
};
svcmgr_handler, :
int svcmgr_handler(struct binder_state* bs, struct binder_txn *txn,
struct binder_io *msg, struct binder_io *reply)
{
struct svcinfo *si;
uint16_t *s;
unsigned len;
void* ptr;
uint32_t strict_policy;
if(txn->target != svcmgr_handler)
return -1; //
strict_policy = bio_get_uint32(msg);
s = bio_get_string16(msg, &len);
switch(txn->code) {
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
s = bio_get_string16(msg, &len); //
ptr = do_find_service(bs, s, len); //
bio_put_ref(reply, ptr);
return 0;
case SVC_MGR_ADD_SERVICE: //
s = bio_get_string16(msg, &len);
ptr = bio_get_ref(msg);
do_add_service(bs, s, len, ptr, txn->sender_euid);
bio_put_uint32(reply, 0); //
return 0;
....
}
return 0;
}
まず、BinderがどのようにBinder伝達メッセージのデータ構造を組織しているかを見なければなりません.Binderドライバを呼び出すとvoid*ptr構造体が得られ、binder_に強制的に変換されます.txn*txn,そしてこのtxnに基づいてBinderの入出力構造体binder_を得た.io *bio.最後に,要求を処理しても返信を送信しても,このbio構造を処理する.我々のBinder通信のbinder構造はbinder_objectが組織しbinder_を指すio構造内data.まず、BinderがどのようにBinder伝達メッセージのデータ構造を組織しているかを見なければなりません.Binderドライバを呼び出すとvoid*ptr構造体が得られ、binder_に強制的に変換されます.txn*txn,そしてこのtxnに基づいてBinderの入出力構造体binder_を得た.io *bio.最後に,要求を処理しても返信を送信しても,このbio構造を処理する.我々のBinder通信のbinder構造はbinder_objectが組織しbinder_を指すio構造内data.
struct binder_object
{
uint32_t type;
uint32_t flags;
void* pointer;
void* cookie;
};
上のbinder_object構造体の内容は、私たちのコードのbio_に順次対応しています.get_uint32(msg); bio_get_string16(msg, &len); bio_get_string16(msg, &len); bio_get_ref(msg); 上のbinder_object構造体の内容は、私たちのコードのbio_に順次対応しています.get_uint32(msg); bio_get_string16(msg, &len); bio_get_string16(msg, &len); bio_get_ref(msg);
クライアントがサービスを追加する必要がある場合:SVC_MGR_ADD_SERVICE 1)まずbio_を呼び出すget_string 16()binder_からioでサービス名を取得します.2)bio_を呼び出すget_ref()binder_からioでサービスを受けるbinderエンティティstruct binder_object
void* bio_get_ref(struct binder_io* bio)
{
struct binder_object* obj;
obj = _bio_get_obj(bio);// void* ptr = bio->data;
return obj->pointer;
}
3)do_を呼び出すadd_サービス()は、上のBinderエンティティ参照をサービスに書き込み、名前でグローバルチェーンテーブルに追加します.
int do_add_service(struct binder_state* bs, uint16_t *s, unsigned len, void* ptr, unsigned uid)
{
struct svcinfo *si;
svc_can_register(uid, s); //
si = find_svc(s, len);
// ,
si = malloc(sizeof(*si) + (len+1)*sizeof(uin16_t));
si->ptr = ptr; // binder_object pointer Binder
memcpy(si->name, s, (len+1)*sizeof(uint16_t));
si->name[len] = '\0';
si->death.func = svcinfo_death;
si->death.ptr = si;
si->next = svclist;
svclist = si;
binder_acquire(bs, ptr);
binder_link_to_death(bs, ptr, &si->death);
return 0;
}
クライアントがサービスを問い合わせる必要がある場合:1)bio_get_string 16()サービス名2)do_find_サービス()は、グローバルチェーンテーブルsvclistを巡回し、サービス名に基づいて対応するサービスを見つけて返します.2)bio_put_ref(reply, ptr);ここでreplyはクライアントに返す必要がある構造体であり,ptrはターゲットBinderエンティティを指す.
void bio_put_ref(struct binder_io* bio, void* ptr)
{
struct binder_object *obj;
obj = bio_alloc(bio);
obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
obj->type = BINDER_TYPE_HANDLE;
obj->pointer = ptr;
obj->cookie = 0;
}
binderに戻るparse関数では、実行:binder_send_reply()はBinderドライバに通知します.