4412运行java_Tiny4412 Android 启动流程

Android系统的启动主要包括三个阶段:

①BootLoader启动

②Linux Kernel启动

③Android系统启动

b16d9490eca1516aa77882c6fc908a73.png

前面我们大致分析了前面两个步骤,即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进程间通信的重要的守护进程

a836b5d0b78416c5af36569011363e5d.png

这个先放一下,之后学习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);//下面还有很多,具体用到哪些东西的时候再回过头来分析

....

再往下就是开机进入锁屏界面了,这部分内容还不熟悉,之后再分析。。。。。-_-!!!

多谢下面两位前辈的无私分享

参考文章:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值