最近在追溯Activity启动的流程,顺手温习下Android上层的启动流程,就从Zygote进程启动开始。
Zygote进程是由linux的init进程启动的,是所有android进程的父进程,包括systemserver和所有的应用进程都是由Zygote fork出来。
Init进程在启动Zygote进程时,会调用ZygoteInit.main方法(MTK平台项目代码,其中残留了一些mtk修改的痕迹)
public static void main(String argv[]) {
/// M: GMO Zygote64 on demand @{
DEBUG_ZYGOTE_ON_DEMAND =
SystemProperties.get(PROP_ZYGOTE_ON_DEMAND_DEBUG).equals("1");
if (DEBUG_ZYGOTE_ON_DEMAND) {
Log.d(TAG, "ZygoteOnDemand: Zygote ready = " + sZygoteReady);
}
String socketName = "zygote";
/// M: GMO Zygote64 on demand @}
// Mark zygote start. This ensures that thread creation will throw
// an error.
ZygoteHooks.startZygoteNoThreadCreation();
try {
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygoteInit");
RuntimeInit.enableDdms();
/// M: Added for BOOTPROF
//MTPROF_DISABLE = "1".equals(SystemProperties.get("ro.mtprof.disable"));
// Start profiling the zygote initialization.
SamplingProfilerIntegration.start();
boolean startSystemServer = false;
String abiList = null;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
socketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
if (abiList == null) {
throw new RuntimeException("No ABI list supplied.");
}
registerZygoteSocket(socketName);
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygotePreload");
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
/// M: Added for BOOTPROF
addBootEvent("Zygote:Preload Start");
/// M: GMO Zygote64 on demand @{
/// M: Added for Zygote preload control @{
preloadByName(socketName);
/// @}
/// M: GMO Zygote64 on demand @}
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
// Finish profiling the zygote initialization.
SamplingProfilerIntegration.writeZygoteSnapshot();
// Do an initial gc to clean up after startup
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PostZygoteInitGC");
gcAndFinalize();
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
// Disable tracing so that forked processes do not inherit stale tracing tags from
// Zygote.
Trace.setTracingEnabled(false);
// Zygote process unmounts root storage spaces.
Zygote.nativeUnmountStorageOnInit();
/// M: Added for BOOTPROF
addBootEvent("Zygote:Preload End");
ZygoteHooks.stopZygoteNoThreadCreation();
/// N: Move MPlugin init after preloading due to "Zygote: No Thread Creation Issues". @{
boolean preloadMPlugin = false;
if (!sZygoteOnDemandEnabled) {
preloadMPlugin = true;
} else {
if ("zygote".equals(socketName)) {
preloadMPlugin = true;
}
}
if (preloadMPlugin) {
Log.i(TAG1, "preloadMappingTable() -- start ");
PluginLoader.preloadPluginInfo();
Log.i(TAG1, "preloadMappingTable() -- end ");
}
/// @}
if (startSystemServer) {
startSystemServer(abiList, socketName);
}
/// M: GMO Zygote64 on demand @{
sZygoteReady = true;
if (DEBUG_ZYGOTE_ON_DEMAND) {
Log.d(TAG, "ZygoteOnDemand: Zygote ready = " + sZygoteReady +
", socket name: " + socketName);
}
/// M: GMO Zygote64 on demand @}
Log.i(TAG, "Accepting command socket connections");
runSelectLoop(abiList);
/// M: GMO Zygote64 on demand @{
zygoteStopping("ZygoteOnDemand: End of runSelectLoop", socketName);
/// M: GMO Zygote64 on demand @}
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
/// M: GMO Zygote64 on demand @{
zygoteStopping("ZygoteOnDemand: End of main function", socketName);
/// M: GMO Zygote64 on demand @}
}
1. Mark zygote start.
// Mark zygote start. This ensures that thread creation will throw
// an error.
ZygoteHooks.startZygoteNoThreadCreation();
标记zygote启动开始,调用ZygoteHooks的Jni方法,原因不是特别理解,贴出该方法google给的说明:
/**
* Called by the zygote when starting up. It marks the point when any thread
* start should be an error, as only internal daemon threads are allowed there.
*/
public static native void startZygoteNoThreadCreation();
zygote启动时调用,在这里启动任意其他线程都是错误的,只有内部的守护线程被允许。
2. ddms服务
RuntimeInit.enableDdms();
3.启动系能统计
SamplingProfilerIntegration.start();
4.解析参数列表
boolean startSystemServer = false;
String abiList = null;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
socketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
判断systemserver是否启动,获取socketname等等
5.注册Socket
registerZygoteSocket(socketName);
private static void registerZygoteSocket(String socketName) {
if (sServerSocket == null) {
int fileDesc;
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
try {
String env = System.getenv(fullSocketName);
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
throw new RuntimeException(fullSocketName + " unset or invalid", ex);
}
try {
FileDescriptor fd = new FileDescriptor();
fd.setInt$(fileDesc);
sServerSocket = new LocalServerSocket(fd);
} catch (IOException ex) {
throw new RuntimeException(
"Error binding to local socket '" + fileDesc + "'", ex);
}
}
}
初始化Server端(也就是Zygote)的socket。值得一提的是,这里用到的socket类型是LocalSocket, 它是Android对Linux 的 Local Socket的一个封装。Local Socket 是Linux提供的一种基于Socket的进程间通信方式,对Server端来讲,唯一的区别就是bind到一个本地的文件描述符(fd)而不是某个IP地址和端口号。
6.预加载资源
static void preload() {
Log.d(TAG, "begin preload");
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "BeginIcuCachePinning");
beginIcuCachePinning();
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadClasses");
preloadClasses(); //预加载位于/system/etc/preloaded-classes文件中的类
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadResources");
preloadResources(); //预加载资源,包含drawable和color资源
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadOpenGL");
preloadOpenGL(); //预加载OpenGL
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
preloadSharedLibraries(); //通过System.loadLibrary()方法,
//预加载"android","compiler_rt","jnigraphics"这3个共享库
preloadTextResources(); //预加载 文本连接符资源
// Ask the WebViewFactory to do any initialization that must run in the zygote process,
// for memory sharing purposes.
WebViewFactory.prepareWebViewInZygote(); //仅用于zygote进程,用于内存共享的进程
endIcuCachePinning();
warmUpJcaProviders();
Log.d(TAG, "end preload");
}
对于类加载,采用反射机制Class.forName()方法来加载。对于资源加载,主要是 com.android.internal.R.array.preloaded_drawables和com.android.internal.R.array.preloaded_color_state_lists,在应用程序中以com.android.internal.R.xxx开头的资源,便是此时由Zygote加载到内存的。
zygote进程内加载了preload()方法中的所有资源,当需要fork新进程时,采用copy on write技术,如下:
7.gc操作
/**
* Runs several special GCs to try to clean up a few generations of
* softly- and final-reachable objects, along with any other garbage.
* This is only useful just before a fork().
*/
/*package*/ static void gcAndFinalize() {
final VMRuntime runtime = VMRuntime.getRuntime();
/* runFinalizationSync() lets finalizers be called in Zygote,
* which doesn't have a HeapWorker thread.
*/
System.gc();
runtime.runFinalizationSync();
System.gc();
}
Runs多次gc,保证清理?
8.startSystemServer
private static boolean startSystemServer(String abiList, String socketName)
throws MethodAndArgsCaller, RuntimeException {
long capabilities = posixCapabilitiesAsBits(
OsConstants.CAP_IPC_LOCK,
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
);
/* Containers run without this capability, so avoid setting it in that case */
if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) {
capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND);
}
/* Hardcoded command line to start the system server */
String args[] = {
"--setuid=1000",
"--setgid=1000",
/// M: ANR mechanism for system_server add shell(2000) group to access
/// /sys/kernel/debug/tracing/tracing_on
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,2000," +
"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);
/* Request to fork the system server process */
// fork子进程,用于运行system_server
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 */
//进入子进程system_server
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
// 完成system_server进程剩余的工作
handleSystemServerProcess(parsedArgs);
}
return true;
}
9.runSelectLoop
/**
* Runs the zygote process's select loop. Accepts new connections as
* they happen, and reads commands from connections one spawn-request's
* worth at a time.
*
* @throws MethodAndArgsCaller in a child process when a main() should
* be executed.
*/
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
ArrayList fds = new ArrayList();
ArrayList peers = new ArrayList();
//sServerSocket是socket通信中的服务端,即zygote进程
fds.add(sServerSocket.getFileDescriptor());
peers.add(null);
while (true) {
StructPollfd[] pollFds = new StructPollfd[fds.size()];
for (int i = 0; i < pollFds.length; ++i) {
pollFds[i] = new StructPollfd();
pollFds[i].fd = fds.get(i);
pollFds[i].events = (short) POLLIN;
}
try {
Os.poll(pollFds, -1);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
//采用I/O多路复用机制,当客户端发出连接请求或者数据处理请求时,跳过continue,执行后面的代码
for (int i = pollFds.length - 1; i >= 0; --i) {
if ((pollFds[i].revents & POLLIN) == 0) {
continue;
}
if (i == 0) {
//创建客户端连接
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
//处理客户端数据事务
boolean done = peers.get(i).runOnce();
if (done) {
peers.remove(i);
fds.remove(i);
}
}
}
}
}
Zygote采用高效的I/O多路复用机制,保证在没有客户端连接请求或数据处理时休眠,否则响应客户端的请求。
10.简单小结
ZygoteInit.main方法是android java代码开始的地方,
- registerZygoteSocket()建立socket通道,zygote作为通信的服务端,用于响应客户端请求;
- preload()预加载通用类、drawable和color资源、openGL以及共享库以及WebView,用于提高ap启动效率;
- zygote完毕大部分工作,接下来再通过startSystemServer(),fork得力帮手system_server进程,也是上层framework的运行载体。
- zygote功成身退,调用runSelectLoop(),随时待命,当接收到请求创建新进程请求时立即唤醒并执行相应工作。
参考链接:
http://www.cnblogs.com/samchen2009/p/3294713.html
http://gityuan.com/2016/02/14/android-system-server/
http://blog.csdn.net/omnispace/article/details/51773292