From 8a09f5c70cc14690c5a4aa9c195948424069c370 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 7 Nov 2026 01:26:35 +0000 Subject: [PATCH] =?UTF-8?q?docs:=20=E5=8A=A0=E5=85=A5=E5=9B=BE=E6=A0=87?= =?UTF-8?q?=E4=B8=8E=20SVG=20=E7=A4=BA=E6=84=8F=E5=9B=BE=EF=BC=8Cheader=20?= =?UTF-8?q?=E6=96=87=E5=AD=97=E6=94=B9=E4=B8=BA=E5=9B=BE=E6=A0=87=EF=BC=8C?= =?UTF-8?q?=E5=87=8F=E5=B0=91=E7=BA=AF=E6=96=87=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 只放在有信息量的地方,避免给每张卡片配同一批通用图标: 机制图 - PySpOS:一条命令的执行路径(Shell → 进程 → 运行时) - SpaceOS 9:启动顺序(UEFI → Limine → SpaceKernel → systemg → ash) - SpaceOS 8:系统分层图,含系统调用 ABI 分界;应用规模用条形图对比 - OTA:A/B 槽位升级与回滚的 SVG 示意 - 两个下载页:下载 → 校验 → 启动三步 插画与图标 - 首页首屏的分层示意图,三个项目色块各配不同图标 - 每个产品页顶部四个要点,图标各不相同 - 提示块、已验证/未验证徽标、下载按钮配功能性图标 - 配置要求页的产品标题配与首页一致的图标 Header - 主题切换、菜单按钮改为太阳/月亮、汉堡/关闭图标,随状态切换 - 下拉箭头由文字符号改为 SVG,下拉项配产品图标;GitHub 加外链图标 - 品牌名前加分层标志,与首页插画呼应 实现 - 20 余个线条图标画成一个 SVG sprite,由 sync_docs_chrome.py 统一注入, 用 currentColor 与 token 上色,深浅主题自动适配 - check_docs_html 新增: 必须在 sprite 里有对应 symbol - 流程图用 HTML + CSS 画,窄屏自动竖排,文字保持真实字号 Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01SdLheqvbhbobVxS1NvgLpw --- docs/css/style.css | 210 +++++++++++++++++++++++++++++++- docs/index.html | 109 +++++++++++++---- docs/js/main.js | 5 +- docs/ota/index.html | 81 +++++++++--- docs/ota/releases.html | 55 ++++++--- docs/pyspos.html | 99 ++++++++++++--- docs/requirements.html | 71 ++++++++--- docs/spaceos6.html | 63 +++++++--- docs/spaceos7.html | 63 +++++++--- docs/spaceos8-download.html | 100 +++++++++++---- docs/spaceos8.html | 156 ++++++++++++++++-------- docs/spaceos9-download.html | 100 +++++++++++---- docs/spaceos9.html | 105 ++++++++++++---- tools/checks/check_docs_html.py | 6 + tools/sync_docs_chrome.py | 100 ++++++++++++--- 15 files changed, 1058 insertions(+), 265 deletions(-) diff --git a/docs/css/style.css b/docs/css/style.css index 32afb74..4c7062f 100644 --- a/docs/css/style.css +++ b/docs/css/style.css @@ -129,7 +129,16 @@ strong { font-weight: 700; } text-decoration: none; white-space: nowrap; } +.brand { + display: inline-flex; + align-items: center; + gap: var(--pg-space-2); +} .brand:hover { color: var(--pg-fg-1); } +.brand-mark { width: 1.75rem; height: 1.75rem; flex: none; } +.brand-mark .m1 { fill: var(--pg-fg-1); } +.brand-mark .m2 { fill: var(--pg-brand); } +.brand-mark .m3 { fill: var(--pg-line-strong); } .site-nav { margin-left: auto; } .site-nav > ul { @@ -168,7 +177,12 @@ strong { font-weight: 700; } .menu { position: relative; } .menu > summary { list-style: none; } .menu > summary::-webkit-details-marker { display: none; } -.menu > summary::after { content: " ▾"; font-size: var(--pg-text-xs); } +.menu > summary { display: flex; align-items: center; gap: var(--pg-space-1); } +.menu > summary .chev { width: 1em; height: 1em; vertical-align: 0; } +.menu[open] > summary .chev { transform: rotate(180deg); } +.menu > ul a { display: flex; align-items: center; gap: var(--pg-space-3); } +.menu > ul a .icon { color: var(--pg-fg-3); vertical-align: 0; } +.site-nav a .ext { width: 0.9em; height: 0.9em; margin-left: var(--pg-space-1); vertical-align: -0.1em; color: var(--pg-fg-3); } .menu > ul { position: absolute; top: calc(100% + var(--pg-space-1)); @@ -202,6 +216,14 @@ strong { font-weight: 700; } } .icon-btn:hover { color: var(--pg-fg-1); background: var(--pg-bg-sunken); } .nav-toggle { display: none; } +.icon-btn { width: 2.25rem; padding: 0; } +.icon-btn .icon { vertical-align: 0; } +.icon-sun { display: none; } +body.theme-dark .icon-sun { display: inline; } +body.theme-dark .icon-moon { display: none; } +.nav-toggle .icon-close { display: none; } +.nav-toggle[aria-expanded="true"] .icon-menu { display: none; } +.nav-toggle[aria-expanded="true"] .icon-close { display: inline; } /* ---------- 首屏 ---------- */ .hero { padding-block: var(--pg-space-9) var(--pg-space-8); } @@ -390,7 +412,15 @@ td.num { text-align: right; font-family: var(--pg-font-mono); white-space: nowra border: 1px solid var(--pg-line-2); border-radius: var(--pg-radius); } -.notice > * + * { margin-top: var(--pg-space-2); } +.notice { + display: flex; + align-items: flex-start; + gap: var(--pg-space-3); +} +.notice > div { min-width: 0; } +.notice > div > * + * { margin-top: var(--pg-space-2); } +.notice-icon { margin-top: 0.2em; color: var(--pg-accent); } +.notice-warn .notice-icon { color: var(--pg-warn-fg); } .notice-title { font-weight: 700; } .notice-info { background: var(--pg-accent-soft); border-color: var(--pg-accent-soft); } .notice-warn { background: var(--pg-warn-bg); border-color: var(--pg-warn-line); } @@ -534,9 +564,176 @@ figcaption { } .footer-base p { margin: 0; } + +/* ---------- 图标 ---------- */ +.sprite { position: absolute; width: 0; height: 0; overflow: hidden; } +.icon { + width: 1.25em; + height: 1.25em; + flex: none; + fill: none; + stroke: currentColor; + stroke-width: 1.75; + stroke-linecap: round; + stroke-linejoin: round; + vertical-align: -0.25em; +} +.icon-box { + display: inline-grid; + place-items: center; + flex: none; + width: 3rem; + height: 3rem; + color: var(--pg-fg-1); + background: var(--pg-bg-raised); + border-radius: var(--pg-radius); +} +.icon-box .icon { width: 1.625rem; height: 1.625rem; vertical-align: 0; } +.section-tint .icon-box { background: var(--pg-bg-page); } +.button .icon { margin-right: var(--pg-space-2); vertical-align: -0.2em; } +.badge .icon { width: 1em; height: 1em; margin-right: var(--pg-space-1); vertical-align: -0.15em; } +.tile-icon { margin-bottom: var(--pg-space-2); } +.split-head { display: flex; flex-direction: column; gap: var(--pg-space-3); align-items: flex-start; } +.icon-line { display: flex; align-items: baseline; gap: var(--pg-space-3); } +.icon-line .icon { position: relative; top: 0.25em; color: var(--pg-fg-3); } + +/* ---------- 要点条:每页顶部的四件事 ---------- */ +.points { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: var(--pg-space-5); + margin: 0; + padding: 0; + list-style: none; +} +.points > li { display: flex; flex-direction: column; gap: var(--pg-space-2); margin: 0; } +.points .icon-box { margin-bottom: var(--pg-space-1); background: var(--pg-bg-sunken); } +.points + .notice { margin-top: var(--pg-space-6); } +.points strong { + font-family: var(--pg-font-serif); + font-size: var(--pg-text-lg); + font-weight: 400; + line-height: var(--pg-leading-tight); +} +.points p { font-size: var(--pg-text-sm); color: var(--pg-fg-2); } + +/* ---------- 流程图 ---------- */ +.flow { + display: grid; + grid-template-columns: repeat(var(--cols, 3), minmax(0, 1fr)); + gap: var(--pg-space-5); + margin: 0; + padding: 0; + list-style: none; +} +.flow-4 { --cols: 4; } +.flow-5 { --cols: 5; } +.flow > li { + position: relative; + display: flex; + flex-direction: column; + gap: var(--pg-space-2); + min-width: 0; + margin: 0; + padding: var(--pg-space-5); + background: var(--pg-bg-raised); + border: 1px solid var(--pg-line-2); + border-radius: var(--pg-radius-lg); +} +.section-tint .flow > li { background: var(--pg-bg-page); } +.flow > li + li::before { + content: ""; + position: absolute; + top: 50%; + left: -1.05rem; + width: 0.6rem; + height: 0.6rem; + margin-top: -0.3rem; + border-top: 2px solid var(--pg-line-strong); + border-right: 2px solid var(--pg-line-strong); + transform: rotate(45deg); +} +.flow-top { display: flex; align-items: center; justify-content: space-between; } +.flow-top .icon-box { background: var(--pg-bg-sunken); } +.section-tint .flow-top .icon-box { background: var(--pg-bg-sunken); } +.flow-n { font-family: var(--pg-font-serif); font-size: var(--pg-text-xl); color: var(--pg-brand); } +.flow-title { font-weight: 700; line-height: var(--pg-leading-tight); } +.flow p { font-size: var(--pg-text-sm); color: var(--pg-fg-2); } +.flow code { font-size: var(--pg-text-xs); } +.flow > li > a { margin-top: auto; padding-top: var(--pg-space-2); font-size: var(--pg-text-sm); font-weight: 600; } +.flow > li > code { margin-top: auto; } + +/* ---------- 分层图 ---------- */ +.layers { + display: grid; + gap: var(--pg-space-2); + margin: 0; + padding: 0; + list-style: none; +} +.layers > li { + display: flex; + flex-wrap: wrap; + align-items: baseline; + justify-content: space-between; + gap: var(--pg-space-1) var(--pg-space-4); + margin: 0; + padding: var(--pg-space-3) var(--pg-space-4); + background: var(--pg-bg-sunken); + border-radius: var(--pg-radius); +} +.layers strong { font-weight: 700; } +.layers span { font-size: var(--pg-text-sm); color: var(--pg-fg-2); } +.layers .layer-user { background: var(--pg-tile-sky); } +.layers .layer-compat { background: var(--pg-tile-sage); } +.layers .layer-lib { background: var(--pg-tile-sage); } +.layers .layer-kernel { background: var(--pg-tile-clay); } +.layers .layer-abi { + background: transparent; + border: 2px dashed var(--pg-line-strong); +} +.section-tint .layers .layer-boot { background: var(--pg-bg-raised); } + +/* ---------- 条形图:表格里的数量对比 ---------- */ +.bar { + display: block; + width: 7rem; + height: 0.375rem; + margin: 0 0 var(--pg-space-1); + overflow: hidden; + background: var(--pg-line-1); + border-radius: var(--pg-radius-pill); +} +.num .bar { margin-left: auto; } +.bar > i { + display: block; + width: var(--w); + height: 100%; + background: var(--pg-brand); +} + +/* ---------- 插画 ---------- */ +.art { display: block; width: 100%; max-width: 30rem; height: auto; margin-inline: auto; } +.art text { font-family: var(--pg-font-sans); fill: var(--pg-fg-1); } +.art .art-sub { fill: var(--pg-fg-2); } +.art .art-note { fill: var(--pg-fg-3); } +.art-l1 { fill: var(--pg-tile-sky); } +.art-l2 { fill: var(--pg-tile-clay); } +.art-l3 { fill: var(--pg-tile-sage); } +.art-slot { fill: var(--pg-bg-raised); stroke: var(--pg-line-strong); stroke-width: 2; } +.art-slot-on { fill: var(--pg-tile-clay); stroke: var(--pg-brand); stroke-width: 2; } +.art-line { fill: none; stroke: var(--pg-fg-3); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; } +.art-brand { fill: none; stroke: var(--pg-brand); stroke-width: 2.5; stroke-linecap: round; stroke-linejoin: round; } +.art-ico { fill: none; stroke: var(--pg-fg-2); stroke-width: 1.1; stroke-linecap: round; stroke-linejoin: round; } +.stack .art { max-width: 34rem; margin-inline: 0; } +.hero-art-svg { min-width: 0; } +.hero-art-svg figcaption { max-width: 30rem; margin-inline: auto; } + /* ---------- 窄屏 ---------- */ @media (max-width: 62rem) { .tiles { grid-template-columns: minmax(0, 1fr); } + .points { grid-template-columns: repeat(2, minmax(0, 1fr)); } + .flow-4, .flow-5 { --cols: 2; } .footer-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } .footer-about { grid-column: 1 / -1; } } @@ -547,6 +744,15 @@ figcaption { .hero-split, .split, .release { grid-template-columns: minmax(0, 1fr); gap: var(--pg-space-5); } .section { padding-block: var(--pg-space-7); } .rows > li, .rows-wide > li { grid-template-columns: minmax(0, 1fr); gap: var(--pg-space-1); } + .points { grid-template-columns: minmax(0, 1fr); } + .flow, .flow-4, .flow-5 { --cols: 1; gap: var(--pg-space-6); } + .flow > li + li::before { + top: -1.05rem; + left: 50%; + margin: 0 0 0 -0.3rem; + transform: rotate(135deg); + } + .hero-art-svg { max-width: 24rem; } /* 没有脚本时,导航直接在页眉里折行,仍然可用。 */ .header-inner { flex-wrap: wrap; padding-block: var(--pg-space-2); } diff --git a/docs/index.html b/docs/index.html index 617c012..7ec34b3 100644 --- a/docs/index.html +++ b/docs/index.html @@ -7,56 +7,110 @@ GoutouStdio - + +
-
-

几个学生写的操作系统。

-

GoutouStdio 是学生自发组织的开源小组,2022 年开始做操作系统。现在维护两个项目:用 Python 写的 PySpOS,和用 Rust 写内核的 SpaceOS 9。

-
- 了解 PySpOS - 了解 SpaceOS 9 +
+
+

几个学生,
在写操作系统。

+

GoutouStdio 是学生自发组织的开源小组,2022 年开始做操作系统。现在维护两个项目:用 Python 写的 PySpOS,和用 Rust 写内核的 SpaceOS 9。

+
+
+ + + 用户态 + shell · 应用 · 系统程序 + + + + 系统调用 + + + 内核 + 调度 · 内存 · 文件系统 · 驱动 + + + + 设备访问 + + + 宿主 / 硬件 + Python 运行时 · UEFI 与硬件 + + +
PySpOS 的宿主是 Python 运行时,SpaceOS 直接跑在 UEFI 和硬件上。
+
@@ -65,26 +119,29 @@

几个学生写的操作系统。

项目

+

PySpOS

维护中 v3.2.0 RC1 · MIT

用 Python 写的模拟操作系统。有进程调度、文件系统和引导流程,能执行 x86_64 的 ELF 程序。

- +
+

SpaceOS 9

公开预览 x86_64

内核 SpaceKernel 3.0 用 Rust 写成,实现 Linux ABI。自带 PID 1(systemg)和 C 库(splibc),能运行动态链接的 BusyBox。

- +
+

SpaceOS 8

抢先体验 x86_64 · Apache-2.0

上一代项目。基于 Uinxed 内核(C 写的 UNIX-like 内核),带自研桌面 SPUI 和一批系统程序。

- +
-

存档

+

存档

  • SpaceOS 7 @@ -129,8 +186,8 @@

    历史

    联系

    -

    合作、反馈问题或自我介绍都可以发邮件到 goutoustdio@outlook.com。我们是学生,回复可能比较慢。

    -

    代码在 GitHub:ViudiraTech,PySpOS 仓库是 ViudiraTech/PySpOS。

    +

    合作、反馈问题或自我介绍都可以发邮件到 goutoustdio@outlook.com。我们是学生,回复可能比较慢。

    +

    代码在 GitHub:ViudiraTech,PySpOS 仓库是 ViudiraTech/PySpOS。

    @@ -182,7 +239,7 @@ - + diff --git a/docs/js/main.js b/docs/js/main.js index ea8b0e6..3d558fa 100644 --- a/docs/js/main.js +++ b/docs/js/main.js @@ -23,8 +23,9 @@ document.body.classList.toggle("theme-dark", dark); document.documentElement.dataset.theme = dark ? "dark" : "light"; if (btn) { - btn.textContent = dark ? "主题:深色" : "主题:浅色"; - btn.setAttribute("aria-label", dark ? "当前为深色主题,点击切换到浅色" : "当前为浅色主题,点击切换到深色"); + var label = dark ? "当前为深色主题,点击切换到浅色" : "当前为浅色主题,点击切换到深色"; + btn.setAttribute("aria-label", label); + btn.title = label; } if (persist) saveTheme(dark ? "dark" : "light"); } diff --git a/docs/ota/index.html b/docs/ota/index.html index 103ec42..6367492 100644 --- a/docs/ota/index.html +++ b/docs/ota/index.html @@ -7,43 +7,70 @@ PySpOS 更新包 | GoutouStdio - + + @@ -54,7 +81,7 @@

    PySpOS 更新包

    PySpOS 的 OTA 更新包。支持云端更新、本地安装,以及用 A/B 槽位回滚。

    @@ -118,6 +145,27 @@

    安装前确认

    更新出问题时回滚

    +
    + + + 槽位 A + 活动,正在运行 + + + 槽位 B + 非活动,装入新版本 + + + ① 更新包 + + + ② 校验后切换 + + + ③ 回滚 + +
    更新装进非活动槽位 B,校验通过后切换;出问题时用 ota_rollback 切回 A。切换之后,两个槽位的角色互换。
    +

    回滚会切换到另一个槽位。请确认另一个槽位里有可用的系统版本,否则可能无法启动。

    1. 在 PySpOS 中输入 recovery,进入恢复模式。
    2. @@ -176,7 +224,7 @@
    - + + @@ -127,7 +154,7 @@ - + + @@ -55,7 +82,7 @@

    PySpOS

    用 Python 写的模拟操作系统。它跑在宿主系统上,自己实现了 shell、进程调度、文件系统、引导流程和 OTA 更新,也能执行 x86_64 的 ELF 程序。

    @@ -83,6 +110,46 @@

    PySpOS

    +
    +
    +
      +
    • 真子进程

      应用是独立的 OS 进程,有 PID、父子关系和信号。

    • +
    • EEVDF 调度

      参照 Linux 6.6+,按虚拟截止期和 nice 权重排程。

    • +
    • ELF 引擎

      Unicorn 执行 x86_64 指令,缺它时退回自研模拟器。

    • +
    • A/B 升级

      更新装进非活动槽位,校验后切换,失败可回滚。

    • +
    +
    +
    + +
    +
    +
    +

    一条命令的执行路径

    +

    以外部程序为例:从按下 Enter 到系统调用,经过这三步。

    +
    +
      +
    1. +
      1
      +

      Shell:parse → dispatch

      +

      Shell 把输入解析成命令和参数,再交给对应的模块。管道、重定向和后台作业都从这里开始。

      + src/shell/dispatch.py +
    2. +
    3. +
      2
      +

      进程:fork → exec

      +

      外部应用通过 fork / exec 运行,是独立的进程。调度器用虚拟运行时间和截止期安排执行。

      + src/forkexec.py · src/process.py +
    4. +
    5. +
      3
      +

      运行时:execute → syscall

      +

      ELF 由 Unicorn 执行 x86_64 指令,系统调用转发到内置的模拟层。可以观察执行、改实现,再运行一次。

      + Unicorn Engine → syscall +
    6. +
    +
    +
    +

    概览

    @@ -168,7 +235,7 @@

    兼容性

    @@ -222,7 +289,7 @@ - + diff --git a/docs/requirements.html b/docs/requirements.html index 7b154c8..42d0f09 100644 --- a/docs/requirements.html +++ b/docs/requirements.html @@ -7,43 +7,70 @@ 配置要求 | GoutouStdio - + + @@ -58,7 +85,7 @@

    配置要求

    -

    PySpOS 3.2.0

    +

    PySpOS 3.2.0

    纯用户态,不直接操作硬件,能跑 Python 的机器就能跑。

    @@ -80,7 +107,7 @@

    PySpOS 3.2.0

    -

    SpaceOS 9 公开预览

    +

    SpaceOS 9 公开预览

    目前只在 QEMU 上验证过。

    @@ -101,12 +128,16 @@

    SpaceOS 9 公开预览

    -

    SpaceOS 8

    +

    SpaceOS 8

    -

    请用可抛弃的机器和测试盘

    -

    NTFS 写入驱动目前还不能信任,确认稳定前不要让它碰重要数据。已在 Dell PowerEdge R410 等实体服务器上验证。

    + +
    +

    请用可抛弃的机器和测试盘

    +

    NTFS 写入驱动目前还不能信任,确认稳定前不要让它碰重要数据。已在 Dell PowerEdge R410 等实体服务器上验证。

    +
    +

    表里“已验证”是实际跑过的组合,“默认关闭”的需要自己在 make menuconfig 里打开。

    @@ -137,7 +168,7 @@

    默认关闭的功能

    -

    SpaceOS 6 / 7

    +

    SpaceOS 6 / 7

    这两个项目已停止开发,这里不再列硬件要求。页面仅作历史存档,配置和构建说明以当时的仓库记录为准。

    SpaceOS 7 存档 · SpaceOS 6 存档

    @@ -192,7 +223,7 @@
    - + diff --git a/docs/spaceos6.html b/docs/spaceos6.html index adc75b4..5ef6cfa 100644 --- a/docs/spaceos6.html +++ b/docs/spaceos6.html @@ -7,43 +7,70 @@ SpaceOS 6(已停更) | GoutouStdio - + + @@ -67,8 +94,12 @@

    SpaceOS 6

    -

    这个项目已停止开发,本页仅作存档

    -

    不再维护,不接受 issue、功能请求或移植,请不要基于它继续投入。目前在维护的是 PySpOS 和 SpaceOS 9;PySpOS 的代码在 ViudiraTech/PySpOS。

    + +
    +

    这个项目已停止开发,本页仅作存档

    +

    不再维护,不接受 issue、功能请求或移植,请不要基于它继续投入。目前在维护的是 PySpOS 和 SpaceOS 9;PySpOS 的代码在 ViudiraTech/PySpOS。

    + +
    @@ -158,7 +189,7 @@ - + diff --git a/docs/spaceos7.html b/docs/spaceos7.html index 55db170..d4e10c2 100644 --- a/docs/spaceos7.html +++ b/docs/spaceos7.html @@ -7,43 +7,70 @@ SpaceOS 7(已停更) | GoutouStdio - + + @@ -65,8 +92,12 @@

    SpaceOS 7

    -

    这个项目已停止开发,本页仅作存档

    -

    不再维护,不接受 issue、功能请求或移植,请不要基于它继续投入。目前在维护的是 PySpOS 和 SpaceOS 9;PySpOS 的代码在 ViudiraTech/PySpOS。

    + +
    +

    这个项目已停止开发,本页仅作存档

    +

    不再维护,不接受 issue、功能请求或移植,请不要基于它继续投入。目前在维护的是 PySpOS 和 SpaceOS 9;PySpOS 的代码在 ViudiraTech/PySpOS。

    + +
    @@ -167,7 +198,7 @@ - + diff --git a/docs/spaceos8-download.html b/docs/spaceos8-download.html index c0aa496..dafefe4 100644 --- a/docs/spaceos8-download.html +++ b/docs/spaceos8-download.html @@ -7,43 +7,70 @@ 下载 SpaceOS 8 | GoutouStdio - + + @@ -55,21 +82,50 @@

    下载 SpaceOS 8

    第二版公开测试镜像,修复了 xHCI 控制器上的 USB HID,USB 键盘和鼠标可以使用。下载前请读使用声明,下载后核对 SHA-256。

    -
    +
    +
    +
      +
    1. +
      1
      +

      下载第二版

      +

      39.7 MiB 的 ISO,精简掉了一部分 Linux 应用。

      + 镜像信息与校验值 +
    2. +
    3. +
      2
      +

      核对 SHA-256

      +

      用 sha256sum 或 Get-FileHash 对比本页公布的值。

      + 校验命令 +
    4. +
    5. +
      3
      +

      写入测试盘或挂给虚拟机

      +

      只在可抛弃的环境里使用,先读使用声明。

      + 使用声明 +
    6. +
    +
    +
    + +

    镜像信息

    -

    实验版本,不作担保

    -

    按“现状”提供。下载即表示你自行承担全部风险,只能在虚拟机、测试机或可抛弃的磁盘上使用。

    + +
    +

    实验版本,不作担保

    +

    按“现状”提供。下载即表示你自行承担全部风险,只能在虚拟机、测试机或可抛弃的磁盘上使用。

    +
    +

    默认下载第二版。第一版镜像继续保留,只用于对照。镜像是可启动的 ISO,精简掉了一部分 Linux 应用。

    @@ -89,13 +145,13 @@

    校验

    -
    +

    版本记录

    - + @@ -116,7 +172,7 @@

    版本记录

    -
    +

    使用声明

    @@ -129,7 +185,7 @@

    使用声明

  • 版本识别与反馈。请用本页公布的 SHA-256 确认镜像后再使用。反馈是自愿的,请不要提交个人数据;是否采纳、回复或修复,均不作承诺。
  • @@ -183,7 +239,7 @@
    - + diff --git a/docs/spaceos8.html b/docs/spaceos8.html index 56bc954..8b03481 100644 --- a/docs/spaceos8.html +++ b/docs/spaceos8.html @@ -7,43 +7,70 @@ SpaceOS 8 | GoutouStdio - + + @@ -56,7 +83,7 @@

    SpaceOS 8

    内核是 C 写的 UNIX-like 内核 Uinxed-Kernel,用户态是一套自研的桌面和系统程序,包括窗口合成器、浏览器和文件管理器。第二版 slim 镜像修好了 xHCI 上的 USB HID,USB 键盘和鼠标现在可以用;第一版里它们插上没有反应。

    @@ -72,16 +99,43 @@

    SpaceOS 8

    -
    +
    +
      +
    • 自研用户态

      桌面、合成器、浏览器和系统程序,约 29.2 万行。

    • +
    • X11 兼容层

      120 个核心协议请求,能运行 DOOM 这类图形程序。

    • +
    • Uinxed 内核

      C 写的 UNIX-like 内核,实现 Linux 6.12 系统调用 ABI。

    • +
    • 实体机验证

      已在 Dell PowerEdge R410 等实体服务器上启动。

    • +
    -

    抢先体验版,不是正式 release

    -

    内核已在实体服务器上启动,桌面能运行,也能跑 OpenJDK 和 DOOM 这类现成的 Linux 软件。图形和部分 ABI 还在补,所以只叫抢先体验。

    + +
    +

    抢先体验版,不是正式 release

    +

    内核已在实体服务器上启动,桌面能运行,也能跑 OpenJDK 和 DOOM 这类现成的 Linux 软件。图形和部分 ABI 还在补,所以只叫抢先体验。

    + +
    +
    +
    +
    + +
    +
    +

    系统结构

    +
    +

    从上到下是各层的职责;虚线是用户态和内核之间的系统调用接口。

    +
      +
    1. SPUI 桌面与应用compositor · browser · terminal · filemgr · settings 等
    2. +
    3. X11 兼容层 · VortexGlassLinux 图形软件与窗口主题
    4. +
    5. libc · libgfx · imgui自研的 C 库、图形库和 GUI 工具包
    6. +
    7. Linux 6.12 系统调用 ABI编号 0–462
    8. +
    9. Uinxed-KernelEEVDF 调度 · 内存 · VFS · 网络 · 驱动
    10. +
    11. Limine 引导UEFI 与 Legacy 双模
    12. +
    -
    +

    规模

    @@ -90,10 +144,10 @@

    规模

    - - - - + + + + @@ -102,7 +156,7 @@

    规模

    -
    +

    现成软件的运行情况

    @@ -113,9 +167,9 @@

    现成软件的运行情况

    - - - + + +
    版本日期说明下载
    版本日期说明下载
    部分规模说明
    用户态约 29.2 万行SPUI 桌面、合成器、浏览器和系统程序,全部自研。
    内核约 18.1 万行C 写的 UNIX-like 单体内核,449 个 C/H 文件。
    图形界面约 3.4 万行合成器和自研图形库 libgfx。
    浏览器约 2.4 万行纯 C 的 UxHtml 引擎,带 JavaScript 引擎。
    用户态约 29.2 万行SPUI 桌面、合成器、浏览器和系统程序,全部自研。
    内核约 18.1 万行C 写的 UNIX-like 单体内核,449 个 C/H 文件。
    图形界面约 3.4 万行合成器和自研图形库 libgfx。
    浏览器约 2.4 万行纯 C 的 UxHtml 引擎,带 JavaScript 引擎。
    系统调用编号 0–462Linux 6.12 x86-64 的系统调用编号。
    版本 / 许可1.0.0-alpha.1内核仓库的许可是 Apache-2.0。
    程序状态备注
    OpenJDK能运行为它重写了信号处理、TSS / SMP / APIC 和中断路径,并修了 VFS 与页管理。JVM 的 GC 线程、线程挂起和内存映射都依赖这些地方行为正确。
    DOOM能运行经自研的 X11 兼容层运行。需要键盘、鼠标、连续动画帧、音频和稳定的显示通路。
    systemd初步跑通systemd 一启动就探测大量可选的 sysctl、挂载点和命名空间接口,任何一处行为不符都会起不来。为此补了 Cgroup v2 和完整的 Linux 命名空间支持。
    OpenJDK能运行为它重写了信号处理、TSS / SMP / APIC 和中断路径,并修了 VFS 与页管理。JVM 的 GC 线程、线程挂起和内存映射都依赖这些地方行为正确。
    DOOM能运行经自研的 X11 兼容层运行。需要键盘、鼠标、连续动画帧、音频和稳定的显示通路。
    systemd初步跑通systemd 一启动就探测大量可选的 sysctl、挂载点和命名空间接口,任何一处行为不符都会起不来。为此补了 Cgroup v2 和完整的 Linux 命名空间支持。
    Minecraft团队实测需要内核扛住真实 JVM 的内存管理、GC 线程调度、mmap 和 futex 行为。运行环境见页首截图。
    @@ -124,7 +178,7 @@

    现成软件的运行情况

    -
    +

    X11 兼容层与窗口主题

      @@ -134,7 +188,7 @@

      X11 兼容层与窗口主题

    -
    +

    用户态与桌面

    @@ -153,21 +207,21 @@

    应用

    程序作用行数 - compositor窗口合成器:DRM/KMS、损伤跟踪、Xcursor、窗口装饰12,320 - browser浏览器,含 UxHtml 渲染引擎与 JS 引擎25,713 - libgfx自研图形库与控件库21,785 - settings系统设置3,064 - terminal终端仿真器2,869 - oobe首次开机向导2,137 - editor文本编辑器1,637 - displaymgr显示管理器1,489 - filemgr文件管理器1,347 - sysmon活动监视器1,267 - initPID 1 服务管理器1,262 - uxconfd配置守护进程873 - netmgrd网络管理器761 - escalate提权通道685 - calc计算器388 + compositor窗口合成器:DRM/KMS、损伤跟踪、Xcursor、窗口装饰12,320 + browser浏览器,含 UxHtml 渲染引擎与 JS 引擎25,713 + libgfx自研图形库与控件库21,785 + settings系统设置3,064 + terminal终端仿真器2,869 + oobe首次开机向导2,137 + editor文本编辑器1,637 + displaymgr显示管理器1,489 + filemgr文件管理器1,347 + sysmon活动监视器1,267 + initPID 1 服务管理器1,262 + uxconfd配置守护进程873 + netmgrd网络管理器761 + escalate提权通道685 + calc计算器388
    @@ -175,7 +229,7 @@

    应用

    -
    +

    Uinxed-Kernel

    @@ -196,14 +250,18 @@

    Uinxed-Kernel

    -
    +

    当前状态

    -

    实验性系统,不要用重要数据冒险

    -

    内核版本串是 Uinxed 1.0.0-alpha.1。请用可抛弃的机器和测试盘。

    + +
    +

    实验性系统,不要用重要数据冒险

    +

    内核版本串是 Uinxed 1.0.0-alpha.1。请用可抛弃的机器和测试盘。

    +
    +

    已经跑通

    • 内核在实体服务器上启动,已验证 Dell PowerEdge R410 等机器。
    • @@ -224,7 +282,7 @@

      还在做

    -
    +

    构建与运行

    @@ -285,7 +343,7 @@
    - + diff --git a/docs/spaceos9-download.html b/docs/spaceos9-download.html index 6ebbf2c..cd82948 100644 --- a/docs/spaceos9-download.html +++ b/docs/spaceos9-download.html @@ -7,43 +7,70 @@ 下载 SpaceOS 9 | GoutouStdio - + + @@ -55,21 +82,50 @@

    下载 SpaceOS 9

    x86_64 的可启动 ISO,包含 SpaceKernel 3.0、FAT32 根盘、systemg(PID 1)、splibc 和可交互的 BusyBox ash。下载前请读使用声明,下载后核对 SHA-256。

    -
    +
    +
    +
      +
    1. +
      1
      +

      下载镜像

      +

      69.8 MiB 的 ISO,托管在 GitHub Release。

      + 镜像信息与校验值 +
    2. +
    3. +
      2
      +

      核对 SHA-256

      +

      用 sha256sum 或 Get-FileHash 对比本页公布的值。

      + 校验命令 +
    4. +
    5. +
      3
      +

      在 QEMU / UEFI 上启动

      +

      推荐 Q35 机型,至少 512 MiB 内存。

      + 启动命令 +
    6. +
    +
    +
    + +

    镜像信息

    -

    开发预览,不作担保

    -

    按“现状”提供。下载即表示你自行承担全部风险,只能在虚拟机、测试机或可抛弃的磁盘上使用。不要在主力设备或唯一的数据副本上运行。

    + +
    +

    开发预览,不作担保

    +

    按“现状”提供。下载即表示你自行承担全部风险,只能在虚拟机、测试机或可抛弃的磁盘上使用。不要在主力设备或唯一的数据副本上运行。

    +
    +
    @@ -89,7 +145,7 @@

    校验

    -
    +

    在 QEMU / UEFI 上启动

    @@ -104,7 +160,7 @@

    在 QEMU / UEFI 上启动

    -
    +

    使用声明

    @@ -116,13 +172,13 @@

    使用声明

  • 版本识别与反馈。请用本页公布的 SHA-256 确认镜像后再使用。反馈请提交到 SpaceOS-9 issue tracker;是否采纳或修复,不作承诺。
  • -
    +

    第三方组件

    镜像包含 BusyBox、musl、Limine 等 GPL / MIT / BSD 许可的第三方组件。完整许可、版本、校验值和源码获取方式见 THIRD_PARTY_NOTICES.md。

    @@ -176,7 +232,7 @@
    - + diff --git a/docs/spaceos9.html b/docs/spaceos9.html index 228aac5..23cca39 100644 --- a/docs/spaceos9.html +++ b/docs/spaceos9.html @@ -7,43 +7,70 @@ SpaceOS 9 | GoutouStdio - + + @@ -56,7 +83,7 @@

    SpaceOS 9

    内核是 Rust 写的 SpaceKernel 3.0,实现了 Linux 64 位 ABI,目标是让现成的 Linux 程序直接运行。目前验证过的是 musl 动态链接的 BusyBox。镜像是 x86_64 的可启动 ISO。

    @@ -72,16 +99,42 @@

    SpaceOS 9

    -
    +
    +
      +
    • Rust 内核

      SpaceKernel 3.0,soft-float,x86_64 优先。

    • +
    • Linux ABI

      ELF / PIE / 动态链接、信号、futex、epoll。

    • +
    • FAT32 根盘

      由 Limine 模块提供,只读挂载。

    • +
    • BusyBox ash

      musl 动态链接,带作业控制和 Ctrl-C。

    • +
    -

    这是公开预览

    -

    内核自测、三个架构的编译检查和 QEMU 启动已经通过;用户态和驱动覆盖还在补。下载前请读使用声明。

    + +
    +

    这是公开预览

    +

    内核自测、三个架构的编译检查和 QEMU 启动已经通过;用户态和驱动覆盖还在补。下载前请读使用声明。

    + +
    +
    +
    +
    + +
    +
    +
    +

    启动顺序

    +

    在 QEMU / UEFI 上的启动流程,每一步对应镜像里的一个组件。

    +
      +
    1. 1

      UEFI 固件

      QEMU 里由 OVMF 提供,从 ISO 启动引导程序。

    2. +
    3. 2

      Limine

      引导内核,并把 FAT32 的 rootfs 作为模块交给它。

    4. +
    5. 3

      SpaceKernel 3.0

      初始化后只读挂载根盘,再启动 PID 1。

    6. +
    7. 4

      systemg

      作为 PID 1,按依赖顺序启动 .service 里定义的服务。

    8. +
    9. 5

      ash

      控制台 shell。退出后由 systemg 重新拉起。

    10. +
    -
    +

    组成

    @@ -102,7 +155,7 @@

    组成

    -
    +

    这一版新增的部分

      @@ -114,7 +167,7 @@

      这一版新增的部分

    -
    +

    验证情况

    @@ -123,22 +176,22 @@

    验证情况

    - - - + + +
    范围状态内容
    x86_64已验证UEFI/QEMU 启动、systemg 作 PID 1、BusyBox 动态加载、ash 交互、uname / id / nproc / ls / cat、VFS dcache 自测、SELFTEST_OK,以及三个架构的 cargo check。
    aarch64 / riscv64仅编译检查内核能通过编译检查。用户态、rootfs 和启动链路没有在这个镜像里验证。
    真实硬件与 GPU未验证目前只在 QEMU 的 VirtIO GPU 2D 上验证。真实 GPU、音频、网络、睡眠唤醒不在这个镜像的承诺范围内。
    x86_64已验证UEFI/QEMU 启动、systemg 作 PID 1、BusyBox 动态加载、ash 交互、uname / id / nproc / ls / cat、VFS dcache 自测、SELFTEST_OK,以及三个架构的 cargo check。
    aarch64 / riscv64仅编译检查内核能通过编译检查。用户态、rootfs 和启动链路没有在这个镜像里验证。
    真实硬件与 GPU未验证目前只在 QEMU 的 VirtIO GPU 2D 上验证。真实 GPU、音频、网络、睡眠唤醒不在这个镜像的承诺范围内。
    -
    +

    源码与许可

    SpaceOS 9 的源码在 ViudiraTech/SpaceOS-9。镜像里包含 BusyBox、musl、Limine 等第三方组件,各自遵循自己的许可证,许可与源码获取方式见下载页和 THIRD_PARTY_NOTICES.md。

    @@ -192,7 +245,7 @@
    - + diff --git a/tools/checks/check_docs_html.py b/tools/checks/check_docs_html.py index 68ea83c..c740fba 100644 --- a/tools/checks/check_docs_html.py +++ b/tools/checks/check_docs_html.py @@ -36,6 +36,7 @@ def __init__(self): self.errs = [] self.links = [] self.ids = set() + self.uses = [] # Record ids and link targets, and push every non-void tag onto the stack. def handle_starttag(self, tag, attrs): @@ -44,6 +45,8 @@ def handle_starttag(self, tag, attrs): self.ids.add(d["id"]) if tag == "a" and "href" in d: self.links.append(d["href"]) + if tag == "use" and d.get("href", "").startswith("#"): + self.uses.append(d["href"][1:]) if tag == "link" and d.get("rel") == "stylesheet" and "href" in d: self.links.append(d["href"]) if tag == "script" and d.get("src"): @@ -72,6 +75,9 @@ def check_page(path): c.errs.append("未闭合: " + ", ".join(f"<{t}>(L{p[0]})" for t, p in c.stack)) + for ref in sorted(set(c.uses) - c.ids): + c.errs.append(f"图标不存在: #{ref}(sprite 里没有这个 symbol)") + base = os.path.dirname(path) for href in c.links: if href.startswith(("http://", "https://", "mailto:", "data:", "#")): diff --git a/tools/sync_docs_chrome.py b/tools/sync_docs_chrome.py index a188d54..447a31e 100644 --- a/tools/sync_docs_chrome.py +++ b/tools/sync_docs_chrome.py @@ -36,17 +36,18 @@ ("配置要求", "requirements.html"), ] -# Drop-down menus in the header, shown after the plain links. (label, [(text, page)]) +# Drop-down menus in the header, shown after the plain links. (label, [(text, page, icon)]) +# The icons match the product glyphs used on the home page: terminal, chip and window. HEADER_MENUS = [ ("下载", [ - ("PySpOS 更新包", "ota/index.html"), - ("PySpOS 版本历史", "ota/releases.html"), - ("SpaceOS 9 镜像", "spaceos9-download.html"), - ("SpaceOS 8 镜像", "spaceos8-download.html"), + ("PySpOS 更新包", "ota/index.html", "terminal"), + ("PySpOS 版本历史", "ota/releases.html", "clock"), + ("SpaceOS 9 镜像", "spaceos9-download.html", "chip"), + ("SpaceOS 8 镜像", "spaceos8-download.html", "window"), ]), ("存档", [ - ("SpaceOS 7", "spaceos7.html"), - ("SpaceOS 6", "spaceos6.html"), + ("SpaceOS 7", "spaceos7.html", "archive"), + ("SpaceOS 6", "spaceos6.html", "archive"), ]), ] @@ -81,6 +82,41 @@ "fill='%23faf9f5' font-family='Georgia,serif'%3EG%3C/text%3E%3C/svg%3E" ) + +# Line icons, 24x24, drawn for this site. Pages use them as . +# Stroke, fill and size come from CSS (.icon), so one set works in both themes. +ICONS = { + "check": '', + "alert": '', + "info": '', + "download": '', + "terminal": '', + "chip": '' + '', + "window": '', + "layers": '', + "fork": '' + '', + "clock": '', + "code": '', + "swap": '', + "plug": '', + "disk": '', + "server": '' + '', + "archive": '' + '', + "mail": '', + "shield": '', + "play": '', + "chevron": '', + "external": '', + "sun": '', + "moon": '', + "menu": '', + "close": '', +} + BLOCKS = ("head", "chrome", "foot") @@ -115,6 +151,21 @@ def render_link(page, text, target): return f'{escape(text)}' +# One inline icon that references the sprite. +def icon(name, extra=""): + cls = f"icon {extra}".strip() + return f'' + + +# The brand mark: three stacked layers, the same picture as the home page illustration. +BRAND_MARK = ( + '' +) + + # Render the stylesheet links and favicon for one page. def render_head(page): root = root_prefix(page) @@ -131,36 +182,49 @@ def render_menu(page): for text, target in HEADER_LINKS: out.append(f"
  • {render_link(page, text, target)}
  • ") for label, items in HEADER_MENUS: - current = " is-current" if any(t == page for _x, t in items) else "" - out.append(f'