android zygote root,详细分析Android中实现Zygote的源码

概述

在Android系统中,所有的应用程序进程,以及用来运行系统关键服务的System进程都是由zygote进程负责创建的。因此,我们将它称为进程孵化器。zygote进程是通过复制自身的方式来创建System进程和应用程序进程的。由于zygote进程在启动时会在内部创建一个虚拟机实例,因此,通过复制zygote进程而得到的System进程和应用程序进程可以快速地在内部获得一个虚拟机实例拷贝。

zygote进程在启动完成之后,会马上将System进程启动起来,以便它可以将系统的关键服务启动起来。下面我们将介绍zygote进程的启动脚本,然后分析它和System进程的启动过程。

zygote分析

zygote进程的启动脚本如下:

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

在我之前的一篇博客中已经分析了init进程是如何启动service服务了,需要了解的同学可以参考这篇文章:Android init进程——解析配置文件

通过zygote服务的启动脚本,我们可以知道,zygote进程的实际是二进制文件app_process的调用,我们就从这个应用程序的main函数入手去分析一下zygote进程的启动过程,源码如下(/frameworks/base/cmds/app_process/app_main.cpp):

/**

* 将-Xzygote加入到JavaVMOption中,返回/system/bin参数指向的下标

*/

int AndroidRuntime::addVmArguments(int argc, const char* const argv[])

{

int i;

for (i = 0; i < argc; i ++) {

if (argv[i][0] != '-') {

return i;

}

if (argv[i][1] == '-' && argv[i][2] == 0) {

return i + 1;

}

JavaVMOption opt;

memset(&opt, 0, sizeof(opt));

opt.optionString = (char*)argv[i];

mOptions.add(opt);

}

return i;

}

int main(int argc, char* const argv[])

{

// zygote call parameters

// /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server

// 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 tp '--' 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)) {

niceName = arg + 12;

} else {

className = arg;

break;

}

}

if (niceName && *niceName) {

setArgv0(argv0, niceName);

set_process_name(niceName);

}

runtime.mParentDir = parentDir;

if (zygote) {

// 进入到AppRuntime的start函数

runtime.start("com.android.internal.os.ZygoteInit",

startSystemServer? "start-system-server" : "");

} else if (className) {

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;

}

}

在zygote的main函数中,通过AppRuntime runtime代码创建了一个AppRuntime对象runtime,接下来Zygote进程就是通过它来进一步启动的。

init.rc中关于启动zygote命令中包含了–zygote参数,所以在if(strcmp(arg, “–zygote”) == 0)判断的时候,会将niceName赋值为”zygote”,然后通过set_process_name(niceName)函数将当前进程的名称设置为zygote。这也是为什么调用的脚本为/system/bin/app_process,而进程名为zygote的原因。set_process_name函数的源码如下(/system/core/libcutils/process_name.c):

static const char* process_name = "unknown";

void set_process_name(const char* new_name)

{

if (new_name == NULL) {

return;

}

int len = strlen(new_name);

char* copy = (char*)malloc(len + 1);

strcpy(copy, new_name);

process_name = (const char*) copy;

}

从init.rc文件中关于zygote进程的配置参数可知,Zygote进程传递给应用程序app_process的启动参数arg还包含一个”–start-system-server”选项。因此,在调用AppRuntime对象runtime的成员函数start时,第二个参数为”start-system-server”,表示zygote进程启动完成之后,需要将system进程启动起来。

AppRuntime分析

AppRuntime类的成员函数start是从父类AndroidRuntime继承下来的,因此,接下来我们就继续分析AndroidRuntime类的成员函数start的实现,函数源码位置:/frameworks/base/core/jni/AndroidRuntime.cpp:

char* AndroidRuntime::toSlashClassName(const char* className)

{

char* result = strdup(className);

for (char* cp = result; *cp != '\0'; cp ++) {

if (*cp == '.') {

*cp = '/';

}

}

return result;

}

/**

* Start the Android runtime. This involves starting the virtual machine

* and calling the "static void main(String[] args)" method int the class

* named by "className".

*

* 这两个参数的值分别为:

* const char* className = "com.android.internal.os.ZygoteInit";

* const char* options = "start-system-server";

*/

