Zygote
本篇基于android2.2.3
Zygote是Android系统应用中一个相当重要的进程,它的主要功能就是执行Android应用程序
Zygote进程运行时,会初始化Dalvik虚拟机,并启动它。
在Android中,应用程序运行前,Zygote进程通过共享已运行的虚拟机的代码与内存信息,缩短应用程序运行所耗费的时间。并且,它会实现将应用程序要使用的Android Framework中的类与资源加载到内存中,并组织形成所用资源的链接信息。新运行的Android应用程序在使用所需资源时不必每次重新形成资源的链接信息,这会节省大量时间,提供程序运行速度
Android的服务与应用程序都由Zygote进程启动运行
Zygote启动后,初始化运行Dalvik虚拟机,而后将需要的类与资源加载到内存中。随后调用fork()创建出Zygote的子进程,接着Zygote的子进程动态加载并运行Android应用程序A。运行的应用程序A会使用Zygote已经初始化并启动运行的Dalvik虚拟机代码,通过使用已加载至内存中的类与资源来加快运行速度。
与其他本地服务或Daemon不同的是,Zygote由Java编写而成,不能直接由init进程启动运行。若想运行Zygote类,必须先生成Dalvik虚拟机,再在Dalvik虚拟机上装载ZygoteInit类,执行这一任务的就是app_process进程。
int main(int argc, const char* const argv[])
{
mArgC = argc;
mArgV = argv;
mArgLen = 0;
for (int i=0; i<argc; i++) {
mArgLen += strlen(argv[i]) + 1;
}
mArgLen--;
AppRuntime runtime;
...
int i = runtime.addVmArguments(argc, argv);
if (i < argc) {
runtime.mParentDir = argv[i++];
if (0 == strcmp("--zygote", arg)) {
bool startSystemServer = (i < argc) ?
strcmp(argv[i], "--start-system-server") == 0 : false;
setArgv0(argv0, "zygote");
//设置本进程的名称为zygote
set_process_name("zygote");
//注意第二个参数为true
runtime.start("com.android.internal.os.ZygoteInit",startSystemServer);
} else {
set_process_name(argv0);
runtime.mClassName = arg;
runtime.mArgC = argc-i;
runtime.mArgV = argv+i;
...
runtime.start();
}
}
...
}
AndroidRuntime
AppRuntime类继承字AndroidRuntime类,AndroidRuntime类用于初始化并运行Dalvik虚拟机,为运行Android应用程序做好准备。
在运行Dalvik虚拟机之前,通过AppRuntime对象,分析环境变量以及运行的参数,并以此生成虚拟机选项。
void AndroidRuntime::start(const char* className, const bool startSystemServer)
{
//className的值"com.android.internal.os.ZygoteInit"
//startSystemServer的值是true
char* slashClassName = NULL;
char* cp;
JNIEnv* env;
blockSigpipe(); //处理SIGPIPE信号
...
const char* rootDir = getenv("ANDROID_ROOT");
if (rootDir == NULL) {
//如果环境变量中没有ANDROID_ROOT,则新增该变量。并设置值为"/system"
rootDir = "/system";
...
setenv("ANDROID_ROOT", rootDir, 1);
}
//创建虚拟机
if (startVm(&mJavaVM, &env) != 0)
goto bail;
...
//注册JNI函数
if (startReg(env) < 0) {
...
goto bail;
}
...
stringClass = env->FindClass("java/lang/String");
//创建一个有两个元素的String数组,即Java代码String strArray[] = new String[2];
strArray = env->NewObjectArray(2, stringClass, NULL);
classNameStr = env->NewStringUTF(className);
//设置第一个元素"com.android.internal.os.ZygoteInit"
env->SetObjectArrayElement(strArray, 0, classNameStr);
startSystemServerStr = env->NewStringUTF(startSystemServer ?"true" : "false");
//设置第二个元素为"true",注意这两个元素都是String类型,即字符串
env->SetObjectArrayElement(strArray, 1, startSystemServerStr);
jclass startClass;
jmethodID startMeth;
slashClassName = strdup(className);
/*
将字符串"com.android.internal.os.ZygoteInot"中的"."换成"/".
即"com/android/internal/os/ZygoteInit",这个名称符合JNI规范。
*/
for (cp = slashClassName; *cp != '\0'; cp++)
if (*cp == '.')
*cp = '/';
startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
} else {
//找到ZygoteInit类的static main函数的jMethodId
startMeth = env->GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V");
if (startMeth == NULL) {
} else {
/*
通过JNI调用Java函数,注意调用的函数是main,传入的参数为"true"
所属的类是com.android.internal.os.ZygoteInit
在调用ZygoteInit的main函数后,Zygote便进入Java世界
*/
env->CallStaticVoidMethod(startClass, startMeth, strArray);
//zygote退出,在正常情况下,zygote不需要退出
if (mJavaVM->DetachCurrentThread() != JNI_OK)
...
if (mJavaVM->DestroyJavaVM() != 0)
...
bail:
free(slashClassName);
}
AndroidRuntime::startVm
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
{
//设置虚拟机参数,创建虚拟机
...
}
AndroidRuntime::startReg
int AndroidRuntime::startReg(JNIEnv* env)
{
//设置Thread类的线程创建函数为javaCreateThreadEtc
androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);
env->PushLocalFrame(200);
//注册JNI函数,gRegJNI是一个全局数组
if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
env->PopLocalFrame(NULL);
return -1;
}
env->PopLocalFrame(NULL);
...
return 0;
}
ZygoteInit
public static void main(String argv[]) {
try {
SamplingProfilerIntegration.start();
//注册Zygote用的socket
registerZygoteSocket();
...
//预加载类和资源
preloadClasses();
preloadResources();
...
//强制执行一次垃圾收集
gc();
...
if (argv[1].equals("true")) {
startSystemServer();//启动system_server
} else if (!argv[1].equals("false")) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
...
if (ZYGOTE_FORK_MODE) {
runForkMode();
} else {
//处理新Android应用程序运行请求
runSelectLoopMode();
}
closeServerSocket();//关闭socket
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
...
closeServerSocket();
throw ex;
}
}
ZygoteInit类的功能
绑定套接字,接收新Android应用程序运行请求
为了从ActivityManager接收新Android应用程序的运行请求,Zygote使用UDS(Unix Domain Socket),init进程在运行app_process时,使用init.rc文件中以”/dev/zygote”形式注册的套接字
registerZygoteSocket
private static void registerZygoteSocket() {
if (sServerSocket == null) {
int fileDesc;
try {
//从环境变量中获取Socket的fd
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 {
//创建服务端Socket,这个Socket将listen并accept Client
sServerSocket = new LocalServerSocket(createFileDescriptor(fileDesc));
} catch (IOException ex) {
throw new RuntimeException("Error binding to local socket '" + fileDesc + "'", ex);
}
}
}
加载Android Application Framework使用的类与资源
将应用程序框架中的类、平台资源(图像、XML信息、字符串等)预先加载到内存中。新进程直接使用这些类与资源,而不需要重新加载它们,这大大加快了程序的执行速度
preloadClasses
private static final String PRELOADED_CLASSES = "preloaded-classes";
private static void preloadClasses() {
final VMRuntime runtime = VMRuntime.getRuntime();
//预加载类的信息存储在PRELOADED_CLASSES变量中,它的值为"preloaded-classes"
InputStream is = ZygoteInit.class.getClassLoader().getResourceAsStream(PRELOADED_CLASSES);
if (is == null) {
Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");
} else {
...//做一些统计和准备工作
try {
//读取"preloaded-classes"文件的内容
BufferedReader br = new BufferedReader(new InputStreamReader(is), 256);
int count = 0;
String line;
String missingClasses = null;
while ((line = br.readLine()) != null) {
//读取文件的每一行,忽略#开头的注释行
line = line.trim();
if (line.startsWith("#") || line.equals("")) {
continue;
}
try {
if (Config.LOGV) {
Log.v(TAG, "Preloading " + line + "...");
}
//通过Java反射来记载类,line中存储的是预加载的类名
Class.forName(line);
...
count++;
} catch (ClassNotFoundException e) {
...
} catch (Throwable t) {
...
}
}
...//扫尾工作
}
}
}
# Classes which are preloaded by com.android.internal.os.ZygoteInit.
2# Automatically generated by frameworks/base/tools/preload/WritePreloadedClassFile.java.
3# MIN_LOAD_TIME_MICROS=1250
4android.R$styleable
5android.accounts.AccountManager
6android.accounts.AccountManager$4
7android.accounts.AccountManager$6
8android.accounts.AccountManager$AmsTask
...
preload_class文件由framework/base/tools/preload工具生成,它判断每个类的加载的时间是否大于1250微秒(1.25毫秒)即MIN_LOAD_TIME_MICROS=1250,超时的类会被写入到preload-classes文件中,最后由zygote预加载
preloadResources
private static void preloadResources() {
final VMRuntime runtime = VMRuntime.getRuntime();
Debug.startAllocCounting();
try {
runtime.gcSoftReferences();
runtime.runFinalizationSync();
//预加载系统资源
mResources = Resources.getSystem();
mResources.startPreloading();
if (PRELOAD_RESOURCES) {
Log.i(TAG, "Preloading resources...");
long startTime = SystemClock.uptimeMillis();
//加载Drawable资源
TypedArray ar = mResources.obtainTypedArray(com.android.internal.R.array.preloaded_drawables);
int N = preloadDrawables(runtime, ar);
Log.i(TAG, "...preloaded " + N + " resources in "+ (SystemClock.uptimeMillis()-startTime) + "ms.");
startTime = SystemClock.uptimeMillis();
//加载Color State资源
ar = mResources.obtainTypedArray(com.android.internal.R.array.preloaded_color_state_lists);
N = preloadColorStateLists(runtime, ar);
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();
}
}
加载Drawable与Color State资源,preloaded_drawables与preloaded_color_state_lists记录的会被加载到内存中
启动运行SystemServer
通过app_process运行zygote时,参数”–start-system-server”会调用startSystemServer方法启动系统服务器,系统服务器用来运行Android平台需要的一些主要的本地服务
startSystemServer
private static boolean startSystemServer()throws MethodAndArgsCaller, RuntimeException {
//该数组保存SystemServer的启动参数
String args[] = {
"--setuid=1000", //uid
"--setgid=1000", //gid
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,3001,3002,3003",
"--capabilities=130104352,130104352",
"--runtime-init",
"--nice-name=system_server", //进程名
"com.android.server.SystemServer", //启动的类名
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
//把上面字符串数组参数转换成Arguments对象
parsedArgs = new ZygoteConnection.Arguments(args);
int debugFlags = parsedArgs.debugFlags;
if("1".equals(SystemProperties.get("ro.debuggable")))
debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
//fork一个子进程
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids, debugFlags, null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
//如果pid为0,表示处在子进程中,也就是处于system_server进程中
if (pid == 0) {
//system_server进程工作
handleSystemServerProcess(parsedArgs);
}
return true;
}
与运行其他应用程序不同,startSystemServer方法会调用forkSystemServer()方法来创建新进程,并运行SystemServer。系统在运行普通Android应用程序时,只负责创建应用程序进程,至于进程是否创建成功并不检查。与此不同,SystemServer是必须运行的,因此在forkSystemServer()方法中必须检查生成的SystemServer进程是否正常
在生成的SystemServer进程中运行com.android.server.SystemServer类的main()方法
main
public static void main(String[] args) {
...
VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
System.loadLibrary("android_servers");
init1(args);
}
执行main()方法时会加载名称为android_server的本地库。
本地库加载完毕后,继续加载init1()函数,它是一个JNI本地方法。init1()函数调用system_init()函数,启动Audio Flinger、Surface Flinger、MediaPlayerService、CameraService等本地服务
system_init
extern "C" status_t system_init()
{
...
if (strcmp(propBuf, "1") == 0) {
SurfaceFlinger::instantiate();
}
if (!proc->supportsProcesses()) {
AudioFlinger::instantiate();
MediaPlayerService::instantiate();
CameraService::instantiate();
AudioPolicyService::instantiate();
}
...
AndroidRuntime* runtime = AndroidRuntime::getRuntime();
...
runtime->callStatic("com/android/server/SystemServer", "init2");
if (proc->supportsProcesses()) {
LOGI("System server: entering thread pool.\n");
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
LOGI("System server: exiting thread pool.\n");
}
return NO_ERROR;
}
本地服务组成完毕后,再此调用SystemServer类的静态方法init2(),init2()方法创建android.server.ServerThread线程,并启动它,从而运行Android Framework的主要服务
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();
}
当ServerThread线程创建好并运行后,Thread类的run()方法被调用,此时ServerThread类中重定义的run()方法被调用。在run()方法中包含主要服务生成与注册的代码
当所有服务正常启动后,Zygote才做好运行新应用程序的准备
处理新Android应用程序运行请求
监视UDS,若收到新Android应用程序生成请求,则进入处理循环
在SystemServer运行后,程序会进入一个循环,处理来自多有绑定的套接字的请求,若ZYGOTE_FORK_MODE为false,程序就会调用runSelectLoopMode()方法,直到Zygote进程终止,该方法才会返回
runSelectLoopMode
private static void runSelectLoopMode() throws MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList();
ArrayList<ZygoteConnection> peers = new ArrayList();
FileDescriptor[] fdArray = new FileDescriptor[4];
//sServerSocket是我们先前在registerZygoteSocket中建立的Socket
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);
/*
selectReadable内部调用select,使用多路复用I/O模型
当有客户端连接或有数据时,则selectReadable就会返回
*/
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);
fds.add(newPeer.getFileDesciptor());
} else {
boolean done;
//客户端发送了请求,peers.get返回的是ZygoteConnection
done = peers.get(index).runOnce();
if (done) {
peers.remove(index);
fds.remove(index);
}
}
}
}
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
String args[];
Arguments parsedArgs = null;
FileDescriptor[] descriptors;
try {
//读取请求信息,请求信息包含创建新进程的参数选项
args = readArgumentList();
descriptors = mSocket.getAncillaryFileDescriptors();
} catch (IOException ex) {
Log.w(TAG, "IOException on command socket " + ex.getMessage());
closeSocket();
return true;
}
if (args == null) {
closeSocket();
return true;
}
PrintStream newStderr = null;
if (descriptors != null && descriptors.length >= 3) {
newStderr = new PrintStream(
new FileOutputStream(descriptors[2]));
}
int pid;
try {
/*
分析请求信息中的字符串数组,为运行进程设置好各个选项,具体
包括了设置应用程序的gid、uid、调试标记处理,设置rlimit,以及检查运行权限等
*/
parsedArgs = new Arguments(args);
applyUidSecurityPolicy(parsedArgs, peer);
applyDebuggerSecurityPolicy(parsedArgs);
applyRlimitSecurityPolicy(parsedArgs, peer);
applyCapabilitiesSecurityPolicy(parsedArgs, peer);
int[][] rlimits = null;
if (parsedArgs.rlimits != null) {
rlimits = parsedArgs.rlimits.toArray(intArray2d);
}
//创建新进程
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids, parsedArgs.debugFlags, rlimits);
} catch (IllegalArgumentException ex) {
logAndPrintError (newStderr, "Invalid zygote arguments", ex);
pid = -1;
} catch (ZygoteSecurityException ex) {
logAndPrintError(newStderr,"Zygote security policy preventsrequest: ", ex);
pid = -1;
}
if (pid == 0) {
handleChildProc(parsedArgs, descriptors, newStderr);
return true;
} else {
return handleParentProc(pid, descriptors, parsedArgs);
}
}