Android8.0.0-r4系统的启动过程

Android8.0.0-r4系统的启动过程_第1张图片

Init进程是Linux系统中用户空间的第一个进程,其进程号为1。

Android本质上就是一个基于Linux内核的操作系统。与 Linux的最大的区别是, Android 在应用层专门为移动设备添加了一些特有的支持。例如进程间通信机制中增加的Binder通信等。

Android系统启动流程的前几步:
1.启动电源以及系统启动
当电源按下时引导芯片代码开始从预定义的地方(固化在ROM)开始执行。加载引导程序Bootloader到RAM,然后执行。 
2.引导程序Bootloader 
引导程序是在Android操作系统开始运行前的一个小程序,它的主要作用是把系统OS拉起来并运行。 

3.linux内核启动 
内核启动时,设置缓存、被保护存储器、计划列表,加载驱动。当内核完成系统设置,它首先在系统文件中寻找”init”文件,然后启动root进程或者系统的第一个进程加载完Linux基本内核后开始初始化进程Init的。

4.init进程启动


本文主要分析init启动到zygote,systemserver启动的过程


1.init启动过程

Init进程主要做的事情为:
        初始化属性;
        处理配置文件的命令(主要是init.rc文件),包括处理各种Action;
        无限循环执行command(启动其他进程);

Init源码的主要目录:
        /system/core/init/
    主要jni代码:
        /frameworks/base/core/jni/
    涉及的其他目录:
        /bionic/libc/bionic/libc_init_common.cpp
        /bionic/libc/bionic/libc_init_common.h
        /bionic/libc/bionic/libc_init_dynamic.cpp

        /bionic/libc/bionic/libc_init_static.cpp
    属性核心文件:
        system/core/libcutils/properties.cpp
主要分为两部分:
        1.初始化:初始化主要包括建立/dev、/proc等目录,初始化属性,执行init.rc等初始化文件中的Action等。
        2.使用while的无限循环来建立子进程。

Linux中除过init外的其他进程都是init负责创建的,都是在这个无限while循环中完成的;而且init也会常驻内容

 代码路径:/system/core/init/init.cpp

    (http://androidxref.com/8.0.0_r4/xref/system/core/init/init.cpp)

  在main函数一开始主要进行一开始的准备工作,例如ueventd和看门狗判断,和信号系统安装,系统环境变量的添加工作

948int main(int argc, char** argv) {
949    if (!strcmp(basename(argv[0]), "ueventd")) {//判断是否为ueventd
950        return ueventd_main(argc, argv);
951    }
952     //判断是否为看门狗
953    if (!strcmp(basename(argv[0]), "watchdogd")) {
954        return watchdogd_main(argc, argv);
955    }
956
957    if (REBOOT_BOOTLOADER_ON_PANIC) {
958        install_reboot_signal_handlers();
959    }
960
961    add_environment("PATH", _PATH_DEFPATH);//添加环境变量
962

main函数中此段代码主要做的工作就是:创建文件系统目录并挂载相关的文件系统
963    bool is_first_stage = (getenv("INIT_SECOND_STAGE") == nullptr);//创建文件并挂载
964
965    if (is_first_stage) {
966        boot_clock::time_point start_time = boot_clock::now();
967
968        // Clear the umask.
969        umask(0); //清除屏蔽字(file mode creation mask),保证新建的目录的访问权限不受屏蔽字影响
970
971        // Get the basic filesystem setup we need put together in the initramdisk
972        // on / and then we'll let the rc file figure out the rest.
973        mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"); //挂载tmpfs文件系统 
974        mkdir("/dev/pts", 0755);
975        mkdir("/dev/socket", 0755);
976        mount("devpts", "/dev/pts", "devpts", 0, NULL);// 挂载devpts文件系统 
977        #define MAKE_STR(x) __STRING(x)
978        mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC));// 挂载proc文件系统 
979        // Don't expose the raw commandline to unprivileged processes.
980        chmod("/proc/cmdline", 0440);
981        gid_t groups[] = { AID_READPROC };
982        setgroups(arraysize(groups), groups);
983        mount("sysfs", "/sys", "sysfs", 0, NULL);// 挂载sysfs文件系统
984        mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL);// 挂载selinuxfs文件系统
985        mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11));
986        mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8));
987        mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9));
988
 
  

 
  
 
  