void AndroidRuntime::start(const char* className, const char* options)

{

ALOGD("\n>>>>> AndroidRuntime START %s <<<<<

className != NULL ? className : "(unknown)");

/**

* 'startSystemServer == true' means runtime is obsolete and not run from

* init.rc anymore, so we print out the boot start event here.

*/

if (strcmp(options, "start-system-server") == 0) {

const int LOG_BOOT_PROGRESS_START = 3000;

LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));

}

// 设置ANDROID_ROOT环境变量

const char* rootDir = getenv("ANDROID_ROOT");

if (rootDir == NULL) {

rootDir = "/system";

if (!hasDir("/system")) {

LOG_FATAL("No root directory specified, and /android dose not exist.");

return;

}

setenv("ANDROID_ROOT", rootDir, 1);

}

JniInvocation jni_invocation;

jni_invocation.Init(NULL);

JNIEnv* env;

// 1. 创建虚拟机

if (startVm(&mJavaVM, &env) != 0) {

return;

}

onVmCreated(env);

// 2. 注册JNI函数

if (startReg(env) < 0) {

ALOGE("Unable to register all android natives\n");

return;

}

jclass stringClass;

jobjectArray strArray;

jstring classNameStr;

jstring optionsStr;

stringClass = env->FindClass("java/lang/String");

assert(stringClass != NULL);

// 创建一个有两个元素的String数组,用Java代码表示为:String[] strArray = new String[2];

strArray = env->NewObjectArray(2, stringClass, NULL);

assert(strArray != NULL);

classNameStr = env->NewStringUTF(className);

assert(classNameStr != NULL);

// 设置第一个元素为"com.android.internal.os.ZygoteInit"

env->SetObjectArrayElement(strArray, 0, classNameStr);

optionsStr = env->NewStringUTF(options);

// 设置第二个元素为"start-system-server"

env->SetObjectArrayElement(strArray, 1, optionsStr);

// 将字符串"com.android.internal.os.ZygoteInit"转换为"com/android/internal/os/ZygoteInit"

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 {

// 3.

// 通过JNI调用java函数,注意调用的是main函数,所属的类是"com.android.internal.os.ZygoteInit".

// 传递的参数是"com.android.internal.os.ZygoteInit true"

env->CallStaticVoidMethod(startClass, startMeth, strArray);

}

}

free(slashClassName);

ALOGD("Shutting down VM\n");

if (mJavaVM->DetachCurrentThread() != JNI_OK) {

ALOGW("Warning: unable to detach main thread\n");

}

if (mJavaVM->DestoryJavaVM() != 0) {

ALOGW("Warning: VM did not shut down cleanly\n");

}

}

上述代码有几处关键点,分别是:

创建虚拟机。

注册JNI函数。

进入Java世界。

接下来,我们分别分析这三个关键点。

创建虚拟机——startVm

startVm并没有特别之处,就是调用JNI的虚拟机创建函数,但是创建虚拟机时的一些参数却是在startVm中确定的,其源码如下:

#define PROPERTY_VALUE_MAX 92

/**

* Start the Dalvik Virtual Machine.

*

* Various arguments, most determined by system properties, are passed in.

* The "mOptions" vector is updated.

*

* Returns 0 on success.

*/

int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIENV** pEnv)

{

int result = -1;

JavaVMInitArgs initArgs;

JavaVMOption opt;

char propBuf[PROPERTY_VALUE_MAX];

char stackTraceFileBuf[PROPERTY_VALUE_MAX];

char dexoptFlagsBuf[PROPERTY_VALUE_MAX];

char enableAssertBuf[sizeof("-ea:")-1 + PROPERTY_VALUE_MAX];

char jniOptsBuf[sizeof("-Xjniopts:")-1 + PROPERTY_VALUE_MAX];

char heapstartsizeOptsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];

char heapsizeOptsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];

char heapgrowthlimitOptsBuf[sizeof("-XX:HeapGrowthLimit=")-1 + PROPERTY_VALUE_MAX];

char heapminfreeOptsBuf[sizeof("-XX:HeapMinFree=")-1 + PROPERTY_VALUE_MAX];

