android系统启动流程分析

目录

一,android系统整体框架

1.1 用户空间启动入口

1.2 init.cpp启动和流程分析

1.2.1 android系统中各种xxx.rc文件结构含义

1.2.2 android系统init启动服务顺序

1.3 app_main.cpp启动和流程分析

二,进入ZygoteInit世界

      2.1 入口,是ZygoteInit的main方法

      2.2 加载资源

三,启动SystemServer进程

3.1最核心的就是做了五件事情


一,android系统整体框架

1.1 用户空间启动入口

bionic/libc/bionic/libc_init_static.cpp是整个系统启动入口,这段代码是通过汇编调用过来It is called from,arch-$ARCH/bionic/crtbegin_static.S

__noreturn void __libc_init(void* raw_args,
                            void (*onexit)(void) __unused,
                            int (*slingshot)(int, char**, char**),
                            structors_array_t const * const structors) {
  KernelArgumentBlock args(raw_args);
  __libc_init_main_thread(args);

  // Initializing the globals requires TLS to be available for errno.
  __init_thread_stack_guard(__get_thread());
  __libc_init_globals(args);

  __libc_init_AT_SECURE(args);
  __libc_init_common(args);

  apply_gnu_relro();

  // Several Linux ABIs don't pass the onexit pointer, and the ones that
  // do never use it.  Therefore, we ignore it.

  call_array(structors->preinit_array);
  call_array(structors->init_array);

  // The executable may have its own destructors listed in its .fini_array
  // so we need to ensure that these are called when the program exits
  // normally.
  if (structors->fini_array != NULL) {
    __cxa_atexit(__libc_fini,structors->fini_array,NULL);
  }

  exit(slingshot(args.argc, args.argv, args.envp));
}

1.2 init.cpp启动和流程分析

最后会调用到init.cpp,在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);
    }

    if (REBOOT_BOOTLOADER_ON_PANIC) {
        InstallRebootSignalHandlers();
    }

    add_environment("PATH", _PATH_DEFPATH);
add_environment("PATH", _PATH_DEFPATH);就是这是系统常用的一些命令,_PATH_DEFPATH的值:
#define	_PATH_DEFPATH	"/sbin:/system/sbin:/system/bin:/system/xbin:/vendor/bin:/vendor/xbin"

为后续准备

首次启动的时候,还需要挂载文件系统,创建需要的文件夹,并且设置对应的权限

if (is_first_stage) {
        boot_clock::time_point start_time = boot_clock::now();

        // Clear the umask.
        umask(0);

        // Get the basic filesystem setup we need put together in the initramdisk
        // on / and then we'll let the rc file figure out the rest.
        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));
        // Don't expose the raw commandline to unprivileged processes.
        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));
        mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8));
        mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9));

设置系统安全策略

selinux_initialize(true);

设置解析init.rc文件的服务,开始准备解析init.rc文件,注意这里的init.rc文件,

在8.0中对init.rc文件进行了拆分,可查看system\core\rootdir目录,包括:
init.zygote32.rc:Zygote对应的执行程序是app_process(纯32位模式);
init.zygote64.rc:Zygote对应的执行程序是app_process64(纯64位模式);
init.zygote32_64.rc:启动两个Zygote进程( zygote 和 zygote_secondary),对应的执行程序是app_process32(主模式)和app_process64;
init.zygote64_32.rc:启动两个Zygote进程( zygote 和 zygote_secondary),对应的执行程序是app_process64(主模式)和app_process32。一个是在32位环境运行,一个是64位环境运行

特别注意这段代码

我们可以看到虽然在8.0中对init.rc文件进行了拆分,但是把这些核心的rc文件都通过import的方式引用进来,做到了指责单一

通过分析/Volumes/aosp/android-8.1.0_r52/system/core/rootdir/init.zygote32.rc文件可以看到,如果 zygote 服务重启时,系统将会重启一些其他关键服务:

