Android 系统启动流分析 & Zygote启动流程分析

30 篇文章 0 订阅
22 篇文章 7 订阅

本文是基于Android 7.1进行分析      

Zygote在Android系统扮演着不可或缺的角色,Android系统的启动首先需要Zygote参与,比如启动SystemService , 还有一个就是孵化应用的进程,比如我们创建一个Activity也是需要Zygote参与.     

Zygote 启动分为两个部分:

1.Native程序涉及文件

system/core/ini/service.cpp 
system/core/rootdir/init.rc
system/core/rootdir/init.zygote64_32.rc
frameworks/base/cmds/app_process/Android.mk
frameworks/base/core/jni/AndroidRuntime.cpp

2.Java程序 涉及文件路径

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
frameworks/base/services/java/com/android/server/SystemServer.java
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

我们先看一下系统启动的流程图先有一个大概的了解

 

 

一.底层程序

那么Zygote是怎么启动的? 首先是开机的时候会Linux会先启动init进行,这也是手机开机的第一个进程,这个进程启动之后会去加载启动文件init.rc 而init进程的源代码位于 system/core/ini/service.cpp 文件,是由 Service::Start()函数来解释init.rc文件中的命令,而pid_t pid = fork(); 是 0 的时候则返回的是子线程.非0 返回的是父进程.

bool Service::Start() {
    ......省略代码.........
    pid_t pid = fork();
    if (pid == 0) {
        umask(077);

        for (const auto& ei : envvars_) {
            add_environment(ei.name.c_str(), ei.value.c_str());
        }
 
        for (const auto& si : sockets_) {
            int socket_type = ((si.type == "stream" ? SOCK_STREAM :
                                (si.type == "dgram" ? SOCK_DGRAM :
                                 SOCK_SEQPACKET)));
            const char* socketcon =
                !si.socketcon.empty() ? si.socketcon.c_str() : scon.c_str();
 
            int s = create_socket(si.name.c_str(), socket_type, si.perm,
                                  si.uid, si.gid, socketcon);
            if (s >= 0) {
                PublishSocket(si.name, s);
            }
        }
      ......省略代码.........
    return true;
}

我们来查看一下init.rc文件 文件位置在 system/core/rootdir/ 文件夹下 

查看一下文件夹结构

tree rootdir
rootdir
├── Android.mk
├── asan.options
├── asan.options.off.template
├── etc
│   ├── hosts
│   ├── public.libraries.android.txt
│   └── public.libraries.wear.txt
├── fastbootinit
│   ├── Android.mk
│   └── init.rc
├── init-debug.rc
├── init.environ.rc.in
├── init.rc
├── init.usb.configfs.rc
├── init.usb.rc
├── init.zygote32_64.rc
├── init.zygote32.rc
├── init.zygote64_32.rc
├── init.zygote64.rc
└── ueventd.rc

2 directories, 18 files

打开 init.rc如下会发现其中要使用的具体是那个.rc文件 需要${ro.zygote} 决定


import /init.environ.rc
import /init.usb.rc
import /init.${ro.hardware}.rc
import /init.usb.configfs.rc
import /init.${ro.zygote}.rc

${ro.zygote} 这个字段有两种方式可以查看到 

第一种先编译一下需要选中的版本从下面可以看到ro.zygote=zygote64_32 ,那么毫无疑问我编译系统使用的将会是init.zygote64_32.rc

./out/target/product/msmXXX/root/default.prop:9:ro.zygote=zygote64_32
./out/target/product/msmXXX/root/init.rc:11:import /init.${ro.zygote}.rc

第二种方式 build/target/product/ 下面如果我们编译的是 64位的 ro.zygote=zygote64_32,如果是 minimal 或者 tiny版本用的是 ro.zygote=zygote32

build$ grep "ro.zygote" . -rn
./target/product/core_64_bit.mk:30:PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.zygote=zygote64_32
./target/product/core_minimal.mk:118:    ro.zygote=zygote32
./target/product/core_tiny.mk:108:    ro.zygote=zygote32

因我编译的是 64位的所以使用的是 system/core/rootdir/init.zygote64_32.rc 进行的讲解

打开init.zygote64_32.rc 文件

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
    class main
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    writepid /dev/cpuset/foreground/tasks

service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
    class main
    socket zygote_secondary stream 660 root system
    onrestart restart zygote
    writepid /dev/cpuset/foreground/tasks

关于上面的代码 我们来逐个分析一下

关键字service告诉init进程创建一个名为"zygote"的进程,这个zygote进程要执行的程序是/system/bin/app_process64.

"class main"表示执行system/bin/app_process64后调用main方法.

socket关键字表示这个zygote进程需要一个名称为"zygote"的socket资源(因为JavaZygote和nativeZygote 使用的是 socke 通讯)

进入烧录好的系统后可以在/dev/socket目录下看到有一个名为zygote的文件 

onrestart关键字表示这个zygote进程重启时需要执行的命令

writepid关键字表示需要重写系统pid。

那么接下来app_process64 可执行程序是在什么地方生成的那?

全局搜索发现是 frameworks/base/cmds/app_process/Android.mk 中有发现,原来app_process64 或者app_process32 是由我们编译的版本决定的,编译的是 app_main.cpp

LOCAL_SRC_FILES:= \
    app_main.cpp
LOCAL_MODULE_STEM_32 := app_process32
LOCAL_MODULE_STEM_64 := app_process64

查看 app_main.cpp  中的main 方法我们发现 main函数参数不同 启动的线程也是不同的

int main(int argc, char* const argv[])
{
    .....省略代码......
    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;
        }
    }

  .....省略代码......
  
   // 开启 ZygoteInit 
    if (zygote) {     
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        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.");
        return 10;
    }
}