char heapmaxfreeOptsBuf[sizeof("-XX:HeapMaxFree=")-1 + PROPERTY_VALUE_MAX];

char heaptargetutilizationOptsBuf[sizeof("-XX:HeapTargetUtilization=")-1 + PROPERTY_VALUE_MAX];

char jitcodecachesizeOptsBuf[sizeof("-Xjitcodecachesize:")-1 + PROPERTY_VALUE_MAX];

char extraOptsBuf[PROPERTY_VALUE_MAX];

char* stackTraceFile = NULL;

bool checkJni = false;

bool checkDexSum = false;

bool logStdio = false;

enum {

KEMDefault,

KEMIntPortable,

KEMIntFast,

KEMJitCompiler,

} executionMode = KEMDefault;

/**

* 这段代码是用了设置JNI_check选项的。JNI_check指的是Native层调用JNI函数时,系统所做的一些检查动作。

* 这个选项虽然能增加可靠性,但是还有一些副作用:

* 1. 因为检查工作比较耗时,所以会影响系统运行速度。

* 2. 有些检查工作比较耗时,一旦出错,整个进程会abort。

* 所以,JNI_check选项一般只在eng版本设置。

*/

property_get("dalvik.vm.checkjni", propBuf, "");

if (strcmp(propBuf, "true") == 0) {

checkJni = true;

} else if (strcmp(propBuf, "false") != 0) {

property_get("ro.kernel.android.checkjni", propBuf, "");

if (propBuf[0] == '1') {

checkJni = true;

}

}

property_get("dalvik.vm.execution-mode", propBuf, "");

if (strcmp(propBuf, "int:portable") == 0) {

executionMode = KEMIntPortable;

} else if (strcmp(propBuf, "int:fast") == 0) {

executionMode = KEMIntFast;

} else if (strcmp(propBuf, "int:jit") == 0) {

executionMode = KEMJitCompiler;

}

// ... 省略大部分参数设置

/**

* 设置虚拟机的heapsize,默认为16m。绝大多数厂商都会在build.prop文件里修改这个属性,一般是256m。

* heapsize不能设置得过小,否则在操作大尺寸的图片时无法分配所需的内存。

*/

strcpy(heapsizeOptsBuf, "-Xmx");

property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m");

opt.optionString = heapsizeOptsBuf;

mOptions.add(opt);

// ......

if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {

ALOGE("JNI_CreateJavaVM failed\n");

goto bail;

}

result = 0;

bail:

free(stackTraceFile);

return result;

}

更多虚拟机参数的设置,我这里就不做特殊说明了,大家感兴趣可以自行google。(ps:因为我不太懂虚拟机这一块…)

注册JNI函数——startReg

上面讲了如何创建虚拟机,接下来需要给这个虚拟机注册一些JNI函数。正是因为后续的Java世界用到的一些函数是采用native方式实现的,所以才必须提前注册这些函数。

接下来,我们来看一下startReg函数的源码实现:

int AndroidRuntime::startReg(JNIEnv* env)

{

// 设置Thread类的线程创建函数为javaCreateThreadEtc

androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);

ALOGV("--- registering native functions ---\n");

env->PushLocalFrame(200);

if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {

env->PopLocalFrame(NULL);

return -1;

}

env->PopLocalFrame(NULL);

return 0;

}

关键是需要注册JNI函数,具体实现是由register_jni_procs函数实现的,我们来看一下这个函数的具体实现(/frameworks/base/core/jni/AndroidRuntime.cpp):

static int register_jni_procs(const RegJNIRec array[], size_T count, JNIEnv* env)

{

for (size_t i = 0; i < count; i ++) {

if (array[i].mProc(env) < 0) {

#ifndef NDEBUG

ALOGD("------!!! %s failed to load\n", array[i].mName);

#endif

return -1;

}

}

return 0;

}

通过源码,我们可以看到,register_jni_procs只是对array数组的mProc函数的封装,而array数组指向的是gRegJNI数组,我们来看一下这个数组的实现:

static const RegJNIRec gRegJNI[] = {

REG_JNI(register_android_debug_JNITest),

REG_JNI(register_com_android_internal_os_RuntimeInit),

REG_JNI(register_android_os_SystemClock),

REG_JNI(register_android_util_EventLog),

REG_JNI(register_android_util_Log),

REG_JNI(register_android_util_FloatMath),

REG_JNI(register_android_text_format_Time),

REG_JNI(register_android_content_AssetManager),

REG_JNI(register_android_content_StringBlock),

REG_JNI(register_android_content_XmlBlock),

REG_JNI(register_android_emoji_EmojiFactory),

REG_JNI(register_android_text_AndroidCharacter),

REG_JNI(register_android_text_AndroidBidi),

REG_JNI(register_android_view_InputDevice),

REG_JNI(register_android_view_KeyCharacterMap),

REG_JNI(register_android_os_Process),

REG_JNI(register_android_os_SystemProperties),

REG_JNI(register_android_os_Binder),

REG_JNI(register_android_os_Parcel),

REG_JNI(register_android_view_DisplayEventReceiver),

REG_JNI(register_android_nio_utils),

REG_JNI(register_android_graphics_Graphics),

REG_JNI(register_android_view_GraphicBuffer),

REG_JNI(register_android_view_GLES20DisplayList),

REG_JNI(register_android_view_GLES20Canvas),

REG_JNI(register_android_view_HardwareRenderer),

REG_JNI(register_android_view_Surface),

REG_JNI(register_android_view_SurfaceControl),

REG_JNI(register_android_view_SurfaceSession),

REG_JNI(register_android_view_TextureView),

REG_JNI(register_com_google_android_gles_jni_EGLImpl),

REG_JNI(register_com_google_android_gles_jni_GLImpl),

REG_JNI(register_android_opengl_jni_EGL14),

REG_JNI(register_android_opengl_jni_EGLExt),

REG_JNI(register_android_opengl_jni_GLES10),

REG_JNI(register_android_opengl_jni_GLES10Ext),

REG_JNI(register_android_opengl_jni_GLES11),

REG_JNI(register_android_opengl_jni_GLES11Ext),

REG_JNI(register_android_opengl_jni_GLES20),

REG_JNI(register_android_opengl_jni_GLES30),

REG_JNI(register_android_graphics_Bitmap),

REG_JNI(register_android_graphics_BitmapFactory),

REG_JNI(register_android_graphics_BitmapRegionDecoder),

REG_JNI(register_android_graphics_Camera),

REG_JNI(register_android_graphics_CreateJavaOutputStreamAdaptor),

REG_JNI(register_android_graphics_Canvas),

REG_JNI(register_android_graphics_ColorFilter),

REG_JNI(register_android_graphics_DrawFilter),

REG_JNI(register_android_graphics_Interpolator),

REG_JNI(register_android_graphics_LayerRasterizer),

REG_JNI(register_android_graphics_MaskFilter),

REG_JNI(register_android_graphics_Matrix),

REG_JNI(register_android_graphics_Movie),

REG_JNI(register_android_graphics_NinePatch),

REG_JNI(register_android_graphics_Paint),

REG_JNI(register_android_graphics_Path),

REG_JNI(register_android_graphics_PathMeasure),

REG_JNI(register_android_graphics_PathEffect),

REG_JNI(register_android_graphics_Picture),

REG_JNI(register_android_graphics_PorterDuff),

REG_JNI(register_android_graphics_Rasterizer),

REG_JNI(register_android_graphics_Region),

REG_JNI(register_android_graphics_Shader),

REG_JNI(register_android_graphics_SurfaceTexture),

REG_JNI(register_android_graphics_Typeface),

REG_JNI(register_android_graphics_Xfermode),

REG_JNI(register_android_graphics_YuvImage),

REG_JNI(register_android_graphics_pdf_PdfDocument),

REG_JNI(register_android_database_CursorWindow),

REG_JNI(register_android_database_SQLiteConnection),

REG_JNI(register_android_database_SQLiteGlobal),

REG_JNI(register_android_database_SQLiteDebug),

REG_JNI(register_android_os_Debug),

REG_JNI(register_android_os_FileObserver),

REG_JNI(register_android_os_MessageQueue),

REG_JNI(register_android_os_SELinux),

REG_JNI(register_android_os_Trace),

REG_JNI(register_android_os_UEventObserver),

REG_JNI(register_android_net_LocalSocketImpl),

REG_JNI(register_android_net_NetworkUtils),

REG_JNI(register_android_net_TrafficStats),

REG_JNI(register_android_net_wifi_WifiNative),

REG_JNI(register_android_os_MemoryFile),

REG_JNI(register_com_android_internal_os_ZygoteInit),

REG_JNI(register_android_hardware_Camera),

REG_JNI(register_android_hardware_camera2_CameraMetadata),

REG_JNI(register_android_hardware_SensorManager),

REG_JNI(register_android_hardware_SerialPort),

REG_JNI(register_android_hardware_UsbDevice),

REG_JNI(register_android_hardware_UsbDeviceConnection),

REG_JNI(register_android_hardware_UsbRequest),

REG_JNI(register_android_media_AudioRecord),

REG_JNI(register_android_media_AudioSystem),

REG_JNI(register_android_media_AudioTrack),

REG_JNI(register_android_media_JetPlayer),

REG_JNI(register_android_media_RemoteDisplay),

REG_JNI(register_android_media_ToneGenerator),

REG_JNI(register_android_opengl_classes),

REG_JNI(register_android_server_NetworkManagementSocketTagger),

REG_JNI(register_android_server_Watchdog),

REG_JNI(register_android_ddm_DdmHandleNativeHeap),

REG_JNI(register_android_backup_BackupDataInput),

REG_JNI(register_android_backup_BackupDataOutput),

REG_JNI(register_android_backup_FileBackupHelperBase),

REG_JNI(register_android_backup_BackupHelperDispatcher),

REG_JNI(register_android_app_backup_FullBackup),

REG_JNI(register_android_app_ActivityThread),

REG_JNI(register_android_app_NativeActivity),

REG_JNI(register_android_view_InputChannel),

REG_JNI(register_android_view_InputEventReceiver),

REG_JNI(register_android_view_InputEventSender),

REG_JNI(register_android_view_InputQueue),

REG_JNI(register_android_view_KeyEvent),

REG_JNI(register_android_view_MotionEvent),

REG_JNI(register_android_view_PointerIcon),

REG_JNI(register_android_view_VelocityTracker),

REG_JNI(register_android_content_res_ObbScanner),

REG_JNI(register_android_content_res_Configuration),

REG_JNI(register_android_animation_PropertyValuesHolder),

REG_JNI(register_com_android_internal_content_NativeLibraryHelper),

REG_JNI(register_com_android_internal_net_NetworkStatsFactory),

};