开始解析之前的各类初始化准备工作
989        // Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually
990        // talk to the outside world...
991        InitKernelLogging(argv);//内核log初始化
992
993        LOG(INFO) << "init first stage started!";
994
995        if (!DoFirstStageMount()) {
996            LOG(ERROR) << "Failed to mount required partitions early ...";
997            panic();
998        }
999
1000        SetInitAvbVersionInRecovery();//判断是否为recovery模式
1001
1002        // Set up SELinux, loading the SELinux policy.
1003        selinux_initialize(true);//初始化selinux
1004
1005        // We're in the kernel domain, so re-exec init to transition to the init domain now
1006        // that the SELinux policy has been loaded.
1007        if (restorecon("/init") == -1) {
1008            PLOG(ERROR) << "restorecon failed";
1009            security_failure();
1010        }
1011
1012        setenv("INIT_SECOND_STAGE", "true", 1);
1013
1014        static constexpr uint32_t kNanosecondsPerMillisecond = 1e6;
1015        uint64_t start_ms = start_time.time_since_epoch().count() / kNanosecondsPerMillisecond;
1016        setenv("INIT_STARTED_AT", StringPrintf("%" PRIu64, start_ms).c_str(), 1);
1017
1018        char* path = argv[0];
1019        char* args[] = { path, nullptr };
1020        execv(path, args);
1021
1022        // execv() only returns if an error happened, in which case we
1023        // panic and never fall through this conditional.
1024        PLOG(ERROR) << "execv(\"" << path << "\") failed";
1025        security_failure();
1026    }
1027
1028    // At this point we're in the second stage of init.
1029    InitKernelLogging(argv);
1030    LOG(INFO) << "init second stage started!";
1031
1032    // Set up a session keyring that all processes will have access to. It
1033    // will hold things like FBE encryption keys. No process should override
1034    // its session keyring.
1035    keyctl(KEYCTL_GET_KEYRING_ID, KEY_SPEC_SESSION_KEYRING, 1);
1036
1037    // Indicate that booting is in progress to background fw loaders, etc.
1038    close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));// 检测/dev/.booting文件是否可读写、创建等
1039
1040    property_init();// 初始化属性域 --> 定义于system/core/init/property_service.cpp
1041
1042    // If arguments are passed both on the command line and in DT,
1043    // properties set in DT always have priority over the command-line ones.
1044    process_kernel_dt();//dt中的属性设置
1045    process_kernel_cmdline();//处理内核命令行,dt中的属性总是优先于内核命令行
1046
1047    // Propagate the kernel variables to internal variables
1048    // used by init as well as the current required properties.
1049    export_kernel_boot_props();//将内核变量传播给init使用的内部变量以及当前所需的属性
1050
1051    // Make the time that init started available for bootstat to log.
1052    property_set("ro.boottime.init", getenv("INIT_STARTED_AT"));//设置boot启动时间在log中
1053    property_set("ro.boottime.init.selinux", getenv("INIT_SELINUX_TOOK"));//设置selinux启动时间在log中
1054
1055    // Set libavb version for Framework-only OTA match in Treble build.
1056    const char* avb_version = getenv("INIT_AVB_VERSION");
1057    if (avb_version) property_set("ro.boot.avb_version", avb_version);//在Treble版本中设置libavb版本以进行仅限框架的OTA匹配
1058
1059    // Clean up our environment.
1060    unsetenv("INIT_SECOND_STAGE");
1061    unsetenv("INIT_STARTED_AT");
1062    unsetenv("INIT_SELINUX_TOOK");
1063    unsetenv("INIT_AVB_VERSION");
1064
1065    // Now set up SELinux for second stage.
1066    selinux_initialize(false);//加载SELinux策略, 后面有一些初始化文件上下文的操作等
1067    selinux_restore_context();
1068
1069    epoll_fd = epoll_create1(EPOLL_CLOEXEC);
1070    if (epoll_fd == -1) {
1071        PLOG(ERROR) << "epoll_create1 failed";
1072        exit(1);
1073    }
1074
1075    signal_handler_init();///初始化子进程退出的信号处理过程
1076
1077    property_load_boot_defaults();//加载/default.prop文件
1078    export_oem_lock_status();
1079    start_property_service();//启动属性服务器(通过socket通信)
1080    set_usb_controller();
1081
1082    const BuiltinFunctionMap function_map;
1083    Action::set_function_map(&function_map);
1084
 
  

 
  
 
  
 
  
 
  
正式开启解析init.rc工作
1085    Parser& parser = Parser::GetInstance();
1086    parser.AddSectionParser("service",std::make_unique());//设置对应的解析函数 “service”块以关键字“service”开始,表示启动某个进程的方式和参数
1087    parser.AddSectionParser("on", std::make_unique());//“action”块以关键字“on”开始,表示一堆命令的集合
1088    parser.AddSectionParser("import", std::make_unique()); //“import”是用来引入一个init配置文件,来扩展当前配置的
1089    std::string bootscript = GetProperty("ro.boot.init_rc", "");
1090    if (bootscript.empty()) {
1091        parser.ParseConfig("/init.rc");
1092        parser.set_is_system_etc_init_loaded(
1093                parser.ParseConfig("/system/etc/init"));
1094        parser.set_is_vendor_etc_init_loaded(
1095                parser.ParseConfig("/vendor/etc/init"));
1096        parser.set_is_odm_etc_init_loaded(parser.ParseConfig("/odm/etc/init"));
1097    } else {
1098        parser.ParseConfig(bootscript);
1099        parser.set_is_system_etc_init_loaded(true);
1100        parser.set_is_vendor_etc_init_loaded(true);
1101        parser.set_is_odm_etc_init_loaded(true);
1102    }
1103
1104    // Turning this on and letting the INFO logging be discarded adds 0.2s to
1105    // Nexus 9 boot time, so it's disabled by default.
1106    if (false) parser.DumpState();
1107
1108    ActionManager& am = ActionManager::GetInstance();
1109
1110    am.QueueEventTrigger("early-init");
1111
1112    // Queue an action that waits for coldboot done so we know ueventd has set up all of /dev...
1113    am.QueueBuiltinAction(wait_for_coldboot_done_action, "wait_for_coldboot_done");
1114    // ... so that we can start queuing up actions that require stuff from /dev.
1115    am.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
1116    am.QueueBuiltinAction(set_mmap_rnd_bits_action, "set_mmap_rnd_bits");
1117    am.QueueBuiltinAction(set_kptr_restrict_action, "set_kptr_restrict");
1118    am.QueueBuiltinAction(keychord_init_action, "keychord_init");
1119    am.QueueBuiltinAction(console_init_action, "console_init");
1120
1121    // Trigger all the boot actions to get us started.
1122    am.QueueEventTrigger("init");
1123
1124    // Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random
1125    // wasn't ready immediately after wait_for_coldboot_done
1126    am.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
1127
1128    // Don't mount filesystems or start core system services in charger mode.
1129    std::string bootmode = GetProperty("ro.bootmode", "");
1130    if (bootmode == "charger") {
1131        am.QueueEventTrigger("charger");
1132    } else {
1133        am.QueueEventTrigger("late-init");
1134    }
1135
1136    // Run all property triggers based on current state of the properties.
1137    am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");
 
  

