日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

本篇文章主要介紹 Android 開發(fā)中的部分知識(shí)點(diǎn),通過(guò)閱讀本篇文章,您將收獲以下內(nèi)容:

一、啟動(dòng)流程概述

二、Android啟動(dòng)分析

三、init 進(jìn)程啟動(dòng)分析

四、init 啟動(dòng)腳本分析

五、init 進(jìn)程分析

六、init 腳本執(zhí)行

七、init 進(jìn)程守護(hù)

八、init rc 腳本啟動(dòng)Zygote

九、啟動(dòng)分析小結(jié)

一、 啟動(dòng)流程概述

Android啟動(dòng)流程跟 linux啟動(dòng)類似,大致分為如下五個(gè)階段。

  • 1.開機(jī)上電,加載固化的ROM。
  • 2.加載BootLoader,拉起Android OS。
  • 3.加載Uboot,初始外設(shè),引導(dǎo)Kernel啟動(dòng)等。
  • 4.啟動(dòng)Kernel,加載驅(qū)動(dòng),硬件。
  • 5.啟動(dòng)Android,掛載分區(qū),加載驅(qū)動(dòng)、服務(wù),init進(jìn)程等。

Android系統(tǒng)啟動(dòng)大致過(guò)程如下:

 

Android 9.0 init 啟動(dòng)流程

 

 

Android 啟動(dòng)過(guò)程

由于水平有限,無(wú)法深入了理解驅(qū)動(dòng)層代碼,本文主要對(duì) Android上層啟動(dòng)流程進(jìn)行分析。

二、Android啟動(dòng)分析

Uboot啟動(dòng)Kernel完成系統(tǒng)設(shè)置后,會(huì)首先在系統(tǒng)中尋找init.rc文件,并啟動(dòng)init進(jìn)程。

 

Android 9.0 init 啟動(dòng)流程

 

 

Android 啟動(dòng)分析

三、init 進(jìn)程啟動(dòng)分析

Init進(jìn)程是Android啟動(dòng)的第一個(gè)進(jìn)程,進(jìn)程號(hào)為1,是Android的系統(tǒng)啟動(dòng)的核心進(jìn)程,主要用來(lái)創(chuàng)建Zygote、屬性服務(wù)等。 init.cpp 中的main 函數(shù),是init進(jìn)程的入口函數(shù),源碼主要存在systemcoreinit目錄下。

常見(jiàn)init.xxx.rc 進(jìn)程如下:

 

Android 9.0 init 啟動(dòng)流程

 

 

常見(jiàn)init.xxx.rc 進(jìn)程

init 進(jìn)程主要作用

 

Android 9.0 init 啟動(dòng)流程

 

 

init 進(jìn)程主要作用

/system/core/init 部分內(nèi)容如下:

 

Android 9.0 init 啟動(dòng)流程

 

 

/system/core/init 部分內(nèi)容

main 函數(shù)主要做的事情

1.創(chuàng)建掛載啟動(dòng)所需的文件系統(tǒng)(tmpfs、 devpts、 proc、 sysfs、 selinuxfs等)。

2.初始化并啟動(dòng)屬性服務(wù)

3.解析init.rc 腳本配置文件,并啟動(dòng)Zygote 進(jìn)程。

init.cpp main 函數(shù)實(shí)現(xiàn)代碼如下:

int main(int argc, char** argv) {
 ... ...
 if (!strcmp(basename(argv[0]), "watchdogd")) {
 //啟動(dòng)看門狗函數(shù)
 return watchdogd_main(argc, argv);
 }
 ... ...
 //啟動(dòng)第一階段
 if (is_first_stage) {
 boot_clock::time_point start_time = boot_clock::now();
 // 清理 umask.
 umask(0);
 clearenv();
 setenv("PATH", _PATH_DEFPATH, 1);
 // 在RAM內(nèi)存上獲取基本的文件系統(tǒng),剩余的被 rc 文件所用
 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));
 // 非特權(quán)應(yīng)用不能使用 Android 命令行
 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));
 if constexpr (WORLD_WRITABLE_KMSG) {
 mknod("/dev/kmsg_debug", S_IFCHR | 0622, makedev(1, 11));
 }
 mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8));
 mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9));
 // Mount staging areas for devices managed by vold
 // See storage config details at http://source.android.com/devices/storage/
 mount("tmpfs", "/mnt", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
 "mode=0755,uid=0,gid=1000");
 //創(chuàng)建可供讀寫的 vendor目錄
 mkdir("/mnt/vendor", 0755);
 // 在/dev目錄下掛載好 tmpfs 以及 kmsg 
 // 這樣就可以初始化 /kernel Log 系統(tǒng),供用戶打印log
 InitKernelLogging(argv);
 LOG(INFO) << "init first stage started!";
 if (!DoFirstStageMount()) {
 LOG(FATAL) << "Failed to mount required partitions early ...";
 }
 SetInitAvbVersionInRecovery();
 // Enable seccomp if global boot option was passed (otherwise it is enabled in zygote).
 global_seccomp();
 // 優(yōu)先加載selinux log系統(tǒng), 緊接著初始化selinux
 SelinuxSetupKernelLogging();
 SelinuxInitialize();
 // 添加 selinux 是否啟動(dòng)成功的log
 if (selinux_android_restorecon("/init", 0) == -1) {
 PLOG(FATAL) << "restorecon failed of /init failed";
 }
 setenv("INIT_SECOND_STAGE", "true", 1);
 static constexpr uint32_t kNanosecondsPerMillisecond = 1e6;
 uint64_t start_ms = start_time.time_since_epoch().count() / kNanosecondsPerMillisecond;
 setenv("INIT_STARTED_AT", std::to_string(start_ms).c_str(), 1);
 char* path = argv[0];
 char* args[] = { path, nullptr };
 execv(path, args);
 // execv() only returns if an error hAppened, in which case we
 // panic and never fall through this conditional.
 PLOG(FATAL) << "execv("" << path << "") failed";
 }
 //啟動(dòng)第二階段
 InitKernelLogging(argv);
 LOG(INFO) << "init second stage started!";
 // Set up a session keyring that all processes will have access to. It
 // will hold things like FBE encryption keys. No process should override
 // its session keyring.
 keyctl_get_keyring_ID(KEY_SPEC_SESSION_KEYRING, 1);
 // Indicate that booting is in progress to background fw loaders, etc.
 close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));
 //初始化屬性
 property_init();
 // 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();
 // Propagate the kernel variables to internal variables
 // used by init as well as the current required properties.
 export_kernel_boot_props();
 // Make the time that init started available for bootstat to log.
 property_set("ro.boottime.init", getenv("INIT_STARTED_AT"));
 property_set("ro.boottime.init.selinux", getenv("INIT_SELINUX_TOOK"));
 // Set libavb version for Framework-only OTA match in Treble build.
 const char* avb_version = getenv("INIT_AVB_VERSION");
 if (avb_version) property_set("ro.boot.avb_version", avb_version);
 // 清空設(shè)置的環(huán)境變量
 unsetenv("INIT_SECOND_STAGE");
 unsetenv("INIT_STARTED_AT");
 unsetenv("INIT_SELINUX_TOOK");
 unsetenv("INIT_AVB_VERSION");
 // 設(shè)置第二階段的selinux
 SelinuxSetupKernelLogging();
 SelabelInitialize();
 SelinuxRestoreContext();
 //創(chuàng)建 epoll 句柄
 epoll_fd = epoll_create1(EPOLL_CLOEXEC);
 if (epoll_fd == -1) {
 PLOG(FATAL) << "epoll_create1 failed";
 }
 //設(shè)置 子進(jìn)程處理函數(shù)
 sigchld_handler_init();
 if (!IsRebootCapable()) {
 // If init does not have the CAP_SYS_BOOT capability, it is running in a container.
 // In that case, receiving SIGTERM will cause the system to shut down.
 InstallSigtermHandler();
 }
 LoadRscRoProps();
 property_load_boot_defaults();
 export_oem_lock_status();
 //啟動(dòng)屬性服務(wù)
 start_property_service();
 //為USB存儲(chǔ)設(shè)置udc Contorller, sys/class/udc
 set_usb_controller();
 const BuiltinFunctionMap function_map;
 Action::set_function_map(&function_map);
 subcontexts = InitializeSubcontexts();
 ActionManager& am = ActionManager::GetInstance();
 ServiceList& sm = ServiceList::GetInstance();
 LoadBootScripts(am, sm);
 // 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();
 am.QueueEventTrigger("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");
 // ... so that we can start queuing up actions that require stuff from /dev.
 am.QueueBuiltinAction(MixHwrngIntoLinuxRngAction, "MixHwrngIntoLinuxRng");
 am.QueueBuiltinAction(SetMmapRndBitsAction, "SetMmapRndBits");
 am.QueueBuiltinAction(SetKptrRestrictAction, "SetKptrRestrict");
 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");
 // 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(MixHwrngIntoLinuxRngAction, "MixHwrngIntoLinuxRng");
 // Don't mount filesystems or start core system services in charger mode.
 std::string bootmode = GetProperty("ro.bootmode", "");
 if (bootmode == "charger") {
 am.QueueEventTrigger("charger");
 } else {
 am.QueueEventTrigger("late-init");
 }
 // Run all property triggers based on current state of the properties.
 am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");
 while (true) {
 // By default, sleep until something happens.
 int epoll_timeout_ms = -1;
 if (do_shutdown && !shutting_down) {
 do_shutdown = false;
 if (HandlePowerctlMessage(shutdown_command)) {
 shutting_down = true;
 }
 }
 if (!(waiting_for_prop || Service::is_exec_service_running())) {
 am.ExecuteOneCommand();
 }
 if (!(waiting_for_prop || Service::is_exec_service_running())) {
 if (!shutting_down) {
 auto next_process_restart_time = RestartProcesses();
 // If there's a process that needs restarting, wake up in time for that.
 if (next_process_restart_time) {
 epoll_timeout_ms = std::chrono::ceil<std::chrono::milliseconds>(
 *next_process_restart_time - boot_clock::now())
 .count();
 if (epoll_timeout_ms < 0) epoll_timeout_ms = 0;
 }
 }
 // If there's more work to do, wake up again immediately.
 if (am.HasMoreCommands()) epoll_timeout_ms = 0;
 }
 epoll_event ev;
 int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev, 1, epoll_timeout_ms));
 if (nr == -1) {
 PLOG(ERROR) << "epoll_wait failed";
 } else if (nr == 1) {
 ((void (*)()) ev.data.ptr)();
 }
 }
 return 0;
}

