本文是基于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/services/java/com/android/server/SystemServer.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& 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);
} else {
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
} 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;
}
}
我们现在只看下 //4.启动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 {
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
handleSystemServerProcess(parsedArgs);
}
return true;
}
我们看到执行的路径是 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);
}
}
Zygote简单总结一下:
1. 系统启动时init进程会创建Zygote进程,Zygote进程会Fork出System进程和创建虚拟机也会创建Fork进程.
2. Zygote进程会首先创建一个SystemServer进程,SystemServer进程负责启动系统的关键服务,Android应用程序通过ActivityManagerService先调用java层的Zygote服务然后java层的Zygote层通过Socket与底层Zygote进程为这个应用程序创建一个新的进程.
作者:ChaoLi_Chen