Android系统架构(二)—Android系统启动过程

Android开机启动流程 在Android,Binder也是Android里面的进程通信的主要方式。Android开机时很久的两个主要原因一个是启动80多种服务(如ActivityManagerService),另一个原因是去获取手机所有app的信息,并重新安装一遍,这个过程是很耗时。总的来说,首先有一个线程在不断的监听屏幕,一旦有触摸事件,就将事件捕获并通过WMS的InputChannel知道是哪个Windows的,然后分发指定的Windows处理;常见的操作系统有Windows,Android,Linux,MacOS。 阅读详情

前言

作为一个Android应用层的开发者,我们平常开发Android应用程序可能对Android系统了解的并不深入。虽然Android系统底层细节并不需要应用层开发者十分了解,但能够知道Android系统的基本架构也是必要。

这里就分析一下Android系统的启动流程来了解一下Android系统的启动过程。

在这里插入图片描述

上图是Android系统启动过程的一个概览。从图中可以看到,Android系统的启动过程涉及到了Android系统的各层架构。我们可以看紫色标出的部分,从Boot Loader开始,到swapper -> init -> Zygote -> System Server。这就是Android系统启动后要做的事情。

Android系统的启动流程

我们知道Android系统是基于Linux内核的系统。与之类似,Android系统的启动过程前几步是:

  1. 启动电源以及系统启动:当按下电源键开机后,引导芯片代码从ROM(只读内存)里开始执行,然后加载引导程序到RAM(运行内存)中。

  2. 引导程序BootLoader:引导程序BootLoader是在Android操作系统开始运行前的一个小程序,它的主要作用是把系统OS拉起来并运行,并为内核的启动做准备。(它不是Android操作系统的一部分。引导程序是OEM厂商或者运营商加锁和限制的地方)

  3. Linux内核启动:当内核启动时,设置缓存、被保护存储器、计划列表、加载驱动。在内核完成系统设置后,它首先在系统文件中寻找init.rc文件,并启动init进程。

  4. init进程启动:init进程是第一个进程。它的任务是初始化系统环境,负责挂载目录,运行init。rc脚本。

init进程的启动

接下来就从init进程的进程启动开始说起。

int main(int argc, char** argv) {
    //......
    bool is_first_stage = (getenv("INIT_SECOND_STAGE") == nullptr);
    if (is_first_stage) {
        boot_clock::time_point start_time = boot_clock::now();
        // Clear the umask. 清除umask,作用就是设置文件属性为0777,即可读、可写、可执行
        umask(0);
        // 获取在initramdisk中放在一起的基本文件系统设置,在/然后我们将让rc文件找出其余部分
        //创建挂载启动所需要的文件目录
        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));
        chmod("/proc/cmdline", 0440);
        gid_t groups[] = { AID_READPROC };
        setgroups(arraysize(groups), groups);
        mount("sysfs", "/sys", "sysfs", 0, NULL);
        mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL);
        mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11));
        if constexpr (WORLD_WRITABLE_KMSG) {
            mknod("/dev/kmsg_debug", S_IFCHR | 0622, makedev(1, 11));
        }
        mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8));
        mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9));
        //......
        //初始化Kennel的Log,以便可以从外界获取Kernel的日志
        InitKernelLogging(argv);
        //......
    }
    // 初始化第二阶段
    InitKernelLogging(argv);
	//......
	//对属性服务进行初始化
    property_init();
	//......
  
    //创建epoll句柄.epoll是Linux中I/O多路复用的机制
    epoll_fd = epoll_create1(EPOLL_CLOEXEC);
    if (epoll_fd == -1) {
        PLOG(FATAL) << "epoll_create1 failed";
    }
	//用于设置子进程信号处理函数,如果紫禁城异常退出,init进程会调用该函数中设定的信号处理函数来进行处理
    sigchld_handler_init();

	//导入默认的环境变量
    property_load_boot_defaults();
    export_oem_lock_status();
    //启动属性服务
    start_property_service();
    set_usb_controller();
    //在LoadBootScripts方法中解析了init.rc文件
	 LoadBootScripts(am, sm);
    //......

    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<std::chrono::milliseconds>(
                                           *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;
}

init的main函数主要做了以下的事情:

  • 创建和挂载启动所需的文件。

  • 对属性进行初始化,并且启动属性服务。通过property_init方法初始化属性,通过start_property_service方法启动属性服务。

  • 通过sigchld_handler_init方法设置子进程信号处理函数。主要作用是防止init的子进程成为僵尸进程。

  • 解析init.rc文件

解析init.rc文件

init.rc是一个重要的配置文件,在init进程启动时会解析init.rc文件。rc文件主要包含Action、Service、Command、Options和import五种类型。接下来分析一个rc文件,init.zygote64.rc。这个文件是启动Zygote的脚本。除此之外还有init.zygote32.rc、init.zygote32_64.rc、init.zygote64_32.rc,每个文件对应不同版本的Zygote进程启动。

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
//表示进程名为Zygote
//执行的程序是app_process64
    class main
    priority -20
    user root
    group root readproc reserved_disk
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    onrestart restart wificond
    writepid /dev/cpuset/foreground/tasks

通过解析上面的rc文件,开始启动Zygote进程。

Zygote进程的启动

从启动Zygote进程的rc文件中可以看到执行的程序名是app_process64,也就是在/system/bin/app_process64这个路径下。在这里执行了app_main.cpp文件。

int main(int argc, char* const argv[])
{
	////传到的参数argv为“-Xzygote /system/bin --zygote --start-system-server”,也就是启动Zygote进程的参数
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    argc--;
    argv++;
    bool known_command = false;
    int i;
    for (i = 0; i < argc; i++) {
        if (known_command == true) {
          runtime.addOption(strdup(argv[i]));
          known_command = false;
          continue;
        }

        for (int j = 0;
             j < static_cast<int>(sizeof(spaced_commands) / sizeof(spaced_commands[0]));
             ++j) {
          if (strcmp(argv[i], spaced_commands[j]) == 0) {
            known_command = true;
          }
        }
        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进程中运行
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;//对于64位系统nice_name为zygote64; 32位系统为zygote
        } else if (strcmp(arg, "--start-system-server") == 0) {
        	//同样的,判断当前是否运行在SystemServer进程中
            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<String8> args;
    if (!className.isEmpty()) {
        args.add(application ? String8("application") : String8("tool"));
        runtime.setClassNameAndArgs(className, argc - i, argv + i);
        }
    } else {
        // We're in zygote mode.
        // 进入zygote模式,创建 /data/dalvik-cache路径
        maybeCreateDalvikCache();

        if (startSystemServer) {
        	//是否启动SystemServer进程
            args.add(String8("start-system-server"));
        }

        char prop[PROP_VALUE_MAX];
        String8 abiFlag("--abi-list=");
        abiFlag.append(prop);
        args.add(abiFlag);
        for (; i < argc; ++i) {
            args.add(String8(argv[i]));
        }
    }
	//设置进程名
    if (!niceName.isEmpty()) {
        runtime.setArgv0(niceName.string(), true /* setProcName */);
    }

    if (zygote) {
    	// 启动AppRuntime
        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.");
    }
}

Zygote进程通过fork自身来创建子进程,这样Zygote进程以及它的子进程都会调用main方法。在main方法中可以看到其中区分了当前运行在哪个进程中。

如果运行在Zygote进程中就会调用AppRuntime的start方法,即runtime.start("com.android.internal.os.ZygoteInit", args, zygote);

/*
 * 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<String8>& options, bool zygote)
{
    static const String8 startSystemServer("start-system-server");
    //......
    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;
    // 启动Java虚拟机
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);

    /*
     * Register android functions.
     */
     // 为Java虚拟机注册JNI方法
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }
    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);
      // 找到className,其中className是参数calssName,为: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.
     */
   //将ClassName替换为com/android/internal/os/ZygoteInit
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    // 通过ClassName找到对应的类
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
    	//找到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 {
        	//通过JNI调用ZygoteInit的main方法
            env->CallStaticVoidMethod(startClass, startMeth, strArray);

#if 0
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
#endif
        }
    }
    //......
}

上面的start方法中主要完成了Java虚拟机的启动、注册了JNI方法、通过ClassName找到ZygoteInit并且了调用ZygoteInit的main方法。从这里就进入了Java框架层。