init.rc的过程就是识别一个个section的过程,将各个section的信息保存下来,然后在init.c的main()中去执行一个个命令。 android采用双向链表(关于双向链表详解见本文第三部分)来存储section的信息,解析完成之后,会得到三个双向链表action_list、service_list、import_list来分别存储三种section的信息上

init.rc解析完成之后,所有的启动项目都被放入到action_add_queue_tail中,接着调用action_for_each_trigger("early-init", action_add_queue_tail),触发early-init触发器来出发这些相关services和actions的运行。

使用while的无限循环来建立子进程
 
  
 
  
1138
1139    while (true) {
1140        // By default, sleep until something happens.
1141        int epoll_timeout_ms = -1;//以下决定epoll_timeout_ms的时间,将影响while循环的间隔
1142
1143        if (!(waiting_for_prop || ServiceManager::GetInstance().IsWaitingForExec())) {
1144            am.ExecuteOneCommand();
1145        }
1146        if (!(waiting_for_prop || ServiceManager::GetInstance().IsWaitingForExec())) {
1147            restart_processes();
1148
1149            // If there's a process that needs restarting, wake up in time for that.
1150            if (process_needs_restart_at != 0) {//有进程需要重启时,等待该进程重启
1151                epoll_timeout_ms = (process_needs_restart_at - time(nullptr)) * 1000;
1152                if (epoll_timeout_ms < 0) epoll_timeout_ms = 0;
1153            }
1154
1155            // If there's more work to do, wake up again immediately.
1156            if (am.HasMoreCommands()) epoll_timeout_ms = 0;
1157        }
1158
1159        epoll_event ev;
1160        int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, epoll_timeout_ms));
1161        if (nr == -1) {
1162            PLOG(ERROR) << "epoll_wait failed";
1163        } else if (nr == 1) {
1164            ((void (*)()) ev.data.ptr)();
1165        }
1166    }
1167
1168    return 0;
1169}

在 init 进程中 ,配置文件是指文件 init.rc,其路径是:
/system/core/rootdir/init .rc

文件 init.rc 是一个可配置的初始化文件 ,在里面定制了厂商可以配置的额外的初始化配置信息,具体格式为:
init.%PRODUCT%.rc
文件init.rc是在文件“/system/core/init/init.cpp”中读取的,它基于“行”,包含一些用空格隔开的关键字(它属于特殊字符)。如果在关键字中含有空格,则使用“/“表示转义,使用“”防止关键字被断开,如果“/”在末尾则表示换行,以“#”开头的表示注释。文件init.rc 包含 4 种状态类别 ,分别是 Actions 、Commands 、Services 和 Options ,当声明一个 Service  或者 Action  的时候,它将隐式声明一个 section,它之后跟随的Command或者Option都将属于这个 section。另外,Action    和 Service  不能重名,否则忽略为eπor

2.zygote启动过程
在init.rc中,early-init相关启动的services和actions。基本上是恢复某些文件或文件夹的安全上下文,然后调用init_zygote32_64.rc文件中的命令启动zygote

1service zygote /system/bin/app_process32 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
2    class main
3    priority -20
4    user root
5    group root readproc
6    socket zygote stream 660 root system
7    onrestart write /sys/android_power/request_state wake
8    onrestart write /sys/power/state on
9    onrestart restart audioserver
10    onrestart restart cameraserver
11    onrestart restart media
12    onrestart restart netd
13    onrestart restart wificond
14    writepid /dev/cpuset/foreground/tasks
15
16service zygote_secondary /system/bin/app_process64 -Xzygote /system/bin --zygote --socket-name=zygote_secondary
17    class main
18    priority -20
19    user root
20    group root readproc
21    socket zygote_secondary stream 660 root system
22    onrestart restart zygote
23    writepid /dev/cpuset/foreground/tasks

通过/system/bin/app_process32程序启动zygote进程,参数为--zygote和--start-system-server,这两个参数在后面我们会用到的。下面我们来看一下Zygote的main函数

 

zygote启动过程大体上分为七部分:

1.app_main.main

