目 录CONTENT

文章目录

💻工作经历:机载软件Agent - 基于libchrome+mojo

TalentQ
2025-09-05 / 0 评论 / 0 点赞 / 11 阅读 / 0 字

1 任务描述

基于 Chromium 的 “IPC通信框架mojo“ 和 “基础类库libchrome“,开发一个机载软件Agent。该Agent需要实现:

  • 向 OTA Agent 提供补光灯 OTA 的mojo接口,支持补光灯固件在线升级;

  • 向其他 Agent 提供补光灯控制的mojo接口,以适应夜航场景下的各种需求;

  • 与补光灯外设交互,下发指令,做好异常处理;

  • Agent 内部维护状态,周期性上报,并记录;

2 任务分析

主要涉及:

  • mojo接口设计(mojom);

  • agent 内部线程模型设计(base::thread);

  • 状态设计(protobuf);

  • 异常处理逻辑设计;

  • 与补光灯外设交互的api设计(SDK);

由于设计内部信息,具体细节不予详述。

3 mojo & libchrome

团队由于某种原因(新leader有谷歌经历),开始引入谷歌 chromium 项目里的 mojo 和 libchrome。

3.1 mojo

谷歌Chromium项目的Mojo是一个高性能、跨平台的进程间通信(IPC)框架。Mojo 的应用范围相对较窄,几乎只在 Chromium 中用到,因此非 Chromium 开发者不必花太多时间钻研。简单了解其原理即可,我们内部在使用的时候,也仅仅是基于一个框架做开发。

mojo框架概述:

  1. 首先存在一个中心化节点 Service Manager,用于管理服务和请求;

  2. 开发一个Agent提供服务,并向 Service Manager 注册;

  3. 使用方向 Service Manager 查找服务并连接;

框架的核心通信单元是 MessagePipe(双向消息队列)。MessagePipe两端通过Mojo Handle(本质是无符号整数字符串)引用资源,支持跨进程传递。通信全程异步化,通过SimpleWatcher监听管道事件,结合Chromium的TaskRunner在特定线程调度消息,避免阻塞。

我个人并不认同团队引入mojo这一行为,理由如下:

  1. 引入了带有 service manager 的mojo框架,直接引入了一个中心节点,存在一点瘫痪全部服务瘫痪的风险,这在飞机上尤其应当受到重视;

  2. 引入mojo架构是对机端整个架构的重构,没有任何详细的论证,甚至都没有正式的性能分析和测试,只有一个标注了WIP(work in progress)的文档;

  3. 团队里全员没有接触过mojo框架,没有全员会议交流,也没有相关培训或技术交流。

3.2 libchrome

谷歌Chromium项目的libchrome(或称base库)是一个核心的、跨平台的底层基础库,它提供了操作系统抽象层、常用数据结构和多线程编程模型,是构建Chromium及其衍生项目(如Chrome、Android系统组件等)的基石。

其核心设计目标是通过封装Windows、macOS、Linux、Android和iOS等不同操作系统的底层API(如文件I/O、线程、进程、同步原语、内存管理和定时器),为上层代码提供一套统一、稳定且高性能的C++接口,从而极大增强代码的可移植性和可维护性。它本质上扮演了Chromium的“标准运行时库”角色,确保了整个庞大项目能在异构环境中高效、一致地运行。

简言之,libchrome也称为 libbase,是 chromium 项目中独立于其他模块的一个通用工具库。常用的有 base::Thread、base::Timer, base::File。

3.2.1 base::Thread

base::Thread: 一个封装了底层线程和消息循环的类。

创建 base::Thread thread("MyThread") 后,调用 thread.Start() 会启动新线程并运行其消息循环。然后可以使用 thread.task_runner()->PostTask(...) 向该线程投递任务。

每个线程的核心都有一个消息循环(base::MessageLoop)。它管理着一个任务队列,不断地从队列中取出任务并执行(RunLoop)。

在 libchrome 中,直接操作裸线程(如 std::thread)并不推荐。其核心思想是 “任务”(Task) 驱动的并发模型。开发者将工作包装成任务,然后投递到特定的线程或线程池中执行,由框架负责调度和管理线程的生命周期。

3.2.2 base::Timer

base::Timer 及其变体用于安排一个任务在未来的某个时间点执行一次或重复执行。其底层实现依赖于所在线程的 消息循环。

base::OneShotTimer(一次性定时器): 在指定的延迟之后执行一次回调函数。

base::RepeatingTimer(重复定时器): 以固定的时间间隔重复执行回调函数。

base::RepeatingTimer timer;
timer.Start(FROM_HERE, base::Seconds(1),
            base::BindRepeating(&MyClass::OnTimerFired, base::Unretained(this)));
// 每秒调用一次OnTimerFired,直到调用Stop()

3..2.3 base::File

base::File 类是对操作系统底层文件描述符(Linux)或文件句柄(Windows)的一个高级、跨平台的C++封装。它提供了一套统一、安全且易用的API来进行文件I/O操作。

通过RAII避免资源泄漏,通过统一的API消除平台差异,并通过良好的错误处理(许多方法返回 base::File::Error 枚举)使文件操作更加健壮和安全。

{
  base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ);
  // 使用 file 对象...
  // 离开作用域后,文件会自动关闭,无需手动调用 close
}
  • base::File::GetInfo: 获取文件信息(大小、修改时间等,封装在 base::File::Info 结构体中)。

  • base::CreateDirectory: 创建目录。

  • base::PathExists: 检查路径是否存在。

  • base::DeleteFile: 删除文件。

0

评论区