IPC浅析Binder进程通信和ServiceManager
Posted 從前以後
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了IPC浅析Binder进程通信和ServiceManager相关的知识,希望对你有一定的参考价值。
Binder机制是android中实现的进程间通信的架构,它采用的是C-S架构,Client通过代理完成对Server的调用。既然是C-S模式,那么谁是Server呢?答案就是Native中的进程:ServiceManager。
顾名思义,这个是用来管理所有Server的。Android设备在硬件启动之后,第一个进程就是init进程,init进程启动之后,会启动另外一系列的进程,其中最重要的就是Zygote进程和ServiceManager进程,身下的如VM和Runtime等等进程,ServiceManager进程启动之后其他Server就可以通过ServiceManager的add_service和check_service来添加和获取特定的server了。
关于ServiceMananger:
ServiceMananger是android中比较重要的一个进程,它是在init进程启动之后启动。ServiceMananger是系统服务的管理者,包括Java层的系统服务,比如:WindowManagerService、ActivityManagerService等,以及Native层的系统服务,例如SurfaceFlingerdeng 。在ServiceManager中有两个比较重要的方法:add_service、check_service。系统的service需要通过add_service把自己的信息注册到ServiceManager中,当需要使用时,通过check_service检查该service是否存在,并通过find_service返回。
既然Service Manager组件是用来管理Server并且向Client提供查询Server远程接口的,Service Manger、Client和Server三者分别是运行在独立的进程当中,这样它们之间的通信也属于进程间通信了,而且也是采用Binder机制进行进程间通信,因此,Service Manager在充当Binder机制的守护进程的角色的同时,也在充当Server的角色,然而,它是一种特殊的Server,下面就来领略下它的特殊之处。
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;
从main函数中看出,init大值做了一下事情:
1,打开BinderDriver设备。
2,通知BinderDriver设备,把自己变成context_manager。
3开启循环,不停的去读BinderDriver设备,看是否有对service的请求,如果有的话,就去调用svcmgr_handler函数回调处理请求。
int svcmgr_handler(struct binder_state *bs,
struct binder_txn *txn,
struct binder_io *msg,
struct binder_io *reply)
struct svcinfo *si;
uint16_t *s;
unsigned len;
void *ptr;
uint32_t strict_policy;
// LOGI("target=%p code=%d pid=%d uid=%d\\n",
// txn->target, txn->code, txn->sender_pid, txn->sender_euid);
if (txn->target != svcmgr_handle)
return -1;
// Equivalent to Parcel::enforceInterface(), reading the RPC
// header with the strict mode policy mask and the interface name.
// Note that we ignore the strict_policy and don't propagate it
// further (since we do no outbound RPCs anyway).
strict_policy = bio_get_uint32(msg);
s = bio_get_string16(msg, &len);
if ((len != (sizeof(svcmgr_id) / 2)) ||
memcmp(svcmgr_id, s, sizeof(svcmgr_id)))
fprintf(stderr,"invalid id %s\\n", str8(s));
return -1;
switch(txn->code)
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
s = bio_get_string16(msg, &len);
ptr = do_find_service(bs, s, len);
if (!ptr)
break;
bio_put_ref(reply, ptr);
return 0;
case SVC_MGR_ADD_SERVICE:
s = bio_get_string16(msg, &len);
ptr = bio_get_ref(msg);
if (do_add_service(bs, s, len, ptr, txn->sender_euid))
return -1;
break;
case SVC_MGR_LIST_SERVICES:
unsigned n = bio_get_uint32(msg);
si = svclist;
while ((n-- > 0) && si)
si = si->next;
if (si)
bio_put_string16(reply, si->name);
return 0;
return -1;
default:
LOGE("unknown code %d\\n", txn->code);
return -1;
bio_put_uint32(reply, 0);
return 0;
在该回调函数中会判断Service有什么需要,如果是请求注册service,那么久执行:case SVC_MGR_ADD_SERVICE,该方法通过ServiceManager,把服务加入到BinderDriver中。如果是获取service,那么执行上文case SVC_MGR_CHECK_SERVICE: 并把返回的数据写入reply,返回给客户端。
服务端注册完Service到BinderDriver中,客户端请求绑定拿到IBinder接口对象,那么就可以愉快的通信了。
Binder进行进程间通信
上文只是提到了怎么注册服务和获取到注册服务返回值。究竟是怎么拿到返回值的,并且Binder究竟是怎么传输数据的呢?
下面以startActivity为例子,探究怎么找到AMS,并且传输数据的。
首先Activity是继承自Context的,Context的实现类是ContextImpl,那么就会调用ContextImpl里面的startActivity方法
@Override
public void startActivity(Intent intent, Bundle options)
warnIfCallingFromSystemProcess();
if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) == 0)
throw new AndroidRuntimeException(
"Calling startActivity() from outside of an Activity "
+ " context requires the FLAG_ACTIVITY_NEW_TASK flag."
+ " Is this really what you want?");
mMainThread.getInstrumentation().execStartActivity(
getOuterContext(), mMainThread.getApplicationThread(), null,
(Activity)null, intent, -1, options);
接着会调用到Instrumentation中的execStartActivity方法
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options)
IApplicationThread whoThread = (IApplicationThread) contextThread;
if (mActivityMonitors != null)
synchronized (mSync)
final int N = mActivityMonitors.size();
for (int i=0; i<N; i++)
final ActivityMonitor am = mActivityMonitors.get(i);
if (am.match(who, null, intent))
am.mHits++;
if (am.isBlocking())
return requestCode >= 0 ? am.getResult() : null;
break;
try
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess();
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, null, options);
checkStartActivityResult(result, intent);
catch (RemoteException e)
return null;
Instrumentation中的execStartActivity方法中ActivityManagerNative.getDefault()该方法通过ServiceManager的get方法拿到远程的IBinder实现类对象(为什么是IBinder类型?ActivityManagerNative继承自Binder),同时调用该接口实现类对象的startActivity方法
最终调用到ActivityManagerProxy中的startActivity
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, String profileFile,
ParcelFileDescriptor profileFd, Bundle options) throws RemoteException
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeString(callingPackage);
intent.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeStrongBinder(resultTo);
data.writeString(resultWho);
data.writeInt(requestCode);
data.writeInt(startFlags);
data.writeString(profileFile);
if (profileFd != null)
data.writeInt(1);
profileFd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
else
data.writeInt(0);
if (options != null)
data.writeInt(1);
options.writeToParcel(data, 0);
else
data.writeInt(0);
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
reply.readException();
int result = reply.readInt();
reply.recycle();
data.recycle();
return result;
最终调用IBinder接口方法transact写入数据到BinderDriver中,Service从BinderDriver读取数据,执行完之后在原路返回数据给客户端。
Binder到底是个啥?在Java层Binder是一个实现了IBinder类,在Linux中Binder是一个驱动。本人认为Binder实际是Linux中的一块驱动而已,实现数据交换,至于Java层和Native层的Binder,实际上是实现了IBinder接口,利用IBinder中的transact写入数据到Binder驱动中。所以Java层和Native层的Binder本人认为是伪Binder,只是提供方法写入数据到BinderDriver中而已。
以上是关于IPC浅析Binder进程通信和ServiceManager的主要内容,如果未能解决你的问题,请参考以下文章
Android进程间通信(IPC)机制Binder简要介绍和学习计划
Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析