Android系统启动


以前对于Android系统源码这一块并没有系统的学习,现在利用空闲时间对其进行重新学习和归纳,如有问题请斧正,感谢!

一、 init进程启动过程

init进程是Android系统中用户空间的第一个进程,进程号是1,是Android系统启动流程中一个关键的步骤,作为第一个进程 ,它被赋予了很多极其重要的工作职责,比如创建Zygote(孵化器)和属性服务等。init进程是由多个源文件共同组成的,这些文件源码目录system/core/init中。

1、引入init进程

1.1、启动电源以及系统启动

当电源 按下时引导芯片代码从预定义的地方(ROM)开始执行。加载引导程序BootLoader到RAM中,然后执行。

1.2、引导程序BootLoader

引导程序BootLoader是在Android操作系统开始运行前的一个程序,它的主要作用是吧系统OS拉起来并运行。

1.3、Linux内核启动

当内核启动时,设置缓存、被保护存储器、计划列表、加载驱动。在内核完成系统设置后。它首先在系统文件中寻找init.rc文件,并启动init进程。

1.4、init进程启动

init进程做的工作比较多,主要用来初始化和启动属性服务,也用来启动Zygote进程 。

2、init进程的入口函数

在Linux内核加载完成后,它首先在系统文件中寻找init.rc文件,并启动init进程,然后查看init进程的入口函数main,代码如下所示:

system/core/init/init.cpp

int main(int argc,char ** argv){
    
    ...
    if(is_first_stage){
        //创建和挂在启动所需要的文件目录
        mount("tmpfs","/dev","tmpfs",MS_NOSUID,"mode=0755");
        mkdir("/dev/pts",0755);
        //创建和挂在很多...
        ...
    }
    
    ...
    //对属性服务进行初始化
    property_init();
    
    ...
    //用于设置子进程信号处理函数(如Zygote),如果子进程异常退出,init进程会调用该函数中设定的信号处理函数来处理
    signal_handler_init();
    
 	//导入默认的环境变量
 	property_load_boot_defaults();
    ...

    //启动属性服务
    start_property_service();
    
    ...
    
    //解析init.rc配置文件
    parser.ParseConfig("/init.rc");
    
}

init的main函数做了很多事情,比较复杂,我们只需要关注主要的几点就可以了。在开始的时候创建和挂载启动所需要的文件目录,其中挂载了tmpfs、devpts、proc、sysfs、和selinuxfs共五种文件系统,这些都是系统运行时目录,且只在系统运行时才会存在,系统停止时会消失。

3、解析init.rc

init.rc是一个非常重要的配置文件,它是由Android初始化语言编写的脚本,这种语言主要包含5种类型语句:Action、Command、Service、Option和Import。init.rc的配置代码如下所示:

system/core/rootdir/init.rc
on		init
	sysclktz 0
	copy		/proc/cmdline		/dev/urandom
	copy 		/default.prop 		/dev/urandom
...
on		boot
		ifup		lo
		hostname		localhost
		domainname		localdomain
		setrlimit		13		40		40
...

这里只裁取了一部分代码。on init 和 on boot 是Action 类型语句,它的格式如下:

on ‹trigger> [&& ‹trigger>]*		//设置触发器
(command>
(Command>		//动作触发之后要执行的命令

为了分析如何创建 Zygote,我们主要查看 Service 类型语向,它的格式如下所示:

service sname> spathname > I <argament> ]*	//<service 的名字><执行程序路径><传递参数>
<option> //option 是 service 的修饰词,影响什么时候、如何启动 Service
<option>

需要注意的是,在Android8.0中对 inir.rc 文件进行了拆分。每个服务对应一个rc文件。我们要分析的Zygote 启动脚本则在 init.zygoteXX.rc 中定义,这里拿 64 位处理器为例:init.zygote64.rc 的代码如下所示:

system/core/rootdir/init.zygote64.rc 
service zygote /system/bin/app process64	-Xzygote /system/bin	--zygote	--start
system-server
class main
priority -20
user root
group root readproc
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
onrestart
restart wificond
writepid/dev/puset/foreground/tasks

根据 Service 类型语句的格式我们来大概分析上面代码的意思。S00000000000000ervice 用于通知 init
进程创建名为 zygote 的进程,这个进程执行程序的路径为/system/bin/app process64,
其后面的代码是要传给 app_Process64 的参数。class main 指的是Zygote 的classname 为
main,后面会用到它。

4、解析Service类型语句

init.rc 中的 Action 类型语句和 Service 类型语句都有相应的类来进行解析,Action 类型语句采用 ActionParser 来进行解析,Service 类型语句采用 ServiceParser 来进行解析,这里因为主要分析 zygote,所以只介绍 ServiceParser。 ServiceParser 的实现代码在system/core/init/service.cpp 中,接下来我们来查看 ServiceParser 是如何解析上面提到的Service 类型语句的,会用到两个函数:一个是 ParseSection,它会解析 Service 的rc 文件,比如上文讲到的 init.zygote64.rc, ParseSection 函数主要用来搭建 Service 的架子,另一个是ParseLineSection, 用于解析子项。代码如下所示:

system/core/init/service.cpp
bool ServiceParser: : ParseSection(const std: : vector‹std: : string>& args,std::string* err){
	if (args. size ()3{ //判断Service 是否有name 与可抉行程序
		*err
		"services must have a name and a program"
		return false;
	}
	const std: :string& name =	args|1]:
	if (!ISValidName (name)){//检查 Service 的 pame 是否有效
		*err= StringPrintf ("invalid service name		'%s'", name.c strU));
		return false;
	}
	std: :vector‹std: :string› str args (args,begin () + 2, args, end () ) ;
	service	= std: :make unique<Service> (name, str args);//1
	return true;
}

