天天看點

ServiceManager源碼流程

ServiceManager啟動于單獨的程序,要早于zygote啟動,啟動時首先運作到service_manager.c的main函數,對binder進行初始化并進入binderloop

int main(int argc, char **argv){
	bs = binder_open(128*1024);
	binder_become_context_manager(bs);
	
	binder_loop(bs, svcmgr_handler);
}
           

binder_open函數定義在binder.c中,打開了binder驅動并進行記憶體映射

bs->fd = open("/dev/binder", O_RDWR);
bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
           

binder_become_context_manager同樣定義在binder.c中,是向驅動注冊0号節點成為manager

ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
           

binder_loop也是定義在binder.c中,是一個死循環,通過ioctl監聽binder調用,如果有消息,進行解析

res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
           

binder_loop中傳入的svcmgr_handler是一個函數指針(回調),經過一層一層傳遞,傳遞到binder_parse最後一個參數func,在binder_parse中,根據binder指令對func進行回調

int binder_parse(struct binder_state *bs, struct binder_io *bio,uintptr_t ptr, size_t size, binder_handler func){
	switch(cmd){
		case BR_TRANSACTION:
			res = func(bs, txn, &msg, &reply);  
			binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);
			break;
		}
}
           

svcmgr_handler在service_manager.c中,根據不同的指令碼對查找或添加服務進行操作

int svcmgr_handler(struct binder_state *bs,struct binder_transaction_data *txn,struct binder_io *msg,struct binder_io *reply){
	case SVC_MGR_GET_SERVICE:
	case SVC_MGR_CHECK_SERVICE:
		// 拿到服務名字
		s = bio_get_string16(msg, &len);  
		// 查找拿到節點
		handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid); 
		 // 通過binder回複結果
		bio_put_ref(reply, handle);
		break;

	case SVC_MGR_ADD_SERVICE:
		s = bio_get_string16(msg, &len);
		// 添加service
		do_add_service(bs, s, len, handle, txn->sender_euid,allow_isolated, txn->sender_pid);
		break;

	case SVC_MGR_LIST_SERVICES:
		// 周遊
		svc_can_list(txn->sender_pid)
		// 列印
		bio_put_string16(reply, si->name);
		break;
}
           

do_find_service函數内部調用find_svc對svclist進行周遊,找到名字相同的進行傳回

for (si = svclist; si; si = si->next) {
        if ((len == si->len) &&
            !memcmp(s16, si->name, len * sizeof(uint16_t))) {
            return si;
        }
    }
           

do_add_service同樣調用find_svc對svclist進行周遊,如果沒有找到,就添加一個節點

si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
// 經過一系列參數設定,添加進來
si->next = svclist;
svclist = si;
           

C層次的ServiceManager大概流程就是這樣,接下來看java層的ServiceManager,這個類主要是getService方法

IBinder service = sCache.get(name);
if (service != null) {
    return service;
} else {
	return getIServiceManager().getService(name);
}
           

如果緩存中有要查詢的binder,就直接傳回,否則就調用native的servicemanager進行查詢,這裡是用binder進行查詢的,首先獲得ServiceManager的binder,在調用Service_manager.c的方法進行查詢,添加

繼續閱讀