Android系統啓動分析(一)

本文的分析基於Android 8.1源碼。

Android系統啓動與應用程序的啓動流程、四大組件原理、AMS、ClassLoader等息息相關,因此瞭解Android系統啓動流程對深入理解Android有很大的幫助。

本文將分爲以下幾個小節講述Android系統的系統流程,分別是:init進程啓動、Zygote進程啓動、SystemServer進程啓動以及Launcher進程啓動。

一、init進程啓動

  都知道當手機關機時不會啓動任何一個進程,所以在init進程啓動前,Android就爲進程的啓動做了很多鋪墊。具體爲:按下電源鍵加載BootLoader、拉起系統OS、啓動Linux內核…但由於本人暫未學到Linux內核,因此前面的暫不做分析(當我沒說emmm…)

本節涉及到的文件有:

文件路徑
init.cppsystem/core/init/init.cpp
init.rcsystem/core/rootdir/init.rc
init.zygote64_32.rcsystem/core/rootdir/init.zygote64_32.rc
service.cppsystem/core/init/service.cpp
builtins.cpp system/core/init/builtins.cpp

1.1 init.main()

  Linux內核啓動後,運行的第一個進程是init進程。

system/core/init/init.cpp
int main(int argc, char** argv) {
    if (!strcmp(basename(argv[0]), "ueventd")) {
        return ueventd_main(argc, argv);
    }
    if (!strcmp(basename(argv[0]), "watchdogd")) {
        return watchdogd_main(argc, argv);
    }
    if (REBOOT_BOOTLOADER_ON_PANIC) {
        InstallRebootSignalHandlers();
    }
    add_environment("PATH", _PATH_DEFPATH);
    bool is_first_stage = (getenv("INIT_SECOND_STAGE") == nullptr);
    //註釋1:掛載必須的文件路徑
    if (is_first_stage) {
        ……
        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));
        // Don't expose the raw commandline to unprivileged processes.
        chmod("/proc/cmdline", 0440);
        gid_t groups[] = { AID_READPROC };
        setgroups(arraysize(groups), groups);
        mount("sysfs", "/sys", "sysfs", 0, NULL);
        mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL);
        mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11));
        mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8));
        mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9));
        //system/core/init/init_first_stage.cpp
        SetInitAvbVersionInRecovery();
        //加載及初始化SELinux
        selinux_initialize(true);
        ……
    }
    //初始化Kernel Log
    InitKernelLogging(argv);
    //bionic/libc/bionic/system_properties.cpp
    //註釋2:初始化屬性服務
    property_init();
    ……
    //
    signal_handler_init();
    //導入默認的環境變量
    //"/system/etc/prop.default,/odm/default.prop,/vendor/default.prop"
    property_load_boot_defaults();
    //啓動屬性服務
    start_property_service();
    ……
    const BuiltinFunctionMap function_map;
    Action::set_function_map(&function_map);
    ActionManager& am = ActionManager::GetInstance();
    ServiceManager& sm = ServiceManager::GetInstance();
    Parser& parser = Parser::GetInstance();
    //make_unique是C++的智能指針,可以自動管理內存
    //ServiceParser、ActionParser、ImportParser分別解析service,action,import
    parser.AddSectionParser("service", std::make_unique<ServiceParser>(&sm));
    parser.AddSectionParser("on", std::make_unique<ActionParser>(&am));
    parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser));
    std::string bootscript = GetProperty("ro.boot.init_rc", "");
    if (bootscript.empty()) {
    	//若不存在"ro.boot.init_rc"屬性,則解析下列文件
	    parser.ParseConfig("/init.rc"); //註釋3,解析init.rc
    	parser.set_is_system_etc_init_loaded(
    	parser.ParseConfig("/system/etc/init"));
    	parser.set_is_vendor_etc_init_loaded(
    	parser.ParseConfig("/vendor/etc/init"));
parser.set_is_odm_etc_init_loaded(parser.ParseConfig("/odm/etc/init"));
	} else {
        //如果"ro.boot.init_rc"屬性存在,則解析屬性值
    	parser.ParseConfig(bootscript);
    	parser.set_is_system_etc_init_loaded(true);
    	parser.set_is_vendor_etc_init_loaded(true);
    	parser.set_is_odm_etc_init_loaded(true);
	}
	……
 	while (true) {
        // By default, sleep until something happens.
        int epoll_timeout_ms = -1;
        //重置shutting_down標誌
        if (do_shutdown && !shutting_down) {
            do_shutdown = false;
            if (HandlePowerctlMessage(shutdown_command)) {
                shutting_down = true;
            }
        }
        if (!(waiting_for_prop || sm.IsWaitingForExec())) {
            //執行每個Action所帶的執行函數
            am.ExecuteOneCommand();
        }
        if (!(waiting_for_prop || sm.IsWaitingForExec())) {
            //重啓死去的進程
            if (!shutting_down) restart_processes();
            ……
        }
    }
    return 0;
}

init進程做的事較多,但我們只需關注幾點:

  1. 註釋1處創建和掛載啓動所需的文件
  2. 註釋2處初始化屬性服務,隨後調用start_property_service()啓動屬性服務
  3. 註釋3處解析**/init.rc,{/system,/vendor,/odm}/etc/init**幾個文件

1.2 解析init.rc

init.rc是用Android初始化語言(Android Init Language)編寫的文件,在init文件夾中的README對它有描述。感興趣的可以自行去看。

system/core/init/README.md

AIL主要包含5種類型的語句:Actions, Commands, Services, Options, Imports.

重點來看看Actions和Services

Actions的格式如下:

on <trigger> [&& <trigger>]*   #觸發條件
   <command>                   #操作命令
   <command>

例如:

on charger
    class_start charger

只要條件charger成立,便會執行 class_start charger 命令

Services的格式如下:

service <name> <pathname> [<argument>] #<service服務名稱><執行文件路徑><參數>
   <option>                           #這個服務的一些配置
   <option>

例如:

service adbd /system/bin/adbd --root_seclabel=u:r:su:s0
    class core
    socket adbd stream 660 system system
    disabled
    seclabel u:r:adbd:s0

這是init.usb.rc的一段代碼,用來啓動adbd服務

瞭解了AIL語言後,我們來看看init.rc,代碼路徑如下:

system/core/rootdir/init.rc
import /init.environ.rc
import /init.usb.rc
import /init.${ro.hardware}.rc
import /vendor/etc/init/hw/init.${ro.hardware}.rc
import /init.usb.configfs.rc
import /init.${ro.zygote}.rc
……

在init.rc開始位置引入了一些rc文件,重點關注Zygote啓動相關的文件。/init.${ro.zygote}.rc

這裏根據ro.zygote屬性值加載對應的rc文件。這個屬性值可通過**adb shell getprop | grep “zygote”**獲取。

例如在我的手機上該屬性值爲: [ro.zygote]: [zygote64_32]

在我手機上啓動Zygote會涉及到init.zygote64_32.rc,代碼路徑如下:

system/core/rootdir/init.zygote64_32.rc
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
    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
    onrestart restart wificond
    writepid /dev/cpuset/foreground/tasks
service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary --enable-lazy-preload
    class main
    priority -20
    user root
    group root readproc
    socket zygote_secondary stream 660 root system
    onrestart restart zygote
    writepid /dev/cpuset/foreground/tasks

可以看到該文件裏有兩個service,最大的區別就是對應的可執行文件不一樣。可以看到,啓動64位的Zygote需要執行/system/bin/app_process64,後面是傳入的參數。
那麼zygote的service是怎麼被解析的呢? 我們回憶一下init.main()。

system/core/init/init.cpp
int main(int argc, char** argv) {
    ……
    ServiceManager& sm = ServiceManager::GetInstance();
    Parser& parser = Parser::GetInstance();
    //make_unique是C++的智能指針,可以自動管理內存
    //ServiceParser、ActionParser、ImportParser分別解析service,action,import
    parser.AddSectionParser("service", std::make_unique<ServiceParser>(&sm));	
    ……
 	parser.ParseConfig("/init.rc");
    ……
    return 0;
}

AddSectionParser函數將"service"當做鍵,ServiceParser對象當做值,存到一個map中,執行ParseConfig函數後,會調用ServiceParser的ParseSection和ParseLineSection函數來解析service語句。

1.2.1 解析service

system/core/init/service.cpp

ServiceParser的實現在 system/core/init/service.cpp中,ParseSection的實現如下:

bool ServiceParser::ParseSection(std::vector<std::string>&& args, const std::string& filename,int line, std::string* err) {
    if (args.size() < 3) {
        *err = "services must have a name and a program";
        return false;
    }
   	//獲取服務名
    const std::string& name = args[1];
    if (!IsValidName(name)) { //檢查service的name是否有效
        *err = StringPrintf("invalid service name '%s'", name.c_str());
        return false;
    }
    Service* old_service = service_manager_->FindServiceByName(name);
    if (old_service) {
        *err = "ignored duplicate definition of service '" + name + "'";
        return false;
    }
    std::vector<std::string> str_args(args.begin() + 2, args.end());
    //將service_指針指向當前Service對象
    service_ = std::make_unique<Service>(name, str_args);
    return true;
}

