天天看點

android7.0啟動zygote程序

    zygote孵化器在android系統中有着及其中要的位置. android系統中的程序都是有zygote孵化出來的, 所有應用程序都是zygote的子程序. 在init程序中的服務都是由指令啟動起來的, zygote服務也不例外, 是以在分析zygote之前要分析一下init.rc中指令是如何執行的.

 在分析init程序時知道在init.cpp中的main函數循環執行指令

while (true) {
        if (!waiting_for_exec) {
            am.ExecuteOneCommand();   //循環執行指令
            restart_processes();    //重新開機死掉的程序
        }

        int timeout = -1;
        if (process_needs_restart) {
            timeout = (process_needs_restart - gettime()) * 1000;
            if (timeout < 0)
                timeout = 0;
        }

        if (am.HasMoreCommands()) {
            timeout = 0;
        }

        bootchart_sample(&timeout);

        epoll_event ev;
        int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, timeout));
        if (nr == -1) {
            ERROR("epoll_wait failed: %s\n", strerror(errno));
        } else if (nr == 1) {
            ((void (*)()) ev.data.ptr)();
        }
    }

    return 0;
           
void ActionManager::ExecuteOneCommand() {
    // Loop through the trigger queue until we have an action to execute
    while (current_executing_actions_.empty() && !trigger_queue_.empty()) { //目前的可執行action隊列為空, trigger_queue_隊列不為空
        for (const auto& action : actions_) {           //循環周遊action_隊列,包含了所有需要執行的指令,解析init.rc獲得
            if (trigger_queue_.front()->CheckTriggers(*action)) {   //擷取隊頭的trigger, 檢查actions_清單中的action的trigger,對比是否相同
                current_executing_actions_.emplace(action.get());  //将所有具有同一trigger的action加入目前可執行action隊列
            }
        }
        trigger_queue_.pop();   //将隊頭trigger出棧
    }

    if (current_executing_actions_.empty()) {//目前可執行的actions隊列為空就傳回
        return;
    }

    auto action = current_executing_actions_.front(); //擷取目前可執行actions隊列的首個action

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

    action->ExecuteOneCommand(current_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_;    //不斷疊加,将action_中的所有指令取出
    if (current_command_ == action->NumCommands()) {
        current_executing_actions_.pop();
        current_command_ = 0;
        if (action->oneshot()) {
            auto eraser = [&action] (std::unique_ptr<Action>& a) {
                return a.get() == action;
            };
            actions_.erase(std::remove_if(actions_.begin(), actions_.end(), eraser));
        }
    }
}
           

由于所有的指令執行順序都是根據trigger的順序執行的, 是以在擷取現在需要執行的action就需要檢查一下這個action的trigger.

不同的trigger對應這不同的CheckTriggers. 之前講android7.0 init程序時知道

early-init等的trigger為EventTrigger

wait_for_coldboot_done_action等的trigger就為BuiltinTrigger

在init.rc可以看到類似與on property:sys.powerctl=*這樣的trigger為PropertyTrigger

下面具體看一下這幾個trigger的CheckTriggers函數

class EventTrigger : public Trigger {
public:
    EventTrigger(const std::string& trigger) : trigger_(trigger) {
    }
    bool CheckTriggers(const Action& action) const override {
        return action.CheckEventTrigger(trigger_);
    }
private:
    const std::string trigger_;
};

class PropertyTrigger : public Trigger {
public:
    PropertyTrigger(const std::string& name, const std::string& value)
        : name_(name), value_(value) {
    }
    bool CheckTriggers(const Action& action) const override {
        return action.CheckPropertyTrigger(name_, value_);
    }
private:
    const std::string name_;
    const std::string value_;
};

class BuiltinTrigger : public Trigger {
public:
    BuiltinTrigger(Action* action) : action_(action) {
    }
    bool CheckTriggers(const Action& action) const override {
        return action_ == &action;    //如果action相等就傳回true執行
    }
private:
    const Action* action_;
};
           

EventTrigger

bool Action::CheckEventTrigger(const std::string& trigger) const {
    return !event_trigger_.empty() &&   //event_trigger_不為空, 在addCommand時InitTriggers添加資料
        trigger == event_trigger_ &&       //event_trigger_與目前的trigger相同
        CheckPropertyTriggers();            //不是property trigger
} 
           

PropertyTrigger

bool Action::CheckPropertyTrigger(const std::string& name,
                                  const std::string& value) const {
    return event_trigger_.empty() && CheckPropertyTriggers(name, value);  
}
           
bool Action::CheckPropertyTriggers(const std::string& name,
                                   const std::string& value) const {
    if (property_triggers_.empty()) {   //property triggers為空傳回true
        return true;
    }

    bool found = name.empty();
    for (const auto& t : property_triggers_) {
        const auto& trigger_name = t.first;
        const auto& trigger_value = t.second;
        if (trigger_name == name) {
            if (trigger_value != "*" && trigger_value != value) {
                return false;      //是property trigger 傳回false
            } else {
                found = true;
            }
        } else {
            std::string prop_val = property_get(trigger_name.c_str());
            if (prop_val.empty() || (trigger_value != "*" &&
                                     trigger_value != prop_val)) {
                return false;
            }
        }
    }
    return found;
}
           

根據trigger找到對應的action就開始執行了

void Action::ExecuteOneCommand(std::size_t command) const {
    ExecuteCommand(commands_[command]);   //從commands_隊列取出指令對應的函數
}
           
void Action::ExecuteCommand(const Command& command) const {
    Timer t;      //使用timer計時
    int result = command.InvokeFunc();

    if (klog_get_level() >= KLOG_INFO_LEVEL) {
        std::string trigger_name = BuildTriggersString();
        std::string cmd_str = command.BuildCommandString();
        std::string source = command.BuildSourceString();

        INFO("Command '%s' action=%s%s returned %d took %.2fs\n",
             cmd_str.c_str(), trigger_name.c_str(), source.c_str(),
             result, t.duration());  //可以将該log級别改為NOTICE,可以輸出目前執行指令的資訊以及執行時間輸出, 定位開機問題
    }
}
           
int Command::InvokeFunc() const {
    std::vector<std::string> expanded_args;
    expanded_args.resize(args_.size());
    expanded_args[0] = args_[0];    
    for (std::size_t i = 1; i < args_.size(); ++i) {
        if (!expand_props(args_[i], &expanded_args[i])) {
            ERROR("%s: cannot expand '%s'\n", args_[0].c_str(), args_[i].c_str());
            return -EINVAL;
        }
    }

    return func_(expanded_args);  //執行獲得的函數
}
           

由于根據android7.0 init程序可以知道第一個觸發的動作為early-init

在init.rc中early-init的指令如下:

on early-init       //觸發器為early-init, 首先執行
    # Set init and its forked children's oom_adj.
    write /proc/1/oom_score_adj -1000  //調用do_write函數

    # Disable sysrq from keyboard
    write /proc/sys/kernel/sysrq 0  

    # Set the security context of /adb_keys if present.
    restorecon /adb_keys      //調用do_restorecon函數

    # Shouldn't be necessary, but sdcard won't start without it. http://b/22568628.
    mkdir /mnt 0775 root system  //調用do_mkdir函數

    # Set the security context of /postinstall if present.
    restorecon /postinstall 

    start ueventd   //調用do_start函數啟動ueventd服務
           
service ueventd /sbin/ueventd
    class core      //class name為core
    critical          //重要服務
    seclabel u:r:ueventd:s0
           

之後會相繼觸發init, late-init等.

on late-init     
    trigger early-fs    //觸發early-fs
    trigger fs             //觸發fs
    trigger post-fs    //觸發post-fs

    # Load properties from /system/ + /factory after fs mount. Place
    # this in another action so that the load will be scheduled after the prior
    # issued fs triggers have completed.
    trigger load_system_props_action

    # Now we can mount /data. File encryption requires keymaster to decrypt
    # /data, which in turn can only be loaded when system properties are present
    trigger post-fs-data
    trigger load_persist_props_action

    # Remove a file to wake up anything waiting for firmware.
    trigger firmware_mounts_complete

    trigger early-boot
    trigger boot
           
on fs         //觸發fs就會執行如下指令
    ubiattach 0 ubipac
    exec /sbin/resize2fs -ef /fstab.${ro.hardware}
    mount_all /fstab.${ro.hardware}     //執行do_mount_all函數
    mount pstore pstore /sys/fs/pstore
    setprop ro.crypto.fuse_sdcard true
        symlink /system/res /res
        symlink /system/bin /bin
           

在system/core/init/builtins.cpp中實作了do_mount_all函數

static int do_mount_all(const std::vector<std::string>& args) {
    pid_t pid;
    int ret = -1;
    int child_ret = -1;
    int status;
    struct fstab *fstab;

    const char* fstabfile = args[1].c_str();
    /*
     * Call fs_mgr_mount_all() to mount all filesystems.  We fork(2) and
     * do the call in the child to provide protection to the main init
     * process if anything goes wrong (crash or memory leak), and wait for
     * the child to finish in the parent.
     */
    pid = fork();
    ..............
    if (ret == FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION) {
        ActionManager::GetInstance().QueueEventTrigger("encrypt");
    } else if (ret == FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED) {
        property_set("ro.crypto.state", "encrypted");
        property_set("ro.crypto.type", "block");
        ActionManager::GetInstance().QueueEventTrigger("defaultcrypto");
    } else if (ret == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) {
        property_set("ro.crypto.state", "unencrypted");
        ActionManager::GetInstance().QueueEventTrigger("nonencrypted");  //将nonencrypted加入trigger_queue_
    } else if (ret == FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) {
        property_set("ro.crypto.state", "unsupported");
        ActionManager::GetInstance().QueueEventTrigger("nonencrypted");  //将nonencrypted加入trigger_queue_
    } else if (ret == FS_MGR_MNTALL_DEV_NEEDS_RECOVERY) {
        /* Setup a wipe via recovery, and reboot into recovery */
        ERROR("fs_mgr_mount_all suggested recovery, so wiping data via recovery.\n");
        ret = wipe_data_via_recovery("wipe_data_via_recovery");
        /* If reboot worked, there is no return. */
    } else if (ret == FS_MGR_MNTALL_DEV_FILE_ENCRYPTED) {
        if (e4crypt_install_keyring()) {
            return -1;
        }
        property_set("ro.crypto.state", "encrypted");
        property_set("ro.crypto.type", "file");

        // Although encrypted, we have device key, so we do not need to
        // do anything different from the nonencrypted case.
        ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
    } else if (ret > 0) {
        ERROR("fs_mgr_mount_all returned unexpected error %d\n", ret);
    }
    /* else ... < 0: error */

    return ret;
}
           
on nonencrypted    //觸發action 
    # A/B update verifier that marks a successful boot.
    exec - root -- /system/bin/update_verifier nonencrypted
    class_start main         //調用do_class_start函數将class name為main的services啟動起來
    class_start late_start
           

在system/core/rootdir/init.zygote64.rc檔案中可以看出zygote的class name就為main

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
    class main                 //class name為main
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
           

還是在system/core/init/builtins.cpp中實作了do_class_start函數

static int do_class_start(const std::vector<std::string>& args) {
        /* Starting a class does not start services
         * which are explicitly disabled.  They must
         * be started individually.
         */
    ServiceManager::GetInstance().
        ForEachServiceInClass(args[1], [] (Service* s) { s->StartIfNotDisabled(); });
    return 0;
}
           
bool Service::StartIfNotDisabled() {
    if (!(flags_ & SVC_DISABLED)) {
        return Start();          //如果services不是disable,就将start()函數傳回
    } else {
        flags_ |= SVC_DISABLED_START;  //否則,标記services為disable
    }
    return true;
}
           
void ServiceManager::ForEachServiceInClass(const std::string& classname,
                                           void (*func)(Service* svc)) const {
    for (const auto& s : services_) {   //周遊services_尋找所有name為main的servies
        if (classname == s->classname()) {   
            func(s.get());    //如果找到就調用Start()函數
        }
    }
}
           
bool Service::Start() {
    // Starting a service removes it from the disabled or reset state and
    // immediately takes it out of the restarting state if it was in there.
    flags_ &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART|SVC_DISABLED_START));
    time_started_ = 0;

    // Running processes require no additional work --- if they're in the
    // process of exiting, we've ensured that they will immediately restart
    // on exit, unless they are ONESHOT.
    if (flags_ & SVC_RUNNING) {
        return false;
    }

    bool needs_console = (flags_ & SVC_CONSOLE);
    if (needs_console && !have_console) {
        ERROR("service '%s' requires console\n", name_.c_str());
        flags_ |= SVC_DISABLED;
        return false;
    }

    struct stat sb;
    if (stat(args_[0].c_str(), &sb) == -1) {
        ERROR("cannot find '%s' (%s), disabling '%s'\n",
              args_[0].c_str(), strerror(errno), name_.c_str());
        flags_ |= SVC_DISABLED;
        return false;
    }

    std::string bootmode = property_get("ro.bootmode");
    if(((!strncmp(name_.c_str(),"healthd",7))||(!strncmp(name_.c_str(),"bootanim",8))||(!strncmp(name_.c_str(),"zygote",6))||(!strncmp(name_.c_str(),"surfaceflinger",14)))&&(bootmode == "charger")){

         ERROR("stopping '%s'\n",name_.c_str());

        flags_ |= SVC_DISABLED;

         return false;

     }
    std::string scon;
    if (!seclabel_.empty()) {
        scon = seclabel_;
    } else {
        char* mycon = nullptr;
        char* fcon = nullptr;

        INFO("computing context for service '%s'\n", args_[0].c_str());
        int rc = getcon(&mycon);
        if (rc < 0) {
            ERROR("could not get context while starting '%s'\n", name_.c_str());
            return false;
        }

        rc = getfilecon(args_[0].c_str(), &fcon);
        if (rc < 0) {
            ERROR("could not get context while starting '%s'\n", name_.c_str());
            free(mycon);
            return false;
        }

        char* ret_scon = nullptr;
        rc = security_compute_create(mycon, fcon, string_to_security_class("process"),
                                     &ret_scon);
        if (rc == 0) {
            scon = ret_scon;
            free(ret_scon);
        }
        if (rc == 0 && scon == mycon) {
            ERROR("Service %s does not have a SELinux domain defined.\n", name_.c_str());
            free(mycon);
            free(fcon);
            return false;
        }
        free(mycon);
        free(fcon);
        if (rc < 0) {
            ERROR("could not get context while starting '%s'\n", name_.c_str());
            return false;
        }
    }
    //上面都是對services進行判斷,設定flags, 下面才是重點
    NOTICE("Starting service '%s'...\n", name_.c_str());  //在kernel log中可以看列印資訊
    pid_t pid = fork();     //孵化程序
    if (pid == 0) {
        umask(077);

        for (const auto& ei : envvars_) {
            add_environment(ei.name.c_str(), ei.value.c_str());
        }

        for (const auto& si : sockets_) {
            int socket_type = ((si.type == "stream" ? SOCK_STREAM :
                                (si.type == "dgram" ? SOCK_DGRAM :
                                 SOCK_SEQPACKET)));
            const char* socketcon =
                !si.socketcon.empty() ? si.socketcon.c_str() : scon.c_str();

            int s = create_socket(si.name.c_str(), socket_type, si.perm,
                                  si.uid, si.gid, socketcon);
            if (s >= 0) {
                PublishSocket(si.name, s);
            }
        }

        std::string pid_str = StringPrintf("%d", getpid());
        for (const auto& file : writepid_files_) {
            if (!WriteStringToFile(pid_str, file)) {
                ERROR("couldn't write %s to %s: %s\n",
                      pid_str.c_str(), file.c_str(), strerror(errno));
            }
        }

        if (ioprio_class_ != IoSchedClass_NONE) {
            if (android_set_ioprio(getpid(), ioprio_class_, ioprio_pri_)) {
                ERROR("Failed to set pid %d ioprio = %d,%d: %s\n",
                      getpid(), ioprio_class_, ioprio_pri_, strerror(errno));
            }
        }

        if (needs_console) {
            setsid();
            OpenConsole();
        } else {
            ZapStdio();
        }

        setpgid(0, getpid());
        // As requested, set our gid, supplemental gids, and uid.
        if (gid_) {
            if (setgid(gid_) != 0) {
                ERROR("setgid failed: %s\n", strerror(errno));
                _exit(127);
            }
        }
        if (!supp_gids_.empty()) {
            if (setgroups(supp_gids_.size(), &supp_gids_[0]) != 0) {
                ERROR("setgroups failed: %s\n", strerror(errno));
                _exit(127);
            }
        }
        if (uid_) {
            if (setuid(uid_) != 0) {
                ERROR("setuid failed: %s\n", strerror(errno));
                _exit(127);
            }
        }
        if (!seclabel_.empty()) {
            if (setexeccon(seclabel_.c_str()) < 0) {
                ERROR("cannot setexeccon('%s'): %s\n",
                      seclabel_.c_str(), strerror(errno));
                _exit(127);
            }
        }

        std::vector<char*> strs;
        for (const auto& s : args_) {
            strs.push_back(const_cast<char*>(s.c_str()));
        }
        strs.push_back(nullptr);
        if (execve(args_[0].c_str(), (char**) &strs[0], (char**) ENV) < 0) {     //執行system/bin/process程式,進入framework層
            ERROR("cannot execve('%s'): %s\n", args_[0].c_str(), strerror(errno));
        }

        _exit(127);
    }

    if (pid < 0) {
        ERROR("failed to start '%s'\n", name_.c_str());
        pid_ = 0;
        return false;
    }

    time_started_ = gettime();
    pid_ = pid;
    flags_ |= SVC_RUNNING;   //将services标記為running
    if ((flags_ & SVC_EXEC) != 0) {
        INFO("SVC_EXEC pid %d (uid %d gid %d+%zu context %s) started; waiting...\n",
             pid_, uid_, gid_, supp_gids_.size(),
             !seclabel_.empty() ? seclabel_.c_str() : "default");
    }

    NotifyStateChange("running");
    return true;
}
           

調用execve執行system/bin/app_process程式, 就會進入framework/cmds/app_process/app_main.cpp的main函數.

正式進入framework層. 後文将詳細分析.