本文档详细描述 ZerOS 虚拟操作系统的核心流程,包括系统启动、程序启动、程序结束、程序与内核交互以及权限控制等关键流程。
查看 API 文档索引 获取所有 API 的完整列表。
┌─────────────────────────────────────────────────────────────┐
│ 系统启动流程 (BootLoader) │
└─────────────────────────────────────────────────────────────┘
HTML 加载阶段
├─ 加载 KernelLogger (日志系统)
├─ 加载 DependencyConfig (依赖管理器)
└─ 加载 POOL (对象池)
BootLoader 初始化
├─ 等待核心模块就绪
│ ├─ 验证 KernelLogger
│ ├─ 验证 DependencyConfig
│ └─ 验证 POOL
│
├─ 初始化对象池
│ ├─ 创建 KERNEL_GLOBAL_POOL
│ ├─ 设置系统加载标志位
│ ├─ 注册 Dependency 实例
│ └─ 设置工作空间路径
│
└─ 按依赖顺序加载模块
├─ 第一层:枚举管理器
│ └─ enumManager.js
│
├─ 第二层:类型枚举
│ ├─ logLevel.js
│ ├─ addressType.js
│ └─ fileType.js
│
├─ 第三层:文件系统
│ ├─ fileFramework.js
│ ├─ disk.js
│ └─ nodeTree.js
│
├─ 第四层:内存管理
│ ├─ heap.js
│ ├─ shed.js
│ ├─ memoryManager.js
│ ├─ kernelMemory.js
│ └─ memoryUtils.js
│
├─ 第五层:进程管理
│ ├─ applicationAssets.js
│ ├─ applicationAssetManager.js
│ ├─ programCategories.js
│ └─ processManager.js
│
├─ 第六层:事件系统
│ └─ eventManager.js
│
├─ 第七层:GUI 系统
│ ├─ guiManager.js
│ ├─ contextMenuManager.js
│ ├─ taskbarManager.js
│ ├─ notificationManager.js
│ └─ desktop.js
│
├─ 第八层:文件系统初始化
│ └─ init.js
│
├─ 第九层:网络与动态模块
│ ├─ networkManager.js
│ ├─ dynamicManager.js
│ └─ SystemInformation.js
│
├─ 第十层:本地存储
│ └─ LStorage.js
│
├─ 第十一层:主题与用户控制
│ ├─ themeManager.js
│ ├─ userControl.js
│ └─ lockscreen.js
│
└─ 第十二层:权限与驱动
├─ permissionManager.js
├─ animateManager.js
├─ multithreadingDrive.js
├─ dragDrive.js
├─ geographyDrive.js
├─ cacheDrive.js
├─ cryptDrive.js
├─ speechDrive.js
├─ exceptionHandler.js (异常处理管理器)
└─ safeModeManager.js (安全模式管理器)
内核初始化
├─ 检查内核异常标志
│ ├─ 初始化 ExceptionHandler
│ ├─ 调用 ExceptionHandler.canNormalBoot()
│ │ ├─ 如果检测到内核异常标志
│ │ │ ├─ 设置安全模式标志
│ │ │ ├─ 显示安全模式界面
│ │ │ ├─ 显示BIOS加载动画
│ │ │ └─ 中断启动流程(不继续正常启动)
│ │ └─ 如果未检测到异常
│ │ └─ 继续正常启动流程
│ └─ 如果检查失败,继续正常启动(避免因检查错误导致系统无法启动)
│
├─ 初始化事件管理器
├─ 初始化事件管理器
│ └─ EventManager.init()
│
├─ 初始化进程管理器
│ ├─ ProcessManager.init()
│ ├─ 注册 Exploit 程序 (PID: 10000)
│ └─ 标记为系统进程
│
├─ 验证文件系统
│ ├─ 等待 Disk.canUsed = true
│ └─ 检查磁盘分区状态
│
└─ 验证核心模块
├─ 检查所有必需模块已加载
├─ 验证 Exploit 程序已注册
├─ 验证内核内存就绪
└─ 生成初始化报告
内核自检
├─ 核心模块检查
│ ├─ KernelLogger
│ ├─ DependencyConfig
│ └─ POOL
│
├─ 枚举管理器检查
│ ├─ EnumManager
│ ├─ FileType
│ ├─ LogLevel
│ └─ AddressType
│
├─ 文件系统检查
│ ├─ Disk
│ ├─ NodeTreeCollection
│ ├─ FileFramework
│ └─ LStorage
│
├─ 内存管理检查
│ ├─ MemoryManager
│ ├─ Heap
│ ├─ Shed
│ └─ KernelMemory
│
├─ 进程管理检查
│ ├─ ProcessManager
│ └─ ApplicationAssetManager
│
├─ GUI 管理检查
│ ├─ GUIManager
│ ├─ ThemeManager
│ ├─ DesktopManager
│ ├─ TaskbarManager
│ ├─ NotificationManager
│ ├─ PermissionManager
│ ├─ ContextMenuManager
│ └─ EventManager
│
├─ 其他模块检查
│ ├─ NetworkManager
│ ├─ SystemInformation
│ ├─ DynamicManager
│ ├─ MultithreadingDrive
│ ├─ DragDrive
│ ├─ GeographyDrive
│ ├─ CacheDrive
│ └─ CryptDrive
│
└─ 浏览器环境检查
├─ localStorage
├─ document.body
└─ window 对象
显示锁屏界面
├─ 初始化 LockScreen
│ ├─ 创建锁屏容器
│ ├─ 设置背景(随机或自定义)
│ │ ├─ 检查是否启用随机背景
│ │ │ ├─ 启用:从默认背景库随机选择
│ │ │ └─ 禁用:使用用户自定义背景
│ │ └─ 加载背景图片
│ ├─ 创建登录界面
│ │ ├─ 显示用户头像
│ │ ├─ 显示用户名
│ │ ├─ 创建密码输入框(如果用户有密码)
│ │ └─ 创建登录按钮
│ ├─ 设置键盘监听
│ │ ├─ Enter 键登录
│ │ └─ Ctrl+L 锁定屏幕
│ ├─ 初始化时间组件
│ │ ├─ 显示当前时间
│ │ └─ 每秒更新
│ └─ 初始化每日一言组件
│ ├─ 从缓存读取
│ └─ 如果缓存不存在则预加载
│
└─ 等待用户登录
├─ 用户选择用户(点击头像切换)
│ └─ 显示所有可用用户列表
│
├─ 用户输入密码(如果用户有密码)
│ └─ 密码输入框显示/隐藏
│
├─ 用户点击登录或按 Enter
│ └─ 触发登录流程
│
└─ 验证用户凭据
├─ 调用 UserControl.login(username, password)
│ ├─ 检查用户是否存在
│ ├─ 验证密码(MD5 加密)
│ └─ 更新最后登录时间
│
├─ 登录成功
│ ├─ 显示"登录成功"消息
│ ├─ 删除系统加载标志位
│ └─ 进入系统
│
└─ 登录失败
├─ 清空密码输入框
├─ 显示错误动画
└─ 重新聚焦密码输入框
进入系统
├─ 隐藏锁屏界面
│ ├─ 淡出动画(500ms)
│ └─ 移除锁屏容器
│
├─ 显示桌面 (kernel-content)
│ ├─ 设置 display: flex
│ ├─ 淡入动画(500ms)
│ └─ 显示 GUI 容器和任务栏
│
├─ 更新开始菜单用户信息
│ └─ TaskbarManager._updateStartMenuUserInfo()
│
├─ 初始化任务栏
│ ├─ 延迟 500ms 初始化
│ ├─ 加载任务栏图标
│ ├─ 加载固定程序
│ └─ 显示系统托盘
│
├─ 初始化通知管理器
│ ├─ 延迟 1000ms 初始化(等待任务栏就绪)
│ ├─ 设置通知容器位置
│ └─ 加载历史通知
│
└─ 启动自动启动程序
├─ 从 ApplicationAssetManager 获取自动启动列表
│ └─ 筛选 autoStart: true 的程序
│
├─ 按优先级排序
│ └─ priority 值越小优先级越高
│
└─ 依次启动程序
├─ 调用 ProcessManager.startProgram()
├─ 等待程序启动完成
└─ 继续下一个程序
┌─────────────────────────────────────────────────────────────┐
│ 程序启动流程 (ProcessManager) │
└─────────────────────────────────────────────────────────────┘
接收启动请求
└─ ProcessManager.startProgram(programName, initArgs)
验证程序存在
├─ 从 ApplicationAssetManager 获取程序信息
│ ├─ 获取脚本路径
│ ├─ 获取样式表列表
│ ├─ 获取资源文件列表
│ └─ 获取程序元数据
│
└─ 如果不存在,抛出错误
权限检查
├─ 检查是否为管理员专用程序
│ ├─ 如果是管理员程序
│ │ ├─ 检查当前用户是否为管理员
│ │ │ ├─ 是:继续启动
│ │ │ └─ 否:显示错误通知并拒绝启动
│ │ └─ 管理员程序列表:
│ │ ├─ regedit
│ │ ├─ kernelchecker
│ │ ├─ authenticator
│ │ └─ permissioncontrol
│ └─ 如果不是管理员程序:继续启动
多实例检查
├─ 检查程序是否支持多开
│ ├─ 从元数据获取 allowMultipleInstances
│ │
│ ├─ 如果不支持多开
│ │ ├─ 检查程序是否已在运行
│ │ │ ├─ 如果已运行
│ │ │ │ ├─ 聚焦现有窗口
│ │ │ │ └─ 返回现有 PID
│ │ │ └─ 如果未运行:继续启动
│ │ └─ 如果支持多开:继续启动
分配 PID
├─ 调用 _allocatePid()
│ ├─ 从 10001 开始分配(10000 为 Exploit 程序)
│ ├─ 检查 PID 是否已被使用
│ └─ 返回新的 PID
│
└─ 创建进程信息对象
├─ pid
├─ programName
├─ programNameUpper
├─ scriptPath
├─ styles
├─ assets
├─ metadata
├─ status: 'loading'
├─ startTime
├─ memoryRefs: Map
├─ domElements: Set
├─ isCLI: false
└─ requestedModules: Set
注册进程
├─ 添加到进程表 (PROCESS_TABLE)
├─ 保存到 KernelMemory
├─ 清空进程表缓存
└─ 注册到 MemoryManager
加载程序资源
├─ 加载样式表
│ ├─ 遍历 styles 数组
│ ├─ 创建 <link> 标签
│ └─ 等待加载完成
│
├─ 加载资源文件
│ ├─ 遍历 assets 数组
│ ├─ 根据类型加载(图片、字体等)
│ └─ 等待加载完成
│
└─ 加载程序脚本
├─ 创建 <script> 标签
├─ 设置 src 为 scriptPath
├─ 添加到 document.head
└─ 等待脚本加载完成
等待程序对象出现
├─ 检查全局对象
│ ├─ window[programNameUpper]
│ ├─ globalThis[programNameUpper]
│ └─ POOL["APPLICATION_POOL"][programNameUpper]
│
├─ 轮询检查(最多 5 秒)
│ ├─ 每 50ms 检查一次
│ └─ 最多检查 100 次
│
└─ 如果超时未找到:抛出错误
检查程序类型
├─ 调用程序的 __info__() 方法
│ ├─ 获取程序类型 (type: 'CLI' | 'GUI')
│ └─ 获取程序元数据
│
└─ 根据类型处理
├─ CLI 程序
│ ├─ 标记 isCLI = true
│ │ └─ processInfo.isCLI = true
│ │
│ ├─ 检查是否有终端实例
│ │ ├─ 如果有(initArgs.terminal 存在)
│ │ │ ├─ 使用现有终端实例
│ │ │ ├─ 标记 launchedFromTerminal = true
│ │ │ └─ 记录日志:从终端内启动
│ │ │
│ │ └─ 如果没有(从 GUI 启动)
│ │ ├─ 创建独立终端实例
│ │ │ ├─ 调用 ProcessManager.startProgram('terminal', {...})
│ │ │ ├─ 设置 autoStart = true
│ │ │ ├─ 设置 forCLI = true(标记为 CLI 程序专用终端)
│ │ │ ├─ 设置 cliProgramName = programName
│ │ │ ├─ 设置 cliProgramPid = pid
│ │ │ ├─ 设置 disableTabs = true(禁用标签页功能)
│ │ │ └─ 获取终端 PID (terminalPid)
│ │ │
│ │ ├─ 关联终端 PID
│ │ │ └─ processInfo.terminalPid = terminalPid
│ │ │
│ │ ├─ 标记终端实例
│ │ │ └─ 终端进程的 isCLITerminal = true
│ │ │
│ │ └─ 等待终端就绪(最多 3 秒)
│ │ ├─ 检查终端进程状态
│ │ │ └─ status === 'running'
│ │ │
│ │ ├─ 检查终端 API 是否可用
│ │ │ ├─ 从 POOL 获取 TerminalAPI
│ │ │ ├─ 调用 getActiveTerminal()
│ │ │ └─ 获取终端实例
│ │ │
│ │ └─ 如果超时:记录警告但继续
│ │
│ └─ 保存终端实例
│ └─ 用于传递给 __init__ 方法
│
└─ GUI 程序
└─ 继续初始化(无需终端处理)
调用程序初始化
├─ 记录启动前的 DOM 快照
│ └─ _getDOMSnapshot()(用于后续跟踪程序创建的元素)
│
├─ 设置进程状态为 'starting'
│ ├─ processInfo.status = 'starting'
│ ├─ 保存进程表
│ └─ 允许在 __init__ 中调用 ProcessManager API
│
├─ 获取程序类对象
│ └─ window[programNameUpper] 或 globalThis[programNameUpper]
│
├─ 构建标准化初始化参数
│ └─ standardizedInitArgs = {
│ ├─ pid: pid
│ ├─ args: initArgs.args || []
│ ├─ env: initArgs.env || {}
│ ├─ cwd: initArgs.cwd || 'C:'
│ ├─ terminal: terminalInstance(CLI 程序)
│ ├─ metadata: initArgs.metadata || {}
│ └─ ...initArgs(保留其他自定义参数)
│ }
│
├─ 调用 __init__(pid, standardizedInitArgs)
│ ├─ 传递 PID
│ ├─ 传递标准化初始化参数
│ └─ 等待初始化完成(异步)
│
├─ 初始化成功
│ ├─ 设置 status = 'running'
│ ├─ 保存进程表
│ ├─ 清除进程表缓存
│ ├─ 标记程序创建的元素
│ │ └─ _markProgramElements(pid, domSnapshotBefore)
│ │ └─ 为新创建的 DOM 元素设置 data-pid 属性
│ ├─ 延迟更新任务栏(100ms)
│ └─ 记录日志:初始化完成
│
└─ 如果初始化失败
├─ 设置 status = 'exited'
├─ 设置 exitTime = Date.now()
├─ 保存进程表
├─ 清除进程表缓存
├─ 从进程表删除进程信息
├─ 释放内存
└─ 抛出错误
注册程序权限(在 __init__ 之前)
├─ 获取程序信息
│ └─ 调用程序的 __info__() 方法
│
├─ 提取权限列表
│ └─ programInfo.permissions
│
└─ 调用 PermissionManager.registerProgramPermissions(pid, programInfo, options)
├─ 确保权限管理器已初始化
│ └─ await PermissionManager._ensureInitialized()
│
├─ 验证权限有效性
│ └─ 检查权限是否在 PERMISSION 枚举中
│
├─ 检查是否为管理员专用程序
│ └─ options.isAdminProgram === true
│
├─ 遍历权限列表
│ └─ 对每个权限进行处理
│
├─ 根据权限级别处理
│ ├─ NORMAL(普通权限)
│ │ ├─ 自动授予
│ │ ├─ 添加到权限表 (_permissions)
│ │ ├─ 记录到审计日志
│ │ └─ 增加 granted 计数
│ │
│ ├─ SPECIAL(特殊权限)
│ │ ├─ 检查是否已授予(从本地存储读取)
│ │ │ ├─ 已授予:添加到权限表
│ │ │ └─ 未授予:等待首次使用时请求
│ │ ├─ 记录到审计日志
│ │ └─ 增加 checked 计数
│ │
│ └─ DANGEROUS(危险权限)
│ ├─ 如果是管理员专用程序
│ │ ├─ 自动授予(管理员专用程序享有特权)
│ │ ├─ 添加到权限表
│ │ └─ 记录到审计日志(标记为管理员程序)
│ │
│ └─ 如果不是管理员专用程序
│ ├─ 检查是否已授予(从本地存储读取)
│ │ ├─ 已授予:添加到权限表
│ │ └─ 未授予:等待首次使用时请求
│ └─ 记录到审计日志
│
├─ 保存权限到本地存储
│ └─ LStorage.setSystemStorage('permissionManager.permissions', ...)
│
└─ 记录注册结果
├─ 记录授予的权限数量
└─ 记录危险权限数量(如果是管理员程序)
标记 DOM 元素
├─ 创建 MutationObserver(可选)
│ └─ 监听程序创建的 DOM 元素
│
├─ 标记已存在的 DOM 元素
│ └─ 设置 data-pid 属性
│
└─ 添加到 domElements Set
更新进程状态
├─ 设置 status = 'running'
├─ 保存进程表
└─ 更新任务栏
完成启动
└─ 返回 PID
┌─────────────────────────────────────────────────────────────┐
│ 程序结束流程 (ProcessManager) │
└─────────────────────────────────────────────────────────────┘
接收终止请求
└─ ProcessManager.killProgram(pid, force)
验证进程存在
├─ 从进程表获取进程信息
│ └─ PROCESS_TABLE.get(pid)
│
└─ 如果不存在:返回 false
检查进程状态
├─ 如果状态为 'exited'
│ ├─ 检查是否还有窗口
│ │ ├─ 如果有窗口:继续清理(force = true)
│ │ └─ 如果没有窗口:返回 false
│ └─ 如果 force = false:返回 false
调用程序退出方法
├─ 设置状态为 'exiting'(防止递归调用)
│
├─ 获取程序类对象
│ └─ window[programNameUpper] 或 globalThis[programNameUpper]
│
└─ 调用 __exit__(pid, force)
├─ 传递 PID
├─ 传递 force 标志
└─ 等待退出完成
├─ 如果失败且 force = false:抛出错误
└─ 如果失败且 force = true:继续清理
清理关联资源
├─ CLI 程序处理
│ ├─ 如果创建了独立终端
│ │ └─ 关闭关联终端 (killProgram(terminalPid))
│ │
│ └─ 如果是 CLI 程序专用终端
│ └─ 关闭关联的 CLI 程序
│
├─ GUI 元素清理
│ ├─ 获取程序的所有窗口
│ │ └─ GUIManager.getWindowsByPid(pid)
│ │
│ ├─ 注销所有窗口
│ │ └─ GUIManager.unregisterWindow(windowId)
│ │
│ └─ 清理其他 GUI 元素
│ └─ _cleanupGUI(pid)
│
├─ 上下文菜单清理
│ └─ ContextMenuManager.unregisterContextMenu(pid)
│
├─ 桌面组件清理
│ └─ DesktopManager.cleanupProgramComponents(pid)
│
├─ 拖拽会话清理
│ └─ DragDrive.cleanupProcessDrags(pid)
│
├─ 通知清理
│ └─ NotificationManager.cleanupProgramNotifications(pid)
│ ├─ 清理依赖类型通知
│ └─ 保留快照类型通知(触发关闭回调)
│
├─ 事件处理器清理
│ └─ EventManager.unregisterAllHandlersForPid(pid)
│
├─ 权限清理
│ └─ PermissionManager.clearProgramPermissions(pid)
│
├─ 多线程资源清理
│ └─ MultithreadingDrive.cleanupProcessThreads(pid)
│
└─ 语音识别会话清理
└─ SpeechDrive.cleanupProcess(pid)
释放内存
├─ 释放进程内存
│ └─ MemoryManager.freeMemory(pid)
│
├─ 清理内存引用
│ └─ processInfo.memoryRefs.clear()
│
└─ 清理动态模块
└─ 清理 requestedModules Set
清理 DOM 元素
├─ 清理 DOM 元素集合
│ └─ processInfo.domElements.clear()
│
└─ 停止 DOM 观察器
└─ mutationObserver.disconnect()
更新进程状态
├─ 设置 status = 'exited'
├─ 设置 exitTime = Date.now()
├─ 保存进程表到 KernelMemory
└─ 清除 PID 缓存
通知任务栏
└─ TaskbarManager.update()
└─ 延迟 50ms 更新(确保状态已保存)
完成终止
└─ 返回 true
强制终止处理
└─ 如果发生错误且 force = true
├─ 跳过 __exit__ 调用
├─ 直接清理所有资源
├─ 更新进程状态
└─ 返回 true
┌─────────────────────────────────────────────────────────────┐
│ 程序与内核交互流程 (callKernelAPI) │
└─────────────────────────────────────────────────────────────┘
程序调用内核 API
└─ ProcessManager.callKernelAPI(pid, apiName, args)
验证进程
├─ 检查进程是否存在
│ └─ PROCESS_TABLE.get(pid)
│
└─ 如果不存在:抛出错误
检查是否为 Exploit 程序
├─ 检查 processInfo.isExploit
│ ├─ 如果是 Exploit 程序(PID = 10000)
│ │ ├─ 跳过权限检查
│ │ ├─ 直接调用 _executeKernelAPI()
│ │ └─ 返回结果
│ │
│ └─ 如果不是 Exploit 程序:继续权限检查
│
└─ 检查进程状态
└─ 如果状态不是 'running':抛出错误
权限检查
├─ 解析 API 名称
│ └─ 格式:'ModuleName.methodName'
│
├─ 获取所需权限
│ └─ 根据 API 名称映射到权限
│
└─ 调用 PermissionManager.checkAndRequestPermission()
├─ 检查是否已有权限
│ ├─ 检查权限缓存(5 秒 TTL)
│ └─ 检查权限表
│
├─ 如果没有权限
│ ├─ 检查权限级别
│ │ ├─ NORMAL: 自动授予
│ │ ├─ SPECIAL: 弹出权限请求对话框
│ │ └─ DANGEROUS: 弹出权限请求对话框(需要管理员)
│ │
│ ├─ 用户选择
│ │ ├─ 允许:授予权限并继续
│ │ └─ 拒绝:抛出权限错误
│ │
│ └─ 保存权限决策
│ └─ 持久化到本地存储
│
└─ 如果有权限:继续执行
路由到对应模块
├─ 调用 _executeKernelAPI(apiName, args, pid)
│
├─ 解析 API 名称
│ └─ 格式:'ModuleName.methodName'
│ ├─ 示例:'Cache.get' → 模块: 'Cache', 方法: 'get'
│ └─ 示例:'Disk.read' → 模块: 'Disk', 方法: 'read'
│
├─ 获取模块实例
│ ├─ 从 POOL 获取(优先)
│ │ └─ POOL.__GET__("KERNEL_GLOBAL_POOL", moduleName)
│ │
│ └─ 或从全局对象获取(降级)
│ ├─ window[moduleName]
│ └─ globalThis[moduleName]
│
└─ 如果模块不存在:抛出错误
调用模块方法
├─ 解析方法名称
│ └─ 从 apiName 提取方法名
│
├─ 检查方法是否存在
│ └─ typeof module[methodName] === 'function'
│
└─ 调用方法
├─ 传递参数
│ └─ args 数组展开为方法参数
│
├─ 传递 PID(如果需要)
│ └─ 某些 API 需要 PID 进行权限验证或资源管理
│
├─ 处理返回值
│ ├─ 同步方法:直接返回结果
│ └─ 异步方法:返回 Promise,等待结果
│
└─ 错误处理
├─ 捕获方法执行错误
└─ 包装为统一的错误格式
记录程序行为
└─ ProcessManager._logProgramAction()
├─ 记录 API 调用
├─ 记录参数
└─ 记录时间戳
返回结果
└─ 返回 API 调用结果
常见内核 API 调用示例
├─ 文件系统操作
│ ├─ callKernelAPI(pid, 'Disk.read', [path])
│ ├─ callKernelAPI(pid, 'Disk.write', [path, data])
│ └─ callKernelAPI(pid, 'Disk.list', [path])
│
├─ 内存操作
│ ├─ callKernelAPI(pid, 'MemoryManager.allocateMemory', [heapSize, shedSize])
│ └─ callKernelAPI(pid, 'MemoryManager.freeMemory', [pid])
│
├─ GUI 操作
│ ├─ callKernelAPI(pid, 'GUIManager.registerWindow', [pid, window, options])
│ └─ callKernelAPI(pid, 'GUIManager.unregisterWindow', [windowId])
│
├─ 存储操作
│ ├─ callKernelAPI(pid, 'LStorage.setSystemStorage', [key, value])
│ └─ callKernelAPI(pid, 'LStorage.getSystemStorage', [key])
│
├─ 缓存操作
│ ├─ callKernelAPI(pid, 'Cache.set', [key, value, options])
│ ├─ callKernelAPI(pid, 'Cache.get', [key, defaultValue, options])
│ └─ callKernelAPI(pid, 'Cache.delete', [key, options])
│
└─ 网络操作
├─ callKernelAPI(pid, 'NetworkManager.request', [url, options])
└─ callKernelAPI(pid, 'NetworkManager.getConnectionInfo', [])
┌─────────────────────────────────────────────────────────────┐
│ 权限控制流程 (PermissionManager) │
└─────────────────────────────────────────────────────────────┘
权限声明阶段
└─ 程序在 __info__() 中声明权限
└─ 返回 { permissions: [...] }
权限注册阶段
└─ ProcessManager 调用 PermissionManager.registerProgramPermissions(pid, programInfo, options)
├─ 确保权限管理器已初始化
│ └─ await PermissionManager._ensureInitialized()
│
├─ 提取权限列表
│ ├─ 从 programInfo.permissions 获取
│ └─ 如果为空:记录日志并返回
│
├─ 检查是否为管理员专用程序
│ └─ options.isAdminProgram === true
│ └─ 管理员专用程序享有特权,自动授予危险权限
│
├─ 遍历权限列表
│ └─ 对每个权限进行处理
│
├─ 检查权限有效性
│ └─ 验证权限名称是否在 PERMISSION 枚举中
│ └─ 如果无效:记录警告并跳过
│
├─ 根据权限级别处理
│ ├─ NORMAL(普通权限)
│ │ ├─ 自动授予
│ │ ├─ 添加到权限表 (_permissions.get(pid).add(permission))
│ │ ├─ 记录到审计日志
│ │ └─ 增加 granted 计数
│ │
│ ├─ SPECIAL(特殊权限)
│ │ ├─ 检查是否已授予(从本地存储读取)
│ │ │ ├─ 已授予:添加到权限表
│ │ │ └─ 未授予:等待首次使用时请求(不添加到权限表)
│ │ ├─ 记录到审计日志
│ │ └─ 增加 checked 计数
│ │
│ └─ DANGEROUS(危险权限)
│ ├─ 如果是管理员专用程序
│ │ ├─ 自动授予(管理员专用程序享有特权)
│ │ ├─ 添加到权限表
│ │ ├─ 记录到审计日志(标记为管理员程序)
│ │ └─ 增加 dangerousGranted 计数
│ │
│ └─ 如果不是管理员专用程序
│ ├─ 检查是否已授予(从本地存储读取)
│ │ ├─ 已授予:添加到权限表
│ │ └─ 未授予:等待首次使用时请求(不添加到权限表)
│ └─ 记录到审计日志
│
├─ 保存权限到本地存储
│ └─ LStorage.setSystemStorage('permissionManager.permissions', ...)
│ └─ 序列化权限表(Map<pid, Set<permission>> → Object)
│
└─ 记录注册结果
├─ 记录授予的权限数量
├─ 记录危险权限数量(如果是管理员程序)
└─ 记录到内核日志
权限检查阶段
└─ 程序调用内核 API 时触发权限检查
检查流程
├─ PermissionManager.hasPermission(pid, permission)
│ ├─ 检查是否为 Exploit 程序
│ │ ├─ 如果是 PID = 10000:直接返回 true
│ │ └─ 如果不是:继续检查
│ │
│ ├─ 检查权限缓存
│ │ ├─ 查找缓存键:`${pid}_${permission}`
│ │ ├─ 检查缓存是否过期(5 秒 TTL)
│ │ │ ├─ 未过期:返回缓存结果
│ │ │ └─ 已过期:继续检查
│ │ └─ 如果缓存不存在:继续检查
│ │
│ ├─ 检查权限表
│ │ └─ _permissions.get(pid)?.has(permission)
│ │
│ └─ 返回检查结果
│
└─ PermissionManager.checkAndRequestPermission(pid, permission)
├─ 检查是否已有权限
│ ├─ 调用 hasPermission()
│ └─ 如果已有权限:返回 true
│
├─ 检查并发请求去重
│ ├─ 查找待处理的权限检查
│ │ └─ _pendingPermissionChecks.get(`${pid}_${permission}`)
│ │
│ └─ 如果存在:等待现有请求完成
│
├─ 获取权限级别
│ └─ PERMISSION_LEVEL_MAP[permission]
│
├─ 根据权限级别处理
│ ├─ NORMAL(普通权限)
│ │ ├─ 自动授予
│ │ ├─ 添加到权限表 (_permissions)
│ │ ├─ 更新权限缓存(5 秒 TTL)
│ │ ├─ 记录到审计日志
│ │ ├─ 更新统计信息(granted++, checked++)
│ │ └─ 返回 true
│ │
│ ├─ SPECIAL(特殊权限)
│ │ ├─ 检查用户级别(UserControl.isAdmin())
│ │ │ ├─ 普通用户:可以授权
│ │ │ └─ 管理员:可以授权
│ │ │
│ │ ├─ 检查是否已授予(从本地存储读取)
│ │ │ ├─ 已授予:添加到权限表,更新缓存,返回 true
│ │ │ └─ 未授予:继续请求流程
│ │ │
│ │ ├─ 弹出权限请求对话框(GUIManager.showPermissionDialog)
│ │ │ ├─ 显示程序名称和图标
│ │ │ ├─ 显示权限名称和描述
│ │ │ ├─ 显示权限级别(特殊权限)
│ │ │ ├─ 提供"允许"和"拒绝"按钮
│ │ │ └─ 可选:"记住选择"复选框
│ │ │
│ │ ├─ 用户选择
│ │ │ ├─ 允许
│ │ │ │ ├─ 授予权限
│ │ │ │ ├─ 添加到权限表
│ │ │ │ ├─ 保存到本地存储(如果选择记住)
│ │ │ │ ├─ 更新权限缓存
│ │ │ │ ├─ 记录到审计日志
│ │ │ │ ├─ 更新统计信息
│ │ │ │ └─ 返回 true
│ │ │ │
│ │ │ └─ 拒绝
│ │ │ ├─ 记录到审计日志
│ │ │ ├─ 更新统计信息(denied++, checked++)
│ │ │ └─ 返回 false
│ │ │
│ │ └─ 如果用户关闭对话框
│ │ └─ 视为拒绝
│ │
│ └─ DANGEROUS(危险权限)
│ ├─ 检查用户级别(UserControl.isAdmin())
│ │ ├─ 普通用户:拒绝授权
│ │ │ ├─ 显示错误提示(需要管理员权限)
│ │ │ ├─ 记录到审计日志(标记为权限不足)
│ │ │ ├─ 更新统计信息(denied++, checked++)
│ │ │ └─ 返回 false
│ │ │
│ │ └─ 管理员:可以授权
│ │ ├─ 检查是否已授予(从本地存储读取)
│ │ │ ├─ 已授予:添加到权限表,更新缓存,返回 true
│ │ │ └─ 未授予:继续请求流程
│ │ │
│ │ ├─ 检查高风险权限列表
│ │ │ └─ 某些权限需要额外验证
│ │ │
│ │ ├─ 弹出权限请求对话框(带警告)
│ │ │ ├─ 显示警告图标和警告信息
│ │ │ ├─ 显示程序名称和图标
│ │ │ ├─ 显示权限名称和详细风险说明
│ │ │ ├─ 显示权限级别(危险权限)
│ │ │ ├─ 提供"允许"和"拒绝"按钮
│ │ │ └─ 可选:"记住选择"复选框
│ │ │
│ │ ├─ 用户选择
│ │ │ ├─ 允许
│ │ │ │ ├─ 授予权限
│ │ │ │ ├─ 添加到权限表
│ │ │ │ ├─ 保存到本地存储(如果选择记住)
│ │ │ │ ├─ 更新权限缓存
│ │ │ │ ├─ 记录到审计日志(标记为危险权限,记录管理员用户名)
│ │ │ │ ├─ 更新统计信息
│ │ │ │ └─ 返回 true
│ │ │ │
│ │ │ └─ 拒绝
│ │ │ ├─ 记录到审计日志
│ │ │ ├─ 更新统计信息
│ │ │ └─ 返回 false
│ │ │
│ │ └─ 如果用户关闭对话框
│ │ └─ 视为拒绝
│ │
│ └─ 检查高风险权限列表(UserControl.HIGH_RISK_PERMISSIONS)
│ └─ 某些权限需要额外验证(如加密相关权限)
│
└─ 更新权限统计
├─ 增加 checked 计数
├─ 如果授予:增加 granted 计数
└─ 如果拒绝:增加 denied 计数
权限验证阶段
└─ 内核 API 调用时验证权限
验证流程
├─ 解析 API 名称
│ └─ 映射到所需权限
│
├─ 调用 checkAndRequestPermission()
│ └─ 如果返回 false:抛出权限错误
│
└─ 如果返回 true:继续执行 API
权限审计
├─ 记录所有权限操作
│ ├─ 权限授予
│ ├─ 权限拒绝
│ ├─ 权限检查
│ └─ 权限违规
│
├─ 审计日志条目
│ ├─ timestamp: 时间戳
│ ├─ pid: 进程 ID
│ ├─ programName: 程序名称
│ ├─ permission: 权限名称
│ ├─ action: 操作类型(grant/deny/check/violation)
│ ├─ result: 结果(granted/denied)
│ ├─ level: 权限级别
│ ├─ reason: 原因(可选)
│ └─ context: 上下文(可选)
│
└─ 保存审计日志
├─ 限制日志大小(最多 10000 条)
└─ 定期清理旧日志
权限违规处理
├─ 检测权限违规
│ ├─ 尝试使用未授予的权限
│ ├─ 尝试绕过权限检查
│ └─ 尝试修改权限系统
│
├─ 记录违规
│ ├─ 添加到违规日志
│ ├─ 记录调用栈
│ └─ 记录上下文信息
│
└─ 处理违规
├─ 拒绝操作
├─ 记录到审计日志
└─ 可选:终止进程(严重违规)
权限持久化
├─ 保存权限决策
│ └─ LStorage.setSystemStorage('permissionManager.permissions', ...)
│
├─ 加载权限决策
│ └─ 系统启动时从本地存储加载
│
└─ 权限白名单/黑名单
├─ 白名单:自动授予权限的程序列表
└─ 黑名单:禁止运行的程序列表
权限级别说明
├─ NORMAL(普通权限)
│ ├─ 自动授予,无需用户确认
│ ├─ 仅记录到审计日志
│ └─ 示例:GUI_WINDOW_CREATE, KERNEL_DISK_READ
│
├─ SPECIAL(特殊权限)
│ ├─ 首次使用时弹出权限请求对话框
│ ├─ 用户可以选择"允许"或"拒绝"
│ ├─ 决策会被保存,下次自动应用
│ └─ 示例:SYSTEM_NOTIFICATION, KERNEL_DISK_WRITE
│
└─ DANGEROUS(危险权限)
├─ 需要用户明确授权
├─ 仅管理员可以授予
├─ 每次使用都可能弹出权限请求对话框
└─ 示例:PROCESS_MANAGE, SYSTEM_STORAGE_WRITE_USER_CONTROL
ZerOS 提供结构化异常处理(SEH)机制,支持4种异常等级,自动处理不同类型的异常。
┌─────────────────────────────────────────────────────────────┐
│ 异常处理流程 (ExceptionHandler) │
└─────────────────────────────────────────────────────────────┘
异常报告入口
├─ 程序调用 KernelAPI.call('Exception.report', [level, message, details, pid])
│ ├─ ProcessManager._executeKernelAPI() 接收请求
│ ├─ 权限检查:SYSTEM_NOTIFICATION(普通权限,自动授予)
│ └─ 路由到 ExceptionHandler.reportException()
│
└─ 根据异常等级分发处理
├─ KERNEL(内核异常)
├─ SYSTEM(系统异常)
├─ PROGRAM(程序异常)
└─ SERVICE(服务异常)
程序调用 Exception.report('KERNEL', message, details)
│
├─ 设置内核异常标志
│ ├─ ExceptionHandler._kernelExceptionFlag = true
│ ├─ LStorage.setSystemStorage('exceptionHandler.kernelExceptionFlag', true)
│ └─ LStorage.setSystemStorage('exceptionHandler.blockNormalBoot', true)
│
├─ 启用安全模式
│ ├─ 如果 SafeModeManager 可用
│ │ └─ SafeModeManager.enableSafeMode()
│ └─ 否则设置 sessionStorage
│ └─ sessionStorage.setItem('__ZEROS_SAFE_MODE__', 'true')
│
├─ 记录日志
│ └─ KernelLogger.error('ExceptionHandler', '内核异常', ...)
│
└─ 跳转到BIOS或刷新页面
├─ 如果 BIOSManager 可用
│ └─ 跳转到BIOS界面
└─ 否则
└─ location.reload()(刷新页面)
系统重启后(BootLoader)
├─ 加载 ExceptionHandler 模块
│ └─ 从 LStorage 读取内核异常标志
│
├─ 检查内核异常标志
│ ├─ ExceptionHandler.init() 初始化
│ └─ ExceptionHandler.canNormalBoot() 检查
│ ├─ 如果检测到内核异常标志
│ │ ├─ 设置安全模式标志
│ │ ├─ 显示安全模式界面
│ │ ├─ 显示BIOS加载动画
│ │ └─ 中断启动流程(不继续正常启动)
│ └─ 如果未检测到异常
│ └─ 继续正常启动流程
│
└─ 用户在BIOS中清除标志
├─ 选择"清除内核异常标志并强制进入系统"
├─ BIOSManager._confirmClearKernelException()
├─ ExceptionHandler.clearKernelExceptionFlag()
│ ├─ ExceptionHandler._kernelExceptionFlag = false
│ ├─ LStorage.setSystemStorage('exceptionHandler.kernelExceptionFlag', false)
│ └─ LStorage.setSystemStorage('exceptionHandler.blockNormalBoot', false)
└─ 系统可以正常启动
程序调用 Exception.report('SYSTEM', message, details)
│
├─ 强制停止所有程序
│ ├─ 遍历 ProcessManager.PROCESS_TABLE
│ ├─ 跳过 Exploit 程序 (PID: 10000)
│ └─ 终止所有其他进程
│ └─ ProcessManager.terminateProcess(pid)
│
├─ 显示蓝屏界面
│ ├─ 创建全屏覆盖层
│ ├─ 设置蓝色背景 (#0078D4)
│ ├─ 显示错误信息
│ │ ├─ 错误代码:SYSTEM_EXCEPTION
│ │ ├─ 错误消息:message
│ │ ├─ 时间戳:当前时间
│ │ └─ 详细信息:details(JSON格式)
│ └─ 显示进度指示器
│ └─ "正在收集错误信息..."
│
├─ 执行系统自检
│ ├─ 检查内存管理器
│ │ └─ MemoryManager.checkMemory()
│ ├─ 检查文件系统
│ │ └─ Disk.canUsed
│ └─ 检查进程管理器
│ └─ ProcessManager.PROCESS_TABLE.size
│
├─ 更新蓝屏进度
│ ├─ "正在检查内存..."
│ ├─ "正在检查文件系统..."
│ └─ "正在检查进程管理器..."
│
├─ 等待随机延迟(15-60秒)
│ └─ setTimeout(..., random(15000, 60000))
│
└─ 自动重启系统
└─ location.reload()
程序调用 Exception.report('PROGRAM', message, details, pid)
│
├─ 获取进程信息
│ ├─ 如果 pid 为 null,使用当前调用者 PID
│ └─ ProcessManager.getProcessInfo(pid)
│
├─ 强制终止进程
│ └─ ProcessManager.terminateProcess(pid)
│ ├─ 调用程序的 exit() 方法(如果存在)
│ ├─ 清理程序资源
│ ├─ 从 PROCESS_TABLE 移除进程
│ └─ 释放内存
│
├─ 显示通知
│ └─ NotificationManager.createNotification({
│ title: '程序异常',
│ content: `程序 ${programName} 发生异常并已被终止`,
│ type: 'error',
│ duration: 5000
│ })
│
└─ 记录日志
└─ KernelLogger.error('ExceptionHandler', '程序异常', {
pid, programName, message, details
})
程序调用 Exception.report('SERVICE', message, details)
│
└─ 记录日志
└─ KernelLogger.error('ExceptionHandler', '服务异常', {
message, details
})
└─ 不影响系统运行
本文档详细描述了 ZerOS 虚拟操作系统的六个核心流程:
这些流程共同构成了 ZerOS 系统的核心运行机制,确保了系统的安全性、稳定性和可扩展性。
ZerOS 系统流程文档 - 完整描述系统核心运行机制
Made with ❤️ by ZerOS Team