Files
lou 0827b2399c 内核框架 v0.1 首次提交: 引导器 / 内核 / 驱动 + 日志系统
引导器 UEFI.boot.py (纯 stdlib, 内核的管家)
  体检 6 项 (解释器/venv/包/驱动目录/PG) / venv 重建 / 包台账 / 内核进程启停记账 / 参数原样透传
  内核日志 / 引导器日志 / 内核 stdio 三条道的查看入口都归它

内核 内核/ (常驻调度 = 甲)
  命令消费 (PG commands + LISTEN/NOTIFY) / 驱动调用仲裁六条 (越权·成环·无人提供·按需拉起·同锁排队·超时收权)
  依赖链巡检 10s / 心跳 300s / 独一份调度锁 (pg_try_advisory_lock 0x65666901)
  扫描: 9 条校验 + 契约匹配 + 拓扑排序; 状态: 快照原子写 + 断电收尸判定
  db.py 是唯一碰 SQL 的文件 (drivers/driver_state/events/scans/commands/calls/kernel_env/kernel_runs)

日志系统 (2026-09-16 完整化, 设计/04-日志系统.md)
  三条道一个文件一种内容: 内核.log (结构化行) / 内核.out.log (命令输出 + 崩溃原文) / 引导器.log (引导器动作)
  驱动日志每轮启动前插分隔头; 门槛 log_level / 轮转 log_max_mb + log_keep / -n · -f · --级别 · -g · --json · --全部
  实现 内核/日志.py (内核与引导器共用一份); 修掉"命令输出混进日志文件" (实证存档 归档/20260916-日志系统重做前/)

驱动样板 (也是写驱动的示范): Json解码 (oneshot) / 样板常驻 (provides 样板:心跳) / 样例消费器 (needs 只发契约名)

代码标点统一为 ASCII (保留界面用的框线 ─│◄▶ 与表格占位符 —); 已用 AST 等价对比证明逻辑零改动

自测 (真机, 不 mock): 进程 (真起进程真收子树) / 内核 58 项 / 配置 / db 182 项 / 日志 86 项
验收: 试跑引导器.py PASS 11 / FAIL 0 / 残留无; uvx pyright 与 uvx basedpyright 均 0 errors 0 warnings
2026-09-16 21:03:48 +08:00

11 KiB
Raw Permalink Blame History

03 引导器 UEFI.boot.py

引导器 = 内核的管家,三件事:管内核环境管包状态管内核进程。 它不碰驱动 —— 驱动是内核的活。分层是一层管一层:引导器管内核,内核管驱动。

1. 职责边界

引导器做 引导器不做
内核环境体检(解释器 / venv / 路径 / PG 不扫驱动、不管驱动进程(内核的活)
venv 重建、包安装(显式敲命令才动手 不自动修复、不自动装包、不自动升级
包状态台账(已装 / 缺失 / 版本不符) 不管驱动的 venv 和依赖(驱动自己的事)
管内核进程(启停 / 判活 / 日志 / 记账) 不改任何 配置.efi.json
其余参数原样透传给内核 不重复实现内核子命令

2. 铁律:引导器零第三方依赖

鸡生蛋问题:引导器要检查"内核环境里的包状态",可引导器自己要是依赖某个包,那包坏了引导器也起不来 —— 就没人来报错了。所以:

| 引导器自己的命令(自检 / 环境 / 包) | 纯 stdlibsubprocess 调 uv/pip、importlib.metadata 读版本、pathlib 查路径 | | 写 PG 台账 | try: import psycopg2;没有就降级:只写 环境状态.efi.json 快照 + 一行 WARN不算失败 | | 透传给内核的命令 | PG 连不上由内核自己报错退出(内核的内存就是 PG,它不降级) |

分界线一句话:引导器自己的命令 PG 降级,内核的命令不降级。 引导器永远要能跑起来、能报错、能给出修复命令。

3. 三层文件(对称设计)

每层都是"一份声明 + 一份状态快照":

声明(人/引导器写) 状态快照(运行时写)
驱动 驱动/<名>/配置.efi.json 驱动/<名>/运行.efi.json
内核 / 引导器 环境.efi.json 环境状态.efi.json

4. 环境.efi.json(项目根,外置声明)

引导器是它唯一的写者,内核只读。 一份配置,不许有第二份(两份真相 = 迟早打架)。 内核原先设计的"内核自己的 配置.efi.json"取消,合并到这一份。

类型 说明
efi int 版本
python str 解释器要求,如 ">=3.11"
venv str venv 相对路径,默认 .venv
index str 包索引源。校网必须走国内:https://pypi.tuna.tsinghua.edu.cn/simple
packages list 内核依赖清单,见下
db dict {name, host, port, user}host 填 unix socket 目录
driver_root str 驱动目录,默认 "驱动"
stop_timeout int 停进程超时秒,默认 10
log_lines int 日志命令默认行数,默认 200
log_level str 日志门槛 DEBUG/INFO/WARN/ERROR,默认 INFO(低于它的不写)
log_max_mb int 单份日志轮转上限(MB),默认 50 = 不轮转
log_keep int 轮转后保留份数,默认 30 = 不轮转

packages 每项:

说明
name 安装名(pip 名),如 psycopg2-binary
version 版本要求,如 ">=2.9.9",空 = 不校验
import 导入名(校验用),如 psycopg2
required true 缺失即环境不通过;false 缺失只 WARN
{
  "efi": 1,
  "python": ">=3.11",
  "venv": ".venv",
  "index": "https://pypi.tuna.tsinghua.edu.cn/simple",
  "packages": [
    { "name": "psycopg2-binary", "version": ">=2.9.9", "import": "psycopg2", "required": true }
  ],
  "db": { "name": "efi_kernel", "host": "/home/lou/pgdata/socket", "port": 5432, "user": "lou" },
  "driver_root": "驱动",
  "stop_timeout": 10,
  "log_lines": 200
}

5. 环境体检(自检 / 环境

6 项,逐项出结论 + 修复命令,从不含糊:

# 检查 方法 不过时给什么
1 解释器版本符合 python 跑解释器报版本,比 >= / <= / == 报"需要 ≥x,当前 y"
2 venv 存在 .venv/bin/python 环境 重建
3 venv 健康 .venv/bin/python -c "import sys;print(sys.prefix)",结果必须等于 .venv 自身绝对路径;pyvenv.cfghome 指向存在的解释器 环境 重建(★治"目录搬走后 shebang 还指旧路径"这个病,本项目 .venv 现在正是坏的:shebang 指着 /home/lou/桌面/内核/.venv/...
4 包状态 uv pip list --format json 读实装版本(没 uv 就 importlib.metadata),逐条核 packages 列出缺的 / 版本不符的 + 包 安装
5 driver_root 可读写 存在 + 能建临时文件 报错(不自动建空目录
6 PG 能连 实例在跑 + 库 db.name 存在 + 真连一次 给建库/起库命令

判定 → 汇总 ok: true/false,落 环境状态.efi.json(快照)+ PG kernel_env(台账)。

6. 包状态(

  • → 台账表:包名 / 要求 / 实装 / 状态(一致·缺失·版本不符)/ 必需性
  • 包 安装 [名...]uv pip install(走 index 里的国内源,校网 GFW 下这是硬要求);不带名字 = 按清单全装
  • 不自动装、不自动升(手动控制口径,"一搞就炸")
  • uv 不在时回落 python3 -m venv + pip -i <index>

7. 内核进程管理(内核 ...

内核通常是一次性短命进程(跑完就退,状态在 PG),引导器把它当受管进程记账:

命令 作用
内核 状态 有没有内核在跑(pid + /proc/<pid>/cmdline 校验);上次运行(起止 / 耗时 / 退出码);今天跑了几次
内核 启动 [--守护] 拉起内核进程;--守护 = 常驻模式(预留,v0.1 不实现)
内核 停止 / 内核 重启 停 / 重启内核进程
内核 日志 [选项] 内核日志(默认看结构化日志 内核.log--输出 看命令输出/崩溃原文 内核.out.log
日志 [选项] 引导器自己的动作日志(内核/logs/引导器.log--内核/--输出 转看内核那两份)

复用 内核/进程.py —— 启停 / 判活 / cmdline 校验 / 收子树全用同一份实现。 绝不为引导器再写一套(两套实现 = 各有一套坑,还各自以为对方对)。

边界:内核是总调度(见 02 第 2 节末),引导器只保证"它活着、它跑得起来"—— 拉起、判活、重启、收日志,不干预它怎么调度驱动

(内核自身常驻已定稿 = 甲:常驻调度器。所以引导器管的这个内核进程是长期存在的, 内核 启动/停止/状态/日志 就是它的生命周期;引导器只保证它活着,不干预它怎么调度。)

记账两张表(同库 efi_kernel):

-- 环境/包体检台账
CREATE TABLE kernel_env (
  id            bigserial PRIMARY KEY,
  ts            timestamptz DEFAULT now(),
  python_version text,
  venv_path     text,
  venv_healthy  boolean,
  packages      jsonb,        -- [{name, want, got, ok}]
  pg_ok         boolean,
  driver_root_ok boolean,
  ok            boolean,
  detail        text
);

-- 内核运行台账(每次运行一行)
CREATE TABLE kernel_runs (
  id          bigserial PRIMARY KEY,
  started_at  timestamptz DEFAULT now(),
  finished_at timestamptz,
  argv        text,
  mode        text,           -- oneshot | daemon
  pid         integer,
  exit_code   integer,
  seconds     real,
  ok          boolean,
  detail      text
);

8. CLI 全表

顶层固定 4 个词(自检 / 环境 / / 内核)归引导器,其余原样透传内核 —— 重名因此不冲突:启动 抓取器 是驱动,内核 启动 是内核。

命令 谁干
UEFI.boot.py 自检 → 内核默认动作(列表)
UEFI.boot.py --check | 自检 只体检,不启内核
UEFI.boot.py 环境 [--json] 体检(同上)
UEFI.boot.py 环境 重建 python 要求重建 venv(显式)
UEFI.boot.py 包 [--json] 包状态台账
UEFI.boot.py 包 安装 [名...] 装包(显式)
UEFI.boot.py 内核 状态|启动|停止|重启|日志 内核进程管理
UEFI.boot.py 日志 [选项] 引导器自己的动作日志(体检 / 包 / 移交 / 内核启停 / WARN)
UEFI.boot.py 列表|扫描|启动 <驱动>|停止 <驱动>|重启 <驱动>|状态|日志 <驱动>|事件|清单 透传给内核

日志选项(日志 / 内核 日志 / 透传的 日志 <驱动> 认同一套,解析只有一份 日志.解析选项):

开关 含义
-n 200 尾部行数(含轮转的历史份一起数)
-f 实时跟(先吐 10 行,Ctrl+C 停;一次只能跟一个来源)
--级别 WARN 只要这个级别及以上(驱动原始日志按字样猜级别)
-g 关键词 只要含它的行(不区分大小写)
--json JSON Lines(结构化日志拆字段;裸行给空来源 + 猜的级别)
--全部 / --内核 / --引导器 / --输出 换来源

参数写错 → 打用法 + 退出码 1(不猜、不静默用默认值)。引导器每次跑都轮转一次自己的日志 (短命进程,天然没有"运行中改名"的风险)。

9. 启动时序

$ python3 UEFI.boot.py 列表
   │
   ├─ ① 体检(纯 stdlib,任何情况都能报)
   │     解释器版本 → venv 存在/健康 → 包状态 → 驱动目录 → PG
   │     不通过 → 打印原因 + 修复命令,退出 1(不往下走,不自动改)
   │
   ├─ ② 记账
   │     写 环境状态.efi.json(必做,原子替换)
   │     写 PG kernel_env(尽力而为,连不上就 WARN)
   │
   ├─ ③ 移交
   │     fork 内核进程(argv 透传) → 等 → 记 kernel_runs → 返回它的退出码
   │     内核自己写 内核/logs/内核.log(结构化行)
   │     --守护 时内核 stdio 重定向到 内核/logs/内核.out.log(命令输出 + 崩溃原文)
   │
   └─ ④ 退出不管子进程(驱动是独立进程组,不随引导器死)

10. 边界

场景 行为
引导器自己的命令 + PG 不通 WARN + 只写 json 快照,不失败
透传内核的命令 + PG 不通 由内核报错退出,引导器原样返回非 0
venv 不健康 明确报"不健康 + 为什么" + 环境 重建不自动重建
包缺失 列出缺哪个 + 包 安装不自动装
uv 不在 回落 python3 -m venv + pip -i <index>,并 WARN
driver_root 不存在 报错退出 1(不建空目录)
内核文件缺失 报错退出 1,指路径
内核抛异常 原样打印堆栈,退出码非 0
内核秒退非 0 kernel_runs.ok=false + detail 存日志末尾若干行

11. v0.1 范围

:环境体检 / venv 重建 / 包台账 / 装包 / 内核进程记账与启停 / 参数透传。

不做:自动修复、自动装包、开机自启、常驻守护(--守护 只留接口)、驱动 env 代管。