Init进程作为Android的第一个user space(用户空间)的进程,它是所有 Android 系统 native service 的祖先,它的进程号是 1。
init进程工作分为第一阶段和第二阶段。
代码参考: http://androidxref.com/9.0.0_r3/xref/system/core/init/init.cpp
init第一阶段都是为第二阶段准备的工作,主要工作如下:
从init进程的Android.bp可以看到,ueventd跟watchdogd都是Init进程的软连接。
symlinks: [
"sbin/ueventd",
"sbin/watchdogd",
],
ueventd进程用来管理设备,如果有新设备插入,就会在/dev创建对应的设备文件。ueventd会fork一个新的子进程做检测工作。
watchdogd进程是看门狗程序,每隔一段时间通过系统调用write向内核看门狗设备发一个信息,以确保系统正常运行。
init进程是用户空间进程,为了把LOG打印到Kernel log里面,需要初始化InitKernelLogging。InitKernelLogging的源码路径是 system/core/init/log.cpp,该函数首先是将标准输入输出重定向到"/sys/fs/selinux/null",然后调用InitLogging初始化log日志系统。
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 分区文件系统。
加载property service是因为init.rc 很多触发时机是通过property 回调执行的。
下面为各个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
其中高通的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过程。
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博客
/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加载两部分,一部分是在native 时候加载的,如surfaceflinger, ServiceManager, MediaServer。主要是为了完成跨进程通信和播放开机动画。不影响开机动画的服务由SystemServer加载。
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完成的加载,这部分网络资料很多,不再继续描述。
为了让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