代码路径:/frameworks/base/cmds/app_process/app_main.cpp

    (http://androidxref.com/8.0.0_r4/xref//frameworks/base/cmds/app_process/app_main.cpp)

在Zygote进程中加载的应用程序文件为system/bin/app_process。 因此,接下来就从这个应用程序文件的入口函数main开始分析Zygote进程的启动过程

187int main(int argc, char* const argv[])
188{
189    if (!LOG_NDEBUG) {
190      String8 argv_String;
191      for (int i = 0; i < argc; ++i) {
192        argv_String.append("\"");
193        argv_String.append(argv[i]);
194        argv_String.append("\" ");
195      }
196      ALOGV("app_process main with argv: %s", argv_String.string());
197    }
198
199    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));//创建了一个AppRuntime对象runtime
200    // Process command line arguments
201    // ignore argv[0]
202    argc--;
203    argv++;
204
205    // Everything up to '--' or first non '-' arg goes to the vm.
206    //
207    // The first argument after the VM args is the "parent dir", which
208    // is currently unused.
209    //
210    // After the parent dir, we expect one or more the following internal
211    // arguments :
212    //
213    // --zygote : Start in zygote mode
214    // --start-system-server : Start the system server.
215    // --application : Start in application (stand alone, non zygote) mode.
216    // --nice-name : The nice name for this process.
217    //
218    // For non zygote starts, these arguments will be followed by
219    // the main class name. All remaining arguments are passed to
220    // the main method of this class.
221    //
222    // For zygote starts, all remaining arguments are passed to the zygote.
223    // main function.
224    //
225    // Note that we must copy argument string values since we will rewrite the
226    // entire argument block when we apply the nice name to argv0.
227    //
228    // As an exception to the above rule, anything in "spaced commands"
229    // goes to the vm even though it has a space in it.
230    const char* spaced_commands[] = { "-cp", "-classpath" };
231    // Allow "spaced commands" to be succeeded by exactly 1 argument (regardless of -s).
232    bool known_command = false;
233
234    int i;
235    for (i = 0; i < argc; i++) {
236        if (known_command == true) {
237          runtime.addOption(strdup(argv[i]));
238          ALOGV("app_process main add known option '%s'", argv[i]);
239          known_command = false;
240          continue;
241        }
242
243        for (int j = 0;
244             j < static_cast(sizeof(spaced_commands) / sizeof(spaced_commands[0]));
245             ++j) {
246          if (strcmp(argv[i], spaced_commands[j]) == 0) {
247            known_command = true;
248            ALOGV("app_process main found known command '%s'", argv[i]);
249          }
250        }
251
252        if (argv[i][0] != '-') {
253            break;
254        }
255        if (argv[i][1] == '-' && argv[i][2] == 0) {
256            ++i; // Skip --.
257            break;
258        }
259
260        runtime.addOption(strdup(argv[i]));
261        ALOGV("app_process main add option '%s'", argv[i]);
262    }
263
264    // Parse runtime arguments.  Stop at first unrecognized option.
265    bool zygote = false;
266    bool startSystemServer = false;
267    bool application = false;
268    String8 niceName;
269    String8 className;
270
271    ++i;  // Skip unused "parent dir" argument.
272    while (i < argc) {
273        const char* arg = argv[i++];
274        if (strcmp(arg, "--zygote") == 0) {//检查应用程序 app_process 的启动参数arg是否包含了一个 “一zygote ” 选项。
275            zygote = true;                 //如果包含了 ,那么就说明这时候应用程序app_process是在Zygote进程中启动的
276            niceName = ZYGOTE_NICE_NAME;
277        } else if (strcmp(arg, "--start-system-server") == 0) {
278            startSystemServer = true;
279        } else if (strcmp(arg, "--application") == 0) {
280            application = true;
281        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
282            niceName.setTo(arg + 12);
283        } else if (strncmp(arg, "--", 2) != 0) {
284            className.setTo(arg);
285            break;
286        } else {
287            --i;
288            break;
289        }
290    }
291
292    Vector args;
293    if (!className.isEmpty()) {
294        // We're not in zygote mode, the only argument we need to pass
295        // to RuntimeInit is the application argument.
296        //
297        // The Remainder of args get passed to startup class main(). Make
298        // copies of them before we overwrite them with the process name.
299        args.add(application ? String8("application") : String8("tool"));
300        runtime.setClassNameAndArgs(className, argc - i, argv + i);
301
302        if (!LOG_NDEBUG) {
303          String8 restOfArgs;
304          char* const* argv_new = argv + i;
305          int argc_new = argc - i;
306          for (int k = 0; k < argc_new; ++k) {
307            restOfArgs.append("\"");
308            restOfArgs.append(argv_new[k]);
309            restOfArgs.append("\" ");
310          }
311          ALOGV("Class name = %s, args = %s", className.string(), restOfArgs.string());
312        }
313    } else {
314        // We're in zygote mode.
315        maybeCreateDalvikCache();
316        
317        if (startSystemServer) {
318            args.add(String8("start-system-server"));
319        }
320
321        char prop[PROP_VALUE_MAX];
322        if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
323            LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
324                ABI_LIST_PROPERTY);
325            return 11;
326        }
327
328        String8 abiFlag("--abi-list=");
329        abiFlag.append(prop);
330        args.add(abiFlag);
331
332        // In zygote mode, pass all remaining arguments to the zygote
333        // main() method.
334        for (; i < argc; ++i) {
335            args.add(String8(argv[i]));
336        }
337    }
338
339    if (!niceName.isEmpty()) {
340        runtime.setArgv0(niceName.string(), true /* setProcName */);
341    }
342
343    if (zygote) {//AppRuntime类的成员函数start是从其父类AndroidRuntime继承下来的,接下来分析AndroidRuntime类的成员函数start的实现
344        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
345    } else if (className) {
346        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
347    } else {
348        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
349        app_usage();
350        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
351    }
352}
 
  

2.AndroidRuntime.start

代码路径:/frameworks/base/core/jni/AndroidRuntime.cpp

    (http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/jni/AndroidRuntime.cpp)

