Android Init进程源码分析

来源:互联网 发布:平面设计作图软件 编辑:程序博客网 时间:2024/05/16 09:50

http://blog.csdn.net/xichangbao/article/details/53024698

一 Init

init进程,它是内核启动的第一个用户级进程。
代码路径system/core/init/

1.0 main
init程序的入口函数是init.cpp中的main函数
int main(int argc, char** argv) {
    if (!strcmp(basename(argv[0]), "ueventd")) { //  ln -sf ../init /sbin/ueventd
        return ueventd_main(argc, argv); // ueventd软链接到了init,当运行ueventd时,执行ueventd_main函数
    }

    if (!strcmp(basename(argv[0]), "watchdogd")) { // ln -sf ../init /sbin/watchdogd
        return watchdogd_main(argc, argv); // watchdogd软链接到了init,当运行watchdogd时,执行watchdogd_main函数
    }

    // Clear the umask.
    umask(0); // 清除umask值

    add_environment("PATH", _PATH_DEFPATH); // 设置环境变量PATH=/usr/local/bin:/bin:/usr/bin

    bool is_first_stage = (argc == 1) || (strcmp(argv[1], "--second-stage") != 0);

    // Get the basic filesystem setup we need put together in the initramdisk
    // on / and then we'll let the rc file figure out the rest.
    if (is_first_stage) { // 第一次启动init,创建或挂载一些linux根文件系统中的目录
        mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"); 
        mkdir("/dev/pts", 0755);
        mkdir("/dev/socket", 0755);
        mount("devpts", "/dev/pts", "devpts", 0, NULL);
        #define MAKE_STR(x) __STRING(x)
        mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC));
        mount("sysfs", "/sys", "sysfs", 0, NULL);
        mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL);
    }

    // We must have some place other than / to create the device nodes for
    // kmsg and null, otherwise we won't be able to remount / read-only
    // later on. Now that tmpfs is mounted on /dev, we can actually talk
    // to the outside world.
    open_devnull_stdio(); // init的标准输入,标准输出,标准错误文件描述符定向到/dev/__null__
    klog_init(); // 打开/dev/kmsg,init进程的log,打印到内核printk的log buffer
    klog_set_level(KLOG_NOTICE_LEVEL); // 设置log级别为5

    NOTICE("init %s started!\n", is_first_stage ? "first stage" : "second stage");

    if (!is_first_stage) {
        // Indicate that booting is in progress to background fw loaders, etc.
        close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));

        property_init(); // 创建/dev/__properties__文件,大小128KB,并映射进内存

        // If arguments are passed both on the command line and in DT,
        // properties set in DT always have priority over the command-line ones.
        process_kernel_dt();
        process_kernel_cmdline(); // 解析cmdline中以androidboot.开头的参数,并设置相应的property属性

        // Propagate the kernel variables to internal variables
        // used by init as well as the current required properties.
        export_kernel_boot_props(); 设置"ro.serialno", "ro.bootmode", "ro.baseband", "ro.bootloader","ro.hardware", "ro.revision"的property属性
    }

    // Set up SELinux, including loading the SELinux policy if we're in the kernel domain.
    selinux_initialize(is_first_stage); // 初始化SEAndroid

    // If we're in the kernel domain, re-exec init to transition to the init domain now
    // that the SELinux policy has been loaded.
    if (is_first_stage) {
        if (restorecon("/init") == -1) { // 恢复/init的SELinux文件属性
            ERROR("restorecon failed: %s\n", strerror(errno));
            security_failure();
        }
        char* path = argv[0];
        char* args[] = { path, const_cast<char*>("--second-stage"), nullptr };
        if (execv(path, args) == -1) { // execv会停止执行当前的进程,并且以progname应用进程替换被停止执行的进程,进程ID没有改变,这里是运行init,将其从kernel域变成用户域
            ERROR("execv(\"%s\") failed: %s\n", path, strerror(errno));
            security_failure();
        }
    }

    // These directories were necessarily created before initial policy load
    // and therefore need their security context restored to the proper value.
    // This must happen before /dev is populated by ueventd.
    NOTICE("Running restorecon...\n");
    restorecon("/dev"); // 我的看版本restorecon是个空函数? 
    restorecon("/dev/socket");
    restorecon("/dev/__properties__");
    restorecon("/property_contexts");
    restorecon_recursive("/sys");

    epoll_fd = epoll_create1(EPOLL_CLOEXEC); // 表示生成的epoll fd具有“执行后关闭”特性
    if (epoll_fd == -1) {
        ERROR("epoll_create1 failed: %s\n", strerror(errno));
        exit(1);
    }

    signal_handler_init(); // 子进程退出处理

    property_load_boot_defaults(); // 加载/default.prop文件
    export_oem_lock_status(); // 设置ro.boot.flash.locked的property属性
    start_property_service(); // 启动property属性服务

    const BuiltinFunctionMap function_map; // BuiltinFunctionMap:keyword和处理函数
    Action::set_function_map(&function_map); // 竟然用到了c++11,表示看不懂

    Parser& parser = Parser::GetInstance(); // 单例模式
    // init.rc文件基本组成单位是section, section分为三种类型,由三个关键字来区分:on(Action)、service(Service)、import(Import)
    parser.AddSectionParser("service",std::make_unique<ServiceParser>()); // Service的parser为ServiceParser // Service section 表示一个可执行程序
    parser.AddSectionParser("on", std::make_unique<ActionParser>()); // Action的parser为ActionParser // Action section 表示一系列命令的组合
    parser.AddSectionParser("import", std::make_unique<ImportParser>()); // Import的parser为ImportParser // 引入其他rc文件
    parser.ParseConfig("/init.rc"); // 开始解析init.rc,这是init的一个核心工作 // init.rc的语法可自行用Google百度一下,网上的资料十分详尽

    ActionManager& am = ActionManager::GetInstance(); // 单例模式

    am.QueueEventTrigger("early-init"); // 添加early-init EventTrigger // 添加EventTrigger的先后,决定了对应Trigger的执行顺序,early-init是最先执行的

    // Queue an action that waits for coldboot done so we know ueventd has set up all of /dev...
    am.QueueBuiltinAction(wait_for_coldboot_done_action, "wait_for_coldboot_done"); // 构造并添加action
    // ... so that we can start queuing up actions that require stuff from /dev.
    am.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
    am.QueueBuiltinAction(keychord_init_action, "keychord_init");
    am.QueueBuiltinAction(console_init_action, "console_init");

    // Trigger all the boot actions to get us started.
    am.QueueEventTrigger("init"); // 添加init EventTrigger

    // Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random
    // wasn't ready immediately after wait_for_coldboot_done
    am.QueueBuiltinAction(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");

    // Don't mount filesystems or start core system services in charger mode.
    std::string bootmode = property_get("ro.bootmode");
    if (bootmode == "charger") { // 是否进入关机充电
        am.QueueEventTrigger("charger"); // 添加charger EventTrigger
    } else {
        am.QueueEventTrigger("late-init"); // 正常开机 // 这个Trigger下,主要是完成挂载一些文件系统和启动一些系统service
    }

    // Run all property triggers based on current state of the properties.
    am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");

    while (true) {
        if (!waiting_for_exec) { // 判断是否有事件需要处理
            am.ExecuteOneCommand(); // 执行action中command
            restart_processes();  // 重启需要重启的service
        }

        int timeout = -1;
        if (process_needs_restart) {  // 有进程需要重启时,将在下面epoll_wait处进行等待
            timeout = (process_needs_restart - gettime()) * 1000;
            if (timeout < 0)
                timeout = 0;
        }

        if (am.HasMoreCommands()) { // 还有action需要处理,不等待
            timeout = 0;
        }

        bootchart_sample(&timeout); // bootchart是一个性能统计工具

        epoll_event ev;
        int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, timeout)); // 等待在epoll_fd文件描述符的I/O事件
        if (nr == -1) {
            ERROR("epoll_wait failed: %s\n", strerror(errno));
        } else if (nr == 1) {
            ((void (*)()) ev.data.ptr)(); // 有事件到来进行处理 // keychord,property设置,signal(例如子进程退出信号)处理
        }
    }

    return 0;
}