ParseSection主要檢驗參數的有效性,並構造一個Service對象。

接下來看看ParseLineSection

bool ServiceParser::ParseLineSection(std::vector<std::string>&& args, int line, std::string* err) {
    return service_ ? service_->ParseLine(std::move(args), err) : false;
}

再來看看ParseLine

bool Service::ParseLine(const std::vector<std::string>& args, std::string* err) {
    static const OptionParserMap parser_map;
    auto parser = parser_map.FindFunction(args, err); //1
    if (!parser) {
        return false;
    }
    return (this->*parser)(args, err); //2
}

ParseLine的作用是爲Service的每一個Option指定處理函數。

註釋1處FindFunction根據傳入的args找到對應的處理函數,並在註釋2的return語句中調用。

具體的Options和對應的函數在Service::OptionParserMap::map()中定義

const Service::OptionParserMap::Map& Service::OptionParserMap::map() const {
    constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
    // clang-format off
    static const Map option_parsers = {
        ……
        {"priority",    {1,1,&Service::ParsePriority}},
       ……
        {"namespace",   {1,2,&Service::ParseNamespace}},
		……
    };
    // clang-format on
    return option_parsers;
}

解析完所有數據後,會調用EndSection函數

void ServiceParser::EndSection() {
    if (service_) {
        service_manager_->AddService(std::move(service_));
    }
}

在EndSection中又調用了ServiceManager的AddService函數。

void ServiceManager::AddService(std::unique_ptr<Service> service) {
    services_.emplace_back(std::move(service));
}

EndSection的主要工作是將解析完成的Service添加到ServiceManager的service_鏈表中。

1.2.2 啓動ServiceManager

ServiceManager用來管理系統中所有的binder service,最主要的作用是註冊添加服務和Zygote進程啓動。

system/core/rootdir/init.rc
on post-fs
	……
    start servicemanager
    ……

1.2.3 啓動Zygote

system/core/rootdir/init.rc
on nonencrypted
    class_start main
    class_start late_start

這是一個Action語句,class_start對應的函數是do_class_start, class_start main會啓動classname爲main的Service

system/core/init/builtins.cpp
static int do_class_start(const std::vector<std::string>& args) {
    ServiceManager::GetInstance().
        ForEachServiceInClass(args[1], [] (Service* s) { s->StartIfNotDisabled(); });
    return 0;
}

ForEachServiceInClass會找到classname爲main的Service,並執行Service的StartIfNotDisabled。

system/core/init/service.cpp
bool Service::StartIfNotDisabled() {
    if (!(flags_ & SVC_DISABLED)) {
        return Start();
    } else {
        flags_ |= SVC_DISABLED_START;
    }
    return true;
}

接着進入到Start()函數。Start函數較長,這裏只截取關鍵部分分析。

bool Service::Start() {
    flags_ &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART|SVC_DISABLED_START));
    //如果Service已經啓動,則直接返回
    if (flags_ & SVC_RUNNING) {
        return false;
    }
    //對Service判斷,設置一些Flag
	……
    pid_t pid = -1;
    if (namespace_flags_) {
        pid = clone(nullptr, nullptr, namespace_flags_ | SIGCHLD, nullptr);
    } else {
        pid = fork();
    }
    if (pid == 0) {
        //fork出子進程後,爲子進程設置參數
        ……
        //執行對應Service的對應執行文件
        //調用execve函數執行程序
      	if (!ExpandArgsAndExecve(args_)) {
    		PLOG(ERROR) << "cannot execve('" << args_[0] << "')";
		}
    }
    ……
    return true;
}

Start()函數先通過fork函數創建一個子進程,然後在子進程中調用ExpandArgsAndExecve()->execve()函數啓動一個新的程序。fork()+execve()結合可以產生一個新的進程,這裏涉及到Linux內核層面,便不再繼續深入。

由init.zygote64_32.rc可知,Zygote的執行路徑爲:/system/bin/app_process64,執行該程序後,不管是32位還是64位系統,都會進入到framework/cmds/app_process/app_main.cpp的main()函數。
由此可知,Zygote進程也不是憑空產生,而是由Init進程fork而來。

1.3 小結

init進程的啓動做了很多工作,主要爲以下幾點:

  1. 創建和掛載必須的文件路徑
  2. 初始化並啓動屬性服務
  3. 解析並執行init.rc文件的語句

至此,代碼流程進入到framework層,關於Zygote進程的啓動將在下節講解。
Android系統啓動分析(二)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章