Android9开机启动与FBE过程完整介绍与LOG流程

一,开机整体流程概述

Android9开机启动与FBE过程完整介绍与LOG流程_第1张图片 

Init进程作为Android的第一个user space(用户空间)的进程,它是所有 Android 系统 native service 的祖先,它的进程号是 1。

init进程工作分为第一阶段和第二阶段。

二,init fisrt stage 

代码参考: http://androidxref.com/9.0.0_r3/xref/system/core/init/init.cpp 

init第一阶段都是为第二阶段准备的工作,主要工作如下:

  • ueventd/watchdogd跳转以及其它初始化
  • 挂载基础文件系统并创建目录
  • 初始化日志输出(InitKernelLogging)
  • 挂载分区设备 (mount fstab)
  • 启用SELinux安全策略
  • 开始第二阶段前的准备。

1, ueventd跟watchdogd

从init进程的Android.bp可以看到,ueventd跟watchdogd都是Init进程的软连接。

symlinks: [
"sbin/ueventd",
"sbin/watchdogd",
],

ueventd进程用来管理设备,如果有新设备插入,就会在/dev创建对应的设备文件。ueventd会fork一个新的子进程做检测工作。

watchdogd进程是看门狗程序,每隔一段时间通过系统调用write向内核看门狗设备发一个信息,以确保系统正常运行。

2,挂载基础文件,创建目录。

3,InitKernelLogging

init进程是用户空间进程,为了把LOG打印到Kernel log里面,需要初始化InitKernelLogging。InitKernelLogging的源码路径是 system/core/init/log.cpp,该函数首先是将标准输入输出重定向到"/sys/fs/selinux/null",然后调用InitLogging初始化log日志系统。

4,DoFirstStageMount

http://androidxref.com/9.0.0_r3/xref/system/core/init/init_first_stage.cpp   DoFirstStageMount()
Cross Reference: /system/core/fs_mgr/fs_mgr_fstab.cpp (androidxref.com)

fs_mgr流程是先从启动命令行中获取bootdir 拼接字符串得到 fstab的位置 

通过mount fstab,加载UFS中 system vendor 分区文件系统。

三,init second stage

1,加载system vendor 分区的selinux规则

2,初始化Property与property_service

      加载property service是因为init.rc 很多触发时机是通过property 回调执行的。

3,加载system vendor各种init.rc脚本

4,解析nit.rc 

     下面为各个section的执行顺序,英文编号的section是系统内建的,数字是可客制化的。

1) early-init

a) wait_for_coldboot_done

b) property_init

c) keychord_int

d) console_init

e) set_init_properties

2) init

3) early-fs

4) fs

5) post-fs

6) post-fs-data

f) property_service_init

g) signal_init

h) check_startup

7) early-boot

8) boot

9) service

5,其中解析厂商的规则

其中高通的init.target.rc中:

on fs
# exec u:r:vendor_init:s0 -- /vendor/bin/init.qti.getbootdevice.sh
mount_all /vendor/etc/fstab.qcom

 挂载/data分区。此过程结果接下面第四章节FBE过程。

四,FBE过程

1, 进入FBE加密

init进程处理 do_mount_all() 函数,会根据mount_all /vendor/etc/fstab.qcom 结果配置系统属性。 

