Android系统启动——Zygote启动

Posted cao_null

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android系统启动——Zygote启动相关的知识,希望对你有一定的参考价值。

上一篇讲到了init启动Zygote的过程,这次分析Zygote

涉及类

/frameworks/base/cmds/app_process/android.mk

/frameworks/base/cmds/app_process/app_main.cpp

/frameworks/base/core/jni/AndroidRuntime.cpp

/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

/frameworks/base/core/java/com/android/internal/os/ZygoteServer.java

//frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

执行到启动app_process64,我们打开app_process/Android.mk

//frameworks/base/cmds/app_process/Android.mk


LOCAL_PATH:= $(call my-dir)

app_process_common_shared_libs := \\
    libandroid_runtime \\
    libbinder \\
    libcutils \\
    libdl \\
    libhwbinder \\
    liblog \\
    libnativeloader \\
    libutils \\

app_process_common_shared_libs += \\
    libwilhelm \\

app_process_common_static_libs := \\
    libsigchain \\

//源文件
app_process_src_files := \\
    app_main.cpp \\

app_process_cflags := \\
    -Wall -Werror -Wunused -Wunreachable-code

app_process_ldflags_32 := \\
    -Wl,--version-script,art/sigchainlib/version-script32.txt -Wl,--export-dynamic
app_process_ldflags_64 := \\
    -Wl,--version-script,art/sigchainlib/version-script64.txt -Wl,--export-dynamic

include $(CLEAR_VARS)

LOCAL_SRC_FILES:= $(app_process_src_files)

LOCAL_LDFLAGS_32 := $(app_process_ldflags_32)
LOCAL_LDFLAGS_64 := $(app_process_ldflags_64)

LOCAL_SHARED_LIBRARIES := $(app_process_common_shared_libs)

LOCAL_WHOLE_STATIC_LIBRARIES := $(app_process_common_static_libs)

//32和64位都是同一个
LOCAL_MODULE:= app_process
LOCAL_MULTILIB := both
LOCAL_MODULE_STEM_32 := app_process32
LOCAL_MODULE_STEM_64 := app_process64

LOCAL_CFLAGS += $(app_process_cflags)

include $(BUILD_EXECUTABLE)

...

接下来是app_main

//app_main.cpp


