Android系统启动流程,从init.rc 到 launcher 启动过程分析
目录
1、zygote 启动分析
1.1、init进程的入口函数
1.2、解析init.rc
1.3、app_main.cpp 解析zygote启动参数
1.4、ZygoteInit.java 进入Java的地盘
1.5、Zygote进程启动总结:
2、启动systemServer
2.1、systemServer 简介
2.2、启动SystemServer进程的子进程
2.3、SystemServer 启动总结
3、启动Launcher
3.1、Launcher 启动总结:
4、参考
system\core\init\init.cpp
int main(int argc, char** argv) {
if (!strcmp(basename(argv[0]), "ueventd")) {
return ueventd_main(argc, argv);
}
if (!strcmp(basename(argv[0]), "watchdogd")) {
return watchdogd_main(argc, argv);
}
umask(0);
add_environment("PATH", _PATH_DEFPATH);
bool is_first_stage = (argc == 1) || (strcmp(argv[1], "--second-stage") != 0);
// 1、创建挂载系统运行所需的目录
if (is_first_stage) {
mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
mkdir("/dev/pts", 0755);
mkdir("/dev/socket", 0755);
mount("devpts", "/dev/pts", "devpts", 0, NULL);
#define MAKE_STR(x) __STRING(x)
mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC));
mount("sysfs", "/sys", "sysfs", 0, NULL);
mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL);
}
...
// 2、初始化kernel 打印的日志。
InitKernelLogging(argv);
...
// 3、系统属性服务初始化
property_init();
...
// 4、创建epoll句柄
epoll_fd = epoll_create1(EPOLL_CLOEXEC);
if (epoll_fd == -1) {
PLOG(ERROR) << "epoll_create1 failed";
exit(1);
}
// 5、用于设置处理子进程处理函的数,如果其子进程(zygote) 异常退出,
// init进程会调用改函数中设定的信号处理函数来处理。
signal_handler_init();
// 6、导入默认的环境变量
property_load_boot_defaults();
export_oem_lock_status();
// 7、启动属性服务
start_property_service();
const BuiltinFunctionMap function_map;
Action::set_function_map(&function_map);
Parser& parser = Parser::GetInstance();
parser.AddSectionParser("service",std::make_unique());
parser.AddSectionParser("on", std::make_unique());
parser.AddSectionParser("import", std::make_unique());
// 8、解析init.rc 文件
parser.ParseConfig("/init.rc");
ActionManager& am = ActionManager::GetInstance();
am.QueueEventTrigger("early-init");
// Queue an action that waits for coldboot done so we know ueventd has set up all of /dev...
am.QueueBuiltinAction(wait_for_coldboot_done_action, "wait_for_coldboot_done");
// ... so that we can start queuing up actions that require stuff from /dev.
am.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
am.QueueBuiltinAction(keychord_init_action, "keychord_init");
am.QueueBuiltinAction(console_init_action, "console_init");
// Trigger all the boot actions to get us started.
am.QueueEventTrigger("init");
// Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random
// wasn't ready immediately after wait_for_coldboot_done
am.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
// Don't mount filesystems or start core system services in charger mode.
std::string bootmode = property_get("ro.bootmode");
if (bootmode == "charger") {
am.QueueEventTrigger("charger");
} else {
am.QueueEventTrigger("late-init");
}
// Run all property triggers based on current state of the properties.
am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");
while (true) {
if (!waiting_for_exec) {
am.ExecuteOneCommand();
// 9、重启已经 死去 的进程
restart_processes();
}
int timeout = -1;
if (process_needs_restart) {
timeout = (process_needs_restart - gettime()) * 1000;
if (timeout < 0)
timeout = 0;
}
if (am.HasMoreCommands()) {
timeout = 0;
}
bootchart_sample(&timeout);
epoll_event ev;
int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, timeout));
if (nr == -1) {
PLOG(ERROR) << "epoll_wait failed";
} else if (nr == 1) {
((void (*)()) ev.data.ptr)();
}
}
return 0;
}
1、创建挂在文系统运行的时候所需要的文件目录,在系统不存在的时候这些目录也会不存在。
2、初始化Kernel 的 log,这样就可以从外界获取Kernel 的日志。 让kernel 和外界进行交流了。
3、对系统属性进行初始化。
4、epoll是在2.6内核中提出的,是之前的select和poll的增强版本。相对于select和poll来说,epoll更加灵活,没有描述符限制。epoll使用一个文件描述符管理多个描述符,将用户关系的文件描述符的事件存放到内核的一个事件表中,这样在用户空间和内核空间的copy只需一次.
5、用于设置处理子进程处理函的数,如果其子进程(zygote) 异常退出,init进程会调用改函数中设定的信号处理函数来处理。
6、导入默认的环境变量
7、启动属性服务
8、启动解析init.rc 服务
9、init 的所有子进程(zygote 和 其他的子进程)如果 死掉了,都是会在这里进行重启。
system/core/rootdir/init.rc
init.rc是一个非常重要的文件,它是有Android 初始化语言(Android init Language)编写的脚本。主要包含5中类型语句:
import /init.environ.rc
import /init.usb.rc
import /init.${ro.hardware}.rc
import /init.usb.configfs.rc
import /init.${ro.zygote}.rc
on early-init
write /proc/1/oom_score_adj -1000
write /proc/sys/kernel/sysrq 0
restorecon /adb_keys
mkdir /mnt 0775 root system
restorecon /postinstall
start ueventd
on init
sysclktz 0
# Mix device-specific information into the entropy pool
copy /proc/cmdline /dev/urandom
copy /default.prop /dev/urandom
...
其中这里的
其中以 init.zygote32_64.rc 内容如下:
service zygote /system/bin/app_process32 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
class main
priority -20
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
writepid /dev/cpuset/foreground/tasks /sys/fs/cgroup/stune/foreground/tasks
service zygote_secondary /system/bin/app_process64 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
class main
priority -20
socket zygote_secondary stream 660 root system
onrestart restart zygote
writepid /dev/cpuset/foreground/tasks /sys/fs/cgroup/stune/foreground/tasks
可以看出启动了两个service 一个名称为zygote ,执行app_process32,作为主模式。
另一个名称为zygote_secondary,执行app_process64 ,作为辅助模式。
以 init.zygote64.rc 为例进行分析学习:
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
class main
priority -20
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
writepid /dev/cpuset/foreground/tasks /sys/fs/cgroup/stune/foreground/tasks
Zygote是以service配置的,所以当解析该完成时,init进程就会调用fork去创建Zygote进程,并且执行app_main.cpp文件中的main函数,作为Zygote进行的启动入口。
frameworks\base\cmds\app_process\app_main.cpp
int main(int argc, char* const argv[])
{
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
// Older kernels don't understand PR_SET_NO_NEW_PRIVS and return
// EINVAL. Don't die on such kernels.
if (errno != EINVAL) {
LOG_ALWAYS_FATAL("PR_SET_NO_NEW_PRIVS failed: %s", strerror(errno));
return 12;
}
}
// 1、创建AppRuntime 对象
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
// Process command line arguments
// ignore argv[0]
argc--;
argv++;
// Everything up to '--' or first non '-' arg goes to the vm.
//
// The first argument after the VM args is the "parent dir", which
// is currently unused.
//
// After the parent dir, we expect one or more the following internal
// arguments :
//
// --zygote : Start in zygote mode
// --start-system-server : Start the system server.
// --application : Start in application (stand alone, non zygote) mode.
// --nice-name : The nice name for this process.
//
// For non zygote starts, these arguments will be followed by
// the main class name. All remaining arguments are passed to
// the main method of this class.
//
// For zygote starts, all remaining arguments are passed to the zygote.
// main function.
//
// Note that we must copy argument string values since we will rewrite the
// entire argument block when we apply the nice name to argv0.
int i;
for (i = 0; i < argc; i++) {
if (argv[i][0] != '-') {
break;
}
if (argv[i][1] == '-' && argv[i][2] == 0) {
++i; // Skip --.
break;
}
runtime.addOption(strdup(argv[i]));
}
// Parse runtime arguments. Stop at first unrecognized option.
bool zygote = false;
bool startSystemServer = false;
bool application = false;
String8 niceName;
String8 className;
++i; // Skip unused "parent dir" argument.
// 解析参数
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName.setTo(arg + 12);
} else if (strncmp(arg, "--", 2) != 0) {
className.setTo(arg);
break;
} else {
--i;
break;
}
}
Vector args;
if (!className.isEmpty()) {
// We're not in zygote mode, the only argument we need to pass
// to RuntimeInit is the application argument.
//
// The Remainder of args get passed to startup class main(). Make
// copies of them before we overwrite them with the process name.
args.add(application ? String8("application") : String8("tool"));
runtime.setClassNameAndArgs(className, argc - i, argv + i);
} else {
// We're in zygote mode.
maybeCreateDalvikCache();
if (startSystemServer) {
args.add(String8("start-system-server"));
}
char prop[PROP_VALUE_MAX];
if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
ABI_LIST_PROPERTY);
return 11;
}
String8 abiFlag("--abi-list=");
abiFlag.append(prop);
args.add(abiFlag);
// In zygote mode, pass all remaining arguments to the zygote
// main() method.
for (; i < argc; ++i) {
args.add(String8(argv[i]));
}
}
if (!niceName.isEmpty()) {
const char* procName = niceName.string();
pthread_setname_np(pthread_self(), procName);
runtime.setArgv0(procName);
}
if (zygote) {
// 调用start 启动zygoteInit
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
return 10;
}
}
1、该函数首先创建一个AppRuntime对象。
2、然后对init.rc配置文件中的启动参数argc、argv[]进行解析。while循环中我们可以看到,
3、最后的if/else分支就会执行runtime.start("com.android.internal.os.ZygoteInit", args, zygote) 来继续完成Zygote进行的启动。
其中AppRuntime 也是在该类中定义的:
class AppRuntime : public AndroidRuntime
{
public:
AppRuntime(char* argBlockStart, const size_t argBlockLength)
: AndroidRuntime(argBlockStart, argBlockLength)
, mClass(NULL)
{
}
void setClassNameAndArgs(const String8& className, int argc, char * const *argv) {
mClassName = className;
for (int i = 0; i < argc; ++i) {
mArgs.add(String8(argv[i]));
}
}
virtual void onVmCreated(JNIEnv* env)
{
if (mClassName.isEmpty()) {
return; // Zygote. Nothing to do here.
}
/*
* This is a little awkward because the JNI FindClass call uses the
* class loader associated with the native method we're executing in.
* If called in onStarted (from RuntimeInit.finishInit because we're
* launching "am", for example), FindClass would see that we're calling
* from a boot class' native method, and so wouldn't look for the class
* we're trying to look up in CLASSPATH. Unfortunately it needs to,
* because the "am" classes are not boot classes.
*
* The easiest fix is to call FindClass here, early on before we start
* executing boot class Java code and thereby deny ourselves access to
* non-boot classes.
*/
char* slashClassName = toSlashClassName(mClassName.string());
mClass = env->FindClass(slashClassName);
if (mClass == NULL) {
ALOGE("ERROR: could not find class '%s'\n", mClassName.string());
}
free(slashClassName);
mClass = reinterpret_cast(env->NewGlobalRef(mClass));
}
virtual void onStarted()
{
sp proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();
AndroidRuntime* ar = AndroidRuntime::getRuntime();
ar->callMain(mClassName, mClass, mArgs);
IPCThreadState::self()->stopProcess();
}
virtual void onZygoteInit()
{
sp proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();
}
virtual void onExit(int code)
{
if (mClassName.isEmpty()) {
// if zygote
IPCThreadState::self()->stopProcess();
}
AndroidRuntime::onExit(code);
}
String8 mClassName;
Vector mArgs;
jclass mClass;
}
可以看到,AppRuntime 是继承 AndroidRuntime
/*
* Start the Android runtime. This involves starting the virtual machine
* and calling the "static void main(String[] args)" method in the class
* named by "className".
*
* Passes the main function two arguments, the class name and the specified
* options string.
*/
void AndroidRuntime::start(const char* className, const Vector& options, bool zygote)
{
ALOGD(">>>>>> START %s uid %d <<<<<<\n",
className != NULL ? className : "(unknown)", getuid());
static const String8 startSystemServer("start-system-server");
/*
* 'startSystemServer == true' means runtime is obsolete and not run from
* init.rc anymore, so we print out the boot start event here.
*/
for (size_t i = 0; i < options.size(); ++i) {
if (options[i] == startSystemServer) {
/* track our progress through the boot sequence */
const int LOG_BOOT_PROGRESS_START = 3000;
LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
}
}
const char* rootDir = getenv("ANDROID_ROOT");
if (rootDir == NULL) {
rootDir = "/system";
if (!hasDir("/system")) {
LOG_FATAL("No root directory specified, and /android does not exist.");
return;
}
setenv("ANDROID_ROOT", rootDir, 1);
}
//const char* kernelHack = getenv("LD_ASSUME_KERNEL");
//ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
// 1.启动JVM
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
onVmCreated(env);
/*
* Register android functions.
*/
// 2.为JVM 注册 JNI 方法
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
/*
* We want to call main() with a String array with arguments in it.
* At present we have two arguments, the class name and an option string.
* Create an array to hold them.
*/
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
stringClass = env->FindClass("java/lang/String");
assert(stringClass != NULL);
strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
assert(strArray != NULL);
// 3.传递进来的第一个参数 "com.android.internal.os.ZygoteInit"
classNameStr = env->NewStringUTF(className);
assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray, 0, classNameStr);
for (size_t i = 0; i < options.size(); ++i) {
jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
assert(optionsStr != NULL);
env->SetObjectArrayElement(strArray, i + 1, optionsStr);
}
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
*/
// 4.将 classNameStr 中的 . 替换为 /
char* slashClassName = toSlashClassName(className);
// 5.找到zygoteInit类
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
// 6.找到 zygoteInit 的 main 方法
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
// 7.通过jni 调用main方法。
env->CallStaticVoidMethod(startClass, startMeth, strArray);
#if 0
if (env->ExceptionCheck())
threadExitUncaughtException(env);
#endif
}
}
free(slashClassName);
ALOGD("Shutting down VM\n");
if (mJavaVM->DetachCurrentThread() != JNI_OK)
ALOGW("Warning: unable to detach main thread\n");
if (mJavaVM->DestroyJavaVM() != 0)
ALOGW("Warning: VM did not shut down cleanly\n");
}
上述代码主要是:
frameworks\base\core\java\com\android\internal\os\ZygoteInit.java
public static void main(String argv[]) {
try {
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygoteInit");
RuntimeInit.enableDdms();
// Start profiling the zygote initialization.
SamplingProfilerIntegration.start();
boolean startSystemServer = false;
String socketName = "zygote";
String abiList = null;
// 1、解析从init.rc 文件中传递过来的参数是否启动system-server,并设置器对应
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
socketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
if (abiList == null) {
throw new RuntimeException("No ABI list supplied.");
}
// 2.注册zygoteSocket,这个socket 的名称是在 zygote
registerZygoteSocket(socketName);
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygotePreload");
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
// 3.预加载类和资源
preload();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
// Finish profiling the zygote initialization.
SamplingProfilerIntegration.writeZygoteSnapshot();
// Do an initial gc to clean up after startup
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PostZygoteInitGC");
gcAndFinalize();
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
// Disable tracing so that forked processes do not inherit stale tracing tags from
// Zygote.
Trace.setTracingEnabled(false);
// Zygote process unmounts root storage spaces.
Zygote.nativeUnmountStorageOnInit();
// 4.启动systemServer
if (startSystemServer) {
startSystemServer(abiList, socketName);
}
Log.i(TAG, "Accepting command socket connections");
// 5.启动Loop 来处理AMS 来创建应用进行处理。
runSelectLoop(abiList);
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
zygoteinit.java 主要做了如下几件事情
1.创建 serverSocket 来看一下具体实现:
/**
* Registers a server socket for zygote command connections
*
* @throws RuntimeException when open fails
*/
private static void registerZygoteSocket(String socketName) {
if (sServerSocket == null) {
int fileDesc;
// 1.拼接socket 名称
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
try {
// 2.获取socket 环境变量的值
String env = System.getenv(fullSocketName);
// 3.得到sockt 环境变量的值,并将其转为文件描述符参数
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
throw new RuntimeException(fullSocketName + " unset or invalid", ex);
}
try {
// 4.创建文件描述符
FileDescriptor fd = new FileDescriptor();
fd.setInt$(fileDesc);
// 5.用这个文件描述法作为参数 创建LocalServerSocket
sServerSocket = new LocalServerSocket(fd);
} catch (IOException ex) {
throw new RuntimeException(
"Error binding to local socket '" + fileDesc + "'", ex);
}
}
}
使用JNI 获取的环境变量的文件描述符参数来创建文件描述符,并将此描述符用于创建本地的serverSocket。在Zygote进程将SystemServer启动之后,就会在这个服务端等待AMS 来请求zygote进程来创建一个新的应用进程。
2. 加载类和资源,有PreloadClasses,PreloadResources,PreloadOpenGL,这几项的加载在android 启动中占据了大约4秒钟的事件,这里其实可以进行加载优化,将这些穿行的加载做成线程池,放在线程池中加载,启动的事件会大大缩短。
3.启动 systemService:
/**
* Prepare the arguments and fork for the system server process.
*/
private static boolean startSystemServer(String abiList, String socketName)
throws MethodAndArgsCaller, RuntimeException {
long capabilities = posixCapabilitiesAsBits(
OsConstants.CAP_BLOCK_SUSPEND,
OsConstants.CAP_KILL,
OsConstants.CAP_NET_ADMIN,
OsConstants.CAP_NET_BIND_SERVICE,
OsConstants.CAP_NET_BROADCAST,
OsConstants.CAP_NET_RAW,
OsConstants.CAP_SYS_MODULE,
OsConstants.CAP_SYS_NICE,
OsConstants.CAP_SYS_RESOURCE,
OsConstants.CAP_SYS_TIME,
OsConstants.CAP_SYS_TTY_CONFIG
);
/* Hardcoded command line to start the system server */
// 1.创建数组保存systemServer 启动的参数
String args[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007,3009,3010",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try {
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
/* Request to fork the system server process */
// 2.从当前(zygote)进程中fork 出一个子进程(就是当前的systemServer进程)
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
// 3.处理这个刚刚出生的systemserver子进程的后续事情
handleSystemServerProcess(parsedArgs);
}
return true;
}
这里启动systemserver 主要是 像细胞分裂一样,从 zygote进程 fork出一个systemserver 进程来,这样就启动了systemserver,这样子这个server就有了父进程(zygote)的所有的资源。
4.runSelectLoop,等待AMS 来请求建立连接,或者请求创建应用程序进程
/**
* Runs the zygote process's select loop. Accepts new connections as
* they happen, and reads commands from connections one spawn-request's
* worth at a time.
*
* @throws MethodAndArgsCaller in a child process when a main() should
* be executed.
*/
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
ArrayList fds = new ArrayList();
ArrayList peers = new ArrayList();
// 1.拿到服务端的socket文件描述符
fds.add(sServerSocket.getFileDescriptor());
peers.add(null);
// 2.就在这里傻傻的等着来AMS的连接请求
while (true) {
StructPollfd[] pollFds = new StructPollfd[fds.size()];
for (int i = 0; i < pollFds.length; ++i) {
pollFds[i] = new StructPollfd();
pollFds[i].fd = fds.get(i);
pollFds[i].events = (short) POLLIN;
}
try {
Os.poll(pollFds, -1);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
// 3
for (int i = pollFds.length - 1; i >= 0; --i) {
if ((pollFds[i].revents & POLLIN) == 0) {
continue;
}
if (i == 0) {
// 4
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
boolean done = peers.get(i).runOnce();
if (done) {
// 5
peers.remove(i);
fds.remove(i);
}
}
}
}
}
在注释2.处无限等待AMS 的连接请求或者创建应用程序进程
在注释3:将fds 中的数据转移到pollFds中
在注释4:如果i==0 说明服务器和AMS 连接上了。通过acceptCommandPeer 来得到这个ZygoteConnection 并添加到socket 连接列表peers 中。以便可以接收到AMS 发过来的请求。 如果 i != 0 说明是AMS 向 zygote 发送了请求创建一个应用进程,如果创建成功,就把这个连接从socket 连接表和 文件描述符中移除。
zygote 启动过程至此就告一段落了。
zygote 启动做了如下几件事情
SystemServer 用来创建其他service ,并管理创建的service 。例如:AMS、WMS、PMS等都是由他来创建的,下面来看下如何启动这个 父进程。
startSystemServer方法最终有一句 handleSystemServerProcess() 方法
/**
* Finish remaining work for the newly forked system server process.
*/
private static void handleSystemServerProcess(
ZygoteConnection.Arguments parsedArgs)
throws ZygoteInit.MethodAndArgsCaller {
// 子类不需要zygote进程的 serverSocket
closeServerSocket();
...
if (parsedArgs.invokeWith != null) {
...
} else {
ClassLoader cl = null;
if (systemServerClasspath != null) {
// 1.创建 PathClassLoader
cl = createSystemServerClassLoader(systemServerClasspath,
parsedArgs.targetSdkVersion);
Thread.currentThread().setContextClassLoader(cl);
}
// 2. 调用zygote的zygoteInit方法
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
}
}
最终调用 “RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);” 方法继续执行。
/**
* 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 argv arg strings
*/
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
redirectLogStreams();
commonInit();
// 1.启动binder 线程池
nativeZygoteInit();
// 2.进入systemServer 的main方法
applicationInit(targetSdkVersion, argv, classLoader);
}
在注释1 调用的nativeZygoteInit()是个JNI函数,启动了大名鼎鼎的Binder线程池
在注释2 进入了系统的SystemServer 的main方法。
分别学习一下
注释1:启动binder线程池,在AndroidRuntime.cpp文件中可以看到
\frameworks\base\core\jni\AndroidRuntime.cpp
/*
* JNI registration.
*/
static const JNINativeMethod gMethods[] = {
{ "nativeFinishInit", "()V",
(void*) com_android_internal_os_RuntimeInit_nativeFinishInit },
{ "nativeZygoteInit", "()V",
(void*) com_android_internal_os_RuntimeInit_nativeZygoteInit },
{ "nativeSetExitWithoutCleanup", "(Z)V",
(void*) com_android_internal_os_RuntimeInit_nativeSetExitWithoutCleanup },
};
static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->onZygoteInit();
}
/**
* This gets called after the JavaVM has initialized after a Zygote
* fork. Override it to initialize threads, etc. Upon return, the
* correct static main will be invoked.
*/
virtual void onZygoteInit() { }
点进去之后实现为空,注释说 Override it to initialize threads ,那就找下子类的实现。不过实际调用的onZygoteInit()应该是AndroidRuntime的子类AppRuntime的:
frameworks/base/cmds/app_process/app_main.cpp
virtual void onZygoteInit()
{
sp proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();
}
里面构造了进程的ProcessState全局对象,而且启动了线程池。
ProcessState对象是典型的单例模式,它的self()函数如下:
sp ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != NULL) {
return gProcess;
}
gProcess = new ProcessState;
return gProcess;
}
ProcessState对于Binder通信机制而言非常重要,现在system server进程的PrecessState算是初始化完毕了。启动了binder线程池。
注释2 :用于进入systemServer 的main方法。
private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
...
invokeStaticMain(args.startClass, args.startArgs, classLoader);
}
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
Class> cl;
try {
// 1.通过反射得到 systemServer 类
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
Method m;
try {
// 2.找到systemServer 的main方法
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);
}
// 3.找到main的方法传入MethodAndArgsCaller,抛出异常。
/*
* 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.
*/
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}
注释1 处通过反射拿到SystemServer类,并在注释2处找打这个类的main,在注释3 处抛出异常。这个MethodAndArgsCaller异常。
捕获这个异常的地方在ZygoteInit的main方法中,这个main方法会调用systemServer 的main方法。这个异常的定义是在zygoteInit.java 中定义的
/**
* Helper exception class which holds a method and arguments and
* can call them. This is used as part of a trampoline to get rid of
* the initial process setup stack frames.
*/
public static class MethodAndArgsCaller extends Exception
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 {
// 1.代用main 方法
mMethod.invoke(null, new Object[] { mArgs });
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
...
}
}
}
在注释1 mMethed 方法就是 SystemServer 的 main 方法,启动这个main 方法就进入 systemServer 的 main 中。
frameworks\base\services\java\com\android\server\SystemServer.java
public static void main(String[] args) {
new SystemServer().run();
}
private void run() {
try {
...
Looper.prepareMainLooper();
// Initialize native services.
// 1.加载这个so 文件,初始化native service
System.loadLibrary("android_servers");
// Check whether we failed to shut down last time we tried.
// This call may not return.
performPendingShutdown();
// Initialize the system context.
// 2.初始化系统的Context
createSystemContext();
// Create the system service manager.
// 3. 创建一个SystemServiceManager
mSystemServiceManager = new SystemServiceManager(mSystemContext);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
// Start services.
try {
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");
// 4.启动引导服务
startBootstrapServices();
// 5.启动核心服务
startCoreServices();
// 6. 启动其他服务
startOtherServices();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
...
// Loop forever.
Looper.loop();
...
}
这些服务启动逻辑都比较相似。以PowerManagerService 为例:
public T startService(Class serviceClass) {
try {
final String name = serviceClass.getName();
...
// 1.Register it.
mServices.add(service);
// 2.Start it.
try {
service.onStart();
} catch (RuntimeException ex) {
throw new RuntimeException("Failed to start service " + name
+ ": onStart threw an exception", ex);
}
return service;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
}
启动service 首先在 注释1 处将这个service 加入到systemService ( private final ArrayList
除了这样启动服务以外,还可以直接调用的main 方法来启动,以PackageManagerService为例:
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
public static PackageManagerService main(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
PackageManagerService m = new PackageManagerService(context, installer,
factoryTest, onlyCore);
ServiceManager.addService("package", m);
return m;
}
直接创建完对应的服务,然后注册到ServiceManager中,通过这个ServiceManager 来管理创建的服务。用于系统的binder通信,客户端使用的时候通过注册服务,进行信息查询,根据信息与services所在的server进程监理通路,才Client可以使用。
在加载完成SystemServer之后,对系统的各种server进行管理。启动Launcher 的入口为AMS 的 systemReady 方法,它在SystemServer 的 startOtherServices 方法中被调用。如下所示:
frameworks\base\services\java\com\android\server\SystemServer.java
/**
* Starts a miscellaneous grab bag of stuff that has yet to be refactored
* and organized.
*/
private void startOtherServices() {
...
mActivityManagerService.systemReady(new Runnable() {
@Override
public void run() {
Slog.i(TAG, "Making services ready");
mSystemServiceManager.startBootPhase(
SystemService.PHASE_ACTIVITY_MANAGER_READY);
...
}
});
}
然后再AMS 中查看SystemReady 方法如下:
public void systemReady(final Runnable goingCallback) {
...
// Start up initial activity.
mBooting = true;
startHomeActivityLocked(mCurrentUserId, "systemReady");
...
}
从这里看到系统的注释 stat up initial activity .这样一个默认的activity就是我们的homeActivity。launcher 桌面
boolean startHomeActivityLocked(int userId, String reason) {
// 1
if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
&& mTopAction == null) {
// We are running in factory test mode, but unable to find
// the factory test app, so just sit around displaying the
// error message and don't try to start anything.
return false;
}
// 2 获取homeIntent
Intent intent = getHomeIntent();
ActivityInfo aInfo =
resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
if (aInfo != null) {
intent.setComponent(new ComponentName(
aInfo.applicationInfo.packageName, aInfo.name));
// Don't do this if the home app is currently being
// instrumented.
aInfo = new ActivityInfo(aInfo);
aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
ProcessRecord app = getProcessRecordLocked(aInfo.processName,
aInfo.applicationInfo.uid, true);
// 3.设置对intent进行判断
if (app == null || app.instrumentationClass == null) {
// 4. 设置intent 的一些标志位,并启动launcher
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
mStackSupervisor.startHomeActivity(intent, aInfo, reason);
}
}
return true;
}
注释1处的mFactoryTest代表系统的运行模式,系统的运行模式分为三种,分别是非工厂模式、低级工厂模式和高级工厂模式,mTopAction则用来描述第一个被启动Activity组件的Action,它的值为Intent.ACTION_MAIN。因此注释1的代码意思就是mFactoryTest为FactoryTest.FACTORY_TEST_LOW_LEVEL(低级工厂模式)并且mTopAction=null时,直接返回false,然后是调用getHomeIntent()方法。
注释2的 代码处获取Intent ,代码如下
Intent getHomeIntent() {
Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
intent.setComponent(mTopComponent);
if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
intent.addCategory(Intent.CATEGORY_HOME);
}
return intent;
}
创建Intent ,并将mTopAction(String mTopAction = Intent.ACTION_MAIN;) 和 mTopData 传入。设置 setComponent 的值 为mTopComponent = new ComponentName(app.packageName, ai.name); 为包名(Name of the package that this item is in) 和 app 名称 (Public name of this item. From the "android:name" attribute.),如果系统运行非低级工程模式,则 addCategory 为 Intent.CATEGORY_HOME 最后返回改intent。
我们再回到ActivityManagerService的startHomeActivityLocked函数,假设系统的运行模式不是低级工厂模式,在注释3处判断符合Action为Intent.ACTION_MAIN,Category为Intent.CATEGORY_HOME的应用程序是否已经启动,如果没启动则调用注释4的方法启动该应用程序。这个应用程序就是launcher。因为launcher 的AndroidManifest文件中的intent-filter标签匹配了Action 为Intent.ACTION_MAIN,Category为Intent.CATEGORY_HOME。
Launcher 的 AndroidManifest文件如下所示:
packages\apps\Launcher3\AndroidManifest.xml
经历了一系列的方法后就进入了 startHomeActivity 方法。
void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason) {
// 1. 将Home任务排到栈顶
moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
// 2.启动Activity
startActivityLocked(null /* caller */, intent, null /* resolvedType */, aInfo,
null /* voiceSession */, null /* voiceInteractor */, null /* resultTo */,
null /* resultWho */, 0 /* requestCode */, 0 /* callingPid */, 0 /* callingUid */,
null /* callingPackage */, 0 /* realCallingPid */, 0 /* realCallingUid */,
0 /* startFlags */, null /* options */, false /* ignoreTargetSecurity */,
false /* componentSpecified */,
null /* outActivity */, null /* container */, null /* inTask */);
if (inResumeTopActivity) {
// If we are in resume section already, home activity will be initialized, but not
// resumed (to avoid recursive resume) and will stay that way until something pokes it
// again. We need to schedule another resume.
// 3.刚好如果已在Home了,那就直接前置
scheduleResumeTopActivities();
}
}
Android系统启动后Launcher启动(概述)
Android Framework学习(四)之Launcher启动流程解析
Android系统启动流程(四)Launcher启动过程与系统启动流程