public static void main(String argv[]) {
        ZygoteServer zygoteServer = new ZygoteServer();
        //......
        final Runnable caller;
        try {
            String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";
         	//......
            boolean startSystemServer = false;
            String socketName = "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)) {
                    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.");
            }
            //创建一个Server端的Socket
            zygoteServer.registerServerSocket(socketName);
            // 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);
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                    SystemClock.uptimeMillis());
                bootTimingsTraceLog.traceEnd(); // ZygotePreload
            } else {
                Zygote.resetNicePriority();
            }
            //是否启动SysTemServer进程
            if (startSystemServer) {
                Runnable r = forkSystemServer(abiList, socketName, 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;
                }
            }
            //等待AMS请求,AMS请求就是创建应用程序的请求,AMS即ActivityManagerService
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            throw ex;
        } finally {
            zygoteServer.closeServerSocket();
        }

        // We're in the child process and have exited the select loop. Proceed to execute the
        // command.
        if (caller != null) {
            caller.run();
        }
    }

ZygoteInit的main方法主要做了4件事:

  • 创建一个Server端的Socket;

  • 预加载资源;

  • 启动SystemServer进程;

  • 等待AMS请求创建新的应用程序;

创建Socket

void registerServerSocket(String socketName) {
        if (mServerSocket == null) {
            int fileDesc;
            //拼接Socket名称,ANDROID_SOCKET_ + ""
            final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
            try {
            	//获取Socket的环境变量
                String env = System.getenv(fullSocketName);
                //将环境变量转换为文件描述符的参数
                fileDesc = Integer.parseInt(env);
            } catch (RuntimeException ex) {
                throw new RuntimeException(fullSocketName + " unset or invalid", ex);
            }

            try {
            	//创建文件描述符
                FileDescriptor fd = new FileDescriptor();
                fd.setInt$(fileDesc);
                //创建爱你服务端Socket
                mServerSocket = new LocalServerSocket(fd);
            } catch (IOException ex) {
                throw new RuntimeException(
                        "Error binding to local socket '" + fileDesc + "'", ex);
            }
        }
    }

预加载资源

static void preload() {
    //预加载位于/system/etc/preloaded-classes文件中的类
    preloadClasses();
​
    //预加载资源,包含drawable和color资源
    preloadResources();
​
    //预加载OpenGL
    preloadOpenGL();
​
    //通过System.loadLibrary()方法,
    //预加载"android","compiler_rt","jnigraphics"这3个共享库
    preloadSharedLibraries();
​
    //预加载 文本连接符资源
    preloadTextResources();
​
    //仅用于zygote进程,用于内存共享的进程
    WebViewFactory.prepareWebViewInZygote();
}

启动SystemServer

private static Runnable forkSystemServer(String abiList, String socketName, ZygoteServer zygoteServer) {
		//......
		//创建args数组,保存启动参数
        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,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 */
            //创建SystemServer进程
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
			if (pid == 0) {
	            if (hasSecondZygote(abiList)) {
	                waitForSecondaryZygote(socketName);
	            }
				//关闭socket
	            zygoteServer.closeServerSocket();
	            //处理启动SystemServer进程的其他事情
	            return handleSystemServerProcess(parsedArgs);
        }
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }
		//......
        return null;
    }

监听AMS请求

Runnable runSelectLoop(String abiList) {
        ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
		//将Socket的文件描述符加入到列表中
        fds.add(mServerSocket.getFileDescriptor());
        peers.add(null);
		//在死循环中等待AMS请求
        while (true) {
            StructPollfd[] pollFds = new StructPollfd[fds.size()];
            for (int i = 0; i < pollFds.length; ++i) {
            	//将fds的储存信息转移到pollFds中
                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);
            }
            for (int i = pollFds.length - 1; i >= 0; --i) {
            	如果i==0说明与服务端已经建立连接
                if ((pollFds[i].revents & POLLIN) == 0) {
                    continue;
                }

                if (i == 0) {
                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
                    peers.add(newPeer);
                    fds.add(newPeer.getFileDesciptor());
                } else {
                    try {
                        ZygoteConnection connection = peers.get(i);
                        final Runnable command = connection.processOneCommand(this);
                        if (mIsForkChild) {
                            if (command == null) {
                                throw new IllegalStateException("command == null");
                            }
                            return command;
                        } else {
                            if (connection.isClosedByPeer()) {
                                connection.closeSocket();
                                peers.remove(i);
                                fds.remove(i);
                            }
                        }
                    } catch (Exception e) {
                       //.....
                        }
                    }
                }
            }
        }
    }