1.1 klog_init

void klog_init(void) {
    if (klog_fd >= 0) return; /* Already initialized */

    klog_fd = open("/dev/kmsg", O_WRONLY | O_CLOEXEC); // 打开kmsg文件节点
    if (klog_fd >= 0) {
        return;
    }

    static const char* name = "/dev/__kmsg__";
    if (mknod(name, S_IFCHR | 0600, (1 << 8) | 11) == 0) {
        klog_fd = open(name, O_WRONLY | O_CLOEXEC);
        unlink(name);
    }
}

1.2 selinux_initialize

static void selinux_initialize(bool in_kernel_domain) {
    Timer t;

    selinux_callback cb;
    cb.func_log = selinux_klog_callback;
    selinux_set_callback(SELINUX_CB_LOG, cb); // 将selinux_log的值设置成selinux_klog_callback
    cb.func_audit = audit_callback;
    selinux_set_callback(SELINUX_CB_AUDIT, cb); // 将selinux_audit的值设置成audit_callback

    if (in_kernel_domain) {
        INFO("Loading SELinux policy...\n");
        if (selinux_android_load_policy() < 0) {
            ERROR("failed to load policy: %s\n", strerror(errno));
            security_failure();
        }

        bool kernel_enforcing = (security_getenforce() == 1);
        bool is_enforcing = selinux_is_enforcing();
        if (kernel_enforcing != is_enforcing) {
            if (security_setenforce(is_enforcing)) { // 设置SELinux模式(permissive或enforcing),其实就是写/sys/fs/selinux/enforce文件节点
                ERROR("security_setenforce(%s) failed: %s\n",
                      is_enforcing ? "true" : "false", strerror(errno));
                security_failure();
            }
        }

        if (write_file("/sys/fs/selinux/checkreqprot", "0") == -1) { // 1表示SElinux会检查应用请求的保护,0表示默认使用内核对mmap和mprotect系统调用的保护
            security_failure();
        }

        NOTICE("(Initializing SELinux %s took %.2fs.)\n",
               is_enforcing ? "enforcing" : "non-enforcing", t.duration());
    } else {
        selinux_init_all_handles();
    }
}

int selinux_android_load_policy(void)
{
    int fd = -1, rc;
    struct stat sb;
    void *map = NULL;
    static int load_successful = 0;

    /*
     * Since updating policy at runtime has been abolished
     * we just check whether a policy has been loaded before
     * and return if this is the case.
     * There is no point in reloading policy.
     */
    if (load_successful){
      selinux_log(SELINUX_WARNING, "SELinux: Attempted reload of SELinux policy!/n");
      return 0;
    }

    set_selinuxmnt(SELINUXMNT); // 挂载点/sys/fs/selinux
    fd = open(sepolicy_file, O_RDONLY | O_NOFOLLOW | O_CLOEXEC); // 打开/sepolicy
    if (fd < 0) {
        selinux_log(SELINUX_ERROR, "SELinux:  Could not open sepolicy:  %s\n",
                strerror(errno));
        return -1;
    }   
    if (fstat(fd, &sb) < 0) {
        selinux_log(SELINUX_ERROR, "SELinux:  Could not stat %s:  %s\n",
                sepolicy_file, strerror(errno));
        close(fd);
        return -1;
    }   
    map = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
    if (map == MAP_FAILED) {
        selinux_log(SELINUX_ERROR, "SELinux:  Could not map %s:  %s\n",
                sepolicy_file, strerror(errno));
        close(fd);
        return -1;
    }   

    rc = security_load_policy(map, sb.st_size);
    if (rc < 0) {
        selinux_log(SELINUX_ERROR, "SELinux:  Could not load policy:  %s\n",
                strerror(errno));
        munmap(map, sb.st_size);
        close(fd);
        return -1;
    }   

    munmap(map, sb.st_size);
    close(fd);
    selinux_log(SELINUX_INFO, "SELinux: Loaded policy from %s\n", sepolicy_file);
    load_successful = 1;
    return 0;
}

int security_load_policy(void *data, size_t len)
{
    char path[PATH_MAX];
    int fd, ret;

    if (!selinux_mnt) {
        errno = ENOENT;
        return -1;
    }   

    snprintf(path, sizeof path, "%s/load", selinux_mnt);
    fd = open(path, O_RDWR | O_CLOEXEC); // 打开/sys/fs/selinux/load文件
    if (fd < 0)
        return -1;

    ret = write(fd, data, len); // 将/sepolicy的策略数据写入/sys/fs/selinux/load文件
    close(fd);
    if (ret < 0)
        return -1;
    return 0;
}

static void selinux_init_all_handles(void)
{
    sehandle = selinux_android_file_context_handle();
    selinux_android_set_sehandle(sehandle);
    sehandle_prop = selinux_android_prop_context_handle();
}

1.3 signal_handler_init

void signal_handler_init() {
    // Create a signalling mechanism for SIGCHLD.
    int s[2];
    if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0, s) == -1) { // 建立一对匿名的已经连接的套接字
        ERROR("socketpair failed: %s\n", strerror(errno));
        exit(1);
    }

    signal_write_fd = s[0];
    signal_read_fd = s[1];

    // Write to signal_write_fd if we catch SIGCHLD.
    struct sigaction act;
    memset(&act, 0, sizeof(act));
    act.sa_handler = SIGCHLD_handler;  
    act.sa_flags = SA_NOCLDSTOP;
    sigaction(SIGCHLD, &act, 0); // Init进程是所有用户空间进程的父进程,需要处理其子进程终止时产生的SIGCHLD信号

    ServiceManager::GetInstance().ReapAnyOutstandingChildren();

    register_epoll_handler(signal_read_fd, handle_signal); // 注册epoll handler,当signal_read_fd有数据可读时,调用handle_signal
}

static void SIGCHLD_handler(int) {
    if (TEMP_FAILURE_RETRY(write(signal_write_fd, "1", 1)) == -1) { // 当子进程退出时,向signal_write_fd写1
        ERROR("write(signal_write_fd) failed: %s\n", strerror(errno));
    }
}

void register_epoll_handler(int fd, void (*fn)()) {
    epoll_event ev;
    ev.events = EPOLLIN;
    ev.data.ptr = reinterpret_cast<void*>(fn);
    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev) == -1) {
        ERROR("epoll_ctl failed: %s\n", strerror(errno));
    }
}

static void handle_signal() {
    // Clear outstanding requests.
    char buf[32];
    read(signal_read_fd, buf, sizeof(buf));

    ServiceManager::GetInstance().ReapAnyOutstandingChildren();
}

1.4 ReapAnyOutstandingChildren

void ServiceManager::ReapAnyOutstandingChildren() {
    while (ReapOneProcess()) {
    }
}

bool ServiceManager::ReapOneProcess() {
    int status;
    pid_t pid = TEMP_FAILURE_RETRY(waitpid(-1, &status, WNOHANG)); // 等待子进程退出,WNOHANG表示非阻塞
    if (pid == 0) {
        return false;
    } else if (pid == -1) {
        ERROR("waitpid failed: %s\n", strerror(errno));
        return false;
    }

    Service* svc = FindServiceByPid(pid); // 根据pid查找到相应的Service

    std::string name;
    if (svc) {
        name = android::base::StringPrintf("Service '%s' (pid %d)",
                                           svc->name().c_str(), pid);
    } else {
        name = android::base::StringPrintf("Untracked pid %d", pid);
    }

    if (WIFEXITED(status)) { // WIFEXITED(status)如果子进程正常结束则为非0值。
        NOTICE("%s exited with status %d\n", name.c_str(), WEXITSTATUS(status)); // WEXITSTATUS(status)取得子进程exit()返回的结束代码
    } else if (WIFSIGNALED(status)) { // WIFSIGNALED(status)如果子进程是因为信号而结束则此宏值为真。
        NOTICE("%s killed by signal %d\n", name.c_str(), WTERMSIG(status)); // WTERMSIG(status)取得子进程因信号而中止的信号代码
    } else if (WIFSTOPPED(status)) { // WIFSTOPPED(status)如果子进程处于暂停执行情况则此宏值为真。
        NOTICE("%s stopped by signal %d\n", name.c_str(), WSTOPSIG(status)); // WSTOPSIG(status)取得引发子进程暂停的信号代码
    } else {
        NOTICE("%s state changed", name.c_str());
    }

    if (!svc) {
        return true;
    }

    if (svc->Reap()) { // 结束服务
        waiting_for_exec = false;
        RemoveService(*svc); // 移除服务
    }

    return true;
}

