安卓启动流程
看了很多相关博客,今天也来自己梳理以下~~~
Android从Linux系统启动
init进程启动
Native服务启动
System Server, Android 服务启动
Home启动
总体启动框架:
2012111315182764.jpgInit进程启动
首先uboot引导Linux内核启动,然后在用户空间中启动init进程,再启动其他系统进程。在系统启动完成完成后,init将变为守护进程监视系统其他进程。Android是基于Linux的操作系统,所以init也是Android系统中用户空间的第一个进程,它的进程号是1。
Init的主要职责是:
作为守护进程
解析核执行init.rc文件
生成设备节点
属性服务
源码在/system/core/init/init.c
int main(int argc, char **argv) { //启动uevent守护进程 if (!strcmp(basename(argv[0]), "ueventd")) return ueventd_main(argc, argv); //启动看门狗守护进程 if (!strcmp(basename(argv[0]), "watchdogd")) return watchdogd_main(argc, argv); umask(0); //创建并挂在启动所需的文件目录 mkdir("/dev", 0755); mkdir("/proc", 0755); mkdir("/sys", 0755); mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"); mkdir("/dev/pts", 0755); mkdir("/dev/socket", 0755); mount("devpts", "/dev/pts", "devpts", 0, NULL); mount("proc", "/proc", "proc", 0, NULL); mount("sysfs", "/sys", "sysfs", 0, NULL); close(open("/dev/.booting", O_WRONLY | O_CREAT, 0000)); //重定向标准输入/输出/错误输出到/dev/_null_ open_devnull_stdio(); klog_init();//log初始化 property_init();//属性服务初始化 //从/proc/cpuinfo中读取Hardware名,在后面的mix_hwrng_into_linux_rng_action函 数中会将hardware的值设置给属性ro.hardware get_hardware_name(hardware, &revision); //导入并设置内核变量 process_kernel_cmdline(); ...... INFO("property init\n"); if (!is_charger) property_load_boot_defaults(); INFO("reading config file\n"); init_parse_config_file("/init.rc");//解析init.rc配置文件 /* * 解析完init.rc后会得到一系列的action等,下面的代码将执行处于early-init阶段的 action。 * init将action按照执行时间段的不同分为early-init、init、early-boot、boot。 * 进行这样的划分是由于有些动作之间具有依赖关系,某些动作只有在其他动作完成后才能执行,所以就有了先后的区别。 * 具体哪些动作属于哪个阶段是在init.rc中的配置决定的 */ action_for_each_trigger("early-init", action_add_queue_tail); ...... for(;;) {//init进入无限循环 ...... execute_one_command(); restart_processes();//重启已经死去的进程 ...... nr = poll(ufds, fd_count, timeout); //等待事件发生 if (nr <= 0) continue; for (i = 0; i < fd_count; i++) { if (ufds[i].revents == POLLIN) { if (ufds[i].fd == get_property_set_fd())//处理属性服务事件 handle_property_set_fd(); else if (ufds[i].fd == get_keychord_fd())//处理keychord事件 handle_keychord(); else if (ufds[i].fd == get_signal_fd()) handle_signal();//处理SIGCHLD信号事件 } } } return 0;}
看看init.rc脚本
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server class main 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
ps:(1)这里描述了孵化器zygote的启动(init是zygote的父进程,而系统服务进程system_server和其他所有的com.xxx结尾的应用程序都是从zygote fork 而来)。
(2)前面的关键字service告诉init进程创建一个名为"zygote"的进程,这个zygote进程要执行的程序是/system/bin/app_process,后面是要传给app_process的参数。最后的一系列onrestart关键字表示这个zygote进程重启时需要执行的命令。
了解了这个信息之后,我们就知道Zygote进程要执行的程序便是system/bin/app_process了,它的源代码位于frameworks/base/cmds/app_process/app_main.cpp文件中,入口函数是main。
int main(int argc, char* const argv[]){ ...... // These are global variables in ProcessState.cpp mArgC = argc; mArgV = argv; mArgLen = 0; for (int i=0; i
main函数的主要作用就是创建一个AppRuntime变量,然后调用它的start函数。它的定义也在同一文件app_main.cpp下面class AppRuntime : public AndroidRuntime
(AndroidRuntime的源码在/frameworks/base/core/jni下,它是抽象基类);
在AndroidRuntime.h中定义了4种启动模式
enum StartMode { Zygote,//启动Zygote SystemServer,//启动系统服务 Application,//启动应用程序 Tool,// };
再看看具体的start函数做了什么
/* * 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. *///上面的解释是开始android运行时环境。将开始虚拟机,然后用类似反射的机制去调用类名为参数className的main()方法!void AndroidRuntime::start(const char* className, const char* options){ if (strcmp(options, "start-system-server") == 0) { /* 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); } /* start the virtual machine */ JniInvocation jni_invocation; jni_invocation.Init(NULL); JNIEnv* env; if (startVm(&mJavaVM, &env) != 0) {//开启虚拟机 return; } onVmCreated(env); /* * Register android functions. 注册本地native函数 */ if (startReg(env) < 0) { ALOGE("Unable to register all android natives\n"); return; } jclass stringClass; jobjectArray strArray; jstring classNameStr; jstring optionsStr; stringClass = env->FindClass("java/lang/String"); assert(stringClass != NULL); strArray = env->NewObjectArray(2, stringClass, NULL); assert(strArray != NULL); classNameStr = env->NewStringUTF(className); assert(classNameStr != NULL); env->SetObjectArrayElement(strArray, 0, classNameStr); optionsStr = env->NewStringUTF(options); env->SetObjectArrayElement(strArray, 1, optionsStr); /* * Start VM. This thread becomes the main thread of the VM, and will * not return until the VM exits. */ //激活虚拟机,当前线程变成虚拟机下的主线程。 char* slashClassName = toSlashClassName(className); jclass startClass = env->FindClass(slashClassName); if (startClass == NULL) { ALOGE("JavaVM unable to locate class '%s'\n", slashClassName); } else { 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 { env->CallStaticVoidMethod(startClass, startMeth, strArray); } } }
通过源代码的分析知道,其实上面主要是给一个应用程序分配一个虚拟机环境(虚拟机拷贝),然后通过JNI的方式去调java里某个className类的main()方法。
还记得runtime.start("com.android.internal.os.ZygoteInit", startSystemServer ? "start-system-server" : "");
实际执行com.android.internal.os.ZygoteInit类的main()(源码地址frameworks/base/core/java/com/android/internal/os/ZygoteInit.java):
public static void main(String argv[]) { try { // Start profiling the zygote initialization. SamplingProfilerIntegration.start(); registerZygoteSocket(); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis()); preload(); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, SystemClock.uptimeMillis()); // Finish profiling the zygote initialization. SamplingProfilerIntegration.writeZygoteSnapshot(); // Do an initial gc to clean up after startup gc(); ...... // If requested, start system server directly from Zygote ....... if (argv[1].equals("start-system-server")) { startSystemServer();//启动system_server进程 } else if (!argv[1].equals("")) { throw new RuntimeException(argv[0] + USAGE_STRING); } ...... runSelectLoop(); closeServerSocket(); } catch (MethodAndArgsCaller caller) { caller.run(); } catch (RuntimeException ex) { ...... } }
它主要作了三件事情:
1、调用registerZygoteSocket函数创建了一个socket接口,用来和ActivityManagerService通讯;
2、调用startSystemServer函数来启动SystemServer组件;
3、调用runSelectLoopMode函数进入一个无限循环在前面创建的socket接口上等待ActivityManagerService请求创建新的应用程序进程。
这里Zygote进程初始化完毕,开始大循环了~~~
仔细分析下第二步startSystemServer启动系统服务组件
/** * Prepare the arguments and fork for the system server process. */ private static boolean startSystemServer() throws MethodAndArgsCaller, RuntimeException { /* 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,1032,3001,3002,3003,3006,3007", "--capabilities=" + capabilities + "," + capabilities, "--runtime-init", "--nice-name=system_server", "com.android.server.SystemServer", }; ZygoteConnection.Arguments parsedArgs = null; int pid; try { parsedArgs = new ZygoteConnection.Arguments(args); ...... /* Request to fork the system server process */ pid = Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities); } catch (IllegalArgumentException ex) { ...... } /* For child process */ if (pid == 0) {//pid==0说明是子进程,父进程为Zygote handleSystemServerProcess(parsedArgs); } return true; }
在startSystemServer中先设置了Zygote.forkSystemServer所需的参数,然后通过forkSystemServer方法fork出SystemServer进程,最后通过handleSystemServerProcess处理新进程中的琐事。
首先看一下参数:
1、setuid=1000,这里1000代表SYSTEM_UID,即系统进程,关于进程ID的说明可以参见:/frameworks/base/core/java/android/os/Process.java。
2、nice-name=system_server表示制定进程的名字为“system_server”
3、com.android.server.SystemServer表示SystemServer类的位置。
接下来看一下forkSystemServer的实现:
libcore/dalvik/src/main/java/dalvik/system/Zygote.java
/** * Special method to start the system server process. In addition to the * common actions performed in forkAndSpecialize, the pid of the child * process is recorded such that the death of the child process will cause * zygote to exit. * 注意由zygote fork 出的system_service进程如果死了,则zygote进程也退出 */ public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) { preFork(); int pid = nativeForkSystemServer( uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities); postFork(); return pid; } native public static int nativeForkSystemServer(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);
forkSystemServer最后调nativeForkSystemServer,而它是通过JNI实现,源码:/dalvik/vm/native/dalvik_system_Zygote.cpp:
static void Dalvik_dalvik_system_Zygote_forkSystemServer( const u4* args, JValue* pResult){ pid_t pid; pid = forkAndSpecializeCommon(args, true); /* The zygote process checks whether the child process has died or not. */ if (pid > 0) {//pid大于0,说明是在父进程中,Zygote进程往下执行 int status; gDvm.systemServerPid = pid; /* There is a slight window that the system server process has crashed * but it went unnoticed because we haven't published its pid yet. So * we recheck here just to make sure that all is well. */ if (waitpid(pid, &status, WNOHANG) == pid) { ALOGE("System server process %d has died. Restarting Zygote!", pid); kill(getpid(), SIGKILL);//一旦上面的等待返回,说明进程pid(system_server)已终止,此时Zygote杀死自己 } } RETURN_INT(pid);}//native函数注册const DalvikNativeMethod dvm_dalvik_system_Zygote[] = { { "nativeFork", "()I", Dalvik_dalvik_system_Zygote_fork }, { "nativeForkAndSpecialize", "(II[II[[IILjava/lang/String;Ljava/lang/String;)I", Dalvik_dalvik_system_Zygote_forkAndSpecialize }, { "nativeForkSystemServer", "(II[II[[IJJ)I", Dalvik_dalvik_system_Zygote_forkSystemServer }, { NULL, NULL, NULL },};
SystemServer创建之后交给handleSystemServerProcess处理!
回到 frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
/** * Finish remaining work for the newly forked system server process. * 完成新建的system server进程的剩余工作 */ private static void handleSystemServerProcess( ZygoteConnection.Arguments parsedArgs) throws ZygoteInit.MethodAndArgsCaller { closeServerSocket();//关闭从Zygote复制过来的socket // set umask to 0077 so new files and directories will default to owner-only permissions. Libcore.os.umask(S_IRWXG | S_IRWXO);//设置文件的默认权限,去除文件所有者之外的权限 if (parsedArgs.niceName != null) { Process.setArgV0(parsedArgs.niceName); } if (parsedArgs.invokeWith != null) { WrapperInit.execApplication(parsedArgs.invokeWith, parsedArgs.niceName, parsedArgs.targetSdkVersion, null, parsedArgs.remainingArgs); } else { /* * Pass the remaining arguments to SystemServer.传递剩下的参数给SystemServer */ RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs); } /* should never reach here */ }
最后将参数往下传给RuntimeInit.zygoteInit(,)
源码:frameworks/base/core/java/com/android/internal/os/RuntimeInit.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. */ public static final void zygoteInit(int targetSdkVersion, String[] argv) throws ZygoteInit.MethodAndArgsCaller { if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote"); redirectLogStreams();//将System.out 和 System.err 输出重定向到Android 的Log系统 /* * 初始化了一些系统属性,其中最重要的一点就是设置了一个未捕捉异常的handler, * 当代码有任何未知异常,就会执行它, * 调试过Android代码的同学经常看到的"*** FATAL EXCEPTION IN SYSTEM PROCESS" 打印就出自这里 */ commonInit(); /* * 最终会调用app_main的onZygoteInit函数 * 这里的作用是在新进程中引入Binder,也就说通过nativeZygoteInit以后,新的进程就可以使用Binder进程通信了 */ nativeZygoteInit(); applicationInit(targetSdkVersion, argv);//应用初始化 } private static void applicationInit(int targetSdkVersion, String[] argv) throws ZygoteInit.MethodAndArgsCaller { // 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); // We want to be fairly aggressive about heap utilization, to avoid // holding on to a lot of memory that isn't needed. VMRuntime.getRuntime().setTargetHeapUtilization(0.75f); VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion); final Arguments args; try { args = new Arguments(argv); } catch (IllegalArgumentException ex) { Slog.e(TAG, ex.getMessage()); // let the process exit return; } // Remaining arguments are passed to the start class's static main invokeStaticMain(args.startClass, args.startArgs); }
这里invokeStaticMain的args.startClass的值为com.android.server.SystemServer。接下来SystemServer类的main函数将会被调用,我太机智了~。
源码:frameworks/base/services/java/com/android/server/SystemServer.java
public static void main(String[] args) { /* * 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. */ SystemProperties.set("persist.sys.dalvik.vm.lib", VMRuntime.getRuntime().vmLibrary()); if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {//调整时间 Slog.w(TAG, "System clock is before 1970; setting to 1970."); SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME); } ...... // Mmmmmm... more memory! dalvik.system.VMRuntime.getRuntime().clearGrowthLimit(); // The system server has to run all of the time, so it needs to be // as efficient as possible with its memory usage. VMRuntime.getRuntime().setTargetHeapUtilization(0.8f); Environment.setUserRequired(true); System.loadLibrary("android_servers"); Slog.i(TAG, "Entered the Android system server!"); // Initialize native services. nativeInit();//初始化本地所以服务 > SensorService // This used to be its own separate thread, but now it is // just the loop we run on the main thread. ServerThread thr = new ServerThread(); thr.initAndLoop(); }
在main中会加载libandroid_servers.so库,然后调用nativeInit初始化native层的Service。
ServerThread初始化一堆android服务。
小结一下:
- Linux的init在启动若干守护进程之后,就启动了Android的runtime和zygote,Zygote进程负责后续Android应用程序框架层的其它进程的创建和启动工作。
- Zygote进程会首先创建一个SystemServer进程,SystemServer进程负责启动系统的关键服务,如包管理服务PackageManagerService和应用程序组件管理服务ActivityManagerService。
- 当我们需要启动一个Android应用程序时,ActivityManagerService会通过Socket进程间通信机制,通知Zygote进程为这个应用程序创建一个新的进程。
更多相关文章
- Android下的binder机制和IPC原理
- Android(安卓)技能图谱学习路线
- Task和Activity相关
- Android(安卓)开发艺术探索笔记(18)
- Android(安卓)Service 详解(上)
- Android(安卓)代理自动配置PAC研究
- Android的Activity的启动流程分析
- AndroidO SystemUI-QuickSettings
- 如何让android的service一直在后台运行