SystemServer进程的启动

上面学习了Zygote进程的启动过程,这里讲学习一下SystemServer的启动过程。从上面的代码可以看出在Zygote进程启动后,后fork出一个SystemServer进程。SystemServer进程主要是用于创建系统服务,比如AMS(活动服务)、WMS(窗口服务)、PMS(Power服务)等。

在ZygoteInit类中通过fork的方式启动了SystemServer进程。在forkSystemServer方法创建了SystemServer进程,除此之外还需要完成SystemServer进程启动的其他工作。

	/**
     * Finish remaining work for the newly forked system server process.
     */
    private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {
        final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
        if (systemServerClasspath != null) {
           //......
        } else {
            ClassLoader cl = null;
            if (systemServerClasspath != null) {
            	//创建ClassLoader
                cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);

                Thread.currentThread().setContextClassLoader(cl);
            }

            /*
             * Pass the remaining arguments to SystemServer.
             */
             //传递其他参数到SystemServer
            return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
        }
    }

public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
        //......
        RuntimeInit.commonInit();
        //启动Binder线程池,SystemServer通过Binder与其他进程通信
        ZygoteInit.nativeZygoteInit();
        //进入SystemServer的main方法
        return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
    }

通过RuntimeInit类来进入SystemServer的main方法。

public static void main(String[] args) {
        new SystemServer().run();
    }

