您當前的位置:首頁 > 攝影

Android系統啟動-綜述

作者:由 西門吹雪 發表于 攝影時間:2022-01-18

基於Android 12的原始碼剖析, Android啟動過程概述

一。 概述

Android系統底層基於Linux Kernel, 當Kernel啟動過程會建立init程序, 該程序是所有使用者空間的鼻祖, init程序會啟動servicemanager(binder服務管家), Zygote程序(Java程序的鼻祖)。 Zygote程序會建立 system_server程序以及各種app程序,下圖是這幾個系統重量級程序之間的層級關係。

Android系統啟動-綜述

二。 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程序拉起。

Android系統啟動-綜述

接下來,便是進入了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(sizeof(spaced_commands) / sizeof(spaced_commands[0]));

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 args;

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& options, bool zygote)

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 socketFDs = new ArrayList<>();

ArrayList peers = new 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 proc = ProcessState::self();

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重啟。

標簽: System  main  Server  zygote