在 app_main.cpp 首行可以看到 AppRuntime 是内部类继承于 AndroidRuntime.cpp

class AppRuntime : public AndroidRuntime {

}

因此 runtime.start("com.android.internal.os.ZygoteInit", args, zygote); 需要查看  AndroidRuntime类中的 start() 方法

frameworks/base/core/jni/AndroidRuntime.cpp

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
.........省略代码...........
   //启动system Service
    static const String8 startSystemServer("start-system-server");
.........省略代码...........
    //注册JNI
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
   //启动虚拟机
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);

.........省略代码...........
   //启动 com.android.internal.os.ZygoteInit 的main方法

    char* slashClassName = toSlashClassName(className);
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
        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 {
            env->CallStaticVoidMethod(startClass, startMeth, strArray);

#if 0
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
#endif
        }
    }
.........省略代码...........
}

由上面的代码我们查看到 在AndroidRuntime.cpp 中启动了Java 虚拟机和system -Service 然后 然后启动了Java虚拟机器调用了

com.android.internal.os.ZygoteInit中的main方法.由此我们进入到了 Java代码层面.

 

二.Java程序

下面查看ZygoteInit.java 类中的main方法

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

ZygoteInit中的main方法主要干了6件事:

1.registerZygoteSocket,

2.调用preload加载资源,

3.利用gcAndFinalize初始化gc,

4.启动SystemServer,

5.调用runSelectLoop运行Zygote进程选择的looper,

6.关闭和清理zygote sockets

    public static void main(String argv[]) {
        try {
         ...........省略代码.........
            //1.registerZygoteSocket
            registerZygoteSocket(socketName);
           //2.调用preload加载资源
            preload();
           //3.利用gcAndFinalize初始化gc
            gcAndFinalize();
           //4.启动SystemServer
            if (startSystemServer) {
                startSystemServer(abiList, socketName);
            }
            //5.调用runSelectLoop运行Zygote进程选择的looper
            runSelectLoop(abiList);
            //6.关闭和清理zygote sockets
            closeServerSocket();
        } catch (MethodAndArgsCaller caller) {
            caller.run();
        } catch (Throwable ex) {
            Log.e(TAG, "Zygote died with exception", ex);
            closeServerSocket();
            throw ex;
        }
    }

我们先看看runSelectLoop方法 进入到死循环阻塞等待消息处理, 重点关注runOnce函数

  private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
        ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
        //死循环 等待接受处理消息
        while (true) {
           ..........省略代码.......
            for (int i = pollFds.length - 1; i >= 0; --i) {
           ..........省略代码.......
                if (i == 0) {
                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
                    peers.add(newPeer);
                    fds.add(newPeer.getFileDesciptor());
                } else {
                    //runOnce
                    ..........省略代码.......
                    //runOnce
                    boolean done = peers.get(i).runOnce();
                    if (done) {
                        peers.remove(i);
                        fds.remove(i);
                    }
                }
            }
        }
    }

 

ZygoteConnection.java类 runOnce();方法

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

    boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
        ..........省略代码.......
        try {
            parsedArgs = new Arguments(args);
            //返回fork出来的进程id
            pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                    parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                    parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
                    parsedArgs.appDataDir);
        } catch (ErrnoException ex) {
            logAndPrintError(newStderr, "Exception creating pipe", ex);
        } 
        ..........省略代码.......
        //我们看到 pid == 0 处理的是子进程 不等0 是父进程
        try {
            if (pid == 0) {
                // in child
                IoUtils.closeQuietly(serverPipeFd);
                serverPipeFd = null;
                handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
                return true;
            } else {
                // in parent...pid of < 0 means failure
                IoUtils.closeQuietly(childPipeFd);
                childPipeFd = null;
                return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
            }
        } 
        ..........省略代码.......
    }

可以发现  pid == 0 处理的是子进程 不等0 是父进程 ,我们可以断定的是Zygote启动一个looper一直在等待带消息通过runOnce方法处理每次传递的消息决定返回的是子线程还是父进程

 

我们再看下 启动SystemServer  startSystemServer(abiList, socketName); 来创建一个新的进程来启动SystemServer组件,返回值pid如果是 0的就是子进程 非0就是父进程 .

  private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {
        ...........省略代码.......
      String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,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 {
            /* Request to fork the system server process */
            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);
            }
             // 启动SystemService 和 启动Binder机制
            handleSystemServerProcess(parsedArgs);
        }
        return true;
    }

