init进程详细分析

概述

android设备上电,引导程序引导进入boot(通常是uboot),加载initramfs、kernel镜像,启动kernel后,进入用户态程序。第一个用户空间程序是init,PID固定是1.在android系统上,init的代码位于/system/core/init下,基本功能有:

  • 管理设备
  • 解析并处理启动脚本init.rc
  • 实时维护这个init.rc中的服务

流程分析

这些init.rc只是语法文件,并不是程序,真正的入口则是上面提到的system/core/init/init.cpp .

  • 参考文档:
  • Android P (9.0) 之Init进程源码分析
  • Android系统init进程启动及init.rc全解析

对比老版本差异

在Android Q中,对该机制做了一些改变 。

单一的init.rc,被拆分,服务根据其二进制文件的位置(/system,/vendor,/odm)定义到对应分区的etc/init目录中,每个服务一个rc文件。与该服务相关的触发器、操作等也定义在同一rc文件中。

/system/etc/init,包含系统核心服务的定义,如SurfaceFlinger、MediaServer、Logcatd等。/vendor/etc/init, SOC厂商针对SOC核心功能定义的一些服务。比如高通、MTK某一款SOC的相关的服务。/odm/etc/init,OEM/ODM厂商如小米、华为、OPP其产品所使用的外设以及差异化功能相关的服务。

这样的目录结构拆分,也与Android产品的开发流程相吻合,减轻了维护的负担。下图为Android Q 中定义的所有服务。

  • k62v1_64_bsp$ find ./ -name "*.rc" :
