`
hyshucom
  • 浏览: 811569 次
文章分类
社区版块
存档分类
最新评论

android之Binder机制解析

 
阅读更多

说到Binder我们就不得不说android的服务,android之所以引入Binder就是为了实现代码的远程调用(一个进程调用另一个进程中的代码)
而服务(service)大多都是通过binder机制来实现和客户端的通信的。
要弄懂Binder机制,你只需要懂以下四点就OK了:
==========================================================
1.service_manager.c
这个里面就是创建了servicemanager的进程。它主要的工作就是将设备“/dev/binder”映射到虚拟内存。然后进入循环轮询这块内存,看是否有数据写到这块内存来,并且根据写入的数据进行响应的处理
先看
int main(int argc, char **argv)
{
struct binder_state *bs;
void *svcmgr = BINDER_SERVICE_MANAGER;

bs = binder_open(128*1024);//key word

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);//key word
return 0;
}
binder_open函数就是从设备“/dev/binder”里面隐射了大小为128*1024的内存出来,至于设备的,描述符和内存的首地址等信息都存储在了返回值bs里面了。
struct binder_state
{
int fd;//设备描述符
void *mapped;//首地址
unsigned mapsize;//内存大小128*1024
};
binder_loop(bs, svcmgr_handler)函数传入了两个参数,第一个参数就是上面函数返回的,第二个参数是一个函数指针。
它的里面似乎是对一些命令的处理,像添加服务获取服务等等。
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;
}
}
}
这个函数最重要的就是那个for循环了。
作用就是从"/dev/binder"设备里面读取数据,然后根据数据的类型进行处理(svcmgr_handler处理)。
==============================================================
2.启动一个服务
大家都是拿的MediaServer来举例的,我换一个吧!就拿SurfaceFlinger来举例。
看main_surfaceflinger.cpp(当然有可能SurfaceFlinger不是在这里启动的,在这里就不多说了,想知道的,可以仔细学习下android的启动流程)
int main(int argc, char** argv) {
SurfaceFlinger::publishAndJoinThreadPool();
return 0;
}
static void publishAndJoinThreadPool() {
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(String16(SERVICE::getServiceName()), new SERVICE());
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
跟MediaServer启动完全是一样的。
一个一个的看:
sp<ProcessState> proc(ProcessState::self());

sp<ProcessState> ProcessState::self()
{
if (gProcess != NULL) return gProcess;

AutoMutex _l(gProcessMutex);
if (gProcess == NULL) gProcess = new ProcessState;
return gProcess;
}
这像是一个单件模式,返回的是一个ProcessState实例。下面我们看ProcessState的构造函数。
ProcessState::ProcessState()
: mDriverFD(open_driver())
, mVMStart(MAP_FAILED)
, mManagesContexts(false)
, mBinderContextCheckFunc(NULL)
, mBinderContextUserData(NULL)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
{
if (mDriverFD >= 0) {
// XXX Ideally, there should be a specific define for whether we
// have mmap (or whether we could possibly have the kernel module
// availabla).
#if !defined(HAVE_WIN32_IPC)
// mmap the binder, providing a chunk of virtual address space to receive transactions.
mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
if (mVMStart == MAP_FAILED) {
// *sigh*
LOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
close(mDriverFD);
mDriverFD = -1;
}
#else
mDriverFD = -1;
#endif
}
if (mDriverFD < 0) {
// Need to run without the driver, starting our own thread pool.
}
}
可以看出这里面做的事情跟1里面的一样,也是将设备"/dev/binder"设备映射出来。难道这就是共享内存?
再看sp<IServiceManager> sm(defaultServiceManager());
sp<IServiceManager> defaultServiceManager()
{
if (gDefaultServiceManager != NULL) return gDefaultServiceManager;

{
AutoMutex _l(gDefaultServiceManagerLock);
if (gDefaultServiceManager == NULL) {
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
}
}

return gDefaultServiceManager;
}
这貌似也是一个单件模式,进入ProcessState::self()->getContextObject(NULL));看个究竟。
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)
{
if (supportsProcesses()) {
return getStrongProxyForHandle(0);
} else {
return getContextObject(String16("default"), caller);
}
}
返回的是getStrongProxyForHandle(0),可以看到大致就是BpBinder(handle)(handle=0)这么一个东西
重点看下interface_cast<IServiceManager>(BpBinder(0))
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
宏定义
#define DECLARE_META_INTERFACE(INTERFACE) \
static const android::String16 descriptor; \
static android::sp<I##INTERFACE> asInterface( \
const android::sp<android::IBinder>& obj); \
virtual const android::String16& getInterfaceDescriptor() const; \
I##INTERFACE(); \
virtual ~I##INTERFACE(); \


#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
const android::String16 I##INTERFACE::descriptor(NAME); \
const android::String16& \
I##INTERFACE::getInterfaceDescriptor() const { \
return I##INTERFACE::descriptor; \
} \
android::sp<I##INTERFACE> I##INTERFACE::asInterface( \
const android::sp<android::IBinder>& obj) \
{ \
android::sp<I##INTERFACE> intr; \
if (obj != NULL) { \
intr = static_cast<I##INTERFACE*>( \
obj->queryLocalInterface( \
I##INTERFACE::descriptor).get()); \
if (intr == NULL) { \
intr = new Bp##INTERFACE(obj); \
} \
} \
return intr; \
} \
I##INTERFACE::I##INTERFACE() { } \
I##INTERFACE::~I##INTERFACE() { } \

通过转化我们知道最终是返回的BpServiceManager(BpBinder(0))的东西(注意构造函数里面传进来的BpBinder,它实际是作为mRemote来保存的)。
然后又调用了sm->addService(String16(SERVICE::getServiceName()), new SERVICE());
这样就到了BpServiceManager的addSercice函数了
virtual status_t addService(const String16& name, const sp<IBinder>& service)
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
data.writeStrongBinder(service);
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
return err == NO_ERROR ? reply.readExceptionCode() : err;
}
remote()是什么东西?实际就是mRemote,也就是构造函数中传进来的BpBinder
status_t BpBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
// Once a binder has died, it will never come back to life.
if (mAlive) {
status_t status = IPCThreadState::self()->transact(
mHandle, code, data, reply, flags);
if (status == DEAD_OBJECT) mAlive = 0;
return status;
}

return DEAD_OBJECT;
}
又到了IPCThreadState的transact
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
...
...
...

if (err == NO_ERROR) {
LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),
(flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
}

...

if ((flags & TF_ONE_WAY) == 0) {
...

if (reply) {
err = waitForResponse(reply);
} else {
Parcel fakeReply;
err = waitForResponse(&fakeReply);
}

...

} else {
err = waitForResponse(NULL, NULL);
}

return err;
}
writeTransactionData是将这些code data等等(code就是我们的ADD_SERVICE_TRANSACTION请求)存储到了Parcel的数据结构mOut里面了。
我们猜想肯定会将数据写入到“/dev/binder”设备里面去。
waitForResponse()里面就是做这个事的,将请求写入设备,然后1中的循环就派上用场了,调用do_add_service将BnSurfaceFlinger加入到service队列中管理起来。
==================================================================
3.service的使用
一般在android里面使用service都是在一个xxxClient的地方。
在SurfaceComposerClient这个类里面,你可以大量看到surfaceflinger这个服务的使用。
void SurfaceComposerClient::onFirstRef()
{
sp<ISurfaceComposer> sm(getComposerService());
if (sm != 0) {
sp<ISurfaceComposerClient> conn = sm->createConnection();
if (conn != 0) {
mClient = conn;
Composer::addClient(this);
mPrebuiltLayerState = new layer_state_t;
mStatus = NO_ERROR;
}
}
}
就是SurfaceComposerClient被第一次实例化的地方会调用的函数。getComposerService就是返回一个SurfaceFlinger的服务,但返回的肯定是一个Bp。并且是BpSurfaceComposer(SurfaceFlinger是继承的这个的服务端BnSurfaceComposer)
virtual sp<ISurfaceComposerClient> createConnection()
{
uint32_t n;
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());//key word
remote()->transact(BnSurfaceComposer::CREATE_CONNECTION, data, &reply);
return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
}
ISurfaceComposer::getInterfaceDescriptor()这句话很重要,它是servicemanager找到服务的依据。
remote()->transact就不多说了,它跟2中分析的BpServiceManager一样最终调入了IPCThreadState::transact,
将命令写入到设备,servicemanager读取到后,会将对应的Service的服务端写入设备,然后再被executeCommand处理
status_t IPCThreadState::executeCommand(int32_t cmd)
{
BBinder* obj;
RefBase::weakref_type* refs;
status_t result = NO_ERROR;

switch (cmd) {
...
...
...

case BR_TRANSACTION:
{
binder_transaction_data tr;
result = mIn.read(&tr, sizeof(tr));
LOG_ASSERT(result == NO_ERROR,
"Not enough command data for brTRANSACTION");
if (result != NO_ERROR) break;

Parcel buffer;
buffer.ipcSetDataReference(
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(size_t), freeBuffer, this);

const pid_t origPid = mCallingPid;
const uid_t origUid = mCallingUid;

mCallingPid = tr.sender_pid;
mCallingUid = tr.sender_euid;

int curPrio = getpriority(PRIO_PROCESS, mMyThreadId);
if (gDisableBackgroundScheduling) {
if (curPrio > ANDROID_PRIORITY_NORMAL) {
// We have inherited a reduced priority from the caller, but do not
// want to run in that state in this process. The driver set our
// priority already (though not our scheduling class), so bounce
// it back to the default before invoking the transaction.
setpriority(PRIO_PROCESS, mMyThreadId, ANDROID_PRIORITY_NORMAL);
}
} else {
if (curPrio >= ANDROID_PRIORITY_BACKGROUND) {
// We want to use the inherited priority from the caller.
// Ensure this thread is in the background scheduling class,
// since the driver won't modify scheduling classes for us.
// The scheduling group is reset to default by the caller
// once this method returns after the transaction is complete.
androidSetThreadSchedulingGroup(mMyThreadId,
ANDROID_TGROUP_BG_NONINTERACT);
}
}

//LOGI(">>>> TRANSACT from pid %d uid %d\n", mCallingPid, mCallingUid);

Parcel reply;
IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
alog << "BR_TRANSACTION thr " << (void*)pthread_self()
<< " / obj " << tr.target.ptr << " / code "
<< TypeCode(tr.code) << ": " << indent << buffer
<< dedent << endl
<< "Data addr = "
<< reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer)
<< ", offsets addr="
<< reinterpret_cast<const size_t*>(tr.data.ptr.offsets) << endl;
}
if (tr.target.ptr) {
sp<BBinder> b((BBinder*)tr.cookie);
const status_t error = b->transact(tr.code, buffer, &reply, tr.flags);
if (error < NO_ERROR) reply.setError(error);

} else {
const status_t error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
if (error < NO_ERROR) reply.setError(error);
}

//LOGI("<<<< TRANSACT from pid %d restore pid %d uid %d\n",
// mCallingPid, origPid, origUid);

if ((tr.flags & TF_ONE_WAY) == 0) {
LOG_ONEWAY("Sending reply to %d!", mCallingPid);
sendReply(reply, 0);
} else {
LOG_ONEWAY("NOT sending reply to %d!", mCallingPid);
}

mCallingPid = origPid;
mCallingUid = origUid;

IF_LOG_TRANSACTIONS() {
TextOutput::Bundle _b(alog);
alog << "BC_REPLY thr " << (void*)pthread_self() << " / obj "
<< tr.target.ptr << ": " << indent << reply << dedent << endl;
}

}
break;

...
...
...

default:
printf("*** BAD COMMAND %d received from Binder driver\n", cmd);
result = UNKNOWN_ERROR;
break;
}

if (result != NO_ERROR) {
mLastError = result;
}

return result;
}
我们只需要看BR_TRANSACTION
if (tr.target.ptr) {
sp<BBinder> b((BBinder*)tr.cookie);
const status_t error = b->transact(tr.code, buffer, &reply, tr.flags);//key word
if (error < NO_ERROR) reply.setError(error);

} else {
const status_t error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
if (error < NO_ERROR) reply.setError(error);
}

会调用BBinder的transact,实际这个tr.cookie就是BnXXX,是由ServiceManager写进设备的,而BnXXX又是继承的BBinder
status_t BBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
data.setDataPosition(0);

status_t err = NO_ERROR;
switch (code) {
case PING_TRANSACTION:
reply->writeInt32(pingBinder());
break;
default:
err = onTransact(code, data, reply, flags);//key word
break;
}

if (reply != NULL) {
reply->setDataPosition(0);
}

return err;
}
转来转去,最终还是调用的Bnxxx的OnTransact,像SurfaceFlinger是继承的BnSurfaceComposer,它里面实现了OnTransact
status_t BnSurfaceComposer::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
case CREATE_CONNECTION: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
sp<IBinder> b = createConnection()->asBinder();
reply->writeStrongBinder(b);
} break;
...
...
...
case TURN_ELECTRON_BEAM_OFF: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
int32_t mode = data.readInt32();
status_t res = turnElectronBeamOff(mode);
reply->writeInt32(res);
} break;
case TURN_ELECTRON_BEAM_ON: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
int32_t mode = data.readInt32();
status_t res = turnElectronBeamOn(mode);
reply->writeInt32(res);
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
return NO_ERROR;
}
这样就到了各自操作的具体实现了(在SurfaceFlinger里面)。


时间原因后面说的有点模糊,以后再做详细研究,做更细致的解释。

分享到:
评论

相关推荐

    Android Binder机制完全解析

    详见http://blog.csdn.net/huaxun66/article/details/52966087

    Binder机制原理解析

    Android Binder机制全解析,从Kernel binder层到native binder到java binder。很详细值得推荐阅读

    【一图流】_02_一张图看懂 Android 进程间通信(IPC)Binder机制.png

    【一图流】_02_一张图看懂 Android 进程间通信(IPC)Binder机制:  此图表述了Android系统_进程间通信(IPC)机制全部体系,其中重点放在 Android系统中 重用 的 Binder机制 上,详尽细致,希望对大家有用;

    从java到C解析Binder机制

    文章http://blog.csdn.net/rambo_huang/article/details/52263835的word文档

    Android技术内幕.系统卷(扫描版)

    第3章 android的ipc机制--binder /100 3.1 binder概述 /101 3.1.1 为什么选择binder /101 3.1.2 初识binder /102 3.2 binder驱动的原理和实现 /102 3.2.1 binder驱动的原理 /102 3.2.2 binder驱动的实现 /103 3.3 ...

    《Android系统源代码情景分析》

    第14章 Android应用程序的键盘消息处理机制 14.1 键盘消息处理模型 14.2 InputManager的启动过程 14.2.1 创建InputManager 14.2.2 启动InputManager 14.2.3 启动InputDispatcher 14.2.4 启动Input...

    台湾高焕堂Android讲义

    13.Android的IBinder接口及其安全性机制.doc 14.Activity之间的Inter-process沟通.doc 15.从应用框架角度看ListView与Adapter类别.doc 16.善于设计自己的Listener来进行沟通.doc 17.如何使用SurfaceView计时绘点或线...

    Android系统源代码情景分析-罗升阳-源码

    第14章 Android应用程序的键盘消息处理机制 14.1 键盘消息处理模型 14.2 InputManager的启动过程 14.2.1 创建InputManager 14.2.2 启动InputManager 14.2.3 启动InputDispatcher 14.2.4 启动InputReader 14.3...

    Android技术内幕.系统卷 pdf

    第3章 android的ipc机制--binder /100 3.1 binder概述 /101 3.1.1 为什么选择binder /101 3.1.2 初识binder /102 3.2 binder驱动的原理和实现 /102 3.2.1 binder驱动的原理 /102 3.2.2 binder驱动的实现 /103 ...

    android多媒体框架

    MediaPlayer在运行的时候,可以大致上分成Client和Server两个部分,它们分别在两个进程中运行,它们之间使用Binder机制实现IPC通讯,图中libmediaplayerservice.so是服务端的实现库。 对于视频文件的播放,...

    《深入理解Android:卷I》试读本

    第6章以MediaServer为切入点,对Android中极为重要的Binder进行了较为全面的分析,深刻揭示了其本质。第7章对Audio系统进行了深入的分析,尤其是AudioTrack、AudioFlinger和AudioPolicyService等的工作原理。第8章...

    高焕堂关于Android讲义

    13.Android的IBinder接口及其安全性机制 14.Activity之间的Inter-process沟通 15.从应用框架角度看ListView与Adapter类别 16.善于设计自己的Listener来进行沟通 17.如何使用SurfaceView计时绘点或线 18.从...

    Android开发艺术探索.任玉刚(带详细书签).pdf

    10.2 Android的消息机制分析 375 10.2.1 ThreadLocal的工作原理 375 10.2.2 消息队列的工作原理 380 10.2.3 Looper的工作原理 383 10.2.4 Handler的工作原理 385 10.3 主线程的消息循环 389 第11章 Android的...

    Android开发艺术探索

    10.1 Android的消息机制概述 / 373 10.2 Android的消息机制分析 / 375 10.2.1 Thread Local的工作原理 / 375 10.2.2 消息队列的工作原理 / 380 10.2.3 Looper的工作原理 / 383 10.2.4 Handler的工作原理 ...

    深入理解Android 卷1.pdf

    第6章以MediaServer为切入点,对Android中极为重要的Binder进行了较为全面的分析,深刻揭示了其本质。第7章对Audio系统进行了深入的分析,尤其是AudioTrack、AudioFlinger和AudioPolicyService等的工作原理。第8章...

    深入理解Android++卷1pdf电子书

    第6章以MediaServer为切入点,对Android中极为重要的Binder进行了较为全面的分析,深刻揭示了其本质。第7章对Audio系统进行了深入的分析,尤其是AudioTrack、AudioFlinger和AudioPolicyService等的工作原理。第8章...

    深入理解Android卷1

    第6章以MediaServer为切入点,对Android中极为重要的Binder进行了较为全面的分析,深刻揭示了其本质。第7章对Audio系统进行了深入的分析,尤其是AudioTrack、AudioFlinger和AudioPolicyService等的工作原理。第8章...

    深入理解Android:卷2

    第6章以MediaServer为切入点,对Android中极为重要的Binder进行了较为全面的分析,深刻揭示了其本质。第7章对Audio系统进行了深入的分析,尤其是AudioTrack、AudioFlinger和AudioPolicyService等的工作原理。第8章...

    android开发艺术探索高清完整版PDF

    / 133 3.3 弹性滑动 / 135 3.3.1 使用Scroller / 136 3.3.2 通过动画 / 138 3.3.3 使用延时策略 / 139 3.4 View的事件分发机制 / 140 3.4.1 点击事件的传递规则 / 140 3.4.2 事件分发的源码解析 / 144 3.5 ...

    深入理解Android:卷I--详细书签版

    第6章以mediaserver为切入点,对android中极为重要的binder进行了较为全面的分析,深刻揭示了其本质。第7章对 audio系统进行了深入的分析,尤其是audiotrack、audioflinger和audiopolicyservice等的工作原理。第8章...

Global site tag (gtag.js) - Google Analytics