简介
当Linux内核启动之后,运行的第一个进程是init,这个进程是一个守护进程,它的生命周期贯穿整个linux 内核运行的始终, linux中所有其它的进程的共同始祖均为init进程。
Android系统是运作在linux内核上的,为了启动并运行整个android系统,google实现了android系统的init进程。
init主函数
Android init进程的入口文件在system/core/init/init.cpp中。
|
|
init主函数完成了许多功能,主要实现的功能有如下:
property_init()
初始化属性服务start_property_service()
启动属性服务parser.ParseConfig("/init.rc")
解析init.rc配置文件- 将所有需要操作的action加入到ActionManager管理的队列中,进入无线循环过程,不断处理运行队列中的事件,同时进行重启service等操作。
接下来了解属性服务:
属性服务
system/core/init/init.cpp
|
|
property_init()
属性初始化,init进程在共享内存区域中,创建并初始化属性域。
property_init()函数的具体实现在system/core/init/property_service.cpp
|
|
start_property_service()
启动配置属性服务端
system/core/init/property_service.cpp
|
|
调用listen后,init进程成为一个服务进程,其它进程可以通过property_set_fd连接init进程,提交设置系统属性的申请。在启动配置属性服务的最后,调用了register_epoll_handler函数,该函数将利用之前创建出的epoll句柄监听property_set_fd。当property_set_fd有数据到来时,init进程将使用handle_property_set_fd()函数进行处理
|
|
handle_property_set_fd()函数实际上调用accept函数监听连接请求,recv接收到来的数据,然后根据数据类型,进行设置系统属性等相关操作。
init进程在共享内存区域中,创建并初始化属性域。其它进程可以访问属性域中的值,但更改属性值仅能在init进程中进行。这就是init进程调用start_property_service的原因。其它进程修改属性值时,要预先向init进程提交值变更申请,然后init进程处理该申请,并修改属性值。在访问和修改属性时,init进程都可以进行权限控制。所以在修改属性时,通过check_mac_perms()函数检查进程权限。
属性修改则调用property_set()实现:
|
|
property_set函数则通过调用property_set_impl函数来实现:
|
|
属性服务的工作过程基本就是这样,下面来看看init.rc文件的解析
init.rc
init.rc文件是在init进程启动后执行的启动脚本,文件中记录着init进程需执行的操作。在Android系统中,使用init.rc和init.{ hardware }.rc两个文件。
|
|
此处解析函数传入的参数为“/init.rc”,解析的是运行时与init进程同在根目录下的init.rc文件。该文件在编译前,定义于system/core/rootdir/init.rc中,可以看到
|
|
从import的文件命名方式,我们可以看出在不同的平台(32、64及64_32)上,init.rc将包含不同的zygote.rc文件。不同的zygote.rc内容大致相同,主要区别体现在启动的是32位,还是64位的进程。这里拿64位处理器为例,init.zygote64.rc的代码如下所示。
system/core/rootdir/init.zygote64.rc
|
|
可以看到init进程将会zygote进程,这个进程的执行路径为
/system/bin/app_process64
,后面则是要传给app_process64的参数。
接下来看看系统如何解析service。
service解析
|
|
从上述代码可知,service的rc文件最终解析是由ServiceParser的函数解析的,比如init.zygote64.rc,接下来看看ServiceParser的函数:函数位于system/core/init/service.cpp
|
|
init启动zygote
接下来看看init是如何启动service,在这里主要了解启动zygote这个service。在zygote的启动脚本中我们得知zygote的class name为main。在init.rc有如下配置代码:
system/core/rootdir/init.rc
|
|
那么系统是是如何处理上面的脚本的呢?在init.cpp的main函数中有
|
|
因此,Action中调用functionmap->FindFunction时,实际上调用的是BuiltinFunctionMap的FindFunction函数。我们已经知道FindFunction是keyword定义的通用函数,重点是重构的map函数。我们看看system/core/init/builtins.cpp:
|
|
第四项就是就是的Action nonencrypted 的命令class_start所对应的执行函数,执行函数为do_class_start,接下来看看这个函数:
system/core/init/builtins.cpp
|
|
来查看StartIfNotDisabled做了什么:
system/core/init/service.cpp
|
|
继续看Start()方法:
|
|
Start方法中调用fork函数来创建子进程,并在子进程中调用execve执行system/bin/app_process64,这样就会进入framework/cmds/app_process/app_main.cpp的main函数,如下所示。
frameworks/base/cmds/app_process/app_main.cpp
|
|
系统最终调用runtime(AppRuntime)的start来启动zygote。
小结
init进程的主要功能:
- 创建和挂载设备
- 初始化和启动属性服务
- 解析init.rc文件并启动zygote进程
下面将要分析zygote进程的启动过程。