audioserver:管理音频相关功能。
cameraserver:管理摄像头服务。
media:处理媒体相关服务。
netd:网络管理服务,负责网络接口的管理。
wificond:管理 Wi-Fi 连接的服务。

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    class main
    priority -20
    user root
    group root readproc
    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

同时启动surfaceflinger进程,对应的surfaceflinger.rc文件

service surfaceflinger /system/bin/surfaceflinger
    class core animation
    user system
    group graphics drmrpc readproc
    onrestart restart zygote
    writepid /dev/stune/foreground/tasks
    socket pdx/system/vr/display/client     stream 0666 system graphics u:object_r:pdx_display_client_endpoint_socket:s0
    socket pdx/system/vr/display/manager    stream 0666 system graphics u:object_r:pdx_display_manager_endpoint_socket:s0
    socket pdx/system/vr/display/vsync      stream 0666 system graphics u:object_r:pdx_display_vsync_endpoint_socket:s0

对于surfaceflinger我们单独用一篇文章介绍

,对应的入口函数:

/Volumes/aosp/android-8.1.0_r52/frameworks/native/services/surfaceflinger/main_surfaceflinger.cpp

int main(int, char**) {
    startHidlServices();

    signal(SIGPIPE, SIG_IGN);
    // When SF is launched in its own process, limit the number of
    // binder threads to 4.
    ProcessState::self()->setThreadPoolMaxThreadCount(4);

    // start the thread pool
    sp<ProcessState> ps(ProcessState::self());
    ps->startThreadPool();

    // instantiate surfaceflinger
    sp<SurfaceFlinger> flinger = new SurfaceFlinger();

    setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);

    set_sched_policy(0, SP_FOREGROUND);

    // Put most SurfaceFlinger threads in the system-background cpuset
    // Keeps us from unnecessarily using big cores
    // Do this after the binder thread pool init
    if (cpusets_enabled()) set_cpuset_policy(0, SP_SYSTEM);

    // initialize before clients can connect
    flinger->init();

    // publish surface flinger
    sp<IServiceManager> sm(defaultServiceManager());
    sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);

    // publish GpuService
    sp<GpuService> gpuservice = new GpuService();
    sm->addService(String16(GpuService::SERVICE_NAME), gpuservice, false);

    struct sched_param param = {0};
    param.sched_priority = 2;
    if (sched_setscheduler(0, SCHED_FIFO, &param) != 0) {
        ALOGE("Couldn't set SCHED_FIFO");
    }

    // run surface flinger in this thread
    flinger->run();

    return 0;
}

1.2.1 android系统中各种xxx.rc文件结构含义

# 注释
service 服务名 可执行文件路径
    class 服务类别
    user 用户
    group 用户组
    socket socket名称 协议类型 权限 所有者 用户组
    onrestart 执行的命令
    writepid PID文件路径

1.2.2 android系统init启动服务顺序

上面说的这些rc文件对应的可执行程序在编译完成系统以后的这个目录下/Volumes/aosp/android-8.1.0_r52/out/target/product/angler/symbols/system


1.2.3 小结

对1.2.2章节讲解的 init进程fork其他进程做一个总结可以得出以下几点结论

1)凡是通过init fork出来的进程都会有一个对应的xxx.rc文件,这个xxx.rc文件里面定义了启动对应进程所需要的一个参数,以及对应进程的类别,同时和这个xxx.rc文件对应的有一个main_xxx.app/xx_main.cpp文件

2)凡是通过init fork出来的进程都会有一个编译出来一个二进制可执行的文件,这个文件在/Volumes/aosp/android-8.1.0_r52/out/target/product/angler/symbols/system目录下,二进制对应的源码是和xxx.rc在一起

3)凡是通过init fork出来的进程都不能在android studio里面断点 attach到,如

3)凡是通过zygote进程fork出来的子进程都可以在android studio里面attach到

