Android进阶知识树——应用进程的启动过程

程序的启动是从进程启动开始的,换句话说只有程序进程启动后,程序才会加载和执行,在AMS启动程序时首先会判断当前进程是否启动,对未启动的进程会发送请求,Zygote在收到请求后创建新的进程;

1、Zygote监听客户端请求

由Android进阶知识树——Android系统的启动过程知道,系统的启动会执行到ZygoteInit.main()方法;

public static void main(String argv[]) {
   ZygoteServer zygoteServer = new ZygoteServer();//1
   zygoteServer.registerServerSocketFromEnv(socketName);
   caller = zygoteServer.runSelectLoop(abiList); //2
}

在main中创建并注册了服务端的Socket,然后执行runSelectLoop()循环等待AMS的请求创建进程;

  • registerServerSocketFromEnv()
void registerServerSocketFromEnv(String socketName) {
        if (mServerSocket == null) {
            int fileDesc;
            final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;//1
            try {
                String env = System.getenv(fullSocketName);//2
                fileDesc = Integer.parseInt(env);
            } 
            try {
                FileDescriptor fd = new FileDescriptor();//3
                fd.setInt$(fileDesc);
                mServerSocket = new LocalServerSocket(fd);//4
                mCloseSocketFd = true;
            } catch (IOException ex) {
        }
    }

在registerServerSocketFromEnv中,首先使用ANDROID_SOCKET_PREFIX拼接Socket名称,最终的名称为ANDROID_SOCKET_zygote,然后将fullSocketName转换为环境变量的值,注释3处创建文件描述符,然后根据文件描述符创建LocalServerSocket对象

  • zygoteServer.runSelectLoop()
    Runnable runSelectLoop(String abiList) {
        ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
177        fds.add(mServerSocket.getFileDescriptor());//1
178        peers.add(null);
179
180        while (true) { //2
181            StructPollfd[] pollFds = new StructPollfd[fds.size()];
182            for (int i = 0; i < pollFds.length; ++i) {
183                pollFds[i] = new StructPollfd();
184                pollFds[i].fd = fds.get(i);
185                pollFds[i].events = (short) POLLIN;
186            }
187            try {
188                Os.poll(pollFds, -1);
189            } catch (ErrnoException ex) {
190                throw new RuntimeException("poll failed", ex);
191            }
192            for (int i = pollFds.length - 1; i >= 0; --i) {
193                if ((pollFds[i].revents & POLLIN) == 0) {
194                    continue;
195                }
197                if (i == 0) { // 3
198                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
199                    peers.add(newPeer);
200                    fds.add(newPeer.getFileDesciptor());
201                } else {
202                    try {
203                        ZygoteConnection connection = peers.get(i);
204                        final Runnable command = connection.processOneCommand(this); // 4
205
206                        if (mIsForkChild) {
213                            return command;
214                        } else {
223                            if (connection.isClosedByPeer()) {
224                                connection.closeSocket();
225                                peers.remove(i);
226                                fds.remove(i);
227                            }
228                        }
229                    } catch (Exception e) {
230                        if (!mIsForkChild) {
241                            ZygoteConnection conn = peers.remove(i);
242                            conn.closeSocket();
244                            fds.remove(i);
245                        } else {
250                            throw e;
251                        }
252                    } finally {
256                        mIsForkChild = false;
257                    }
258                }
259            }
260        }
261    }

在runSelectLoop方法中,首先获取注册Socket的文件描述符fd,并将其保存在fds集合中,然后开启循环监听AMS的请求,在注释3处判断i ==0,若i=0表示Socket已连接,否则表示接收到AMS的请求信号,调用connection.processOneCommand(this)创建新的进程,创建完成后清除对应的peers集合和fds集合;

2、AMS发送创建进程请求

AMS会检查目标程序进程,如果进程未启动则调用startProcessLocked()方法启动进程

   int uid = app.uid; //1
   ......
if (ArrayUtils.isEmpty(permGids)) { //2
           gids = new int[3];
        } else {
            gids = new int[permGids.length + 3];
            System.arraycopy(permGids, 0, gids, 3, permGids.length);
        }
          gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
          gids[1] = UserHandle.getCacheAppGid(UserHandle.getAppId(uid));
          gids[2] = UserHandle.getUserGid(UserHandle.getUserId(uid));
.....
final String entryPoint = "android.app.ActivityThread"; //3
return startProcessLocked(hostingType, hostingNameStr, entryPoint, app, uid, gids,runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith,startTime); //4

startProcessLocked执行一下逻辑:

  1. 获取当前程序的uid
  2. 对用户组gids创建并赋值
  3. entryPoint赋值为ActivityThread的路径,ActivityThread就是进程启动时要初始化的类
  4. 调用startProcessLocked()启动进程

在startProcessLocked()中又调用startProcess(),startProcess()中调用Process.start()方法,start中调用ZygoteProcess.startViaZygote()启动进程,

  • ZygoteProcess.startViaZygote()
private Process.ProcessStartResult startViaZygote(final String processClass,
   ......String[] extraArgs)throws ZygoteStartFailedEx {
   ArrayList<String> argsForZygote = new ArrayList<String>();
   argsForZygote.add("--runtime-args");
   argsForZygote.add("--setuid=" + uid);
   argsForZygote.add("--setgid=" + gid);
   argsForZygote.add("--runtime-flags=" + runtimeFlags);

synchronized(mLock) {
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}

在startViaZygote中首先创建ArrayList集合,然后添加创建进程的启动参数,最后调用zygoteSendArgsAndGetResult()执行启动进程,在zygoteSendArgsAndGetResult的第一个参数中首先调用了openZygoteSocketIfNeeded()方法,它的作用其实就是连接Zygote 中服务端的Socket

private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
        if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
            try {
                primaryZygoteState = ZygoteState.connect(mSocket); //1
            } catch (IOException ioe) {
                throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
            }
            maybeSetApiBlacklistExemptions(primaryZygoteState, false);
           maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState);
        }
        if (primaryZygoteState.matches(abi)) { //2
            return primaryZygoteState;
        }
        if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
            try {
                secondaryZygoteState = ZygoteState.connect(mSecondarySocket);//3
            } 
           maybeSetApiBlacklistExemptions(secondaryZygoteState, false);
           maybeSetHiddenApiAccessLogSampleRate(secondaryZygoteState);
        }
        if (secondaryZygoteState.matches(abi)) { //4
            return secondaryZygoteState;
        }
 }