#ifdef NDEBUG

#define REG_JNI(name) {name}

struct RegJNIRec {

int (*mProc)(JNIEnv*);

};

#else

#define REG_JNI(name) {name, #name}

struct RegJNIRec {

int (*mProc)(JNIEnv*);

const char* mName;

};

#endif

可以看到,REG_JNI是一个宏,宏里面包括的就是那个参数为JNIEnv*,返回值为int的函数指针mProc,我们以register_android_debug_JNITest为例,源码位置为/frameworks/base/core/jni/android_debug_JNITest.cpp:

#define NELEM(x) (sizeof(x)/sizeof(*(x)))

int register_android_debug_JNITest(JNIEnv* env)

{

return jniRegisterNativeMethods(env, "android/debug/JNITest", gMethods, NELEM(gMethods));

}

可以看到,mProc其实就是为Java类注册JNI函数。

进入JAVA世界

可以看到CallStaticVoidMethod最终将调用com.android.internal.os.ZygoteInit的main函数,下面就来看一下这个Java世界的入口函数。源码位置:/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java,源码如下:

public static void main(String argv[])

{

try {

SamplingProfilerIntegration.start();

// 1. 注册zygote用的socket

registerZygoteSocket();

EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis());

// 2. 预加载类和资源

preload();

EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, SystemClock.uptimeMillis());

SamplingProfilerIntegration.writeZygoteSnapshot();

// 强制执行一次垃圾收集

gc();

Trace.setTracingEnabled(false);

if (argv.length != 2) {

throw new RuntimeException(argv[0] + USAGE_STRING);

}

if (argv[1].equals("start-system-server")) {

// 3. 启动system-server

startSystemServer();

} else if (!argv[1].equals("")) {

throw new RuntimeException(argv[0] + USAGE_STRING);

}

