DEX2OTA流程概述​
  8km7sx0kvVPb 2023年11月02日 25 0

DEX2OTA流程概述

DEX2OTA流程概述​_compile


dexopt()

/frameworks/native/cmds/installd/dexopt.cpp


包含了大量的判断及属性代码,其中run_dex2oat是将dex转化为oat的关键函数。

  1. pid_t pid = fork();这行代码调用fork()函数创建一个新的进程。fork()函数返回两次:在父进程中,它返回新创建子进程的PID,在子进程中,它返回0。
  2. if (pid == 0) { ... }这个if语句用于判断当前是在子进程中还是在父进程中。由于子进程中fork()返回0,所以这段代码只会在子进程中执行。
  3. else{

int res = wait_child(pid){

...

}

}

由于父进程中fork()返回0,所以这段代码只会在父进程执行。

DEX2OTA流程概述​_dex2ota_02


在子进程中执行run_dex2oat,父进程中阻塞等待子进程结束

在C或C++语言中,wait_child函数通常用于父进程等待子进程结束并获取子进程的退出状态。这个函数通常在fork或exec等系统调用之后使用,以确保子进程完成任务后再继续执行父进程的代码。

以下是一个示例代码,展示了如何使用wait_child函数等待子进程结束:

#include <stdio.h>

#include <stdlib.h>

#include <sys/wait.h>

#include <unistd.h>


int main() {

pid_t pid = fork(); // 创建一个子进程


if (pid == -1) {

perror("fork failed");

exit(EXIT_FAILURE);

} else if (pid == 0) {

// 子进程执行的代码

printf("Child process running.../n");

sleep(2); // 模拟子进程执行任务

printf("Child process finished./n");

exit(EXIT_SUCCESS);

} else {

// 父进程执行的代码

printf("Parent process waiting for child.../n");

int res = wait_child(pid); // 等待子进程结束

if (res == -1) {

perror("wait_child failed");

exit(EXIT_FAILURE);

} else {

printf("Child process exited with status: %d/n", res);

}

}


return 0;

}


run_dex2oat()

大约99%的函数都是在做属性的判断以及参数的定义,最终确定了bin程序及所需参数。

execv(dex2oat_bin, (char * const *)argv);

execv是一个函数名,它属于Unix和类Unix操作系统(如Linux)中的系统调用。这个函数的目的是装入并运行其它程序的函数。它的基本语法是:int execv(const char *pathname, char * const argv[]),其中pathname是你想要执行的程序的路径,而argv是一个指针数组,其中每个指针指向一个参数字符串,这个数组必须以NULL指针结束。

execv函数在执行新的程序后,会替换当前进程的映像,加载并执行新的程序。这意味着在调用execv之后,当前的程序会停止运行,而新的程序(在给定的路径下)会在同一个进程内开始运行。新的程序可以访问当前进程的数据,但一旦execv返回,当前进程的代码和数据就会被丢弃。

DEX2OTA流程概述​_watchdog_03



fork的意义

DEX2OTA流程概述​_watchdog_04



dex2ota_bin

/art/dex2oat/dex2oat.cc


int main(int argc, char** argv) {

int result = static_cast<int>(art::Dex2oat(argc, argv));

// Everything was done, do an explicit exit here to avoid running Runtime destructors that take

// time (bug 10645725) unless we're a debug or instrumented build or running on valgrind. Note:

// The Dex2Oat class should not destruct the runtime in this case.

if (!art::kIsDebugBuild && !art::kIsPGOInstrumentation && (RUNNING_ON_MEMORY_TOOL == 0)) {

_exit(result);

}

return result;

}

dex2oat()

main函数中,调用了art命名空间下的dex2oat函数,在dex2oat()函数中,


  1. arm上的workaround由b13564922()完成,这个与dex2oat的主要线程无关,可以暂时忽略
  2. 构造Dex2oat对象——Dex2Oat dex2oat(&timings);
  3. 处理命令行参数,将dex文件名文件路径等参数传入函数中——dex2oat.ParseArgs(argc, argv);
  4. 判断对于dex文件是否有写的权限——dex2oat.OpenFile()
  5. 打印命令行参数——LOG(INFO) << CommandLine();
  6. 判断dex2oat编译环境是否启动成功——dex2oat.Setup()
  7. 根据是否image分别调用CompileImage(dex2oat)或CompileApp(dex2oat)的处理