if (ret== FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION) {

        //如果fstab里设置了默认加密,则设置下面这个属性

       property_set("vold.decrypt","trigger_encryption");

    } elseif (ret == FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED) {

        //如果设备已经加密,则我们需要做一些处理:

       property_set("ro.crypto.state","encrypted");

        property_set("vold.decrypt", "trigger_default_encryption");

    } elseif (ret == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED){

       //如果设备没有加密,则不需要做什么处理,和以前一样

       property_set("ro.crypto.state","unencrypted");

       action_for_each_trigger("nonencrypted", action_add_queue_tail);

init.rc 进入encrypt 状态

on property:vold.decrypt=trigger_encryption

start encrypt 

查看vdc.rc,通过exec 加上参数调用自己:

# One shot invocation to deal with encrypted volume.
on defaultcrypto
    exec - root -- /system/bin/vdc --wait cryptfs mountdefaultencrypted
    # vold will set vold.decrypt to trigger_restart_framework (default
    # encryption) or trigger_restart_min_framework (other encryption)

# One shot invocation to encrypt unencrypted volumes
on encrypt
    start surfaceflinger
    exec - root -- /system/bin/vdc --wait cryptfs enablecrypto
    # vold will set vold.decrypt to trigger_restart_framework (default
    # encryption)
vdc是个可执行文件,实际上功能不是vdc实现的,vdc是通过binder给VOLD发送响应的消息来实现的。具体代码跳过。

FBE相关技术参考下面文档

【数据安全】4. Android 文件级加密(File-based Encryption)之密钥管理_android fbe_zs.w的博客-CSDN博客

2,创建用户0

/system/core/rootdir/init.rc 中,on post-fs-data最后一个步骤是创建用户0:

on post-fs-data
    init_user0
查看 这个动作的代码/system/core/init/builtins.cpp,也是调用vdc来完成:
static Result do_init_user0(const BuiltinArguments& args) {
    return ExecWithRebootOnFailure(
        "init_user0_failed",
        {{"exec", "/system/bin/vdc", "--wait", "cryptfs", "init_user0"}, args.context});
}

​
和前面一样,VDC也是给vold发送消息,过程不再细说。

五,Android相关加载过程介绍

android加载两部分,一部分是在native 时候加载的,如surfaceflinger, ServiceManager, MediaServer。主要是为了完成跨进程通信和播放开机动画。不影响开机动画的服务由SystemServer加载。

Android9开机启动与FBE过程完整介绍与LOG流程_第2张图片

service surfaceflinger /system/bin/surfaceflinger
    class core animation
    user system
    group graphics drmrpc readproc
    onrestart restart zygote

对应init.rc的脚本

on boot
    # Start standard binderized HAL daemons
    class_start hal

    class_start core

on nonencrypted
    class_start main
    class_start late_start

第二部分是zygote完成的加载,这部分网络资料很多,不再继续描述。

六,开机过程LOG介绍

为了让vold log打印在kernel log中,需要修改一下vold与kernel printk.

system/vold/main.cpp修改一下:

int main(int argc, char** argv) {
    atrace_set_tracing_enabled(false);
    if (getppid() == 1) {
        // If init is calling us then it's during boot and we should log to kmsg
        android::base::InitLogging(argv, &android::base::KernelLogger);
    } else {
        setenv("ANDROID_LOG_TAGS", "*:v", 1);
        android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM));
    }

kernel/msm-4.14/kernel/printk/printk.c  删掉两行限制kernel log打印