上面的代码中我们注意handleSystemServerProcess(parsedArgs)这个方法 进方法查看执行了RuntimeInit.zygoteInit()方法


    private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {
          .........省略代码......
            /*
             * Pass the remaining arguments to SystemServer.
             */
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
           .........省略代码......
    }

进入到 RuntimeInit.zygoteInit() 方法查看到         nativeZygoteInit()是启动了Binder机制 ,  applicationInit(targetSdkVersion, argv, classLoader);开启了SystemServer

    public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        .........省略代码......
        commonInit();
        //此处开启Binder机制
        nativeZygoteInit();
        //启动SystemService
        applicationInit(targetSdkVersion, argv, classLoader);
    }




  private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
         .........省略代码......
        invokeStaticMain(args.startClass, args.startArgs, classLoader);
    }





 private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        Class<?> cl;
        try {
            //cls 是 com.android.server.SystemServer 类
            cl = Class.forName(className, true, classLoader);
        } 
        Method m;
        try {
            //执行 com.android.server.SystemServer 类中的main方法
            m = cl.getMethod("main", new Class[] { String[].class });
        } 
        int modifiers = m.getModifiers();
        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
            throw new RuntimeException(
                    "Main method is not public and static on " + className);
        }
    }

我们看到执行的路径是 com.android.server.SystemServer 类

我们查看一下SystemServer.java类

frameworks/base/services/java/com/android/server/SystemServer.java

   public static void main(String[] args) {
        new SystemServer().run();
    }

run方法比较大 基本上是 初始化设置一些系统属性、准备MainLooper、初始化system context对象、创建system service manager;启动各种service

private void run() {
        try {
            ........省略代码.......
            //设置一些系统属性
            if (!SystemProperties.get("persist.sys.language").isEmpty()) {
                final String languageTag = Locale.getDefault().toLanguageTag();

                SystemProperties.set("persist.sys.locale", languageTag);
                SystemProperties.set("persist.sys.language", "");
                SystemProperties.set("persist.sys.country", "");
                SystemProperties.set("persist.sys.localevar", "");
            }
            ........省略代码.......
            //2、准备MainLooper
            Looper.prepareMainLooper();
            // Initialize native services.
            System.loadLibrary("android_servers");
            ........省略代码.......
            //3、初始化system context
            createSystemContext();
            ........省略代码.......
            //4、创建system service manager
            mSystemServiceManager = new SystemServiceManager(mSystemContext);
            mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }

        // Start services.
        try {
            ........省略代码.......
            //启动各种service
            startBootstrapServices();
            startCoreServices();
            //joe add here start serevice reoder for fastboot 20180830
            if(SystemProperties.getBoolean("ro.quectel.bootfast", false)){                
                startOtherServices_reOrgnize();
				
            }else{
		   startOtherServices();
            }
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }
        // Loop forever.
        Looper.loop();

    }

其中SystemServer中有  private void startOtherServices() 方法 有mActivityManagerService.systemReady(Runnable)方法

此方法开启的  System UI ,网络状态 等等等.

mActivityManagerService.systemReady(new Runnable() {
            @Override
            public void run() {
                ...........省略代码........
                //开启UI
                try {
                    startSystemUi(context);
                } catch (Throwable e) {
                    reportWtf("starting System UI", e);
                }
                //开启网络
                try {
                    if (networkScoreF != null) networkScoreF.systemReady();
                } catch (Throwable e) {
                    reportWtf("making Network Score Service ready", e);
                }
                try {
                    if (networkManagementF != null) networkManagementF.systemReady();
                } catch (Throwable e) {
                    reportWtf("making Network Managment Service ready", e);
                }
                try {
                    if (networkStatsF != null) networkStatsF.systemReady();
                } catch (Throwable e) {
                    reportWtf("making Network Stats Service ready", e);
                }
                try {
                    if (networkPolicyF != null) networkPolicyF.systemReady();
                } catch (Throwable e) {
                    reportWtf("making Network Policy Service ready", e);
                }
                try {
                    if (connectivityF != null) connectivityF.systemReady();
                } catch (Throwable e) {
                    reportWtf("making Connectivity Service ready", e);
                }
}

接下来我们再来查看一下 ActivityManagerService.java  中的 systemReady 方法

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

    public void systemReady(final Runnable goingCallback) {
      .........省略代码......
        synchronized (this) {
        .........省略代码......
            //启动桌面
            startHomeActivityLocked(currentUserId, "systemReady");
        }
         .........省略代码......
    }

由上面的代码我们查看到启动了桌面应用程序,到此启动流程基本追述完毕.

Zygote简单总结一下:
   1. 系统启动时init进程会创建Zygote进程,Zygote进程会Fork出System进程和创建虚拟机也会创建Fork进程.
   2. Zygote进程会首先创建一个SystemServer进程,SystemServer进程负责启动系统的关键服务,Android应用程序通过ActivityManagerService先调用java层的Zygote服务然后java层的Zygote层通过Socket与底层Zygote进程为这个应用程序创建一个新的进程.

    

 

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值