Android 시스템 프로 세 스 간 통신(IPC)메커니즘 Binder 의 서버 와 Client 가 Service Manager 인 터 페 이 스 를 얻 는 길

앞의 글 에서 Service Manager 가 어떻게 Binder 체제 의 데 몬 이 되 었 는 지 소개 했다.데 몬 으로서 Service Manager 의 직책 은 당연히 Server 와 Client 를 위 한 서비스 입 니 다.그렇다면 서버 와 Client 는 어떻게 Service Manager 인 터 페 이 스 를 얻어 서 제공 하 는 서 비 스 를 누 릴 수 있 습 니까?본 고 는 Server 와 Client 가 Service Manager 를 얻 는 과정 을 간략하게 분석 할 것 이다.
        본 고 를 읽 기 전에 독자 가 먼저 읽 기 를 바란다Service Manager 가 안 드 로 이 드 프로 세 스 간 통신(IPC)메커니즘 Binder 데 몬 이 됨한 글 에서 언급 한 참고 자료Android 프로 세 스 간 통신(IPC)메커니즘 Binder 개요 및 학습 계획이렇게 하면 본 고 에 대한 이 해 를 강화 할 수 있다.
        Service Manager 는 Binder 체제 에서 데 몬 의 역할 을 하 는 동시에 Server 역할 도 하 는 것 을 알 고 있 습 니 다.그러나 일반적인 Server 와 는 다 릅 니 다.일반적인 서버 의 경우 클 라 이언 트 가 서버 의 원 격 인 터 페 이 스 를 얻 으 려 면 Service Manager 원 격 인터페이스 에서 제공 하 는 getService 인 터 페 이 스 를 통 해 얻 어야 합 니 다.이 자체 가 Binder 체 제 를 사용 하여 프로 세 스 간 통신 을 하 는 과정 입 니 다.한편,Service Manager 라 는 서버 에 있어 Client 가 Service Manager 원 격 인 터 페 이 스 를 얻 으 려 면 프로 세 스 간 통신 체 제 를 통 해 얻 을 필요 가 없습니다.Service Manager 원 격 인 터 페 이 스 는 특수 한 Binder 참조 이기 때문에 인용 핸들 은 0 일 것 입 니 다.
        Service Manager 원 격 인 터 페 이 스 를 가 져 오 는 함 수 는 default ServiceManager 입 니 다.이 함 수 는 frameworks/base/include/binder/IServiceManager.h 파일 에 있 습 니 다.
          sp 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; 
} 
        gDefault ServiceManager Lock 과 gDefault ServiceManager 는 전역 변수 로 프레임 워 크/base/libs/binder/static.cpp 파일 에 정 의 됩 니 다.