986/*
987 * Start the Android runtime.  This involves starting the virtual machine
988 * and calling the "static void main(String[] args)" method in the class
989 * named by "className".
990 *
991 * Passes the main function two arguments, the class name and the specified
992 * options string.
993 */
994void AndroidRuntime::start(const char* className, const Vector& options, bool zygote)
995{
996    ALOGD(">>>>>> START %s uid %d <<<<<<\n",
997            className != NULL ? className : "(unknown)", getuid());
998
999    static const String8 startSystemServer("start-system-server");
1000
1001    /*
1002     * 'startSystemServer == true' means runtime is obsolete and not run from
1003     * init.rc anymore, so we print out the boot start event here.
1004     */
1005    for (size_t i = 0; i < options.size(); ++i) {
1006        if (options[i] == startSystemServer) {
1007           /* track our progress through the boot sequence */
1008           const int LOG_BOOT_PROGRESS_START = 3000;
1009           LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,  ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
1010        }
1011    }
1012
1013    const char* rootDir = getenv("ANDROID_ROOT");
1014    if (rootDir == NULL) {
1015        rootDir = "/system";
1016        if (!hasDir("/system")) {
1017            LOG_FATAL("No root directory specified, and /android does not exist.");
1018            return;
1019        }
1020        setenv("ANDROID_ROOT", rootDir, 1);
1021    }
1022
1023    //const char* kernelHack = getenv("LD_ASSUME_KERNEL");
1024    //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
1025
1026    /* start the virtual machine *///调用成员函数startVMZygote进程中创建个虚拟机实例
1027    JniInvocation jni_invocation;
1028    jni_invocation.Init(NULL);
1029    JNIEnv* env;
1030    if (startVm(&mJavaVM, &env, zygote) != 0) {
1031        return;
1032    }
1033    onVmCreated(env);
1034
1035    /*
1036     * Register android functions.
1037     */
1038    if (startReg(env) < 0) {//成员函数startReg在这个虚拟机实例中注册一系列JNI方法 
1039        ALOGE("Unable to register all android natives\n");
1040        return;
1041    }
1042
1043    /*
1044     * We want to call main() with a String array with arguments in it.
1045     * At present we have two arguments, the class name and an option string.
1046     * Create an array to hold them.
1047     */
1048    jclass stringClass;
1049    jobjectArray strArray;
1050    jstring classNameStr;
1051
1052    stringClass = env->FindClass("java/lang/String");
1053    assert(stringClass != NULL);
1054    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
1055    assert(strArray != NULL);
1056    classNameStr = env->NewStringUTF(className);
1057    assert(classNameStr != NULL);
1058    env->SetObjectArrayElement(strArray, 0, classNameStr);
1059
1060    for (size_t i = 0; i < options.size(); ++i) {
1061        jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
1062        assert(optionsStr != NULL);
1063        env->SetObjectArrayElement(strArray, i + 1, optionsStr);
1064    }
1065
1066    /*
1067     * Start VM.  This thread becomes the main thread of the VM, and will
1068     * not return until the VM exits.
1069     */
1070    char* slashClassName = toSlashClassName(className);
1071    jclass startClass = env->FindClass(slashClassName);
1072    if (startClass == NULL) {
1073        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
1074        /* keep going */
1075    } else {
1076        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
1077            "([Ljava/lang/String;)V");
1078        if (startMeth == NULL) {
1079            ALOGE("JavaVM unable to find main() in '%s'\n", className);
1080            /* keep going */
1081        } else {
1082            env->CallStaticVoidMethod(startClass, startMeth, strArray);
1083            //调用com.android.internal.os.Zygotelnit类的静态成员函数main来进一步启动Zygote进程
1084#if 0
1085            if (env->ExceptionCheck())
1086                threadExitUncaughtException(env);
1087#endif
1088        }
1089    }
1090    free(slashClassName);
1091
1092    ALOGD("Shutting down VM\n");
1093    if (mJavaVM->DetachCurrentThread() != JNI_OK)
1094        ALOGW("Warning: unable to detach main thread\n");
1095    if (mJavaVM->DestroyJavaVM() != 0)
1096        ALOGW("Warning: VM did not shut down cleanly\n");
1097}


3.ZygoteInit.main

代码路径:/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

    (http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java)

