update_engine-整体结构(一)
update_engine简介
update_engine是A/B升级的核心逻辑。理解了update_engine就理解了在Android系统中A/B升级是如何运行的。它的代码放在源码目录下system/update_engine/下。那么接下来对update_engine进行分析,首先会分析它的结构,之后分析它的核心操作。
update_engine结构分析
Android.mk分析
一个源码工程中包含的源文件会有很多,但是不代表所有的文件都和我们的目标相关。而通过Android.mk文件可以找到和分析目标update_engine相关的源文件。我们只需要关注这些文件便可。Android.mk中直接和update_engine相关的内容
include $(CLEAR_VARS)
LOCAL_MODULE := update_engine
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_REQUIRED_MODULES := \
cacerts_google
LOCAL_CPP_EXTENSION := .cc
LOCAL_CLANG := true
LOCAL_CFLAGS := $(ue_common_cflags)
LOCAL_CPPFLAGS := $(ue_common_cppflags)
LOCAL_LDFLAGS := $(ue_common_ldflags)
LOCAL_C_INCLUDES := \
$(ue_common_c_includes)
LOCAL_SHARED_LIBRARIES := \
$(ue_common_shared_libraries)
LOCAL_STATIC_LIBRARIES := \
$(ue_common_static_libraries)
LOCAL_SRC_FILES := \
main.cc ifeq ($(local_use_omaha),)
LOCAL_C_INCLUDES += \
$(ue_libupdate_engine_exported_c_includes)
LOCAL_STATIC_LIBRARIES += \
libupdate_engine \
$(ue_libupdate_engine_exported_static_libraries:-host=)
LOCAL_SHARED_LIBRARIES += \
$(ue_libupdate_engine_exported_shared_libraries:-host=)
else # local_use_omaha ==
LOCAL_STATIC_LIBRARIES += \
libupdate_engine_android \
$(ue_libupdate_engine_android_exported_static_libraries:-host=)
LOCAL_SHARED_LIBRARIES += \
$(ue_libupdate_engine_android_exported_shared_libraries:-host=)
endif # local_use_omaha == LOCAL_INIT_RC := update_engine.rc
include $(BUILD_EXECUTABLE)
从中首先可以获取到的信息就是该模块是个可执行的模块,并且入口函数在main.cc中。接下来再看它一定依赖的文件。
ue_common_c_includes := \ #依赖的c文件
$(LOCAL_PATH)/client_library/include \
system ue_common_shared_libraries := \ #依赖的动态库
libbrillo-stream \
libbrillo \ #在源码下的external中
libchrome #在源码下的external中 ue_common_static_libraries := \ #依赖的静态库
libgtest_prod \
由于local_use_omaha := $(if $(filter true,$(PRODUCT_IOT)),1,0) 意思为该设备是否是IOT设备,如果是则值为1否则为0,在这里我们分析的状况是非IOT设备。所以local_use_omaha := 0。所以该模块还依赖如下
LOCAL_STATIC_LIBRARIES += \ #静态依赖
libupdate_engine_android \
$(ue_libupdate_engine_android_exported_static_libraries:-host=)
-------------------------------------------------------------------------
ue_libupdate_engine_android_exported_static_libraries := \
libpayload_consumer \
libfs_mgr \
libbase \
liblog \
$(ue_libpayload_consumer_exported_static_libraries) \
libupdate_engine_boot_control \
$(ue_libupdate_engine_boot_control_exported_static_libraries)
ue_libupdate_engine_android_exported_shared_libraries := \
$(ue_libpayload_consumer_exported_shared_libraries) \
$(ue_libupdate_engine_boot_control_exported_shared_libraries) \
libandroid_net \
libbinder \
libbinderwrapper \
libbrillo-binder \
libcutils \
libcurl \
libssl \
libutils LOCAL_SHARED_LIBRARIES += \ #动态依赖
$(ue_libupdate_engine_android_exported_shared_libraries:-host=)
-------------------------------------------------------------------------
ue_libupdate_engine_android_exported_shared_libraries := \
$(ue_libpayload_consumer_exported_shared_libraries) \
$(ue_libupdate_engine_boot_control_exported_shared_libraries) \
libandroid_net \
libbinder \
libbinderwrapper \
libbrillo-binder \
libcutils \
libcurl \
libssl \
libutils
可以看到其中还有很多依赖的源文件是以变量赋值的形式出现的。这里就不一一列出了,但是方法已经知道了,那就是当遇到一个方法存在于两个文件中时就可以通过Android.mk来确定我们所需要的文件。
从main.cc开始分析
src/system/update_engine/main.cc
int main(int argc, char** argv) {
DEFINE_bool(logtostderr, false,
"Write logs to stderr instead of to a file in log_dir.");
DEFINE_bool(foreground, false,
"Don't daemon()ize; run in foreground.");
chromeos_update_engine::Terminator::Init();
brillo::FlagHelper::Init(argc, argv, "Chromium OS Update Engine");
chromeos_update_engine::SetupLogging(FLAGS_logtostderr);
if (!FLAGS_foreground)
PLOG_IF(FATAL, daemon(, ) == ) << "daemon() failed";
LOG(INFO) << "Chrome OS Update Engine starting";
// xz-embedded requires to initialize its CRC-32 table once on startup.
xz_crc32_init();
// Ensure that all written files have safe permissions.
// This is a mask, so we _block_ all permissions for the group owner and other
// users but allow all permissions for the user owner. We allow execution
// for the owner so we can create directories.
// Done _after_ log file creation.
umask(S_IRWXG | S_IRWXO);
chromeos_update_engine::UpdateEngineDaemon update_engine_daemon;
int exit_code = update_engine_daemon.Run();
LOG(INFO) << "Chrome OS Update Engine terminating with exit code "
<< exit_code;
return exit_code;
}
可以看到首先进行了初始化工作,这些初始化并不影响对程序主干的分析,所以可以暂时略过。直接看最重要的UpdateEngineDaemon以及其Run()方法。UpdateEngineDaemon继承了brillo::Daemon,UpdateEngineDaemon的内容为
src/system/update_engine/daemon.h
namespace chromeos_update_engine {
class UpdateEngineDaemon : public brillo::Daemon {
public:
UpdateEngineDaemon() = default;
protected:
int OnInit() override;
private:
#if USE_DBUS
// Run from the main loop when the |dbus_adaptor_| object is registered. At
// this point we can request ownership of the DBus service name and continue
// initialization.
void OnDBusRegistered(bool succeeded);
// Main D-Bus service adaptor.
std::unique_ptr<UpdateEngineAdaptor> dbus_adaptor_;
#endif // USE_DBUS
// The Subprocess singleton class requires a brillo::MessageLoop in the
// current thread, so we need to initialize it from this class instead of
// the main() function.
Subprocess subprocess_;
#if USE_BINDER
brillo::BinderWatcher binder_watcher_;
#endif // USE_BINDER
#if USE_BINDER
#if USE_OMAHA
android::sp<BinderUpdateEngineBrilloService> binder_service_;
#else // !USE_OMAHA
android::sp<BinderUpdateEngineAndroidService> binder_service_;
#endif // USE_OMAHA
#endif // USE_BINDER
// The daemon state with all the required daemon classes for the configured
// platform.
std::unique_ptr<DaemonStateInterface> daemon_state_;
DISALLOW_COPY_AND_ASSIGN(UpdateEngineDaemon);
};
} // namespace chromeos_update_engine
#endif // UPDATE_ENGINE_DAEMON_H_
从中可以看到它并没有对Run()进行重写,所以必须要看看daemon类的内容了:
src/external/librillo/brillo/daemons/daemon.cc
namespace brillo {
........
int Daemon::Run() {
int exit_code = OnInit(); //会调用子类的OnInit()方法
if (exit_code != EX_OK)
return exit_code;
message_loop_.Run();
OnShutdown(&exit_code_);
// base::RunLoop::QuitClosure() causes the message loop to quit
// immediately, even if pending tasks are still queued.
// Run a secondary loop to make sure all those are processed.
// This becomes important when working with D-Bus since dbus::Bus does
// a bunch of clean-up tasks asynchronously when shutting down.
while (message_loop_.RunOnce(false /* may_block */)) {}
return exit_code_;
}
int Daemon::OnInit() {
async_signal_handler_.Init();
for (int signal : {SIGTERM, SIGINT}) {
async_signal_handler_.RegisterHandler(
signal, base::Bind(&Daemon::Shutdown, base::Unretained(this)));
}
async_signal_handler_.RegisterHandler(
SIGHUP, base::Bind(&Daemon::Restart, base::Unretained(this)));
return EX_OK;
}
........
}
可以看到在Run()方法中主要就是调用了OnInit()方法,子类一旦对其进行了重写那么就会调用子类的OnInit()方法.UpdateEngineDaemon的Oninit()方法体如下:
src/system/update_engine/daemon.cc
namespace chromeos_update_engine {
int UpdateEngineDaemon::OnInit() {
// Register the |subprocess_| singleton with this Daemon as the signal
// handler.
subprocess_.Init(this); //初始化子进程,用来处理信号
int exit_code = Daemon::OnInit(); //调用父类的OnInit()方法
if (exit_code != EX_OK)
return exit_code;
#if USE_BINDER //USE_BINDER=1
android::BinderWrapper::Create(); //创建BinderWrapper
binder_watcher_.Init();
#endif // USE_BINDER
#if USE_OMAHA //USE_OMAHA=0
// Initialize update engine global state but continue if something fails.
// TODO(deymo): Move the daemon_state_ initialization to a factory method
// avoiding the explicit re-usage of the |bus| instance, shared between
// D-Bus service and D-Bus client calls.
RealSystemState* real_system_state = new RealSystemState();
daemon_state_.reset(real_system_state);
LOG_IF(ERROR, !real_system_state->Initialize())
<< "Failed to initialize system state.";
#else // !USE_OMAHA
DaemonStateAndroid* daemon_state_android = new DaemonStateAndroid();
daemon_state_.reset(daemon_state_android);
LOG_IF(ERROR, !daemon_state_android->Initialize())
<< "Failed to initialize system state.";
#endif // USE_OMAHA
#if USE_BINDER
// Create the Binder Service.
#if USE_OMAHA
binder_service_ = new BinderUpdateEngineBrilloService{real_system_state};
#else // !USE_OMAHA
binder_service_ = new BinderUpdateEngineAndroidService{
daemon_state_android->service_delegate()}; //创建binder_service
#endif // USE_OMAHA
auto binder_wrapper = android::BinderWrapper::Get();
if (!binder_wrapper->RegisterService(binder_service_->ServiceName(), //向ServiceManager注册binder_service
binder_service_)) {
LOG(ERROR) << "Failed to register binder service.";
}
daemon_state_->AddObserver(binder_service_.get()); //将binder_service添加到观察者队列中
#endif // USE_BINDER
#if USE_DBUS //USE_DBUS=0
// Create the DBus service.
dbus_adaptor_.reset(new UpdateEngineAdaptor(real_system_state));
daemon_state_->AddObserver(dbus_adaptor_.get());
dbus_adaptor_->RegisterAsync(base::Bind(&UpdateEngineDaemon::OnDBusRegistered,
base::Unretained(this)));
LOG(INFO) << "Waiting for DBus object to be registered.";
#else // !USE_DBUS
daemon_state_->StartUpdater(); //开始服务的核心流程
#endif // USE_DBUS
return EX_OK;
}
在Oninit()中其实主要就是做了两件事,首先是对Binder进行了初始化,包括创建,注册,添加到观察者队列中。其次就是创建了DaemonStateAndroid,并将其赋给daemon_state_,最后调用daemon_state_->StartUpdater()。
update_engine-整体结构(一)的更多相关文章
- Abot 爬虫分析-整体结构
1. 引言 在Github 上搜索下Web Crawler 有上千个开源的项目,但是C#的仅仅只有168 个,相比于Java 或者Python 确实少的可怜.如果按照Stars 排名.可以看到 排在第 ...
- html规范整体结构
<!DOCTYPE html><html lang="zh"><head> <meta charset="utf-8" ...
- NFC规范学习之一 ---整体结构
1.NFC 采用两个感应线圈进行数据交互,其中至少必须有一个设备产生13.56MHZ的磁场,该场被调制以方便数据传输.通讯中,一个设备处于initiator模式(就是发起通讯)另外一个设备则工作在ta ...
- LIRe 源代码分析 1:整体结构
===================================================== LIRe源代码分析系列文章列表: LIRe 源代码分析 1:整体结构 LIRe 源代码分析 ...
- Media Player Classic - HC 源代码分析 1:整体结构
===================================================== Media Player Classic - HC 源代码分析系列文章列表: Media P ...
- HTML(二)HTML元素(整体结构,块级元素,内联元素,结构元素,交互元素,元素嵌套规则)
HTML整体结构解释 <!DOCTYPE html> // 文件应以"<!DOCTYPE ......>"首行顶格开始,推荐使用"<!DOC ...
- HTML 初识 HTML【 整体结构 文字 图片 表格 超链接】
HTML 超文本标记语言,页面内可以包含图片.链接,甚至音乐.程序等非文字元素. 网页的本质就是超级文本标记语言,万维网是建立在超文本基础之上的.TML 通过标记符号来标记要 ...
- Android4.0 Launcher 源码分析1——Launcher整体结构
1.Launcher整体结构 桌面程序其实并不包含桌面壁纸,桌面壁纸其实是由 WallpaperManagerService来提供,整个桌面其实是叠加在整个桌面壁纸上的另外一个层. 1.1 WorkS ...
- Hyperledger Fabric1.0 整体结构
整体结构 Hyperledger Fabric 在 1.0 中,架构已经解耦为三部分: fabric-peer:主要起到 peer 作用,包括 endorser.committer 两种角色: fab ...
- Spring IOC源代码具体解释之整体结构
Spring ICO具体解释之整体结构 IOC介绍 IOC, spring的核心.贯穿Spring始终.直观的来说.就是由spring来负责控制对象的生命周期和对象间的关系,将对象之间的关系抽象出来. ...
随机推荐
- mac安装破解的Navicat
原文:https://www.jianshu.com/p/f42785e55b6b 原始文档没操作成功,折腾了一下午,后来在如下地址看的简洁版的,突然发现一句重要的话,豁然开朗. 原文链接:https ...
- mybatics 与jpa
mybatics,dao层接口,mapper: public interface UserMapper { @Select("SELECT * FROM T_ROLE WHERE ROLE_ ...
- vmware10.0.1安装redhat linux6.2每次启动vm崩溃问题解决!
最近在学习linux技术,安装了一套redhat linux6.2的环境,里面有软件若干,wmare用的是10.0.1的,最近每次出现登陆界面,输入root登陆后,wm就报错vmui不可恢复错误MEM ...
- vgcreate语法
vgcreate 用于创建LVM卷组 补充说明 vgcreate命令 用于创建LVM卷组.卷组(Volume Group)将多个物理卷组织成一个整体,屏蔽了底层物理卷细节.在卷组上创建逻辑卷时不用考虑 ...
- anaconda3下64位python和32位python共存
查看当前工作平台:conda info 切换64位和32位: set CONDA_FORCE_32BIT=1是切换到32位 set CONDA_FORCE_32BIT= 是切换到64位 注意=号前后不 ...
- vue项目中如何使用less
首先你的vue-cli下载完成 第一步 安装less-loader 依赖 npm install less less-loader --save-dev 直接自动就配置上了,不用手动配置 ...
- 深度学习(pytorch)-1.基于简单神经网络的图片自动分类
这是pytorch官方的一个例子 官方教程地址:http://pytorch.org/tutorials/beginner/blitz/cifar10_tutorial.html#sphx-glr-b ...
- centOS6.0虚拟机ip配置
1.首先使用虚拟机安装好centOS6.0系统 2.虚拟机网络配置:(选择桥接模式) 3. 第一步:首先关闭防火墙 1.将防火服务从启动列表移除 #chkconfig --del iptables # ...
- JS里浮点数的运算
//浮点数加法运算 function FloatAdd(arg1,arg2){ var r1,r2,m; try{r1=arg1.toString().split(".")[1]. ...
- sqlite当天时间的23:59:59
select strftime('%Y-%m-%d %H:%M:%S','now','+1 day','localtime','start of day','-1 seconds')