在Android系统中,init进程是整个系统最先启动的进程,它的启动过程是整个系统启动过程的第一步。init进程的主要作用是启动系统服务和应用进程,其中,Zygote进程是Android系统中的一个重要进程,它主要负责预热Java虚拟机和启动应用进程。本文将着重分析init进程如何启动Zygote进程,作者将结合代码注释和示例代码,让读者更好地理解Zygote的启动流程。
init进程的启动过程
init进程是Android系统中启动最早的进程,其主要职责是启动系统服务和应用进程。在init进程的启动过程中,主要包含以下几个关键步骤:
init进程读取init.rc配置文件,执行其中的命令,启动各个系统服务。
在启动过程中,init进程会读取ro.zygote属性,判断是否需要启动Zygote进程。
如果需要启动Zygote进程,init进程则会执行如下命令:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
如上所示,init进程启动Zygote进程的关键步骤主要涉及读取ro.zygote属性、启动命令的执行和与Zygote进程的连接。下面我们将逐一进行讲解。
读取ro.zygote属性
在启动过程中,init进程会通过读取ro.zygote属性的方式来判断是否需要启动Zygote进程。ro.zygote属性是一个系统属性,它的值通常是"/system/bin/app_process32"或"/system/bin/app_process64",用于指定Zygote进程的路径。
在读取ro.zygote属性时,init进程会调用getConfigurationProperty()方法,该方法会读取/system/build.prop和/prop/*.prop等多个属性文件,并将结果缓存在静态变量中,以提升系统启动速度。
/**
* Returns the property value for a given key or {@code defaultValue} if no such property
* exists.
*/
static String getConfigurationProperty(String key, String defaultValue) {
if (key == null) return defaultValue;
String value = (String) sConfigKeysAndValues.get(key);
if (value == null) {
// On Android, system properties are prefixed with "ro.", whereas on ctsdevices, they are not. Since CTS is not expected to pass when running on a commercial device, we
// handle the "ro." prefix here to make it easier to perform target-independent testing.
value = SystemProperties.get("ro." + key);
if (TextUtils.isEmpty(value)) {
value = SystemProperties.get(key);
}
if (!TextUtils.isEmpty(value)) {
sConfigKeysAndValues.put(key, value);
}
}
return !TextUtils.isEmpty(value) ? value : defaultValue;
}
如上所示,getConfigurationProperty()方法是读取系统属性文件的重要方法之一,它会先从缓存中查找属性值,如果缓存中没有,则会依次读取/system/build.prop和/prop/*.prop等属性文件,并通过SystemProperties.get()方法获取属性值。
如果ro.zygote属性存在并且值不为空,则认为需要启动Zygote进程。
启动命令的执行
如果ro.zygote属性存在并且值不为空,则init进程会执行启动Zygote进程的命令:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
上述命令的核心是执行/system/bin/app_process命令,并启动Zygote进程。下面,我们来详细解析/system/bin/app_process命令的原理。
app_process命令的原理
app_process命令是Android系统中启动Zygote进程的关键命令,它主要负责预热Java虚拟机和启动应用进程。下面,我们来详细了解app_process命令的原理。
app_process命令是通过/system/bin/app_process.sh脚本来实现的,具体实现过程如下:
# 构造CLASSPATH和LD_LIBRARY_PATH
MAGIC_VM_ARGS_FIRST="--runtime-args"
MAGIC_VM_ARGS_SECOND="log:logcat -s ZygoteInit"
if [ "$nice_name" = "zygote" ] ; then
export LD_LIBRARY_PATH=/system/lib64:/system/lib
CLASSPATH=$SYSTEMSERVERCLASSPATH
else
CLASSPATH=$ANDROID_ROOT/$SYSTEMSERVERCLASSPATH:$BOOTCLASSPATH
export ANDROID_ROOT
fi
export CLASSPATH LD_LIBRARY_PATH
通过读取/android_root/prop文件中的ro.debuggable属性、/system/lib/libz.so库和/system/bin/debuggerd程序来判断是否需要启用调试模式。
添加/system/bin/config文件中的-Djava.awt.headless=true参数,并构造启动Zygote进程的命令。
# 添加-Djava.awt.headless=true
args="$args -Djava.awt.headless=true"
# 构造启动Zygote进程的命令
exec $ZYGOTE_BINARY $ARGS_FOR_ZYGOTE
$MAGIC_VM_ARGS_FIRST
$args
$MAGIC_VM_ARGS_SECOND
"${debug_flags[@]}"
如上所示,通过构造CLASSPATH和LD_LIBRARY_PATH环境变量、判断是否启用调试模式以及构造启动Zygote进程的命令,app_process命令完成了Java虚拟机的预热和Zygote进程的启动。
与Zygote进程的连接
在启动Zygote进程后,init进程会通过Binder机制和Impersonation进行身份验证,与Zygote进程建立连接,并执行如下命令:
write /sys/android_power/request_state 0
目的是让Zygote进程能够释放设备资源,并准备就绪,等待应用进程的请求。在连接建立完成后,init进程会通过Binder机制向Zygote进程发送启动应用进程的请求。
总结
本文主要针对Android系统启动流程中init进程如何启动Zygote进程这个重要的问题展开了详细的讲解。作者结合实际代码,对相关知识点进行了解析,包括ro.zygote属性的读取、app_process命令的原理、与Zygote进程的连接等方面。在了解了这些内容后,读者应该能够更深入地理解Android系统的启动过程,并在实际开发中做出更加明智的决策。
参考资料:
Android Framework源码:https://cs.android.com/android/platform/superproject/
Android Developers官方文档:https://developer.android.com/docs