671    public static void main(String argv[]) {
672        ZygoteServer zygoteServer = new ZygoteServer();
673
674        // Mark zygote start. This ensures that thread creation will throw
675        // an error.
676        ZygoteHooks.startZygoteNoThreadCreation();
677
678        // Zygote goes into its own process group.
679        try {
680            Os.setpgid(0, 0);
681        } catch (ErrnoException ex) {
682            throw new RuntimeException("Failed to setpgid(0,0)", ex);
683        }
684
685        try {
686            // Report Zygote start time to tron unless it is a runtime restart
687            if (!"1".equals(SystemProperties.get("sys.boot_completed"))) {
688                MetricsLogger.histogram(null, "boot_zygote_init",
689                        (int) SystemClock.elapsedRealtime());
690            }
691
692            String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";
693            BootTimingsTraceLog bootTimingsTraceLog = new BootTimingsTraceLog(bootTimeTag,
694                    Trace.TRACE_TAG_DALVIK);
695            bootTimingsTraceLog.traceBegin("ZygoteInit");
696            RuntimeInit.enableDdms();
697            // Start profiling the zygote initialization.
698            SamplingProfilerIntegration.start();
699
700            boolean startSystemServer = false;
701            String socketName = "zygote";
702            String abiList = null;
703            boolean enableLazyPreload = false;
704            for (int i = 1; i < argv.length; i++) {
705                if ("start-system-server".equals(argv[i])) {
706                    startSystemServer = true;
707                } else if ("--enable-lazy-preload".equals(argv[i])) {
708                    enableLazyPreload = true;
709                } else if (argv[i].startsWith(ABI_LIST_ARG)) {
710                    abiList = argv[i].substring(ABI_LIST_ARG.length());
711                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
712                    socketName = argv[i].substring(SOCKET_NAME_ARG.length());
713                } else {
714                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
715                }
716            }
717
718            if (abiList == null) {
719                throw new RuntimeException("No ABI list supplied.");
720            }
721            //Server端Socket是用来等待Activity管理服务ActivityManagerService请求Zygote进程创建新的应用程序进程的
722            zygoteServer.registerServerSocket(socketName);//调用zygoteServer类的静态成员函数registerZygoteSocket来创建一个Server端Socket


执行preload函数来进行资源文件的预加载工作,加载类,加载资源文件,加载OPenGl,加载共享库,文本资源以及准备WebView.

723            // In some configurations, we avoid preloading resources and classes eagerly.
724            // In such cases, we will preload things prior to our first fork.
725            if (!enableLazyPreload) {
726                bootTimingsTraceLog.traceBegin("ZygotePreload");
727                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
728                    SystemClock.uptimeMillis());
729                preload(bootTimingsTraceLog);
730                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
731                    SystemClock.uptimeMillis());
732                bootTimingsTraceLog.traceEnd(); // ZygotePreload
733            } else {
734                Zygote.resetNicePriority();
735            }
736
737            // Finish profiling the zygote initialization.
738            SamplingProfilerIntegration.writeZygoteSnapshot();
739
740            // Do an initial gc to clean up after startup
741            bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
742            gcAndFinalize();
743            bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC
744
745            bootTimingsTraceLog.traceEnd(); // ZygoteInit
746            // Disable tracing so that forked processes do not inherit stale tracing tags from
747            // Zygote.
748            Trace.setTracingEnabled(false);
749
750            // Zygote process unmounts root storage spaces.
751            Zygote.nativeUnmountStorageOnInit();
752
753            // Set seccomp policy
754            Seccomp.setPolicy();
755
756            ZygoteHooks.stopZygoteNoThreadCreation();
757            //调用Zygotelnit类的静态成员函数startSystemServer来启动System进程,以便它可以将系统的关键服务启动起来
758            if (startSystemServer) {
759                startSystemServer(abiList, socketName, zygoteServer);
760            }
761
762            Log.i(TAG, "Accepting command socket connections");
763            zygoteServer.runSelectLoop(abiList);
764
765            zygoteServer.closeServerSocket();
766        } catch (Zygote.MethodAndArgsCaller caller) {
767            caller.run();
768        } catch (Throwable ex) {
769            Log.e(TAG, "System zygote died with exception", ex);
770            zygoteServer.closeServerSocket();
771            throw ex;
772        }
773    }
774

通过参数判断是否启动systemServer,也就是通过刚刚我们记录下来的参数--start-system-server判定startSystemServer为true;接着通过调用registerZygoteSocket(socketName)函数来注册zygote套接字,进行进程间的通信


4.ZygoteInit.startSystemServer

代码路径:/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

(http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java)

590    /**
591     * Prepare the arguments and fork for the system server process.
592     */
593    private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)
594            throws Zygote.MethodAndArgsCaller, RuntimeException {
595        long capabilities = posixCapabilitiesAsBits(
596            OsConstants.CAP_IPC_LOCK,
597            OsConstants.CAP_KILL,
598            OsConstants.CAP_NET_ADMIN,
599            OsConstants.CAP_NET_BIND_SERVICE,
600            OsConstants.CAP_NET_BROADCAST,
601            OsConstants.CAP_NET_RAW,
602            OsConstants.CAP_SYS_MODULE,
603            OsConstants.CAP_SYS_NICE,
604            OsConstants.CAP_SYS_PTRACE,
605            OsConstants.CAP_SYS_TIME,
606            OsConstants.CAP_SYS_TTY_CONFIG,
607            OsConstants.CAP_WAKE_ALARM
608        );
609        /* Containers run without this capability, so avoid setting it in that case */
610        if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) {
611            capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND);
612        }
613        /* Hardcoded command line to start the system server */
614        String args[] = {
615            "--setuid=1000",
616            "--setgid=1000",
617            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010",
618            "--capabilities=" + capabilities + "," + capabilities,
619            "--nice-name=system_server",
620            "--runtime-args",
621            "com.android.server.SystemServer",
622        };
623        ZygoteConnection.Arguments parsedArgs = null;
624
625        int pid;
626
627        try {
628            parsedArgs = new ZygoteConnection.Arguments(args);
629            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
630            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
631
632            /* Request to fork the system server process */
633            pid = Zygote.forkSystemServer(
634                    parsedArgs.uid, parsedArgs.gid,
635                    parsedArgs.gids,
636                    parsedArgs.debugFlags,
637                    null,
638                    parsedArgs.permittedCapabilities,
639                    parsedArgs.effectiveCapabilities);
640        } catch (IllegalArgumentException ex) {
641            throw new RuntimeException(ex);
642        }
643
644        /* For child process */
645        if (pid == 0) {
646            if (hasSecondZygote(abiList)) {
647                waitForSecondaryZygote(socketName);
648            }
649
650            zygoteServer.closeServerSocket();
651            handleSystemServerProcess(parsedArgs);
652        }
653
654        return true;
655    }

