Android開發之serviceManager分析


Android 開發之serviceManager分析

        在Android系統中用到最多的通信機制就是Binder,Binder主要由Client、Server、ServiceManager和Binder驅動程序組成。其中Client、Service和ServiceManager運行在用戶空間,而Binder驅動程序運行在內核空間。核心組件就是Binder驅動程序了,而ServiceManager提供輔助管理的功能,無論是Client還是Service進行通信前首先要和ServiceManager取得聯系。而ServiceManager是一個守護進程,負責管理Server並向Client提供查詢Server的功能。

 

在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函數主要有三個功能:
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_string16()從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_service()將上面的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_string16() 獲得服務名字
2)do_find_service() 遍歷全局鏈表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驅動程序。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM