Zygote的启动之二ZygoteInit

Android  源码分析  2023年8月5日 am8:00发布1年前 (2023)更新 91es.com站长
146 0 0

前言

Android系统中,所有的应用程序以及SystemServer都是由Zygote进程孕育(fork)出来的。接上文,上文介绍从Native世界进入了Java世界。而且java世界的大门就是ZygtoeInit.java。这次我们看ZygtoeInit中处理了哪些功能。

Android P

正文

涉及文件

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
frameworks\base\core\jni\com_android_internal_os_Zygote.cpp
frameworks\base\core\jni\com_android_internal_os_ZygoteInit.cpp

Zygote的启动之二ZygoteInit

接上一篇《Zygote的启动之一app_main》,启动了com.android.internal.os.ZygoteInit进入了Java的世界,

runtime.start("com.android.internal.os.ZygoteInit", args, zygote);

args中的参数

{"start-system-server", "--abi-list=arm64-v8a", "--socket-name=zygote", "--enable-lazy-preload"}

进入ZygoteInit.java世界,启动的依旧是main()函数。

public static void main(String argv[]) {
    //[1]创建ZygoteServer
    ZygoteServer zygoteServer = new ZygoteServer();
    final Runnable caller;
    try {
        for (int i = 1; i < argv.length; i++) {
            //是否有start-system-server参数,有就需要启动startSystemServer
            if ("start-system-server".equals(argv[i])) {
                //是否启动SystemServer
                startSystemServer = true;
            } else if ("--enable-lazy-preload".equals(argv[i])) {
                //是否延迟加载
                enableLazyPreload = true;
            } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                //32位 --abi-list=armeabi-v7a,armeabi
                //64位 --abi-list=arm64-v8a
                abiList = argv[i].substring(ABI_LIST_ARG.length());
            } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
                //设置socket名
                socketName = argv[i].substring(SOCKET_NAME_ARG.length());
            } else {
                throw new RuntimeException("Unknown command line argument: " + argv[i]);
            }
        }
        //[2]注册socket
        zygoteServer.registerServerSocketFromEnv(socketName);
        //懒惰预加载,enableLazyPreload=true;
        if (!enableLazyPreload) {
            //这里暂时不走
            preload(bootTimingsTraceLog);
        } else {
            Zygote.resetNicePriority();
        }
        //[3]提前加载Resources
        preloadResources();
        //提前加载文本Resources
        preloadTextResources();
        //主动GC
        gcAndFinalize();
        //我这64位时startSystemServer= true
        if (startSystemServer) {
            //[4]创建SystemServer
            Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
            if (r != null) {
                r.run();
                return;
            }
        }
        //[5]循环中。对于zygote不会退出,至于fork的子进程,是会退出的
        caller = zygoteServer.runSelectLoop(abiList);
    } catch (Throwable ex) {
        throw ex;
    } finally {
        //关闭socket
        zygoteServer.closeServerSocket();
    }
    if (caller != null) {
        caller.run();
    }
}

上面主要是如下功能:

  1. 创建ZygoteServer

  2. 注册socket

  3. 预加载资源

  4. 创建SystemServer

  5. runSelectLoop()一直循环处理

下面就简单的走一下流程。

创建ZygoteServer

ZygoteServer zygoteServer = new ZygoteServer();

功能很简单,就是创建ZygoteServer对象,后面需要。

注册socket

zygoteServer.registerServerSocketFromEnv(socketName);

也就是处理功能都是ZygoteServer类。

socketName就是之前init.zygote64_32.rc中配置的。

64位socketName:zygote
32位socketName:zygote_secondary

就是注册了对应的socket,后面用于通信

void registerServerSocketFromEnv(String socketName) {
    if (mServerSocket == null) {
        //略
         FileDescriptor fd = new FileDescriptor();
         fd.setInt$(fileDesc);
         //创建mServerSocket
         mServerSocket = new LocalServerSocket(fd);
         mCloseSocketFd = true;
    }
}

预加载资源

//enableLazyPreload= true
if (!enableLazyPreload) {
	//暂时不走这里,后面会加载
    preload(bootTimingsTraceLog);
} else {
    Zygote.resetNicePriority();
}
//提前加载Resources
preloadResources();
//提前加载文本Resources
preloadTextResources();

提前加载系统相关的资源,这也是为啥开发中推荐优先用系统资源文件。

预加载的资源是存在framework-res.apk中。

forkSystemServer()

if (startSystemServer) {
	// fork SystemServer,并返回一个 Runnable
    Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
    if (r != null) {
        r.run();
        return;
    }
}

这里是创建出SystemServer进程,然后后面找到main()入口函数,进行启动SystemServer.java

private static Runnable forkSystemServer(String abiList, String socketName,ZygoteServer zygoteServer){
	//略
	//配置uid,gid,group等参数
    String args[] = {
        "--setuid=1000",
        "--setgid=1000",
        "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1024,1032,1065,3001,3002,3003,3006,3007,3009,3010",
        "--capabilities=" + capabilities + "," + capabilities,
        "--nice-name=system_server", //进程名
        "--runtime-args",
        "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
        "com.android.server.SystemServer", //启动类
    };
    int pid;
    try {
		//参数转换
        parsedArgs = new ZygoteConnection.Arguments(args);
        ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
        ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
		//默认为false
        boolean profileSystemServer = SystemProperties.getBoolean(
                "dalvik.vm.profilesystemserver", false);
		//fork一个进程,就是创建SystemServer
        pid = Zygote.forkSystemServer(
                parsedArgs.uid, parsedArgs.gid,
                parsedArgs.gids,
                parsedArgs.runtimeFlags,
                null,
                parsedArgs.permittedCapabilities,
                parsedArgs.effectiveCapabilities);
    } catch (IllegalArgumentException ex) {
        throw new RuntimeException(ex);
    }
    //子进程
    if (pid == 0) {
        if (hasSecondZygote(abiList)) {
            waitForSecondaryZygote(socketName);
        }
		//关闭子进程的socket
        zygoteServer.closeServerSocket();
		//处理SYstemServer进程
        return handleSystemServerProcess(parsedArgs);
    }
    return null;
}

进入handleSystemServerProcess

handleSystemServerProcess()
private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {
    if (parsedArgs.niceName != null) {
    	//设置进程名为system_server
        Process.setArgV0(parsedArgs.niceName);
    }
    //加载SystemServer类的路径
    final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
	//systemServerClasspath不为空
	if (systemServerClasspath != null) {
        performSystemServerDexOpt(systemServerClasspath);
		//profileSystemServer = false
        boolean profileSystemServer = SystemProperties.getBoolean(
                "dalvik.vm.profilesystemserver", false);
		//略
    }
	//parsedArgs.invokeWith = null
    if (parsedArgs.invokeWith != null) {
	  //不走这
    } else {
        ClassLoader cl = null;
        if (systemServerClasspath != null) {
        	//创建ClassLoader
            cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);
            Thread.currentThread().setContextClassLoader(cl);
        }
		//进入ZygoteInit.zygoteInit()
        return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
    }
}

systemServerClasspath存储的内容

/system/framework/services.jar:/system/framework/ethernet-service.jar:/system/framework/wifi-service.jar:/system/framework/com.android.location.provider.jar:/system/framework/car-frameworks-service.jar
zygoteInit()
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader){
	//略
	//native方法
    ZygoteInit.nativeZygoteInit();
	//进入applicationInit,返回Runnable
    return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
applicationInit()

此时进入了RuntimeInit.java中,我们看applicationInit()

protected static Runnable applicationInit(int targetSdkVersion, String[] argv,ClassLoader classLoader) {
	//略
    return findStaticMain(args.startClass, args.startArgs, classLoader);
}
findStaticMain()

看名字就是找到类的启动入口。

根据前面,知道className传入的是com.android.server.SystemServer

protected static Runnable findStaticMain(String className, String[] argv,ClassLoader classLoader) {
    Class<?> cl;
    try {
		//加载com.android.server.SystemServer类
        cl = Class.forName(className, true, classLoader);
    } catch (ClassNotFoundException ex) {
    }
    Method m;
    try {
		//查找main函数
        m = cl.getMethod("main", new Class[] { String[].class });
    } catch (NoSuchMethodException ex) {
    }
    int modifiers = m.getModifiers();
	//判断是否有static和public修饰
    if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
        throw new RuntimeException(
                "Main method is not public and static on " + className);
    }
    //MethodAndArgsCaller就是一个Runnable
    return new MethodAndArgsCaller(m, argv);
}

最终就创建的一个Runnable。

MethodAndArgsCaller
 static class MethodAndArgsCaller implements Runnable {
     private final Method mMethod;
     private final String[] mArgs;
     public MethodAndArgsCaller(Method method, String[] args) {
         mMethod = method;
         mArgs = args;
     }

     public void run() {
         try {
			//Method = com.android.server.SystemServer的main函数
             mMethod.invoke(null, new Object[] { mArgs });
         } catch (IllegalAccessException ex) {
			//略
		}
     }
 }

上面我们知道,fork出SystemServer之后,进行了null判断,然后启动了run()

这里用了反射

# Method = com.android.server.SystemServer的main函数
mMethod.invoke(null, new Object[] { mArgs });

到这里就算启动了com.android.server.SystemServer,并进入了main()。

疑惑
if (startSystemServer) {
	// fork SystemServer,并返回一个 Runnable
    Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
    if (r != null) {
    	//这里进入了MethodAndArgsCaller的run()
        r.run();
        //哈哈这里return
        return;
    }
}

上面fork出SystemServer后,r不为null,也就是执行了下面代码

if (r != null) {
    r.run();
    return;
}

这里竟然直接return了,那后面代码不执行?

其实不是,这个就需要看Linux中的fork的原理。上面return的只是子进程(SystemServer进程)程序,而父类进程还是会继续往下执行。也就是进入了runSelectLoop()

runSelectLoop()

//循环中。
caller = zygoteServer.runSelectLoop(abiList);

对于父进程,也就是Zygote的会进入循环中;对于子进程SystemServer在上面会return,其他子进程,会返回caller,然后退出。

Runnable runSelectLoop(String abiList) {
    ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
    ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
	//mServerSocket是之前创建的socket
    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;
        }
        for (int i = pollFds.length - 1; i >= 0; --i) {
		    //采用I/O多路复用机制,当客户端发出连接请求或者数据处理请求时,则执行continue
            if ((pollFds[i].revents & POLLIN) == 0) {
                continue;
            }
            if (i == 0) {
				//有socket客户端连接上,创建一个新的ZygoteConnection
                ZygoteConnection newPeer = acceptCommandPeer(abiList);
                peers.add(newPeer);
				//添加socket的描述符
                fds.add(newPeer.getFileDesciptor());
            } else {
                try {
				  //客户端发送了请求
                    ZygoteConnection connection = peers.get(i);
				  //这里创建了一个Runnable,是不是子进程,这里会设置
                    final Runnable command = connection.processOneCommand(this);
                    if (mIsForkChild) {
						//如果在子进程,就返回Runnable
                        return command;
                    } else {
					  //判断是否需要关闭socket
                        if (connection.isClosedByPeer()) {
                            connection.closeSocket();
                            peers.remove(i);
                            fds.remove(i);
                        }
                    }
                }
            }
        }
    }
}

runSelectLoop()是个死循环,也就是Zygote是一直存在并处理对应事物的。主要做了如下事

  1. 添加之前创建的socket并获取请求消息

  2. 进入死循环读取请求消息

  3. i == 0时,有新客户端,创建新的ZygoteConnection

  4. i != 0时,处理客户端发送的请求,如果是子进程,就返回Runnable

processOneCommand()

下面就介绍一下,当收到新的子进程创建流程。

Runnable processOneCommand(ZygoteServer zygoteServer) {
    try {
		//从socket读取命令
        args = readArgumentList();
        descriptors = mSocket.getAncillaryFileDescriptors();
    } catch (IOException ex) {
        throw new IllegalStateException("IOException on command socket", ex);
    }
	//如果没有读取到命令,socket可能断了,
    if (args == null) {
        isEof = true;
        return null;
    }
	//创建Arguments对象,这里会解析args中的命令
    parsedArgs = new Arguments(args);
	//根据参数值进行处理
    if (parsedArgs.abiListQuery) {
        handleAbiListQuery();
        return null;
    }
	//handlePreload也就是之前没有预加载的
    if (parsedArgs.preloadDefault) {
        handlePreload();
        return null;
    }
	//略
	//	fork进程
	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 {
        if (pid == 0) {//如果是子线程,进入这里
            zygoteServer.setForkChild();
            zygoteServer.closeServerSocket();
            IoUtils.closeQuietly(serverPipeFd);
            serverPipeFd = null;
            //handleChildProc
            return handleChildProc(parsedArgs, descriptors, childPipeFd,
                    parsedArgs.startChildZygote);
        } else { //如果是父进程,走这里
            IoUtils.closeQuietly(childPipeFd);
            childPipeFd = null;
            handleParentProc(pid, descriptors, serverPipeFd);
            return null;
        }
    } finally {
        IoUtils.closeQuietly(childPipeFd);
        IoUtils.closeQuietly(serverPipeFd);
    }
}