bool Service::Reap() {
    if (!(flags_ & SVC_ONESHOT) || (flags_ & SVC_RESTART)) { // 当flags为RESTART,且不是ONESHOT时
        NOTICE("Service '%s' (pid %d) killing any children in process group\n",
               name_.c_str(), pid_);
        kill(-pid_, SIGKILL); // 杀死以pid_为组标识的进程
    }

    // Remove any sockets we may have created.
    for (const auto& si : sockets_) { // 移除当前服务svc创建的所有socket
        std::string tmp = StringPrintf(ANDROID_SOCKET_DIR "/%s", si.name.c_str());
        unlink(tmp.c_str());
    }

    if (flags_ & SVC_EXEC) {  // 当flags为EXEC时
        INFO("SVC_EXEC pid %d finished...\n", pid_);
        return true;
    }

    pid_ = 0;
    flags_ &= (~SVC_RUNNING);

    // Oneshot processes go into the disabled state on exit,
    // except when manually restarted.
    if ((flags_ & SVC_ONESHOT) && !(flags_ & SVC_RESTART)) {
        flags_ |= SVC_DISABLED;
    }

    // Disabled and reset processes do not get restarted automatically.
    if (flags_ & (SVC_DISABLED | SVC_RESET))  {  // 当flag为ONESHOT时,将其设为stopped状态
        NotifyStateChange("stopped");
        return false;
    }

    time_t now = gettime();
    if ((flags_ & SVC_CRITICAL) && !(flags_ & SVC_RESTART)) {
        if (time_crashed_ + CRITICAL_CRASH_WINDOW >= now) { // 服务在4分钟内重启次数超过4次,则重启手机进入recovery模式
            if (++nr_crashed_ > CRITICAL_CRASH_THRESHOLD) {
                ERROR("critical process '%s' exited %d times in %d minutes; "
                      "rebooting into recovery mode\n", name_.c_str(),
                      CRITICAL_CRASH_THRESHOLD, CRITICAL_CRASH_WINDOW / 60);
                android_reboot(ANDROID_RB_RESTART2, 0, "recovery");
                return false;
            }
        } else {
            time_crashed_ = now;
            nr_crashed_ = 1;
        }
    }

    flags_ &= (~SVC_RESTART);
    flags_ |= SVC_RESTARTING;

    // Execute all onrestart commands for this service.
    onrestart_.ExecuteAllCommands(); // 执行当前service中所有onrestart命令,不得不说Android代码越来越复杂了,这一块代码原来是很简洁的,现在写得都快看不懂了,汗

    NotifyStateChange("restarting");  // 将service设为restarting状态
    return false;
}


1.5 start_property_service

void start_property_service() {
    property_set_fd = create_socket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, // 创建socket并绑定到/dev/socket/property_service
                                    0666, 0, 0, NULL);
    if (property_set_fd == -1) {
        ERROR("start_property_service socket creation failed: %s\n", strerror(errno));
        exit(1);
    }

    listen(property_set_fd, 8); // 监听这个socket,当客户端调用connect()发出连接请求,服务器端就会收到这个请求。

    register_epoll_handler(property_set_fd, handle_property_set_fd);
}

int create_socket(const char *name, int type, mode_t perm, uid_t uid,
                  gid_t gid, const char *socketcon)
{
    struct sockaddr_un addr;
    int fd, ret, savederrno;
    char *filecon;

    if (socketcon) {
        if (setsockcreatecon(socketcon) == -1) {
            ERROR("setsockcreatecon(\"%s\") failed: %s\n", socketcon, strerror(errno));
            return -1;
        }
    }

    fd = socket(PF_UNIX, type, 0);
    if (fd < 0) {
        ERROR("Failed to open socket '%s': %s\n", name, strerror(errno));
        return -1;
    }

    if (socketcon)
        setsockcreatecon(NULL);

    memset(&addr, 0 , sizeof(addr));
    addr.sun_family = AF_UNIX;
    snprintf(addr.sun_path, sizeof(addr.sun_path), ANDROID_SOCKET_DIR"/%s",
             name);

    ret = unlink(addr.sun_path);
    if (ret != 0 && errno != ENOENT) {
        ERROR("Failed to unlink old socket '%s': %s\n", name, strerror(errno));
        goto out_close;
    }

    filecon = NULL;
    if (sehandle) {
        ret = selabel_lookup(sehandle, &filecon, addr.sun_path, S_IFSOCK);
        if (ret == 0)
            setfscreatecon(filecon);
    }

    ret = bind(fd, (struct sockaddr *) &addr, sizeof (addr));
    savederrno = errno;

    setfscreatecon(NULL);
    freecon(filecon);

    if (ret) {
        ERROR("Failed to bind socket '%s': %s\n", name, strerror(savederrno));
        goto out_unlink;
    }

    ret = lchown(addr.sun_path, uid, gid);
    if (ret) {
        ERROR("Failed to lchown socket '%s': %s\n", addr.sun_path, strerror(errno));
        goto out_unlink;
    }
    ret = fchmodat(AT_FDCWD, addr.sun_path, perm, AT_SYMLINK_NOFOLLOW);
    if (ret) {
        ERROR("Failed to fchmodat socket '%s': %s\n", addr.sun_path, strerror(errno));
        goto out_unlink;
    }

    INFO("Created socket '%s' with mode '%o', user '%d', group '%d'\n",
         addr.sun_path, perm, uid, gid);

    return fd;

out_unlink:
    unlink(addr.sun_path);
out_close:
    close(fd);
    return -1;
}

// 服务器端依次调用socket()、bind()、listen()建立,绑定,监听指定的socket地址;TCP客户端依次调用socket()、connect()创建,连接向TCP服务器发送连接请求;服务器监听到请求之后,调用accept()函数接收请求,至此服务器端和客户端连接建立完成。

static void handle_property_set_fd()
{
    prop_msg msg;
    int s;
    int r;
    struct ucred cr;
    struct sockaddr_un addr;
    socklen_t addr_size = sizeof(addr);
    socklen_t cr_size = sizeof(cr);
    char * source_ctx = NULL;
    struct pollfd ufds[1];
    const int timeout_ms = 2 * 1000;  /* Default 2 sec timeout for caller to send property. */
    int nr;

    if ((s = accept(property_set_fd, (struct sockaddr *) &addr, &addr_size)) < 0) { // 建立连接
        return;
    }

    /* Check socket options here */
    if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cr_size) < 0) {
        close(s);
        ERROR("Unable to receive socket options\n");
        return;
    }

    ufds[0].fd = s;
    ufds[0].events = POLLIN;
    ufds[0].revents = 0;
    nr = TEMP_FAILURE_RETRY(poll(ufds, 1, timeout_ms)); // 监测连接
    if (nr == 0) {
        ERROR("sys_prop: timeout waiting for uid=%d to send property message.\n", cr.uid);
        close(s);
        return;
    } else if (nr < 0) {
        ERROR("sys_prop: error waiting for uid=%d to send property message: %s\n", cr.uid, strerror(errno));
        close(s);
        return;
    }

    r = TEMP_FAILURE_RETRY(recv(s, &msg, sizeof(msg), MSG_DONTWAIT)); // 读取数据
    if(r != sizeof(prop_msg)) {
        ERROR("sys_prop: mis-match msg size received: %d expected: %zu: %s\n",
              r, sizeof(prop_msg), strerror(errno));
        close(s);
        return;
    }

    switch(msg.cmd) {
    case PROP_MSG_SETPROP:
        msg.name[PROP_NAME_MAX-1] = 0;
        msg.value[PROP_VALUE_MAX-1] = 0;

        if (!is_legal_property_name(msg.name, strlen(msg.name))) {
            ERROR("sys_prop: illegal property name. Got: \"%s\"\n", msg.name);
            close(s);
            return;
        }

        getpeercon(s, &source_ctx);

        if(memcmp(msg.name,"ctl.",4) == 0) {
            // Keep the old close-socket-early behavior when handling
            // ctl.* properties.
            close(s);
            if (check_control_mac_perms(msg.value, source_ctx, &cr)) {
                handle_control_message((char*) msg.name + 4, (char*) msg.value); // 运行,停止,重启service
            } else {
                ERROR("sys_prop: Unable to %s service ctl [%s] uid:%d gid:%d pid:%d\n",
                        msg.name + 4, msg.value, cr.uid, cr.gid, cr.pid);
            }
        } else {
            if (check_mac_perms(msg.name, source_ctx, &cr)) {
                property_set((char*) msg.name, (char*) msg.value); // 设置property
            } else {
                ERROR("sys_prop: permission denied uid:%d  name:%s\n",
                      cr.uid, msg.name);
            }

            // Note: bionic's property client code assumes that the
            // property server will not close the socket until *AFTER*
            // the property is written to memory.
            close(s);
        }
        freecon(source_ctx);
        break;

    default:
        close(s);
        break;
    }
}


