Android14 - init进程的启动过程

1,440 阅读18分钟

最近在学习Android Framework相关的东西,很多内容都与Android系统启动关系密切,因此需要特地记录。其中init进程是Andorid系统中用户空间的第一个进程,进程号为1,是Android系统启动流程中比较关键的步骤。

init进程由多个源文件共同组成,这个文件位于源码目录system/core/init中。

环境参数:

  • android-14.0.0_r27
  • Ubuntu 22.04.5 LTS

在线源码网址:xrefandroid

init进程的定位

了解init进程,就需要先了解Android系统启动的前几步,从而找到init进程在系统中的定位。

Android系统的启动主要分为5个步骤:

  • Loader → Kernel → Native → Framework → Application

上图是网上某大佬总结,借鉴重新绘制了下加深印象=。=

Loader

  • Boot ROM:当我们按下电源,引导芯片代码会从预定义的位置(固化在ROM中)开始执行,加载引导程序BootLoader到RAM中,然后执行。
  • Boot Loader:引导操作系统启动,把系统OS拉起来,是Android操作系统开始运行前的一个小程序,主要功能由检查RAM,初始化硬件外设参数等功能。

Kernel

Android内核层,系统的发起点。

  • swapper进程也称为交换(idle)进程由系统自动创建,运行在内核态,进程id为0,是系统创建的第一个进程,也是唯一一个没有通过fork或者kernel_thread产生的进程。用于初始化进程管理,内存管理,加载Camera,Binder,Display,Input等驱动工作。
  • kthreadd进程是idle通过kernel_thread创建,进程id为2,始终运行在内核空间,主要是负责内核线程的调度和管理。

Native

Native层,也就是Framework层中C++的那一部分,主要包括由init进程孵化出的用户进程,HAL层,Binder的管理者ServiceManager以及启动动画,Media Server等。

  • init进程是idle通过kernel_thread创建,在内核空间完成初始化,加载init进程,最后转变为用户空间的init进程,是其他所有用户进程的鼻祖
  • HAL层是硬件和软件之间的桥梁。Android把对硬件的操作分成了两部分,HAL和内核驱动,HAL实现在用户空间,驱动在内核空间。Linux内核中的代码需要开源,用户空间不需要,因此这样可以保护厂家的利益。
  • Media Server由init进程fork而来,负责启动和管理AudioFlinger,MediaPlayerService等服务。

Framework

Framework层中纯Java的那一部分,通过JNI与Native层通信。

  • 启动Zygote进程,加载ZygoteInit类,注册Zygote Socket服务端套接字;加载虚拟机,加载类和系统资源 —— fork出来的进程天生就有自己的虚拟机和系统资源。
  • System Server由Zygote进程fork而来,System Server是Zygote孵化出来的第一个进程,负责启动和管理整个Java Framework,包括AMS,WMS,PMS等

Application

应用层。

  • Launcher是Zygote孵化的第一个App进程
  • 所有的App都是由Zygote孵化而来

从上面的步骤来看,当我们按下电源,系统启动会先加载引导程序,引导程序又去启动Linux内核,开天辟地产生第一个进程swapper,Linux内核加载完成后,首先就是启动init进程。

init进程的启动

init进程是由swapper进程启动的,而swapper进程位于kernel层,因此启动init进程的地方应该位于kernel层:

AOSP目录中没有找到bsp的代码,就找了个线上的:lxr.linux.no/#linux+v6.7…

@init/main.c
asmlinkage __visible void __init start_kernel(void)
{
    char *command_line;
    char *after_dashes;

    set_task_stack_end_magic(&init_task);
    smp_setup_processor_id();//打印了驱动加载的第一行log
    ... 
    //初始化一系列系统底层机制
    pr_notice("%s", linux_banner);//打印内核版本信息
    ...
    pr_notice("Kernel command line: %s\n", saved_command_line);//打印从uboot传递过来的command_line字符串
    ...
    /* Do the rest non-__init'ed, we're now alive */
    arch_call_rest_init();//创建init进程、kthread进程、idle进程
    prevent_tail_call_optimization();
}

arch_call_rest_init方法继续往下走:

@init/main.c
void __init __weak arch_call_rest_init(void)
{
    rest_init();
}

noinline void __ref rest_init(void)
{
    ...
    pid = kernel_thread(kernel_init, NULL, CLONE_FS);//创建init进程
    ...
    pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);//创建kthreadd进程
    ...
    /* Call into cpu_idle with preempt disabled */
    cpu_startup_entry(CPUHP_ONLINE);//设置当前进程为idle进程
}

通过kernel_thread创建了init进程,init进程入口函数:system/core/init/main.cpp

@system/core/init/main.cpp
int main(int argc, char** argv) {
    ...
    if (argc > 1) {
        if (!strcmp(argv[1], "subcontext")) {
            android::base::InitLogging(argv, &android::base::KernelLogger);
            const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();

            return SubcontextMain(argc, argv, &function_map);
        }

        if (!strcmp(argv[1], "selinux_setup")) {
            return SetupSelinux(argv);
        }

        if (!strcmp(argv[1], "second_stage")) {
            return SecondStageMain(argc, argv);
        }
    }

    return FirstStageMain(argc, argv);
} 

程序根据传递的参数执行对应的方法,根据方法名,首先查看FirstStageMain()的操作:

@system/core/init/first_stage_init.cpp#FirstStageMain
int FirstStageMain(int argc, char** argv) {
    ...
    // Clear the umask.
    umask(0);
    
    //创建和挂载启动所需要的文件目录
    CHECKCALL(mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"));
    CHECKCALL(mkdir("/dev/pts", 0755));
    CHECKCALL(mkdir("/dev/socket", 0755));
    CHECKCALL(mkdir("/dev/dm-user", 0755));
    CHECKCALL(mount("devpts", "/dev/pts", "devpts", 0, NULL));
    CHECKCALL(mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC)));

    CHECKCALL(setgroups(arraysize(groups), groups));
    CHECKCALL(mount("sysfs", "/sys", "sysfs", 0, NULL));
    CHECKCALL(mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL));
    ...
    CHECKCALL(mount("tmpfs", "/mnt", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
                    "mode=0755,uid=0,gid=1000"));
   
     ...
     //初始化Kernel的Log,这样外界可以获取Kernel的日志
     InitKernelLogging(argv);
}

这在第一步中,创建和挂载启动需要的文件目录,其中挂载了tmpfs,devpts,proc,sysfs和selinuxfs五种文件系统,这些都是系统运行时候才有的目录,也就是说如果系统没有运行,则不会有这些目录。

再来看SecondStageMain()方法:

@system/core/init/init.cpp#SecondStageMain
int SecondStageMain(int argc, char** argv) {
   ...
   //1.初始化属性服务
   PropertyInit();

   ...
    //2.初始化子进程终止信号处理函数
    Epoll epoll;
    if (auto result = epoll.Open(); !result.ok()) {
        PLOG(FATAL) << result.error();
    }
    InstallSignalFdHandler(&epoll);
    InstallInitNotifier(&epoll);
    //3.设置其他系统属性并开启系统属性服务
    StartPropertyService(&property_fd);

    ...
    ActionManager& am = ActionManager::GetInstance();
    //单例类ServiceList
    ServiceList& sm = ServiceList::GetInstance();
    //4.解析init.rc等文件,建立rc文件的action 、service
    LoadBootScripts(am, sm);


    while (true) {
        ...
        if (!IsShuttingDown()) {
            //注意此处,后续包有用的
            HandleControlMessages();
            SetUsbController();
        }
    }

    return 0;
}

注释已经比较清楚了:

  • 第一步是初始化属性服务;
  • 第二步主要是为了防止init进程的子进程成为僵尸进程,系统会在子进程暂停和终止的时候发出SIGCHLD信号,而InstallSignalFdHandler函数就是用来接收SIGCHLD信号的。

    比如init进程的子进程Zygote进程终止了,InstallSignalFdHandler函数内部会调用HandleSignalFd函数,经过一系列的调用和处理,最终会找到Zygote进程并且移除所有Zygote进程的信息,再重启Zygote服务的启动脚本(init.Zygote64.rc)中带有onrestart选项的服务。

  • 第三步启动属性服务,监听属性变化,与第一步呼应
  • 第四步解析init.rc文件