Mutex gDefaultServiceManagerLock; 
sp<IServiceManager> gDefaultServiceManager; 
        이 함수 에서 알 수 있 듯 이 gDefaultServiceManager 는 단일 모드 입 니 다.defaultServiceManager 함 수 를 호출 할 때 gDefaultServiceManager 가 만 들 어 졌 으 면 바로 돌아 갑 니 다.그렇지 않 으 면 interface 를 통 해cast(ProcessState:self()->getContextObject(NULL)를 만 들 고 gDefault ServiceManager 전역 변수 에 저장 합 니 다.
       인 터 페 이 스 를 계속 소개 하고 있 습 니 다cast(ProcessState:self()->getContextObject(NULL)가 실현 되 기 전에 클래스 맵 을 살 펴 보면 Service Manager 원 격 인터페이스의 생 성 과정 을 알 수 있 습 니 다.

        참고 자료 인 Android 의 심오 한 Binder 메커니즘 을 참고 한 독자 들 은 이 그림 을 쉽게 이해 할 수 있 을 것 이다.이 그림 은 BpServiceManager 클래스 가 BpInterface클래스 를 계승 하고 BpInterface 는 템 플 릿 클래스 로 frameworks/base/include/binder/IInterface.h 파일 에 정의 되 어 있 음 을 나타 낸다.

template<typename INTERFACE> 
class BpInterface : public INTERFACE, public BpRefBase 
{ 
public: 
 BpInterface(const sp<IBinder>& remote); 
 
protected: 
 virtual IBinder* onAsBinder(); 
}; 
        IServiceManager 클래스 는 IInterface 클래스 를 물 려 받 았 고,IInterface 클래스 와 BpRefBase 클래스 는 각각 RefBase 클래스 를 물 려 받 았 다.BpRefBase 클래스 에 멤버 변수 mRemote 가 있 습 니 다.형식 은 IBinder*이 고 실현 클래스 는 BpBinder 입 니 다.이 는 Binder 참조,참조 핸들 값 은 BpBinder 클래스 의 mHandle 멤버 변수 에 저 장 됩 니 다.BpBinder 클래스 는 IPCThreadState 클래스 를 통 해 Binder 드라이버 와 상호 작용 하고 IPCThreadState 는 구성원 변수 mProcess 를 통 해/dev/binder 장치 파일 을 엽 니 다.mProcess 구성원 변수의 유형 은 ProcessState 입 니 다.ProcessState 클래스 는 장치/dev/binder 를 열 면 mDriverFD 구성원 변수 에 파일 설명 부 호 를 열 어 나중에 사용 할 수 있 도록 합 니 다.
        이러한 개념 을 이해 한 후에 Service Manager 원 격 인 터 페 이 스 를 만 드 는 과정 을 계속 분석 할 수 있 습 니 다.최종 목적 은 BpServiceManager 인 스 턴 스 를 만 들 고 IServiceManager 인 터 페 이 스 를 되 돌려 주 는 것 입 니 다.Service Manager 원 격 인 터 페 이 스 를 만 드 는 것 은 주로 다음 문장 입 니 다.
gDefaultServiceManager = interface_cast
    ProcessState::self()->getContextObject(NULL));  
        짧 아 보이 지만 현묘 한 기 회 를 숨 기 고 안 드 로 이 드 의 심오 한 Binder 체제 라 는 참고 자 료 를 읽 을 수 있 습 니 다.여기 서 간략하게 설명 하 겠 습 니 다.
        먼저 ProcessState::self 함수,self 함 수 는 ProcessState 의 정적 구성원 함수 입 니 다.이 변 수 는 전체 국면 에서 유일한 ProcessState 인 스 턴 스 변 수 를 되 돌려 주 는 역할 을 합 니 다.바로 단일 모드 입 니 다.이 변 수 는 gProcess 라 고 합 니 다.gProcess 가 생 성 되 지 않 으 면 생 성 작업 을 수행 합 니 다.ProcessState 의 구조 함수 에 서 는 open 파일 조작 함 수 를 통 해 장치 파일/dev/binder 를 열 고 돌아 오 는 장치 파일 설명 자 는 구성원 변수 mDriverFD 에 존재 합 니 다.
        이 어 gProcess->getContextObject 함 수 를 호출 하여 핸들 값 이 0 인 Binder 참조,즉 BpBinder 를 얻 었 습 니 다.따라서 Service Manager 원 격 인 터 페 이 스 를 만 드 는 문 구 는 다음 과 같이 간소화 할 수 있 습 니 다.
gDefaultServiceManager = interface_cast(new BpBinder(0));  
        함수 인터페이스 다시 보기cast의 실현 은 템 플 릿 함수 로 framework/base/include/binder/IInterface.h 파일 에 정의 합 니 다.

template<typename INTERFACE> 
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj) 
{ 
 return INTERFACE::asInterface(obj); 
} 
    여기 인 터 페 이 스 는 IServiceManager 입 니 다.그래서 IServiceManager:asInterface 함 수 를 호출 했 습 니 다.IServiceManager::asInterface 는 DECLARE 를 통 해META_INTERFACE(ServiceManager)매크로 는 IServiceManager 클래스 에서 설명 합 니 다.framework/base/include/binder/IServiceManager.h 파일 에 있 습 니 다.
DECLARE_META_INTERFACE(ServiceManager);  
        다음으로:

#define DECLARE_META_INTERFACE(ServiceManager)        \ 
 static const android::String16 descriptor;       \ 
 static android::sp<IServiceManager> asInterface(     \ 
 const android::sp<android::IBinder>& obj);       \ 
 virtual const android::String16& getInterfaceDescriptor() const; \ 
 IServiceManager();             \ 
 virtual ~IServiceManager();           
  
  IServiceManager::asInterface 의 실현 은 IMPLEMENTMETA_INTERFACE(ServiceManager,"android.os.IServiceManager")매크로 는 framework/base/libs/binder/IServiceManager.cpp 파일 에 있 습 니 다.
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");  
       다음으로:

#define IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager")     \ 
 const android::String16 IServiceManager::descriptor("android.os.IServiceManager");  \ 
 const android::String16&         \ 
 IServiceManager::getInterfaceDescriptor() const {          \ 
 return IServiceManager::descriptor;             \ 
 }                      \ 
 android::sp<IServiceManager> IServiceManager::asInterface(        \ 
 const android::sp<android::IBinder>& obj)            \ 
 {                      \ 
 android::sp<IServiceManager> intr;              \ 
 if (obj != NULL) {                  \ 
 intr = static_cast<IServiceManager*>(             \ 
 obj->queryLocalInterface(                \ 
 IServiceManager::descriptor).get());             \ 
 if (intr == NULL) {                 \ 
 intr = new BpServiceManager(obj);              \ 
 }                      \ 
 }                      \ 
 return intr;                   \ 
 }                      \ 
 IServiceManager::IServiceManager() { }             \ 
 IServiceManager::~IServiceManager() { }  
         이 코드 를 쓴 직원 은 마이크로소프트 에서 구 글 로 이 직 한 것 으로 추정 된다.여기 서 우 리 는 IServiceManager::asInterface 의 실현 에 관심 을 가지 고 있 습 니 다.