5、init启动Zygote

zygote进程由init通过fork而来,在init.rc中,搜索一下“start zygote”,可看到:

# system/core/rootdir/init.rc
# It is recommended to put unnecessary data/ initialization from post-fs-data
# to start-zygote in device's init.rc to unblock zygote start.
on zygote-start && property:ro.crypto.state=unencrypted
    # A/B update verifier that marks a successful boot.
    exec_start update_verifier_nonencrypted
    start netd
    <span style="color:#FF0000;">start zygote</span>
    start zygote_secondary

on zygote-start && property:ro.crypto.state=unsupported
    # A/B update verifier that marks a successful boot.
    exec_start update_verifier_nonencrypted
    start netd
    <span style="color:#FF0000;">start zygote</span>
    start zygote_secondary

on zygote-start && property:ro.crypto.state=encrypted && property:ro.crypto.type=file
    # A/B update verifier that marks a successful boot.
    exec_start update_verifier_nonencrypted
    start netd
    <span style="color:#FF0000;">start zygote</span>
    start zygote_secondary

zygote-start 是在 on late-init 中触发的:

# system/core/rootdir/init.rc
# Mount filesystems and start core system services.
on late-init
    ......
    # Now we can start zygote for devices with file based encryption
    trigger zygote-start
    ......

在init进程的最后,会加入 late-init 的 trigger:

if (bootmode == "charger") {
        am.QueueEventTrigger("charger");
    } else {
        am.QueueEventTrigger("late-init");
    }

init进程是在最后触发zygote。


//frameworks/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[])
{
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    ......
    // Parse runtime arguments.  Stop at first unrecognized option.
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    ......
    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    }
    ......
}

在 com/android/internal/os/ZygoteInit.java 的 main 函数中,启动了SystemServer.

//frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
......
if (startSystemServer) {
    // gh 1.1 - 1.2
    Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
 
    // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
    // child (system_server) process.
    if (r != null) {
        r.run();
        return;
    }
}
}
 
// gh 1.2
private static Runnable forkSystemServer(String abiList, String socketName,
        ZygoteServer zygoteServer) { 
......
/* For child process */
if (pid == 0) {
    if (hasSecondZygote(abiList)) {
        waitForSecondaryZygote(socketName);
    }
 
    zygoteServer.closeServerSocket();
    // gh 1.2-1.3
    return handleSystemServerProcess(parsedArgs);
}
......
}
 
//gh 1.3
private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs){
......
/*
 * Pass the remaining arguments to SystemServer.
 */
// 1.3 - 1.4
return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
.......
}
 
// gh 1.4
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
    if (RuntimeInit.DEBUG) {
        Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
    }
 
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
    RuntimeInit.redirectLogStreams();//重定向log
 
    RuntimeInit.commonInit();//初始化运行环境
 
    ZygoteInit.nativeZygoteInit();//启动binder线程池
    // gh 1.4 - 1.5
    //调用应用程序的入口函数
    return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
//frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
// gh 1.5
protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
        ClassLoader classLoader) {
......
    // Remaining arguments are passed to the start class's static main
    // gh 1.5 -1.6
    return findStaticMain(args.startClass, args.startArgs, classLoader);
}
 
 
// gh 1.6
private static Runnable findStaticMain(String className, String[] argv,
        ClassLoader classLoader) {
    // 解析类名
    Class<?> cl;
 
    try {
        cl = Class.forName(className, true, classLoader);
    } catch (ClassNotFoundException ex) {
        throw new RuntimeException(
                "Missing class when invoking static main " + className,
                ex);
    }
 
    Method m;
    try {
        //gh 1.6 - 1.7
        //解析main方法,然会就会调用SystemServer的main函数
        m = cl.getMethod("main", new Class[] { String[].class });
    }
......
}

6、属性服务

android的属性服务类似于windows的注册表服务,系统或者应用会把自己的一些属性储存在注册表中即使系统重启也能够根据之前注册表中的属性进行相应初始化工作

属性服务默认项初始化流程如下:

#define PROP_PATH_RAMDISK_DEFAULT  "/default.prop"
//property_load_boot_defaults->load_properties_from_file(PROP_PATH_RAMDISK_DEFAULT, NULL);实现如下
static void load_properties_from_file(const char *fn, const char *filter)
{
    char *data;
    unsigned sz;
    data = read_file(fn, &sz);
    if(data != 0) {
        load_properties(data, filter);->//这里最终会循环调用property_set(key, value);来设置各个属性
        free(data);
    }
}

启动属性服务{queue_builtin_action(property_service_init_action, “property_service_init”)}
这里着重分析property_service_init_action,实现如下:

//property_service_init_action()-just call ->start_property_service();实现如下:
//主要工作为,创建socket,但此时并未接收客户端

void start_property_service(void)
{
    int fd;
    //creates a Unix domain socket in ANDROID_SOCKET_DIR* ("/dev/socket") as dictated in init.rc
    fd = create_socket(PROP_SERVICE_NAME, SOCK_STREAM, 0666, 0, 0, NULL);
    if(fd < 0) return;
    fcntl(fd, F_SETFD, FD_CLOEXEC);
    fcntl(fd, F_SETFL, O_NONBLOCK);
    listen(fd, 8);
    property_set_fd = fd;
}

对这一部分也只是简单了解,理解并不深,后续再学习相关内容。

总结一下,init进程启动后做了哪几件事:
(1)创建和挂载启动所需要的文件和目录

(2)初始化和启动属性服务。

(3)解析init.rc配置文件,并且启动了Zygote进程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值