Ubuntu, Android

[Android] Binder

vhxpffltm 2019. 10. 19. 17:59

Android Architecture

먼저 안드로이드의 구조이다. 여기서 시스템 아키텍처인 Binder IPC에 대해 정리하고자 한다.

https://source.android.com/devices/architecture

 

 

Binder IPC(Binder Inter Process Communcation)

모든 시스템 서비스가 서버 프로세스 형태로 제공되기 때문에 다른 프로세스로 요청과 응답을 보내는 메커니즘이 필요한데, 이 메커니즘이 바인더(Binder)이다. 

 

예를 들어 시스템 서비스와 어플리케이션의 상호작용에서 음악 애플리케이션에서 음악을 들으면 오디오 Flinger 서비스에서 제공하는 play() 기능을 사용할 것이다. 하지만 이 오디오 Flinger 서비스는 '미디어 서버'에서 동작하고 음악 애플리케이션은 자신의 프로세스에서 동작 중이기 때문에 이 둘 사이에 play() 함수호출을 전달하는 Binder IPC가 필요하다.

 

 

Binder IPC를 사용하는 이유는 성능 때문이다. Android의 모든 시스템 기능은 서버 프로세스로 제공되기 때문에 프로세스 사이에 최적화된 통신 방법이 필요하고 그 결과가 바인더이다. 바인더는 모든 프로세스가 공유하는 커널 메모리를 참조하게 함으로써 메모리 복사 오버헤드를 최소화한다. 뿐만 아니라 C++을 이용해 작성된 RPC(Remote Procedure Call) 프레임워크를 제공하여 생산성이 높다.

 

RPC : RPC는 Remote Procedure Call , 원격 호출 개념이다, 네트워크상에 있는 함수등을 직접 호출한다. 간단한 예로 A, B 2개의 프로세스가 있고 foo() 라는 Interface를 공유한다고 할때, A Process에서 foo()함수를 호출하면 B Process의 foo() 함수가 호출되어 실행하는것을 말한다.

 

 

이정도로 정리할 수 있다.

 

바인더 드라이버의 커널 공간은 모든 프로세스들이 공유한다. 바인더 드라이버의 역할은 각 프로세스가 매핑해 놓은 메모리 주소와 커널 공간의 메모리 주소를 변환하여 참조해 사용할 수 있도록 하는 것이다.

 

Linux에서 사용하는 표준 방법인 ioctl 시스템 함수를 이용해 바인더 드라이버를 사용할 수 있다. 이와 같은 일련의 메커니즘을 바인더 IPC라고 한다.

 

바인더 IPC를 이용해 주고받는 데이터를 가공해서 RPC(Remote Procedure Call)로 만들어 주는 C++ 프레임워크가 제공되고 시스템 서비스를 만들 때 사용한다. 다른 프로세스에서 제공하는 함수를 마치 내 함수처럼 사용할 수 있게 되는 것이다.

 

 

위의 Context Manager는 시스템 서비스의 위치를 관리하는 프로세스이다. 서비스 등록, 검색 등의 기능을 구현하고 있으며, servicemanager 프로세스로 동작하는 서비스이다.

 

service manager는 서비스를 등록하고 검색하는 기능을 제공한다.  

 

 

그렇다면 위 과정중, Binder driver 호출과정을 직접 코드로 살펴보자.

 

/framework/native/libs/binder/ProcessState.cpp

 

 

함수 선언부에 보면 mVMStartFDmVMStart(open_driver(driver)를 바로 호출하고 있다.

그리고 이후 여러 함수를 호출하고 if() 이후에 mmap(...) 함수를 호출하고 있다. mmap(...)는 커널 내에서 Binder 데이터를 수신하기 위한 공유 공간을 확보한다.

 

 

open_driver() 함수는 binder의 file descriptor을 반환하며. 이 함수를 통해 Binder가 호출된다.

 

 

 

mDriverFD(open_driver(driver)) 

:: processState 바로 위로 가면 위의 함수를 만날 수 있다. 여기서 ioctl() 함수를 호출하는것을 볼 수 있다. 이 함수를 통해 이제 Binder Binder가 호출된다. 

 

status_t result = ioctl(fd, BINDER_VERSION, &vers)

이 함수로 Binder의 입출력 설정을 바꾸어준다.  

 

BINDER_VERSION에 관한 내용은 bionic\libc\kernel\uapi\linux\android 에서 확인할 수 있다.

ioctl에 관한 헤더파일은  bionic\libc\kernel\uapi\asm-generic

cpp 파일은 bionic\libc\bionic\ioctl.cpp  에서 확인할 수 있다.

 

result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);

Binder의 최대 쓰레드 수를 BINDER_SET_MAX_THREADS의 값인 15개로 한 후 이를 ioctl을 통해 설정한다.


 

 

Reference

https://elecs.tistory.com/92

https://d2.naver.com/helloworld/47656

도서 : 안드로이드 미디어 프레임워크