// Helps debugging on device. Can be used to determine which dalvikvm instance invoked a dex2oat

// instance. Used by tools/bisection_search/bisection_search.py.

VLOG(compiler) << "Running dex2oat (parent PID = " << getppid() << ")";


dex2oat::ReturnCode result;

if (dex2oat->IsImage()) {

result = CompileImage(*dex2oat);

} else {

result = CompileApp(*dex2oat);

}

CompileApp()&&CompileImage()

两者代码基本相同,有一个共同的特点,就是都先调用了dex2oat.Compile()函数。

Compile()

// Create and invoke the compiler driver. This will compile all the dex files.

void Compile() {

TimingLogger::ScopedTiming t("dex2oat Compile", timings_);

compiler_phases_timings_.reset(new CumulativeLogger("compilation times"));


// Handle and ClassLoader creation needs to come after Runtime::Create

jobject class_loader = nullptr;

Thread* self = Thread::Current();

if (!boot_image_option_.empty()) {

ClassLinker* class_linker = Runtime::Current()->GetClassLinker();

OpenClassPathFiles(runtime_->GetClassPathString(), dex_files_, &class_path_files_);

ScopedObjectAccess soa(self);

// Classpath: first the class-path given.

std::vector<const DexFile*> class_path_files;

for (auto& class_path_file : class_path_files_) {

class_path_files.push_back(class_path_file.get());

}

// Store the classpath we have right now.

key_value_store_->Put(OatHeader::kClassPathKey,

OatFile::EncodeDexFileDependencies(class_path_files));

// Then the dex files we'll compile. Thus we'll resolve the class-path first.

class_path_files.insert(class_path_files.end(), dex_files_.begin(), dex_files_.end());

class_loader = class_linker->CreatePathClassLoader(self, class_path_files);

}

driver_.reset(new CompilerDriver(compiler_options_.get(),

verification_results_.get(),

&method_inliner_map_,

compiler_kind_,

instruction_set_,

instruction_set_features_.get(),

image_,

image_classes_.release(),

compiled_classes_.release(),

nullptr,

thread_count_,

dump_stats_,

dump_passes_,

dump_cfg_file_name_,

compiler_phases_timings_.get(),

swap_fd_,

profile_file_));

driver_->CompileAll(class_loader, dex_files_, timings_);

}


之后便是对具体的dex文件进行complie,不再做具体分析。

WatchDog

WatchDog的开启时机在于dex2oat()中的ParseArgs(argc, argv);

  1. 设置编译选项compiler_options_.reset(new CompilerOptions());
  2. 对参数进行筛选检查
  3. 配置编译器

if (!ReadCompilerOptions(args, compiler_options_.get(), &error_msg)) {

Usage(error_msg.c_str());

}


ProcessOptions(parser_options.get());

// Insert some compiler things.

InsertCompileOptions(argc, argv);

在processOptions中对相关选项进行配置

其中有着关于WatchDog开关的配置

// Done with usage checks, enable watchdog if requested

if (parser_options->watch_dog_enabled) {

int64_t timeout = parser_options->watch_dog_timeout_in_ms > 0

? parser_options->watch_dog_timeout_in_ms

: WatchDog::kDefaultWatchdogTimeoutInMS;

watchdog_.reset(new WatchDog(timeout));

}


WatchDog::kDefaultWatchdogTimeoutInMS便是对dex2oat编译管控的具体时间

// 9.5 minutes scaled by kSlowdownFactor. This is slightly smaller than the Package Manager

// watchdog (PackageManagerService.WATCHDOG_TIMEOUT, 10 minutes), so that dex2oat will abort

// itself before that watchdog would take down the system server.

static constexpr int64_t kWatchDogTimeoutSeconds = kWatchdogSlowdownFactor * (9 * 60 + 30);


static constexpr int64_t kDefaultWatchdogTimeoutInMS =

kWatchdogVerifyMultiplier * kWatchDogTimeoutSeconds * 1000;


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
8km7sx0kvVPb
作者其他文章 更多