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. if (is_first_stage) { // (3)创建一些基本的目录;同时把一些文件系统Mount到相应的目录。 mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");//基于内存的文件系统 mkdir("/dev/pts", 0755); mkdir("/dev/socket", 0755); mount("devpts", "/dev/pts", "devpts", 0, NULL);//虚拟终端文件系统 #define MAKE_STR(x) __STRING(x) mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC));//基于内存的虚拟文件系统,内部数据结构的接口 mount("sysfs", "/sys", "sysfs", 0, NULL);//用于把系统的设备和总线按层次组织起来 } // We must have some place other than / to create the device nodes for // kmsg and null, otherwise we won't be able to remount / read-only // later on. Now that tmpfs is mounted on /dev, we can actually talk // to the outside world. // (4)把标准输入、标准输出和标准错误重定向到空设备文件/dev/_null_ open_devnull_stdio(); // (5)创建节点/dev/_msg_,这样init进程可以使用kernel的log系统来输出log klog_init(); klog_set_level(KLOG_NOTICE_LEVEL);
NOTICE("init %s started!
", is_first_stage ? "first stage" : "second stage"); if (!is_first_stage) { // (6)在/dev目录下创建一个空文件.booting表示初始化正在进行,is_booting函数将依 // 靠.booting来判断进程是否处于初始化中 // Indicate that booting is in progress to background fw loaders, etc. close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000)); // (7)初始化Android属性系统。创建一个共享区域来存储属性值。 property_init();
// If arguments are passed both on the command line and in DT, // properties set in DT always have priority over the command-line ones. process_kernel_dt(); // (8)解析kernel的启动参数,通常放在/proc/cmdline中,利用解析结果参数中的值设置几个属性值 process_kernel_cmdline();
// Propagate the kernel variables to internal variables // used by init as well as the current required properties. export_kernel_boot_props(); } // Set up SELinux, including loading the SELinux policy if we're in the kernel domain. // (9)初始化SElinux selinux_initialize(is_first_stage);
// If we're in the kernel domain, re-exec init to transition to the init domain now // that the SELinux policy has been loaded. if (is_first_stage) { if (restorecon("/init") == -1) {//按SELinux要求,重新设定/init文件属性 ERROR("restorecon failed: %s
", strerror(errno)); security_failure(); } char* path = argv[0]; char* args[] = { path, const_cast("--second-stage"), nullptr };//设置参数--second-stage if (execv(path, args) == -1) {// 执行init进程,重新进入main函数 ERROR("execv("%s") failed: %s
", path, strerror(errno)); security_failure(); } }
// These directories were necessarily created before initial policy load // and therefore need their security context restored to the proper value. // This must happen before /dev is populated by ueventd. // 这些目录必须在初始策略加载之前创建,因此需要将其安全上下文恢复到适当的值。 这必须在/ dev由ueventd填充之前发生。 NOTICE("Running restorecon...
"); restorecon("/dev"); restorecon("/dev/socket"); restorecon("/dev/__properties__"); restorecon("/property_contexts"); restorecon_recursive("/sys");
// 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");//从硬件RNG的设备文件/dev/hw_random中读取512字节并写到Linux RNG的设备文件/dev/urandom中。 am.QueueBuiltinAction(set_mmap_rnd_bits_action, "set_mmap_rnd_bits"); am.QueueBuiltinAction(keychord_init_action, "keychord_init");//初始化组合键监听模块 am.QueueBuiltinAction(console_init_action, "console_init");//在屏幕上显示Android字样的logo
// Trigger all the boot actions to get us started. am.QueueEventTrigger("init");// 添加触发器init,执行on init内容,主要包括创建/挂载一些目录,以及symlink等
// Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random // wasn't ready immediately after wait_for_coldboot_done am.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");//重复以防冷插拔设备初始化后/dev/hw_random或者/dev/random未就绪
// Don't mount filesystems or start core system services in charger mode. std::string bootmode = property_get("ro.bootmode"); if (bootmode == "charger") {// 判断是否为充电模式 am.QueueEventTrigger("charger"); } else { am.QueueEventTrigger("late-init");// 非充电模式添加触发器late-init }
// Run all property triggers based on current state of the properties. am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");//检查Action列表中通过修改属性来触发的Action,查看相关的属性值是否已经设置,如果已经设置,则将该Action加入到执行列表中。
/* 360OS begin */ get_cpu_id(); /* 360OS end */ // (15)处理添加到运行队列中的事件 while (true) { if (!waiting_for_exec) { am.ExecuteOneCommand();//依次执行每个action中携带的命令 restart_processes();//重启一些挂掉的进程 }
int timeout = -1; if (process_needs_restart) {//还有服务进程需要重启 timeout = (process_needs_restart - gettime()) * 1000;//把timeout值设为下次启动服务的时间 if (timeout < 0) timeout = 0; }
if (am.HasMoreCommands()) {//命令列表中还有命令 timeout = 0; }
bootchart_sample(&timeout);
epoll_event ev; int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, timeout)); if (nr == -1) { ERROR("epoll_wait failed: %s
", strerror(errno)); } else if (nr == 1) { ((void (*)()) ev.data.ptr)(); } }
return 0; }
2、解析init.rc init.cpp的main函数中,(13)步对init.rc做了解析,这是我们比较关注的东西。 init.rc(/system/core/rootdir/init.rc)是什么? init.rc是一个配置文件,内部由Android初始化语言编写(Android Init Language)编写的脚本,在Android中有特定的格式以及规则。 Android初始化语言由四大类型的声明组成,即Actions(动作)、Commands(命令)、Services(服务)、以及Options(选项)。所有这些都以行为单位,各种符号则用空格隔开。 1)init.rc(/system/core/rootdir/init.rc): import /init.environ.rc import /init.usb.rc import /init.${ro.hardware}.rc import /init.usb.configfs.rc import /init.${ro.zygote}.rc ... 导入一些配置文件,zygote的.rc文件有多个。主要就是来区分不同的平台(32、64及64_32)。 init.rc文件进行了拆分,每个服务一个rc文件。 2)init.rc(/system/core/rootdir/init.rc): ... on early-init # Set init and its forked children's oom_adj. write /proc/1/oom_score_adj -1000
# Disable sysrq from keyboard write /proc/sys/kernel/sysrq 0
# Set the security context of /adb_keys if present. restorecon /adb_keys
# Shouldn't be necessary, but sdcard won't start without it. http://b/22568628. mkdir /mnt 0775 root system
# Set the security context of /postinstall if present. restorecon /postinstall
start ueventd ... on early-init为action类型语句,其一般格式为: on [&& ]* //设置触发器 //动作触发之后要执行的命令 3)init.zygote64.rc(/system/core/rootdir/init.zygote64.rc): service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server class main socket zygote stream 660 root system onrestart write /sys/android_power/request_state wake onrestart write /sys/power/state on onrestart restart audioserver onrestart restart cameraserver onrestart restart media onrestart restart netd writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks service zygote ...为service类型语句,其一般格式为: service [ ]* //<执行程序路径><传递参数>