在openZygoteSocketIfNeeded()中ZygoteState.connect()连接Zygote进程中的Socket,连接成功后返回连接的主模式,用此主模式和传入的abi比较是否匹配,如果匹配则直接返回ZygoteState,否则连接zygote辅模式;

  • zygoteSendArgsAndGetResult()
 private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
281            ZygoteState zygoteState, ArrayList<String> args)
282            throws ZygoteStartFailedEx {
283        try {
286            int sz = args.size();
287            for (int i = 0; i < sz; i++) {
288                if (args.get(i).indexOf('\n') >= 0) {
289                    throw new ZygoteStartFailedEx("embedded newlines not allowed");
290                }
291            }
303            final BufferedWriter writer = zygoteState.writer;
304            final DataInputStream inputStream = zygoteState.inputStream;
306            writer.write(Integer.toString(args.size()));
307            writer.newLine();
309            for (int i = 0; i < sz; i++) {
310                String arg = args.get(i);
311                writer.write(arg);
312                writer.newLine();
313            }
315            writer.flush();
323            result.pid = inputStream.readInt();
324            result.usingWrapper = inputStream.readBoolean();
326            if (result.pid < 0) {
327                throw new ZygoteStartFailedEx("fork() failed");
328            }
329            return result;
330        } catch (IOException ex) {
331            zygoteState.close();
332            throw new ZygoteStartFailedEx(ex);
333        }
334    }

在zygoteSendArgsAndGetResult中获取连接Socket返回的ZygoteState,利用ZygoteState内部的BufferedWriter将请求参数写入Zygote进程中;

3、Zygote接收信息并创建进程

由第一部分知道,在AMS发送请求后zygote进程会接收请求,并调用ZygoteConnection.processOneCommand()方法处理请求,在ZygoteInit.main()方法中有以下代码

  final Runnable caller;
  caller = zygoteServer.runSelectLoop(abiList);
  if (caller != null) {
      caller.run();
  }

在runSelectLoop()中接收到AMS请求信息后,然后执行处理并返回Runnable对象并执行run()方法,

  Runnable processOneCommand(ZygoteServer zygoteServer) {
   String args[];
   Arguments parsedArgs = null;
        FileDescriptor[] descriptors;
        try {
            args = readArgumentList(); //1
            descriptors = mSocket.getAncillaryFileDescriptors();
        } 
         parsedArgs = new Arguments(args); //2
  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);
 if (pid == 0) {
                zygoteServer.setForkChild();
                zygoteServer.closeServerSocket();
                IoUtils.closeQuietly(serverPipeFd);
                serverPipeFd = null;
                return handleChildProc(parsedArgs, descriptors, childPipeFd,
                        parsedArgs.startChildZygote); //3
            } else {
                IoUtils.closeQuietly(childPipeFd);
                childPipeFd = null;
                handleParentProc(pid, descriptors, serverPipeFd);
                return null;
            }

  }

