Android系统的心脏-Zygote进程启动流程分析
简介:
Android中,Zygote是整个Android系统的核心进程,是Android系统的心脏。所有的Android应用程序,包括Android框架层所在的进程system_server,都是由Zygote孵化(通过Linux系统调用fork函数创建)出来的。
Zygote初探:
我们说,zygote是整个Android系统的心脏,在zygote被启动的同时,还启动了其它的很多守护进程,有的比zygote启动的还早。 换句话说,在zygote还没有启动时,其实,作为底层的Linux系统已经启动了,标志就是init进程已经启动。
如果我们在adb shell命令行,用kill命令(在root的情况下),居然可以杀死zygote,然后,设备屏幕又会显示“>>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<”,即android系统重启。
zytote是一个实实在在的进程,可以在进程列表中查看到:
USER PID PPID VSIZE RSS WCHAN PC NAME
root 1 0 548 196 c00b8c14 0000d5cc S /init
root 2 0 0 0 c006bf70 00000000 S kthreadd
......
root 724 2 0 0 c0216908 00000000 S mmcqd
root 726 1 772 180 c019dbc4 afe0c1dc S /system/bin/sh
system 727 1 840 188 c022d8a0 afe0c47c S /system/bin/servicemanager
......
root 734 1 72000 14172 c00b92b0 afe0c5a4 S zygote
......system 825 734 574128 28360 ffffffff afe0c47c S system_server
......app_22 890 734 117068 30228 ffffffff afe0d404 S oms.home
可以看到,
zygote的父进程id是1,即init进程,而且,zygote的权限是root权限;
system_server是Android系统框架所在的进程,即AMS,WMS等很多服务所在的就是这个进程。system_server的父进程就是zygote;
oms.home:是home应用,即手机桌面应用。oms是Ophone系统(中国移动基于Android系统进行定制的一个系统)。作为应用程序,它的父进程也是zygote。
下图,是比较重要的一些进程的相关关系:
zygote的启动流程简单说明:
1)创建Java虚拟机;
2)为Java虚拟机注册native方法;
3)在com.android.internal.os.ZygoteInit中调用java类的主要方法;
4)加载ZygoteInit class;
5)注册zygote socket;
6)加载preload class;
7)加载preload 资源文件;
8)调用Zygote::forkSystemServer,fork一个新的进程,调用SystemServer的main方法,从而进入到java层的system_server进程的初始化流程中;
zygote进程初始化源代码分析:
代码位置:“frameworks/base/core/java/com/android/internal/os/
zygote进程是由init.rc文件中启动的,如下:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server class main socket zygote stream 660 root system onrestart write /sys/android_power/request_state wake onrestart write /sys/power/state on onrestart restart media onrestart restart netd
app_process:
其中app_process被编译成一个可执行程序,
代码位置:frameworks\base\cmds\app_process,分析如下:
1)Android.mk:
Android.mk:LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ app_main.cpp LOCAL_SHARED_LIBRARIES := \ libcutils \ libutils \ libandroid_runtime LOCAL_MODULE:= app_process include $(BUILD_EXECUTABLE)
其中,app_main.cpp是入口,而且,引用了libandroid_runtime库。
2)app_main.cpp:
看一下app_main.cpp的main函数:
int main(int argc, const char* const argv[]){ // These are global variables in ProcessState.cpp mArgC = argc; mArgV = argv; mArgLen = 0; for (int i=0; i<argc; i++) { mArgLen += strlen(argv[i]) + 1; } mArgLen--; AppRuntime runtime; const char* argv0 = argv[0]; // Process command line arguments // ignore argv[0] argc--; argv++; // Everything up to '--' or first non '-' arg goes to the vm int i = runtime.addVmArguments(argc, argv); // Parse runtime arguments. Stop at first unrecognized option. bool zygote = false; bool startSystemServer = false; bool application = false; const char* parentDir = NULL; const char* niceName = NULL; const char* className = NULL; while (i < argc) { const char* arg = argv[i++]; if (!parentDir) { parentDir = arg; } else if (strcmp(arg, "--zygote") == 0) { zygote = true; niceName = "zygote"; } 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 = arg + 12; } else { className = arg; break; } } if (niceName && *niceName) { setArgv0(argv0, niceName); set_process_name(niceName); } runtime.mParentDir = parentDir; if (zygote) { runtime.start("com.android.internal.os.ZygoteInit", startSystemServer ? "start-system-server" : ""); } else if (className) { // Remainder of args get passed to startup class main() runtime.mClassName = className; runtime.mArgC = argc - i; runtime.mArgV = argv + i; runtime.start("com.android.internal.os.RuntimeInit", application ? "application" : "tool"); } 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; }}
分析:
(1)根据输入参数来判断,该如何进行runtime.start参数的配置。在上面的initl.rc中,参数是:
-Xzygote /system/bin --zygote --start-system-server
所以 ,有:
zygote = true;
startSystemServer = true;
然后,会执行到:
runtime.start("com.android.internal.os.ZygoteInit",
startSystemServer ? "start-system-server" : "");
去通过ZygoteInit来继续进行zygote的初始化流程。
3)runtime:
既然ZygoteIni由truntime.start来运行,看一下runtime的实现:
类图:
流程图:
分析:
如果是“--zygote”,则启动zygote进程相关代码;
否则,会根据参数,启动(创建)参数所在的app。
4)ZygoteInit:
在分析完runtime之后,再来看一runtime.start的第一个参数“
com.android.internal.os.ZygoteInit
”的相关实现:
代码位置:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java。
这是个java代码,也就是说,执行了大半天,这时候终于执行到了java代码,有runtime(即dvm虚拟机的runtime运行时库)启动了java代码。看一下这个目录的代码文件(已经是java代码了):
在这个目录下,没有Android.mk文件。这是因为这已经是java层了,而不是native层。对于java层的代码来说,只是说是不是要打包到jar中。而对于C/C++来说,要编译成lib,或者exe。
其中,ZygoteInit的 流程图如下:
分析:
(1)为zygote注册一个socket,并且保存起来,保存到
sServerSocket
变量中;这是一个LocalServerSocket类型的socket,详细代码如下:
private static void registerZygoteSocket() { if (sServerSocket == null) { int fileDesc; try { String env = System.getenv(ANDROID_SOCKET_ENV); fileDesc = Integer.parseInt(env); } catch (RuntimeException ex) { throw new RuntimeException( ANDROID_SOCKET_ENV + " unset or invalid", ex); } try { sServerSocket = new LocalServerSocket( createFileDescriptor(fileDesc)); } catch (IOException ex) { throw new RuntimeException( "Error binding to local socket '" + fileDesc + "'", ex); } } }
同时,创建了文件描述符FileDescriptor, 即ANDROID_SOCKET_ENV环境变量对应的文件描述符FileDescriptor,ANDROID_SOCKET_ENV的定义:
private static final String ANDROID_SOCKET_ENV = "ANDROID_SOCKET_zygote";
(2)预加载一些class和资源文件。这样的好处是,会加快app的启动。当一个app启动时,就不需要重新加载这些资源了;
(3)孵化(fork)SystemServer进程:Zygote::SystemServer就会通过系统调用fork函数来创建一个新的进程,这个进程就是SystemServer;
(4)然后,执行到SystemServer的main方法,这是一个java类,整个SystemServer的文件中,定义了两个类,如下:
5) SystemServer:
在SystemServer.main方法中,
System.loadLibrary("android_servers"); //加载“android_servers”库
init1(args); //这是个jni接口,会再调用到native层的init1方法中。
然后,init1会执行到native层,然后再通过native层调用到java层的init2方法,相关代码流程:
SystemServer.java -> com_android_server_SystemServer.cpp -> system_init.cpp ->SystemServer.java
com_android_server_SystemServer.cpp的init1函数:
static void android_server_SystemServer_init1(JNIEnv* env, jobject clazz){ system_init();}system_init的实现(在system_init.cpp文件中):extern "C" status_t system_init(){ ALOGI("Entered system_init()"); sp proc(ProcessState::self()); sp sm = defaultServiceManager(); ALOGI("ServiceManager: %p\n", sm.get()); sp grim = new GrimReaper(); sm->asBinder()->linkToDeath(grim, grim.get(), 0); char propBuf[PROPERTY_VALUE_MAX]; property_get("system_init.startsurfaceflinger", propBuf, "1"); if (strcmp(propBuf, "1") == 0) { // Start the SurfaceFlinger SurfaceFlinger::instantiate(); } property_get("system_init.startsensorservice", propBuf, "1"); if (strcmp(propBuf, "1") == 0) { // Start the sensor service SensorService::instantiate(); } // And now start the Android runtime. We have to do this bit // of nastiness because the Android runtime initialization requires // some of the core system services to already be started. // All other servers should just start the Android runtime at // the beginning of their processes's main(), before calling // the init function. ALOGI("System server: starting Android runtime.\n"); AndroidRuntime* runtime = AndroidRuntime::getRuntime(); ALOGI("System server: starting Android services.\n"); JNIEnv* env = runtime->getJNIEnv(); if (env == NULL) { return UNKNOWN_ERROR; } jclass clazz = env->FindClass("com/android/server/SystemServer"); if (clazz == NULL) { return UNKNOWN_ERROR; } jmethodID methodId = env->GetStaticMethodID(clazz, "init2", "()V"); if (methodId == NULL) { return UNKNOWN_ERROR; } env->CallStaticVoidMethod(clazz, methodId); ALOGI("System server: entering thread pool.\n"); ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool(); ALOGI("System server: exiting thread pool.\n"); return NO_ERROR;}
分析:
在init1函数,启动一写service(如果没有启动的话);然后,创建一个runtime,由runtime去调用到java层的SystemServer类的init2方法;最后,将其加入线程池。
那好,我嗯再回到SystemServer类的init2方法,如下:
public static final void init2() { Slog.i(TAG, "Entered the Android system server!"); Thread thr = new ServerThread(); thr.setName("android.server.ServerThread"); thr.start(); }
在init2中,启动了ServerThread。
6)ServerThread:
所以,整个SystemServer其实,最关键的实体是这个ServerThread线程。我们之间看run函数的实现:
@Override public void run() { Looper.prepare(); android.os.Process.setThreadPriority( android.os.Process.THREAD_PRIORITY_FOREGROUND); BinderInternal.disableBackgroundScheduling(true); android.os.Process.setCanSelfBackground(false); LightsService lights = null; PowerManagerService power = null; BatteryService battery = null; VibratorService vibrator = null; AlarmManagerService alarm = null; NetworkManagementService networkManagement = null; NetworkStatsService networkStats = null; NetworkPolicyManagerService networkPolicy = null; ConnectivityService connectivity = null; ...... // Critical services... try { Slog.i(TAG, "Entropy Mixer"); ServiceManager.addService("entropy", new EntropyMixer()); Slog.i(TAG, "Power Manager"); power = new PowerManagerService(); ServiceManager.addService(Context.POWER_SERVICE, power); ...... pm = PackageManagerService.main(context, factoryTest != SystemServer.FACTORY_TEST_OFF, onlyCore); boolean firstBoot = false; try { firstBoot = pm.isFirstBoot(); } catch (RemoteException e) { } ActivityManagerService.setSystemProcess(); mContentResolver = context.getContentResolver(); // The AccountManager must come before the ContentService try { Slog.i(TAG, "Account Manager"); ServiceManager.addService(Context.ACCOUNT_SERVICE, new AccountManagerService(context)); } catch (Throwable e) { Slog.e(TAG, "Failure starting Account Manager", e); } ...... } catch (RuntimeException e) { Slog.e("System", ""); Slog.e("System", " Failure starting core service", e); } DevicePolicyManagerService devicePolicy = null; StatusBarManagerService statusBar = null; InputMethodManagerService imm = null; AppWidgetService appWidget = null; NotificationManagerService notification = null; WallpaperManagerService wallpaper = null; LocationManagerService location = null; CountryDetectorService countryDetector = null; TextServicesManagerService tsms = null; LockSettingsService lockSettings = null; DreamManagerService dreamy = null; // Bring up services needed for UI. if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { try { Slog.i(TAG, "Input Method Service"); imm = new InputMethodManagerService(context, wm); ServiceManager.addService(Context.INPUT_METHOD_SERVICE, imm); } catch (Throwable e) { reportWtf("starting Input Manager Service", e); } try { Slog.i(TAG, "Accessibility Manager"); ServiceManager.addService(Context.ACCESSIBILITY_SERVICE, new AccessibilityManagerService(context)); } catch (Throwable e) { reportWtf("starting Accessibility Manager", e); } } try { wm.displayReady(); } catch (Throwable e) { reportWtf("making display ready", e); } try { pm.performBootDexOpt(); } catch (Throwable e) { reportWtf("performing boot dexopt", e); } try { ActivityManagerNative.getDefault().showBootMessage( context.getResources().getText( com.android.internal.R.string.android_upgrading_starting_apps), false); } catch (RemoteException e) { } if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { MountService mountService = null; if (!"0".equals(SystemProperties.get("system_init.startmountservice"))) { try { /* * NotificationManagerService is dependant on MountService, * (for media / usb notifications) so we must start MountService first. */ Slog.i(TAG, "Mount Service"); mountService = new MountService(context); ServiceManager.addService("mount", mountService); } catch (Throwable e) { reportWtf("starting Mount Service", e); } } try { Slog.i(TAG, "LockSettingsService"); lockSettings = new LockSettingsService(context); ServiceManager.addService("lock_settings", lockSettings); } catch (Throwable e) { reportWtf("starting LockSettingsService service", e); } try { Slog.i(TAG, "Device Policy"); devicePolicy = new DevicePolicyManagerService(context); ServiceManager.addService(Context.DEVICE_POLICY_SERVICE, devicePolicy); } catch (Throwable e) { reportWtf("starting DevicePolicyService", e); } ...... } // These are needed to propagate to the runnable below. final Context contextF = context; final BatteryService batteryF = battery; final NetworkManagementService networkManagementF = networkManagement; final NetworkStatsService networkStatsF = networkStats; final NetworkPolicyManagerService networkPolicyF = networkPolicy; final ConnectivityService connectivityF = connectivity; final DockObserver dockF = dock; final UsbService usbF = usb; ...... Looper.loop(); Slog.d(TAG, "System ServerThread is exiting!"); }
说明:
在这个run方法中,初始化了Android系统框架层的各种service,包括:
PowerManagerService:电源管理服务
BatteryService:电池服务
PackageManagerService:包管理服务
ActivityManagerService:activity管理服务
NetworkStatsService:网络状态服务
......
这样,Android系统框架层的SystemServer进程启动完毕,许多srevice组件也都初始化好了。
至此,整个zygote就完成了它的使命,最终把Android系统框架层的SystemServer进程启动完毕做为结束点。
7)runSelectLoopMode函数:
在初始化完的SystemServer进程后,就进入一个循环中,即runSelectLoopMode函数的执行。等待客户端的请求事件,如果有请求事件,就去创建进程,这就涉及到应用进程的创建了,这部分内容在下一节讨论。
下一节:
Android系统的心脏-Zygote进程如何fork一个新的应用进程