总结:init进程的启动源于Kernel,作为第一个用户进程,在入口函数中主要创建和挂载文件目录,初始化和启动了属性服务,解析init.rc文件等。

解析init.rc

init.rc是非常重要的配置文件,文件位于system/core/rootdir/init.rc,它是由Android初始化语言编写的脚本,这种语言包含5种类型语句:Action、Command、Service、Option和Import。

粗略看下init.rc文件:

@system/core/rootdir/init.rc
on init
  sysclktz 0

   # Mix device-specific information into the entropy pool
   copy /proc/cmdline /dev/urandom
   copy /system/etc/prop.default /dev/urandom
    ...
on boot
    # basic network init
    ifup lo
    hostname localhost
    domainname localdomain

    # Start standard binderized HAL daemons
    class_start hal

    class_start core
    ...
on nonencrypted
    class_start main
    class_start late_start

其中on init, on boot, on nonencrypted属于Action类型的语句,表示触发时机;下面的class_start main类型的语句属于Command,表示动作触发之后要执行的命令。

需要注意的是从Android8.0开始对init.rc做了拆分,每个服务对应一个rc文件。Zygote启动脚本在init.zygoteXX.rc中定义,其中XX表示为处理器位数,一般我们用init.zygote64.rc:

@system/core/rootdir/init.zygote64.rc
//1
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
    class 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
    # NOTE: If the wakelock name here is changed, then also
    # update it in SystemSuspend.cpp
    onrestart write /sys/power/wake_lock zygote_kwl
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart media.tuner
    onrestart restart netd
    onrestart restart wificond
    task_profiles ProcessCapacityHigh MaxPerformance
    critical window=${zygote.critical_window.minute:-off} target=zygote-fatal

其中注释1这一行,service表示这语句为Service类型, zygote表示service的名字为zygote,/system/bin/app_process64表示进程的程序路径,这一行后面代码都是要传递给app_process64的参数。 下面的参数为Option类型语句,其中class mian表示Zygote此服务的服务类型为main(此点后面会用到)

解析Service类型语句

Service类型语句由ServiceParser来解析,解析实现代码在system/core/init/service_parser.cpp中:

@system/core/init/service_parser.cpp#ParseSection
//ParseSection主要用来搭建Service的架子
Result<void> ServiceParser::ParseSection(std::vector<std::string>&& args,
                                         const std::string& filename, int line) {
    if (args.size() < 3) {
        return Error() << "services must have a name and a program";
    }

    const std::string& name = args[1];
    if (!IsValidName(name)) {
        return Error() << "invalid service name '" << name << "'";
    }

    filename_ = filename;

    Subcontext* restart_action_subcontext = nullptr;
    if (subcontext_ && subcontext_->PathMatchesSubcontext(filename)) {
        restart_action_subcontext = subcontext_;
    }

    std::vector<std::string> str_args(args.begin() + 2, args.end());

    if (SelinuxGetVendorAndroidVersion() <= __ANDROID_API_P__) {
        if (str_args[0] == "/sbin/watchdogd") {
            str_args[0] = "/system/bin/watchdogd";
        }
    }
    if (SelinuxGetVendorAndroidVersion() <= __ANDROID_API_Q__) {
        if (str_args[0] == "/charger") {
            str_args[0] = "/system/bin/charger";
        }
    }
    //构建了一个service对象
    service_ = std::make_unique<Service>(name, restart_action_subcontext, filename, str_args);
    return {};
}

@system/core/init/service_parser.cpp#ParseLineSection
//ParseLineSection主要是用来解析子项的
Result<void> ServiceParser::ParseLineSection(std::vector<std::string>&& args, int line) {
    if (!service_) {
        return {};
    }

    auto parser = GetParserMap().Find(args);

    if (!parser.ok()) return parser.error();

    return std::invoke(*parser, this, std::move(args));
}

在ParseSection创建service对象,在ParseLineSection解析完所有数据后,就会调用EndSection方法:

@system/core/init/service_parser.cpp#EndSection
Result<void> ServiceParser::EndSection() {
    if (!service_) {
        return {};
    }

    if (interface_inheritance_hierarchy_) {
        if (const auto& check_hierarchy_result = CheckInterfaceInheritanceHierarchy(
                    service_->interfaces(), *interface_inheritance_hierarchy_);
            !check_hierarchy_result.ok()) {
            return Error() << check_hierarchy_result.error();
        }
    }

    if (SelinuxGetVendorAndroidVersion() >= __ANDROID_API_R__) {
        if ((service_->flags() & SVC_CRITICAL) != 0 && (service_->flags() & SVC_ONESHOT) != 0) {
            return Error() << "service '" << service_->name()
                           << "' can't be both critical and oneshot";
        }
    }

    Service* old_service = service_list_->FindService(service_->name());
    if (old_service) {
        if (!service_->is_override()) {
            return Error() << "ignored duplicate definition of service '" << service_->name()
                           << "'";
        }

        if (StartsWith(filename_, "/apex/") && !old_service->is_updatable()) {
            return Error() << "cannot update a non-updatable service '" << service_->name()
                           << "' with a config in APEX";
        }

        std::string context = service_->subcontext() ? service_->subcontext()->context() : "";
        std::string old_context =
                old_service->subcontext() ? old_service->subcontext()->context() : "";
        if (context != old_context) {
            return Error() << "service '" << service_->name() << "' overrides another service "
                           << "across the treble boundary.";
        }

        service_list_->RemoveService(*old_service);
        old_service = nullptr;
    }
    //1
    service_list_->AddService(std::move(service_));

    return {};
}

其中注释1处的service_list_->RemoveService(*old_service)会走到单例类ServiceList中去,最终将service_对象添加到vector类型的Service链表中去,位于system/core/init/service_list.cpp

@system/core/init/service_list.h
//vector类型的链表
private:
   std::vector<std::unique_ptr<Service>> services_;
   
@system/core/init/service_list.cpp#AddService
void ServiceList::AddService(std::unique_ptr<Service> service) {
    services_.emplace_back(std::move(service));
}

总结:其实解析Service语句就是根据参数创建Serice对象,根据选项区域的内容填充Service对象,最后将Service对象加入到vector类型的Service链表中去。

如何启动Service

解析完Service,那如何启动Service呢?在init.rc中有如下配置:

@system/core/rootdir/init.rc
on boot
    # basic network init
    ifup lo
    hostname localhost
    domainname localdomain

    # Start standard binderized HAL daemons
    class_start hal

    class_start core
    
on nonencrypted
    class_start main
    class_start late_start

其中class_start是一个Command,对应函数为do_class_startclass_start main表示启动那些服务类型为main的Service,class_start core表示启动那些服务类型为core的Service:

比如:

在Zygote进程对应的rc文件中:

@system/core/rootdir/init.zygote64.rc
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
    class main
    ...

Zygot被定义为main类服务,因此class_start main就是用来启动Zygote的。

在bootanim进程对应的rc文件中:

@frameworks/base/cmds/bootanimation/bootanim.rc
service bootanim /system/bin/bootanimation
   class core animation
   user graphics
   group graphics audio
   //注意
   disabled
   oneshot
   ioprio rt 0
   task_profiles MaxPerformance

bootanim被定义为core类服务,animation表示用途,因此class_start core就是用来启动bootanim的。

do_class_start函数在builtins.cpp中定义:

@system/core/init/builtins.cpp#do_class_start
static Result<void> do_class_start(const BuiltinArguments& args) {
    // Do not start a class if it has a property persist.dont_start_class.CLASS set to 1.
    if (android::base::GetBoolProperty("persist.init.dont_start_class." + args[1], false))
        return {};
    // Starting a class does not start services which are explicitly disabled.
    // They must  be started individually.
    for (const auto& service : ServiceList::GetInstance()) {
        if (service->classnames().count(args[1])) {
            if (auto result = service->StartIfNotDisabled(); !result.ok()) {
                LOG(ERROR) << "Could not start service '" << service->name()
                           << "' as part of class '" << args[1] << "': " << result.error();
            }
        }
    }
    return {};
}

遍历ServiceList,找到classname为main的Zygote执行StartIfNotDisabled方法:

@system/core/init/service.cpp#StartIfNotDisabled
Result<void> Service::StartIfNotDisabled() {
    if (!(flags_ & SVC_DISABLED)) {//注意
        return Start();
    } else {
        flags_ |= SVC_DISABLED_START;
    }
    return {};
}

其中SVC_DISABLED表示Service没有在其对应的rc文件中设置disable选项,如果没有设置,则会调用Start函数启动该Service,否则就不启动。

bootanim对应的rc文件bootanim.rc中设置有disabled,因此不会直接被启动。 Zygote对应的init.zygote64.rc中并没有设置disable选项,因此可以直接调用Start函数启动。

@system/core/init/service.cpp#Start
Result<void> Service::Start() {
    ...
    //如果service已经在运行了,就不启动了
    if (flags_ & SVC_RUNNING) {
        if ((flags_ & SVC_ONESHOT) && disabled) {
            flags_ |= SVC_RESTART;
        }

        LOG(INFO) << "service '" << name_
                  << "' requested start, but it is already running (flags: " << flags_ << ")";

        // It is not an error to try to start a service that is already running.
        reboot_on_failure.Disable();
        return {};
    }

    ...
    //判断需要启动的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();
    }
    //当前代码逻辑在子进程中运行
    if (pid == 0) {
        umask(077);
        cgroups_activated.CloseWriteFd();
        setsid_finished.CloseReadFd();
        //最终执行execv函数,Service子进程被启动
        RunService(descriptors, std::move(cgroups_activated), std::move(setsid_finished));
        _exit(127);
    } else {
        cgroups_activated.CloseReadFd();
        setsid_finished.CloseWriteFd();
    }

    if (pid < 0) {
        pid_ = 0;
        return ErrnoError() << "Failed to fork";
    }

    ...

    return {};
}

RunService最终执行到ExpandArgsAndExecv函数:

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;
}

如果当前需要启动的Service是Zygote,进程被启动后,就会进入该Service的main函数中,由Zygote对应的rc文件init.zygote64.rc可知,Zygote执行程序路径为/system/bin/app_process64,对应的文件为app_main.cpp,这样就会进入到app_main.cpp的main函数中:

@frameworks/base/cmds/app_process/app_main.cpp#main
int main(int argc, char* const argv[])
{
    ...
    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (!className.isEmpty()) {
        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。

总结:系统根据rc文件中定义的action,在不同的阶段触发不同的Command,通过class_start xx去启动某一类服务。

为什么执行程序/system/bin/app_process64对应的执行文件是app_main.cpp?

frameworks目录搜索可执行程序名称app_process:

图片.png

查看frameworks/base/cmds/app_process/Android.bp文件

cc_binary {
    name: "app_process",

    srcs: ["app_main.cpp"],

    multilib: {
        lib32: {
            suffix: "32",
        },
        lib64: {
            suffix: "64",
        },
    },
    ...
}

定义了一个可执行文件app_process,根据不同处理器位数添加不同的后缀,其入口文件为app_main.cpp。

属性服务

init进程启动的时候就会去启动属性服务,并且会为其分配内存,用来存储这些属性,如果需要直接读取就可以了。init.cpp中关于属性服务的入口代码:

@system/core/init/init.cpp#SecondStageMain
PropertyInit();

StartPropertyService(&property_fd);

这两行代码分别是用来初始化属性服务和启动属性服务的。先来看PropertyInit函数

@system/core/init/property_service.cpp#PropertyInit
void PropertyInit() {
    selinux_callback cb;
    cb.func_audit = PropertyAuditCallback;
    selinux_set_callback(SELINUX_CB_AUDIT, cb);

    mkdir("/dev/__properties__", S_IRWXU | S_IXGRP | S_IXOTH);
    CreateSerializedPropertyInfo();
    if (__system_property_area_init()) {
        LOG(FATAL) << "Failed to initialize property area";
    }
    if (!property_info_area.LoadDefaultPath()) {
        LOG(FATAL) << "Failed to load serialized property info file";
    }

    // If arguments are passed both on the command line and in DT,
    // properties set in DT always have priority over the command-line ones.
    ProcessKernelDt();
    ProcessKernelCmdline();
    ProcessBootconfig();

    // Propagate the kernel variables to internal variables
    // used by init as well as the current required properties.
    ExportKernelBootProps();

    PropertyLoadBootDefaults();
}

PropertyInit函数主要就是用来初始化属性内存区域的。那如何启动属性服务的呢

@system/core/init/property_service.cpp#StartPropertyService
void StartPropertyService(int* epoll_socket) {
    InitPropertySet("ro.property_service.version", "2");//设置属性服务的版本为2

    int sockets[2];
    //创建一对套接字用于属性服务和init进程之间通信
    if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sockets) != 0) {
        PLOG(FATAL) << "Failed to socketpair() between property_service and init";
    }
    *epoll_socket = from_init_socket = sockets[0];
    init_socket = sockets[1];
    StartSendingMessages();
    //创建非阻塞socket
    if (auto result = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
                                   /*passcred=*/false, /*should_listen=*/false, 0666, /*uid=*/0,
                                   /*gid=*/0, /*socketcon=*/{});
        result.ok()) {
        property_set_fd = *result;
    } else {
        LOG(FATAL) << "start_property_service socket creation failed: " << result.error();
    }
    //监听property_set_fd,最大连接数为8
    listen(property_set_fd, 8);
    //创建线程执行,执行函数为PropertyServiceThread
    auto new_thread = std::thread{PropertyServiceThread};
    property_service_thread.swap(new_thread);
    ...
}