这里主要如下工作

  1. readArgumentList()从socket读取命令

  2. Arguments解析读取的命令并执行对应的功能

  3. 根据parsedArgs的信息进行fork进程

  4. 处理子进程并返回Runnable

readArgumentList()

主要是从socket中读取命令

private String[] readArgumentList()throws IOException {
    int argc;
    try {
		//socket读取一行命名
        String s = mSocketReader.readLine();
        if (s == null) {
            return null;
        }
        argc = Integer.parseInt(s);
    } catch (NumberFormatException ex) {
        Log.e(TAG, "invalid Zygote wire format: non-int at argc");
        throw new IOException("invalid wire format");
    }
    if (argc > MAX_ZYGOTE_ARGC) {
        throw new IOException("max arg count exceeded");
    }
    String[] result = new String[argc];
    for (int i = 0; i < argc; i++) {
		//读取出所有的命令
        result[i] = mSocketReader.readLine();
        if (result[i] == null) {
            throw new IOException("truncated request");
        }
    }
    return result;
}
Arguments
//创建Arguments对象,这里会解析args中的命令
parsedArgs = new Arguments(args);
Arguments(String args[]) throws IllegalArgumentException {
    parseArgs(args);
}

最终是调用parseArgs()解析命令,很长,略过,就是对命令解析并对parsedArgs的属性进行赋值。

handlePreload()

根据之前parsedArgs中解析的命令,执行对应的功能。我这里以handlePreload()为例。

if (parsedArgs.preloadDefault) {
    handlePreload();
    //返回null,也就是处理完后就不会继续执行后面的代码
    return null;
}
private void handlePreload() {=
    try {
		//判断是否有预加载过,如果有就调过,没有就执行preload()
        if (isPreloadComplete()) {
            mSocketOutStream.writeInt(1);
        } else {
            preload();
            mSocketOutStream.writeInt(0);
        }
    } catch (IOException ioe) {
        throw new IllegalStateException("Error writing to command socket", ioe);
    }
}

isPreloadComplete()返回true的前提是有执行过preload()中调用的ZygoteInit.preload(),后面会看到。

preload()
protected void preload() {
    ZygoteInit.lazyPreload();
}

哈哈 进入ZygoteInit.java

ZygoteInit.lazyPreload()
public static void lazyPreload() {
    Preconditions.checkState(!sPreloadComplete);
    preload(new TimingsTraceLog("ZygoteInitTiming_lazy", Trace.TRACE_TAG_DALVIK));
}
ZygoteInit.preload()
static void preload(TimingsTraceLog bootTimingsTraceLog) {
	//只做了一件事,preloadClasses
    preloadClasses();
	//sPreloadComplete这里赋值为true
    sPreloadComplete = true;
}

preloadClasses()看函数名就名,预加载类,就是提前加载一些类而已。

forkAndSpecialize()

这根据中parsedArgs的信息,然后fork一个新的进程。我们关注pid,不关心怎么fork。

如果pid=0,表示子进程,走处理子进程流程,返回Runnable

如果pid!=0,表示父进程,走处理父进程的流程,返回null

handleChildProc()
private Runnable handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors,
        FileDescriptor pipeFd, boolean isZygote) {
	//关闭socket通信
    closeSocket();
	//设置进程名
    if (parsedArgs.niceName != null) {
        Process.setArgV0(parsedArgs.niceName);
    }
	//一般这里为invokeWith = null
	//除非parsedArgs解析socket命令行中有对应的命令,略过,看下面
    if (parsedArgs.invokeWith != null) {
        WrapperInit.execApplication(parsedArgs.invokeWith,
                parsedArgs.niceName, parsedArgs.targetSdkVersion,
                VMRuntime.getCurrentInstructionSet(),
                pipeFd, parsedArgs.remainingArgs);
        throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned");
    } else {
		//isZygote = false,就是parsedArgs.startChildZygote
        if (!isZygote) {
			//走这里。又回到了ZygoteInit类
            return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs,
                    null /* classLoader */);
        } else {
            return ZygoteInit.childZygoteInit(parsedArgs.targetSdkVersion,
                    parsedArgs.remainingArgs, null /* classLoader */);
        }
    }
}
ZygoteInit.zygoteInit()
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
	//RuntimeInit初始化相关
    RuntimeInit.redirectLogStreams();
    RuntimeInit.commonInit();
	//native方法
    ZygoteInit.nativeZygoteInit();
	//执行applicationInit
    return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}

zygoteInit()也是不干活的,真正处理进入RuntimeInit

RuntimeInit.applicationInit()
protected static Runnable applicationInit(int targetSdkVersion, String[] argv,ClassLoader classLoader) {
    nativeSetExitWithoutCleanup(true);
    VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
    VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
	//找到static的main入口
    return findStaticMain(args.startClass, args.startArgs, classLoader);
}

也是不干活的,哈哈,这个跟上面启动com.android.server.SystemServer是找到static的mian入口一样的流程了?

最后都一样,findStaticMain()返回Runnable,然后启动run(),通过反射直接进入main()入口,也就是算启动了进程。

到这里,就基本走完了一圈,zygote也一直循环,等待着新的命令进行fork出新的进程。

参考文章

  1. Android Zygote进程的启动流程简单分析

  2. 《深入理解Android卷1(邓凡平)》

  3. zygote启动过程

  4. Android系统启动-综述

 历史上的今天

  1. 2021: 许立志:行走的肉体(0条评论)
  2. 2019: 梁漱溟:花点心思活着,人生才有意义(0条评论)
版权声明 1、 本站名称: 91易搜
2、 本站网址: 91es.com3xcn.com
3、 本站内容: 部分来源于网络,仅供学习和参考,若侵权请留言
3、 本站申明: 个人流水账日记,内容并不保证有效

暂无评论

暂无评论...

随机推荐

Android 13 MediaProvider简单记录

前言Android 9时扫描逻辑还在MediaScanner中(这块之前有介绍过),而后续Android高版本开始变化,以Android 13来说,扫描逻辑已经放在MediaProvider中了,也就是ModernMediaScanner。Android 10,11和12项目少今天就简单...

Android修改原生电话铃声

前言简单记录一下,修改Android原生默认的铃声。推荐看参考文章,这里只是个人随笔记录。正文隐藏内容!付费阅读后才能查看!¥1 ¥3多个隐藏块只需支付一次付费阅读参考文章《Android 设置铃声》《Android 设置来电铃声、通知铃声、闹钟铃声中的坑》

付志勇:我的秋天没有忧伤

我喜欢秋天胜过任何一个季节,我喜欢那弹指可破的空气、橙色明亮的阳光甚至草枯、花落、风吹过大地 我喜欢在秋天里写诗写我三十年一晃而过的光阴写我尘世里的清欢写窗外飘落的叶子渐渐覆盖住旧事 秋天让我回望过去但更多的思索将来一场繁华的凋敝是不是意味着另一场繁华...

Android.mk 用法解析整理

Android.mk 还是整理一下,有时候还是忘记了,这里只是讲解一部分,其他的自己百度或谷歌吧。 编译一个APK的Android.mk文件LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)#指定依赖的共享Java类库...

张晓风:经济学的旁听生

“什么是经济学呢?”他站在讲台上,戴眼镜,灰西装,声音平静,典型的中年学者。台下坐的是大学一年级的学生,而我,是置身在这二百人大教室里偷偷旁听的一个。从一开学我就昂奋起来,因为在课表上看见要开一门《社会科学概论》的课程,包括四位教授来设“政治”“法律”“经济”“人类学”四个讲座。想起可以重新做学...

SurfaceView和TextureView介绍

前言TextureView和SurfaceView常用于视频播放画面显示,项目中根据各种需求需要在二者中选中。这次记录一下他们之间的区别和特点。正文 个人随笔,只是简单总结,谢谢隐藏内容!评论可看后才能查看!评论可看参考文章《SurfaceView 与 TextureView ...