private void run() {
        try {
          //......
          //创建一个消息Looper
          Looper.prepareMainLooper();
          // Create the system service manager.
          //创建系统服务管理。
          mSystemServiceManager = new SystemServiceManager(mSystemContext);
          mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
          LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
          // Prepare the thread pool for init tasks that can be parallelized
          SystemServerInitThreadPool.get();
        } finally {
            traceEnd();  // InitBeforeStartServices
        }

        // Start services.
        try {
            //启动引导服务
            startBootstrapServices();
            //启动核心服务
            startCoreServices();
            //启动其他服务
            startOtherServices();
            SystemServerInitThreadPool.shutdown();
        } catch (Throwable ex) {
            throw ex;
        } finally {
            traceEnd();
        }

从上面的分析可以看到,SystemServer进程启动后主要完成了:

  • 启动Binder线程池,用来与其他进程通信;

  • 创建SystemServiceManager,用来管理系统服务;

  • 启动各种系统服务;

Launcher启动过程

经过上面进程的启动后,Android系统基本处于就绪状态。最后一步是启动一个应用程序来显示已安装的应用程序,即Launcher(Android系统的桌面)。

在SystemServer进程启动的过程中会启动PackageManagerService,然后PackageManagerService会将系统中的应用程序安装完成。接下来通过ActivityManagerService将Launcher启动。入口就是ActivityManagerService的systemReady方法。

public void systemReady(final Runnable goingCallback, BootTimingsTraceLog traceLog) {
    ...
    startHomeActivityLocked(currentUserId, "systemReady");
    ...
}

总结

通过上面的学习,将Android系统启动的主要过程描述一遍。由于整个Android系统的启动流程非常复杂,同时涉及到了非常多的底层代码,阅读起来会感觉到吃力。所以在最后要简要的总结一下Android系统的启动流程加强整个过程的理解。

  1. 启动电源以及系统启动,当按下电源键后,引导芯片代码从ROM中开始执行。加载引导程序BootLoader到RAM中。

  2. 通过引导程序BootLoader将系统OS拉起来并运行。

  3. Linux内核启动,设置缓存、计划列表、加载驱动。当内核完成系统设置时,解析init.rc文件,然后启动init进程。

  4. init进程启动主要初始化和启动属性服务,然后启动Zygote进程。

  5. Zygote进程创建Java虚拟机,创建服务端的Socket进程通信,然后启动SystemServer进程。

  6. SystemServer进程启动Binder线程池、创建SystemServiceManager,并且启动各种系统服务。

  7. Launcher应用程序启动。

可以看出,在Android系统的启动过程中主要涉及到了3个重要的进程,这3个进程向Android应用程序提供了必要的服务。最后启动了Launcher应用程序,将系统桌面呈现给了用户。

Android系统启动流程(三)解析SyetemServer进程启动过程 上一篇我们学习了Zygote进程,并且知道Zygote进程启动了SyetemServer进程,那么这一篇我们就来学习Android7.0版本的SyetemServer进程。 阅读详情

相关推荐

Android系统启动过程分析

主要流程 init进程启动过程 init进程是Android系统中用户空间的第一个进程。进程号为1。 第一步:启动电源 当电源按下,引导芯片代码开始从预定义的地方(固化在ROM)开始执行。加载引导程序到RAM,然后执行。 第二步:执行引导程序(Boot Loader) 通常在运行Android系统之前会先执行Boot Loader引导程序,它不属于Android系统,常见的引导程序有:redb...

weixin_39079048的博客 2205

Android:动态更新app启动图标和应用名

Android app只能替换内置的icon,因此需要提前将logo图标放入App资源文件件里 实际项目App更新桌面启动图标由服务器端控制,可以在App启动页里请求全局配置接口,根据接口返回的是否更新启动图标字段值进行处理。

ChinaDragon10的博客 3639

Android系统启动-SystemServer(二)

该方法所创建的服务:ActivityManagerService, PowerManagerService, LightsService, DisplayManagerService, PackageManagerService, UserManagerService, sensor服务.该方法比较长,有近千行代码,逻辑很简单,主要是启动一系列的服务,这里就不具体列举源码了,在第四节直接对其中的服务进行一个简单分类。到此,系统服务启动阶段完成就绪,system_server进程启动完成则进入。

a546036242的博客 1055

Android系统启动流程(基于Android 11)

本文讲解了我对Android开发现状的一些看法,也许有些人会觉得我的观点不对,但我认为没有绝对的对与错,一切交给时间去证明吧!愿与各位坚守的同胞们互相学习,共同进步!《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

2301_77595001的博客 990

从零开始:H20服务器上DeepSeek R1 671B大模型部署与压力测试全攻略

最近,我有幸在工作中接触到了DeepSeek R1 671B模型,这是目前中文开源领域参数量最大的高质量模型之一。DeepSeek团队在2024年推出的这款模型,以其惊人的6710亿参数量和出色的推理性能,引起了业界广泛关注。作为一名AI基础设施工程师,我有机会在H20服务器上部署这个庞然大物,并对其进行了全面的压力测试。这篇文章将详细记录我的部署过程和性能测试方法,希望能为大家提供一些参考。💡为什么选择DeepSeek R1?超大规模参数量(671B)优秀的中英文理解能力开源可商用的许可证。

wangli的博客 1万+

TBtools的序列提取步骤

本教程详细介绍了如何使用TBtools软件从原来的FASTA序列中提取特定的DNA序列。

weixin_47509995的博客 1万+

Android系统启动流程

Android系统启动过程及APP的启动过程

Java和Android架构 7290

什么是无人机巡检?如何实现无人机自动巡检?

复亚智能的无人机自动巡检系统通过高度自动化的技术,实现了无人机的高效巡检作业。无人机自动机场支持无人机的自动起降和电池更换,自动飞行算法确保无人机在复杂环境中的精准飞行和拍摄,而云端识别诊断和AI感知算法平台则实现图像的实时传输和智能分析。复亚智能,作为无人机技术的创新者和推动者,致力于开发先进的无人机自动巡检解决方案,助力各行各业实现智能化、自动化的巡检工作,引领智能巡检的未来。利用人工智能和机器学习算法,无人机可以被训练来识别特定的模式和异常,如结构损坏、热泄漏等,从而提高巡检的准确性和效率。

foiadrone的博客 2842

Android 系统源码-1:Android 系统启动流程源码分析

现在我们来梳理下 Android 系统的启动过程。Android 启动过程还是比较重要的,因为在这个过程中除了要完成 Linux 系统的初始化工作还要完成 Android 的基础服务和启动界面的初始化工作。 在这篇文章中,我们不打算过多深入源码。因为 Android 中任何一个功能模块在 Framework 层都涉及大量的代码调用。过多深入源码只会让我们迷失在一层层的调用栈中。相比之下,我更倾向于...

weixin_34261415的博客 566

M1/M2 Mac用户看过来:不装VirtualBox,用PD虚拟机也能跑ENSP的保姆级教程

本文为M1/M2 Mac用户提供了一份不依赖VirtualBox,使用Parallels Desktop虚拟机运行ENSP的详细指南。通过ARM架构的Win10镜像选择、组件替代方案和网络配置优化,实现ENSP核心功能的高效运行,特别适合网络工程师在苹果芯片设备上进行网络模拟。

weixin_28683065的博客 411

手把手教你学simulink(69.3)--毫米波5G/6G 系统场景实例设计并实现基于Simulink的毫米波多用户MIMO通信系统模型

毫米波频段(30 GHz到300 GHz)因其高带宽和高速率特性,成为5G和未来6G通信系统的理想选择。然而,毫米波信号的传播特性较差,容易受到大气吸收、雨衰、建筑物遮挡等因素的影响。为了克服这些挑战并提高通信容量,多用户MIMO(MU-MIMO, Multi-User Multiple-Input Multiple-Output)技术被广泛应用。多用户MIMO技术通过在基站和多个用户之间同时传输多个数据流,充分利用空间资源,从而显著提升系统容量和频谱效率。

MHD0815的博客 493

Android系统启动过程-uBoot+Kernel+Android

本文是参考大量网上资源在结合自己查看源代码总结出来的,让自己同时也让大家加深对Android系统启动过程有一个更加深入的了解!再次强调,本文的大多数功劳应归功于那些原创者们,同时一些必要的参考链接我会一一附上。注:由于本人采用Exynos4412开发板学习,所以本文大部分资料都是基于此处理器的简介:对于整个Android系统的启动总的来说分为三个阶段:BootLoader引导即uBoot.binlinux内核启动即zImageAndroid系统启动即ramdisk.img与system.img。

domen_pan的博客 3078

uni-app 实现高德 / 百度 / 腾讯地图多端导航跳转(H5最全方案)

本文介绍了一套生产级可复用的多地图导航Hook封装方案。针对开发中常见的经纬度顺序混乱、中文乱码、参数不统一等问题,提供了统一解决方案。方案支持高德、百度、腾讯三大地图平台,封装了各平台的URI参数处理逻辑,包括坐标顺序转换、名称编码、导航模式适配等核心功能。通过组合式API设计,开发者只需调用统一入口即可实现多地图导航跳转,同时保留单独调用各平台的能力。文中还总结了6大常见坑点,并推荐默认使用高德地图作为最稳定的导航方案。该方案适用于车辆定位、物流配送等多种业务场景,可封装为可复用的Hooks组件。

专注于前端开发与实战技巧,记录从零到一的学习与项目经验。分享 Vue3 / JavaScript / TypeScript / Flutter /Uniapp等前端技术,以及 性能优化、工程化、最佳实践。 537

Android系统架构-[Android取经之路]

系列文章: [1] Android系统架构 [2]Android是怎么启动的 [3]Android 10.0系统启动之init进程 [4]Android10.0系统启动之Zygote进程 [5]Android 10.0 系统启动之SystemServer进程 [6]Android 10.0 系统服务之ActivityMnagerService [7]Android10....

IngresGe 的专栏 2万+

HTOL集成电路老化测试学习总结-20250510

电子元器件的可靠性在产品开发中至关重要,尤其是在微电子技术迅速发展的今天。电子元器件的失效率通常遵循“浴盆曲线”,分为早期失效期、可使用期和老化期。为了评估芯片的可靠性,常采用高温操作寿命测试(HTOL),通过高温和高压加速芯片老化,以筛选出早期失效的芯片并评估其长期可靠性。HTOL测试中,芯片在高温下运行并监控其性能变化,通过阿伦尼乌斯公式计算加速因子,预测芯片的失效率和寿命。此外,Burn-in测试用于加速芯片老化,提前发现并剔除不合格产品,而早期失效率测试(ELFR)则用于评估产品初期使用阶段的可靠性

歌颂苦难的行为是无耻的; 2101

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Android系统架构开篇

一、Android概述Android系统非常庞大,底层是采用Linux作为基底,上层采用带有虚拟机的Java层,通过通过JNI技术,将上下打通,融为一体。下图是Google提供的一张经典的4层架构图,从下往上,依次分为Linux内核,系统库和Android Runtime,应用框架层,应用程序层这4层架构,每一层都包含大量的子模块或子系统。为了能够更深入地掌握Android整个架构思想,以及每块之间

Gityuan的博客 1万+

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Android 系统启动过程纪要(基于Android 10)

认识Android的系统启动的三个进程 init ->zygote -> system_server

hirezy 1740

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Android系统启动过程剖析

init_parse_config_fileàparse_configà parse_new_sectionàparse_service (或者parse_action)-> parse_line_service(或者parce_line_action)(3) 触发需要执行的action:Action需要在Triggers(触发条件)中调用,本阶段对需要执行的Action进行触发,并根据触发条件将需要执行的Action放入Action队列;函数间的调用执行关系使用“à”表示)

