Android 개발 의 serviceManager 분석

8443 단어 androidservicemanager
원본 링크:http://www.cnblogs.com/dyllove98/archive/2013/08/01/3231080.html       
안 드 로 이 드 시스템 에서 가장 많이 사용 되 는 통신 메커니즘 은 바로 Binder 이다. Binder 는 주로 Client, Server, ServiceManager 와 Binder 드라이버 로 구성 된다.그 중에서 Client, Service, ServiceManager 는 사용자 공간 에서 실행 되 고 Binder 드라이버 는 커 널 공간 에서 실 행 됩 니 다.핵심 구성 요 소 는 Binder 드라이버 입 니 다. ServiceManager 는 보조 관리 기능 을 제공 합 니 다. Client 든 Service 든 통신 하기 전에 먼저 ServiceManager 와 연락 해 야 합 니 다.ServiceManager 는 서버 를 관리 하고 클 라 이언 트 에 게 서버 를 조회 하 는 기능 을 제공 하 는 데 몬 입 니 다.
 
 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 / servicemanager.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 binderstate 구조 체 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 역할 을 하 며 클 라 이언 트 의 요청 을 기다린다.
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 를 얻 었 습 니 다. 마지막 으로 우 리 는 요청 을 처리 하 든 답장 을 보 내 든 모두 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 uint 32 (msg), bio get string 16 (msg, & len), bio get string 16 (msg, & len), bio get ref (msg), 위의 binder object 구조 체 내용 은 순서대로 우리 코드 중의 bio get uint 32 (msg), bio get string 16 (msg, & len), bio get string 16 (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 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 string 16 () 은 서비스 이름 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 드라이버.

좋은 웹페이지 즐겨찾기