PropertyServiceThread函数执行逻辑:

@system/core/init/property_service.cpp#PropertyServiceThread
static void PropertyServiceThread() {
    Epoll epoll;
    if (auto result = epoll.Open(); !result.ok()) {
        LOG(FATAL) << result.error();
    }
    
    //1
    if (auto result = epoll.RegisterHandler(property_set_fd, handle_property_set_fd);
        !result.ok()) {
        LOG(FATAL) << result.error();
    }

    if (auto result = epoll.RegisterHandler(init_socket, HandleInitSocket); !result.ok()) {
        LOG(FATAL) << result.error();
    }

    while (true) {
        auto epoll_result = epoll.Wait(std::nullopt);
        if (!epoll_result.ok()) {
            LOG(ERROR) << epoll_result.error();
        }
    }
}

在注释1处,将property_set_fd放入epoll中,用epoll监听property_set_fd,当property_set_fd有数据来到时,init进程将调用handle_property_set_fd函数来进行处理。handle_property_set_fd函数最终会执行到HandlePropertySet函数:

std::optional<uint32_t> HandlePropertySet(const std::string& name, const std::string& value,
                                          const std::string& source_context, const ucred& cr,
                                          SocketConnection* socket, std::string* error) {
    //权限检查
    if (auto ret = CheckPermissions(name, value, source_context, cr, error); ret != PROP_SUCCESS) {
        return {ret};
    }
    //如果是ctl开头,则发送控制信息
    if (StartsWith(name, "ctl.")) {
        return {SendControlMessage(name.c_str() + 4, value, cr.pid, socket, error)};
    }

    if (name == "sys.powerctl") {
        std::string cmdline_path = StringPrintf("proc/%d/cmdline", cr.pid);
        std::string process_cmdline;
        std::string process_log_string;
        if (ReadFileToString(cmdline_path, &process_cmdline)) {
            process_log_string = StringPrintf(" (%s)", process_cmdline.c_str());
        }
        LOG(INFO) << "Received sys.powerctl='" << value << "' from pid: " << cr.pid
                  << process_log_string;
        if (value == "reboot,userspace" && !is_userspace_reboot_supported().value_or(false)) {
            *error = "Userspace reboot is not supported by this device";
            return {PROP_ERROR_INVALID_VALUE};
        }
    }

    if (name == kRestoreconProperty && cr.pid != 1 && !value.empty()) {
        static AsyncRestorecon async_restorecon;
        async_restorecon.TriggerRestorecon(value);
        return {PROP_SUCCESS};
    }

    return PropertySet(name, value, socket, error);
}

ctl开头的属于控制属性需要特殊处理,属性sys.powerctl跟重启关机相关,需要记录谁来设置的。其他属性则调用PropertySet来设置。

