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 BOOTCHARTqueue_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;
}
}#endifnr=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 voidrestart_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
voidservice_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, structservice, 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:=: 当属性值满足条件时触发;
②Commands(命令)
下面列举常用的命令
class_start : 启动属于同一个class的所有服务;
start : 启动指定的服务,若已启动则跳过;
stop : 停止正在运行的服务;
setprop :设置属性值;
mkdir :创建指定目录;
symlink : 创建连接到的符号链接;
write : 向文件path中写入字符串;
exec: fork并执行,会阻塞init进程直到程序完毕;
exprot :设定环境变量;
loglevel :设置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/的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 stream0666logd logd
socket logdr seqpacket0666logd logd
socket logdw dgram0222logd logd
seclabel u:r:logd:s0
service healthd/sbin/healthd
class core
critical
seclabel u:r:healthd:s0
service console/system/bin/shclass core
console
disabled
user shell
group shell log
seclabel u:r:shell:s0
on property:ro.debuggable=1start console
# adbd is controlled via property triggersin init..usb.rc
service adbd/sbin/adbd --root_seclabel=u:r:su:s0
class core
socket adbd stream660system system
disabled
seclabel u:r:adbd:s0
# adbd on at bootinemulator
on property:ro.kernel.qemu=1start adbd
service lmkd/system/bin/lmkd
class core
critical
socket lmkd seqpacket0660system 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 stream0660 root mountioprio be2service netd/system/bin/netd
class main
socket netd stream0660root system
socket dnsproxyd stream0660root inet
socket mdns stream0660root system
socket fwmarkd stream0660root inet
service debuggerd/system/bin/debuggerd
class main
#forZTE 3G
service ril-daemon /system/bin/rild -l /system/lib/libzte-ril.so -- -d /dev/ttyUSB1 -u /dev/ttyUSB3
class main
socket rild stream660root radio
socket rild-debug stream 660radio system
user root
group radio cache inet misc audio sdcard_r sdcard_rw log net_admin net_raw
on property:ril.reset.rild=1stop ril-daemon
start ril-daemon
setprop ril.reset.rild0service 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 rt4# One shot invocation to deal with encrypted volume.
service defaultcrypto/system/bin/vdc --waitcryptfs 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 --waitcryptfs 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 stream600system system
service flash_recovery/system/bin/install-recovery.shclass main
seclabel u:r:install_recovery:s0
oneshot
service racoon/system/bin/racoon
class main
socket racoon stream600system system
# IKE uses UDP port500. 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 stream600system 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 stream0660shell log
disabled
oneshot
service mdnsd/system/bin/mdnsd
class main
user mdnsr
group inet net_raw
socket mdnsd stream0660mdnsr 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 stream660root system
onrestartwrite /sys/android_power/request_state wake
onrestartwrite /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* constargv[])
{
....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&options)
{
ALOGD("\n>>>>>> AndroidRuntime START %s <<<<<
....//启动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 voidmain(String argv[]) {
....
registerZygoteSocket(socketName);//注册socket
....if(startSystemServer) {//启动SystemServer
startSystemServer(abiList, socketName);
}
....
}
systemserver启动了一票的Java层服务
//frameworks/base/services/java/com/android/server/SystemServer.java
public static voidmain(String[] args) {//new一个SystemServer对象并调用其run函数
newSystemServer().run();
}private voidrun() {
....//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);throwex;
}
下面看一下这些系统服务的启动过程,注释很详细
private voidstartBootstrapServices() {//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 voidstartCoreServices() {//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 voidstartOtherServices() {
....
Slog.i(TAG,"Reading configuration...");
SystemConfig.getInstance();
Slog.i(TAG,"Scheduling Policy");
ServiceManager.addService("scheduling_policy", newSchedulingPolicyService());
Slog.i(TAG,"Telephony Registry");
telephonyRegistry= newTelephonyRegistry(context);
ServiceManager.addService("telephony.registry", telephonyRegistry);
Slog.i(TAG,"Entropy Mixer");
ServiceManager.addService("entropy", newEntropyMixer(context));
Slog.i(TAG,"Account Manager");
accountManager= newAccountManagerService(context);
ServiceManager.addService(Context.ACCOUNT_SERVICE, accountManager);//下面还有很多,具体用到哪些东西的时候再回过头来分析
....
再往下就是开机进入锁屏界面了,这部分内容还不熟悉,之后再分析。。。。。-_-!!!
多谢下面两位前辈的无私分享
参考文章: