[Android5.1]开机服务启动顺序
来源:互联网 发布:大人变小孩软件 编辑:程序博客网 时间:2024/05/16 16:16
大家知道,当Android系统启动时候,会解析init.rc文件,然后根据里面的定义,启动各种服务,如netd、zygote、servier_manager等等,但这些服务之间其实是有依赖关系的,而且当其中的某个服务启动失败时,有时候会影响后续的服务启动。这篇文章就具体的分析一下开机服务的启动顺序。
服务的分类
init.rc中对服务做了分类,在service section里面有一个’class’标签,指明了该服务所属的类。如:
service surfaceflinger /system/bin/surfaceflinger class core //所属类为‘core’ user system group graphics drmrpc onrestart restart zygoteservice media /system/bin/mediaserver class main //所属类为‘main’ user media group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc mediadrm system ioprio rt 4
init.rc中总共有三个分类:core、main和late_start,下面整理了各分类下属的服务:
- core
ueventd、logd、healthd、adbd(disabled)、lmkd(LowMemoryKiller)、servicemanager、vold、debuggerd、surfaceflinger、bootanim(disabled)等
core分类中的服务都是一些核心服务,它们不启动,后续的服务或系统启动就可能出问题。比如servicemanager,binder通信大管家,它的启动很靠前,因为,其他服务启动时候需要向servicemanager注册binder服务。vold,负责存储类设备的挂载;还有surfaceflinger,图形显示的核心服务等。
- main
debuggerd64、drm、media、ril-daemon、installd、flash_recovery、racoon(disabled)、mtpd(disabled)、keystore、dumpstate(disabled)、mdnsd(disabled)、pre-recovery(disabled)、cmd_services(disabled)、phasecheckserver、zygote等。
main分类中的服务是一些系统的基本服务,有了这些服务android系统、Java世界才能正常运行。
- late_start:字面意思是晚些启动。/device/中一些硬件厂商的.rc文件中会将一些服务设置为该类。
上面服务后面加”(disabled)”,代表init进程在初始化阶段不会启动该服务。该服务的启动是由其他的因素触发而启动的,比如:
on property:persist.sys.cmdservice.enable=enable start cmd_services
表示当属性persist.sys.cmdservice.enable的值设置为enable时,会触发该action,执行下面的命令。由于命令是start,所以init进程会启动cmd_services。
除了“disabled”的服务,上面的顺序基本上就是服务的开机启动顺序,即先启动core服务,然后启动main服务,最后启动late_start类别的服务。注意,相同类别的服务,基本上是同时启动,相互之间的延时很小。
服务的启动
首先看一下,init.c–>main()源码:
int main(int argc, char **argv){ ... action_for_each_trigger("early-init", action_add_queue_tail); ... action_for_each_trigger("init", action_add_queue_tail); ... action_for_each_trigger("late-init", action_add_queue_tail); ... for(;;) { ... execute_one_command(); ... }}
可以看到,依次将early-init、init、late-init三个section对应的命令插入到操作队列中。
然后在后面的for循环中,调用execute_one_command依次执行操作队列中的命令。
那early-init、init、late-init都定义了哪些操作呢?我们看一下init.rc中的定义。这里,我们只关注服务的启动,其他的操作屏蔽掉。
on early-init ... start ueventd //ueventd是init启动的第一个进程 ...on init ... // 创建各种路径,并写入一些参数on late-init //trigger 会调用action_for_each_trigger("xxx", action_add_queue_tail); //从而将xxx section里的操作加入操作队列 // mount文件系统相关的操作 trigger early-fs trigger fs trigger post-fs trigger post-fs-data trigger load_all_props_action //加载属性 trigger firmware_mounts_complete trigger early-boot //将‘early-boot’中的操作加入执行队列 trigger boot //将‘boot’中的操作加入执行队列on early-boot ... // kernel trace相关on boot ... class_start core // 启动core类别的服务
前面说了core类别的服务有很多,那这些服务的启动顺序怎么定义的呢?init进程在解析init.rc(init.rc中还import了其他的rc文件,解析完init.rc后,依次解析其他的rc文件)文件时,是从上到下依次解析,并存放在一个全局链表中的。服务的启动顺序就是该服务在全局链表中的位置。所以在rc文件中定义靠前的服务也会在全局链表的靠前位置,也就会先执行。
core类别的服务启动完了,那main类别的服务什么时候启动呢?
init.rc中对启动main类别服务的定义如下:
on nonencrypted class_start main class_start late_starton property:vold.decrypt=trigger_restart_min_framework class_start mainon property:vold.decrypt=trigger_restart_framework class_start main class_start late_start
可见,有以上三种方式,会触发启动main类别的服务。通过名字可以看出,都和系统是否加密有关。
这里,我们分析一下nonencrypted。前面提到,在“late-init”section中会触发“fs”section。
on late-init ... trigger fs ...//这个section一般在init.${ro.hardware}.rc中定义on fs ... mount_all fstab ...
在“fs”section中会执行mount_all fstab命令。fstab是Android下比较重要的配置文件,它包含了系统在启动时挂载文件系统和存储设备的详细信息。对应的处理函数为:
int do_mount_all(int nargs, char **args){ ... pid = fork(); if (pid > 0) { // 父进程,等待子进程的处理返回结果 int wp_ret = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0)); if (WIFEXITED(status)) { ret = WEXITSTATUS(status); } else { ret = -1; } } else if (pid == 0) { // 子进程,进一步调用fs_mgr_mount_all() fstab = fs_mgr_read_fstab(args[1]); child_ret = fs_mgr_mount_all(fstab); ... _exit(child_ret); } else { ... } if (ret == FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION) { ... } else if (ret == FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED) { ... } else if (ret == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) { ... // 这里就将"nonencrypted"中的操作加入到操作队列中 action_for_each_trigger("nonencrypted", action_add_queue_tail); } else if (ret == FS_MGR_MNTALL_DEV_NEEDS_RECOVERY) { ... } ...}
这里注意:如果调用fs_mgr_mount_all()返回结果不是FS_MGR_MNTALL_DEV_NOT_ENCRYPTED,就不会执行action_for_each_trigger(“nonencrypted”, action_add_queue_tail);这样main类别的服务就不会执行,系统就会无法正常启动。
总结
本文简单介绍了系统启动阶段各服务的启动顺序,实际过程会复杂很多。有时间的话,会进一步补充。
- [Android5.1]开机服务启动顺序
- linux服务开机启动顺序
- Android5.1 应用开机启动方法
- 设置Linux 服务的开机启动顺序
- linux开机服务启动顺序详解
- linux开机启动顺序
- Linux开机启动顺序
- Linux开机启动顺序
- Linux开机启动顺序
- LINUX开机启动顺序
- Linux开机启动顺序
- Linux开机启动顺序
- android5.1开机动画分析
- Android5.1开机LOGO与开机动画
- 设置开机启动服务
- svn服务开机启动
- android 开机启动服务
- linux开机启动服务
- mysql忘记用户名和密码(怎么修改密码)
- Material design之Views and Shadows
- 学生学籍管理系统_源码下载
- Material design之Compatibility(适配)
- librtmp 时间戳超过 0xffffff时,FMS掉连接
- [Android5.1]开机服务启动顺序
- Android中的Manifest.permission(应用权限)整理
- Android中的ACCESS_MOCK_LOCATION权限使用Demo
- “WebApplication.SqlHelper”的类型初始值设定项引发异常。
- Android截图
- android手机有多个摄像头,打开其中一个
- 获取iOS设备上所有的进程名字,以及进程的ID,
- android发送邮件
- 【爱江山越野跑】ITRA积分认证流程