应用是什么时候支持 binder 机制的
- binder 都知道是用来做跨进程服务的,应用内可以通过binder 跟系统组件进行交互。如 AMS Service aidl 等
- 那么可以思考一下,当 Activity onCreate() 的时候,甚至是 Application 的 onCreate() 的时候都可以获取的到系统服务,所以此时 binder 机制一定是初始化好了的。
应用大致启动流程是什么
当系统启动一个组件时,发现其进程未启动会通过 AMS 向 Zygote 发送请求启动应用,zygote 启动应用好了以后,应用会告知 AMS 启动完成,所以,应用通过binder进行通信最早应该是启动好后就已经和 AMS 通信了。所以可以看看再之前启动进程过程中是否启动了 binder 机制。
- 进程启动流程
之前有说过 zygote 进程启动之后会调用 zygoteServer.runSelectLoop(abiList); 开启 loop 等待和处理创建应用的消息。所以我们看看 loop 中获取到消息以后会处理哪些东西;
Android 9.0 当消息到来的时候会执行 Runnable processOneCommand() 方法
Runnable processOneCommand(ZygoteServer zygoteServer) {
String args[];
Arguments parsedArgs = null;
FileDescriptor[] descriptors;
try {
// 先读取 AMS 发送过来的参数列表
args = readArgumentList();
descriptors = mSocket.getAncillaryFileDescriptors();
} catch (IOException ex) {
throw new IllegalStateException("IOException on command socket", ex);
}
/// 略......
int pid = -1;
// 通过 forkAndSpecialize 创建应用的进程
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.runtimeFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.startChildZygote,
parsedArgs.instructionSet, parsedArgs.appDataDir);
/// 略......
try {
// pid == 0 代表子进程
if (pid == 0) {
// in child
zygoteServer.setForkChild();
zygoteServer.closeServerSocket();
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
// handleChildProc 内部会关闭 socket 后执行 ZygoteInit.zygoteInit() 函数
return handleChildProc(parsedArgs, descriptors, childPipeFd,
parsedArgs.startChildZygote);
} else {
return null;
}
} finally {
}
}
ZygoteInit.zygoteInit() 函数如下
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
if (RuntimeInit.DEBUG) {
Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
RuntimeInit.redirectLogStreams();
// 做一些常规的初始化
RuntimeInit.commonInit();
ZygoteInit.nativeZygoteInit();
return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
- ZygoteInit.nativeZygoteInit();
这个是 native 方法 private static final native void nativeZygoteInit(); 调用的是 AndroidRuntime.cpp中的方法
static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->onZygoteInit();
}
virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();
}
- ProcessState::self(); 函数
// ProcessState 这是一个单例
sp<ProcessState> ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != NULL) {
return gProcess;
}
gProcess = new ProcessState("/dev/binder");
return gProcess;
}
ProcessState::self() 函数创建了一个 ProcessState() 对象并传入了 “/dev/binder” 参数,然后看一下ProcessState构造函数。
ProcessState::ProcessState(const char *driver)
: mDriverName(String8(driver))
, mDriverFD(open_driver(driver))
, mVMStart(MAP_FAILED)
// ....
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
{
if (mDriverFD >= 0) {
// 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*
ALOGE("Using %s failed: unable to mmap transaction memory.\n", mDriverName.c_str());
close(mDriverFD);
mDriverFD = -1;
mDriverName.clear();
}
}
LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened. Terminating.");
}
上面方法主要有两个 第一个 定义了 mDriverFD(open_driver(driver)) ,通过open_driver() 赋值,open_driver() 就是打开 binder驱动,如果 mDriverFD > 0 则代表有效的,则通过 mmap 映射到对用的内存空间。所以启动binder机制是在进程启动之后初始化ProcessState中启动的
- onZygoteInit() 方法在打开 binder驱动之后会在调用 proc->startThreadPool(); 函数。线程池中只有一个线程,标记成binder线程,然后开启循环一直等待 binder 启动的操作指令进行执行命令。
总结问题
binder机制是如何启动的
- 打开 binder 驱动
- 映射内存分配缓冲区
- 注册binder线程
- 进入binder loop