Android系統啟動-綜述
基於Android 12的原始碼剖析, Android啟動過程概述
一。 概述
Android系統底層基於Linux Kernel, 當Kernel啟動過程會建立init程序, 該程序是所有使用者空間的鼻祖, init程序會啟動servicemanager(binder服務管家), Zygote程序(Java程序的鼻祖)。 Zygote程序會建立 system_server程序以及各種app程序,下圖是這幾個系統重量級程序之間的層級關係。
二。 init
init是Linux系統中使用者空間的第一個程序(pid=1), Kerner啟動後會呼叫/system/core/init/Init。cpp的main()方法。
2。1 Init。main
int main(int argc, char** argv) {
。。。
InitKernelLogging(argv); //初始化kernel log
property_init(); //建立一塊共享的記憶體空間,用於屬性服務
signal_handler_init(); //初始化子程序退出的訊號處理過程
property_load_boot_defaults(); //載入/default。prop檔案
start_property_service(); //啟動屬性伺服器(透過socket通訊)
ActionManager& am = ActionManager::GetInstance();
ServiceList& sm = ServiceList::GetInstance();
LoadBootScripts(am, sm);//解析init。rc檔案
//執行rc檔案中觸發器為 on early-init的語句
am。QueueEventTrigger(“early-init”);
//執行rc檔案中觸發器為 on init的語句
am。QueueEventTrigger(“init”);
//執行rc檔案中觸發器為 on late-init的語句
am。QueueEventTrigger(“late-init”);
while (true) {
// By default, sleep until something happens。
int epoll_timeout_ms = -1;
if (do_shutdown && !shutting_down) {
do_shutdown = false;
if (HandlePowerctlMessage(shutdown_command)) {
shutting_down = true;
}
}
if (!(waiting_for_prop || Service::is_exec_service_running())) {
am。ExecuteOneCommand();
}
if (!(waiting_for_prop || Service::is_exec_service_running())) {
if (!shutting_down) {
auto next_process_restart_time = RestartProcesses();
// If there‘s a process that needs restarting, wake up in time for that。
if (next_process_restart_time) {
epoll_timeout_ms = std::chrono::ceil
*next_process_restart_time - boot_clock::now())
。count();
if (epoll_timeout_ms < 0) epoll_timeout_ms = 0;
}
}
// If there’s more work to do, wake up again immediately。
if (am。HasMoreCommands()) epoll_timeout_ms = 0;
}
epoll_event ev;
//迴圈 等待事件發生
int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, epoll_timeout_ms));
if (nr == -1) {
PLOG(ERROR) << “epoll_wait failed”;
} else if (nr == 1) {
((void (*)()) ev。data。ptr)();
}
}
return 0;
}
static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {
Parser parser = CreateParser(action_manager, service_list);
std::string bootscript = GetProperty(“ro。boot。init_rc”, “”);
if (bootscript。empty()) {
parser。ParseConfig(“/init。rc”);
if (!parser。ParseConfig(“/system/etc/init”)) {
late_import_paths。emplace_back(“/system/etc/init”);
}
if (!parser。ParseConfig(“/product/etc/init”)) {
late_import_paths。emplace_back(“/product/etc/init”);
}
if (!parser。ParseConfig(“/odm/etc/init”)) {
late_import_paths。emplace_back(“/odm/etc/init”);
}
if (!parser。ParseConfig(“/vendor/etc/init”)) {
late_import_paths。emplace_back(“/vendor/etc/init”);
}
} else {
parser。ParseConfig(bootscript);
}
}
init程序的主要功能點:
分析和執行所有的init。rc檔案;
生成裝置驅動節點; (透過rc檔案建立)
處理子程序的終止(signal方式);
提供屬性服務property service。
2。2 Zygote自動重啟機制
當init解析到下面這條語句,便會啟動Zygote程序
service zygote /system/bin/app_process -Xzygote /system/bin ——zygote ——start-system-server
class main //伴隨著main class的啟動而啟動
socket zygote stream 660 root system //建立socket
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media //當zygote重啟時,則會重啟media
onrestart restart netd // 當zygote重啟時,則會重啟netd
當init子程序(Zygote)退出時,會產生SIGCHLD訊號,併發送給init程序,透過socket套接字傳遞資料,呼叫到wait_for_one_process()方法,根據是否是oneshot,來決定是重啟子程序,還是放棄啟動。由於預設模式oneshot=false,因此Zygote一旦被殺便會再次由init程序拉起。
接下來,便是進入了Zygote程序。
三。 Zygote
當Zygote程序啟動後, 便會執行到frameworks/base/cmds/app_process/App_main。cpp檔案的main()方法。 整個呼叫流程:
App_main。main
AndroidRuntime。start
AndroidRuntime。startVm
AndroidRuntime。startReg
ZygoteInit。main (首次進入Java世界)
Zygote。createManagedSocketFromInitSocket
preload
forkSystemServer
runSelectLoop
3。1 App_main。main
xref: /frameworks/base/cmds/app_process/app_main。cpp
33 class AppRuntime : public AndroidRuntime
187 int main(int argc, char* const argv[])
188{
189 if (!LOG_NDEBUG) {
190 String8 argv_String;
191 for (int i = 0; i < argc; ++i) {
192 argv_String。append(“\”“);
193 argv_String。append(argv[i]);
194 argv_String。append(”\“ ”);
195 }
196 ALOGV(“app_process main with argv: %s”, argv_String。string());
197 }
198
199 AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
200 // Process command line arguments
201 // ignore argv[0]
202 argc——;
203 argv++;
204
205 // Everything up to ‘——’ or first non ‘-’ arg goes to the vm。
206 //
207 // The first argument after the VM args is the “parent dir”, which
208 // is currently unused。
209 //
210 // After the parent dir, we expect one or more the following internal
211 // arguments :
212 //
213 // ——zygote : Start in zygote mode
214 // ——start-system-server : Start the system server。
215 // ——application : Start in application (stand alone, non zygote) mode。
216 // ——nice-name : The nice name for this process。
217 //
218 // For non zygote starts, these arguments will be followed by
219 // the main class name。 All remaining arguments are passed to
220 // the main method of this class。
221 //
222 // For zygote starts, all remaining arguments are passed to the zygote。
223 // main function。
224 //
225 // Note that we must copy argument string values since we will rewrite the
226 // entire argument block when we apply the nice name to argv0。
227 //
228 // As an exception to the above rule, anything in “spaced commands”
229 // goes to the vm even though it has a space in it。
230 const char* spaced_commands[] = { “-cp”, “-classpath” };
231 // Allow “spaced commands” to be succeeded by exactly 1 argument (regardless of -s)。
232 bool known_command = false;
233
234 int i;
235 for (i = 0; i < argc; i++) {
236 if (known_command == true) {
237 runtime。addOption(strdup(argv[i]));
238 // The static analyzer gets upset that we don‘t ever free the above
239 // string。 Since the allocation is from main, leaking it doesn’t seem
240 // problematic。 NOLINTNEXTLINE
241 ALOGV(“app_process main add known option ‘%s’”, argv[i]);
242 known_command = false;
243 continue;
244 }
245
246 for (int j = 0;
247 j < static_cast
248 ++j) {
249 if (strcmp(argv[i], spaced_commands[j]) == 0) {
250 known_command = true;
251 ALOGV(“app_process main found known command ‘%s’”, argv[i]);
252 }
253 }
254
255 if (argv[i][0] != ‘-’) {
256 break;
257 }
258 if (argv[i][1] == ‘-’ && argv[i][2] == 0) {
259 ++i; // Skip ——。
260 break;
261 }
262
263 runtime。addOption(strdup(argv[i]));
264 // The static analyzer gets upset that we don‘t ever free the above
265 // string。 Since the allocation is from main, leaking it doesn’t seem
266 // problematic。 NOLINTNEXTLINE
267 ALOGV(“app_process main add option ‘%s’”, argv[i]);
268 }
269
270 // Parse runtime arguments。 Stop at first unrecognized option。
271 bool zygote = false;
272 bool startSystemServer = false;
273 bool application = false;
274 String8 niceName;
275 String8 className;
276
277 ++i; // Skip unused “parent dir” argument。
278 while (i < argc) {。。。//引數解析
279 const char* arg = argv[i++];
280 if (strcmp(arg, “——zygote”) == 0) {
281 zygote = true;
282 niceName = ZYGOTE_NICE_NAME;
283 } else if (strcmp(arg, “——start-system-server”) == 0) {
284 startSystemServer = true;
285 } else if (strcmp(arg, “——application”) == 0) {
286 application = true;
287 } else if (strncmp(arg, “——nice-name=”, 12) == 0) {
288 niceName。setTo(arg + 12);
289 } else if (strncmp(arg, “——”, 2) != 0) {
290 className。setTo(arg);
291 break;
292 } else {
293 ——i;
294 break;
295 }
296 }
297
298 Vector
299 if (!className。isEmpty()) {
300 // We‘re not in zygote mode, the only argument we need to pass
301 // to RuntimeInit is the application argument。
302 //
303 // The Remainder of args get passed to startup class main()。 Make
304 // copies of them before we overwrite them with the process name。
305 args。add(application ? String8(“application”) : String8(“tool”));
306 runtime。setClassNameAndArgs(className, argc - i, argv + i);
307
308 if (!LOG_NDEBUG) {
309 String8 restOfArgs;
310 char* const* argv_new = argv + i;
311 int argc_new = argc - i;
312 for (int k = 0; k < argc_new; ++k) {
313 restOfArgs。append(“\”“);
314 restOfArgs。append(argv_new[k]);
315 restOfArgs。append(”\“ ”);
316 }
317 ALOGV(“Class name = %s, args = %s”, className。string(), restOfArgs。string());
318 }
319 } else {
320 // We’re in zygote mode。
321 maybeCreateDalvikCache();
322
323 if (startSystemServer) {
324 args。add(String8(“start-system-server”));
325 }
326
327 char prop[PROP_VALUE_MAX];
328 if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
329 LOG_ALWAYS_FATAL(“app_process: Unable to determine ABI list from property %s。”,
330 ABI_LIST_PROPERTY);
331 return 11;
332 }
333
334 String8 abiFlag(“——abi-list=”);
335 abiFlag。append(prop);
336 args。add(abiFlag);
337
338 // In zygote mode, pass all remaining arguments to the zygote
339 // main() method。
340 for (; i < argc; ++i) {
341 args。add(String8(argv[i]));
342 }
343 }
344
345 if (!niceName。isEmpty()) {//設定程序名
346 runtime。setArgv0(niceName。string(), true /* setProcName */);
347 }
348
349 if (zygote) {
350 runtime。start(“com。android。internal。os。ZygoteInit”, args, zygote);// 啟動AppRuntime,見小節[3。2]
351 } else if (className) {
352 runtime。start(“com。android。internal。os。RuntimeInit”, args, zygote);
353 } else {
354 fprintf(stderr, “Error: no class name or ——zygote supplied。\n”);
355 app_usage();
356 LOG_ALWAYS_FATAL(“app_process: no class name or ——zygote supplied。”);
357 }
358}
在app_process程序啟動過程,有三個分支:
當zygote為true時,則執行ZygoteInit。main()
當className為true時,則執行RuntimeInit。main()
都不是時,則執行app_usage()
3。2 AndroidRuntime::start
xref: /frameworks/base/core/jni/AndroidRuntime。cpp
1048 /*
1049 * Start the Android runtime。 This involves starting the virtual machine
1050 * and calling the “static void main(String[] args)” method in the class
1051 * named by “className”。
1052 *
1053 * Passes the main function two arguments, the class name and the specified
1054 * options string。
1055 */
1056 void AndroidRuntime::start(const char* className, const Vector
1057 {
1058 ALOGD(“>>>>>> START %s uid %d <<<<<<\n”,
1059 className != NULL ? className : “(unknown)”, getuid());
1060
1061 static const String8 startSystemServer(“start-system-server”);
1062
1063 /*
1064 * ‘startSystemServer == true’ means runtime is obsolete and not run from
1065 * init。rc anymore, so we print out the boot start event here。
1066 */
1067 for (size_t i = 0; i < options。size(); ++i) {
1068 if (options[i] == startSystemServer) {
1069 /* track our progress through the boot sequence */
1070 const int LOG_BOOT_PROGRESS_START = 3000;
1071 LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
1072 }
1073 }
1074
1075 const char* rootDir = getenv(“ANDROID_ROOT”);
1076 if (rootDir == NULL) {
1077 rootDir = “/system”;
1078 if (!hasDir(“/system”)) {
1079 LOG_FATAL(“No root directory specified, and /android does not exist。”);
1080 return;
1081 }
1082 setenv(“ANDROID_ROOT”, rootDir, 1);
1083 }
1084
1085 //const char* kernelHack = getenv(“LD_ASSUME_KERNEL”);
1086 //ALOGD(“Found LD_ASSUME_KERNEL=‘%s’\n”, kernelHack);
1087
1088 /* start the virtual machine */
1089 JniInvocation jni_invocation;
1090 jni_invocation。Init(NULL);
1091 JNIEnv* env;
1092 if (startVm(&mJavaVM, &env, zygote) != 0) {// 虛擬機器建立
1093 return;
1094 }
1095 onVmCreated(env);
1096
1097 /*
1098 * Register android functions。
1099 */
1100 if (startReg(env) < 0) {// JNI方法註冊
1101 ALOGE(“Unable to register all android natives\n”);
1102 return;
1103 }
1104
1105 /*
1106 * We want to call main() with a String array with arguments in it。
1107 * At present we have two arguments, the class name and an option string。
1108 * Create an array to hold them。
1109 */
1110 jclass stringClass;
1111 jobjectArray strArray;
1112 jstring classNameStr;
1113
1114 stringClass = env->FindClass(“java/lang/String”);
1115 assert(stringClass != NULL);
1116 strArray = env->NewObjectArray(options。size() + 1, stringClass, NULL);
1117 assert(strArray != NULL);
1118 classNameStr = env->NewStringUTF(className);
1119 assert(classNameStr != NULL);
1120 env->SetObjectArrayElement(strArray, 0, classNameStr);
1121
1122 for (size_t i = 0; i < options。size(); ++i) {
1123 jstring optionsStr = env->NewStringUTF(options。itemAt(i)。string());
1124 assert(optionsStr != NULL);
1125 env->SetObjectArrayElement(strArray, i + 1, optionsStr);
1126 }
1127
1128 /*
1129 * Start VM。 This thread becomes the main thread of the VM, and will
1130 * not return until the VM exits。
1131 */
1132 char* slashClassName = toSlashClassName(className != NULL ? className : “”);
1133 jclass startClass = env->FindClass(slashClassName);
1134 if (startClass == NULL) {
1135 ALOGE(“JavaVM unable to locate class ‘%s’\n”, slashClassName);
1136 /* keep going */
1137 } else {
1138 jmethodID startMeth = env->GetStaticMethodID(startClass, “main”,
1139 “([Ljava/lang/String;)V”);
1140 if (startMeth == NULL) {
1141 ALOGE(“JavaVM unable to find main() in ‘%s’\n”, className);
1142 /* keep going */
1143 } else {
1144 env->CallStaticVoidMethod(startClass, startMeth, strArray);// 呼叫ZygoteInit。main()方法[見小節3。3]
1145
1146#if 0
1147 if (env->ExceptionCheck())
1148 threadExitUncaughtException(env);
1149#endif
1150 }
1151 }
1152 free(slashClassName);
1153
1154 ALOGD(“Shutting down VM\n”);
1155 if (mJavaVM->DetachCurrentThread() != JNI_OK)
1156 ALOGW(“Warning: unable to detach main thread\n”);
1157 if (mJavaVM->DestroyJavaVM() != 0)
1158 ALOGW(“Warning: VM did not shut down cleanly\n”);
1159 }
3。3 ZygoteInit。main
[–>ZygoteInit。java]
/**
* This is the entry point for a Zygote process。 It creates the Zygote server, loads resources,
* and handles other tasks related to preparing the process for forking into applications。
*
* This process is started with a nice value of -20 (highest priority)。 All paths that flow
* into new processes are required to either set the priority to the default value or terminate
* before executing any non-system code。 The native side of this occurs in SpecializeCommon,
* while the Java Language priority is changed in ZygoteInit。handleSystemServerProcess,
* ZygoteConnection。handleChildProc, and Zygote。usapMain。
*
* @param argv Command line arguments used to specify the Zygote‘s configuration。
*/
@UnsupportedAppUsage
public static void main(String argv[]) {
ZygoteServer zygoteServer = null;
// Mark zygote start。 This ensures that thread creation will throw
// an error。
ZygoteHooks。startZygoteNoThreadCreation();
// Zygote goes into its own process group。
try {
Os。setpgid(0, 0);
} catch (ErrnoException ex) {
throw new RuntimeException(“Failed to setpgid(0,0)”, ex);
}
Runnable caller;
try {
// Store now for StatsLogging later。
final long startTime = SystemClock。elapsedRealtime();
final boolean isRuntimeRestarted = “1”。equals(
SystemProperties。get(“sys。boot_completed”));
String bootTimeTag = Process。is64Bit() ? “Zygote64Timing” : “Zygote32Timing”;
TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag,
Trace。TRACE_TAG_DALVIK);
bootTimingsTraceLog。traceBegin(“ZygoteInit”);
RuntimeInit。preForkInit();
boolean startSystemServer = false;
String zygoteSocketName = “zygote”;
String abiList = null;
boolean enableLazyPreload = false;
for (int i = 1; i < argv。length; i++) {
if (“start-system-server”。equals(argv[i])) {
startSystemServer = true;
} else if (“——enable-lazy-preload”。equals(argv[i])) {
enableLazyPreload = 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)) {
zygoteSocketName = argv[i]。substring(SOCKET_NAME_ARG。length());
} else {
throw new RuntimeException(“Unknown command line argument: ” + argv[i]);
}
}
final boolean isPrimaryZygote = zygoteSocketName。equals(Zygote。PRIMARY_SOCKET_NAME);
if (!isRuntimeRestarted) {
if (isPrimaryZygote) {
FrameworkStatsLog。write(FrameworkStatsLog。BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__ZYGOTE_INIT_START,
startTime);
} else if (zygoteSocketName。equals(Zygote。SECONDARY_SOCKET_NAME)) {
FrameworkStatsLog。write(FrameworkStatsLog。BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__SECONDARY_ZYGOTE_INIT_START,
startTime);
}
}
if (abiList == null) {
throw new RuntimeException(“No ABI list supplied。”);
}
// 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());
preload(bootTimingsTraceLog);// 預載入類和資源[見小節3。4]
EventLog。writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock。uptimeMillis());
bootTimingsTraceLog。traceEnd(); // ZygotePreload
}
// Do an initial gc to clean up after startup
bootTimingsTraceLog。traceBegin(“PostZygoteInitGC”);
gcAndFinalize();
bootTimingsTraceLog。traceEnd(); // PostZygoteInitGC
bootTimingsTraceLog。traceEnd(); // ZygoteInit
Zygote。initNativeState(isPrimaryZygote);
ZygoteHooks。stopZygoteNoThreadCreation();
zygoteServer = new ZygoteServer(isPrimaryZygote);//為Zygote註冊socket
if (startSystemServer) {//啟動system_server[見小節3。5]
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process。
if (r != null) {
r。run();
return;
}
}
Log。i(TAG, “Accepting command socket connections”);
// The select loop returns early in the child process after a fork and
// loops forever in the zygote。
caller = zygoteServer。runSelectLoop(abiList);//進入迴圈模式[見小節3。6]
} catch (Throwable ex) {
Log。e(TAG, “System zygote died with exception”, ex);
throw ex;
} finally {
if (zygoteServer != null) {
zygoteServer。closeServerSocket();
}
}
// We’re in the child process and have exited the select loop。 Proceed to execute the
// command。
if (caller != null) {
caller。run();//啟動system_server中會講到。
}
}
[–>ZygoteServer。java]
/** //為Zygote註冊socket
* Initialize the Zygote server with the Zygote server socket, USAP pool server socket, and USAP
* pool event FD。
*
* @param isPrimaryZygote If this is the primary Zygote or not。
*/
ZygoteServer(boolean isPrimaryZygote) {
mUsapPoolEventFD = Zygote。getUsapPoolEventFD();
if (isPrimaryZygote) {
mZygoteSocket = Zygote。createManagedSocketFromInitSocket(Zygote。PRIMARY_SOCKET_NAME);//程序名稱
mUsapPoolSocket =
Zygote。createManagedSocketFromInitSocket(
Zygote。USAP_POOL_PRIMARY_SOCKET_NAME);
} else {
mZygoteSocket = Zygote。createManagedSocketFromInitSocket(Zygote。SECONDARY_SOCKET_NAME);
mUsapPoolSocket =
Zygote。createManagedSocketFromInitSocket(
Zygote。USAP_POOL_SECONDARY_SOCKET_NAME);
}
mUsapPoolSupported = true;
fetchUsapPoolPolicyProps();
}
3。4 ZygoteInit。preload
[–>ZygoteInit。java]
static void preload(TimingsTraceLog bootTimingsTraceLog) {
Log。d(TAG, “begin preload”);
bootTimingsTraceLog。traceBegin(“BeginPreload”);
beginPreload();
bootTimingsTraceLog。traceEnd(); // BeginPreload
bootTimingsTraceLog。traceBegin(“PreloadClasses”);
preloadClasses();
bootTimingsTraceLog。traceEnd(); // PreloadClasses
bootTimingsTraceLog。traceBegin(“CacheNonBootClasspathClassLoaders”);
cacheNonBootClasspathClassLoaders();
bootTimingsTraceLog。traceEnd(); // CacheNonBootClasspathClassLoaders
bootTimingsTraceLog。traceBegin(“PreloadResources”);
preloadResources();
bootTimingsTraceLog。traceEnd(); // PreloadResources
Trace。traceBegin(Trace。TRACE_TAG_DALVIK, “PreloadAppProcessHALs”);
nativePreloadAppProcessHALs();
Trace。traceEnd(Trace。TRACE_TAG_DALVIK);
Trace。traceBegin(Trace。TRACE_TAG_DALVIK, “PreloadGraphicsDriver”);
maybePreloadGraphicsDriver();
Trace。traceEnd(Trace。TRACE_TAG_DALVIK);
preloadSharedLibraries();
preloadTextResources();
// Ask the WebViewFactory to do any initialization that must run in the zygote process,
// for memory sharing purposes。
WebViewFactory。prepareWebViewInZygote();
endPreload();
warmUpJcaProviders();
Log。d(TAG, “end preload”);
sPreloadComplete = true;
}
3。5 ZygoteInit。forkSystemServer
[–>ZygoteInit。java]
/**
* Prepare the arguments and forks for the system server process。
*
* @return A {@code Runnable} that provides an entrypoint into system_server code in the child
* process; {@code null} in the parent。
*/
private static Runnable forkSystemServer(String abiList, String socketName,
ZygoteServer zygoteServer) {
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_PTRACE,
OsConstants。CAP_SYS_TIME,
OsConstants。CAP_SYS_TTY_CONFIG,
OsConstants。CAP_WAKE_ALARM,
OsConstants。CAP_BLOCK_SUSPEND
);
/* Containers run without some capabilities, so drop any caps that are not available。 */
StructCapUserHeader header = new StructCapUserHeader(
OsConstants。_LINUX_CAPABILITY_VERSION_3, 0);
StructCapUserData[] data;
try {
data = Os。capget(header);
} catch (ErrnoException ex) {
throw new RuntimeException(“Failed to capget()”, ex);
}
capabilities &= ((long) data[0]。effective) | (((long) data[1]。effective) << 32);
/* Hardcoded command line to start the system server */
String args[] = {
“——setuid=1000”,
“——setgid=1000”,
“——setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,”
+ “1024,1032,1065,3001,3002,3003,3006,3007,3009,3010,3011”,
“——capabilities=” + capabilities + “,” + capabilities,
“——nice-name=system_server”,
“——runtime-args”,
“——target-sdk-version=” + VMRuntime。SDK_VERSION_CUR_DEVELOPMENT,
“com。android。server。SystemServer”,
};
ZygoteArguments parsedArgs = null;
int pid;
try {
parsedArgs = new ZygoteArguments(args);
Zygote。applyDebuggerSystemProperty(parsedArgs);
Zygote。applyInvokeWithSystemProperty(parsedArgs);
if (Zygote。nativeSupportsTaggedPointers()) {
/* Enable pointer tagging in the system server。 Hardware support for this is present
* in all ARMv8 CPUs。 */
parsedArgs。mRuntimeFlags |= Zygote。MEMORY_TAG_LEVEL_TBI;
}
/* Enable gwp-asan on the system server with a small probability。 This is the same
* policy as applied to native processes and system apps。 */
parsedArgs。mRuntimeFlags |= Zygote。GWP_ASAN_LEVEL_LOTTERY;
if (shouldProfileSystemServer()) {
parsedArgs。mRuntimeFlags |= Zygote。PROFILE_SYSTEM_SERVER;
}
/* Request to fork the system server process */
// fork子程序system_server
pid = Zygote。forkSystemServer(
parsedArgs。mUid, parsedArgs。mGid,
parsedArgs。mGids,
parsedArgs。mRuntimeFlags,
null,
parsedArgs。mPermittedCapabilities,
parsedArgs。mEffectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
zygoteServer。closeServerSocket();
return handleSystemServerProcess(parsedArgs); //進入system_server程序[見小節4。1]
}
return null;
}
3。6 ZygoteServer。runSelectLoop
[–>ZygoteServer。java]
/**
* Listening socket that accepts new server connections。
*/
private LocalServerSocket mZygoteSocket;
/**
* 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。
*/
Runnable runSelectLoop(String abiList) {
ArrayList
ArrayList
//mZygoteSocket是socket通訊中的服務端,即zygote程序
socketFDs。add(mZygoteSocket。getFileDescriptor());
peers。add(null);
mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
while (true) {
fetchUsapPoolPolicyPropsWithMinInterval();
mUsapPoolRefillAction = UsapPoolRefillAction。NONE;
int[] usapPipeFDs = null;
StructPollfd[] pollFDs;
// Allocate enough space for the poll structs, taking into account
// the state of the USAP pool for this Zygote (could be a
// regular Zygote, a WebView Zygote, or an AppZygote)。
if (mUsapPoolEnabled) {
usapPipeFDs = Zygote。getUsapPipeFDs();
pollFDs = new StructPollfd[socketFDs。size() + 1 + usapPipeFDs。length];
} else {
pollFDs = new StructPollfd[socketFDs。size()];
}
/*
* For reasons of correctness the USAP pool pipe and event FDs
* must be processed before the session and server sockets。 This
* is to ensure that the USAP pool accounting information is
* accurate when handling other requests like API blacklist
* exemptions。
*/
int pollIndex = 0;
for (FileDescriptor socketFD : socketFDs) {
pollFDs[pollIndex] = new StructPollfd();
pollFDs[pollIndex]。fd = socketFD;
pollFDs[pollIndex]。events = (short) POLLIN;
++pollIndex;
}
final int usapPoolEventFDIndex = pollIndex;
if (mUsapPoolEnabled) {
pollFDs[pollIndex] = new StructPollfd();
pollFDs[pollIndex]。fd = mUsapPoolEventFD;
pollFDs[pollIndex]。events = (short) POLLIN;
++pollIndex;
// The usapPipeFDs array will always be filled in if the USAP Pool is enabled。
assert usapPipeFDs != null;
for (int usapPipeFD : usapPipeFDs) {
FileDescriptor managedFd = new FileDescriptor();
managedFd。setInt$(usapPipeFD);
pollFDs[pollIndex] = new StructPollfd();
pollFDs[pollIndex]。fd = managedFd;
pollFDs[pollIndex]。events = (short) POLLIN;
++pollIndex;
}
}
int pollTimeoutMs;
if (mUsapPoolRefillTriggerTimestamp == INVALID_TIMESTAMP) {
pollTimeoutMs = -1;
} else {
long elapsedTimeMs = System。currentTimeMillis() - mUsapPoolRefillTriggerTimestamp;
if (elapsedTimeMs >= mUsapPoolRefillDelayMs) {
// Normalize the poll timeout value when the time between one poll event and the
// next pushes us over the delay value。 This prevents poll receiving a 0
// timeout value, which would result in it returning immediately。
pollTimeoutMs = -1;
} else if (elapsedTimeMs <= 0) {
// This can occur if the clock used by currentTimeMillis is reset, which is
// possible because it is not guaranteed to be monotonic。 Because we can‘t tell
// how far back the clock was set the best way to recover is to simply re-start
// the respawn delay countdown。
pollTimeoutMs = mUsapPoolRefillDelayMs;
} else {
pollTimeoutMs = (int) (mUsapPoolRefillDelayMs - elapsedTimeMs);
}
}
int pollReturnValue;
try {
pollReturnValue = Os。poll(pollFDs, pollTimeoutMs);
} catch (ErrnoException ex) {
throw new RuntimeException(“poll failed”, ex);
}
if (pollReturnValue == 0) {
// The poll timeout has been exceeded。 This only occurs when we have finished the
// USAP pool refill delay period。
mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
mUsapPoolRefillAction = UsapPoolRefillAction。DELAYED;
} else {
boolean usapPoolFDRead = false;
while (——pollIndex >= 0) {
//採用I/O多路複用機制,當客戶端發出 連線請求或者資料處理請求時,則執行continue
if ((pollFDs[pollIndex]。revents & POLLIN) == 0) {
continue;
}
if (pollIndex == 0) {
// Zygote server socket
//建立客戶端連線
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers。add(newPeer);
socketFDs。add(newPeer。getFileDescriptor());
} else if (pollIndex < usapPoolEventFDIndex) { //處理客戶端資料事務
// Session socket accepted from the Zygote server socket
try {
ZygoteConnection connection = peers。get(pollIndex);
final Runnable command = connection。processOneCommand(this);
// TODO (chriswailes): Is this extra check necessary?
if (mIsForkChild) {
// We’re in the child。 We should always have a command to run at
// this stage if processOneCommand hasn‘t called “exec”。
if (command == null) {
throw new IllegalStateException(“command == null”);
}
return command;
} else {
// We’re in the server - we should never have any commands to run。
if (command != null) {
throw new IllegalStateException(“command != null”);
}
// We don‘t know whether the remote side of the socket was closed or
// not until we attempt to read from it from processOneCommand。 This
// shows up as a regular POLLIN event in our regular processing
// loop。
if (connection。isClosedByPeer()) {
connection。closeSocket();
peers。remove(pollIndex);
socketFDs。remove(pollIndex);
}
}
} catch (Exception e) {
if (!mIsForkChild) {
// We’re in the server so any exception here is one that has taken
// place pre-fork while processing commands or reading / writing
// from the control socket。 Make a loud noise about any such
// exceptions so that we know exactly what failed and why。
Slog。e(TAG, “Exception executing zygote command: ”, e);
// Make sure the socket is closed so that the other end knows
// immediately that something has gone wrong and doesn‘t time out
// waiting for a response。
ZygoteConnection conn = peers。remove(pollIndex);
conn。closeSocket();
socketFDs。remove(pollIndex);
} else {
// We’re in the child so any exception caught here has happened post
// fork and before we execute ActivityThread。main (or any other
// main() method)。 Log the details of the exception and bring down
// the process。
Log。e(TAG, “Caught post-fork exception in child process。”, e);
throw e;
}
} finally {
// Reset the child flag, in the event that the child process is a child-
// zygote。 The flag will not be consulted this loop pass after the
// Runnable is returned。
mIsForkChild = false;
}
} else {
// Either the USAP pool event FD or a USAP reporting pipe。
// If this is the event FD the payload will be the number of USAPs removed。
// If this is a reporting pipe FD the payload will be the PID of the USAP
// that was just specialized。 The `continue` statements below ensure that
// the messagePayload will always be valid if we complete the try block
// without an exception。
long messagePayload;
try {
byte[] buffer = new byte[Zygote。USAP_MANAGEMENT_MESSAGE_BYTES];
int readBytes =
Os。read(pollFDs[pollIndex]。fd, buffer, 0, buffer。length);
if (readBytes == Zygote。USAP_MANAGEMENT_MESSAGE_BYTES) {
DataInputStream inputStream =
new DataInputStream(new ByteArrayInputStream(buffer));
messagePayload = inputStream。readLong();
} else {
Log。e(TAG, “Incomplete read from USAP management FD of size ”
+ readBytes);
continue;
}
} catch (Exception ex) {
if (pollIndex == usapPoolEventFDIndex) {
Log。e(TAG, “Failed to read from USAP pool event FD: ”
+ ex。getMessage());
} else {
Log。e(TAG, “Failed to read from USAP reporting pipe: ”
+ ex。getMessage());
}
continue;
}
if (pollIndex > usapPoolEventFDIndex) {
Zygote。removeUsapTableEntry((int) messagePayload);
}
usapPoolFDRead = true;
}
}
if (usapPoolFDRead) {
int usapPoolCount = Zygote。getUsapPoolCount();
if (usapPoolCount < mUsapPoolSizeMin) {
// Immediate refill
mUsapPoolRefillAction = UsapPoolRefillAction。IMMEDIATE;
} else if (mUsapPoolSizeMax - usapPoolCount >= mUsapPoolRefillThreshold) {
// Delayed refill
mUsapPoolRefillTriggerTimestamp = System。currentTimeMillis();
}
}
}
if (mUsapPoolRefillAction != UsapPoolRefillAction。NONE) {
int[] sessionSocketRawFDs =
socketFDs。subList(1, socketFDs。size())
。stream()
。mapToInt(FileDescriptor::getInt$)
。toArray();
final boolean isPriorityRefill =
mUsapPoolRefillAction == UsapPoolRefillAction。IMMEDIATE;
final Runnable command =
fillUsapPool(sessionSocketRawFDs, isPriorityRefill);
if (command != null) {
return command;
} else if (isPriorityRefill) {
// Schedule a delayed refill to finish refilling the pool。
mUsapPoolRefillTriggerTimestamp = System。currentTimeMillis();
}
}
}
}
Zygote程序建立Java虛擬機器,並註冊JNI方法, 真正成為Java程序的母體,用於孵化Java程序。 在建立完system_server程序後,zygote功成身退,呼叫runSelectLoop(),隨時待命,當接收到請求建立新程序請求時立即喚醒並執行相應工作。
四。 system_server
Zygote透過fork後建立system_server程序,在小節[3。5]執行完forkSystemServer()方法後,進入到了handleSystemServerProcess()方法,如下所示。
4。1 handleSystemServerProcess
[–>ZygoteInit。java]
/**
* Finish remaining work for the newly forked system server process。
*/
private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {
// set umask to 0077 so new files and directories will default to owner-only permissions。
Os。umask(S_IRWXG | S_IRWXO);
if (parsedArgs。mNiceName != null) {
Process。setArgV0(parsedArgs。mNiceName);//設定當前程序名為“system_server”
}
final String systemServerClasspath = Os。getenv(“SYSTEMSERVERCLASSPATH”);
if (systemServerClasspath != null) {
performSystemServerDexOpt(systemServerClasspath);//執行dex最佳化操作,比如services。jar
// Capturing profiles is only supported for debug or eng builds since selinux normally
// prevents it。
if (shouldProfileSystemServer() && (Build。IS_USERDEBUG || Build。IS_ENG)) {
try {
Log。d(TAG, “Preparing system server profile”);
prepareSystemServerProfile(systemServerClasspath);
} catch (Exception e) {
Log。wtf(TAG, “Failed to set up system server profile”, e);
}
}
}
if (parsedArgs。mInvokeWith != null) {
String[] args = parsedArgs。mRemainingArgs;
// If we have a non-null system server class path, we‘ll have to duplicate the
// existing arguments and append the classpath to it。 ART will handle the classpath
// correctly when we exec a new process。
if (systemServerClasspath != null) {
String[] amendedArgs = new String[args。length + 2];
amendedArgs[0] = “-cp”;
amendedArgs[1] = systemServerClasspath;
System。arraycopy(args, 0, amendedArgs, 2, args。length);
args = amendedArgs;
}
WrapperInit。execApplication(parsedArgs。mInvokeWith,
parsedArgs。mNiceName, parsedArgs。mTargetSdkVersion,
VMRuntime。getCurrentInstructionSet(), null, args);
throw new IllegalStateException(“Unexpected return from WrapperInit。execApplication”);
} else {
ClassLoader cl = null;
if (systemServerClasspath != null) {//建立PathClassLoader類載入器
cl = createPathClassLoader(systemServerClasspath, parsedArgs。mTargetSdkVersion);
Thread。currentThread()。setContextClassLoader(cl);
}
/*
* Pass the remaining arguments to SystemServer。
*/
//[見小節4。2]
return ZygoteInit。zygoteInit(parsedArgs。mTargetSdkVersion,
parsedArgs。mDisabledCompatChanges,
parsedArgs。mRemainingArgs, cl);
}
/* should never reach here */
}
system_server程序建立PathClassLoader類載入器。
4。2 ZygoteInit。zygoteInit
[–>ZygoteInit。java]
/**
* The main function called when started through the zygote process。 This could be unified with
* main(), if the native code in nativeFinishInit() were rationalized with Zygote startup。
*
* Current recognized args:
*
-
[——] <;start class name>; <;args>;
*
*
*
* @param targetSdkVersion target SDK version
* @param disabledCompatChanges set of disabled compat changes for the process (all others
* are enabled)
* @param argv arg strings
*/
public static final Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
String[] argv, ClassLoader classLoader) {
if (RuntimeInit。DEBUG) {
Slog。d(RuntimeInit。TAG, “RuntimeInit: Starting application from zygote”);
}
Trace。traceBegin(Trace。TRACE_TAG_ACTIVITY_MANAGER, “ZygoteInit”);
RuntimeInit。redirectLogStreams();
RuntimeInit。commonInit();// 通用的一些初始化
ZygoteInit。nativeZygoteInit();// zygote初始化
return RuntimeInit。applicationInit(targetSdkVersion, disabledCompatChanges, argv,
classLoader);// [見小節3。4]
}
Binder執行緒池啟動
nativeZygoteInit()方法經過層層呼叫,會進入app_main。cpp中的onZygoteInit()方法, Binder執行緒池的建立也是在這個過程,如下:
virtual void onZygoteInit()
{
sp
ALOGV(“App process: starting thread pool。\n”);
proc->startThreadPool();//啟動新binder執行緒池
}
捕獲特殊異常
[–>RuntimeInit。java]
applicationInit()方法經過層層呼叫,會丟擲異常RuntimeInit。MethodAndArgsCaller(m, argv), 具體過程如下:
protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
String[] argv, ClassLoader classLoader) {
// If the application calls System。exit(), terminate the process
// immediately without running any shutdown hooks。 It is not possible to
// shutdown an Android application gracefully。 Among other things, the
// Android runtime shutdown hooks close the Binder driver, which can cause
// leftover running threads to crash before the process actually exits。
nativeSetExitWithoutCleanup(true);
VMRuntime。getRuntime()。setTargetSdkVersion(targetSdkVersion);
VMRuntime。getRuntime()。setDisabledCompatChanges(disabledCompatChanges);
final Arguments args = new Arguments(argv);
// The end of of the RuntimeInit event (see #zygoteInit)。
Trace。traceEnd(Trace。TRACE_TAG_ACTIVITY_MANAGER);
// Remaining arguments are passed to the start class’s static main
return findStaticMain(args。startClass, args。startArgs, classLoader);//找到目標類的靜態main()方法
}
protected static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
Class<?> cl;
try {
cl = Class。forName(className, true, classLoader); //此處的className等於SystemServer
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
“Missing class when invoking static main ” + className,
ex);
}
Method m;
try {
m = cl。getMethod(“main”, new Class[] { String[]。class });
} catch (NoSuchMethodException ex) {
throw new RuntimeException(
“Missing static main on ” + className, ex);
} catch (SecurityException ex) {
throw new RuntimeException(
“Problem getting static main on ” + className, ex);
}
int modifiers = m。getModifiers();
if (! (Modifier。isStatic(modifiers) && Modifier。isPublic(modifiers))) {
throw new RuntimeException(
“Main method is not public and static on ” + className);
}
/*
* This throw gets caught in ZygoteInit。main(), which responds
* by invoking the exception‘s run() method。 This arrangement
* clears up all the stack frames that were required in setting
* up the process。
*/
return new MethodAndArgsCaller(m, argv); //丟擲異常Runnable物件
}
static class MethodAndArgsCaller implements Runnable {
/** method to call */
private final Method mMethod;
/** argument array */
private final String[] mArgs;
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
public void run() {
try {
mMethod。invoke(null, new Object[] { mArgs });
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InvocationTargetException ex) {
Throwable cause = ex。getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else if (cause instanceof Error) {
throw (Error) cause;
}
throw new RuntimeException(ex);
}
}
}
設定TargetSdk版本;並丟擲異常,然後由ZygoteInit。main()捕獲該異常, 見下文
4。3 ZygoteInit。main
[–>ZygoteInit。java]
public static void main(String argv[]) {
。。。。
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);//丟擲MethodAndArgsCaller異常
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process。
if (r != null) {
r。run();//此處透過反射,會呼叫SystemServer。main()方法 [見小節4。4]
return;
}
}
。。。。
}
static class MethodAndArgsCaller implements Runnable {
private final Method mMethod;
private final String[] mArgs;
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
public void run() {
//執行SystemServer。main()
mMethod。invoke(null, new Object[] { mArgs });
}
}
採用丟擲異常的方式,用於棧幀清空,提供利用率, 以至於現在大家看到的每個Java程序的呼叫棧如下:
。。。
at com。android。server。SystemServer。main(SystemServer。java:175)
at java。lang。reflect。Method。invoke!(Native method)
at com。android。internal。os。ZygoteInit$MethodAndArgsCaller。run(ZygoteInit。java:738)
at com。android。internal。os。ZygoteInit。main(ZygoteInit。java:628)
4。4 SystemServer。main
[–>SystemServer。java]
public final class SystemServer {
。。。
public static void main(String[] args) {
//先初始化SystemServer物件,再呼叫物件的run()方法
new SystemServer()。run();
}
}
4。5 SystemServer。run
[–>SystemServer。java]
private void run() {
TimingsTraceAndSlog t = new TimingsTraceAndSlog();
try {
t。traceBegin(“InitBeforeStartServices”);
// Record the process start information in sys props。
SystemProperties。set(SYSPROP_START_COUNT, String。valueOf(mStartCount));
SystemProperties。set(SYSPROP_START_ELAPSED, String。valueOf(mRuntimeStartElapsedTime));
SystemProperties。set(SYSPROP_START_UPTIME, String。valueOf(mRuntimeStartUptime));
EventLog。writeEvent(EventLogTags。SYSTEM_SERVER_START,
mStartCount, mRuntimeStartUptime, mRuntimeStartElapsedTime);
//
// 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。forceSafeLabels();
// Default to FULL within the system server。
SQLiteGlobal。sDefaultSyncMode = SQLiteGlobal。SYNC_MODE_FULL;
// Deactivate SQLiteCompatibilityWalFlags until settings provider is initialized
SQLiteCompatibilityWalFlags。init(null);
// Here we go!
Slog。i(TAG, “Entered the Android system server!”);
final long uptimeMillis = SystemClock。elapsedRealtime();
EventLog。writeEvent(EventLogTags。BOOT_PROGRESS_SYSTEM_RUN, uptimeMillis);
if (!mRuntimeRestart) {
FrameworkStatsLog。write(FrameworkStatsLog。BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
FrameworkStatsLog
。BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__SYSTEM_SERVER_INIT_START,
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’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();
// 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);
Looper。prepareMainLooper();// 準備主執行緒looper
Looper。getMainLooper()。setSlowLogThresholdMs(
SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);
SystemServiceRegistry。sEnableServiceNotFoundWtf = true;
// Initialize native services。
//載入android_servers。so庫,該庫包含的原始碼在frameworks/base/services/目錄下
System。loadLibrary(“android_servers”);
// Allow heap / perf profiling。
initZygoteChildHeapProfiling();
// Debug builds - spawn a thread to monitor for fd leaks。
if (Build。IS_DEBUGGABLE) {
spawnFdLeakCheckThread();
}
// Check whether we failed to shut down last time we tried。
// This call may not return。
performPendingShutdown();//檢測上次關機過程是否失敗,該方法可能不會返回
// Initialize the system context。
createSystemContext();//初始化系統上下文
// Call per-process mainline module initialization。
ActivityThread。initializeMainlineModules();
// Create the system service manager。
//建立系統服務管理
mSystemServiceManager = new SystemServiceManager(mSystemContext);
mSystemServiceManager。setStartInfo(mRuntimeRestart,
mRuntimeStartElapsedTime, mRuntimeStartUptime);
LocalServices。addService(SystemServiceManager。class, mSystemServiceManager);
// Prepare the thread pool for init tasks that can be parallelized
SystemServerInitThreadPool。start();
// Attach JVMTI agent if this is a debuggable build and the system property is set。
if (Build。IS_DEBUGGABLE) {
// Property is of the form “library_path=parameters”。
String jvmtiAgent = SystemProperties。get(“persist。sys。dalvik。jvmtiagent”);
if (!jvmtiAgent。isEmpty()) {
int equalIndex = jvmtiAgent。indexOf(‘=’);
String libraryPath = jvmtiAgent。substring(0, equalIndex);
String parameterList =
jvmtiAgent。substring(equalIndex + 1, jvmtiAgent。length());
// Attach the agent。
try {
Debug。attachJvmtiAgent(libraryPath, parameterList, null);
} catch (Exception e) {
Slog。e(“System”, “*************************************************”);
Slog。e(“System”, “********** Failed to load jvmti plugin: ” + jvmtiAgent);
}
}
}
} finally {
t。traceEnd(); // InitBeforeStartServices
}
// Setup the default WTF handler
RuntimeInit。setDefaultApplicationWtfHandler(SystemServer::handleEarlySystemWtf);
// Start services。
try {//啟動各種系統服務
t。traceBegin(“StartServices”);
startBootstrapServices(t);// 啟動引導服務
startCoreServices(t); // 啟動核心服務
startOtherServices(t); // 啟動其他服務[見小節4。6]
} catch (Throwable ex) {
Slog。e(“System”, “******************************************”);
Slog。e(“System”, “************ Failure starting system services”, ex);
throw ex;
} finally {
t。traceEnd(); // StartServices
}
StrictMode。initVmDefaults(null);
if (!mRuntimeRestart && !isFirstBootOrUpgrade()) {
final long uptimeMillis = SystemClock。elapsedRealtime();
FrameworkStatsLog。write(FrameworkStatsLog。BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
FrameworkStatsLog。BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__SYSTEM_SERVER_READY,
uptimeMillis);
final long maxUptimeMillis = 60 * 1000;
if (uptimeMillis > maxUptimeMillis) {
Slog。wtf(SYSTEM_SERVER_TIMING_TAG,
“SystemServer init took too long。 uptimeMillis=” + uptimeMillis);
}
}
// Diagnostic to ensure that the system is in a base healthy state。 Done here as a common
// non-zygote process。
if (!VMRuntime。hasBootImageSpaces()) {
Slog。wtf(TAG, “Runtime is not running with a boot image!”);
}
// Loop forever。
Looper。loop();//一直迴圈執行
throw new RuntimeException(“Main thread loop unexpectedly exited”);
}
4。6 服務啟動
public final class SystemServer {
private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
。。。
//phase100
mSystemServiceManager。startBootPhase(t, SystemService。PHASE_WAIT_FOR_DEFAULT_DISPLAY);
。。。
}
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
。。。
//phase480 和phase500
mSystemServiceManager。startBootPhase(t, SystemService。PHASE_LOCK_SETTINGS_READY);
mSystemServiceManager。startBootPhase(t, SystemService。PHASE_SYSTEM_SERVICES_READY);
。。。
//[見小節4。7]
mActivityManagerService。systemReady(new Runnable() {
@Override
public void run() {
//phase550
mSystemServiceManager。startBootPhase(
t, SystemService。PHASE_ACTIVITY_MANAGER_READY);
。。。
//phase600
mSystemServiceManager。startBootPhase(
t, SystemService。PHASE_THIRD_PARTY_APPS_CAN_START);
}
}
}
}
start: 建立AMS, PMS, LightsService, DMS。
phase100: 進入Phase100, 建立PKMS, WMS, IMS, DBMS, LockSettingsService, JobSchedulerService, MmsService等服務;
phase480 && 500: 進入Phase480, 呼叫WMS, PMS, PKMS, DisplayManagerService這4個服務的systemReady();
Phase550: 進入phase550, 執行AMS。systemReady(), 啟動SystemUI, WebViewFactory, Watchdog。
Phase600: 進入phase600, 執行AMS。systemReady(), 執行各種服務的systemRunning()。
Phase1000: 進入1000, 執行finishBooting, 啟動啟動on-hold程序。
4。7 AMS。systemReady
public final class ActivityManagerService extends ActivityManagerNative implements Watchdog。Monitor, BatteryStatsImpl。BatteryCallback {
public void systemReady(final Runnable goingCallback) {
。。。 //update相關
mSystemReady = true;
//殺掉所有非persistent程序
removeProcessLocked(proc, true, false, “system update done”);
mProcessesReady = true;
goingCallback。run(); //[見小節1。6。2]
addAppLocked(info, false, null); //啟動所有的persistent程序
mBooting = true;
//啟動home
startHomeActivityLocked(mCurrentUserId, “systemReady”);
//恢復棧頂的Activity
mStackSupervisor。resumeTopActivitiesLocked();
}
}
System_server主執行緒的啟動工作,總算完成, 進入Looper。loop()狀態,等待其他執行緒透過handler傳送訊息再處理。
五。 app
對於普通的app程序,跟system_server程序的啟動過來有些類似。不同的是app程序是向發訊息給system_server程序, 由system_server向zygote發出建立程序的請求。
理解Android程序建立流程, 可知程序建立後 接下來會進入ActivityThread。main()過程。
5。1 ActivityThread。main
public static void main(String[] args) {
Trace。traceBegin(Trace。TRACE_TAG_ACTIVITY_MANAGER, “ActivityThreadMain”);
// Install selective syscall interception
AndroidOs。install();
// CloseGuard defaults to true and can be quite spammy。 We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs。
CloseGuard。setEnabled(false);
Environment。initForCurrentUser();
// Make sure TrustedCertificateStore looks in the right place for CA certificates
final File configDir = Environment。getUserConfigDirectory(UserHandle。myUserId());
TrustedCertificateStore。setDefaultUserDirectory(configDir);
// Call per-process mainline module initialization。
initializeMainlineModules();
Process。setArgV0(“
Looper。prepareMainLooper();//建立主執行緒looper
// Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line。
// It will be in the format “seq=114”
long startSeq = 0;
if (args != null) {
for (int i = args。length - 1; i >= 0; ——i) {
if (args[i] != null && args[i]。startsWith(PROC_START_SEQ_IDENT)) {
startSeq = Long。parseLong(
args[i]。substring(PROC_START_SEQ_IDENT。length()));
}
}
}
ActivityThread thread = new ActivityThread();
thread。attach(false, startSeq);//attach到系統程序
if (sMainThreadHandler == null) {
sMainThreadHandler = thread。getHandler();
}
if (false) {
Looper。myLooper()。setMessageLogging(new
LogPrinter(Log。DEBUG, “ActivityThread”));
}
// End of event ActivityThreadMain。
Trace。traceEnd(Trace。TRACE_TAG_ACTIVITY_MANAGER);
Looper。loop();//主執行緒進入迴圈狀態
throw new RuntimeException(“Main thread loop unexpectedly exited”);
}
5。2 呼叫棧對比
App程序的主執行緒呼叫棧的棧底如下:
。。。
at android。app。ActivityThread。main(ActivityThread。java:5442)
at java。lang。reflect。Method。invoke!(Native method)
at com。android。internal。os。ZygoteInit$MethodAndArgsCaller。run(ZygoteInit。java:738)
at com。android。internal。os。ZygoteInit。main(ZygoteInit。java:628)
跟前面介紹的system_server程序呼叫棧對比:
at com。android。server。SystemServer。main(SystemServer。java:175)
at java。lang。reflect。Method。invoke!(Native method)
at com。android。internal。os。ZygoteInit$MethodAndArgsCaller。run(ZygoteInit。java:738)
at com。android。internal。os。ZygoteInit。main(ZygoteInit。java:628)
六。 啟動日誌分析
以下列舉啟動部分重要程序以及關鍵節點會打印出的log
/system/bin/vold: 383
/system/bin/lmkd: 432
/system/bin/surfaceflinger: 434
/system/bin/debuggerd64: 537
/system/bin/mediaserver: 540
/system/bin/installd: 541
/system/vendor/bin/thermal-engine: 552
zygote64: 557
zygote: 558
system_server: 1274
1。 before zygote日誌
//啟動vold, 再列舉當前系統所支援的檔案系統。 執行到system/vold/main。cpp的main()
11-23 14:36:47。474 383 383 I vold : Vold 3。0 (the awakening) firing up
11-23 14:36:47。475 383 383 V vold : Detected support for: ext4 vfat
//使用核心的lmk策略
11-23 14:36:47。927 432 432 I lowmemorykiller: Using in-kernel low memory killer interface
//啟動SurfaceFlinger
11-23 14:36:48。041 434 434 I SurfaceFlinger: SurfaceFlinger is starting
11-23 14:36:48。042 434 434 I SurfaceFlinger: SurfaceFlinger‘s main thread ready to run。 Initializing graphics H/W。。。
// 開機動畫
11-23 14:36:48。583 508 508 I BootAnimation: bootanimation launching 。。。
// debuggerd
11-23 14:36:50。306 537 537 I : debuggerd: starting
// installd啟動
11-23 14:36:50。311 541 541 I installd: installd firing up
// thermal守護程序
11-23 14:36:50。369 552 552 I ThermalEngine: Thermal daemon started
2。 zygote日誌
// Zygote64程序(Zygote): AndroidRuntime::start
11-23 14:36:51。260 557 557 D AndroidRuntime: >>>>>> START com。android。internal。os。ZygoteInit uid 0 <<<<<<
// Zygote64程序: AndroidRuntime::startVm
11-23 14:36:51。304 557 557 D AndroidRuntime: CheckJNI is OFF
// 執行ZygoteInit。preload()
11-23 14:36:52。134 557 557 D Zygote : begin preload
// 執行ZygoteInit。preloadClasses(), 預載入3860個classes, 花費時長746ms
11-23 14:36:52。134 557 557 I Zygote : Preloading classes。。。
11-23 14:36:52。881 557 557 I Zygote : 。。。preloaded 3860 classes in 746ms。
// 執行ZygoteInit。preloadClasses(), 預載入86組資源, 花費時長179ms
11-23 14:36:53。114 557 557 I Zygote : Preloading resources。。。
11-23 14:36:53。293 557 557 I Zygote : 。。。preloaded 86 resources in 179ms。
// 執行ZygoteInit。preloadSharedLibraries()
11-23 14:36:53。494 557 557 I Zygote : Preloading shared libraries。。。
11-23 14:36:53。503 557 557 D Zygote : end preload
// 執行com_android_internal_os_Zygote_nativeForkSystemServer(),成功fork出system_server程序
11-23 14:36:53。544 557 557 I Zygote : System server process 1274 has been created
// Zygote開始進入runSelectLoop()
11-23 14:36:53。546 557 557 I Zygote : Accepting command socket connections
3。 system_server日誌
//進入system_server, 建立跟Zygote程序的socket通道
11-23 14:36:53。586 1274 1274 I Zygote : Process: zygote socket opened, supported ABIS: armeabi-v7a,armeabi
// 執行SystemServer。run()
11-23 14:36:53。618 1274 1274 I SystemServer: Entered the Android system server! <===> boot_progress_system_run
// 等待installd準備就緒
11-23 14:36:53。707 1274 1274 I Installer: Waiting for installd to be ready。
//服務啟動
11-23 14:36:53。732 1274 1274 I ActivityManager: Memory class: 192
//phase100
11-23 14:36:53。883 1274 1274 I SystemServiceManager: Starting phase 100
11-23 14:36:53。902 1274 1274 I SystemServer: Package Manager
11-23 14:37:03。816 1274 1274 I SystemServer: User Service
。。。
11-23 14:37:03。940 1274 1274 I SystemServer: Init Watchdog
11-23 14:37:03。941 1274 1274 I SystemServer: Input Manager
11-23 14:37:03。946 1274 1274 I SystemServer: Window Manager
。。。
11-23 14:37:04。081 1274 1274 I SystemServiceManager: Starting com。android。server。MountService$Lifecycle
11-23 14:37:04。088 1274 2717 D MountService: Thinking about reset, mSystemReady=false, mDaemonConnected=true
11-23 14:37:04。088 1274 1274 I SystemServiceManager: Starting com。android。server。UiModeManagerService
11-23 14:37:04。520 1274 1274 I SystemServer: NetworkTimeUpdateService
//phase480 && 500
11-23 14:37:05。056 1274 1274 I SystemServiceManager: Starting phase 480
11-23 14:37:05。061 1274 1274 I SystemServiceManager: Starting phase 500
11-23 14:37:05。231 1274 1274 I ActivityManager: System now ready <==> boot_progress_ams_ready
11-23 14:37:05。234 1274 1274 I SystemServer: Making services ready
11-23 14:37:05。243 1274 1274 I SystemServer: WebViewFactory preparation
//phase550
11-23 14:37:05。234 1274 1274 I SystemServiceManager: Starting phase 550
11-23 14:37:05。237 1274 1288 I ActivityManager: Force stopping com。android。providers。media appid=10010 user=-1: vold reset
//Phase600
11-23 14:37:06。066 1274 1274 I SystemServiceManager: Starting phase 600
11-23 14:37:06。236 1274 1274 D MountService: onStartUser 0
4。 logcat小技巧
透過adb bugreport抓取log資訊。先看zygote是否起來, 再看system_server主執行緒的執行情況,再看ActivityManager情況
adb logcat -s Zygote
adb logcat -s SystemServer
adb logcat -s SystemServiceManager
adb logcat | grep “1359 1359” //system_server情況
adb logcat -s ActivityManager
現場除錯命令
cat proc/[pid]/stack ==> 檢視kernel呼叫棧
debuggerd -b [pid] ==> 也不可以不帶引數-b, 則直接輸出到/data/tombstones/目錄
kill -3 [pid] ==> 生成/data/anr/traces。txt檔案
lsof [pid] ==> 檢視程序所開啟的檔案
七。 總結
各大核心程序啟動後,都會進入各種物件所相應的main()方法,如下
程序main方法
程序
主方法
init程序
Init。main()
zygote程序
ZygoteInit。main()
app_process程序
RuntimeInit。main()
system_server程序
SystemServer。main()
app程序
ActivityThread。main()
注意app_process程序是指透過/system/bin/app_process啟動的程序,且後面跟的引數不帶–zygote,即並非啟動zygote程序。 比如常見的有透過adb shell方式來執行am,pm等命令,便是這種方式。
重啟相關程序
關於重要程序重啟的過程,會觸發哪些關聯程序重啟名單:
zygote:觸發media、netd以及子程序(包括system_server程序)重啟;
system_server: 觸發zygote重啟;
surfaceflinger:觸發zygote重啟;
servicemanager: 觸發zygote、healthd、media、surfaceflinger、drm重啟
所以,surfaceflinger,servicemanager,zygote自身以及system_server程序被殺都會觸發Zygote重啟。
下一篇:增值稅中的“減按”知多少