Android init.rc和zygote进程分析

init的任务
创建zygote:JAVA世界的第一个进程
提供属性服务(property service):管理系统属性
加载service

init源码分析
入口函数:init.c:main.c
路径:\system\core\init
完成任务:
解析配置文件init.rc
执行各个阶段动作:early-init、init、late-init(创建zygote)
调用property_init初始化属性相关资源,property_service_init_action->start_property_service启动属性服务
init进入无限循环,等待并执行一些事情,如客户端更改属性服务。

init.rc语法分析
关键字
section:
service:以service开头,服务是指那些需要在系统初始化时就启动或退出时自动重启的程序.
action:以on开头,动作表示了一组命令(commands)组成,当触发器的条件满足时,这个动作会被加入到已被执行的队列尾
option:选项是用来修改服务的。它们影响如何及何时运行这个服务.
class main
trigger:触发器用来描述一个触发条件,当这个触发条件满足时可以执行动作
commands:要执行的动作

解析配置文件init.rc
init_parse_config_file(“/init.rc”):\system\core\init\init_parser.c
读取init.rc
parse_config做真正解析
parse_config:\system\core\init\init_parser.c
找到配置文件的一个SECTION,针对不同的section使用不同的解析函数来解析
在这里插入图片描述
解析zygote
zygote被定义成service section
解析section入口函数:parse_new_section:\system\core\init\init_parser.c
根据kw这个参数判断是k_on还是k_service(这些在keywords.h有定义)
KEYWORD(service, SECTION, 0, 0),第一个参数为service或on或import是SECTION
当kw为k_service时,调用两个函数:
1、parse_service:\system\core\init\init.h
搭建一个struct service结构,将zygote这个service加到全局链表service_list中
2、parse_line_service:根据配置文件的内容填充struct service结构体,结果如下:
zygote解析结果图
service_list是全局链表,保存解析后的service
socketinfo保存zygote的socket
onrestart的commands指向zygote的3个command

在这里插入图片描述
init如何控制service
在init.c的main函数中,要分别执行early-init、init、late-init、boot四个阶段的动作,这些动作来自之前的解析文件init.rc
init.rc的zygote服务中有这样一句话:class main
(服务默认创建的时候classname为“default”,这里通过“class main”来修改classname为“main”)
函数:
1、action_for_each_trigger:将各个阶段的section的command加入队列中
2、queue_builtin_action:执行队列的command
在on boot阶段,有class_start main,对应的函数是do_class_start

do_class_start
路径:\system\core\init\builtins.c
任务:从service_list链表中找到classname和参数一致的service, 然后调用service_start_if_not_disabled->service_start_if_not_disabled->service_start(\system\core\init\init.c)

service_start的任务:
1、调用fork创建新进程
2、调用execve执行/system/bin/app_process,这样就进入app_process的main函数中。

问题:struct service 中的onrestart没有用到?

zygote重启
在init.c的main函数中,signal_init_action被调用,再调用signal_init(\system\core\init\signal_handler.c)
signal_init调用socketpair创建已经connect好的socket
当zygote死掉后,即子进程退出,init的信号处理函数sigchld_handler被调用,该函数往创建的socket的一端写数据,则另一端会接收到数据,此时init从poll函数中返回,init.c->main.c调用handle_signal(\system\core\init\signal_handler.c)->wait_for_one_process

wait_for_one_process的任务
找到死掉的那个service,即zygote进程
杀掉zygote所有子进程,则如果zygote死掉后,JAVA世界将崩溃
如果设置了SVC_CRITICAL标志,4分钟之内若重启次数超过4次,则进入“recovery”模式
执行struct service中onrestart的command

问题:zygote死后如何重启?
在init.c的main函数中,当poll函数返回后,继续进入下一轮循环
restart_processes() :重启被标志为SVC_RESTARTING的service,此时zygote被重启

属性服务
1、作用:
就像window的注册表一样,Android系统提供属性服务,系统重启时可根据这些属性进行初始化,应用程序可查询和修改属性
2、属性服务实现:
创建存储空间
客户端获取存储空间
启动属性服务器
处理设置属性请求

属性服务实现
1、init.c的main函数:property_init->init_property_area(\system\core\init\property_service.c)->init_workspace:创建一块共享内存,用于存储系统属性
2、在property_service.c中调用__system_property_area_init->map_prop_area_rw(\bionic\libc\bionic\system_properties.cpp)->mmap
3、init.c的main函数:property_service_init_action->start_property_service(\system\core\init\property_service.c):创建一个socket用于与客户端更改属性的通讯
4、在init.c的main函数中的循环当中处理设置属性请求:handle_property_set_fd(\system\core\init\property_service.c)
连接TCP、取出消息、做出响应(init_property_set)即添加属性

问题:客户端如何请求更改属性?\system\core\libcutils\properties.c->property_set:发送请求

zygote分析
zygote由init进程创建
zygote的任务:
1、创建JAVA虚拟机
2、注册JNI函数
3、通过JNI进入JAVA世界
3.1、注册一个socket
3.2、预加载类和资源
3.3、创建system_server进程
3.4、处理socket中的客户端连接和请求

说白了就是JAVA世界需要的东西,zygote为你准备好

如何进入zygote进程的
init进程解析完init.rc后会执行一系列动作,其中在on boot阶段,有class_start main,对应的函数是do_class_start,这里最后通过Linux系统调用函数execve进入zygote进程,也就是app_process
app_process的源文件是app_main.cpp(\frameworks\base\cmds\app_process)
在app_main.cpp中调用AppRuntime类(继承AndroidRuntime)中的start,传递的参数是com.android.internal.os.ZygoteInit,下面进入AndroidRuntime.start函数

AndroidRuntime.start
路径:\frameworks\base\core\jni\AndroidRuntime.cpp
1、创建JAVA虚拟机:startVm
1.1、设置参数(如虚拟机大小),1.2、JNI_CreateJavaVM创建虚拟机
2、注册JNI函数:startReg(JAVA需要调用JNI实现)
register_jni_procs,参数:gRegJNI,这是个全局数组,包含JNI函数
3、进入JAVA世界:CallStaticVoidMethod,参数为com.android.internal.os.ZygoteInit,下面分析ZygoteInit.java的main函数

进入JAVA世界,此时还是处于zygote进程
路径:\frameworks\base\core\java\com\android\internal\os\ZygoteInit.java
任务:
1、注册zygote用的socket
registerZygoteSocket(),用于与其他程序通讯
2、预加载类和资源
preload()->preloadClasses、preloadResources。
PRELOADED_CLASSES:\frameworks\base\preloaded-classes
3、创建system_server进程
startSystemServer()->forkSystemServer->fork
4、处理socket中的客户端连接和请求
runSelectLoop()->selectReadable使用select多路复用处理请求

system_server的任务
在哪里创建:
forkSystemServer通过JNI 调用com_android_internal_os_Zygote_nativeForkSystemServer
路径:\frameworks\base\core\jni\com_android_internal_os_Zygote.cpp

任务:入口Zygoteinit.java->handleSystemServerProcess->RuntimeInit.java->zygoteInit->applicationInit->invokeStaticMain:抛出异常,异常被ZygoteInit.java的main函数捕获,并进入caller.run()函数

1、处理异常并进入SystemServer.java的main函数
2、创建各种服务

system_server转交任务给SystemServer.java
路径\frameworks\base\services\java\com\android\server\SystemServer.java
任务:
启动各类系统服务,包括ActivityManager服务
在这里插入图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值