准备系统服启动的参数,并通过forkSystemServer来创建系统服务进程,接着调用handleSystemServerProcess(parsedArgs)来进行系统服务的处理。


5.ZygoteServer.registerServerSocket

代码路径:/frameworks/base/core/java/com/android/internal/os/ZygoteServer.java

    (http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/com/android/internal/os/ZygoteServer.java)

调用zygoteServer类的静态成员函数registerZygoteSocket来创建一个Server端Socket, Zygote进程将System进程启动起来之 后 ,就会在这个Server端Socket上等待Activity管理服务ActivityManagerService请求Zygote进程创建新的应用程序进程.

51    /**
52     * Registers a server socket for zygote command connections
53     *
54     * @throws RuntimeException when open fails
55     */
56    void registerServerSocket(String socketName) {
57        if (mServerSocket == null) {
58            int fileDesc;
59            final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
60            try {
61                String env = System.getenv(fullSocketName);
62                fileDesc = Integer.parseInt(env);
63            } catch (RuntimeException ex) {
64                throw new RuntimeException(fullSocketName + " unset or invalid", ex);
65            }
66
67            try {
68                FileDescriptor fd = new FileDescriptor();
69                fd.setInt$(fileDesc);
70                mServerSocket = new LocalServerSocket(fd);
71            } catch (IOException ex) {
72                throw new RuntimeException(
73                        "Error binding to local socket '" + fileDesc + "'", ex);
74            }
75        }
76    }


6.ZygoteServer.runSelectLoop

代码路径:/frameworks/base/core/java/com/android/internal/os/ZygoteServer.java

    (http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/com/android/internal/os/ZygoteServer.java)

运行zygote进程的选择循环。 在发生时接受新的连接,并且一次从连接读取一次产生请求的价值。

128    /**
129     * Runs the zygote process's select loop. Accepts new connections as
130     * they happen, and reads commands from connections one spawn-request's
131     * worth at a time.
132     *
133     * @throws Zygote.MethodAndArgsCaller in a child process when a main()
134     * should be executed.
135     */
136    void runSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller {
137        ArrayList fds = new ArrayList();
138        ArrayList peers = new ArrayList();
139
140        fds.add(mServerSocket.getFileDescriptor());
141        peers.add(null);
142
143        while (true) {
144            StructPollfd[] pollFds = new StructPollfd[fds.size()];
145            for (int i = 0; i < pollFds.length; ++i) {
146                pollFds[i] = new StructPollfd();
147                pollFds[i].fd = fds.get(i);
148                pollFds[i].events = (short) POLLIN;
149            }
150            try {
151                Os.poll(pollFds, -1);
152            } catch (ErrnoException ex) {
153                throw new RuntimeException("poll failed", ex);
154            }
155            for (int i = pollFds.length - 1; i >= 0; --i) {
156                if ((pollFds[i].revents & POLLIN) == 0) {
157                    continue;
158                }
159                if (i == 0) {
160                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
161                    peers.add(newPeer);
162                    fds.add(newPeer.getFileDesciptor());
163                } else {
164                    boolean done = peers.get(i).runOnce(this);
165                    if (done) {
166                        peers.remove(i);
167                        fds.remove(i);
168                    }
169                }
170            }
171        }
172    }


7.ZygoteServer.closeServerSocket

代码路径:/frameworks/base/core/java/com/android/internal/os/ZygoteServer.java

    (http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/com/android/internal/os/ZygoteServer.java)

关闭zygoteServer类的静态成员函数registerZygoteSocket创建的socket

96    /**
97     * Close and clean up zygote sockets. Called on shutdown and on the
98     * child's exit path.
99     */
100    void closeServerSocket() {
101        try {
102            if (mServerSocket != null) {
103                FileDescriptor fd = mServerSocket.getFileDescriptor();
104                mServerSocket.close();
105                if (fd != null) {
106                    Os.close(fd);
107                }
108            }
109        } catch (IOException ex) {
110            Log.e(TAG, "Zygote:  error closing sockets", ex);
111        } catch (ErrnoException ex) {
112            Log.e(TAG, "Zygote:  error closing descriptor", ex);
113        }
114
115        mServerSocket = null;
116    }

3.System启动过程

System进程是在ZygoteInit类的静态成员函数handleSystemServerProcess中开始启动的

          

 1.ZygoteInit.handleSystemServerProcess

代码路径:/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

    (http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java)

