구체적인 예로 안드로이드 시스템의 귀속 메커니즘을 깊이 있게 분석하다
Binder는 안드로이드 시스템에서 프로세스 간 통신을 실현하는 핵심 메커니즘으로 그 본질은 일종의 Proxy 모델의 구체적인 실현이다. 예를 들어COM,CORBA와 같다.
Proxy 모델의 기본 사상은 클라이언트 프로그램이 어떤 방식을 통해 서버 측의 프록시 대상을 얻어 모든 서버 측에 대한 서비스 요청을 이 프록시 대상에게 보내고 이 프록시 대상은 서버 측과 통신하는 것을 책임진다는 것이다.클라이언트의 측면에서 볼 때 액세스 에이전트 대상은 다른 로컬 대상을 방문하는 것과 같다.서버 프록시 대상은 모든 프로세스 간의 통신 세부 사항을 차단합니다.
본고는 구체적인 예를 제시한 다음에 이 예를 바탕으로 안드로이드 시스템의 귀속 메커니즘을 깊이 있게 분석할 계획이다.
예: 시스템 서비스 Example Service가 새로 추가되었습니다. 이 서비스는 성형 파라미터를 받아들여 그 값을 100으로 추가하고 되돌려줍니다.클라이언트 응용 프로그램은 이 서비스를 사용하여 1+100의 값을 계산합니다.
코드1: 시스템 서비스 Example 서비스의 구체적인 실현
// File: ExampleService.h
#ifndef ANDROID_EXAMPLE_SERVICE_H
#define ANDROID_EXAMPLE_SERVICE_H
#include <utils/threads.h>
#include <utils/RefBase.h>
#include <binder/IInterface.h>
#include <binder/BpBinder.h>
#include <binder/Parcel.h>
namespace android {
class ExampleService : public BBinder
{
mutable Mutex mLock;
int32_t mNextConnId;
public:
static int instantiate();
ExampleService();
virtual ~ExampleService();
virtual status_t onTransact(uint32_t, const Parcel&, Parcel*, uint32_t);
};
}; //namespace
#endif
// File: ExampleService.cpp
#include "ExampleService.h"
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
namespace android {
static struct sigaction oldact;
static pthread_key_t sigbuskey;
int ExampleService::instantiate()
{
LOGE("ExampleService instantiate");
// ServiceManager addService , ServiceManager ,
int r = defaultServiceManager()->addService(String16("byn.example"), new ExampleService());
LOGE("ExampleService r = %d/n", r);
return r;
}
ExampleService::ExampleService()
{
LOGV("ExampleService created");
mNextConnId = 1;
pthread_key_create(&sigbuskey, NULL);
}
ExampleService::~ExampleService()
{
pthread_key_delete(sigbuskey);
LOGV("ExampleService destroyed");
}
// BBinder , BBinder onTransact 。 Service , Service onTransact
status_t ExampleService::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code)
{
case 0: {
pid_t pid = data.readInt32();
int num = data.readInt32();
num = num + 100;
reply->writeInt32(num);
return NO_ERROR;
}
break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
}; //namespace
# File: Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= /
ExampleService.cpp
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
LOCAL_SHARED_LIBRARIES := /
libutils libbinder
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE := libExample
include $(BUILD_SHARED_LIBRARY)
/framework/android/src/frameworks/base 아래에 새 폴더 Example Service를 만듭니다. 이 세 개의 파일을 이 폴더에 복사합니다.
코드 2: Example Service를 실행하는 응용 프로그램
// File: ExampleServer.cpp
#include <sys/types.h>
#include <unistd.h>
#include <grp.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h>
#include <private/android_filesystem_config.h>
#include "../ExampleService/ExampleService.h"
using namespace android;
int main(int argc, char** argv)
{
sp<ProcessState> proc(ProcessState::self()); // Binder , ProcessState
sp<IServiceManager> sm = defaultServiceManager();
LOGI("ServiceManager: %p", sm.get());
ExampleService::instantiate();
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
return 0;
}
# File: Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= /
ExampleServer.cpp
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
LOCAL_SHARED_LIBRARIES := /
libutils libbinder libExample
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE := ExampleServer
include $(BUILD_EXECUTABLE)
/framework/android/src/frameworks/base 아래에 새 폴더 Example Server를 만들고 두 파일을 이 폴더로 복사합니다.
코드 3: Example Service를 사용하는 클라이언트 응용 프로그램
// File: Example.h
#ifndef ANDROID_BYN_EXAMPLE_H
#define ANDROID_BYN_EXAMPLE_H
namespace android
{
class Example {
public:
void add100(int n);
private:
static const void getExampleService();
};
}; //namespace
#endif // ANDROID_BYN_EXAMPLE_H
// File: Example.cpp
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include "Example.h"
namespace android
{
sp<IBinder> binder;
void Example::add100(int n)
{
getExampleService();
Parcel data, reply;
int answer;
data.writeInt32(getpid());
data.writeInt32(n);
LOGE("BpExampleService::create remote()->transact()/n");
binder->transact(0, data, &reply);
answer = reply.readInt32();
printf("answner=%d/n", answer);
return;
}
const void Example::getExampleService()
{
sp<IServiceManager> sm = defaultServiceManager();
binder = sm->getService(String16("byn.example"));
LOGE("Example::getExampleService %p/n",sm.get());
if (binder == 0) {
LOGW("ExampleService not published, waiting...");
return;
}
}
}; //namespace
using namespace android;
int main(int argc, char** argv)
{
Example* p = new Example();
p->add100(1);
return 0;
}
# File: Example
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= /
Example.cpp
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
LOCAL_SHARED_LIBRARIES := /
libutils libbinder libExample
LOCAL_PRELINK_MODULE := false
LOCAL_MODULE := Example
include $(BUILD_EXECUTABLE)
/framework/android/src/frameworks/base 아래에 새 폴더 Example을 만들고 세 개의 파일을 이 폴더로 복사합니다.
Build 전체 Android 시스템에는 각각 세 개의 파일이 생성됩니다.
/system/lib/libExample.so
/system/bin/ExampleServer
/system/bin/Example
그리고 저희가 새로 추가한 Example 서비스 시스템 서비스를 시작하고 클라이언트 프로그램을 시작하여 실행 결과를 검증합니다.
$> adb shell
# cd/system/bin
# ./ExampleServer &
# ./Example
answer=101
다음 몇 편의 글에서 우리는 이 예를 바탕으로 안드로이드 시스템의 Binder 메커니즘의 각 부분을 깊이 있게 분석할 것이다.
참조 자료:
1. 클라우드 워킹 블로그:http://my.unix-center.net/~Simon_fu/
2. 자신의 첫 번째 핵심 서비스인 고환당을 어떻게 작성하는가:http://www.android1.net/Topic.aspx?BoardID=21&TopicID=990
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.