static ssize_t devkmsg_write(struct kiocb *iocb, struct iov_iter *from)
{
	char *buf, *line;
	int level = default_message_loglevel;
	int facility = 1;	/* LOG_USER */
	struct file *file = iocb->ki_filp;
	struct devkmsg_user *user = file->private_data;
	size_t len = iov_iter_count(from);
	ssize_t ret = len;

	if (!user || len > LOG_LINE_MAX)
		return -EINVAL;

	/* Ignore when user logging is disabled. */
	if (devkmsg_log & DEVKMSG_LOG_MASK_OFF)
		return len;

	/* Ratelimit when not explicitly enabled. */
	if (!(devkmsg_log & DEVKMSG_LOG_MASK_ON)) {
        //删掉下面两行
		//if (!___ratelimit(&user->rs, current->comm))
		//	return ret;
	}

LOG打印参考

#这可以看作LINUX启动标志
01-01 08:00:00.000     0     0 I         : Booting Linux on physical CPU 0x0
01-01 08:00:00.016     0     0 I SELinux : Initializing.
#VFS加载后,可以进入第一阶段挂载文件系统
01-01 08:00:02.484     0     0 I VFS     : Mounted root (ext4 filesystem) readonly on device 253:0.
01-01 08:00:02.489     0     0 I         : Freeing unused kernel memory: 6144K
01-01 08:00:02.514     0     0 I init    : init first stage started!
01-01 08:00:02.515     0     0 I init    : Using Android DT directory /proc/device-tree/firmware/android/
01-01 08:00:02.520     0     0 I init    : [libfs_mgr]fs_mgr_read_fstab_default(): failed to find device default fstab
01-01 08:00:02.790     0     0 I         : init (266) used greatest stack depth: 13264 bytes left
01-01 08:00:02.793     0     0 I init    : [libfs_mgr]Enabling dm-verity for vendor (mode 0)
01-01 08:00:02.798     0     0 I device-mapper: verity: sha256 using implementation "sha256-ce"
01-01 08:00:02.816     0     0 I init    : [libfs_mgr]__mount(source=/dev/block/dm-0,target=/vendor,type=ext4)=0: Success
01-01 08:00:02.817     0     0 I init    : Skipped setting INIT_AVB_VERSION (not in recovery mode)
01-01 08:00:02.819     0     0 I init    : Loading SELinux policy
01-01 08:00:03.856     0     0 I selinux : SELinux: Loaded file_contexts
#/system与/vendor挂载后,可以开始解析里面的.rc文件
01-01 08:00:03.863     0     0 I init    : init second stage started!
01-01 08:00:03.996     0     0 I init    : Parsing file /init.rc...

01-01 08:00:05.114     0     0 I init    : processing action (early-init) from (/init.rc:14)
01-01 08:00:05.122     0     0 I init    : starting service 'ueventd'...

01-01 08:00:05.576     0     0 I ueventd : Coldboot took 0.372 seconds
01-01 08:00:05.582     0     0 I init    : wait for '/dev/.coldboot_done' took 239ms

01-01 08:00:05.683     0     0 I init    : processing action (SetMmapRndBits) from (:0)
01-01 08:00:05.685     0     0 I init    : processing action (SetKptrRestrict) from (:0)
01-01 08:00:05.686     0     0 I init    : processing action (keychord_init) from (:0)
01-01 08:00:05.688     0     0 E init    : could not open /dev/keychord: No such file or directory
01-01 08:00:05.689     0     0 I init    : processing action (console_init) from (:0)
01-01 08:00:05.690     0     0 I init    : processing action (init) from (/init.rc:41)

01-01 08:00:05.788     0     0 I init    : processing action (late-init) from (/init.rc:278)
01-01 08:00:05.790     0     0 I init    : processing action (late-init) from (/system/etc/init/atrace.rc:3)
01-01 08:00:05.798     0     0 I init    : processing action (queue_property_triggers) from (:0)
01-01 08:00:05.801     0     0 I init    : processing action (early-fs) from (/vendor/etc/init/hw/init.target.rc:46)
01-01 08:00:05.808     0     0 I init    : processing action (fs) from (/vendor/etc/init/hw/init.target.rc:54)

#开始挂载/data分区
01-01 08:00:07.060     0     0 I init    : Command 'mount_all /vendor/etc/fstab.qcom' action=fs (/vendor/etc/init/hw/init.target.rc:56) took 1248ms and succeeded

#启动servicemanager等
01-01 08:00:07.218     0     0 I init    : Command 'load_system_props' action=post-fs (/init.rc:317) took 124ms and succeeded
01-01 08:00:07.219     0     0 I init    : starting service 'logd'...
01-01 08:00:07.223     0     0 I init    : starting service 'servicemanager'...
01-01 08:00:07.226     0     0 I init    : starting service 'hwservicemanager'...
01-01 08:00:07.227     0     0 I init    : Created socket '/dev/socket/logd', mode 666, user 1036, group 1036
01-01 08:00:07.230     0     0 I init    : starting service 'vndservicemanager'...

#根据'mount_all /vendor/etc/fstab.qcom'的结果,启动vold开始FBE加密
01-01 08:00:07.325     0     0 I init    : processing action (post-fs-data) from (/init.rc:384)
01-01 08:00:07.348     0     0 I init    : starting service 'exec 4 (/system/bin/vdc --wait cryptfs enablefilecrypto)'...
01-01 08:00:07.423     0     0 I vold    : e4crypt_initialize_global_de
01-01 08:00:07.424     0     0 I vold    : Creating new key in /data/unencrypted/key

#根据init.rc on post-fs-data最后动作,创建user0
01-01 08:00:07.635     0     0 I init    : starting service 'exec 5 (/system/bin/vdc --wait cryptfs init_user0)'...
01-01 08:00:07.778     0     0 I vold    : Policy for /data/system_de/0 set to 74252c5158d80351 modes 127/4
01-01 08:00:07.779     0     0 I vold    : Policy for /data/misc_de/0 set to 74252c5158d80351 modes 127/4
01-01 08:00:07.781     0     0 I vold    : Policy for /data/vendor_de/0 set to 74252c5158d80351 modes 127/4
01-01 08:00:07.782     0     0 I vold    : Policy for /data/user_de/0 set to 74252c5158d80351 modes 127/4

#启动zygote
01-01 08:00:07.985     0     0 I init    : processing action (ro.crypto.state=encrypted && ro.crypto.type=file && zygote-start) from (/init.rc:575)
01-01 08:00:07.987     0     0 I init    : starting service 'update_verifier_nonencrypted'...

#后面进入android server与APP启动阶段。最后到boot_completed进入桌面。
01-01 08:00:08.023     0     0 I init    : starting service 'zygote'...
01-01 08:00:08.442   385   385 D AndroidRuntime: >>>>>> START com.android.internal.os.ZygoteInit uid 0 <<<<<<
01-01 08:00:08.442   385   385 I boot_progress_start: 8442
01-01 08:00:09.576   385   385 I boot_progress_preload_start: 9576
01-01 00:00:43.484   385   385 I boot_progress_preload_end: 10679
01-01 00:00:44.320   865   865 I boot_progress_system_run: 11515
01-01 00:00:48.177   865   865 I boot_progress_pms_start: 15372
01-01 00:00:48.206   865   865 I boot_progress_pms_system_scan_start: 15401
01-01 00:00:49.676   865   865 I boot_progress_pms_data_scan_start: 16871
01-01 00:00:49.685   865   865 I boot_progress_pms_scan_end: 16880
01-01 00:00:49.999   865   865 I boot_progress_pms_ready: 17194
01-01 00:01:13.262   865   865 I boot_progress_ams_ready: 40457
01-01 00:01:15.176   865  1073 I boot_progress_enable_screen: 42371

你可能感兴趣的:(服务器,前端,网络,linux,android)