展开查看
```./recovery/root/init.rc./recovery/root/ueventd.rc./recovery/root/init.recovery.mt6762.rc./recovery/root/init.recovery.mt6765.rc./vendor/ueventd.rc./vendor/etc/init/init.wmt_drv.rc./vendor/etc/init/init.volte_imsm_93.rc./vendor/etc/init/mtk_agpsd_p.rc./vendor/etc/init/bootperf.rc./vendor/etc/init/audiocmdservice_atci.rc./vendor/etc/init/android.hardware.graphics.composer@2.1-service.rc./vendor/etc/init/vendor.mediatek.hardware.gpu@1.0-service.rc./vendor/etc/init/init.volte_stack.rc./vendor/etc/init/init_connectivity.rc./vendor/etc/init/init.fmradio_drv.rc./vendor/etc/init/netdagent.rc./vendor/etc/init/atcid_eng.rc./vendor/etc/init/init.vtservice_hidl.rc./vendor/etc/init/mtkrild.rc./vendor/etc/init/android.hardware.health@2.0-service.rc./vendor/etc/init/init.wfca.rc./vendor/etc/init/modemdbfilter_service.rc./vendor/etc/init/init.bt_drv.rc./vendor/etc/init/init.gps_drv.rc./vendor/etc/init/aee_aedv64.rc./vendor/etc/init/android.hardware.secure_element@1.0-service-mediatek.rc./vendor/etc/init/android.hardware.drm@1.2-service.clearkey.rc./vendor/etc/init/vendor.mediatek.hardware.log@1.0-service.rc./vendor/etc/init/init.thermal_manager.rc./vendor/etc/init/init.bip.rc./vendor/etc/init/init.cccimdinit.rc./vendor/etc/init/md_monitor.rc./vendor/etc/init/muxreport.rc./vendor/etc/init/android.hardware.drm@1.0-service.rc./vendor/etc/init/init.wlan_drv.rc./vendor/etc/init/android.hardware.drm@1.2-service.widevine.rc./vendor/etc/init/wlan_assistant.rc./vendor/etc/init/camerahalserver.rc./vendor/etc/init/atci_service.rc./vendor/etc/init/android.hardware.cas@1.1-service.rc./vendor/etc/init/ipsec_mon.rc./vendor/etc/init/android.hardware.thermal@1.0-service.rc./vendor/etc/init/android.hardware.gatekeeper@1.0-service.rc./vendor/etc/init/android.hardware.keymaster@4.0-service.rc./vendor/etc/init/init.thermalloadalgod.rc./vendor/etc/init/android.hardware.graphics.allocator@2.0-service.rc./vendor/etc/init/vendor.mediatek.hardware.mtkpower@1.0-init.rc./vendor/etc/init/lbs_hidl_service.rc./vendor/etc/init/android.hardware.sensors@2.0-service-mediatek.rc./vendor/etc/init/hostapd.android.rc./vendor/etc/init/init.thermal.rc./vendor/etc/init/fuelgauged_nvram_init.rc./vendor/etc/init/em_hidl_eng.rc./vendor/etc/init/vendor.mediatek.hardware.mtkpower@1.0-service.rc./vendor/etc/init/init.cccirpcd.rc./vendor/etc/init/init.volte_md_status.rc./vendor/etc/init/android.hardware.light@2.0-service-mediatek.rc./vendor/etc/init/aee_aedv.rc./vendor/etc/init/init.cccifsd.rc./vendor/etc/init/gsm0710muxd.rc./vendor/etc/init/loghidlvendorservice.rc./vendor/etc/init/fuelgauged_init.rc./vendor/etc/init/android.hardware.wifi@1.0-service-lazy-mediatek.rc./vendor/etc/init/android.hardware.bluetooth@1.0-service-mediatek.rc./vendor/etc/init/ppl_agent.rc./vendor/etc/init/hw/init.project.rc./vendor/etc/init/hw/init.sensor_1_0.rc./vendor/etc/init/hw/init.mt6765.rc./vendor/etc/init/hw/meta_init.connectivity.rc./vendor/etc/init/hw/meta_init.project.rc./vendor/etc/init/hw/multi_init.rc./vendor/etc/init/hw/factory_init.project.rc./vendor/etc/init/hw/factory_init.rc./vendor/etc/init/hw/init.mt6762.rc./vendor/etc/init/hw/init.mt6765.usb.rc./vendor/etc/init/hw/factory_init.connectivity.rc./vendor/etc/init/hw/init.connectivity.rc./vendor/etc/init/hw/init.aee.rc./vendor/etc/init/hw/init.modem.rc./vendor/etc/init/hw/init.ago.rc./vendor/etc/init/hw/meta_init.modem.rc./vendor/etc/init/hw/meta_init.rc./vendor/etc/init/init.md_apps.rc./vendor/etc/init/android.hardware.media.omx@1.0-service.rc./vendor/etc/init/init.volte_ua.rc./vendor/etc/init/nvram_daemon.rc./vendor/etc/init/init.wod.rc./vendor/etc/init/vendor.mediatek.hardware.nvram@1.1-sevice.rc./vendor/etc/init/android.hardware.memtrack@1.0-service.rc./vendor/etc/init/android.hardware.configstore@1.1-service.rc./vendor/etc/init/android.hardware.usb@1.1-service-mediatek.rc./vendor/etc/init/vendor.mediatek.hardware.mtkcodecservice@1.1-service.rc./vendor/etc/init/init.volte_imcb.rc./vendor/etc/init/android.hardware.audio@5.0-service-mediatek.rc./vendor/etc/init/android.hardware.vibrator@1.0-service.rc./vendor/etc/init/vendor.mediatek.hardware.mms@1.3-service.rc./vendor/etc/init/vndservicemanager.rc./vendor/etc/init/android.hardware.gnss@2.0-service-mediatek.rc./vendor/etc/init/vendor.mediatek.hardware.pq@2.2-service.rc./system/apex/com.android.media.swcodec/etc/init.rc./system/etc/init/mdlogger.rc./system/etc/init/atrace.rc./system/etc/init/mediaextractor.rc./system/etc/init/surfaceflinger.rc./system/etc/init/ashmemd.rc./system/etc/init/android.system.suspend@1.0-service.rc./system/etc/init/uncrypt.rc./system/etc/init/camerapostalgo.rc./system/etc/init/bootlogoupdater.rc./system/etc/init/art_apex_boot_integrity.rc./system/etc/init/usbd.rc./system/etc/init/modemdbfilter_client.rc./system/etc/init/atci_service_sys.rc./system/etc/init/drmserver.rc./system/etc/init/recovery-persist.rc./system/etc/init/aee_aed64.rc./system/etc/init/keystore.rc./system/etc/init/wait_for_keymaster.rc./system/etc/init/mobile_log_d.rc./system/etc/init/mediaserver.rc./system/etc/init/hwservicemanager.rc./system/etc/init/init-debug.rc./system/etc/init/gpuservice.rc./system/etc/init/logd.rc./system/etc/init/incidentd.rc./system/etc/init/servicemanager.rc./system/etc/init/lpdumpd.rc./system/etc/init/idmap2d.rc./system/etc/init/bootstat.rc./system/etc/init/blank_screen.rc./system/etc/init/bootstat-debug.rc./system/etc/init/storaged.rc./system/etc/init/netd.rc./system/etc/init/mediametrics.rc./system/etc/init/mediadrmserver.rc./system/etc/init/wificond.rc./system/etc/init/vdc.rc./system/etc/init/cameraserver.rc./system/etc/init/gsid.rc./system/etc/init/consyslogger.rc./system/etc/init/logtagd.rc./system/etc/init/malloc_debug_option.rc./system/etc/init/bootanim.rc./system/etc/init/logcatd.rc./system/etc/init/batterywarning.rc./system/etc/init/statsd.rc./system/etc/init/perfetto.rc./system/etc/init/init.connectivity.rc./system/etc/init/flags_health_check.rc./system/etc/init/mtpd.rc./system/etc/init/init.thermald.rc./system/etc/init/mdnsd.rc./system/etc/init/duraspeed.rc./system/etc/init/emdlogger3.rc./system/etc/init/audioserver.rc./system/etc/init/terserver.rc./system/etc/init/heapprofd.rc./system/etc/init/netdiag.rc./system/etc/init/bpfloader.rc./system/etc/init/init.vtservice.rc./system/etc/init/hw/init.aee.rc./system/etc/init/hw/vendor_init_as_system.rc./system/etc/init/emdlogger5.rc./system/etc/init/iorapd.rc./system/etc/init/wifi-events.rc./system/etc/init/tombstoned.rc./system/etc/init/kpoc_charger.rc./system/etc/init/apexd.rc./system/etc/init/traceur.rc./system/etc/init/android.hidl.allocator@1.0-service.rc./system/etc/init/gatekeeperd.rc./system/etc/init/atrace_userdebug.rc./system/etc/init/lmkd.rc./system/etc/init/rss_hwm_reset.rc./system/etc/init/installd.rc./system/etc/init/racoon.rc./system/etc/init/emdlogger2.rc./system/etc/init/emdlogger1.rc./system/etc/init/em_svr.rc./system/etc/init/dumpstate.rc./system/etc/init/aee_aed.rc./system/etc/init/vold.rc./root/init.rc./root/init.zygote32.rc./root/init.environ.rc./root/ueventd.rc./root/init.zygote64_32.rc./root/init.preload.rc./root/init.usb.configfs.rc./root/init.usb.rc```