ActionManager& am = ActionManager::GetInstance();
    ServiceManager& sm = ServiceManager::GetInstance();
    Parser& parser = Parser::GetInstance();

    parser.AddSectionParser("service", std::make_unique<ServiceParser>(&sm));
    parser.AddSectionParser("on", std::make_unique<ActionParser>(&am));
    parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser));
    std::string bootscript = GetProperty("ro.boot.init_rc", "");
    if (bootscript.empty()) {
        parser.ParseConfig("/init.rc");
        parser.set_is_system_etc_init_loaded(
                parser.ParseConfig("/system/etc/init"));
        parser.set_is_vendor_etc_init_loaded(
                parser.ParseConfig("/vendor/etc/init"));
        parser.set_is_odm_etc_init_loaded(parser.ParseConfig("/odm/etc/init"));
    } else {
        parser.ParseConfig(bootscript);
        parser.set_is_system_etc_init_loaded(true);
        parser.set_is_vendor_etc_init_loaded(true);
        parser.set_is_odm_etc_init_loaded(true);
    }

这里就到了最关键的init.rc文件了,截取其中的一部分看下,并且设置触发器,只有设置了这些书触发器以后那么init.rc里面的文件会自动执行

 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(set_mmap_rnd_bits_action, "set_mmap_rnd_bits");
    am.QueueBuiltinAction(set_kptr_restrict_action, "set_kptr_restrict");
    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");
  # Now we can start zygote for devices with file based encryption
    trigger zygote-start

    # Load persist properties and override properties (if enabled) from /data.
    trigger load_persist_props_action

    # Remove a file to wake up anything waiting for firmware.
    trigger firmware_mounts_complete

    trigger early-boot
    trigger boot


on zygote-start && property:ro.crypto.state=unsupported
    # A/B update verifier that marks a successful boot.
    exec_start update_verifier_nonencrypted
    start netd
    start zygote
    start zygote_secondary    

 开始挂载文件系统

