跳到主要内容

运行时总览

ElenixOS 的运行时系统基于 JerryScript 引擎,负责管理脚本的执行、调度和资源分配。本文档将详细介绍 ElenixOS 的运行时机制、调度器、状态管理和 Realm 生命周期。

脚本生命周期​

ElenixOS 中的脚本(应用和表盘)具有完整的生命周期,从加载到执行再到销毁:

1. 加载阶段​

  1. 脚本加载:从文件系统加载应用或表盘的脚本文件
  2. 解析清单:解析 manifest.json 文件,获取应用信息
  3. 创建 Realm:为脚本创建独立的 ECMAScript Realm
  4. 注册 API:向 Realm 中注册系统 API

2. 执行阶段​

  1. 初始化:执行脚本的初始化代码
  2. 运行:执行脚本的主逻辑
  3. 事件处理:处理用户输入和系统事件
  4. UI 更新:更新用户界面

3. 销毁阶段​

  1. 清理资源:释放脚本使用的资源
  2. 销毁 Realm:销毁脚本的 Realm 环境
  3. 释放内存:释放分配的内存

调度与事件流程​

ElenixOS 使用事件驱动的调度机制,处理用户输入、系统事件和脚本执行:

调度器​

调度器负责管理脚本的执行和事件的分发,确保系统的响应性和稳定性:

  1. 事件队列:维护事件队列,按优先级处理事件
  2. 时间管理:管理定时器和定时事件
  3. 资源调度:合理分配系统资源

事件流程​

  1. 事件产生:用户输入、系统状态变化等产生事件
  2. 事件分发:事件系统将事件分发给相应的处理程序
  3. 脚本响应:脚本根据事件执行相应的逻辑
  4. UI 更新:更新用户界面

运行时错误处理​

ElenixOS 采用多层错误处理机制,确保系统的稳定性:

错误捕获​

  1. 脚本错误:捕获脚本执行过程中的错误
  2. 系统错误:捕获系统级错误
  3. 硬件错误:捕获硬件相关错误

错误处理策略​

  1. 错误隔离:确保一个脚本的错误不会影响其他脚本
  2. 错误恢复:在错误发生后尝试恢复系统状态
  3. 错误日志:记录错误信息,便于调试

错误类型​

错误类型描述处理方式
脚本语法错误脚本代码语法不正确停止脚本执行,显示错误信息
脚本运行时错误脚本执行过程中出现错误捕获错误,尝试恢复
系统资源错误系统资源不足释放资源,尝试继续执行
硬件错误硬件操作失败记录错误,尝试降级操作

Realm 生命周期​

Realm 是 ECMAScript 语言规范中的一个概念,用于实现 JavaScript 的多线程执行环境。在 ElenixOS 中,每个脚本运行在独立的 Realm 中:

Realm 创建​

  1. 初始化:初始化 JerryScript 引擎
  2. 创建 Realm:创建新的 Realm 实例
  3. 注册 API:向 Realm 中注册系统 API
  4. 加载脚本:加载脚本代码到 Realm 中

Realm 运行​

  1. 执行脚本:在 Realm 中执行脚本代码
  2. 处理事件:处理脚本产生的事件
  3. 管理状态:管理脚本的运行状态

Realm 销毁​

  1. 停止执行:停止脚本的执行
  2. 清理资源:清理脚本使用的资源
  3. 销毁 Realm:销毁 Realm 实例
  4. 释放内存:释放分配的内存

运行时安全​

ElenixOS 重视运行时安全,采取了以下措施:

  1. 沙箱隔离:每个脚本运行在独立的沙箱中
  2. 权限控制:对脚本的权限进行严格控制
  3. 资源限制:限制脚本的资源使用
  4. 输入验证:验证用户输入,防止恶意输入

SPM 与 SNI 的协作​

SPM 保存程序记录、程序类型、当前状态、脚本包和 SNI 上下文。程序进入挂起时调用 SNI 的资源暂停接口;程序进入停止时先设置 STOPPING,再按 teardown 阶段清理上下文。上层不得直接调用脚本引擎核心绕过 SPM。

定时器、动画与挂起​

挂起期间不执行脚本回调,但原生资源记录仍然存在。恢复时,定时器可执行一次补偿、执行有限次数的遗漏回调,或跳过遗漏周期;动画可从暂停位置继续,或跳到结束状态并触发完成回调。依赖实时周期的脚本应根据系统时间计算状态,不应把定时器回调次数当作真实经过时间。

Teardown 阶段​

停止路径要区分“禁止回调”和“释放资源”:

  1. 将程序设置为 STOPPING;
  2. 禁止新的 SPM 回调并保存错误上下文;
  3. 解除 JS 对象与原生地址的关联;
  4. 清理 JS 引用、事件回调、定时器和动画;
  5. 清理 Activity/View 及其 LVGL 事件;
  6. 停止引擎并销毁 SNI 上下文;
  7. 将程序标记为 TERMINATED。

任何阶段失败都不能回到 ACTIVE,否则会产生悬挂回调或重复释放。