concept-atlas-dense-explain 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +12 -3
- package/skill/SKILL.md +84 -59
- package/skill/assets/template/content/compile-runtime.mdx +158 -158
- package/skill/assets/template/index.html +16 -16
- package/skill/assets/template/package.json +20 -20
- package/skill/assets/template/scripts/build.mjs +37 -37
- package/skill/assets/template/scripts/clean-temp.mjs +27 -27
- package/skill/assets/template/src/app/App.jsx +239 -239
- package/skill/assets/template/src/components/MDXComponents.jsx +503 -477
- package/skill/assets/template/src/components/index.js +1 -1
- package/skill/assets/template/src/main.jsx +16 -16
- package/skill/assets/template/src/model/concept-schema.js +169 -169
- package/skill/assets/template/src/model/normalize-content.js +241 -236
- package/skill/assets/template/src/model/relation-types.js +90 -90
- package/skill/assets/template/src/styles/concept-explain.css +290 -9
- package/skill/assets/template/src/views/NodeExplorer.jsx +59 -20
- package/skill/assets/template/src/views/RelationGraph.jsx +16 -1
- package/skill/assets/template/vite.config.js +21 -21
- package/skill/references/components.md +74 -64
- package/skill/references/prompting.md +77 -77
package/package.json
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "concept-atlas-dense-explain",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Portable dense-explanation skill and MDX concept atlas template",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"concept-atlas-dense-explain": "bin/install.mjs"
|
|
8
8
|
},
|
|
9
|
-
"files": [
|
|
10
|
-
|
|
9
|
+
"files": [
|
|
10
|
+
"bin",
|
|
11
|
+
"skill"
|
|
12
|
+
],
|
|
13
|
+
"keywords": [
|
|
14
|
+
"codex",
|
|
15
|
+
"skill",
|
|
16
|
+
"mdx",
|
|
17
|
+
"dense-explain",
|
|
18
|
+
"concept-map"
|
|
19
|
+
],
|
|
11
20
|
"license": "MIT"
|
|
12
21
|
}
|
package/skill/SKILL.md
CHANGED
|
@@ -1,15 +1,31 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: concept-atlas-dense-explain
|
|
3
|
-
description: Build
|
|
4
|
-
---
|
|
1
|
+
---
|
|
2
|
+
name: concept-atlas-dense-explain
|
|
3
|
+
description: Build structured explanation webpages with the bundled React/Vite/MDX components. Use this skill whenever the user asks for a technical explanation, concept map, layered knowledge page, interactive explanation, component-based knowledge page, or webpage resembling the Concept Atlas exemplar. Before generating anything, ask whether the user wants (A) a scrollable long-form page assembled from semantic components or (B) the full Concept Atlas interactive framework with concept navigation and relation graph. Do not choose the output mode silently.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Concept Atlas Dense Explain
|
|
7
|
+
|
|
8
|
+
This is an Agent Skills-compatible skill. Keep the instructions and generated content portable across Claude Code, Codex, Cursor, Gemini CLI, OpenCode, Cline, GitHub Copilot, and other agents that support `SKILL.md`.
|
|
9
|
+
|
|
10
|
+
Use the bundled components and, when selected, the complete template to turn knowledge into a structured explanation. The required deliverable is a built webpage, normally `dist/index.html`; it may be a scrollable component page or a full interactive Concept Atlas.
|
|
5
11
|
|
|
6
|
-
|
|
12
|
+
## Mandatory mode selection
|
|
7
13
|
|
|
8
|
-
|
|
14
|
+
Before writing content, determine the output mode. If the user has not already chosen one, ask exactly one concise clarification:
|
|
9
15
|
|
|
10
|
-
|
|
16
|
+
> 你希望生成哪种形式?A. 使用语义组件组装的滚动型讲解网页;B. 使用完整 Concept Atlas 框架的交互式网页(概念树、节点下钻、关系图)。如果没有偏好,我推荐 B。
|
|
11
17
|
|
|
12
|
-
|
|
18
|
+
Do not start implementation until the user chooses A or B. If the user explicitly requests both, create separate outputs only when the workspace and scope support them.
|
|
19
|
+
|
|
20
|
+
### Mode A — Scrollable component page
|
|
21
|
+
|
|
22
|
+
Use the existing React/Vite shell and compose the page from supported semantic and presentation components. A natural vertical reading layout is valid in this mode. It does not require a 15–25 node concept graph or relation graph unless the user asks for those features. Keep content semantic and avoid handwritten CSS, SVG, or replacement app code.
|
|
23
|
+
|
|
24
|
+
### Mode B — Interactive Concept Atlas
|
|
25
|
+
|
|
26
|
+
Use the complete bundled template. The page must contain one `L0` root, multiple `L1` branches, lower-level nodes where useful, `Children` / `ConceptRef` navigation, and labeled cross-branch `Relation`s. The template provides the three-column node explorer, graph view, search, filters, URL node state, keyboard navigation, and responsive behavior.
|
|
27
|
+
|
|
28
|
+
## Mandatory preflight and mode-specific fallback rule
|
|
13
29
|
|
|
14
30
|
Before generating content, resolve the directory containing this `SKILL.md` and verify that these bundled files are readable:
|
|
15
31
|
|
|
@@ -19,55 +35,64 @@ Before generating content, resolve the directory containing this `SKILL.md` and
|
|
|
19
35
|
- `assets/template/src/model/normalize-content.js`
|
|
20
36
|
- `references/components.md`
|
|
21
37
|
|
|
22
|
-
Read the
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
## Step 0 — Read the exemplar before writing
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
- 1 `L0` root, ~5 `L1` branches, 2–3 children per branch, descending to `L3`/`L4` where the topic deserves it.
|
|
31
|
-
- Every `title` is a claim ("ABI 破坏:能链接,不等于能调用"), and every `summary` is a one-sentence judgment.
|
|
32
|
-
- Important nodes carry 3–6 semantic components, not one lone paragraph.
|
|
33
|
-
- Claims are backed by concrete commands, numbers, or named artifacts (`readelf -Ws`, `nm -C`, `objdump -dr`, `.bss`, ASLR).
|
|
34
|
-
- Cross-branch meaning is encoded as labeled `Relation`s, not prose.
|
|
35
|
-
|
|
36
|
-
## Workflow
|
|
37
|
-
|
|
38
|
-
1.
|
|
39
|
-
2. Read
|
|
40
|
-
3.
|
|
41
|
-
4.
|
|
42
|
-
5.
|
|
43
|
-
6. Run the
|
|
44
|
-
7.
|
|
45
|
-
|
|
46
|
-
##
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
-
|
|
51
|
-
-
|
|
52
|
-
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
-
|
|
60
|
-
-
|
|
61
|
-
-
|
|
62
|
-
-
|
|
63
|
-
-
|
|
38
|
+
Read the component contract before writing. For Mode B, also read the exemplar and verify the complete template. If the bundled template is unavailable, report that Mode B cannot be completed and offer Mode A only after the user agrees. Never silently downgrade Mode B to a long page or custom mockup.
|
|
39
|
+
|
|
40
|
+
For Mode B, the template is the implementation boundary: do not edit `src/`, styles, `index.html`, Vite configuration, or package dependencies for a content task; replace only the MDX content after copying the template. For Mode A, use the host project's existing shell and do not introduce a replacement application unless requested.
|
|
41
|
+
|
|
42
|
+
## Step 0 — Read the exemplar before writing Mode B content
|
|
43
|
+
|
|
44
|
+
For Mode B, read [assets/template/content/compile-runtime.mdx](assets/template/content/compile-runtime.mdx) in full first. It is the **reference standard**, not just a file to overwrite. Study its shape before generating anything:
|
|
45
|
+
|
|
46
|
+
- 1 `L0` root, ~5 `L1` branches, 2–3 children per branch, descending to `L3`/`L4` where the topic deserves it.
|
|
47
|
+
- Every `title` is a claim ("ABI 破坏:能链接,不等于能调用"), and every `summary` is a one-sentence judgment.
|
|
48
|
+
- Important nodes carry 3–6 semantic components, not one lone paragraph.
|
|
49
|
+
- Claims are backed by concrete commands, numbers, or named artifacts (`readelf -Ws`, `nm -C`, `objdump -dr`, `.bss`, ASLR).
|
|
50
|
+
- Cross-branch meaning is encoded as labeled `Relation`s, not prose.
|
|
51
|
+
|
|
52
|
+
## Workflow
|
|
53
|
+
|
|
54
|
+
1. Ask for and record Mode A or Mode B before implementation.
|
|
55
|
+
2. Read [references/components.md](references/components.md); for Mode B, resolve and copy the complete `assets/template` directory and read the exemplar first.
|
|
56
|
+
3. Mode A: create the requested scrollable content using semantic components and the existing shell. Mode B: replace only the template content MDX, preserving React, CSS, graph, and build files.
|
|
57
|
+
4. Mode B: model one `L0` root, then `L1` structure, `L2` mechanisms, and optional `L3/L4` boundaries or failures. Add `parent`/`Children` and labeled cross-branch `Relation`s.
|
|
58
|
+
5. In either mode, keep content semantic: do not encode layout, coordinates, CSS, or SVG in MDX. Use supported model and presentation components where they clarify structure.
|
|
59
|
+
6. Run the relevant validator, then `npm install` and `npm run build`. If validation or build fails, revise the content rather than returning an unverified substitute.
|
|
60
|
+
7. Mode B: verify node switching, graph mode, search, URL `#node=...`, keyboard navigation, and responsive layout. Return the built output path and state which mode was used.
|
|
61
|
+
|
|
62
|
+
## Delivery summary
|
|
63
|
+
|
|
64
|
+
After generation, briefly explain:
|
|
65
|
+
|
|
66
|
+
- which mode the user selected (`A` scrollable component page or `B` interactive Concept Atlas);
|
|
67
|
+
- what the skill contributed (semantic components, concept tree, relations, or template interactions);
|
|
68
|
+
- the output path and the main ways to inspect or continue editing it.
|
|
69
|
+
|
|
70
|
+
Keep this summary concise. Do not merely list files or claim interactive features that were not built.
|
|
71
|
+
|
|
72
|
+
## Content rules
|
|
73
|
+
|
|
74
|
+
- Start with a one- or two-sentence core judgment.
|
|
75
|
+
- Use tables/flows for comparison and causality; use short paragraphs only for explanation.
|
|
76
|
+
- Every dense block should contain a conclusion, evidence, or limitation.
|
|
77
|
+
- Prefer 2–4 columns on wide screens and natural stacking on narrow screens.
|
|
78
|
+
- Do not invent unsupported components or relation types. Read [references/components.md](references/components.md) for the supported semantic API.
|
|
79
|
+
- Mode B should aim for the exemplar's scale: roughly 1 root, 4–5 `L1` branches, ~15–25 nodes total. A thin graph is a failure in Mode B, but is not a requirement for Mode A.
|
|
80
|
+
|
|
81
|
+
## Self-check before finishing
|
|
82
|
+
|
|
83
|
+
Run this checklist and revise until every item passes. If an item fails, fix the content instead of adding decoration.
|
|
84
|
+
|
|
85
|
+
- [ ] The user selected Mode A or Mode B before implementation.
|
|
86
|
+
- [ ] Every key section or node has a claim, summary, or clear reading purpose.
|
|
87
|
+
- [ ] Mode B has one `L0`, multiple `L1`s, useful depth, concrete evidence, and labeled whitelisted relations.
|
|
88
|
+
- [ ] First screen shows the core claim plus 3–5 key facts; long detail lives in `Details` / `Tabs` when appropriate.
|
|
64
89
|
- [ ] No CSS, coordinates, SVG, or layout instructions appear in the MDX.
|
|
65
|
-
- [ ]
|
|
66
|
-
- [ ] The
|
|
67
|
-
- [ ]
|
|
68
|
-
|
|
69
|
-
## Portable template
|
|
70
|
-
|
|
71
|
-
The self-contained React/Vite/MDX implementation is in [assets/template](assets/template).
|
|
72
|
-
|
|
73
|
-
For the component contract, relation whitelist, and level semantics, read [references/components.md](references/components.md). For the exemplar breakdown, density targets, and prompt wording, read [references/prompting.md](references/prompting.md).
|
|
90
|
+
- [ ] Mode B changes only the template's MDX content; no replacement JSX or custom vertical article page was created.
|
|
91
|
+
- [ ] The relevant validator passes before the build.
|
|
92
|
+
- [ ] Mode B builds and node switching, graph mode, search, `#node=...`, and keyboard navigation all work.
|
|
93
|
+
|
|
94
|
+
## Portable template
|
|
95
|
+
|
|
96
|
+
The self-contained React/Vite/MDX implementation is in [assets/template](assets/template). It is required for Mode B and optional for Mode A when the host project already provides an equivalent shell. For Mode B, copy it into a project, replace `content/compile-runtime.mdx` **after studying it**, run `npm install`, then `npm run build`. The template has no dependency on the source repository's absolute paths.
|
|
97
|
+
|
|
98
|
+
For the component contract, relation whitelist, and level semantics, read [references/components.md](references/components.md). For the exemplar breakdown, density targets, and prompt wording, read [references/prompting.md](references/prompting.md).
|
|
@@ -1,158 +1,158 @@
|
|
|
1
|
-
<ExplainPage id="compiler-runtime" title="程序如何变成一次可观察的运行" summary="从意图、工具链与操作系统契约出发,追踪程序如何获得身份、地址、时间与副作用。" layout="editorial" density="reading">
|
|
2
|
-
<ConceptGraph root="execution-system">
|
|
3
|
-
<ConceptNode id="execution-system" title="执行系统:从意图到副作用" level="L0" input="源码、工具链与机器" output="行为、资源变化与退出状态" summary="把编译与运行看成跨层契约,而不是只有编译器参与的流水线。">
|
|
4
|
-
<Definition>“运行起来”同时意味着语义被解释、依赖被绑定、地址被授予、时间被调度、结果被暴露。任何一层契约破裂,都可能表现为构建失败、启动失败、性能退化或悄无声息的错误。</Definition>
|
|
5
|
-
<Prerequisite>先掌握源代码、进程、虚拟地址和文件描述符四个概念。</Prerequisite>
|
|
6
|
-
<LearningObjectives items={['区分构建、装载与执行阶段', '为每个阶段找到可验证证据', '从首个错误点缩小故障边界']} />
|
|
7
|
-
<KeyQuestion>为什么“编译成功”仍然不能保证程序能启动?</KeyQuestion>
|
|
8
|
-
<Input>源码快照、目标三元组、编译器版本、依赖锁文件、配置与凭据。</Input>
|
|
9
|
-
<Output>可执行映像、进程地址空间、系统调用轨迹、标准输出与退出码。</Output>
|
|
10
|
-
<Callout type="info" title="阅读地图">沿着“意图 → 表示 → 身份 → 地址 → 时间 → 副作用”下钻;每个节点都给出可观测证据,方便把概念变成排障动作。</Callout>
|
|
11
|
-
<Tabs items={[{label:'工程视角',content:'可重复构建、发布产物、启动延迟与回滚。'},{label:'机器视角',content:'指令、页表、缓存一致性与异常入口。'},{label:'运维视角',content:'日志、指标、追踪、信号与资源上限。'}]} />
|
|
12
|
-
<Children><ConceptRef id="intent" /><ConceptRef id="toolchain" /><ConceptRef id="identity" /><ConceptRef id="address-space" /><ConceptRef id="effects" /></Children>
|
|
13
|
-
</ConceptNode>
|
|
14
|
-
|
|
15
|
-
<ConceptNode id="intent" title="意图与源代码" level="L1" parent="execution-system" input="需求、算法与接口" output="工具链可消费的文本与资源" summary="源代码既是给人看的设计,也是后续每个阶段必须兑现的承诺。">
|
|
16
|
-
<Definition>源文件、宏、生成代码和资源文件共同构成输入;真正的边界由构建系统决定,而不是某个文件扩展名。</Definition>
|
|
17
|
-
<Input>版本提交、编译条件、代码生成器输出、环境变量和平台配置。</Input>
|
|
18
|
-
<Output>确定的源快照与可追溯构建元数据。</Output>
|
|
19
|
-
<Example title="同一提交却得到不同二进制">时间戳宏、未锁定依赖、随机临时目录或本地路径进入产物后,字节比较会失败;先固定输入,再讨论优化。</Example>
|
|
20
|
-
<Glossary term="可重复构建">相同源快照、工具链和外部输入应产生等价产物;等价可以是字节相同,也可以是行为相同。</Glossary>
|
|
21
|
-
<Children><ConceptRef id="preprocess" /><ConceptRef id="reproducibility" /></Children>
|
|
22
|
-
</ConceptNode>
|
|
23
|
-
<ConceptNode id="preprocess" title="预处理与语法树" level="L2" parent="intent" input="字符、宏与包含路径" output="Token 流、AST 与源位置" summary="工具链先决定哪些文本存在,以及它们如何组成结构。">
|
|
24
|
-
<Definition>预处理器展开宏和条件分支;词法分析切分 Token;解析器建立 AST。源位置映射影响诊断、调试和覆盖率。</Definition>
|
|
25
|
-
<Details summary="为什么一个括号错误会拖垮整份文件?">解析器需要在错误位置恢复;同步点不足时,后续 Token 会连锁误判。高质量诊断还要给出恢复后的上下文。</Details>
|
|
26
|
-
<Example title="条件编译的隐藏分支">同一文件在 debug、asan、arm64 配置下可能拥有三棵不同 AST;只评审默认配置并不足够。</Example>
|
|
27
|
-
<Children><ConceptRef id="semantic-contract" /><ConceptRef id="source-maps" /></Children>
|
|
28
|
-
</ConceptNode>
|
|
29
|
-
<ConceptNode id="semantic-contract" title="类型、借用与未定义行为" level="L3" parent="preprocess" input="AST、符号表与语言规则" output="带约束的 IR 或诊断" summary="语义阶段决定哪些操作被语言承诺,哪些被禁止或留给实现。">
|
|
30
|
-
<Definition>类型检查验证值的形状与操作集合;所有权/借用还验证别名与生命周期。越过约束后,编译器可能基于“不会发生”进行变换。</Definition>
|
|
31
|
-
<Callout type="warn" title="契约的反面">一次构建恰好得到的结果不是规范。越界、数据竞争或严格别名违规可能在换优化级别或 CPU 后改变表现。</Callout>
|
|
32
|
-
<Glossary term="IR">连接语言语义与目标指令的中间表示,常包含控制流图、SSA 值和内存操作。</Glossary>
|
|
33
|
-
</ConceptNode>
|
|
34
|
-
<ConceptNode id="source-maps" title="调试信息与可观测映射" level="L3" parent="preprocess" input="AST、优化记录与路径" output="DWARF/PDB、行号表与符号名" summary="优化会改变指令顺序,调试信息把机器状态投影回源码概念。">
|
|
35
|
-
<Definition>调试段不参与逻辑,却决定断点、栈回溯、性能采样和崩溃符号化的质量。</Definition>
|
|
36
|
-
<Example title="发布包如何保留可诊断性">把符号拆到 symbol server,线上二进制只保留 build-id;收到地址后用同一 build-id 找回源位置。</Example>
|
|
37
|
-
</ConceptNode>
|
|
38
|
-
<ConceptNode id="reproducibility" title="可重复构建与供应链" level="L2" parent="intent" input="锁文件、工具链镜像与脚本" output="带来源证明的制品" summary="构建不仅要成功,还要能回答“由什么生成、是否被替换”。">
|
|
39
|
-
<Definition>可重复性解决同样输入是否同样输出;来源证明解决输出由谁、何时、用什么生成。二者构成软件供应链的可审计性。</Definition>
|
|
40
|
-
<Details summary="检查清单">固定编译器 digest、锁定依赖、清理时间与路径噪声、记录 SBOM、签名产物,并在隔离环境中二次构建。</Details>
|
|
41
|
-
</ConceptNode>
|
|
42
|
-
|
|
43
|
-
<ConceptNode id="toolchain" title="工具链:从 IR 到可装载文件" level="L1" parent="execution-system" input="IR、库接口与目标三元组" output="目标文件、共享库与可执行映像" summary="前端解释语义,中端减少工作,后端选择 ISA,链接器把名字变成地址。">
|
|
44
|
-
<Definition>每一步都可能引入契约:调用约定、段权限、异常表、依赖版本和调试信息。</Definition>
|
|
45
|
-
<Example title="查看每层产物">用 `-E` 保留预处理文本、`-S` 查看汇编、`-c` 生成目标文件,再用 `readelf -h -S -r` 或 `dumpbin` 检查头、段和重定位。</Example>
|
|
46
|
-
<Children><ConceptRef id="optimization" /><ConceptRef id="linking" /><ConceptRef id="artifact-format" /></Children>
|
|
47
|
-
</ConceptNode>
|
|
48
|
-
<ConceptNode id="optimization" title="中间表示与优化" level="L2" parent="toolchain" input="控制流、数据流和别名信息" output="更少指令与更好局部性的计划" summary="优化是在已知前提下重排等价计算;收益和风险都来自这些前提。">
|
|
49
|
-
<Definition>常见变换包括常量折叠、内联、循环变换、死代码删除、向量化和寄存器分配,依据 SSA、别名分析与成本模型。</Definition>
|
|
50
|
-
<Input>优化级别、目标 CPU 特性、调试/剖析开关。</Input><Output>指令序列、栈布局、异常表与优化报告。</Output>
|
|
51
|
-
<Callout type="success" title="性能问题的证据链">先用基准和采样确认热点,再查看优化报告与生成汇编;不要仅凭源代码缩进推断 CPU 路径。</Callout>
|
|
52
|
-
<Evidence command="objdump -dr app.o" observes="检查生成指令与尚未解决的重定位。" />
|
|
53
|
-
<Invariant title="优化不变量">在语言规则允许的前提下,优化前后的可观察行为必须等价。</Invariant>
|
|
54
|
-
<Tradeoff title="调试构建还是发布构建" options={[{name:'调试构建', benefit:'符号完整、定位快', cost:'体积和运行开销更大', when:'开发与故障复现'}, {name:'发布构建', benefit:'性能和体积更优', cost:'诊断信息需要单独保存', when:'生产部署'}]} />
|
|
55
|
-
</ConceptNode>
|
|
56
|
-
<ConceptNode id="linking" title="符号解析与重定位" level="L2" parent="toolchain" input="目标文件、静态库、共享库" output="符号地址已确定的映像" summary="链接器把分散的名字变成地址,并选择哪些代码进入最终文件。">
|
|
57
|
-
<Definition>符号表描述定义与引用;重定位记录此处需要填入哪个地址或偏移。动态链接把部分决定推迟到装载或首次调用。</Definition>
|
|
58
|
-
<Details summary="链接失败如何定位">先确认符号存在,再确认名称修饰与 ABI,随后检查库顺序、架构和可见性,最后检查链接脚本与段布局。</Details>
|
|
59
|
-
<FailureMode symptom="undefined reference" cause="符号未定义或 ABI 不匹配" evidence="nm -C、readelf -Ws" remedy="确认库版本、链接顺序与目标架构" />
|
|
60
|
-
<Children><ConceptRef id="relocation" /><ConceptRef id="abi" /></Children>
|
|
61
|
-
</ConceptNode>
|
|
62
|
-
<ConceptNode id="relocation" title="重定位、PLT 与 GOT" level="L3" parent="linking" input="机器码中的占位引用" output="相对/绝对地址与延迟绑定入口" summary="位置无关代码把地址决定拆成两步:共享代码可复用,进程私有表在装载时修补。">
|
|
63
|
-
<Definition>GOT 保存可变地址,PLT 提供调用跳板;懒绑定用首次调用成本换启动时间,安全加固会限制可写表。</Definition>
|
|
64
|
-
<Example title="同一函数地址为何变化">ASLR 让模块基址随机化;相对偏移不变,但每次运行看到的绝对地址不同。</Example>
|
|
65
|
-
</ConceptNode>
|
|
66
|
-
<ConceptNode id="abi" title="ABI 与二进制兼容" level="L3" parent="linking" input="调用约定、数据布局与系统接口" output="可跨编译单元协作的边界" summary="源代码兼容不等于二进制兼容。">
|
|
67
|
-
<Definition>ABI 规定参数位置、结构体对齐、异常传播和符号命名。编译器版本、标准库或字段变化都可能让双方解释不同字节。</Definition>
|
|
68
|
-
<Glossary term="ODR">One Definition Rule:跨翻译单元的实体定义必须满足语言规则;违反时可能链接成功却产生未定义行为。</Glossary>
|
|
69
|
-
<Children><ConceptRef id="abi-break" /></Children>
|
|
70
|
-
</ConceptNode>
|
|
71
|
-
<ConceptNode id="abi-break" title="ABI 破坏:能链接,不等于能调用" level="L4" parent="abi" input="不一致的结构体布局或调用约定" output="启动后崩溃、数据错位或静默损坏" summary="最危险的兼容性问题往往绕过链接器,在第一次真实调用后才显现。">
|
|
72
|
-
<Callout type="danger" title="最小证据">记录双方编译器、目标三元组、sizeof/alignof、符号版本与调用栈;用二进制接口检查工具做发布门禁。</Callout>
|
|
73
|
-
<Example title="字段追加的陷阱">旧库按 16 字节读取,新调用方按 24 字节传递;寄存器可能仍能完成调用,但后续字段会读到未初始化或越界数据。</Example>
|
|
74
|
-
</ConceptNode>
|
|
75
|
-
<ConceptNode id="artifact-format" title="ELF、PE 与段的形状" level="L2" parent="toolchain" input="代码、常量、可写数据和元信息" output="带入口点与权限的文件格式" summary="文件格式把字节分组为装载器可理解的段。">
|
|
76
|
-
<Definition>节偏向链接与分析,段偏向装载与权限。代码通常可执行且只读,数据可能可读写;权限最终反映到页表。</Definition>
|
|
77
|
-
<Example title="文件很小,内存却很大">.bss 只记录零填充大小,不占同等磁盘空间;装载器在内存中分配并清零它。</Example>
|
|
78
|
-
</ConceptNode>
|
|
79
|
-
|
|
80
|
-
<ConceptNode id="identity" title="进程身份与启动协议" level="L1" parent="execution-system" input="映像、argv、环境与权限" output="拥有 PID、凭据、句柄和入口栈的进程" summary="启动是内核与运行时共同建立一个可执行身份。">
|
|
81
|
-
<Definition>内核创建地址空间和线程,装载器解析依赖,运行时初始化 TLS、构造器和库,最后跳转到入口函数。</Definition>
|
|
82
|
-
<Input>工作目录、环境变量、标准流、用户/组凭据、能力与沙箱策略。</Input><Output>入口参数、初始栈、TLS 和可继承文件描述符。</Output>
|
|
83
|
-
<Children><ConceptRef id="loader-protocol" /><ConceptRef id="startup-runtime" /></Children>
|
|
84
|
-
</ConceptNode>
|
|
85
|
-
<ConceptNode id="loader-protocol" title="装载器与地址空间布局" level="L2" parent="identity" input="文件头、段表与依赖路径" output="代码、数据、堆、栈和共享库映射" summary="装载器把文件视图翻译成进程虚拟地址空间。">
|
|
86
|
-
<Definition>映射可按需分页;缺页时才从文件或交换区取页。ASLR、W^X、RELRO 会改变布局和可写范围。</Definition>
|
|
87
|
-
<Details summary="启动失败的分层排查">格式错误看文件头,依赖缺失看搜索路径,权限错误看挂载与策略,段错误继续检查映射、栈和首个异常指令。</Details>
|
|
88
|
-
<Children><ConceptRef id="page-tables" /><ConceptRef id="dynamic-loader" /></Children>
|
|
89
|
-
</ConceptNode>
|
|
90
|
-
<ConceptNode id="page-tables" title="页表、TLB 与缺页" level="L3" parent="loader-protocol" input="虚拟地址、权限位与物理页" output="缓存一致的地址翻译" summary="每次内存访问先通过翻译;TLB 命中与否直接改变延迟。">
|
|
91
|
-
<Definition>页表把虚拟页映射到物理页并携带权限。TLB 缓存近期映射;缺页异常交给内核决定映射文件、分配零页还是终止进程。</Definition>
|
|
92
|
-
<Example title="mmap 后为何没有立刻读盘">映射是承诺;真正访问某页时才触发 page fault,内核按需填充。</Example>
|
|
93
|
-
<Children><ConceptRef id="fault-storm" /></Children>
|
|
94
|
-
</ConceptNode>
|
|
95
|
-
<ConceptNode id="fault-storm" title="缺页风暴与抖动" level="L4" parent="page-tables" input="工作集超过内存、随机访问或映射失配" output="大量 fault、低吞吐与尾延迟" summary="地址翻译正确并不代表性能健康;工作集与内存层级失配会让程序在换页上耗尽时间。">
|
|
96
|
-
<Details summary="如何确认是内存层问题">同时观察 major/minor fault、TLB miss、I/O 等待和工作集大小;逐步缩小数据集或改变访问局部性,验证因果关系。</Details>
|
|
97
|
-
</ConceptNode>
|
|
98
|
-
<ConceptNode id="dynamic-loader" title="共享库与符号可见性" level="L3" parent="loader-protocol" input="依赖清单、搜索路径与版本符号" output="进程内可调用的共享对象" summary="动态装载器同时解决加载版本、符号选择和绑定时机。">
|
|
99
|
-
<Callout type="warn" title="环境变量是隐形输入">LD_LIBRARY_PATH、PATH 或容器挂载差异会让同一二进制连接到不同实现;发布时记录解析后的依赖树。</Callout>
|
|
100
|
-
</ConceptNode>
|
|
101
|
-
<ConceptNode id="startup-runtime" title="语言运行时初始化" level="L2" parent="identity" input="入口栈、TLS、静态对象与运行库" output="可进入 main/async runtime 的状态" summary="main 之前已发生 TLS 建立、静态初始化、参数解析和线程池准备。">
|
|
102
|
-
<Example title="初始化顺序陷阱">跨翻译单元的静态对象初始化顺序通常没有全局保证;把依赖移到显式初始化函数更稳妥。</Example>
|
|
103
|
-
</ConceptNode>
|
|
104
|
-
|
|
105
|
-
<ConceptNode id="address-space" title="时间、调度与内存模型" level="L1" parent="execution-system" input="线程、核心、时钟与同步原语" output="按某种顺序提交的指令与可见状态" summary="逻辑顺序要经过调度器、缓存和内存模型,才成为具体时间线。">
|
|
106
|
-
<Definition>调度器分配运行机会;CPU 乱序执行隐藏延迟;缓存一致性传播写入;语言内存模型定义线程能观察到哪些顺序。</Definition>
|
|
107
|
-
<Prerequisite>区分墙上时钟、单调时钟、CPU 周期以及 happens-before。</Prerequisite>
|
|
108
|
-
<Children><ConceptRef id="scheduler" /><ConceptRef id="memory-order" /></Children>
|
|
109
|
-
</ConceptNode>
|
|
110
|
-
<ConceptNode id="scheduler" title="线程、抢占与系统调用" level="L2" parent="address-space" input="可运行线程、优先级与阻塞原因" output="上下文切换与系统调用返回值" summary="线程会因时间片、I/O 等待或显式让出而切换。">
|
|
111
|
-
<Definition>上下文切换保存寄存器和栈指针;系统调用切到内核态并可能阻塞。调度延迟受 CPU 负载、锁、I/O 和 cgroup 配额共同影响。</Definition>
|
|
112
|
-
<Details summary="解释一次长尾延迟">把请求拆成用户态运行、系统调用、运行队列等待、I/O 等待四段,用 tracing 或 perf 验证。</Details>
|
|
113
|
-
</ConceptNode>
|
|
114
|
-
<ConceptNode id="memory-order" title="缓存一致性与内存序" level="L3" parent="address-space" input="并发读写、原子操作和屏障" output="各线程可观察的值与顺序" summary="一致性协调单地址,内存序规定跨地址的可见性关系。">
|
|
115
|
-
<Definition>release/acquire、seq_cst 把编译器与硬件重排纳入同一契约;volatile 表达设备/信号可见性,不能替代线程同步。</Definition>
|
|
116
|
-
<Callout type="danger" title="数据竞争不是偶尔读旧值">未同步的冲突访问可能直接进入未定义行为;应使用原子、锁或消息传递建立 happens-before。</Callout>
|
|
117
|
-
<Children><ConceptRef id="race-window" /></Children>
|
|
118
|
-
</ConceptNode>
|
|
119
|
-
<ConceptNode id="race-window" title="竞态窗口与不可复现" level="L4" parent="memory-order" input="缺失同步、不同核心速度与调度抖动" output="偶发错误、错误日志或状态回滚" summary="低概率并发错误会被优化、日志和重试机制放大或掩盖。">
|
|
120
|
-
<Callout type="warn" title="复现策略">固定线程数和调度扰动,给共享状态加版本号,采集每次读写的因果链;不要用 sleep 当作同步原语。</Callout>
|
|
121
|
-
</ConceptNode>
|
|
122
|
-
|
|
123
|
-
<ConceptNode id="effects" title="副作用、故障与证据" level="L1" parent="execution-system" input="系统调用、外部服务与资源限制" output="I/O、信号、日志、指标、转储与退出码" summary="最终结果是一组外部可观察的状态变化,而不只是 return 值。">
|
|
124
|
-
<Definition>文件、网络包、子进程、信号和退出码都属于副作用。诊断要把它们与版本、配置、硬件和时间关联。</Definition>
|
|
125
|
-
<Input>文件系统、网络、时钟、随机源、资源配额和安全策略。</Input><Output>业务响应、审计日志、trace/span、core dump 与退出状态。</Output>
|
|
126
|
-
<Callout type="info" title="从症状反推层级">构建错误多停在语义/链接层;启动即退多看装载/初始化;延迟与偶发崩溃优先检查并发、生命周期和资源耗尽。</Callout>
|
|
127
|
-
<Children><ConceptRef id="observability" /><ConceptRef id="failure-analysis" /></Children>
|
|
128
|
-
</ConceptNode>
|
|
129
|
-
<ConceptNode id="observability" title="可观测性三角" level="L2" parent="effects" input="日志、指标与执行跨度" output="可关联的时间线与责任边界" summary="日志说发生了什么,指标说多频繁,追踪说在哪里变慢。">
|
|
130
|
-
<Definition>为构建产物注入版本标识,为请求传播 trace-id,并把系统调用、调度和业务事件放到同一时间轴。</Definition>
|
|
131
|
-
<Example title="一次崩溃的最小证据包">二进制 build-id、符号文件、argv/环境摘要、结构化日志、线程栈、核心转储和机器架构。</Example>
|
|
132
|
-
</ConceptNode>
|
|
133
|
-
<ConceptNode id="failure-analysis" title="故障树与最小复现" level="L3" parent="effects" input="症状、证据与可控变量" output="可验证假设、回归用例和修复边界" summary="把“程序不工作”拆成可证伪的层级假设。">
|
|
134
|
-
<Definition>先确定失败发生在构建、装载、执行还是副作用提交;再固定输入、缩小依赖、记录首个错误点,最后转成自动化回归。</Definition>
|
|
135
|
-
<Details summary="一个可执行的故障树">文件不存在→路径/权限;符号不存在→ABI/库版本;信号 11→地址/生命周期;结果偶发→并发/时间;性能长尾→调度/I/O/锁竞争。</Details>
|
|
136
|
-
<Glossary term="首个错误点">时间线上最早改变不变量的事件;后续日志往往只是它造成的连锁反应。</Glossary>
|
|
137
|
-
<Children><ConceptRef id="resource-exhaustion" /></Children>
|
|
138
|
-
</ConceptNode>
|
|
139
|
-
<ConceptNode id="resource-exhaustion" title="资源耗尽:失败发生在 return 之后" level="L4" parent="failure-analysis" input="文件描述符、线程、句柄、配额与连接池" output="ENOMEM、EMFILE、超时、拒绝服务" summary="程序逻辑正确也可能因外部资源账本归零而失败。">
|
|
140
|
-
<Definition>把资源视为有所有者、有上限、有回收路径的状态机;每次分配都应能在指标中找到余额和释放证据。</Definition>
|
|
141
|
-
<Example title="泄漏为何先表现为延迟">连接池逐渐耗尽后,请求先排队变慢,最终才以超时暴露;只监控错误率会错过早期信号。</Example>
|
|
142
|
-
</ConceptNode>
|
|
143
|
-
|
|
144
|
-
<Relation from="intent" to="toolchain" type="produces" label="提供语义输入" />
|
|
145
|
-
<Relation from="toolchain" to="identity" type="precedes" label="交付可装载映像" />
|
|
146
|
-
<Relation from="identity" to="address-space" type="precedes" label="建立进程与线程" />
|
|
147
|
-
<Relation from="address-space" to="effects" type="causes" label="决定可观察顺序" />
|
|
148
|
-
<Relation from="semantic-contract" to="optimization" type="depends-on" label="优化依赖语义前提" />
|
|
149
|
-
<Relation from="linking" to="loader-protocol" type="precedes" label="段与依赖进入装载器" />
|
|
150
|
-
<Relation from="page-tables" to="scheduler" type="depends-on" label="异常与调度相交" />
|
|
151
|
-
<Relation from="memory-order" to="failure-analysis" type="causes" label="错误顺序制造偶发故障" />
|
|
152
|
-
<Relation from="observability" to="reproducibility" type="depends-on" label="需要稳定制品身份" />
|
|
153
|
-
<Relation from="abi-break" to="failure-analysis" type="exception-of" label="兼容性边界" />
|
|
154
|
-
<Relation from="fault-storm" to="observability" type="causes" label="长尾指标暴露抖动" />
|
|
155
|
-
<Relation from="race-window" to="failure-analysis" type="exception-of" label="并发边界" />
|
|
156
|
-
<Relation from="resource-exhaustion" to="observability" type="causes" label="资源账本耗尽" />
|
|
157
|
-
</ConceptGraph>
|
|
158
|
-
</ExplainPage>
|
|
1
|
+
<ExplainPage id="compiler-runtime" title="程序如何变成一次可观察的运行" summary="从意图、工具链与操作系统契约出发,追踪程序如何获得身份、地址、时间与副作用。" layout="editorial" density="reading">
|
|
2
|
+
<ConceptGraph root="execution-system">
|
|
3
|
+
<ConceptNode id="execution-system" title="执行系统:从意图到副作用" level="L0" input="源码、工具链与机器" output="行为、资源变化与退出状态" summary="把编译与运行看成跨层契约,而不是只有编译器参与的流水线。">
|
|
4
|
+
<Definition>“运行起来”同时意味着语义被解释、依赖被绑定、地址被授予、时间被调度、结果被暴露。任何一层契约破裂,都可能表现为构建失败、启动失败、性能退化或悄无声息的错误。</Definition>
|
|
5
|
+
<Prerequisite>先掌握源代码、进程、虚拟地址和文件描述符四个概念。</Prerequisite>
|
|
6
|
+
<LearningObjectives items={['区分构建、装载与执行阶段', '为每个阶段找到可验证证据', '从首个错误点缩小故障边界']} />
|
|
7
|
+
<KeyQuestion>为什么“编译成功”仍然不能保证程序能启动?</KeyQuestion>
|
|
8
|
+
<Input>源码快照、目标三元组、编译器版本、依赖锁文件、配置与凭据。</Input>
|
|
9
|
+
<Output>可执行映像、进程地址空间、系统调用轨迹、标准输出与退出码。</Output>
|
|
10
|
+
<Callout type="info" title="阅读地图">沿着“意图 → 表示 → 身份 → 地址 → 时间 → 副作用”下钻;每个节点都给出可观测证据,方便把概念变成排障动作。</Callout>
|
|
11
|
+
<Tabs items={[{label:'工程视角',content:'可重复构建、发布产物、启动延迟与回滚。'},{label:'机器视角',content:'指令、页表、缓存一致性与异常入口。'},{label:'运维视角',content:'日志、指标、追踪、信号与资源上限。'}]} />
|
|
12
|
+
<Children><ConceptRef id="intent" /><ConceptRef id="toolchain" /><ConceptRef id="identity" /><ConceptRef id="address-space" /><ConceptRef id="effects" /></Children>
|
|
13
|
+
</ConceptNode>
|
|
14
|
+
|
|
15
|
+
<ConceptNode id="intent" title="意图与源代码" level="L1" parent="execution-system" input="需求、算法与接口" output="工具链可消费的文本与资源" summary="源代码既是给人看的设计,也是后续每个阶段必须兑现的承诺。">
|
|
16
|
+
<Definition>源文件、宏、生成代码和资源文件共同构成输入;真正的边界由构建系统决定,而不是某个文件扩展名。</Definition>
|
|
17
|
+
<Input>版本提交、编译条件、代码生成器输出、环境变量和平台配置。</Input>
|
|
18
|
+
<Output>确定的源快照与可追溯构建元数据。</Output>
|
|
19
|
+
<Example title="同一提交却得到不同二进制">时间戳宏、未锁定依赖、随机临时目录或本地路径进入产物后,字节比较会失败;先固定输入,再讨论优化。</Example>
|
|
20
|
+
<Glossary term="可重复构建">相同源快照、工具链和外部输入应产生等价产物;等价可以是字节相同,也可以是行为相同。</Glossary>
|
|
21
|
+
<Children><ConceptRef id="preprocess" /><ConceptRef id="reproducibility" /></Children>
|
|
22
|
+
</ConceptNode>
|
|
23
|
+
<ConceptNode id="preprocess" title="预处理与语法树" level="L2" parent="intent" input="字符、宏与包含路径" output="Token 流、AST 与源位置" summary="工具链先决定哪些文本存在,以及它们如何组成结构。">
|
|
24
|
+
<Definition>预处理器展开宏和条件分支;词法分析切分 Token;解析器建立 AST。源位置映射影响诊断、调试和覆盖率。</Definition>
|
|
25
|
+
<Details summary="为什么一个括号错误会拖垮整份文件?">解析器需要在错误位置恢复;同步点不足时,后续 Token 会连锁误判。高质量诊断还要给出恢复后的上下文。</Details>
|
|
26
|
+
<Example title="条件编译的隐藏分支">同一文件在 debug、asan、arm64 配置下可能拥有三棵不同 AST;只评审默认配置并不足够。</Example>
|
|
27
|
+
<Children><ConceptRef id="semantic-contract" /><ConceptRef id="source-maps" /></Children>
|
|
28
|
+
</ConceptNode>
|
|
29
|
+
<ConceptNode id="semantic-contract" title="类型、借用与未定义行为" level="L3" parent="preprocess" input="AST、符号表与语言规则" output="带约束的 IR 或诊断" summary="语义阶段决定哪些操作被语言承诺,哪些被禁止或留给实现。">
|
|
30
|
+
<Definition>类型检查验证值的形状与操作集合;所有权/借用还验证别名与生命周期。越过约束后,编译器可能基于“不会发生”进行变换。</Definition>
|
|
31
|
+
<Callout type="warn" title="契约的反面">一次构建恰好得到的结果不是规范。越界、数据竞争或严格别名违规可能在换优化级别或 CPU 后改变表现。</Callout>
|
|
32
|
+
<Glossary term="IR">连接语言语义与目标指令的中间表示,常包含控制流图、SSA 值和内存操作。</Glossary>
|
|
33
|
+
</ConceptNode>
|
|
34
|
+
<ConceptNode id="source-maps" title="调试信息与可观测映射" level="L3" parent="preprocess" input="AST、优化记录与路径" output="DWARF/PDB、行号表与符号名" summary="优化会改变指令顺序,调试信息把机器状态投影回源码概念。">
|
|
35
|
+
<Definition>调试段不参与逻辑,却决定断点、栈回溯、性能采样和崩溃符号化的质量。</Definition>
|
|
36
|
+
<Example title="发布包如何保留可诊断性">把符号拆到 symbol server,线上二进制只保留 build-id;收到地址后用同一 build-id 找回源位置。</Example>
|
|
37
|
+
</ConceptNode>
|
|
38
|
+
<ConceptNode id="reproducibility" title="可重复构建与供应链" level="L2" parent="intent" input="锁文件、工具链镜像与脚本" output="带来源证明的制品" summary="构建不仅要成功,还要能回答“由什么生成、是否被替换”。">
|
|
39
|
+
<Definition>可重复性解决同样输入是否同样输出;来源证明解决输出由谁、何时、用什么生成。二者构成软件供应链的可审计性。</Definition>
|
|
40
|
+
<Details summary="检查清单">固定编译器 digest、锁定依赖、清理时间与路径噪声、记录 SBOM、签名产物,并在隔离环境中二次构建。</Details>
|
|
41
|
+
</ConceptNode>
|
|
42
|
+
|
|
43
|
+
<ConceptNode id="toolchain" title="工具链:从 IR 到可装载文件" level="L1" parent="execution-system" input="IR、库接口与目标三元组" output="目标文件、共享库与可执行映像" summary="前端解释语义,中端减少工作,后端选择 ISA,链接器把名字变成地址。">
|
|
44
|
+
<Definition>每一步都可能引入契约:调用约定、段权限、异常表、依赖版本和调试信息。</Definition>
|
|
45
|
+
<Example title="查看每层产物">用 `-E` 保留预处理文本、`-S` 查看汇编、`-c` 生成目标文件,再用 `readelf -h -S -r` 或 `dumpbin` 检查头、段和重定位。</Example>
|
|
46
|
+
<Children><ConceptRef id="optimization" /><ConceptRef id="linking" /><ConceptRef id="artifact-format" /></Children>
|
|
47
|
+
</ConceptNode>
|
|
48
|
+
<ConceptNode id="optimization" title="中间表示与优化" level="L2" parent="toolchain" input="控制流、数据流和别名信息" output="更少指令与更好局部性的计划" summary="优化是在已知前提下重排等价计算;收益和风险都来自这些前提。">
|
|
49
|
+
<Definition>常见变换包括常量折叠、内联、循环变换、死代码删除、向量化和寄存器分配,依据 SSA、别名分析与成本模型。</Definition>
|
|
50
|
+
<Input>优化级别、目标 CPU 特性、调试/剖析开关。</Input><Output>指令序列、栈布局、异常表与优化报告。</Output>
|
|
51
|
+
<Callout type="success" title="性能问题的证据链">先用基准和采样确认热点,再查看优化报告与生成汇编;不要仅凭源代码缩进推断 CPU 路径。</Callout>
|
|
52
|
+
<Evidence command="objdump -dr app.o" observes="检查生成指令与尚未解决的重定位。" />
|
|
53
|
+
<Invariant title="优化不变量">在语言规则允许的前提下,优化前后的可观察行为必须等价。</Invariant>
|
|
54
|
+
<Tradeoff title="调试构建还是发布构建" options={[{name:'调试构建', benefit:'符号完整、定位快', cost:'体积和运行开销更大', when:'开发与故障复现'}, {name:'发布构建', benefit:'性能和体积更优', cost:'诊断信息需要单独保存', when:'生产部署'}]} />
|
|
55
|
+
</ConceptNode>
|
|
56
|
+
<ConceptNode id="linking" title="符号解析与重定位" level="L2" parent="toolchain" input="目标文件、静态库、共享库" output="符号地址已确定的映像" summary="链接器把分散的名字变成地址,并选择哪些代码进入最终文件。">
|
|
57
|
+
<Definition>符号表描述定义与引用;重定位记录此处需要填入哪个地址或偏移。动态链接把部分决定推迟到装载或首次调用。</Definition>
|
|
58
|
+
<Details summary="链接失败如何定位">先确认符号存在,再确认名称修饰与 ABI,随后检查库顺序、架构和可见性,最后检查链接脚本与段布局。</Details>
|
|
59
|
+
<FailureMode symptom="undefined reference" cause="符号未定义或 ABI 不匹配" evidence="nm -C、readelf -Ws" remedy="确认库版本、链接顺序与目标架构" />
|
|
60
|
+
<Children><ConceptRef id="relocation" /><ConceptRef id="abi" /></Children>
|
|
61
|
+
</ConceptNode>
|
|
62
|
+
<ConceptNode id="relocation" title="重定位、PLT 与 GOT" level="L3" parent="linking" input="机器码中的占位引用" output="相对/绝对地址与延迟绑定入口" summary="位置无关代码把地址决定拆成两步:共享代码可复用,进程私有表在装载时修补。">
|
|
63
|
+
<Definition>GOT 保存可变地址,PLT 提供调用跳板;懒绑定用首次调用成本换启动时间,安全加固会限制可写表。</Definition>
|
|
64
|
+
<Example title="同一函数地址为何变化">ASLR 让模块基址随机化;相对偏移不变,但每次运行看到的绝对地址不同。</Example>
|
|
65
|
+
</ConceptNode>
|
|
66
|
+
<ConceptNode id="abi" title="ABI 与二进制兼容" level="L3" parent="linking" input="调用约定、数据布局与系统接口" output="可跨编译单元协作的边界" summary="源代码兼容不等于二进制兼容。">
|
|
67
|
+
<Definition>ABI 规定参数位置、结构体对齐、异常传播和符号命名。编译器版本、标准库或字段变化都可能让双方解释不同字节。</Definition>
|
|
68
|
+
<Glossary term="ODR">One Definition Rule:跨翻译单元的实体定义必须满足语言规则;违反时可能链接成功却产生未定义行为。</Glossary>
|
|
69
|
+
<Children><ConceptRef id="abi-break" /></Children>
|
|
70
|
+
</ConceptNode>
|
|
71
|
+
<ConceptNode id="abi-break" title="ABI 破坏:能链接,不等于能调用" level="L4" parent="abi" input="不一致的结构体布局或调用约定" output="启动后崩溃、数据错位或静默损坏" summary="最危险的兼容性问题往往绕过链接器,在第一次真实调用后才显现。">
|
|
72
|
+
<Callout type="danger" title="最小证据">记录双方编译器、目标三元组、sizeof/alignof、符号版本与调用栈;用二进制接口检查工具做发布门禁。</Callout>
|
|
73
|
+
<Example title="字段追加的陷阱">旧库按 16 字节读取,新调用方按 24 字节传递;寄存器可能仍能完成调用,但后续字段会读到未初始化或越界数据。</Example>
|
|
74
|
+
</ConceptNode>
|
|
75
|
+
<ConceptNode id="artifact-format" title="ELF、PE 与段的形状" level="L2" parent="toolchain" input="代码、常量、可写数据和元信息" output="带入口点与权限的文件格式" summary="文件格式把字节分组为装载器可理解的段。">
|
|
76
|
+
<Definition>节偏向链接与分析,段偏向装载与权限。代码通常可执行且只读,数据可能可读写;权限最终反映到页表。</Definition>
|
|
77
|
+
<Example title="文件很小,内存却很大">.bss 只记录零填充大小,不占同等磁盘空间;装载器在内存中分配并清零它。</Example>
|
|
78
|
+
</ConceptNode>
|
|
79
|
+
|
|
80
|
+
<ConceptNode id="identity" title="进程身份与启动协议" level="L1" parent="execution-system" input="映像、argv、环境与权限" output="拥有 PID、凭据、句柄和入口栈的进程" summary="启动是内核与运行时共同建立一个可执行身份。">
|
|
81
|
+
<Definition>内核创建地址空间和线程,装载器解析依赖,运行时初始化 TLS、构造器和库,最后跳转到入口函数。</Definition>
|
|
82
|
+
<Input>工作目录、环境变量、标准流、用户/组凭据、能力与沙箱策略。</Input><Output>入口参数、初始栈、TLS 和可继承文件描述符。</Output>
|
|
83
|
+
<Children><ConceptRef id="loader-protocol" /><ConceptRef id="startup-runtime" /></Children>
|
|
84
|
+
</ConceptNode>
|
|
85
|
+
<ConceptNode id="loader-protocol" title="装载器与地址空间布局" level="L2" parent="identity" input="文件头、段表与依赖路径" output="代码、数据、堆、栈和共享库映射" summary="装载器把文件视图翻译成进程虚拟地址空间。">
|
|
86
|
+
<Definition>映射可按需分页;缺页时才从文件或交换区取页。ASLR、W^X、RELRO 会改变布局和可写范围。</Definition>
|
|
87
|
+
<Details summary="启动失败的分层排查">格式错误看文件头,依赖缺失看搜索路径,权限错误看挂载与策略,段错误继续检查映射、栈和首个异常指令。</Details>
|
|
88
|
+
<Children><ConceptRef id="page-tables" /><ConceptRef id="dynamic-loader" /></Children>
|
|
89
|
+
</ConceptNode>
|
|
90
|
+
<ConceptNode id="page-tables" title="页表、TLB 与缺页" level="L3" parent="loader-protocol" input="虚拟地址、权限位与物理页" output="缓存一致的地址翻译" summary="每次内存访问先通过翻译;TLB 命中与否直接改变延迟。">
|
|
91
|
+
<Definition>页表把虚拟页映射到物理页并携带权限。TLB 缓存近期映射;缺页异常交给内核决定映射文件、分配零页还是终止进程。</Definition>
|
|
92
|
+
<Example title="mmap 后为何没有立刻读盘">映射是承诺;真正访问某页时才触发 page fault,内核按需填充。</Example>
|
|
93
|
+
<Children><ConceptRef id="fault-storm" /></Children>
|
|
94
|
+
</ConceptNode>
|
|
95
|
+
<ConceptNode id="fault-storm" title="缺页风暴与抖动" level="L4" parent="page-tables" input="工作集超过内存、随机访问或映射失配" output="大量 fault、低吞吐与尾延迟" summary="地址翻译正确并不代表性能健康;工作集与内存层级失配会让程序在换页上耗尽时间。">
|
|
96
|
+
<Details summary="如何确认是内存层问题">同时观察 major/minor fault、TLB miss、I/O 等待和工作集大小;逐步缩小数据集或改变访问局部性,验证因果关系。</Details>
|
|
97
|
+
</ConceptNode>
|
|
98
|
+
<ConceptNode id="dynamic-loader" title="共享库与符号可见性" level="L3" parent="loader-protocol" input="依赖清单、搜索路径与版本符号" output="进程内可调用的共享对象" summary="动态装载器同时解决加载版本、符号选择和绑定时机。">
|
|
99
|
+
<Callout type="warn" title="环境变量是隐形输入">LD_LIBRARY_PATH、PATH 或容器挂载差异会让同一二进制连接到不同实现;发布时记录解析后的依赖树。</Callout>
|
|
100
|
+
</ConceptNode>
|
|
101
|
+
<ConceptNode id="startup-runtime" title="语言运行时初始化" level="L2" parent="identity" input="入口栈、TLS、静态对象与运行库" output="可进入 main/async runtime 的状态" summary="main 之前已发生 TLS 建立、静态初始化、参数解析和线程池准备。">
|
|
102
|
+
<Example title="初始化顺序陷阱">跨翻译单元的静态对象初始化顺序通常没有全局保证;把依赖移到显式初始化函数更稳妥。</Example>
|
|
103
|
+
</ConceptNode>
|
|
104
|
+
|
|
105
|
+
<ConceptNode id="address-space" title="时间、调度与内存模型" level="L1" parent="execution-system" input="线程、核心、时钟与同步原语" output="按某种顺序提交的指令与可见状态" summary="逻辑顺序要经过调度器、缓存和内存模型,才成为具体时间线。">
|
|
106
|
+
<Definition>调度器分配运行机会;CPU 乱序执行隐藏延迟;缓存一致性传播写入;语言内存模型定义线程能观察到哪些顺序。</Definition>
|
|
107
|
+
<Prerequisite>区分墙上时钟、单调时钟、CPU 周期以及 happens-before。</Prerequisite>
|
|
108
|
+
<Children><ConceptRef id="scheduler" /><ConceptRef id="memory-order" /></Children>
|
|
109
|
+
</ConceptNode>
|
|
110
|
+
<ConceptNode id="scheduler" title="线程、抢占与系统调用" level="L2" parent="address-space" input="可运行线程、优先级与阻塞原因" output="上下文切换与系统调用返回值" summary="线程会因时间片、I/O 等待或显式让出而切换。">
|
|
111
|
+
<Definition>上下文切换保存寄存器和栈指针;系统调用切到内核态并可能阻塞。调度延迟受 CPU 负载、锁、I/O 和 cgroup 配额共同影响。</Definition>
|
|
112
|
+
<Details summary="解释一次长尾延迟">把请求拆成用户态运行、系统调用、运行队列等待、I/O 等待四段,用 tracing 或 perf 验证。</Details>
|
|
113
|
+
</ConceptNode>
|
|
114
|
+
<ConceptNode id="memory-order" title="缓存一致性与内存序" level="L3" parent="address-space" input="并发读写、原子操作和屏障" output="各线程可观察的值与顺序" summary="一致性协调单地址,内存序规定跨地址的可见性关系。">
|
|
115
|
+
<Definition>release/acquire、seq_cst 把编译器与硬件重排纳入同一契约;volatile 表达设备/信号可见性,不能替代线程同步。</Definition>
|
|
116
|
+
<Callout type="danger" title="数据竞争不是偶尔读旧值">未同步的冲突访问可能直接进入未定义行为;应使用原子、锁或消息传递建立 happens-before。</Callout>
|
|
117
|
+
<Children><ConceptRef id="race-window" /></Children>
|
|
118
|
+
</ConceptNode>
|
|
119
|
+
<ConceptNode id="race-window" title="竞态窗口与不可复现" level="L4" parent="memory-order" input="缺失同步、不同核心速度与调度抖动" output="偶发错误、错误日志或状态回滚" summary="低概率并发错误会被优化、日志和重试机制放大或掩盖。">
|
|
120
|
+
<Callout type="warn" title="复现策略">固定线程数和调度扰动,给共享状态加版本号,采集每次读写的因果链;不要用 sleep 当作同步原语。</Callout>
|
|
121
|
+
</ConceptNode>
|
|
122
|
+
|
|
123
|
+
<ConceptNode id="effects" title="副作用、故障与证据" level="L1" parent="execution-system" input="系统调用、外部服务与资源限制" output="I/O、信号、日志、指标、转储与退出码" summary="最终结果是一组外部可观察的状态变化,而不只是 return 值。">
|
|
124
|
+
<Definition>文件、网络包、子进程、信号和退出码都属于副作用。诊断要把它们与版本、配置、硬件和时间关联。</Definition>
|
|
125
|
+
<Input>文件系统、网络、时钟、随机源、资源配额和安全策略。</Input><Output>业务响应、审计日志、trace/span、core dump 与退出状态。</Output>
|
|
126
|
+
<Callout type="info" title="从症状反推层级">构建错误多停在语义/链接层;启动即退多看装载/初始化;延迟与偶发崩溃优先检查并发、生命周期和资源耗尽。</Callout>
|
|
127
|
+
<Children><ConceptRef id="observability" /><ConceptRef id="failure-analysis" /></Children>
|
|
128
|
+
</ConceptNode>
|
|
129
|
+
<ConceptNode id="observability" title="可观测性三角" level="L2" parent="effects" input="日志、指标与执行跨度" output="可关联的时间线与责任边界" summary="日志说发生了什么,指标说多频繁,追踪说在哪里变慢。">
|
|
130
|
+
<Definition>为构建产物注入版本标识,为请求传播 trace-id,并把系统调用、调度和业务事件放到同一时间轴。</Definition>
|
|
131
|
+
<Example title="一次崩溃的最小证据包">二进制 build-id、符号文件、argv/环境摘要、结构化日志、线程栈、核心转储和机器架构。</Example>
|
|
132
|
+
</ConceptNode>
|
|
133
|
+
<ConceptNode id="failure-analysis" title="故障树与最小复现" level="L3" parent="effects" input="症状、证据与可控变量" output="可验证假设、回归用例和修复边界" summary="把“程序不工作”拆成可证伪的层级假设。">
|
|
134
|
+
<Definition>先确定失败发生在构建、装载、执行还是副作用提交;再固定输入、缩小依赖、记录首个错误点,最后转成自动化回归。</Definition>
|
|
135
|
+
<Details summary="一个可执行的故障树">文件不存在→路径/权限;符号不存在→ABI/库版本;信号 11→地址/生命周期;结果偶发→并发/时间;性能长尾→调度/I/O/锁竞争。</Details>
|
|
136
|
+
<Glossary term="首个错误点">时间线上最早改变不变量的事件;后续日志往往只是它造成的连锁反应。</Glossary>
|
|
137
|
+
<Children><ConceptRef id="resource-exhaustion" /></Children>
|
|
138
|
+
</ConceptNode>
|
|
139
|
+
<ConceptNode id="resource-exhaustion" title="资源耗尽:失败发生在 return 之后" level="L4" parent="failure-analysis" input="文件描述符、线程、句柄、配额与连接池" output="ENOMEM、EMFILE、超时、拒绝服务" summary="程序逻辑正确也可能因外部资源账本归零而失败。">
|
|
140
|
+
<Definition>把资源视为有所有者、有上限、有回收路径的状态机;每次分配都应能在指标中找到余额和释放证据。</Definition>
|
|
141
|
+
<Example title="泄漏为何先表现为延迟">连接池逐渐耗尽后,请求先排队变慢,最终才以超时暴露;只监控错误率会错过早期信号。</Example>
|
|
142
|
+
</ConceptNode>
|
|
143
|
+
|
|
144
|
+
<Relation from="intent" to="toolchain" type="produces" label="提供语义输入" />
|
|
145
|
+
<Relation from="toolchain" to="identity" type="precedes" label="交付可装载映像" />
|
|
146
|
+
<Relation from="identity" to="address-space" type="precedes" label="建立进程与线程" />
|
|
147
|
+
<Relation from="address-space" to="effects" type="causes" label="决定可观察顺序" />
|
|
148
|
+
<Relation from="semantic-contract" to="optimization" type="depends-on" label="优化依赖语义前提" />
|
|
149
|
+
<Relation from="linking" to="loader-protocol" type="precedes" label="段与依赖进入装载器" />
|
|
150
|
+
<Relation from="page-tables" to="scheduler" type="depends-on" label="异常与调度相交" />
|
|
151
|
+
<Relation from="memory-order" to="failure-analysis" type="causes" label="错误顺序制造偶发故障" />
|
|
152
|
+
<Relation from="observability" to="reproducibility" type="depends-on" label="需要稳定制品身份" />
|
|
153
|
+
<Relation from="abi-break" to="failure-analysis" type="exception-of" label="兼容性边界" />
|
|
154
|
+
<Relation from="fault-storm" to="observability" type="causes" label="长尾指标暴露抖动" />
|
|
155
|
+
<Relation from="race-window" to="failure-analysis" type="exception-of" label="并发边界" />
|
|
156
|
+
<Relation from="resource-exhaustion" to="observability" type="causes" label="资源账本耗尽" />
|
|
157
|
+
</ConceptGraph>
|
|
158
|
+
</ExplainPage>
|