init.rc定位

  • init的源码位于system/core/init包下,我们先从入口类main.cpp来看
int main(int argc, char** argv) {#if __has_feature(address_sanitizer)    __asan_set_error_report_callback(AsanReportCallback);#endif    if (!strcmp(basename(argv[0]), "ueventd")) {        return ueventd_main(argc, argv);   //ueventd.cpp入口函数,初始化uevent    }    if (argc > 1) {        if (!strcmp(argv[1], "subcontext")) {            android::base::InitLogging(argv, &android::base::KernelLogger);            const BuiltinFunctionMap function_map;            return SubcontextMain(argc, argv, &function_map);        }        if (!strcmp(argv[1], "selinux_setup")) {            // This function initializes SELinux then execs init to run in the init SELinux context.            return SetupSelinux(argv); //对SELinux进行初始化,并通过execs的系统调用开启init进程        }        if (!strcmp(argv[1], "second_stage")) {            return SecondStageMain(argc, argv);  //第二阶段 init.cpp入口函数        }    }    return FirstStageMain(argc, argv);   //第一阶段}

复制代码可以看到main.cpp的函数跟之前版本有了很大的区别,拿Android9.0的源码androidxref.com/9.0.0_r3/xr…来说,Android10中并不只是调用init::main,而是把部分流程性的判断放到的mian.cpp中来做,所以这里如果按照书上或者文章中所说的,直接去找init.cpp中的main函数,其实是找不到入口的。

当入口函数Init.cpp启动加载第一个init.rc如下:

/system/core/rootdir/init.rc/bootable/recovery/etc/init.rc

从目录上大致可以猜测,这两个init.rc使用场景不一样,一个是刷机用到的,也就是进入recorvery模式,一个是正常启动用到的;我们这里重点分析的是正常启动用的,也是init.c关联的那个;

  • device/mediatek/mt6765/device.mk
7:  PRODUCT_DEFAULT_PROPERTY_OVERRIDES += ro.vendor.rc=/vendor/etc/init/hw/919: PRODUCT_COPY_FILES += device/mediatek/mt6765/init.recovery.mt6765.rc:recovery-vendor/init.recovery.mt6765.rc
  • /system/core/rootdir/init.rc
···import /vendor/etc/init/hw/init.${ro.hardware}.rc···
  • /device/mediatek/mt6765/init.mt6765.rc
···import /vendor/etc/init/hw/init.project.rc···
  • device/mediateksample/k62v1_64_bsp/device.mk
16:PRODUCT_COPY_FILES += $(LOCAL_PATH)/init.project.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/hw/init.project.rc

根据以上内容,我们可以判断我们OEM/ODM厂商主要修改文件是device/mediateksample/k62v1_64_bsp/init.project.rc,而在recovery模式下主要修改init.recovery.mt6765.rc文件。

init.rc修改规则

rc规则主要包含了四种类型的语句:

  1. Action
  2. Commands
  3. Services
  4. Options.

以下做具体详解:

动作(Action)

动作表示了一组命令(commands)组成.动作包括一个触发器,决定了何时运行这个动作。

注意:当触发器的条件满足时,这个动作会被增加到已被运行的队列尾。假设此动作在队列中已经存在,那么它将不会运行.

一个动作所包括的命令将被依次运行。

on        ## 触发条件          ##执行命令         ##可以执行多个命令
  1. 触发器(trigger)

在"动作"(action)里面的,on后面跟着的字符串是触发器(trigger),trigger是一个用于匹配某种事件类型的字符串,它将对应的Action的执行。

触发器(trigger)有几种格式:

1、最简单的一种是一个单纯的字符串。比如“on boot”。这种简单的格式可以使用命令"trigger"来触发。2、还有一种常见的格式是"on property<属性>=<值>"。如果属性值在运行时设成了指定的值,则"块"(action)中的命令列表就会执行。

常见的格式:

格式 含义
on early-init 在初始化早期阶段触发
on init 在初始化阶段触发
on late-init 在初始化晚期阶段触发
on boot/charger 当系统启动/充电时触发
on property 当属性值满足条件时触发

commands(命令)

command是action的命令列表中的命令,或者是service中的选项 onrestart 的参数命令.

命令将在所属事件发生时被一个个地执行.

常见命令:

命令 描写叙述
exec [ ]* 运行指定路径下的程序,并传递參数.
export 设置全局环境參数。此參数被设置后对全部进程都有效.
ifup 使指定的网络接口"上线",相当激活指定的网络接口
import 导入一个额外的init配置文件.
hostname 设置主机名
chdir 改变工作文件夹.
chmod 改变指定文件的读取权限.
chown 改变指定文件的拥有都和组名的属性.
chroot 改变进行的根文件夹.
class_start 启动指定类属的全部服务,假设服务已经启动,则不再反复启动.
class_stop 停止指定类属的所胡服务.
domainname 设置域名
insmod 安装模块到指定路径.
mkdir [mode] [owner] [group] 用指定參数创建一个文件夹,在默认情况下,创建的文件夹读取权限为755.username为root,组名为root.
mount [ ]* 类似于linux的mount指令setkey TBD(To Be Determined), 待定.
setprop 设置属性及相应的值.
setrlimit 设置资源的rlimit(资源限制),不懂就百度一下rlimit
start 假设指定的服务未启动,则启动它.
stop 假设指定的服务当前正在执行。则停止它.
symlink 创建一个符号链接.
sysclktz 设置系统基准时间.
trigger Trigger an event. Used to queue an action from another action. 这名话没有理解,望高手指点.
write [ ]* 往指定的文件写字符串.

服务(services)

服务是指那些须要在系统初始化时就启动或退出时自己主动重新启动的程序.

service  [  ]*    

解释一下各个参数:

参数 含义
表示此服务的名称
此服务所在路径因为是可执行文件,所以一定有存储路径。
启动服务所带的参数
对此服务的约束选项

选项(option)

options是Service的修订项。它们决定一个服务何时以及如何运行.

选项 描述
critical 据设备相关的关键服务,如果在4分钟内,此服务重复启动了4次,那么设备将会重启进入还原模式。
disabled 服务不会自动运行,必须显式地通过服务器来启动。
setenv 设置环境变量
socket [ [ ] ] 在/dev/socket/下创建一个unix domain的socket,并传递创建的文件描述符fd给服务进程.其中type必须为dgram或stream,seqpacket.
user 在执行此服务之前先切换用户名。当前默认为root.
group [ ]* 类似于user,切换组名
oneshot 当此服务退出时不会自动重启.
class 给服务指定一个类属,这样方便操作多个服务同时启动或停止.默认情况下为default.
onrestart 当服务重启时执行一条指令,

使用例子:

service bootanim /system/bin/bootanimation    class core  //给服务指定一个类属,这样方便操作多个服务同时启动或停止    user graphics //在执行此服务之前先切换用户名    group graphics audio    disabled  //服务不会自动运行    oneshot  //当此服务退出时不会自动重启

启动顺序

下面为各个section的执行顺序,英文编号的section是系统内建的(写死在init.cpp中的命令)

1) early-init    a) wait_for_coldboot_done    b) property_init    c) keychord_int    d) console_init2) init3) early-fs (sys.boot_from_charger_mode=1)4) fs5) post-fs6) late-fs7) post-fs-data8) load_persist_props_action9) zygote-start10) firmware_mounts_complete11) early-boot12) boot13) service

所有的action运行于service之前。

更多相关文章

  1. android上解析.plist配置文件的xml解析器
  2. Android基于OkHttp实现文件上传
  3. Android之toolbar的使用
  4. Android(安卓)SDK2.2离线安装
  5. Android(安卓)Dalvik ART
  6. Android(安卓)Studio与Genymotion模拟器结合使用的一些心得
  7. Android(安卓)反编译apk文件得到项目文件
  8. Android中设置Button的颜色形状圆角
  9. 【Android性能优化】使用NDK进行Java和C++混编

随机推荐

  1. android SharedPreferences
  2. Android最全面试题库(转)
  3. Android 开发中的倒计时
  4. Android中使Dialog显示时背景不变暗
  5. Android出现java.lang.RuntimeException:
  6. Android UI系列 - 布局 - 目录
  7. Android系统文件夹结构详细解析
  8. Android的网络状态判断
  9. SlidingMenu和ActionBarSherlock结合做出
  10. Android如何获得系统版本