2401_89689756的博客 1888

Android系统启动流程(四)Launcher启动过程与系统启动流程

此前的文章我们学习了init进程、Zygote进程和SyetemServer进程的启动过程,这一篇文章我们就来学习Android系统启动流程的最后一步:Launcher的启动流程,并结合本系列的前三篇文章的内容来讲解Android系统启动流程。建议读这篇文章前要通读本系列的前三篇文章,否则你可能不会理解我在讲什么。

Android进阶三部曲 - 刘望舒 2万+

android系统启动过程

的实现,可以深入理解 Android 启动流程的控制逻辑,并为定制系统行为(如添加新服务、修改启动顺序)提供技术基础。:SystemServer 完成服务启动后发送 BOOT_COMPLETED 广播。是用户空间的第一个进程(PID=1),解析。:内核完成系统启动,初始化系统服务和驱动。触发器启动 Zygote 进程。创建子进程并执行二进制文件。执行early-init阶段。脚本,管理服务生命周期。执行late-init阶段。加载SELinux策略。内核启动init进程。进入无限循环处理事件。

inquisiter 1294

Android 系统启动到 APP 运行原理 —— 中级安卓开发工程师进阶必看

Android系统架构分为五层:应用层、框架层、本地库层、HAL层和内核层。系统启动流程包括Bootloader加载内核、Init进程启动Zygote、SystemServer初始化核心服务,最终启动Launcher。应用启动时,AMS通过Zygote孵化新进程,完成Activity初始化和界面渲染。系统运行时包含1个Binder驱动、1个ServiceManager进程,以及Zygote、SystemServer等核心进程。AIDL通过自动生成Stub和Proxy类实现跨进程通信,客户端通过transac

