一: Zygote概述
Zygote 进程是Android层面第一个进程(第一个art虚拟机),俗称 进程孵化器,android中所有的进程都是通过 Zygote 分裂(fork)出来的。主要是通过socket的方式与SystemServer通讯的。主要责任是:
- 预加载通用类, drawable和color资源,openGL以及共享库以及WebView
- 创建 system_server 进程
- 创建 socket,runSelectLoop 无限循环,来接收 system_server 的创建进程的命令,来分裂进程
谁创建的 Zygote 进程
Android 系统是基于 Linux系统,在android系统下,当开机的时候 Linux 会创建第一个用户空间进程 init进程。在 init 进程中 会初始化好多东西,init进程的工作是 解析 init.rc 文件,初始化很多服务
init进程 进程作用
- servic_emanager :启动 binder IPC,管理所有的 Android 系统服务
- media_server:音视频解码器
- zygote:进程孵化器,启动 jvm虚拟机 和 分裂 systemserver ,用于android中进程的孵化功能 注册底层功能的 JNI 函数到虚拟机 预加载 Java 类和资源 fork 并启动 system_server 核心进程 作为守护进程监听处理“孵化新进程”的请求
Zygote代码跟踪 android28
当zygote进程创建完毕时会执行
/frameworks/base/cmds/app_process/app_main.cpp 下面的代码
里面会加载 ZygoteInit.java 和RuntimeLnit.java两个类。
然后我们看 ZygoteInit.java 文件的main方法,下面的代码不是所有的代码,我只复制了一些关键的点
public static void main(String argv[]) {
// 创建 ZygoteServer,ZygoteServer作用是用来创建 Socket ,用来接受 创建(fork)子进程的命令
ZygoteServer zygoteServer = new ZygoteServer();
// 告诉jvm,Zygote 要开始创建了
ZygoteHooks.startZygoteNoThreadCreation();
//开启DDMS
RuntimeInit.enableDdms();
//是否是启动 SystemServer 进程的标志
boolean startSystemServer = false;
//是否是 让 Zygote 懒加载一些资源的命令
boolean enableLazyPreload = false;
for (int i = 1; i < argv.length; i++) {
// 是启动 SystemServer 的命令
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
}else if ("--enable-lazy-preload".equals(argv[i])) {
enableLazyPreload = true;
}
//...
}
//注册Socket监听,用来接受 创建(fork)子进程的命令
zygoteServer.registerServerSocketFromEnv(socketName);
// In some configurations, we avoid preloading resources and classes eagerly.
// In such cases, we will preload things prior to our first fork.
// 有些情况是需要预先加载一些类和资源的
if (!enableLazyPreload) {
bootTimingsTraceLog.traceBegin("ZygotePreload");
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
// 预加载 /system/etc/preloaded-classes 类
// 预加载资源 图片 和 颜色
// 预加载OpenGL 等等
preload(bootTimingsTraceLog);
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
bootTimingsTraceLog.traceEnd(); // ZygotePreload
} else {
Zygote.resetNicePriority();
}
// 执行 System.gc();
gcAndFinalize();
//访问安全
Zygote.nativeSecurityInit()
//沙盒存储
Zygote.nativeUnmountStorageOnInit();
// 告诉虚拟机 可以在zygote进程中创建线程了
ZygoteHooks.stopZygoteNoThreadCreation();
// fork SystemServer 进程
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
// child (system_server) process.
if (r != null) {
r.run();
return;
}
}
// socket 进入无线循环中,来接受创建进程的命令
caller = zygoteServer.runSelectLoop(abiList);
然后看 Zygote 里面的主要两个方法
- forkAndSpecialize():fork 一个新的进程
- forkSystemServer():fork 出 SystemServer进程
为什么 Zygote 要用 socket ,而不用 binder的机制呢?
fork是有规则限制的,多线程程序里不准使用fork。然后 binder 的机制是基于多线程的。参考
二:SystemServer
服务进程:是由 Zygote 分裂出来的第一个进程,Android系统多个重要的服务,比如 ActivityManagerService、PackageManagerService、WindowManagerService等等 都是在这里开启的。
SystemServer 代码
SystemServer.main的入口
// 入口
public static void main(String[] args) {
new SystemServer().run();
}
private void run() {
try {
traceBeginAndSlog("InitBeforeStartServices");
// If a device's clock is before 1970 (before 0), a lot of
// APIs crash dealing with negative numbers, notably
// java.io.File#setLastModified, so instead we fake it and
// hope that time from cell towers or NTP fixes it shortly.
if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
Slog.w(TAG, "System clock is before 1970; setting to 1970.");
SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
}
//
// Default the timezone property to GMT if not set.
//
String timezoneProperty = SystemProperties.get("persist.sys.timezone");
if (timezoneProperty == null || timezoneProperty.isEmpty()) {
Slog.w(TAG, "Timezone not set; setting to GMT.");
SystemProperties.set("persist.sys.timezone", "GMT");
}
// If the system has "persist.sys.language" and friends set, replace them with
// "persist.sys.locale". Note that the default locale at this point is calculated
// using the "-Duser.locale" command line flag. That flag is usually populated by
// AndroidRuntime using the same set of system properties, but only the system_server
// and system apps are allowed to set them.
//
// NOTE: Most changes made here will need an equivalent change to
// core/jni/AndroidRuntime.cpp
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", "");
}
// The system server should never make non-oneway calls
Binder.setWarnOnBlocking(true);
// The system server should always load safe labels
PackageItemInfo.setForceSafeLabels(true);
// Deactivate SQLiteCompatibilityWalFlags until settings provider is initialized
SQLiteCompatibilityWalFlags.init(null);
// Here we go!
Slog.i(TAG, "Entered the Android system server!");
int uptimeMillis = (int) SystemClock.elapsedRealtime();
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, uptimeMillis);
if (!mRuntimeRestart) {
MetricsLogger.histogram(null, "boot_system_server_init", uptimeMillis);
}
// In case the runtime switched since last boot (such as when
// the old runtime was removed in an OTA), set the system
// property so that it is in sync. We can | xq oqi't do this in
// libnativehelper's JniInvocation::Init code where we already
// had to fallback to a different runtime because it is
// running as root and we need to be the system user to set
// the property. http://b/11463182
SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());
// Mmmmmm... more memory!
VMRuntime.getRuntime().clearGrowthLimit();
// The system server has to run all of the time, so it needs to be
// as efficient as possible with its memory usage.
VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
// Some devices rely on runtime fingerprint generation, so make sure
// we've defined it before booting further.
Build.ensureFingerprintProperty();
// Within the system server, it is an error to access Environment paths without
// explicitly specifying a user.
Environment.setUserRequired(true);
// Within the system server, any incoming Bundles should be defused
// to avoid throwing BadParcelableException.
BaseBundle.setShouldDefuse(true);
// Within the system server, when parceling exceptions, include the stack trace
Parcel.setStackTraceParceling(true);
// Ensure binder calls into the system always run at foreground priority.
BinderInternal.disableBackgroundScheduling(true);
// Increase the number of binder threads in system_server
BinderInternal.setMaxThreads(sMaxBinderThreads);
// Prepare the main looper thread (this thread).
android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_FOREGROUND);
android.os.Process.setCanSelfBackground(false);
// 设置 SystemServer 线程的主 Looper
Looper.prepareMainLooper();
Looper.getMainLooper().setSlowLogThresholdMs(
SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);
// Initialize native services.
System.loadLibrary("android_servers");
// Initialize the system context.
// 初始化 SystemContext 后面方法会写
createSystemContext();
// Create the system service manager.
// 创建 SystemServiceManager,我们可以通过 SystemServiceManager 来获取到 各种各样的 xxServiceManager
mSystemServiceManager = new SystemServiceManager(mSystemContext);
mSystemServiceManager.setStartInfo(mRuntimeRestart,
mRuntimeStartElapsedTime, mRuntimeStartUptime);
// 把 SystemServiceManager.class 添加到 LocalServices里面
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
} finally {
}
// 开始开启各种各样的服务
try {
startBootstrapServices();
startCoreServices();
startOtherServices();
SystemServerInitThreadPool.shutdown();
} catch (Throwable ex) {
}
StrictMode.initVmDefaults(null);
// Loop forever.
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
这里主要初始化了必要的一些环境参数,比如 系统时间,时区,语言,还有加载一些库,初始化 Looper等等,同样也创建了 SystemServiceManager 用来启动和管理 系统的服务
下面看一下createSystemContext()方法
private void createSystemContext() {
//ActivityThread是每个android的入口类
ActivityThread activityThread = ActivityThread.systemMain();
mSystemContext = activityThread.getSystemContext();
mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
final Context systemUiContext = activityThread.getSystemUiContext();
systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
}
创建 SystemServer 中的 ActivityThread,实际上SystemServer不仅仅是一个单纯的后台进程, 它也是运行着组件Service的进程,很多系统的对话框就是从SystemServer中显示出来的,因此, SystemServer本身也需要一个和APK应用类似的上下文环境,创建ActivityThread在SystemServer进程中, 毕竟和普通进程中有区别,因此,这里调用attach()方法时参数为true,表示SystemServer中调用的,系统使用 摘自:SystemServer进程浅析
下面再看启动startBootstrapServices()方法
这个主要启动系统必须要的方服务,比如 AMS,PMS,DispalyMangerService,WMS。等等,下面就看一下怎么启动的这些服务
private void startBootstrapServices() {
mSystemServiceManager.startService(DeviceIdentifiersPolicyService.class);
// 初始化 AMS
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
mActivityManagerService.setInstaller(installer);
}
// 初始化 PowerManagerService
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
// 初始化 LightsService
mSystemServiceManager.startService(LightsService.class);
// 初始化 DisplayManagerService
mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
// 初始化 PackageManagerService
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
mFirstBoot = mPackageManagerService.isFirstBoot();
参考
一个APP从启动到主页面显示经历了哪些过程?
一篇文章看明白 Android 系统启动时都干了什么
Android进程系列第二篇---Zygote进程的启动流程
SystemServer进程浅析