普通属性时,则调用PropertySet方法来设置

@system/core/init/property_service.cpp?#PropertySet
static std::optional<uint32_t> PropertySet(const std::string& name, const std::string& value,
                                           SocketConnection* socket, std::string* error) {
    size_t valuelen = value.size();
    //判断属性是否合法
    if (!IsLegalPropertyName(name)) {
        *error = "Illegal property name";
        return {PROP_ERROR_INVALID_NAME};
    }

    if (auto result = IsLegalPropertyValue(name, value); !result.ok()) {
        *error = result.error().message();
        return {PROP_ERROR_INVALID_VALUE};
    }
    //从属性存储空间查找该属性
    prop_info* pi = (prop_info*)__system_property_find(name.c_str());
    if (pi != nullptr) {
        // ro.* properties are actually "write-once".
        if (StartsWith(name, "ro.")) {
            *error = "Read-only property was already set";
            return {PROP_ERROR_READ_ONLY_PROPERTY};
        }
        //如果属性存在,就更新属性值
        __system_property_update(pi, value.c_str(), valuelen);
    } else {
        //如果属性不存在,就添加属性
        int rc = __system_property_add(name.c_str(), name.size(), value.c_str(), valuelen);
        if (rc < 0) {
            *error = "__system_property_add failed";
            return {PROP_ERROR_SET_FAILED};
        }
    }

    // Don't write properties to disk until after we have read all default
    // properties to prevent them from being overwritten by default values.
    //特殊处理名称开头为persist.的属性
    if (socket && persistent_properties_loaded && StartsWith(name, "persist.")) {
        if (persist_write_thread) {
            persist_write_thread->Write(name, value, std::move(*socket));
            return {};
        }
        WritePersistentProperty(name, value);
    }

    NotifyPropertyChange(name, value);
    return {PROP_SUCCESS};
}

如果是控制属性,则会调用SendControlMessage方法,最终会走到QueueControlMessage方法:

@system/core/init/init.cpp#QueueControlMessage
static std::queue<PendingControlMessage> pending_control_messages;

bool QueueControlMessage(const std::string& message, const std::string& name, pid_t pid, int fd) {
    auto lock = std::lock_guard{pending_control_messages_lock};
    if (pending_control_messages.size() > 100) {
        LOG(ERROR) << "Too many pending control messages, dropped '" << message << "' for '" << name
                   << "' from pid: " << pid;
        return false;
    }
    pending_control_messages.push({message, name, pid, fd});
    WakeMainInitThread();
    return true;
}

在QueueControlMessage方法中,会将控制属性放入pending_control_messages中,pending_control_messages为一个队列。

在上面init进程入口函数SecondStageMain()中,有一个while循环,里面会不断执行HandleControlMessages方法:

@system/core/init/init.cpp#HandleControlMessages
static void HandleControlMessages() {
    auto lock = std::unique_lock{pending_control_messages_lock};
    // Init historically would only execute handle one property message, including control messages
    // in each iteration of its main loop.  We retain this behavior here to prevent starvation of
    // other actions in the main loop.
    if (!pending_control_messages.empty()) {
        //消费
        auto control_message = pending_control_messages.front();
        pending_control_messages.pop();
        lock.unlock();

        bool success = HandleControlMessage(control_message.message, control_message.name,
                                            control_message.pid);

        uint32_t response = success ? PROP_SUCCESS : PROP_ERROR_HANDLE_CONTROL_MESSAGE;
        if (control_message.fd != -1) {
            TEMP_FAILURE_RETRY(send(control_message.fd, &response, sizeof(response), 0));
            close(control_message.fd);
        }
        lock.lock();
    }
    // If we still have items to process, make sure we wake back up to do so.
    if (!pending_control_messages.empty()) {
        WakeMainInitThread();
    }
}

在此函数中,恰好会对队列pending_control_messages执行pop操作,然后通过HandleControlMessage(control_message.message, control_message.name,control_message.pid)函数进行消费:

@system/core/init/init.cpp#HandleControlMessage
static bool HandleControlMessage(std::string_view message, const std::string& name,
                                 pid_t from_pid) {
    std::string cmdline_path = StringPrintf("proc/%d/cmdline", from_pid);
    std::string process_cmdline;
    if (ReadFileToString(cmdline_path, &process_cmdline)) {
        std::replace(process_cmdline.begin(), process_cmdline.end(), '\0', ' ');
        process_cmdline = Trim(process_cmdline);
    } else {
        process_cmdline = "unknown process";
    }

    auto action = message;
    if (ConsumePrefix(&action, "apex_")) {
        if (auto result = HandleApexControlMessage(action, name, message); !result.ok()) {
            LOG(ERROR) << "Control message: Could not ctl." << message << " for '" << name
                       << "' from pid: " << from_pid << " (" << process_cmdline
                       << "): " << result.error();
            return false;
        }
        LOG(INFO) << "Control message: Processed ctl." << message << " for '" << name
                  << "' from pid: " << from_pid << " (" << process_cmdline << ")";
        return true;
    }
    //1
    Service* service = nullptr;
    if (ConsumePrefix(&action, "interface_")) {
        service = ServiceList::GetInstance().FindInterface(name);
    } else {
        service = ServiceList::GetInstance().FindService(name);
    }

    if (service == nullptr) {
        LOG(ERROR) << "Control message: Could not find '" << name << "' for ctl." << message
                   << " from pid: " << from_pid << " (" << process_cmdline << ")";
        return false;
    }

    const auto& map = GetControlMessageMap();
    const auto it = map.find(action);
    if (it == map.end()) {
        LOG(ERROR) << "Unknown control msg '" << message << "'";
        return false;
    }
    const auto& function = it->second;

    if (auto result = function(service); !result.ok()) {
        LOG(ERROR) << "Control message: Could not ctl." << message << " for '" << name
                   << "' from pid: " << from_pid << " (" << process_cmdline
                   << "): " << result.error();
        return false;
    }

    LOG(INFO) << "Control message: Processed ctl." << message << " for '" << name
              << "' from pid: " << from_pid << " (" << process_cmdline << ")";
    return true;
}

在注释1处,通过name在单例ServiceList中寻找对应service,然后在GetControlMessageMap方法返回 数据中查找对应的操作,执行对应的方法。

@system/core/init/init.cpp#GetControlMessageMap
static const std::map<std::string, ControlMessageFunction, std::less<>>& GetControlMessageMap() {
    // clang-format off
    static const std::map<std::string, ControlMessageFunction, std::less<>> control_message_functions = {
        {"sigstop_on",        [](auto* service) { service->set_sigstop(true); return Result<void>{}; }},
        {"sigstop_off",       [](auto* service) { service->set_sigstop(false); return Result<void>{}; }},
        {"oneshot_on",        [](auto* service) { service->set_oneshot(true); return Result<void>{}; }},
        {"oneshot_off",       [](auto* service) { service->set_oneshot(false); return Result<void>{}; }},
        {"start",             DoControlStart},
        {"stop",              DoControlStop},
        {"restart",           DoControlRestart},
    };
    // clang-format on

    return control_message_functions;
}

比如

关于开机动画的一个例子,修改了系统属性就能通知init进程去启动bootanim

当系统需要显示开机动画时,surfaceflinger进程会修改系统属性来启动bootanim:

@frameworks/native/services/surfaceflinger/StartPropertySetThread.cpp#threadLoop
property_set("ctl.start", "bootanim");

init进程启动的属性服务会收到ctl.start控制属性的变化,最终会将此属性放入pending_control_messages队列中;而init进程会不断执行HandleControlMessages方法去消费pending_control_messages队列中的数据,先在ServiceList中找到对应的服务,ctl.start控制属性通过GetControlMessageMap方法的对照,可知最后执行的function(service)DoControlStart(bootanim)

@system/core/init/init.cpp#DoControlStart
static Result<void> DoControlStart(Service* service) {
    return service->Start();
}

调用service的start方法,bootanim服务启动。

总结

init进程启动做了很多工作,主要3件事:

  • 创建和挂载启动需要的文件目录
  • 初始化并启动属性服务
  • 解析init.rc配置文件并且启动Zygote进程