首页 > 代码库 > Tiny4412 Android 启动流程
Tiny4412 Android 启动流程
Android系统的启动主要包括三个阶段:
①BootLoader启动
②Linux Kernel启动
③Android系统启动
前面我们大致分析了前面两个步骤,即u-boot和内核的启动流程(内核启动流程待完善-_-!!),这次就来分析以下Linux内核启动之后是怎样挂载起Android这个“根文件系统”的。Android系统在Linux内核上运行了一系列的系统服务。
和Linux系统类似,Android系统中第一个被启动的进程也是init进程,它的PID为0。Android系统的init进程启动的过程中会解析init.rc文件,以此来构建出系统的初始运行形态。其他Android系统服务,比如装载Android的文件系统、创建系统目录、初始化属性系统、启动Android系统重要的守护进程,这些进程包括USB守护进程,adb守护进程,vold守护进程,rild守护进程、mediaserver和ServiceManager等,大多都是在这个脚本中被相继启动的。
init进程启动后会执行system/core/init/init.c 中的 main 函数,并且在main函数中调用init_parse_config_file函数来解析init.rc脚本。下面就分析以下这个main函数究竟做了那些事。
// system/core/init/init.c int main(int argc, char **argv) { .... //对umask进行清零 umask(0); //为rootfs建立必要的文件夹,并挂载适当的分区 mkdir("/dev", 0755); mkdir("/proc", 0755); mkdir("/sys", 0755); mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"); mkdir("/dev/pts", 0755); mkdir("/dev/socket", 0755); mount("devpts", "/dev/pts", "devpts", 0, NULL); mount("proc", "/proc", "proc", 0, NULL); mount("sysfs", "/sys", "sysfs", 0, NULL); /* indicate that booting is in progress to background fw loaders, etc */ close(open("/dev/.booting", O_WRONLY | O_CREAT, 0000)); //调用dup函数把标准输入,输出,错误输出都重定位到/dev/__null__ open_devnull_stdio(); //初始化kernel log,创建/dev/kmsg设备节点 klog_init(); //属性初始化,读取default.prop property_init(); //获取硬件信息/proc/cpuinfo get_hardware_name(hardware, &revision); //获取命linux内核传来命令行信息 process_kernel_cmdline(); union selinux_callback cb; cb.func_log = log_callback; selinux_set_callback(SELINUX_CB_LOG, cb); cb.func_audit = audit_callback; selinux_set_callback(SELINUX_CB_AUDIT, cb); selinux_initialize(); /* 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. */ restorecon("/dev"); restorecon("/dev/socket"); restorecon("/dev/__properties__"); restorecon_recursive("/sys"); is_charger = !strcmp(bootmode, "charger"); INFO("property init\n"); property_load_boot_defaults(); INFO("reading config file\n"); ///解析init.rc脚本 init_parse_config_file("/init.rc"); //执行rc文件中触发器为 on early-init的语句 action_for_each_trigger("early-init", action_add_queue_tail); /* 解析完init.rc配置文件后,会得到一系列的Action,action_for_each_trigger函数用来执行early-init阶段的Action。 init将动作执行的时间划分为4个阶段:early-init、init、early-boot、boot。由于有些动作必须要在其他动作完成后才能执行, 所以就有了先后之分。哪些动作属于哪个阶段由配置文件决定。 */ queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done"); queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng"); queue_builtin_action(keychord_init_action, "keychord_init"); queue_builtin_action(console_init_action, "console_init"); // 执行init阶段的动作 /* execute all the boot actions to get us started */ action_for_each_trigger("init", action_add_queue_tail); /* Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random * wasn‘t ready immediately after wait_for_coldboot_done */ queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng"); queue_builtin_action(property_service_init_action, "property_service_init"); queue_builtin_action(signal_init_action, "signal_init"); /* Don‘t mount filesystems or start core system services if in charger mode. */ if (is_charger) { action_for_each_trigger("charger", action_add_queue_tail); } else { action_for_each_trigger("late-init", action_add_queue_tail); } /* run all property triggers based on current state of the properties */ queue_builtin_action(queue_property_triggers_action, "queue_property_triggers"); #if BOOTCHART queue_builtin_action(bootchart_init_action, "bootchart_init"); #endif // 无限循环,用来处理各种消息 for(;;) { int nr, i, timeout = -1; execute_one_command(); // 重启那些已经死去的进程,启动所有init脚本中声明的service restart_processes(); // 用来监听属性设置服务的事件 if (!property_set_fd_init && get_property_set_fd() > 0) { ufds[fd_count].fd = get_property_set_fd(); ufds[fd_count].events = POLLIN; ufds[fd_count].revents = 0; fd_count++; property_set_fd_init = 1; } if (!signal_fd_init && get_signal_fd() > 0) { ufds[fd_count].fd = get_signal_fd(); ufds[fd_count].events = POLLIN; ufds[fd_count].revents = 0; fd_count++; signal_fd_init = 1; } if (!keychord_fd_init && get_keychord_fd() > 0) { ufds[fd_count].fd = get_keychord_fd(); ufds[fd_count].events = POLLIN; ufds[fd_count].revents = 0; fd_count++; keychord_fd_init = 1; } if (process_needs_restart) { timeout = (process_needs_restart - gettime()) * 1000; if (timeout < 0) timeout = 0; } if (!action_queue_empty() || cur_action) timeout = 0; #if BOOTCHART if (bootchart_count > 0) { if (timeout < 0 || timeout > BOOTCHART_POLLING_MS) timeout = BOOTCHART_POLLING_MS; if (bootchart_step() < 0 || --bootchart_count == 0) { bootchart_finish(); bootchart_count = 0; } } #endif nr = poll(ufds, fd_count, timeout); if (nr <= 0) continue; // 处理具体的消息 for (i = 0; i < fd_count; i++) { if (ufds[i].revents & POLLIN) { if (ufds[i].fd == get_property_set_fd()) handle_property_set_fd(); else if (ufds[i].fd == get_keychord_fd()) handle_keychord(); else if (ufds[i].fd == get_signal_fd()) handle_signal(); } } } return 0; }
在 restart_processes 函数中回去解析init.rc中的Service标号,启动Service
//system/core/init/init.c static void restart_processes() { process_needs_restart = 0; //调用service_for_each_flags service_for_each_flags(SVC_RESTARTING, restart_service_if_needed); }
在restart_processes调用了 service_for_each_flags
// system/core/init/init_parser.c void service_for_each_flags(unsigned matchflags, void (*func)(struct service *svc)) { struct listnode *node; struct service *svc; //遍历service_list链表里的每一个节点 list_for_each(node, &service_list) { svc = node_to_item(node, struct service, slist); if (svc->flags & matchflags) { //调用传进来的func函数处理svc func(svc); } } }
所以最终我们是调用了 restart_service_if_needed 来处理 SVC_RESTARTING链表里的每一个service节点。看一下这个restart_service_if_needed函数
static void restart_service_if_needed(struct service *svc) { time_t next_start_time = svc->time_started + 5; if (next_start_time <= gettime()) { svc->flags &= (~SVC_RESTARTING); //启动service service_start(svc, NULL); return; } if ((next_start_time < process_needs_restart) || (process_needs_restart == 0)) { process_needs_restart = next_start_time; } }
接着分析一下这个service_start函数
// system/core/init/init.c void service_start(struct service *svc, const char *dynamic_args) { .... NOTICE("starting ‘%s‘\n", svc->name); //创建一个子线程,启动service pid = fork(); .... }
init.rc语法
以行尾单位,以空格间隔的语法,以#开始代表注释行。rc文件主要包含Action、Service、Command、Options,其中对于Action和Service的名称都是唯一的,对于重复的命名视为无效。在android 5.0.2源码system/core/init/readme.txt中有init.rc语法的帮助文档。
①Action(动作)
Action: 通过trigger,即以 on开头的语句,决定何时执行相应的service。
on early-init; 在初始化早期阶段触发;
on init; 在初始化阶段触发;
on late-init; 在初始化晚期阶段触发;
on boot/charger: 当系统启动/充电时触发,还包含其他情况,此处不一一列举;
on property:<key>=<value>: 当属性值满足条件时触发;
②Commands(命令)
下面列举常用的命令
class_start <service_class_name>: 启动属于同一个class的所有服务;
start <service_name>: 启动指定的服务,若已启动则跳过;
stop <service_name>: 停止正在运行的服务;
setprop <name> <value>:设置属性值;
mkdir <path>:创建指定目录;
symlink <target> <sym_link>: 创建连接到<target>的<sym_link>符号链接;
write <path> <string>: 向文件path中写入字符串;
exec: fork并执行,会阻塞init进程直到程序完毕;
exprot <name> <name>:设定环境变量;
loglevel <level>:设置log级别;
③Service(服务)
服务Service,以 service开头,由init进程启动,一般运行于另外一个init的子进程,所以启动service前需要判断对应的可执行文件是否存在。init生成的子进程,定义在rc文件,其中每一个service,在启动时会通过fork方式生成子进程。
例如: service servicemanager /system/bin/servicemanager代表的是服务名为servicemanager,服务的路径,也就是服务执行操作时运行/system/bin/servicemanager。
④Options(选项)
Options是Services的可选项,与service配合使用
disabled: 不随class自动启动,只有根据service名才启动;
oneshot: service退出后不再重启;
user/group: 设置执行服务的用户/用户组,默认都是root;
class:设置所属的类名,当所属类启动/退出时,服务也启动/停止,默认为default;
onrestart:当服务重启时执行相应命令;
socket: 创建名为/dev/socket/<name>的socket
critical: 在规定时间内该service不断重启,则系统会重启并进入恢复模式
default: 意味着disabled=false,oneshot=false,critical=false。
所有的Service里面只有servicemanager ,zygote ,surfaceflinger这3个service有onrestart关键字来触发其他service启动过程。
系统启动流程
本地系统服务:在init.rc初始化一个server入口,然后通过这个server去启动其他service,比如mediaserver
Java系统服务启动:
1):init启动service manager,这个进程主要负责系统服务的注册管理,包括“java系统服务”“本地系统服务”
2):init启动Media server,这个进程负责启动C/C++的“本地系统服务”。
3):init启动Zygote,这个进程启动System server进程,这个进程启动"Java系统服务"---[包括power manager service,sensor service]
4):另外init启动system/bin下面的各种守护进程
首先看一下init.rc里面是如何启动这些系统服务的
## Daemon processes to be run by init. ## service ueventd /sbin/ueventd class core critical seclabel u:r:ueventd:s0 service logd /system/bin/logd class core socket logd stream 0666 logd logd socket logdr seqpacket 0666 logd logd socket logdw dgram 0222 logd logd seclabel u:r:logd:s0 service healthd /sbin/healthd class core critical seclabel u:r:healthd:s0 service console /system/bin/sh class core console disabled user shell group shell log seclabel u:r:shell:s0 on property:ro.debuggable=1 start console # adbd is controlled via property triggers in init.<platform>.usb.rc service adbd /sbin/adbd --root_seclabel=u:r:su:s0 class core socket adbd stream 660 system system disabled seclabel u:r:adbd:s0 # adbd on at boot in emulator on property:ro.kernel.qemu=1 start adbd service lmkd /system/bin/lmkd class core critical socket lmkd seqpacket 0660 system system service servicemanager /system/bin/servicemanager class core user system group system critical onrestart restart healthd onrestart restart zygote onrestart restart media onrestart restart surfaceflinger onrestart restart drm service vold /system/bin/vold class core socket vold stream 0660 root mount ioprio be 2 service netd /system/bin/netd class main socket netd stream 0660 root system socket dnsproxyd stream 0660 root inet socket mdns stream 0660 root system socket fwmarkd stream 0660 root inet service debuggerd /system/bin/debuggerd class main # for ZTE 3G service ril-daemon /system/bin/rild -l /system/lib/libzte-ril.so -- -d /dev/ttyUSB1 -u /dev/ttyUSB3 class main socket rild stream 660 root radio socket rild-debug stream 660 radio system user root group radio cache inet misc audio sdcard_r sdcard_rw log net_admin net_raw on property:ril.reset.rild=1 stop ril-daemon start ril-daemon setprop ril.reset.rild 0 service pppd_gprs /system/etc/ppp/init.gprs-pppd user root group radio cache inet misc log net_admin net_raw disabled oneshot service surfaceflinger /system/bin/surfaceflinger class core user system group graphics drmrpc #重启时会触发zygote重启 onrestart restart zygote service drm /system/bin/drmserver class main user drm group drm system inet drmrpc service media /system/bin/mediaserver class main user media group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm ioprio rt 4 # One shot invocation to deal with encrypted volume. service defaultcrypto /system/bin/vdc --wait cryptfs mountdefaultencrypted disabled oneshot # vold will set vold.decrypt to trigger_restart_framework (default # encryption) or trigger_restart_min_framework (other encryption) # One shot invocation to encrypt unencrypted volumes service encrypt /system/bin/vdc --wait cryptfs enablecrypto inplace default disabled oneshot # vold will set vold.decrypt to trigger_restart_framework (default # encryption) service bootanim /system/bin/bootanimation class core user graphics group graphics audio disabled oneshot service installd /system/bin/installd class main socket installd stream 600 system system service flash_recovery /system/bin/install-recovery.sh class main seclabel u:r:install_recovery:s0 oneshot service racoon /system/bin/racoon class main socket racoon stream 600 system system # IKE uses UDP port 500. Racoon will setuid to vpn after binding the port. group vpn net_admin inet disabled oneshot service mtpd /system/bin/mtpd class main socket mtpd stream 600 system system user vpn group vpn net_admin inet net_raw disabled oneshot service keystore /system/bin/keystore /data/misc/keystore class main user keystore group keystore drmrpc service dumpstate /system/bin/dumpstate -s class main socket dumpstate stream 0660 shell log disabled oneshot service mdnsd /system/bin/mdnsd class main user mdnsr group inet net_raw socket mdnsd stream 0660 mdnsr inet disabled oneshot service pre-recovery /system/bin/uncrypt class main disabled oneshot
init进程通过init.rc脚本启动servicemanager
service servicemanager /system/bin/servicemanager
class core
user system
group system
critical
#重启时会触发下列进程重启
onrestart restart healthd
onrestart restart zygote
onrestart restart media
onrestart restart surfaceflinger
onrestart restart drm
个servicemanager是Android系统Binder进程间通信的重要的守护进程
这个先放一下,之后学习Binder系统的时候再深入分析。
init进程又启动了zygote进程
init.rc脚本在开是引入了zygote的启动脚本
import /init.${ro.zygote}.rc
#system/core/rootdir/init.zygote32.rc service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server class main socket zygote stream 660 root system onrestart write /sys/android_power/request_state wake onrestart write /sys/power/state on onrestart restart media onrestart restart netd
zygote进程是java环境的入口
// frameworks/base/cmds/app_process/app_main.cpp int main(int argc, char* const argv[]) { .... if (!niceName.isEmpty()) { runtime.setArgv0(niceName.string()); set_process_name(niceName.string()); } if (zygote) { //启动zygote进程 runtime.start("com.android.internal.os.ZygoteInit", args); } else if (className) { runtime.start("com.android.internal.os.RuntimeInit", args); } else { fprintf(stderr, "Error: no class name or --zygote supplied.\n"); app_usage(); LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied."); return 10; } }
看一下系统是怎样进入java环境的
// frameworks/base/core/jni/AndroidRuntime.cpp void AndroidRuntime::start(const char* className, const Vector<String8>& options) { ALOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n", .... //启动systemserver static const String8 startSystemServer("start-system-server"); .... //启动java进程 char* slashClassName = toSlashClassName(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); .... }
接着就是启动systemserver了,它是由zygote启动的
// frameworks/base/core/java/com/android/internal/os/ZygoteInit.java public static void main(String argv[]) { .... registerZygoteSocket(socketName);//注册socket .... if (startSystemServer) { //启动SystemServer startSystemServer(abiList, socketName); } .... }
systemserver启动了一票的Java层服务
//frameworks/base/services/java/com/android/server/SystemServer.java public static void main(String[] args) { //new一个SystemServer对象并调用其run函数 new SystemServer().run(); } private void run() { .... // Here we go! Slog.i(TAG, "Entered the Android system server!"); EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis()); .... // Initialize native services. //加载本地库并初始化 System.loadLibrary("android_servers"); nativeInit(); .... // Start services. //启动一票的Java层系统服务 try { startBootstrapServices(); startCoreServices(); startOtherServices(); } catch (Throwable ex) { Slog.e("System", "******************************************"); Slog.e("System", "************ Failure starting system services", ex); throw ex; }
下面看一下这些系统服务的启动过程,注释很详细
private void startBootstrapServices() { // Wait for installd to finish starting up so that it has a chance to // create critical directories such as /data/user with the appropriate // permissions. We need this to complete before we initialize other services. mInstaller = mSystemServiceManager.startService(Installer.class); // Activity manager runs the show. mActivityManagerService = mSystemServiceManager.startService( ActivityManagerService.Lifecycle.class).getService(); mActivityManagerService.setSystemServiceManager(mSystemServiceManager); // Power manager needs to be started early because other services need it. // Native daemons may be watching for it to be registered so it must be ready // to handle incoming binder calls immediately (including being able to verify // the permissions for those calls). mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class); // Now that the power manager has been started, let the activity manager // initialize power management features. mActivityManagerService.initPowerManagement(); // Display manager is needed to provide display metrics before package manager // starts up. mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class); // We need the default display before we can initialize the package manager. mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY); // Only run "core" apps if we‘re encrypting the device. String cryptState = SystemProperties.get("vold.decrypt"); if (ENCRYPTING_STATE.equals(cryptState)) { Slog.w(TAG, "Detected encryption in progress - only parsing core apps"); mOnlyCore = true; } else if (ENCRYPTED_STATE.equals(cryptState)) { Slog.w(TAG, "Device encrypted - only parsing core apps"); mOnlyCore = true; } // Start the package manager. Slog.i(TAG, "Package Manager"); mPackageManagerService = PackageManagerService.main(mSystemContext, mInstaller, mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore); mFirstBoot = mPackageManagerService.isFirstBoot(); mPackageManager = mSystemContext.getPackageManager(); Slog.i(TAG, "User Service"); ServiceManager.addService(Context.USER_SERVICE, UserManagerService.getInstance()); // Initialize attribute cache used to cache resources from packages. AttributeCache.init(mSystemContext); // Set up the Application instance for the system process and get started. mActivityManagerService.setSystemProcess(); }
private void startCoreServices() { // Manages LEDs and display backlight. mSystemServiceManager.startService(LightsService.class); // Tracks the battery level. Requires LightService. mSystemServiceManager.startService(BatteryService.class); // Tracks application usage stats. mSystemServiceManager.startService(UsageStatsService.class); mActivityManagerService.setUsageStatsManager( LocalServices.getService(UsageStatsManagerInternal.class)); // Tracks whether the updatable WebView is in a ready state and watches for update installs. mSystemServiceManager.startService(WebViewUpdateService.class); }
private void startOtherServices() { .... Slog.i(TAG, "Reading configuration..."); SystemConfig.getInstance(); Slog.i(TAG, "Scheduling Policy"); ServiceManager.addService("scheduling_policy", new SchedulingPolicyService()); Slog.i(TAG, "Telephony Registry"); telephonyRegistry = new TelephonyRegistry(context); ServiceManager.addService("telephony.registry", telephonyRegistry); Slog.i(TAG, "Entropy Mixer"); ServiceManager.addService("entropy", new EntropyMixer(context)); Slog.i(TAG, "Account Manager"); accountManager = new AccountManagerService(context); ServiceManager.addService(Context.ACCOUNT_SERVICE, accountManager); //下面还有很多,具体用到哪些东西的时候再回过头来分析 ....
再往下就是开机进入锁屏界面了,这部分内容还不熟悉,之后再分析。。。。。-_-!!!
多谢下面两位前辈的无私分享
参考文章:
http://gityuan.com/
http://blog.csdn.net/hovan/article/details/9896751
Tiny4412 Android 启动流程