Log.i(TAG, "Accepting command socket connections");

// 4. 进入请求应答模式

runSelectLoop();

closeServerSocket();

} catch(MethodAndArgsCaller caller) {

caller.run();

} catch(RuntimeException ex) {

Log.e(TAG, "Zygote died with exception", ex);

closeServerSocket();

throw ex;

}

}

上述代码中有5个重要的点,我已经通过标号标记出来了,接下来我们分别分析一下这5点函数的具体实现。

建立IPC通信服务端——registerZygoteSocket

zygote及系统中其他程序的通信没有使用Binder,而是采用了基于AF_UNIX类型的socket。registerZygoteSocket函数的使命正是建立这个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);

}

}

}

public class LocalServerSocket {

private final LocalSocketImpl impl;

private final LocalSocketAddress localAddress;

private static final int LISTEN_BACKLOG = 50;

/**

* Create a LocalServerSocket from a file descriptor that's already

* been created and bound. listen() will be called immediately on it.

* Used for cases where file descriptors are passed in via environment

* variables.

*/

public LocalServerSocket(FileDescriptor fd) throws IOException {

impl = new LocalSocketImpl(fd);

impl.listen(LISTEN_BACKLOG);

localAddress = impl.getSockAddress();

}

}

registerZygoteSocket很简单,就是创建一个服务端的socket。

预加载类和资源——preload

我们先来看一下preload函数实现:

static void preload()

{

preloadClasses();

preloadResources();

preloadOpenGL();

}

preload函数里面分别调用了三个预加载函数,我们分别来分析一下这几个函数的实现。

首先是preloadClasses,函数实现如下:

private static final int UNPRIVILEGED_UID = 9999;

private static final int UNPRIVILEGED_GID = 9999;

private static final int ROOT_UID = 0;

private static final int ROOT_GID = 0;

private static void preloadClasses()

{

final VMRuntime runtime = VMRuntime.getRuntime();

InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream(PRELOADED_CLASSES);

if (is == null) {

Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");

} else {

Log.i(TAG, "Preloading classes...");

long startTime = SystemClock.uptimeMillis();

setEffectiveGroup(UNPRIVILEGED_GID);

setEffectiveGroup(UNPRIVILEGED_UID);

float defaultUtilization = runtime.getTargetHeapUtilization();

runtime.setTargetHeapUtilization(0.8f);

System.gc();

runtime.runFinalizationSync();

Debug.startAllocCounting();

try {

// 创建一个缓冲区为256字符的输入流

BufferedReader br = new BufferdReader(new InputStreamReader(is), 256);

int count = 0;

String line;

while ((line = br.readLine()) != null) {

// skip comments and blank lines.

line = line.trim();

if (line.startsWith("#") || line.equals("")) {

continue;

}

try {

if (false) {

Log.v(TAG, "Preloading " + line + "...");

}

Class.forName(line);

count ++;

} catch (ClassNotFoundException e) {

Log.w(TAG, "Class not found for preloading: " + line);

} catch (UnsatisfiedLinkError e) {

Log.w(TAG, "Problem preloading " + line + ": " + e);

} catch(Throwable t) {

Log.e(TAG, "Error preloading " + line + ".", t);

}

}

Log.i(TAG, "...preloaded " + count + " classes in " + (SystemClock.uptimeMillis()-startTime) + "ms.");

} catch (IOException e) {

Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);

} finally {

IoUtils.closeQuietly(is);

runtime.setTargetHeapUtilization(defaultUtilization);

runtime.preloadDexCaches();

Debug.stopAllocCounting();

setEffectiveUser(ROOT_UID);

setEffectiveGroup(ROOT_GID);

}

}

}

preloadClasses看起来很简单,但是实际上它有很多的类需要加载。可以查看一下/frameworks/base/preloaded-classes文件,这里面都是需要预加载的类。

接下来,分析一下preloadResources函数的源码:

private static final boolean PRELOAD_RESOURCES = true;

private static void preloadResources()