da_ma_dai的博客 1421

Android系统启动过程

和和。Android 系统启动过程现在我们来梳理下 Android 系统的启动过程。Android 启动过程还是比较重要的,因为在这个过

夜游神 1752

Android 系统架构详解

引言 本文作为Android系统架构的开篇,起到提纲挈领的作用,从系统整体架构角度概要讲解Android系统的核心技术点,带领大家初探Android系统全貌以及内部运作机制。虽然Android系统非常庞大且错综复杂,需要具备全面的技术栈,但整体架构设计清晰。Android底层内核空间以LinuxKernel作为基石,上层用户空间由Native系统库、虚拟机运行环境、框架层组成,通过系统调...

boguesfei的博客 1万+

Android系统启动过程分析代码跟踪。

本笔记是跟踪《深入理解Android卷1》的看书笔记。 参考地址:http://blog.youkuaiyun.com/luoshengyang/article/details/6768304 从看书过程中发现很多问题: 1. 《Linux内核源代码情景分析》 2. 掌握与socket相关的知识 3.常用的I/O模型(租塞式,非租塞式,多路复用异步

哈喽沃德 1436
上一篇: Android系统架构(一)—Android系统架构简述
下一篇: Android探索之路(四)—View的使用
Coding-ls
博客等级 码龄11年 41粉丝 61原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值