在processOneCommand()中首先调用readArgumentList读取参数数组,然后将数组封装在Arguments对象中,调用Zygote.forkAndSpecialize()方法fork子进程,子进程创建成功后调用handleChildProc()初始化进程

private Runnable handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors,FileDescriptor pipeFd, boolean isZygote) {
        if (parsedArgs.niceName != null) {
            Process.setArgV0(parsedArgs.niceName);
        }
            if (!isZygote) {
                return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs,null /* classLoader */);
            } else {
                return ZygoteInit.childZygoteInit(parsedArgs.targetSdkVersion,
                        parsedArgs.remainingArgs, null /* classLoader */);
            }
        }
    }

在handleChildProc调用ZygoteInit.zygoteInit(),关于ZygoteInit.zygoteInit()方法的内容参考Android进阶知识树——Android系统的启动过程,其最终会使用反射调用ActivityThread.main()方法,程序进入进程初始化,关于ActivityThread中的操作这里不做分析,相信Android开发者应该了解;

4、启动Binder线程池

本篇文章和上一篇Android进阶知识树——Android系统的启动过程中都提到Binder线程池的创建,但都没有详细介绍,这里补充一下,程序在启动进程后会调用ZygoteInit.zygoteInit()方法,zygoteInit中调用本地方法nativeZygoteInit(),在ZygoteInit中声明了nativeZygoteInit方法;

public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
       RuntimeInit.commonInit();
       ZygoteInit.nativeZygoteInit();//
       return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
    }
    
private static final native void nativeZygoteInit();

很明显nativeZygoteInit()是JNI方法(关于JNI见另一篇文章Android进阶知识树——JNI和So库开发),他在AndroidRuntime中完成方法动态注册,nativeZygoteInit中对应c文件中com_android_internal_os_ZygoteInit_nativeZygoteInit()方法

int register_com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env)
{
    const JNINativeMethod methods[] = {
        { "nativeZygoteInit", "()V",
            (void*) com_android_internal_os_ZygoteInit_nativeZygoteInit },
    };
    return jniRegisterNativeMethods(env, "com/android/internal/os/ZygoteInit",
        methods, NELEM(methods));
}

static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit();
}

在com_android_internal_os_ZygoteInit_nativeZygoteInit()方法中调用gCurRuntime.onZygoteInit(),这里的gCurRuntime是AppRuntime对象,它继承AndroidRuntime,在AndroidRuntime的构造函数中被初始化,AppRuntime类在app_main中实现

class AppRuntime : public AndroidRuntime
{
virtual void onZygoteInit()    {
       sp<ProcessState> proc = ProcessState::self();
        proc->startThreadPool();
    }
}

在onZygoteInit()中调用ProcessState类的startThreadPool(),startThreadPool()中调用

void ProcessState::spawnPooledThread(bool isMain){
    if (mThreadPoolStarted) {
        String8 name = makeBinderThreadName();
        sp<Thread> t = new PoolThread(isMain);
        t->run(name.string());
    }
}

在spawnPooledThread()中使用makeBinderThreadName()生成线程名称,然后创建PoolThread线程并执行线程

class PoolThread : public Thread{
protected:
    virtual bool threadLoop()
    {
        IPCThreadState::self()->joinThreadPool(mIsMain); 
        return false;
    }
    const bool mIsMain;
};

PoolThread继承Thread类,启动PoolThread对象就创建了一个新的线程,在PoolThread的threadLoop()方法中调用IPCThreadState的joinThreadPool()方法将创建的线程加入Binder线程吃中,那么新创建的应用进程就支持Binder进程通行了;

总结一下整个进程启动的过程:

  1. AMS判断当前进程是否启动,对未启动的进程发送请求
  2. 首先根据程序的pid设置并赋值用户组gids
  3. 将entryPoint赋值为ActivityThread的路径,然后开始执行进程启动
  4. 在与zygote交互中,首先根据设置的abi连接zygote进程中的socket,并判断是匹配主模式还是辅模式,连接成功后返回zygoteState对象
  5. 使用zygoteState将请求参数写入zygote的Socket中,zygote进程中读取请求的信息保存在数组中
  6. 使用参数数组创建Argument对象,并fork出程序进程,从而启动程序进程
  7. 进程启动后调用ZygotezInit.zygoteInit()方法,内部初始化Binder线程池实现进程通信,然后反射获取ActivityThread.main()方法,完成新进程的初始化

你可能感兴趣的:(Android高级进阶之旅)