int main(int argc, char* const argv[])

    ...

    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    
    //忽略第一个参数,然后组装参数
    
    // --zygote : 启动zygot模式
    // --start-system-server : 启动 system server.
    // --application : 启动application模式
    // --nice-name : 进程的nice name.

    ...

    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;

    ++i;  // Skip unused "parent dir" argument.
    //遍历参数设置状态
    while (i < argc) 
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) 
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
         else if (strcmp(arg, "--start-system-server") == 0) 
            startSystemServer = true;
         else if (strcmp(arg, "--application") == 0) 
            application = true;
         else if (strncmp(arg, "--nice-name=", 12) == 0) 
            niceName.setTo(arg + 12);
         else if (strncmp(arg, "--", 2) != 0) 
            className.setTo(arg);
            break;
         else 
            --i;
            break;
        
    

    Vector<String8> args;
    if (!className.isEmpty()) 
        // 非zygote模式,参数传给应用 application
        
        args.add(application ? String8("application") : String8("tool"));
        runtime.setClassNameAndArgs(className, argc - i, argv + i);

        if (!LOG_NDEBUG) 
          String8 restOfArgs;
          char* const* argv_new = argv + i;
          int argc_new = argc - i;
          for (int k = 0; k < argc_new; ++k) 
            restOfArgs.append("\\"");
            restOfArgs.append(argv_new[k]);
            restOfArgs.append("\\" ");
          
          ALOGV("Class name = %s, args = %s", className.string(), restOfArgs.string());
        
     else 
        //这是 zygote 模式.
        maybeCreateDalvikCache();

        if (startSystemServer) 
            args.add(String8("start-system-server"));
        

        char prop[PROP_VALUE_MAX];
        if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) 
            LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
                ABI_LIST_PROPERTY);
            return 11;
        

        String8 abiFlag("--abi-list=");//制定abi
        abiFlag.append(prop);
        args.add(abiFlag);

        // In zygote mode, pass all remaining arguments to the zygote
        // main() method.
        for (; i < argc; ++i) 
            args.add(String8(argv[i]));
        
    

    if (!niceName.isEmpty()) //替换名字
        runtime.setArgv0(niceName.string(), true /* setProcName */);
    

    
    if (zygote) 
        //启动zygote
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
     else if (className) 
        //启动RuntimeInit
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
     else 
        fprintf(stderr, "Error: no class name or --zygote supplied.\\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
    

最终执行的是runtime.start

//app_main.cpp


class AppRuntime : public AndroidRuntime

public:
    AppRuntime(char* argBlockStart, const size_t argBlockLength)
        : AndroidRuntime(argBlockStart, argBlockLength)
        , mClass(NULL)
    
    
    ...省略其他方法,没有复写start

执行的是父类的start

//frameworks/base/core/jni/AndroidRuntime.cpp


//构造
AndroidRuntime::AndroidRuntime(char* argBlockStart, const size_t argBlockLength) :
        mExitWithoutCleanup(false),
        mArgBlockStart(argBlockStart),
        mArgBlockLength(argBlockLength)

    //初始化skia
    SkGraphics::Init();
    // There is also a global font cache, but its budget is specified by
    // SK_DEFAULT_FONT_CACHE_COUNT_LIMIT and SK_DEFAULT_FONT_CACHE_LIMIT.

    // Pre-allocate enough space to hold a fair number of options.
    mOptions.setCapacity(20);
    
    assert(gCurRuntime == NULL);        // one per process
    gCurRuntime = this;



void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)

    ...

    /* 启动虚拟机 */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    //启动
    if (startVm(&mJavaVM, &env, zygote) != 0) 
        return;
    
    //虚拟机创建完后的回调
    onVmCreated(env);

    /*
     * 注册jni方法
     */
    if (startReg(env) < 0) 
        ALOGE("Unable to register all android natives\\n");
        return;
    

    ...
    //替换路径找到ZygoteInit类
    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
    char* slashClassName = toSlashClassName(className);
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) 
        ALOGE("JavaVM unable to locate class '%s'\\n", slashClassName);
        /* keep going */
     else 
        //找到main方法
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) 
            ALOGE("JavaVM unable to find main() in '%s'\\n", className);
            /* keep going */
         else 
            //执行main
            env->CallStaticVoidMethod(startClass, startMeth, strArray);

#if 0
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
#endif
        
    
    //释放资源
    free(slashClassName);

    ...



int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)

    ...设置参数等
    //启动JVM虚拟机
    if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) 
        ALOGE("JNI_CreateJavaVM failed\\n");
        return -1;
    

    return 0;

在这里做了关键的三步操作:

1.创建虚拟机

2.注册jni方法

3.调用main方法

最终执行java代码ZygoteInit类的main方法

/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java


public static void main(String argv[]) 
        ZygoteServer zygoteServer = new ZygoteServer();

            ...
            //注册Socket
            zygoteServer.registerServerSocket(socketName);
            //有时候不需要预加载
            // 第一次fork需要预加载
            if (!enableLazyPreload) 
                bootTimingsTraceLog.traceBegin("ZygotePreload");
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                    SystemClock.uptimeMillis());
                preload(bootTimingsTraceLog);
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                    SystemClock.uptimeMillis());
                bootTimingsTraceLog.traceEnd(); // ZygotePreload
             else 
                Zygote.resetNicePriority();
            

            ...
            //启动SystemServer
            if (startSystemServer) 
                //最终调用nativeForkSystemServer,在native层启动SystemServer,不展开了
                startSystemServer(abiList, socketName, zygoteServer);
            
            //开始监听孵化请求
            Log.i(TAG, "Accepting command socket connections");
            zygoteServer.runSelectLoop(abiList);

            zygoteServer.closeServerSocket();
         catch (Zygote.MethodAndArgsCaller caller) 
            caller.run();
         catch (Throwable ex) 
            Log.e(TAG, "System zygote died with exception", ex);
            zygoteServer.closeServerSocket();
            throw ex;
        
    

startSystemServer负责启动SystemServer

/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java


