Step 15. talkWithDriver
这个函数定义在frameworks/base/libs/binder/IPCThreadState.cpp文件中:
- status_t IPCThreadState::talkWithDriver(bool doReceive)
- {
- ......
- binder_write_read bwr;
- // Is the read buffer empty?
- const bool needRead = mIn.dataPosition() >= mIn.dataSize();
- // We don't want to write anything if we are still reading
- // from data left in the input buffer and the caller
- // has requested to read the next data.
- const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
- bwr.write_size = outAvail;
- bwr.write_buffer = (long unsigned int)mOut.data();
- // This is what we'll read.
- if (doReceive && needRead) {
- bwr.read_size = mIn.dataCapacity();
- bwr.read_buffer = (long unsigned int)mIn.data();
- } else {
- bwr.read_size = 0;
- }
- ......
- // Return immediately if there is nothing to do.
- if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;
- bwr.write_consumed = 0;
- bwr.read_consumed = 0;
- status_t err;
- do {
- ......
- #if defined(HAVE_ANDROID_OS)
- if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
- err = NO_ERROR;
- else
- err = -errno;
- #else
- err = INVALID_OPERATION;
- #endif
- ......
- }
- } while (err == -EINTR);
- ....
- if (err >= NO_ERROR) {
- if (bwr..write_consumed > 0) {
- if (bwr.write_consumed < (ssize_t)mOut.dataSize())
- mOut.remove(0, bwr.write_consumed);
- else
- mOut.setDataSize(0);
- }
- if (bwr.read_consumed > 0) {
- mIn.setDataSize(bwr.read_consumed);
- mIn.setDataPosition(0);
- }
- ......
- return NO_ERROR;
- }
- return err;
- }
-
ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)
有了这个线程池之后,我们在开发Android应用程序的时候,当我们要和其它进程中进行通信时,只要定义自己的Binder对象,然后把这个Binder对象的远程接口通过其它途径传给其它进程后,其它进程就可以通过这个Binder对象的远程接口来调用我们的应用程序进程的函数了,它不像我们在C++层实现Binder进程间通信机制的Server时,必须要手动调用IPCThreadState.joinThreadPool函数来进入一个无限循环中与Binder驱动程序交互以便获得Client端的请求,这样就实现了我们在文章开头处说的Android应用程序进程天然地支持Binder进程间通信机制。
细心的读者可能会发现,从Step 1到Step 9,都是在Android应用程序框架层运行的,而从Step 10到Step 15,都是在Android系统运行时库层运行的,这两个层次中的Binder进程间通信机制的接口一个是用Java来实现的,而别一个是用C++来实现的,这两者是如何协作的呢?这就是通过JNI层来实现的了,具体可以参考
Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析
一文。
回到Step 8中的RuntimeInit.zygoteInit函数中,在初始化完成Binder进程间通信机制的基础设施后,它接着就要进入进程的入口函数了。
Step 16. RuntimeInit.invokeStaticMain
这个函数定义在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中:
- public class ZygoteInit {
- ......
- static void invokeStaticMain(ClassLoader loader,
- String className, String[] argv)
- throws ZygoteInit.MethodAndArgsCaller {
- Class<?> cl;
- try {
- cl = loader.loadClass(className);
- } catch (ClassNotFoundException ex) {
- ......
- }
- Method m;
- try {
- m = cl.getMethod("main", new Class[] { String[].class });
- } catch (NoSuchMethodException ex) {
- ......
- } catch (SecurityException ex) {
- ......
- }
- int modifiers = m.getModifiers();
- ......
- /*
- * This throw gets caught in ZygoteInit.main(), which responds
- * by invoking the exception's run() method. This arrangement
- * clears up all the stack frames that were required in setting
- * up the process.
- */
- throw new ZygoteInit.MethodAndArgsCaller(m, argv);
- }
- ......
- }
前面我们说过,这里传进来的参数className字符串值为"android.app.ActivityThread",这里就通ClassLoader.loadClass函数将它加载到进程中:
-
cl = loader.loadClass(className);
然后获得它的静态成员函数main:
-
m = cl.getMethod("main", new Class[] { String[].class });
函数最后并没有直接调用这个静态成员函数main,而是通过抛出一个异常ZygoteInit.MethodAndArgsCaller,然后让ZygoteInit.main函数在捕获这个异常的时候再调用android.app.ActivityThread类的main函数。为什么要这样做呢?注释里面已经讲得很清楚了,它是为了清理堆栈的,这样就会让android.app.ActivityThread类的main函数觉得自己是进程的入口函数,而事实上,在执行android.app.ActivityThread类的main函数之前,已经做了大量的工作了。
我们看看ZygoteInit.main函数在捕获到这个异常的时候做了什么事:
- public class ZygoteInit {
- ......
- public static void main(String argv[]) {
- try {
- ......
- } catch (MethodAndArgsCaller caller) {
- caller.run();
- } catch (RuntimeException ex) {
- ......
- }
- }
- ......
- }
它执行MethodAndArgsCaller的run函数:
- public class ZygoteInit {
- ......
- public static class MethodAndArgsCaller extends Exception
- implements Runnable {
- /** method to call */
- private final Method mMethod;
- /** argument array */
- private final String[] mArgs;
- public MethodAndArgsCaller(Method method, String[] args) {
- mMethod = method;
- mArgs = args;
- }
- public void run() {
- try {
- mMethod.invoke(null, new Object[] { mArgs });
- } catch (IllegalAccessException ex) {
- ......
- } catch (InvocationTargetException ex) {
- ......
- }
- }
- }
- ......
- }
这里的成员变量mMethod和mArgs都是在前面构造异常对象时传进来的,这里的mMethod就对应android.app.ActivityThread类的main函数了,于是最后就通过下面语句执行这个函数:
-
mMethod.invoke(null, new Object[] { mArgs });
这样,android.app.ActivityThread类的main函数就被执行了。
Step 17. ActivityThread.main
这个函数定义在frameworks/base/core/java/android/app/ActivityThread.java文件中:
- public final class ActivityThread {
- ......
- public static final void main(String[] args) {
- SamplingProfilerIntegration.start();
- Process.setArgV0("<pre-initialized>");
- Looper.prepareMainLooper();
- if (sMainThreadHandler == null) {
- sMainThreadHandler = new Handler();
- }
- ActivityThread thread = new ActivityThread();
- thread.attach(false);
- if (false) {
- Looper.myLooper().setMessageLogging(new
- LogPrinter(Log.DEBUG, "ActivityThread"));
- }
- Looper.loop();
- if (Process.supportsProcesses()) {
- throw new RuntimeException("Main thread loop unexpectedly exited");
- }
- thread.detach();
- String name = (thread.mInitialApplication != null)
- ? thread.mInitialApplication.getPackageName()
- : "<unknown>";
- Slog.i(TAG, "Main thread of " + name + " is now exiting");
- }
- ......
- }
从这里我们可以看出,这个函数首先会在进程中创建一个ActivityThread对象:
-
ActivityThread thread = new ActivityThread();
然后进入消息循环中:
-
Looper.loop();
这样,我们以后就可以在这个进程中启动Activity或者Service了。
至此,Android应用程序进程启动过程的源代码就分析完成了,它除了指定新的进程的入口函数是ActivityThread的main函数之外,还为进程内的Binder对象提供了Binder进程间通信机制的基础设施,由此可见,Binder进程间通信机制在Android系统中是何等的重要,而且是无处不在,想进一步学习Android系统的Binder进程间通信机制,请参考
Android进程间通信(IPC)机制Binder简要介绍和学习计划
一文。
本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966514,如需转载请自行联系原作者