Android R开机流程跟踪-----init.rc和启动Zygote

概述

init.rc是非常重要的配置文件,它是由Android 初始化语言(Android Init Language)编写的脚本,这种语言主要包含5种类型语句:Action、Command、Service、Option和Import。
具体语法可以查阅README.md,位于:Android11\system\core\init,在这里语法不具体发散,详情网上查阅,有很多资料。
在这里插入图片描述
nit.rc有两个,分别位于:
Android11/system/core/rootdir/init.rc
Android11/bootable/recovery/etc/init.rc
在Android11/system/core/rootdir/init.rc中,关注一句:import /system/etc/init/hw/init.${ro.zygote}.rc
在这里插入图片描述

一个是设备文件路径(机器里面的路径),一个是代码文件路径,不要搞混了。

查询机器的系统属性getprop ro.zygote 得:zygote32,所以RT51R是32位系统。
在机器路径/system/etc/init/hw,ls得:init.rc处的import /system/etc/init/hw/init.${ro.zygote}.rc,就是init.zygote32.rc。
在这里插入图片描述

init启动Zygote

`class_start <serviceclass>`
> Start all services of the specified class if they are
  not already running.  See the start entry for more information on
  starting services.
command是action的命令列表中的命令,或者是service中的选项 onrestart 的参数命令,命令将在所属事件发生时被一个个地执行.
列举常用的命令
class_start <service_class_name>: 启动属于同一个class的所有服务;
class_stop <service_class_name> : 停止指定类的服务
start <service_name>: 启动指定的服务,若已启动则跳过;
stop <service_name>: 停止正在运行的服务
setprop <name> <value>:设置属性值
mkdir <path>:创建指定目录
symlink <target> <sym_link>: 创建连接到<target><sym_link>符号链接;
write <path> <string>: 向文件path中写入字符串;
exec: fork并执行,会阻塞init进程直到程序完毕;
exprot <name> <name>:设定环境变量;
loglevel <level>:设置log级别
hostname <name> : 设置主机名
import <filename> :导入一个额外的init配置文件

init.rc解析:

介绍从SecondStageMain到do_class_start这一执行流程如下:

在这里插入图片描述在init.rc中有如下配置代码:

on nonencrypted
    class_start main
    class_start late_start

其中class_star是一个COMMAND,对应的函数为do_class_start。启动init.rc中那些设ClassName为main的Service。Zygote的classname就是main,因此class_start main是用来启动Zygote的。do_class_start函数在builtins.cpp中定义。do_class_start在上述流程图中,最后被InvokeFunc调用。
在这里插入图片描述

init启动Zygote32.rc

文件内容如下:

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server           //进程名为Zygote,执行程序为app_process
    class main        //classname为main
    priority -20
    user root
    group root readproc reserved_disk
    socket zygote stream 660 root system
    socket usap_pool_primary stream 660 root system
    onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    onrestart restart wificond
    writepid /dev/cpuset/foreground/tasks

Services
Services are programs which init launches and (optionally) restarts
when they exit. Services take the form of:

service <name> <pathname> [ <argument> ]*     //<service 的名字><执行程序路径><传递参数>
   <option>                                   //option是Service的修饰词,影响什么时候、如何启动Service
   <option>
   ...

Zygote启动流程

1、builtins.cpp的函数:do_class_start

在这里插入图片描述

2、service.cpp的函数:StartIfNotDisabled

如果Service没有在其对应的rc文件中设置disable选项,则会调用Start()函数启动该Service,Zygote32.rc中没有设置disable选项,因此会执行Start函数。
在这里插入图片描述

3、Start函数:

Result<void> Service::Start() {
    ……
    if (flags_ & SVC_RUNNING) {    //如果 Service已经运行,则不启动
        if ((flags_ & SVC_ONESHOT) && disabled) {
            flags_ |= SVC_RESTART;
        }
        // It is not an error to try to start a service that is already running.
        reboot_on_failure.Disable();
        return {};
    }

    bool needs_console = (flags_ & SVC_CONSOLE);
    if (needs_console) {
        if (proc_attr_.console.empty()) {
            proc_attr_.console = "/dev/" + GetProperty("ro.boot.console", "console");
        }

        // Make sure that open call succeeds to ensure a console driver is
        // properly registered for the device node
        int console_fd = open(proc_attr_.console.c_str(), O_RDWR | O_CLOEXEC);
        if (console_fd < 0) {
            flags_ |= SVC_DISABLED;
            return ErrnoError() << "Couldn't open console '" << proc_attr_.console << "'";
        }
        close(console_fd);
    }
    //判断需要启动的Service的对应的执行文件是否存在,不存在则不启动该Service
    struct stat sb;
    if (stat(args_[0].c_str(), &sb) == -1) {
        flags_ |= SVC_DISABLED;
        return ErrnoError() << "Cannot find '" << args_[0] << "'";
    }

    ……

    pid_t pid = -1;
    if (namespaces_.flags) {
        pid = clone(nullptr, nullptr, namespaces_.flags | SIGCHLD, nullptr);
    } else {
        pid = fork();  //如果子进程没有启动,则调用fork函数创建子进程
    }

    if (pid == 0) {   //当前代码逻辑在子进程中运行
        umask(077);

        if (auto result = EnterNamespaces(namespaces_, name_, pre_apexd_); !result.ok()) {
            LOG(FATAL) << "Service '" << name_
                       << "' failed to set up namespaces: " << result.error();
        }

        for (const auto& [key, value] : environment_vars_) {
            setenv(key.c_str(), value.c_str(), 1);
        }

        for (const auto& descriptor : descriptors) {
            descriptor.Publish();
        }

        if (auto result = WritePidToFiles(&writepid_files_); !result.ok()) {
            LOG(ERROR) << "failed to write pid to files: " << result.error();
        }

        if (task_profiles_.size() > 0 && !SetTaskProfiles(getpid(), task_profiles_)) {
            LOG(ERROR) << "failed to set task profiles";
        }

        // As requested, set our gid, supplemental gids, uid, context, and
        // priority. Aborts on failure.
        SetProcessAttributesAndCaps();

        if (!ExpandArgsAndExecv(args_, sigstop_)) {  //调用execve函数,子进程就会被启动
            PLOG(ERROR) << "cannot execv('" << args_[0]
                        << "'). See the 'Debugging init' section of init's README.md for tips";
        }

        _exit(127);
    }

    ……
    return {};
}

4、ExpandArgsAndExecv函数:

//调用execve函数,子进程就会被启动
static bool ExpandArgsAndExecv(const std::vector<std::string>& args, bool sigstop) {
    std::vector<std::string> expanded_args;
    std::vector<char*> c_strings;

    expanded_args.resize(args.size());
    c_strings.push_back(const_cast<char*>(args[0].data()));
    for (std::size_t i = 1; i < args.size(); ++i) {
        auto expanded_arg = ExpandProps(args[i]);
        if (!expanded_arg.ok()) {
            LOG(FATAL) << args[0] << ": cannot expand arguments': " << expanded_arg.error();
        }
        expanded_args[i] = *expanded_arg;
        c_strings.push_back(expanded_args[i].data());
    }
    c_strings.push_back(nullptr);

    if (sigstop) {
        kill(getpid(), SIGSTOP);
    }

    return execv(c_strings[0], c_strings.data()) == 0;
}

5、app_main.cpp的main函数:

Service子进程被启动,并进去该service的main函数中,Zygote执行程序的路径为/system/bin/app_process,对应的文件为app_main.cpp,这样就会进去app_main.cpp的main函数中,也就是Zygote的main函数。

int main(int argc, char* const argv[])
{
    ……
    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);  
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
    }
}
调用runtime的start函数启动Zygote,至此Zygote就启动了。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值