안드로이드 Binder Source Analysis (바인더 소스 분석)

2013. 12. 30. 21:10Programing/Android / Java

Binder를 사용하는데 굳이 Binder의 동작에 대해 알 필요는 없다. 그러나 Binder에 대해 정확히 알면 활용면에서도 그렇고 디버깅에서도 많은 도움이 된다. 그리고 세상에 알아서 나쁜 지식은 없다. 관련된 함수를 모두 분석하진 않겠다. 오히려 더 어렵게 느껴질 뿐이다. 어떤 역할을 하는지 알면 필요할 때 찾아보면 될 것이다.


 Binder는 service_manager와 함께 시작된다. service_manager의 main함수를 살펴보자. binder_open()함수를 통해서 "/dev/binder"를 open하고 binder_loop()함수를 실행하는데, 이 때 인자로 binder_state 포인터 변수와 BINDER_SERVICE_MANAGER를 넘긴다. 이것은 필요에 따라 실행되는 프로세스가 아닌, 안드로이드 부팅과 함께 실행되어 종료될때까지 동작한다.


<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);
 
    if (binder_become_context_manager(bs)) {
        LOGE("cannot become context manager (%s)\n", strerror(errno));
        return -1;
    }
 
    svcmgr_handle = svcmgr;
    binder_loop(bs, svcmgr_handler);
    return 0;
}


 BINDER_SERVICE_MANAGER는 다음과 같이 정의되어있다.


<frameworks/base/cmds/servicemanager/binder.h>
/* the one magic object */
#define BINDER_SERVICE_MANAGER ((void*) 0)

 


binder_loop()함수에서는 무한루프에서 ioctl()함수와 binder_parse()함수를 호출한다. 뭐 ioctl()함수로 메시지를 가져오고 binder_parse()함수로 parsing한 후 적절한 동작을 수행할 것이다.


<frameworks/base/cmds/servicemanager/binder.c>
void binder_loop(struct binder_state *bs, binder_handler func) 
{ 
    int res; 
    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; 
    binder_write(bs, readbuf, sizeof(unsigned)); 
 
    for (;;) { 
        bwr.read_size = sizeof(readbuf); 
        bwr.read_consumed = 0; 
        bwr.read_buffer = (unsigned) readbuf;
 
        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); 
 
        if (res < 0) { 
            LOGE("binder_loop: ioctl failed (%s)\n", strerror(errno)); 
            break; 
        } 
 
        res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func); 
        if (res == 0) { 
            LOGE("binder_loop: unexpected reply?!\n"); 
            break; 
        } 
        if (res < 0) { 
            LOGE("binder_loop: io error %d %s\n", res, strerror(errno)); 
            break; 
        } 
    } 
}



 그럼 어떻게 메시지가 Binder device driver로 보내지는지, 그리고 parsing한 후 보내야할 프로세스로 메시지를 보내는지를 알아보자.
 Binder 통신을 하기 전에 먼저 메시지를 수신할 프로세스는 자신을 service_manager에 등록해야한다. service_manager가 알지도 못하는 프로세스로 메시지를 보낼 순 없으니 말이다. service_manager에 등록하기 위해서 IServiceManager의 인스턴스를 얻어야 하는데 이때 사용하는 함수가 defaultServiceManager()이다.

<frameworks/base/libs/binder/IServiceManager.cpp>
sp<IServiceManager> defaultServiceManager() 
{ 
    if (gDefaultServiceManager != NULL) return gDefaultServiceManager; 
    { 
        AutoMutex _l(gDefaultServiceManagerLock); 
        if (gDefaultServiceManager == NULL) { 
            gDefaultServiceManager = interface_cast<IServiceManager>( 
                ProcessState::self()->getContextObject(NULL)); 
        } 
    } 
    return gDefaultServiceManager; 
}



 IServiceManager 인스턴스를 통해서 addService()함수를 이용하여 프로세스를 등록한다. 이제 메시지를 수신할 프로세스를 service_manager에 등록했으니 메시지가 있으면 프로세스의 onTransact()함수를 호출할 것이다. 그럼 메시지를 보내는 것은 어떻게 될까. addService()가 있으니 반대로 getService()함수가 있다. getService 함수로 메시지를 수신할 프로세스의 Binder 인스턴스를 획득하고 transact()함수를 호출한다.

 

 

출처 : http://marujj.tistory.com/10