Android 개발 의 serviceManager 분석
8443 단어 androidservicemanager
안 드 로 이 드 시스템 에서 가장 많이 사용 되 는 통신 메커니즘 은 바로 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 드라이버.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Kotlin의 기초 - 2부지난 글에서는 Kotlin이 무엇인지, Kotlin의 특징, Kotlin에서 변수 및 데이터 유형을 선언하는 방법과 같은 Kotlin의 기본 개념에 대해 배웠습니다. 유형 변환은 데이터 변수의 한 유형을 다른 데이터...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.