{

final VMRuntime runtime = VMRuntime.getRuntime();

Debug.startAllocCounting();

try {

System.gc();

runtime.runFinalizationSync();

mResources = Resources.getSystem();

mResources.startPreloading();

if (PRELOAD_RESOURCES) {

Log.i(TAG, "Preloading resources...");

long startTime = SystemClock.uptimeMillis();

TypedArray ar = mResources.obtainTypedArray(com.android.internal.R.array.preloaded_drawables);

int N = preloadDrawables(runtime, ar);

ar.recycle();

Log.i(TAG, "...preloaded " + N + " resources in " + (SystemClock.uptimeMillis()-startTime) + "ms.");

startTime = SystemClock.uptimeMillis();

ar = mResources.obtainTypedArray(com.android.internal.R.array.preloaded_color_state_lists);

N = preloadColorstateLists(runtime, ar);

ar.recycle();

Log.i(TAG, "...preloaded " + N + " resources in " + (SystemClock.uptimeMillis() - startTime) + "ms.");

}

mResources.finishPreloading();

} catch (RuntimeException e) {

Log.w(TAG, "Failure preloading resources", e);

} finally {

Debug.stopAllocCounting();

}

}

接下来,是预加载OpenGL。源码如下:

private static void preloadOpenGL()

{

if (!SystemProperties.getBoolean(PROPERTY_DISABLE_OPENGL_PRELOADING, false)) {

EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);

}

}

启动system_server

现在我们要分析第三个关键点:startSystemServer。这个函数会创建java世界中系统Service所驻留的进程system_server,该进程是framework的核心。如何system_server挂掉,会导致zygote自杀。我们来看一下startSystemServer()实现源码。

/**

* Prepare the arguments and fork for the system server process.

*/

private static boolean startSystemServer() throws MethodAndArgsCaller, RuntimeException

{

long capabilities = posixCapabilitiesAsBits(

OsConstants.CAP_KILL,

OsConstants.CAP_NET_ADMIN,

OsConstants.CAP_NET_BIND_SERVICE,

OsConstants.CAP_NET_BROADCAST,

OsConstants.CAP_NET_RAW,

OsConstants.CAP_SYS_MODULE,

OsConstants.CAP_SYS_NICE,

OsConstants.CAP_SYS_RESOURCE,

OsConstants.CAP_SYS_TIME,

OsConstants.CAP_SYS_TTY_CONFIG

);

// 设置参数

String args[] = {

"--setuid=1000",

"--setgid=1000",

"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",

"--capabilities=" + capabilities + "," + capabilities,

"--runtime-init",

"--nice-name=system_server", // 进程名为system_server

"com.android.server.SystemServer",

};

ZygoteConnection.Arguments parsedArgs = null;

int pid;

try {

parsedArgs = new ZygoteConnection.Arguments(args);

ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);

ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

/* Request to fork the system server process */

pid = Zygote.forkSystemServer(

parsedArgs.uid, parsedArgs.gid,

parsedArgs.gids,

parsedArgs.debugFlags,

null,

parsedArgs.permittedCapabilities,

parsedArgs.effectiveCapabilities

);

} catch (IllegalArgumentException ex) {

throw new RuntimeException(ex);

}

/* For child process */

if (pid == 0) {

handleSystemServerProcess(parsedArgs);

}

return true;

}

有求必应之等待请求——runSelectLoop

zygote从startSystemServer返回后,将进入第四个关键的函数:runSelectLoop。我们来看一下这个函数的实现:

static final int GC_LOOP_COUNT = 10;

private static void runSelectLoop() throws MethodAndArgsCaller {

ArrayList fds = new ArrayList();

ArrayList peers = new ArrayList();

FileDescriptor[] fdArray = new FileDescriptor[4];

fds.add(sServerSocket.getFileDescriptor());

peers.add(null);

int loopCount = GC_LOOP_COUNT;

while (true) {

int index;

if (loopCount <= 0) {

gc();

loopCount = GC_LOOP_COUNT;

} else {

loopCount --;

}

try {

fdArray = fds.toArray(fdArray);

index = selectReadable(fdArray);

} catch(IOException ex) {

throw new RuntimeException("Error in select()", ex);

}

if (index < 0) {

throw new RuntimeException("Error in select()");

} else if (index == 0) {

ZygoteConnection newPeer = acceptCommandPeer();

peers.add(newPeer);

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值