private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)
            throws Zygote.MethodAndArgsCaller, RuntimeException 
        ...

        //参数组装
        String args[] = //注意没有
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010",
            "--capabilities=" + capabilities + "," + capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "com.android.server.SystemServer",
        ;
        ZygoteConnection.Arguments parsedArgs = null;

        int pid;

        try 
            ...
            //通过参数fork SystemServer
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
         catch (IllegalArgumentException ex) 
            throw new RuntimeException(ex);
        

        /* For child process */
        if (pid == 0) 
            if (hasSecondZygote(abiList)) 
                waitForSecondaryZygote(socketName);
            

            zygoteServer.closeServerSocket();
            //这里继续处理SystemServer相关
            handleSystemServerProcess(parsedArgs);
        

        return true;
    

先看参数部分String args[]没有配置--invoke-with

//frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java


//内部类
static class Arguments 

    /** from --invoke-with */
        String invokeWith;

    Arguments(String args[]) throws IllegalArgumentException 
            parseArgs(args);
        

    private void parseArgs(String args[])
                throws IllegalArgumentException 
            int curArg = 0;

            boolean seenRuntimeArgs = false;

            for ( /* curArg */ ; curArg < args.length; curArg++) 
                String arg = args[curArg];

                if (arg.equals("--")) 
                    curArg++;
                    break;
                 else if (arg.startsWith("--setuid=")) 
            ...
            //所以invokeWith是null
             else if (arg.equals("--invoke-with")) 
                    if (invokeWith != null) 
                        throw new IllegalArgumentException(
                                "Duplicate arg specified");
                    
                    try 
                        invokeWith = args[++curArg];
                     catch (IndexOutOfBoundsException ex) 
                        throw new IllegalArgumentException(
                                "--invoke-with requires argument");
                    
                

handleSystemServerProcess继续处理SystemServer

//frameworks/base/core/java/com/android/internal/os/ZygoteInit.java


private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws Zygote.MethodAndArgsCaller 

        ...

        if (parsedArgs.invokeWith != null) 
            ...
         else 
            ClassLoader cl = null;
            if (systemServerClasspath != null) 
                cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);

                Thread.currentThread().setContextClassLoader(cl);
            
                //最终执行这
             ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
        

        /* should never reach here */
    


public static final void zygoteInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) throws Zygote.MethodAndArgsCaller 
        if (RuntimeInit.DEBUG) 
            Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
        

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
        //重点来到RuntimeInit
        RuntimeInit.redirectLogStreams();

        RuntimeInit.commonInit();
        ZygoteInit.nativeZygoteInit();//native一些初始化,包含binder
        RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
    

再看看RuntimeInit

//frameworks/base/core/java/com/android/internal/os/RuntimeInit.java


//各种通用初始化
protected static final void commonInit() 
        if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");

        Thread.setUncaughtExceptionPreHandler(new LoggingHandler());
        Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler());

        TimezoneGetter.setInstance(new TimezoneGetter() 
            @Override
            public String getId() 
                return SystemProperties.get("persist.sys.timezone");
            
        );
        TimeZone.setDefault(null);

        LogManager.getLogManager().reset();
        new AndroidConfig();

        String userAgent = getDefaultUserAgent();
        System.setProperty("http.agent", userAgent);

        NetworkManagementSocketTagger.install();

        String trace = SystemProperties.get("ro.kernel.android.tracing");
        if (trace.equals("1")) 
            Slog.i(TAG, "NOTE: emulator trace profiling enabled");
            Debug.enableEmulatorTraceOutput();
        

        initialized = true;
    


protected static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws Zygote.MethodAndArgsCaller 

        nativeSetExitWithoutCleanup(true);

        VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);

        final Arguments args;
        try 
            args = new Arguments(argv);
         catch (IllegalArgumentException ex) 
            Slog.e(TAG, ex.getMessage());
            // let the process exit
            return;
        

        // The end of of the RuntimeInit event (see #zygoteInit).
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        //关键在这
        // Remaining arguments are passed to the start class's static main
        invokeStaticMain(args.startClass, args.startArgs, classLoader);
    