android::sp<IServiceManager> IServiceManager::asInterface(const android::sp<android::IBinder>& obj)            
{                      
 android::sp<IServiceManager> intr;              
  
 if (obj != NULL) {                  
  intr = static_cast<IServiceManager*>(             
     obj->queryLocalInterface(IServiceManager::descriptor).get()); 
   
  if (intr == NULL) {     
   intr = new BpServiceManager(obj);           
  }           
 } 
 return intr;         
}  
         여기 들 어 오 는 인자 obj 는 방금 만 든 new BpBinder(0)입 니 다.BpBinder 클래스 의 구성원 함수 query LocalInterface 는 기본 클래스 인 IBinder,IBinder 를 계승 합 니 다.:query LocalInterface 함 수 는 framework/base/libs/binder/Binder.cpp 파일 에 있 습 니 다.

sp<IInterface> IBinder::queryLocalInterface(const String16& descriptor) 
{ 
 return NULL; 
} 
         이 를 통 해 알 수 있 듯 이 IServiceManager:asInterface 함수 에서 다음 문 구 를 호출 합 니 다.
                    intr = new BpServiceManager(obj);   
         즉:
                    intr = new BpServiceManager(new BpBinder(0));   
        default ServiceManager 함수 로 돌아 가면 최종 결 과 는 다음 과 같 습 니 다.
           gDefaultServiceManager = new BpServiceManager(new BpBinder(0));  
       이렇게 해서 Service Manager 원 격 인 터 페 이 스 를 만 들 었 습 니 다.본질 적 으로 BpServiceManager 이 고 핸들 값 이 0 인 Binder 참조 가 포함 되 어 있 습 니 다.
        Android 시스템 의 Binder 시스템 에서 Server 와 Client 는 이 Service Manager 원 격 인 터 페 이 스 를 받 은 후에 어떻게 사용 합 니까?
        서버 에 있어 서 는 IServiceManager:addService 라 는 인 터 페 이 스 를 호출 하여 Binder 드라이버 와 상호작용 을 하 는 것 입 니 다.즉,BpServiceManager:addService 를 호출 하 는 것 입 니 다.그리고 BpServiceManager::addService 는 기본 클래스 인 BpRefBase 의 구성원 함수 reote 를 통 해 원래 만 든 BpBinder 인 스 턴 스 를 얻 고 이 어 BpBinder:transact 구성원 함 수 를 호출 합 니 다.BpBinder::transact 함수 에서 IPCThreadState::transact 구성원 함수 가 호출 됩 니 다.여기 가 최종 적 으로 Binder 드라이버 와 상호작용 하 는 곳 입 니 다.앞의 클래스 를 기억 해 보 세 요.IPCThreadState 는 PorcessState 형식의 중간 변수 mProcess 가 있 습 니 다.mProcess 는 구성원 변수 mDriverFD 가 있 습 니 다.장치 파일/dev/binder 의 파일 설명자 입 니 다.따라서 IPCThreadState 는 파일/dev/binder 의 파일 설명 자 를 간접 적 으로 가지 고 있 는 것 과 같 습 니 다.그래서...Binder 드라이버 와 상호작용 을 할 수 있 습 니 다.
       Client 에 있어 서 는 IServiceManager:getService 라 는 인 터 페 이 스 를 호출 하여 Binder 드라이버 와 상호작용 을 하 는 것 입 니 다.구체 적 인 과정 에서 상기 서버 가 Service Manager 를 사용 하 는 방법 은 같 습 니 다.여 기 는 더 이상 언급 하지 않 겠 습 니 다.
      IServiceManager:addService 와 IServiceManager:getService 라 는 두 함수 의 구체 적 인 실현 은 다음 두 편의 글 에서 Binder 드라이버 라 는 층 에 깊이 들 어가 상세 한 소스 코드 분석 을 하여 Binder 프로 세 스 간 통신 체 제 를 잘 이해 할 수 있 도록 하 겠 습 니 다.주목 하 시기 바 랍 니 다.
        이상 은 안 드 로 이 드 바 이 더 통신 자료 에 대한 정리 입 니 다.추 후 관련 자 료 를 계속 보충 하 겠 습 니 다.본 사이트 에 대한 여러분 의 지지 에 감 사 드 립 니 다!

좋은 웹페이지 즐겨찾기