on init
    sysclktz 0

    # Mix device-specific information into the entropy pool
    copy /proc/cmdline /dev/urandom
    copy /default.prop /dev/urandom

    # Backward compatibility.
    symlink /system/etc /etc
    symlink /sys/kernel/debug /d

    # Link /vendor to /system/vendor for devices without a vendor partition.
    symlink /system/vendor /vendor

    # Create energy-aware scheduler tuning nodes
    mkdir /dev/stune
    mount cgroup none /dev/stune schedtune
    mkdir /dev/stune/foreground
    mkdir /dev/stune/background
    mkdir /dev/stune/top-app
    mkdir /dev/stune/rt
    chown system system /dev/stune
    chown system system /dev/stune/foreground
    chown system system /dev/stune/background
    chown system system /dev/stune/top-app
    chown system system /dev/stune/rt
    chown system system /dev/stune/tasks
    chown system system /dev/stune/foreground/tasks
    chown system system /dev/stune/background/tasks
    chown system system /dev/stune/top-app/tasks
    chown system system /dev/stune/rt/tasks
    chmod 0664 /dev/stune/tasks
    chmod 0664 /dev/stune/foreground/tasks
    chmod 0664 /dev/stune/background/tasks
    chmod 0664 /dev/stune/top-app/tasks
    chmod 0664 /dev/stune/rt/tasks

    # Mount staging areas for devices managed by vold
    # See storage config details at http://source.android.com/tech/storage/
    mount tmpfs tmpfs /mnt mode=0755,uid=0,gid=1000
    restorecon_recursive /mnt

    mount configfs none /config
    chmod 0775 /config/sdcardfs
    chown system package_info /config/sdcardfs

    mkdir /mnt/secure 0700 root root
    mkdir /mnt/secure/asec 0700 root root
    mkdir /mnt/asec 0755 root system
    mkdir /mnt/obb 0755 root system
    mkdir /mnt/media_rw 0750 root media_rw
    mkdir /mnt/user 0755 root root
    mkdir /mnt/user/0 0755 root root
    mkdir /mnt/expand 0771 system system
    mkdir /mnt/appfuse 0711 root root

    # Storage views to support runtime permissions
    mkdir /mnt/runtime 0700 root root
    mkdir /mnt/runtime/default 0755 root root
    mkdir /mnt/runtime/default/self 0755 root root
    mkdir /mnt/runtime/read 0755 root root
    mkdir /mnt/runtime/read/self 0755 root root
    mkdir /mnt/runtime/write 0755 root root
    mkdir /mnt/runtime/write/self 0755 root root

    # Symlink to keep legacy apps working in multi-user world
    symlink /storage/self/primary /sdcard
    symlink /storage/self/primary /mnt/sdcard
    symlink /mnt/user/0/primary /mnt/runtime/default/self/primary

    write /proc/sys/kernel/panic_on_oops 1
    write /proc/sys/kernel/hung_task_timeout_secs 0
    write /proc/cpu/alignment 4

    # scheduler tunables
    # Disable auto-scaling of scheduler tunables with hotplug. The tunables
    # will vary across devices in unpredictable ways if allowed to scale with
    # cpu cores.
    write /proc/sys/kernel/sched_tunable_scaling 0
    write /proc/sys/kernel/sched_latency_ns 10000000
    write /proc/sys/kernel/sched_wakeup_granularity_ns 2000000
    write /proc/sys/kernel/sched_child_runs_first 0

    write /proc/sys/kernel/randomize_va_space 2
    write /proc/sys/vm/mmap_min_addr 32768
    write /proc/sys/net/ipv4/ping_group_range "0 2147483647"
    write /proc/sys/net/unix/max_dgram_qlen 600
    write /proc/sys/kernel/sched_rt_runtime_us 950000
    write /proc/sys/kernel/sched_rt_period_us 1000000

    # Assign reasonable ceiling values for socket rcv/snd buffers.
    # These should almost always be overridden by the target per the
    # the corresponding technology maximums.
    write /proc/sys/net/core/rmem_max  262144
    write /proc/sys/net/core/wmem_max  262144

    # reflect fwmark from incoming packets onto generated replies
    write /proc/sys/net/ipv4/fwmark_reflect 1
    write /proc/sys/net/ipv6/fwmark_reflect 1

    # set fwmark on accepted sockets
    write /proc/sys/net/ipv4/tcp_fwmark_accept 1

    # disable icmp redirects
    write /proc/sys/net/ipv4/conf/all/accept_redirects 0
    write /proc/sys/net/ipv6/conf/all/accept_redirects 0

    # /proc/net/fib_trie leaks interface IP addresses
    chmod 0400 /proc/net/fib_trie

    # Create cgroup mount points for process groups
    mkdir /dev/cpuctl
    mount cgroup none /dev/cpuctl cpu
    chown system system /dev/cpuctl
    chown system system /dev/cpuctl/tasks
    chmod 0666 /dev/cpuctl/tasks
    write /dev/cpuctl/cpu.rt_period_us 1000000
    write /dev/cpuctl/cpu.rt_runtime_us 950000

    # sets up initial cpusets for ActivityManager
    mkdir /dev/cpuset
    mount cpuset none /dev/cpuset

    # this ensures that the cpusets are present and usable, but the device's
    # init.rc must actually set the correct cpus
    mkdir /dev/cpuset/foreground
    copy /dev/cpuset/cpus /dev/cpuset/foreground/cpus
    copy /dev/cpuset/mems /dev/cpuset/foreground/mems
    mkdir /dev/cpuset/foreground/boost
    copy /dev/cpuset/cpus /dev/cpuset/foreground/boost/cpus
    copy /dev/cpuset/mems /dev/cpuset/foreground/boost/mems
    mkdir /dev/cpuset/background
    copy /dev/cpuset/cpus /dev/cpuset/background/cpus
    copy /dev/cpuset/mems /dev/cpuset/background/mems

    # system-background is for system tasks that should only run on
    # little cores, not on bigs
    # to be used only by init, so don't change system-bg permissions
    mkdir /dev/cpuset/system-background
    copy /dev/cpuset/cpus /dev/cpuset/system-background/cpus
    copy /dev/cpuset/mems /dev/cpuset/system-background/mems

    mkdir /dev/cpuset/top-app
    copy /dev/cpuset/cpus /dev/cpuset/top-app/cpus
    copy /dev/cpuset/mems /dev/cpuset/top-app/mems

    # change permissions for all cpusets we'll touch at runtime
    chown system system /dev/cpuset
    chown system system /dev/cpuset/foreground
    chown system system /dev/cpuset/foreground/boost
    chown system system /dev/cpuset/background
    chown system system /dev/cpuset/system-background
    chown system system /dev/cpuset/top-app
    chown system system /dev/cpuset/tasks
    chown system system /dev/cpuset/foreground/tasks
    chown system system /dev/cpuset/foreground/boost/tasks
    chown system system /dev/cpuset/background/tasks
    chown system system /dev/cpuset/system-background/tasks
    chown system system /dev/cpuset/top-app/tasks

    # set system-background to 0775 so SurfaceFlinger can touch it
    chmod 0775 /dev/cpuset/system-background

    chmod 0664 /dev/cpuset/foreground/tasks
    chmod 0664 /dev/cpuset/foreground/boost/tasks
    chmod 0664 /dev/cpuset/background/tasks
    chmod 0664 /dev/cpuset/system-background/tasks
    chmod 0664 /dev/cpuset/top-app/tasks
    chmod 0664 /dev/cpuset/tasks


    # qtaguid will limit access to specific data based on group memberships.
    #   net_bw_acct grants impersonation of socket owners.
    #   net_bw_stats grants access to other apps' detailed tagged-socket stats.
    chown root net_bw_acct /proc/net/xt_qtaguid/ctrl
    chown root net_bw_stats /proc/net/xt_qtaguid/stats

    # Allow everybody to read the xt_qtaguid resource tracking misc dev.
    # This is needed by any process that uses socket tagging.
    chmod 0644 /dev/xt_qtaguid

    # Create location for fs_mgr to store abbreviated output from filesystem
    # checker programs.
    mkdir /dev/fscklogs 0770 root system

    # pstore/ramoops previous console log
    mount pstore pstore /sys/fs/pstore
    chown system log /sys/fs/pstore/console-ramoops
    chmod 0440 /sys/fs/pstore/console-ramoops
    chown system log /sys/fs/pstore/console-ramoops-0
    chmod 0440 /sys/fs/pstore/console-ramoops-0
    chown system log /sys/fs/pstore/pmsg-ramoops-0
    chmod 0440 /sys/fs/pstore/pmsg-ramoops-0

    # enable armv8_deprecated instruction hooks
    write /proc/sys/abi/swp 1

    # Linux's execveat() syscall may construct paths containing /dev/fd
    # expecting it to point to /proc/self/fd
    symlink /proc/self/fd /dev/fd

    export DOWNLOAD_CACHE /data/cache

    # set RLIMIT_NICE to allow priorities from 19 to -20
    setrlimit 13 40 40

    # This allows the ledtrig-transient properties to be created here so
    # that they can be chown'd to system:system later on boot
    write /sys/class/leds/vibrator/trigger "transient"

