ServerExpansion 是 ZerOS 的服务扩展模块,负责从 D/server 自识别并加载 server-xxx.js 服务模块,提供 start/stop 生命周期管理。合规模块需包含 __init__、__start__、__stop__、__status__、__info__ 五个方法;加载时不调用任何方法,仅当用户或系统明确启用某服务时依次调用 init、start,再次启动不会调用 init。
权限管控:服务启停与查询 API 由进程管理器以 Server.* 形式暴露,所需权限为 SERVER_SERVICE_MANAGE(权限等级最高,DANGEROUS)。程序应通过 kernelAPI.call('Server.xxx', args) 调用并声明该权限;禁止直接调用 ServerExpansion 的 start/stop/listServices/loadAll/status/info/isInited/isStarted,否则会因内核令牌校验失败而抛错。
Disk / NodeTree - 文件系统(用于列出 D/server 下 server-*.js)ProcessManager - 用于 convertVirtualPathToUrl 将 D/server 路径转为可加载的脚本 URL,并暴露 Server.* API 与权限校验D/server(虚拟路径),项目内对应 system/service/DISK/D/server/server-<id>.js,如 server-myservice.js,id 为 myservicewindow.__ZerOS_ServerExpansion_Register__(api) 上报导出对象,且 api 必须包含上述五个方法且均为函数详见 服务模块编写指南。
服务扩展在 BootLoader 中按依赖顺序加载(依赖 kernel/filesystem/init.js 与 kernel/process/processManager.js)。加载后立即执行 ServerExpansion.init()(异步):
waitForServerPathReady)server-*.js(discoverAndLoad)__init__、__start__)该过程与「是否打开系统服务管理程序」无关,服务列表由内核/扩展自动加载。完成状态保存在 ServerExpansion._ready(Promise)。
所有依赖服务列表的 API(start、stop、listServices、loadAll、status、info、isInited、isStarted)在访问内部 _modules 前会先等待 _ready,因此程序在启动后立即调用 Server.start('processmemory') 等不会出现「未知服务」——会等待服务列表加载完成后再执行。
window.ServerExpansion 或 globalThis.ServerExpansionPOOL.__GET__("KERNEL_GLOBAL_POOL", "ServerExpansion")注意:程序(如系统服务管理、内存编辑器、终端 service 命令等)不得直接调用上述对象上的 start/stop/listServices/loadAll/status/info/isInited/isStarted,否则会抛错「ServerExpansion 仅允许通过进程管理器 kernelAPI(Server.*)调用」。应使用进程管理器注入的 kernelAPI.call('Server.xxx', args),并在 __info__ 中声明 PermissionManager.PERMISSION.SERVER_SERVICE_MANAGE。
以下 API 由进程管理器以 kernelAPI.call(apiName, args) 形式提供,需 SERVER_SERVICE_MANAGE 权限:
| API 名称 | 说明 | 参数 | 返回值 |
|----------|------|------|--------|
| Server.start | 启动服务(会先等待服务列表自动加载完成) | [id] | Promise<boolean> |
| Server.stop | 停止服务(会先等待服务列表自动加载完成) | [id] | Promise<boolean> |
| Server.listServices | 已加载服务 id 列表(会先等待服务列表自动加载完成) | [] | Promise<string[]> |
| Server.loadAll | 重新扫描 D/server 并加载服务(会先等待 init 完成) | [] | Promise<string[]> |
| Server.status | 查询服务状态 | [id] | Promise<*> |
| Server.info | 查询服务信息 | [id] | Promise<*> |
| Server.isInited | 是否已初始化 | [id] | Promise<boolean> |
| Server.isStarted | 是否已启动 | [id] | Promise<boolean> |
| Server.listConfig | 列出服务可配置项(调用 __list__,供系统服务程序渲染) | [id] | Promise<Array> |
| Server.setConfig | 设置并持久化配置(调用 __set__,服务自行保存) | [id, config] | Promise<void> |
服务若实现 __set__ 则必须同时实现 __list__;系统服务程序通过 listConfig 获取可配置项、渲染输入框/开关,保存时调用 setConfig。
示例(在程序的 __init__ 中保存 initArgs.kernelAPI 后使用):
await this._kernelAPI.call('Server.start', ['processmemory']);
const ids = await this._kernelAPI.call('Server.listServices', []);
await this._kernelAPI.call('Server.stop', ['processmemory']);
以下方法在传入内核令牌时由进程管理器内部调用;程序直接调用将抛错。
获取已加载的合规服务 id 列表。会先等待 _ready(init 完成),再返回 _modules 的 key 列表。
参数:token - 内核令牌(由 ProcessManager 传入)
返回值:Promise<string[]> - 服务 id 数组
示例:
const ids = await ServerExpansion.listServices(token); // e.g. ['myservice', 'processmemory']
重新扫描 D/server 并加载所有合规的 server-*.js(不调用任何服务方法)。会先等待 _ready(init 完成)再执行。
参数:token - 内核令牌(由 ProcessManager 传入)
返回值:Promise<string[]> - 本次加载后所有合规服务 id 列表
启动服务。会先等待 _ready(服务列表自动加载完成),再查找并启动。首次启动会先调用该服务的 __init__ 再调用 __start__;之后再次启动仅调用 __start__。
参数:
id (string): 服务 id,对应文件名 server-<id>.js 中的 <id>token: 内核令牌(由 ProcessManager 传入)返回值:Promise<boolean> - 是否成功
示例:
await ServerExpansion.start('myservice');
停止服务。会先等待 _ready,再调用该服务的 __stop__。
参数:
id (string): 服务 idtoken: 内核令牌(由 ProcessManager 传入)返回值:Promise<boolean> - 是否成功
查询服务状态。会先等待 _ready,再调用该服务的 __status__ 并返回其返回值。
参数:
id (string): 服务 idtoken: 内核令牌(由 ProcessManager 传入)返回值:Promise<*> - __status__ 的返回值,未加载或异常时为 undefined
获取服务信息。会先等待 _ready,再调用该服务的 __info__ 并返回其返回值。
参数:
id (string): 服务 idtoken: 内核令牌(由 ProcessManager 传入)返回值:Promise<*> - __info__ 的返回值,未加载或异常时为 undefined
判断服务是否已初始化(是否已调用过 __init__)。会先等待 _ready。
参数:
id (string): 服务 idtoken: 内核令牌(由 ProcessManager 传入)返回值:Promise<boolean>
判断服务是否已启动(已调用 __start__ 且未调用 __stop__)。会先等待 _ready。
参数:
id (string): 服务 idtoken: 内核令牌(由 ProcessManager 传入)返回值:Promise<boolean>
初始化扩展:等待 D/server 就绪后扫描并加载 D/server 下所有合规服务,不调用任何服务方法。脚本加载时自动执行一次(ServerExpansion._ready = ServerExpansion.init()),程序无需再依赖「先打开服务管理」才可用服务。
返回值:Promise<string[]> - 已加载的合规服务 id 列表
初始化完成的 Promise。所有 start/stop/listServices/loadAll/status/info/isInited/isStarted 内部会先 Promise.resolve(_ready) 再访问 _modules,保证不会出现「未知服务」因列表未加载而报错。
| 操作 | 行为 |
|------|------|
| 系统启动 / 扩展加载 | 自动执行 init(),扫描 D/server 并加载所有 server-*.js,不调用任何服务方法;结果保存在 _ready |
| 任意 start/stop/listServices/… 调用 | 先等待 _ready,再访问 _modules 并执行对应逻辑 |
| 第一次 start(id) | 先 __init__(),再 __start__() |
| 后续 start(id) | 仅 __start__() |
| stop(id) | 调用 __stop__() |
| status(id) / info(id) | 调用 __status__() / __info__(),无副作用 |
以下程序已适配 Server.* 权限管控,通过 kernelAPI.call('Server.xxx', ...) 访问服务,并声明 SERVER_SERVICE_MANAGE 权限:
server-notice.js):系统公告通知获取,每 3 分钟拉取公告 API,按等级弹通知或打日志。详见 通知服务(ServerNotice)。