private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
            throws Zygote.MethodAndArgsCaller 
        Class<?> cl;

        try 
            cl = Class.forName(className, true, classLoader);
         catch (ClassNotFoundException ex) 
            throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
        

        Method m;
        try 
            m = cl.getMethod("main", new Class[]  String[].class );
         catch (NoSuchMethodException ex) 
            throw new RuntimeException(
                    "Missing static main on " + className, ex);
         catch (SecurityException ex) 
            throw new RuntimeException(
                    "Problem getting static main on " + className, ex);
        

        int modifiers = m.getModifiers();
        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) 
            throw new RuntimeException(
                    "Main method is not public and static on " + className);
        
        //抛出了异常
        throw new Zygote.MethodAndArgsCaller(m, argv);
    

ZygoteInit.java的main方法catch了这个异常,然后执行了run

/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

public static void main(String argv[]) 
    if (startSystemServer) 
                startSystemServer(abiList, socketName, zygoteServer);
            
    
catch (Zygote.MethodAndArgsCaller caller) 
            caller.run();
        


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 
                //简单的invoke方法
                mMethod.invoke(null, new Object[]  mArgs );
             catch (IllegalAccessException ex) 
                throw new RuntimeException(ex);
             catch (InvocationTargetException ex) 
                Throwable cause = ex.getCause();
                if (cause instanceof RuntimeException) 
                    throw (RuntimeException) cause;
                 else if (cause instanceof Error) 
                    throw (Error) cause;
                
                throw new RuntimeException(ex);
            
        
    

综上所示,最终执行了SystemServer的main方法

ZygoteServer都做了什么

//frameworks/base/core/java/com/android/internal/os/ZygoteServer.java



class ZygoteServer 
    public static final String TAG = "ZygoteServer";

    private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_";

    private LocalServerSocket mServerSocket;

    ZygoteServer() 
    

    void registerServerSocket(String socketName) 
        if (mServerSocket == null) 
            int fileDesc;
            final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
            try 
                String env = System.getenv(fullSocketName);
                fileDesc = Integer.parseInt(env);
             catch (RuntimeException ex) 
                throw new RuntimeException(fullSocketName + " unset or invalid", ex);
            

            try 
                FileDescriptor fd = new FileDescriptor();
                fd.setInt$(fileDesc);
                //创建Socker
                mServerSocket = new LocalServerSocket(fd);
             catch (IOException ex) 
                throw new RuntimeException(
                        "Error binding to local socket '" + fileDesc + "'", ex);
            
        
    

    ...

    void runSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller 
        ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();

        fds.add(mServerSocket.getFileDescriptor());
        peers.add(null);

        while (true) 
            StructPollfd[] pollFds = new StructPollfd[fds.size()];
            for (int i = 0; i < pollFds.length; ++i) 
                pollFds[i] = new StructPollfd();
                pollFds[i].fd = fds.get(i);
                pollFds[i].events = (short) POLLIN;
            
            try 
                //阻塞操作一直到pollFds发生变化,则往下走,有点像handler
                Os.poll(pollFds, -1);
             catch (ErrnoException ex) 
                throw new RuntimeException("poll failed", ex);
            
            for (int i = pollFds.length - 1; i >= 0; --i) 
                //判断socket是否有变化,有变化继续执行
                if ((pollFds[i].revents & POLLIN) == 0) 
                    continue;
                
                if (i == 0) 
                    //处理来自客户端的连接
                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
                    peers.add(newPeer);
                    fds.add(newPeer.getFileDesciptor());
                 else 
                    //处理具体的操作
                    boolean done = peers.get(i).runOnce(this);
                    if (done) 
                        peers.remove(i);
                        fds.remove(i);
                    
                
            
        
    

到这Zygote的启动就告一段落了,接下来还有很重要的SystemServer,以及binder创建,还有AMS创建Activity联动,后续分析

以上是关于Android系统启动——Zygote启动的主要内容,如果未能解决你的问题,请参考以下文章

Android系统启动——Zygote启动

Android系统启动-zygote篇

Android Zygote 从何而来?揭开Android系统启动的面纱

Android 进阶——系统启动之Android进程造物者Zygote 进程启动详解

Android 进阶——系统启动之Android进程造物者Zygote 进程启动详解

Android 进阶——系统启动之Android进程造物者Zygote 进程启动详解