1.6 Action Command

BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
    constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
    static const Map builtin_functions = {
        {"bootchart_init",          {0,     0,    do_bootchart_init}},
        {"chmod",                   {2,     2,    do_chmod}},
        {"chown",                   {2,     3,    do_chown}},
        {"class_reset",             {1,     1,    do_class_reset}},
        {"class_start",             {1,     1,    do_class_start}},
        {"class_stop",              {1,     1,    do_class_stop}},
        {"copy",                    {2,     2,    do_copy}},
        {"domainname",              {1,     1,    do_domainname}},
        {"enable",                  {1,     1,    do_enable}},
        {"exec",                    {1,     kMax, do_exec}},
        {"export",                  {2,     2,    do_export}},
        {"hostname",                {1,     1,    do_hostname}},
        {"ifup",                    {1,     1,    do_ifup}},
        {"insmod",                  {1,     kMax, do_insmod}},
        {"installkey",              {1,     1,    do_installkey}},
        {"load_persist_props",      {0,     0,    do_load_persist_props}},
        {"load_system_props",       {0,     0,    do_load_system_props}},
        {"loglevel",                {1,     1,    do_loglevel}},
        {"mkdir",                   {1,     4,    do_mkdir}},
        {"mount_all",               {1,     kMax, do_mount_all}},
        {"mount",                   {3,     kMax, do_mount}},
        {"powerctl",                {1,     1,    do_powerctl}},
        {"restart",                 {1,     1,    do_restart}},
        {"restorecon",              {1,     kMax, do_restorecon}},
        {"restorecon_recursive",    {1,     kMax, do_restorecon_recursive}},
        {"rm",                      {1,     1,    do_rm}},
        {"rmdir",                   {1,     1,    do_rmdir}},
        {"setprop",                 {2,     2,    do_setprop}},
        {"setrlimit",               {3,     3,    do_setrlimit}},
        {"setusercryptopolicies",   {1,     1,    do_setusercryptopolicies}},
        {"start",                   {1,     1,    do_start}},
        {"stop",                    {1,     1,    do_stop}},
        {"swapon_all",              {1,     1,    do_swapon_all}},
        {"symlink",                 {2,     2,    do_symlink}},
        {"sysclktz",                {1,     1,    do_sysclktz}},
        {"trigger",                 {1,     1,    do_trigger}},
        {"verity_load_state",       {0,     0,    do_verity_load_state}},
        {"verity_update_state",     {0,     0,    do_verity_update_state}},
        {"wait",                    {1,     2,    do_wait}},
        {"write",                   {2,     2,    do_write}},
    };
    return builtin_functions;
}


1.7 ParseConfig

这是一个很好的解析配置文件的实现。
bool Parser::ParseConfig(const std::string& path) {
    if (is_dir(path.c_str())) {
        return ParseConfigDir(path);
    }
    return ParseConfigFile(path);
}

bool Parser::ParseConfigFile(const std::string& path) {
    INFO("Parsing file %s...\n", path.c_str());
    Timer t;
    std::string data;
    if (!read_file(path.c_str(), &data)) {
        return false;
    }

    data.push_back('\n'); // TODO: fix parse_config.
    ParseData(path, data); // 解析init.rc的内容
    for (const auto& sp : section_parsers_) {
        sp.second->EndFile(path);
    }

    // Turning this on and letting the INFO logging be discarded adds 0.2s to
    // Nexus 9 boot time, so it's disabled by default.
    if (false) DumpState(); // 打印Service和Action的状态信息

    NOTICE("(Parsing %s took %.2fs.)\n", path.c_str(), t.duration());
    return true;
}