593    private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)
594            throws Zygote.MethodAndArgsCaller, RuntimeException {
        ..........................................................
643
644        /* For child process */
645        if (pid == 0) {
646            if (hasSecondZygote(abiList)) {
647                waitForSecondaryZygote(socketName);
648            }
649
650            zygoteServer.closeServerSocket();
651            handleSystemServerProcess(parsedArgs);
652        }
653
654        return true;
655    }
 
  
 
  
446    /**
447     * Finish remaining work for the newly forked system server process.
448     */
449    private static void handleSystemServerProcess(
450            ZygoteConnection.Arguments parsedArgs)
451            throws Zygote.MethodAndArgsCaller {
452
453        // set umask to 0077 so new files and directories will default to owner-only permissions.
454        Os.umask(S_IRWXG | S_IRWXO);
455
456        if (parsedArgs.niceName != null) {
457            Process.setArgV0(parsedArgs.niceName);
458        }
459
460        final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
461        if (systemServerClasspath != null) {
462            performSystemServerDexOpt(systemServerClasspath);
463            // Capturing profiles is only supported for debug or eng builds since selinux normally
464            // prevents it.
465            boolean profileSystemServer = SystemProperties.getBoolean(
466                    "dalvik.vm.profilesystemserver", false);
467            if (profileSystemServer && (Build.IS_USERDEBUG || Build.IS_ENG)) {
468                try {
469                    File profileDir = Environment.getDataProfilesDePackageDirectory(
470                            Process.SYSTEM_UID, "system_server");
471                    File profile = new File(profileDir, "primary.prof");
472                    profile.getParentFile().mkdirs();
473                    profile.createNewFile();
474                    String[] codePaths = systemServerClasspath.split(":");
475                    VMRuntime.registerAppInfo(profile.getPath(), codePaths);
476                } catch (Exception e) {
477                    Log.wtf(TAG, "Failed to set up system server profile", e);
478                }
479            }
480        }
481
482        if (parsedArgs.invokeWith != null) {
483            String[] args = parsedArgs.remainingArgs;
484            // If we have a non-null system server class path, we'll have to duplicate the
485            // existing arguments and append the classpath to it. ART will handle the classpath
486            // correctly when we exec a new process.
487            if (systemServerClasspath != null) {
488                String[] amendedArgs = new String[args.length + 2];
489                amendedArgs[0] = "-cp";
490                amendedArgs[1] = systemServerClasspath;
491                System.arraycopy(args, 0, amendedArgs, 2, args.length);
492                args = amendedArgs;
493            }
494
495            WrapperInit.execApplication(parsedArgs.invokeWith,
496                    parsedArgs.niceName, parsedArgs.targetSdkVersion,
497                    VMRuntime.getCurrentInstructionSet(), null, args);
498        } else {
499            ClassLoader cl = null;
500            if (systemServerClasspath != null) {
501                cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);
502
503                Thread.currentThread().setContextClassLoader(cl);
504            }
505
506            /*
507             * Pass the remaining arguments to SystemServer.
508             */
509            ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
510        }
511
512        /* should never reach here */
513    }
 
  
System进程不需要使用这个Socket,因此,会调用zygoteServer类的静态成员函数closeServerSocket来关闭它。由于System进程复制了Zygote进程的地址空间,因此,它就会获得Zygote进程在启动过程中所创建的Socket。接下来调用ZygoteInit.zygoteInit,在ZygoteInit.zygoteInit中RuntimeInit类的静态成员函数zygoteInit来进一步启动System进程 
  


2.ZygoteInit.zygoteInit

代码路径:/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

 (http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java)

创建的系统服务剩余的工作,最后调用ZygoteInit.zygoteInit将剩余的参数传递到系统服务
829    public static final void zygoteInit(int targetSdkVersion, String[] argv,
830            ClassLoader classLoader) throws Zygote.MethodAndArgsCaller {
831        if (RuntimeInit.DEBUG) {
832            Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
833        }
834
835        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
836        RuntimeInit.redirectLogStreams();//将System.out和System.err重定向到Android日志
837
838        RuntimeInit.commonInit();
839        ZygoteInit.nativeZygoteInit();
840        RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
841    }

3.RuntimeInit.applicationInit

代码路径:/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
 (http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java)

nativeZygoteInit()用于进程间通信的初始化操作,applicationInit函数用于服务的启动

289    protected static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
290            throws Zygote.MethodAndArgsCaller {
291        // If the application calls System.exit(), terminate the process
292        // immediately without running any shutdown hooks.  It is not possible to
293        // shutdown an Android application gracefully.  Among other things, the
294        // Android runtime shutdown hooks close the Binder driver, which can cause
295        // leftover running threads to crash before the process actually exits.
296        nativeSetExitWithoutCleanup(true);
297
298        // We want to be fairly aggressive about heap utilization, to avoid
299        // holding on to a lot of memory that isn't needed.
300        VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
301        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
302
303        final Arguments args;
304        try {
305            args = new Arguments(argv);
306        } catch (IllegalArgumentException ex) {
307            Slog.e(TAG, ex.getMessage());
308            // let the process exit
309            return;
310        }
311
312        // The end of of the RuntimeInit event (see #zygoteInit).
313        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
314
315        // Remaining arguments are passed to the start class's static main
316        invokeStaticMain(args.startClass, args.startArgs, classLoader);
317    }

该函数主要是一些运行时的一些工作,同时调用invokeStaticMain来进行main函数的执行,看这个方法的注释,意思便是剩下的参数被传递,用于启动类的静态main函数。这里传递的类参数便是SystemServer类,所以这个函数的工作便是启动SystemServer的main函数

4.SystemServer.main

代码路径:/frameworks/base/services/java/com/android/server/SystemServer.java

 (http://androidxref.com/8.0.0_r4/xref/frameworks/base/services/java/com/android/server/SystemServer.java)

该函数位于frameworks/base/services/java/com/android/server/SystemServer.java类中,这里运行SystemServer的run函数,该函数设置环境变量,启动其他服务,

257     * The main entry point from zygote.
258     */
259    public static void main(String[] args) {
260        new SystemServer().run();
261    }
接着返回到ZygoteInit.java的main函数中,这个函数最后执行runSelectLoop函数,这里运行一个循环,接收新的连接,读取来自连接的命令


参考:

http://blog.csdn.net/gaugamela/article/details/52133186

https://www.jianshu.com/p/88e3a64d3a3e


你可能感兴趣的:(Android代码经验)