整个解析init.rc文件的顺序

这里有一个很关键的地方就是

start_property_service();

启动这个属性服务以后,最后会调用到init.c里面的

void handle_control_message(const std::string& msg, const std::string& name) {
    Service* svc = ServiceManager::GetInstance().FindServiceByName(name);
    if (svc == nullptr) {
        LOG(ERROR) << "no such service '" << name << "'";
        return;
    }

    if (msg == "start") {
        svc->Start();
    } else if (msg == "stop") {
        svc->Stop();
    } else if (msg == "restart") {
        svc->Restart();
    } else {
        LOG(ERROR) << "unknown control msg '" << msg << "'";
    }
}

通过epoll机制,开启epoll循环,没有任务的时候sleep让出cpu,直到epoll里面有事件,启动,关闭,重启服务,当执行的命令是启动zygote服务的时候,此时会调用/Volumes/aosp/android-8.1.0_r52/system/core/init/service.cpp

bool Service::Start() {
    // Starting a service removes it from the disabled or reset state and
    // immediately takes it out of the restarting state if it was in there.
    flags_ &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART|SVC_DISABLED_START));

    // Running processes require no additional work --- if they're in the
    // process of exiting, we've ensured that they will immediately restart
    // on exit, unless they are ONESHOT.
    if (flags_ & SVC_RUNNING) {
        return false;
    }

    bool needs_console = (flags_ & SVC_CONSOLE);
    if (needs_console) {
        if (console_.empty()) {
            console_ = default_console;
        }

        // Make sure that open call succeeds to ensure a console driver is
        // properly registered for the device node
        int console_fd = open(console_.c_str(), O_RDWR | O_CLOEXEC);
        if (console_fd < 0) {
            PLOG(ERROR) << "service '" << name_ << "' couldn't open console '" << console_ << "'";
            flags_ |= SVC_DISABLED;
            return false;
        }
        close(console_fd);
    }

    struct stat sb;
    if (stat(args_[0].c_str(), &sb) == -1) {
        PLOG(ERROR) << "cannot find '" << args_[0] << "', disabling '" << name_ << "'";
        flags_ |= SVC_DISABLED;
        return false;
    }

    std::string scon;
    if (!seclabel_.empty()) {
        scon = seclabel_;
    } else {
        scon = ComputeContextFromExecutable(name_, args_[0]);
        if (scon == "") {
            return false;
        }
    }

    LOG(INFO) << "starting service '" << name_ << "'...";

    pid_t pid = -1;
    if (namespace_flags_) {
        pid = clone(nullptr, nullptr, namespace_flags_ | SIGCHLD, nullptr);
    } else {
        pid = fork();
    }
