Android 应用是如何启动 binder 机制的?

应用是什么时候支持 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

猜你喜欢

转载自blog.csdn.net/ldxlz224/article/details/127378154