基于MTK 平臺(tái) init.cpp 源碼分析

 

Android 9.0 init 啟動(dòng)流程

 

 

基于MTK 平臺(tái) init.cpp 主要作用

四、 init 啟動(dòng)腳本分析

init.rc 路徑 一般在system/core/rootdir下,init腳本是有Android 初始化語(yǔ)言編寫。

Android Init Language 語(yǔ)句類型:

  • 1.Action
  • 2.Command
  • 3.Service
  • 4.Option
  • 5.Import

 

Android 9.0 init 啟動(dòng)流程

 

 

init 進(jìn)程分析

Android 9.0 init 啟動(dòng)流程

 

 

init.rc on

Android 9.0 init 啟動(dòng)流程

 

 

init.rc services

Android 9.0 init 啟動(dòng)流程

 

 

init.rc import

五、init 進(jìn)程分析

 

Android 9.0 init 啟動(dòng)流程

 

 

init 進(jìn)程分析

Android 9.0 init 啟動(dòng)流程

 

 

init 解析腳本分析

Android 9.0 init 啟動(dòng)流程

 

 

init 事件列表

Android 9.0 init 啟動(dòng)流程

 

 

init 事件結(jié)構(gòu)

六 、init 腳本執(zhí)行

 

Android 9.0 init 啟動(dòng)流程

 

 

init 進(jìn)程解析和執(zhí)行

Android 9.0 init 啟動(dòng)流程

 

 

整理事件列表

Android 9.0 init 啟動(dòng)流程

 

 

init 構(gòu)建事件

Android 9.0 init 啟動(dòng)流程

 

 

Service 事件分類

Android 9.0 init 啟動(dòng)流程

 

 

init 進(jìn)程執(zhí)行命令和啟動(dòng)服務(wù)

七、init 進(jìn)程守護(hù)

init進(jìn)程處理消息事件

  1. 根據(jù)Shell或者系統(tǒng)中消息設(shè)置系統(tǒng)prop
  •  
  1. 守護(hù)系統(tǒng)服務(wù),如果服務(wù)退出,重啟退出的服務(wù)。

 

Android 9.0 init 啟動(dòng)流程

 

 

init守護(hù)進(jìn)程

Android 9.0 init 啟動(dòng)流程

 

 

init 處理 prop 消息分析

Android 9.0 init 啟動(dòng)流程

 

 

init 守護(hù)服務(wù)分析

八、init rc 腳本啟動(dòng)Zygote

Zygote 的 classname 為main.

init.rc文件配置代碼如下:

... ... 
on nonencrypted
 class_start main
 class_start late_start
on property:sys.init_log_level=*
 loglevel ${sys.init_log_level}
... ...

九、啟動(dòng)分析小結(jié)

 

Android 9.0 init 啟動(dòng)流程

 

 

啟動(dòng)分析小結(jié)

分享到:
標(biāo)簽:Android
用戶無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定