........
}

上面这段代码的含义,在这里会去fork一个进程,因为此时是创建zygote,所以此时会fork zygote进程,其主要流程如下:

是否正在运行,如正在运行,直接返回;
子进程是否启动,如未启动,调用fork并返回pid值;
如果以上正常,则调用ExpandArgsAndExecve启动该进程,完成Zygote的启动。

启动Zygote进程真正执行的路径为frameworks\base\cmds\app_process\app_main.cpp下的main函数,app_main.cpp是如何被调用起来的,就是用过这段/Volumes/aosp/android-8.1.0_r52/system/core/rootdir/init.zygote32.rc文件中定义的脚步执行的

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server

1.3 app_main.cpp启动和流程分析

app_main.cpp会被编译成app_process32/64的一个可执行的二进制文件,main方法里面,具体代码,这里的参数就是来自service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server

AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));

根据命令行里面的参数解析

const char* spaced_commands[] = { "-cp", "-classpath" };

解析参数

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

最后根据解析的参数,来判断是启动ZygoteInit还是RuntimeInit

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

这也就是为什么在ZygoteInit还是RuntimeInit的main函数里面能获取到对应参数的原因,接下来就会调用AndroidRuntime.start方法启动

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
   ............................................................

    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);

    /*
     * Register android functions.
     */
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }

    ............................................................

    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } 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);

............................................................
}

总结下,在AndroidRuntime的start方法里面总共就是做了三件事情

1):启动java虚拟机,startVm(&mJavaVM, &env, zygote) != 0

2):动态注册jni,int AndroidRuntime::startReg(JNIEnv* env)

3):Native侧反射调用java方法(ZygoteInit-->main())

二,进入ZygoteInit世界

2.1 入口,是ZygoteInit的main方法

主要做了四件事情

1):创建ZygoteServer服务器,接受有新的进程来了以后创建进程