void Parser::ParseData(const std::string& filename, const std::string& data) {
    //TODO: Use a parser with const input and remove this copy
    std::vector<char> data_copy(data.begin(), data.end());
    data_copy.push_back('\0');

    parse_state state;
    state.filename = filename.c_str();
    state.line = 0;
    state.ptr = &data_copy[0];
    state.nexttoken = 0;

    SectionParser* section_parser = nullptr;
    std::vector<std::string> args;

    for (;;) {
        switch (next_token(&state)) { // 以行为单位分割init.rc中的数据
        case T_EOF: // 文件结束
            if (section_parser) {
                section_parser->EndSection();
            }
            return;
        case T_NEWLINE: // 换行符
            state.line++;
            if (args.empty()) {
                break;
            }
            if (section_parsers_.count(args[0])) { // 判断是否为一个新的Section,在init.rc中以on、sevice、import关键字开头
                if (section_parser) {
                    section_parser->EndSection();
                }
                section_parser = section_parsers_[args[0]].get(); // 获取关键字对应的parser
                std::string ret_err;
                if (!section_parser->ParseSection(args, &ret_err)) { // 调用parser的ParseSection函数
                    parse_error(&state, "%s\n", ret_err.c_str());
                    section_parser = nullptr;
                }
            } else if (section_parser) { // 不是一个新的section,而是Service section的option或者Action section中的command
                std::string ret_err;
                if (!section_parser->ParseLineSection(args, state.filename, // 调用parser的ParseLineSection函数
                                                      state.line, &ret_err)) {
                    parse_error(&state, "%s\n", ret_err.c_str());
                }
            }
            args.clear();
            break;
        case T_TEXT: // 文本内容添加到vector
            args.emplace_back(state.text);
            break;
        }
    }
}


1.8 Service Option

Service::OptionHandlerMap::Map& Service::OptionHandlerMap::map() const {
    constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
    static const Map option_handlers = {
        {"class",       {1,     1,    &Service::HandleClass}},
        {"console",     {0,     1,    &Service::HandleConsole}},
        {"critical",    {0,     0,    &Service::HandleCritical}},
        {"disabled",    {0,     0,    &Service::HandleDisabled}},
        {"group",       {1,     NR_SVC_SUPP_GIDS + 1, &Service::HandleGroup}},
        {"ioprio",      {2,     2,    &Service::HandleIoprio}},
        {"keycodes",    {1,     kMax, &Service::HandleKeycodes}},
        {"oneshot",     {0,     0,    &Service::HandleOneshot}},
        {"onrestart",   {1,     kMax, &Service::HandleOnrestart}},
        {"seclabel",    {1,     1,    &Service::HandleSeclabel}},
        {"setenv",      {2,     2,    &Service::HandleSetenv}},
        {"socket",      {3,     6,    &Service::HandleSocket}},
        {"user",        {1,     1,    &Service::HandleUser}},
        {"writepid",    {1,     kMax, &Service::HandleWritepid}},
    };
    return option_handlers;
}


1.9 ExecuteOneCommand

按照Trigger队列的顺序,一次只执行一个action中的一个command
void ActionManager::ExecuteOneCommand() {
    // Loop through the trigger queue until we have an action to execute
    while (current_executing_actions_.empty() && !trigger_queue_.empty()) { // 遍历Trigger队列,找到第一个action不为的Trigger
        for (const auto& action : actions_) { // 遍历action向量
            if (trigger_queue_.front()->CheckTriggers(*action)) { // 当Action的Trigger与Trigger队列的队首元素相同,将其添加到当前需要执行的队列中
                current_executing_actions_.emplace(action.get());
            }
        }
        trigger_queue_.pop(); // 已处理的Trigger出队
    }

    if (current_executing_actions_.empty()) {
        return;
    }

    auto action = current_executing_actions_.front();  // 每次只执行一个action

    if (current_command_ == 0) {
        std::string trigger_name = action->BuildTriggersString();
        INFO("processing action (%s)\n", trigger_name.c_str());
    }

    action->ExecuteOneCommand(current_command_); // 执行Action的一个command

    // If this was the last command in the current action, then remove
    // the action from the executing list.
    // If this action was oneshot, then also remove it from actions_.
    ++current_command_;
    if (current_command_ == action->NumCommands()) { // 判断当前正在执行中command是其action中的最后一个command
        current_executing_actions_.pop(); // action出队
        current_command_ = 0;
        if (action->oneshot()) { // oneshot action不会再次执行,将其从action向量中删除
            auto eraser = [&action] (std::unique_ptr<Action>& a) {
                return a.get() == action;
            };
            actions_.erase(std::remove_if(actions_.begin(), actions_.end(), eraser));
        }
    }
}



0 0