2):fork子进程,这里很关键的一步是,在fork进程以后,这段代码会执行两边,只有在对于父进程来说,这行检查 pid 是否为 0,这是 fork() 系统调用的标准做法。在 Unix-like 系统中,当调用 fork() 时,子进程会接收到 0,而父进程会接收到子进程的 pid。这意味着这段代码只会在 子进程 中执行,也就是在 SystemServer 进程 中,所以返回的r是空的,此时会打开ZygoteServer循环等待

3):zygoteServer.runSelectLoop(abiList);开启等待,接受新的事件

4):preload(bootTimingsTraceLog);预加载资源,比如所有的

public static void main(String argv[]) {
  
           ZygoteServer zygoteServer = new ZygoteServer();

     
            zygoteServer.registerServerSocket(socketName);
            .................................................

             preload(bootTimingsTraceLog);

            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;
                }
            }
 .................................................

            
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            throw ex;
        } finally {
            zygoteServer.closeServerSocket();
        }
 
        // command.
        if (caller != null) {
            caller.run();
        }
    }

2.1.1 创建ZygoteServer,然后开始runSelectLoop

caller = zygoteServer.runSelectLoop(abiList);
Runnable runSelectLoop(String abiList) {
     .........
        while (true) {
            StructPollfd[] pollFds = new StructPollfd[fds.size()];
            .........
                        ZygoteConnection connection = peers.get(i);
                        final Runnable command = connection.processOneCommand(this);

                        if (mIsForkChild) {
.........                            return command;
                        } .............................................
                    }
                }
            }
        }
    }

创建一个链接,然后开始通过socket fork一个进程

Runnable processOneCommand(ZygoteServer zygoteServer) {
        String args[];
       
  


        fd = zygoteServer.getServerSocketFileDescriptor();

        if (fd != null) {
            fdsToClose[1] = fd.getInt$();
        }

        fd = null;

        pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,
                parsedArgs.appDataDir);
................................................
    }

        最后通过调用Zygote.forkAndSpecialize fork一个新的进程,返回进程以后,通过

ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs,
        null /* classLoader */);创建新的进程的binder,然后通过RuntimeInit的findStaticMain方法反射调用新进程的main方法然后返回到ZygoteInit的main方法最后调用
if (caller != null) {
    caller.run();
}

2.2 加载资源


preloadClasses /system/etc/preloaded-classes

差不多4739个java类

preloadResources
nativePreloadAppProcessHALs();
preloadOpenGL();
preloadSharedLibraries();
        
preloadTextResources();
WebViewFactory.prepareWebViewInZygote();
endIcuCachePinning();
warmUpJcaProviders();

2.3 fork进程

 public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
          int[][] rlimits, int mountExternal, String seInfo, String niceName, int[]  
        resetNicePriority();
        int pid = nativeForkAndSpecialize(
 
        return pid;
    }

三,启动SystemServer进程

SystemServer是在Zygonte进程fork出来的,然后通过反射调用SystemServer的main方法

3.1最核心的就是做了五件事情

1):startBootstrapServices(); 启动电源管理,设备管理等服务

2):startCoreServices();启动核心服务,比如WebViewUpdateService

3):startOtherServices();启动AMS,WMS,PMS等服务

4):Looper.prepareMainLooper(); 创建looper

5):Looper.loop();无限循环

 // Initialize the system context.
            createSystemContext();

            // 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 {
            traceBeginAndSlog("StartServices");
            startBootstrapServices();
            startCoreServices();
            startOtherServices();
            SystemServerInitThreadPool.shutdown();

关于SystemServer的启动流程会单独开启一篇文章讲解,可以参考这篇文章

android系统SystemServer进程启动流程分析

四,上帝视角看android启动流程图

通过这个时序图可以更清楚的看明白

 四,fork原理

参考android系统fork原理-CSDN博客

五,结束语

鉴于作者水平有限,文章之中难免有错误或者遗漏地方,欢迎大家批评指正,也欢迎大家讨论,积极评论哈,谢谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值