<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="https://octz.net/rss.xsl"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <atom:link href="https://octz.net/rss.xml" rel="self" type="application/rss+xml"/>
    <title>Octal Zone</title>
    <link>https://octz.net/</link>
    <description>折腾无止境，探索无边界</description>
    <language>zh-CN</language>
    <pubDate>Thu, 13 Feb 2020 00:00:00 GMT</pubDate>
    <lastBuildDate>Mon, 04 May 2026 11:06:25 GMT</lastBuildDate>
    <generator>@vuepress/plugin-feed</generator>
    <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
    <copyright>Copyright © DynamicLoader 2020-present</copyright>
    <ttl>10080</ttl>
    <category>Chromium</category>
    <category>Note</category>
    <category>Maintaince</category>
    <category>Game</category>
    <category>ABYDOS</category>
    <category>CTF</category>
    <category>Embedded</category>
    <category>PC</category>
    <category>Programming</category>
    <category>Web</category>
    <item>
      <title>Step into Chromium (100) - PassKey</title>
      <link>https://octz.net/blog/Chromium/100-Passkey.html</link>
      <guid>https://octz.net/blog/Chromium/100-Passkey.html</guid>
      <source url="https://octz.net/rss.xml">Step into Chromium (100) - PassKey</source>
      <description>PassKey 是什么？ 字如其名，PassKey 是一个钥匙，在 base/types/pass_key.h 中定义，存在 base namespace 下面，允许预先声明的类访问某些特定方法，而不必使用类级别的友元声明。 先来看一下它的最简单定义： 就这么简单。神奇吗？ 怎么用？ 比如我们有 A， B 和 C 三个类，其中只想 B 访问 A 的 f...</description>
      <category>Chromium</category>
      <pubDate>Mon, 06 Apr 2026 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>PassKey 是什么？</h2>
<p>字如其名，PassKey 是一个钥匙，在 <code>base/types/pass_key.h</code> 中定义，存在 <code>base</code> namespace 下面，允许预先声明的类访问某些特定方法，而不必使用类级别的友元声明。</p>
<p>先来看一下它的最简单定义：</p>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">template</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> &#x3C;</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">typename</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">... </span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Args</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">></span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">class</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> PassKey</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">template</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> &#x3C;</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">typename</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> T</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">></span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">class</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> PassKey</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">T</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">> {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  friend</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> T;</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">  PassKey</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">() </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> default</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">};</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>就这么简单。神奇吗？</p>
<h2>怎么用？</h2>
<p>比如我们有 <code>A</code>， <code>B</code> 和 <code>C</code> 三个类，其中只想 <code>B</code> 访问 <code>A</code> 的 <code>foo()</code> 方法，那么可以这样写：</p>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">class</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> B</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">class</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> A</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  public:</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">    // bar 方法可以被任意类调用</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> bar</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(){}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">    // foo 方法只能被 B 调用</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> foo</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">PassKey</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">B</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">>){}</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">};</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">class</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> B</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  public:</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> foo</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(){</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">      A a;</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">      a</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">foo</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">({});</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // OK!</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">};</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">class</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> C</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  public:</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> foo</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(){</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">      A a;</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">      // a.foo({}); // Error under C++20 or higher</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">};</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>发现了吗？只有 <code>B</code> 是 <code>PassKey&lt;B&gt;</code> 的友元类，也就只有 <code>B</code> 可以实例化 <code>PassKey&lt;B&gt;</code>，从而调用 <code>A::foo()</code>。</p>
<div class="hint-container warning">
<p class="hint-container-title">警告</p>
<p>这个约束只在 C++20 以上生效，因为在以前 <code>PassKey&lt;B&gt;</code> 这种没有用户定义的构造函数的类是允许聚合初始化从而绕过检查的，但是 C++ 20 认为只要用户显式写了 <code>= default</code> 或者 <code>= delete</code>，那么就不能认为源类是一个聚合体了，必须调用构造函数，从而触发访问检查。</p>
</div>
<p>不过你可能会发现，这里有一个问题，就是如果 <code>B</code> 实例化 <code>PassKey&lt;B&gt;</code> 之后传给第三方，那么第三方类也可以拿这个实例来调用 <code>A::foo()</code> 了。这就好像 <code>B</code> 拥有 <code>A::foo()</code> 的钥匙，但是钥匙是可以复刻的，那么任何拿到复刻钥匙的实体都可以打开 <code>A::foo()</code> 这把锁。针对这个问题，我们还可以禁用拷贝构造和赋值操作符，这样就得到了 <code>NonCopyablePassKey</code>:</p>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">template</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> &#x3C;</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">typename</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> T</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">></span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">class</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> NonCopyablePassKey</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  friend</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> T;</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">  NonCopyablePassKey</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">() </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> default</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">  NonCopyablePassKey</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> NonCopyablePassKey</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> delete</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">  NonCopyablePassKey</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x26;</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> operator</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">=(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> NonCopyablePassKey</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> delete</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">};</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>常用的场景就是只允许某个 <code>Factory</code> 来构造某类 <code>Object</code> ，给 <code>Object</code> 的构造函数加一个 <code>Passkey&lt;Factory&gt;</code> 参数即可。在 Chromium 中，也常用来管控一些设计上正在被废弃的类在新场景下的利用。</p>
<p>此外，PassKey 在较新版本也加入了多类的支持，如下：</p>
<blockquote>
<p>有点长，而且是偏特化大师和前沿特性大神（需要 requires 和折叠表达式，至少 C++20）...</p>
</blockquote>
<details class="hint-container details"><summary>展开</summary>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">namespace</span><span style="--shiki-light:#383A42;--shiki-dark:#E5C07B"> pass_key_internal</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">template</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> &#x3C;</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">typename</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> T</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">typename</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">... </span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Args</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">></span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">concept</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> OneOf </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (std::same_as</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">T, Args</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">></span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2"> ||</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ...);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">// Calculates how many instances of &#x3C;T> there are among &#x3C;Args...>.</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">template</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> &#x3C;</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">typename</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> T</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">typename</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">... </span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Args</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">></span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">constexpr</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> type_frequency </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    (</span><span style="--shiki-light:#A626A4;--shiki-dark:#ABB2BF">static_cast</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;int></span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(std::is_same_v</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">T, Args</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">></span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">+</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ... </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">+</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">// All types in &#x3C;Args...> are unique if each type occurs there exactly once!</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">template</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> &#x3C;</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">typename</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">... </span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Args</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">></span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">concept</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> PairwiseUnique </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ((type_frequency</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">Args, Args...</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">></span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> ==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ...);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">  // namespace pass_key_internal</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">// Specialization for multi-argument PassKey. This allows a PassKey to be</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">// constructed from another PassKey if all its arguments are present in</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">// the target PassKey's argument list. This enables flexible access control</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">// where a function might accept a PassKey that covers a broader set of</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">// authorized callers, and callers can provide more specific PassKey-s.</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">template</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> &#x3C;</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">typename</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">... </span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Args</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">></span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  requires</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#ABB2BF">sizeof...</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(Args) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">></span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">class</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> PassKey</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">&#x3C;Args...> {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  static_assert</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(pass_key_internal::PairwiseUnique</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">Args...</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">></span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span></span>
<span class="line"><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">                "PassKey&#x3C;> arguments must be pairwise unique."</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> public:</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">  // Allows constructing a PassKey&#x3C;A, B> from PassKey&#x3C;A> or PassKey&#x3C;B>.</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">  // Implicit to allow feeding PassKey&#x3C;A> into a function that expects</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">  // PassKey&#x3C;A, B>.</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  template</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> &#x3C;</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">typename</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> T</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">></span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    requires</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> pass_key_internal::OneOf</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">T, Args...</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">></span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">  // NOLINTNEXTLINE(google-explicit-constructor)</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">  PassKey</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">PassKey</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">T</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">>) {}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">  // Allows constructing a PassKey&#x3C;A, B, ...> from a PassKey&#x3C;A, B>.</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">  // The exact order of arguments doesn't matter.</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">  // Implicit to allow feeding PassKey&#x3C;A, B> into a function that expects</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">  // PassKey&#x3C;A, B, ...>.</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  template</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> &#x3C;</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">typename</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">... </span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">SourceArgs</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">></span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    requires</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">sizeof</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">...(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">SourceArgs</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">></span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2"> &#x26;&#x26;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">             (pass_key_internal::</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">OneOf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">SourceArgs</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, Args...> </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x26;&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ...))</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">  // NOLINTNEXTLINE(google-explicit-constructor)</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">  PassKey</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(PassKey</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">SourceArgs...</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">></span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) {}</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">};</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div></details>
]]></content:encoded>
    </item>
    <item>
      <title>NameSilo 的三个时区踩坑记录</title>
      <link>https://octz.net/blog/Note/three-tz-in-namesilo.html</link>
      <guid>https://octz.net/blog/Note/three-tz-in-namesilo.html</guid>
      <source url="https://octz.net/rss.xml">NameSilo 的三个时区踩坑记录</source>
      <description>卡点转移域名被坑记录</description>
      <category>Note</category>
      <pubDate>Mon, 19 Jan 2026 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<p>最近从 NameSilo 转出域名，贴着 60 天的 ICANN 域名转移锁时限卡点转移，结果被坑了一把：</p>
<ol>
<li><strong>NameSilo 的所有系统的时间都没有时区标记！</strong></li>
<li>UI 显示的解锁时间是按用户本地时间</li>
<li>API 侧给出的解锁时间是按 UTC+0</li>
<li>底层域名管理系统使用 NameSilo 所在地时间，也就是美国山地标准时 MST (UTC-7)</li>
</ol>
<p>结果就是你看面板解锁了，不算！<br>
你看后端接口显示没有锁了，也不算！<br>
必须等到 MST 那个时间到了才是真的解锁，在此之前你提交多少次转移申请都会<strong>静默失败</strong>。</p>
]]></content:encoded>
    </item>
    <item>
      <title>告别 All in BOOM - iSCSI 块存储服务入门</title>
      <link>https://octz.net/blog/Maintaince/iSCSI.html</link>
      <guid>https://octz.net/blog/Maintaince/iSCSI.html</guid>
      <source url="https://octz.net/rss.xml">告别 All in BOOM - iSCSI 块存储服务入门</source>
      <description>前一周整了个 J1900，也算是从 ARM 转入 x86 的怀抱了。众所周知，这玩意由两个 SATA 接口，但是 CPU 性能比较差（也比 树莓派3 强多了），比较适合用来做存储和网关。 | 我才不会告诉你我测了半天发现跑个 docker 都费劲呢~ 什么是 iSCSI iSCSI，全称 Internet Small Computer System I...</description>
      <category>Maintaince</category>
      <pubDate>Sat, 06 Dec 2025 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<p>前一周整了个 J1900，也算是从 ARM 转入 x86 的怀抱了。众所周知，这玩意由两个 SATA 接口，但是 CPU 性能比较差（也比 树莓派3 强多了），比较适合用来做存储和网关。</p>
<p>| 我才不会告诉你我测了半天发现跑个 docker 都费劲呢~</p>
<h2>什么是 iSCSI</h2>
<p>iSCSI，全称 Internet Small Computer System Interface（互联网小型计算机系统接口），是一种基于 TCP/IP 协议的存储网络标准。</p>
<p>它允许通过标准的 以太网（Ethernet）基础设施来传输传统的 SCSI（小型计算机系统接口）命令，从而实现 块级别（Block-level）的数据传输和访问。简单来说，iSCSI 就是在 IP 网络上运行 SCSI 协议，将远程的存储设备（如磁盘阵列）虚拟成本地的硬盘，供服务器或计算机使用。</p>
<p>在整个 iSCSI 架构中，发起方 (Initiator) 扮演着客户端的角色，它通常是需要存储空间的服务器或计算机，通过发送 SCSI 命令来请求数据。而 目标方 (Target) 则扮演着服务端的角色，它是一个存储设备，负责接收和处理来自发起方的 SCSI 命令，并将底层的存储资源（即 LUN，逻辑单元号）通过网络的方式虚拟成一块本地硬盘供发起方使用。</p>
<p>这次我们搞试验，就把 J1900 作为目标，而 Windows 电脑作为发起方。</p>
<h2>Target</h2>
<p>我们常使用 <code>tgt</code> 来搭建 target。我在这里跑 OpenWrt，用 opkg 一把梭就可以安装。</p>
<p>不幸的是，由于这个是比较偏门的应用场景，并没有一个 luci 供我们配置。不过我们仍然可以通过 <code>uci</code> 配置文件来统一化配置，对应的文件是 <code>/etc/config/tgt</code>，下面是一个实例：</p>
<div class="language-conf line-numbers-mode" data-highlighter="shiki" data-ext="conf" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-conf"><span class="line"><span>config options 'tgt'</span></span>
<span class="line"><span># iothreads limits number of worker threads per rdwr target, default is 16</span></span>
<span class="line"><span># which seems to be too much for an avarage router</span></span>
<span class="line"><span>	option iothreads '2'</span></span>
<span class="line"><span>#	option nop_count '3'</span></span>
<span class="line"><span>#	option nop_interval '1'</span></span>
<span class="line"><span>#	option logging '0'</span></span>
<span class="line"><span>#	list portal '[::1]'</span></span>
<span class="line"><span>#	list portal '127.0.0.1:3261'</span></span>
<span class="line"><span>#	list portal '0.0.0.0:3262'</span></span>
<span class="line"><span>#	list portal '[::]:3263'</span></span>
<span class="line"><span></span></span>
<span class="line"><span>config target 1</span></span>
<span class="line"><span>    # 一个名字</span></span>
<span class="line"><span>	option name 'iqn.2012-06.lan.server:target1'</span></span>
<span class="line"><span>    # 允许连接的对端名称</span></span>
<span class="line"><span>	list allow_name 'iqn.1991-05.com.microsoft:xxx-laptop'</span></span>
<span class="line"><span>#	list allow_address '192.168.2.128/27'</span></span>
<span class="line"><span></span></span>
<span class="line"><span>#config target 2</span></span>
<span class="line"><span>#	option name 'iqn.2012-06.org.openwrt:t2'</span></span>
<span class="line"><span></span></span>
<span class="line"><span># all options are set to default, except for the device</span></span>
<span class="line"><span># lun "name" is constructed as TGTID_LUN</span></span>
<span class="line"><span>config lun 1_1</span></span>
<span class="line"><span>    # 这里可以指定一个设备名/文件名</span></span>
<span class="line"><span>	option device '/dev/sda'</span></span>
<span class="line"><span># type of scsi device. available options: disk, cd, pt (sg passthrough)</span></span>
<span class="line"><span>#	option 'type' 'disk'</span></span>
<span class="line"><span># backing store access method: rdwr (read-write), aio (async IO), sg (for pt type only, device must be /dev/sgN)</span></span>
<span class="line"><span>#	option 'bstype' 'aio'</span></span>
<span class="line"><span># set sync and/or direct flags when opening device, affect only rdwr</span></span>
<span class="line"><span>#	option 'sync' '0'</span></span>
<span class="line"><span>#	option 'direct' '0'</span></span>
<span class="line"><span># block size for lun, default is 512</span></span>
<span class="line"><span>#	option 'blocksize' 4096</span></span>
<span class="line"><span># override SCSI mode page, see tgtadm man page for details</span></span>
<span class="line"><span>#	option 'mode_page' 'string'</span></span>
<span class="line"><span># vendor, product, revision, SCSI ID and SCSI Serial number</span></span>
<span class="line"><span>#	option 'vendor_id' 'string'</span></span>
<span class="line"><span>#	option 'product_id' 'string'</span></span>
<span class="line"><span>#	option 'product_rev' 'string'</span></span>
<span class="line"><span>#	option 'scsi_id' 'string'</span></span>
<span class="line"><span>#	option 'scsi_sn' 'string'</span></span>
<span class="line"><span># refuse write attempts. applies only to disk type</span></span>
<span class="line"><span>#	option 'readonly' '0'</span></span>
<span class="line"><span># Disk devices default to non-removable, cd - to removable</span></span>
<span class="line"><span>#	option 'removable' '0'</span></span>
<span class="line"><span>#  0 = Classic sense format, 1 = Support descriptor format.</span></span>
<span class="line"><span>#	option 'sense_format' '0'</span></span>
<span class="line"><span># Rotaion rate: 0: not reported, 1: non-rotational medium (SSD), 2-1024: reserverd, 1025+: "Nominal rotation rate"</span></span>
<span class="line"><span>#	option 'rotation_rate' '0'</span></span>
<span class="line"><span># A thin-provisioned LUN is represented as a sparse file.</span></span>
<span class="line"><span># When initiators use the SCSI UNMAP command TGTD will release the affected areas back to the filesystem using FALLOC_FL_PUNCH_HOLE.</span></span>
<span class="line"><span># This option applies to the disk type and rdwr bstype</span></span>
<span class="line"><span>#	option 'thin_provisioning' '1'</span></span>
<span class="line"><span></span></span>
<span class="line"><span># Target 1 上的第二个卷</span></span>
<span class="line"><span>config lun 1_2</span></span>
<span class="line"><span>	option device '/dev/sdb'</span></span>
<span class="line"><span></span></span>
<span class="line"><span>#config lun 2_2</span></span>
<span class="line"><span>#	option device /dev/sdc</span></span>
<span class="line"><span></span></span>
<span class="line"><span># CHAP 认证账号相关</span></span>
<span class="line"><span>config account</span></span>
<span class="line"><span>	list target 1</span></span>
<span class="line"><span>#	list target 2</span></span>
<span class="line"><span>    # 建议设置为你的 Initiator 的名字，以确保只有一个连接</span></span>
<span class="line"><span>	option user "iqn.1991-05.com.microsoft:xxx-laptop"</span></span>
<span class="line"><span>    # 密码需要符合规范，我的试验是 12 位，带有大小写和数字就行</span></span>
<span class="line"><span>	option password "Abcdefgh1234"</span></span>
<span class="line"><span></span></span>
<span class="line"><span>#config account</span></span>
<span class="line"><span>#	option target 2</span></span>
<span class="line"><span>#	option user "user2"</span></span>
<span class="line"><span>#	option password "pwd2"</span></span>
<span class="line"><span>#	option outgoing 1</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2>Initiator</h2>
<p>Windows 一直都带有 <code>iSCSI 发起程序</code>，我们打开它。然后按图设置完成后，一路<code>确定</code>即可。</p>
<figure><img src="https://imgcdn0.octz.net/blog/2025/iscsi-image.png" alt="发起一个 iSCSI 连接" tabindex="0" loading="lazy"><figcaption>发起一个 iSCSI 连接</figcaption></figure>
<p>连接完成后，可以看到 <code>已发现的目标</code> 列表中多了一个项，且状态为 <code>已连接</code>。</p>
<p>如果使用的是一块现有的磁盘，那么应该可以在资源管理器里面直接看到原来的卷标了，否则请到<code>磁盘管理</code>里面去初始化磁盘再分区、格式化，就像插入了一块新硬盘一样。</p>
]]></content:encoded>
      <enclosure url="https://imgcdn0.octz.net/blog/2025/iscsi-image.png" type="image/png"/>
    </item>
    <item>
      <title>硬件安全密钥 CanoKey 使用小记</title>
      <link>https://octz.net/blog/Note/canokey.html</link>
      <guid>https://octz.net/blog/Note/canokey.html</guid>
      <source url="https://octz.net/rss.xml">硬件安全密钥 CanoKey 使用小记</source>
      <description>记录一下 CanoKey 的使用体验和一些常用命令。</description>
      <category>Note</category>
      <pubDate>Fri, 02 Jan 2026 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<p>又是一个心血来潮，了解了一下硬件安全密钥，最常见的就是 Yubikey 了（好贵呜呜呜），看到国产替代产品 <a href="https://www.canokeys.org/" target="_blank" rel="noopener noreferrer">Canokey</a> 两颗的价格还顶不到一块 Yubikey，果断下手来看看怎么个事。</p>
<p>除了 NFC 很弱（我的手机根本用不了，对，是贴上去无论怎么调整都一点反应都没有的那种）以外，CanoKey Canary 的功能基本对标 Yubikey 5c，而且管理上采用了 WebUSB，十分的便利。</p>
<p>主要是支持了 FIDO2 / WebAuthn，OpenPGP 和 PIV，还有 TOTP，基本够用了。配合 Ed25519-SK 来个 SSH 免密登录（是真的只要插上 key 导出来私钥存根就能用的那种，Xshell 都可以），再替代一手 Authenticator 应用。负担嘛无非是要随身带多一个东西，就像真的钥匙一样。</p>
<p>来点有用的命令：</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-bash"><span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">ssh-keygen</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -t</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> ed25519-sk</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -O</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> resident</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -O</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> application=ssh:YourName</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> # -O verify (to enforce entering PIN)</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">ssh-add</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -K</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> # This may need admin/root perm to recover handle and public key from SK into your PC</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">fido2-token</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -L</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> # List all SK</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">fido2-token</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -L</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -r</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> &#x3C;</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">devic</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">e> </span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"># See what's in it</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>顺便，FIDO 也有两个版本，版本一是非驻留式的，密钥在这里当作一个证明函数；FIDO2 允许驻留私钥，也向后兼容。这也是有些网站明明添加了 PassKey 之后也不能在 SK 上面找到凭据的原因。</p>
]]></content:encoded>
    </item>
    <item>
      <title>构建你的动态路由内网 - OSPF 入门小记</title>
      <link>https://octz.net/blog/Maintaince/OSPF0.html</link>
      <guid>https://octz.net/blog/Maintaince/OSPF0.html</guid>
      <source url="https://octz.net/rss.xml">构建你的动态路由内网 - OSPF 入门小记</source>
      <description>前言 Open Shortest Path First (OSPF) 是一种好用的动态路由协议，采用 IP proto 89 交换信息，要求两端对等。可以在广播、点对点和点对多点的环境使用。 这几天也是试了下水，发现比静态路由舒服一点，顺便也给我的内网规划了一下，这里稍微记录一下配置的东西。 阅读建议：非常推荐先会基本的计算机网络和路由原理。 安装软件...</description>
      <category>Maintaince</category>
      <pubDate>Tue, 25 Nov 2025 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>前言</h2>
<p>Open Shortest Path First  (OSPF) 是一种好用的动态路由协议，采用 IP proto 89 交换信息，要求两端对等。可以在广播、点对点和点对多点的环境使用。</p>
<p>这几天也是试了下水，发现比静态路由舒服一点，顺便也给我的内网规划了一下，这里稍微记录一下配置的东西。</p>
<p><strong>阅读建议：非常推荐先会基本的计算机网络和路由原理。</strong></p>
<h2>安装软件包</h2>
<p>在普通的 Linux 设备上，我们可以通过 <code>frr</code> 来构建这些服务。例如，在 OpenWrt 上，我们需要使用如下的包：</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>frr	</span></span>
<span class="line"><span>frr-ospf6d</span></span>
<span class="line"><span>frr-ospfd</span></span>
<span class="line"><span>frr-staticd</span></span>
<span class="line"><span>frr-watchfrr</span></span>
<span class="line"><span>frr-zebra</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="hint-container tip">
<p class="hint-container-title">本文使用 10.2.1-2 版本</p>
<p>不同的版本可能命令略有差异，具体以实际为准。</p>
</div>
<h2>Frr 基础使用</h2>
<p>frr 提供了一个集中的命令行控制台叫做 <code>vtysh</code>，需要使用 root 权限运行。它的命令和 Cisco 的 IOS 长得很像，玩过 Packet Tracer 的应该知道怎么个事。</p>
<p>命令也是分作用域的，比如刚开始 <code>#</code> 下面我们只能做一些信息查询的工作，比如</p>
<ul>
<li><code>show ip route</code>: 查询 IPv4 路由信息</li>
<li><code>show ipv6 route</code>: 查询 IPv6 路由信息</li>
<li><code>show ip ospf neigh</code>: 查询 IPv4 OSPF 邻居</li>
<li><code>show ipv6 ospf6 neigh</code>: 查询 IPv6 OSPF 邻居</li>
<li><code>show running-conf</code>: 查询正在运行的配置，<strong>其实就是按照层级记录采用了的配置命令，可以手动重现</strong></li>
<li><code>write</code>: 将当前配置写入配置文件，重启后也有效</li>
</ul>
<p>而在基础模式下输入 <code>conf</code> 我们就进入了配置模式。这个模式我们可以配置全局的一些东西，比如</p>
<ul>
<li><code>router-id &lt;A.B.C.D&gt;</code> 可以配置路由器 ID</li>
</ul>
<p>在配置模式下，我们还可以使用 <code>router &lt;xxx&gt;</code> 来配置某一个路由协议，使用 <code>interface &lt;xxx&gt;</code> 来配置一个接口。</p>
<p>此外，如果想要删除某个配置，在原来配置命令的前面加 <code>no</code> 就可以了。</p>
<h2>实验</h2>
<p>场景如下，两台路由器 A 和 B 通过两个 WireGuard 隧道连接（IPv4 和 IPv6 分离），隧道内允许的 IP 都是 <code>0.0.0.0/0</code> 和 <code>::/0</code>。</p>
<table>
<thead>
<tr>
<th style="text-align:center">路由器</th>
<th style="text-align:center">Router ID</th>
<th style="text-align:center">IPv4 隧道地址</th>
<th style="text-align:center">IPv6 隧道地址 (ULA)</th>
<th style="text-align:center">宣告的 IPv4 块</th>
<th style="text-align:center">宣告的 IPv6 块</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">A</td>
<td style="text-align:center"><code>192.168.0.254</code></td>
<td style="text-align:center"><code>192.168.0.254/32</code></td>
<td style="text-align:center"><code>fd00:f000::1/128</code>, <code>fe80::192:168:0:254/64</code></td>
<td style="text-align:center"><code>192.168.0.0/22</code></td>
<td style="text-align:center"><code>fd00:10::/60</code></td>
</tr>
<tr>
<td style="text-align:center">B</td>
<td style="text-align:center"><code>192.168.8.254</code></td>
<td style="text-align:center"><code>192.168.8.254/32</code></td>
<td style="text-align:center"><code>fd00:f000::2/128</code>, <code>fe80::192:168:8:254/64</code></td>
<td style="text-align:center"><code>192.168.8.0/22</code></td>
<td style="text-align:center"><code>fd00:20::/60</code></td>
</tr>
</tbody>
</table>
<div class="hint-container tip">
<p class="hint-container-title">注意</p>
<p>Router A 的隧道地址 (<code>192.168.0.254</code>) 包含在其本地宣告块 (<code>192.168.0.0/22</code>) 内。这不是一个好的分离实践，但是我本地为了方便管理就这么干了，而由于我们使用了 <code>/32</code> 和 <code>point-to-point</code> 网络类型，有一个更长的前缀路由，OSPF 可以正常工作。</p>
</div>
<div class="hint-container info">
<p class="hint-container-title">相关信息</p>
<ul>
<li>
<p><code>router ospf</code> 下面的 <code>network</code> 指令不能和使用了 <code>ip ospf area x.y.z.w</code> 的 <code>interface</code> 同时存在。</p>
</li>
<li>
<p>以下还聚合宣告了块，这要求要么 area 中有至少一个活动路由，要么配置一个静态路由然后在 <code>router ospf</code> 下做 <code>redistribute static</code>。后者可能还需要挂 filter，不然会把所有静态路由都宣布出去。</p>
</li>
</ul>
</div>
<p>以下是最终的示意配置文件，供参考：</p>
<h3>路由器 A (R-A):</h3>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>!</span></span>
<span class="line"><span>frr version 10.2.1</span></span>
<span class="line"><span>frr defaults traditional</span></span>
<span class="line"><span>hostname R-A</span></span>
<span class="line"><span>log syslog</span></span>
<span class="line"><span>!</span></span>
<span class="line"><span>password [YOUR_SECURE_PASSWORD]</span></span>
<span class="line"><span>!</span></span>
<span class="line"><span>ip route 192.168.0.0/16 reject        # 内部地址防环/黑洞策略</span></span>
<span class="line"><span>ip router-id 192.168.0.254            # 路由器A的Router ID</span></span>
<span class="line"><span>!</span></span>
<span class="line"><span>interface eth0</span></span>
<span class="line"><span> ip address 192.168.3.254/24          # 假设eth0的IP</span></span>
<span class="line"><span> ip ospf area 2.0.0.0                 # 本地区域 2.0.0.0</span></span>
<span class="line"><span>exit</span></span>
<span class="line"><span>!</span></span>
<span class="line"><span>interface wg4</span></span>
<span class="line"><span> ip address 192.168.0.254/32          # 隧道IPv4地址 (简易起见与Router ID一致)</span></span>
<span class="line"><span> ip ospf area 0                       # 骨干网区域，area 0 = 0.0.0.0</span></span>
<span class="line"><span> ip ospf network point-to-point       # 指定为点对点网络</span></span>
<span class="line"><span> no ip ospf passive                   # 在这个接口上取消被动接口，即宣告 OSPF 信息</span></span>
<span class="line"><span>exit</span></span>
<span class="line"><span>!</span></span>
<span class="line"><span>interface wg6</span></span>
<span class="line"><span> ipv6 address fd00:f000::1/128        # 隧道IPv6 ULA地址</span></span>
<span class="line"><span> ipv6 address fe80::192:168:0:254/64  # 链路本地地址</span></span>
<span class="line"><span> ipv6 ospf6 area 0                    </span></span>
<span class="line"><span> ipv6 ospf6 network point-to-point</span></span>
<span class="line"><span>exit</span></span>
<span class="line"><span>!</span></span>
<span class="line"><span>router ospf</span></span>
<span class="line"><span> passive-interface default            # 默认接口被动，即默认不宣告 OSPF </span></span>
<span class="line"><span> area 2.0.0.0 range 192.168.0.0/22    # 聚合/通告本地网络 (A 的本地块)</span></span>
<span class="line"><span> default-information originate        # (可选) 宣告一个默认路由</span></span>
<span class="line"><span>exit</span></span>
<span class="line"><span>!</span></span>
<span class="line"><span>router ospf6</span></span>
<span class="line"><span> ospf6 router-id 192.168.0.254        # 这个 router-id 似乎是独立的</span></span>
<span class="line"><span> area 2.0.0.0 range fd00:10::/60      # 聚合/通告本地网络 (A的本地块)</span></span>
<span class="line"><span>exit</span></span>
<span class="line"><span>!</span></span>
<span class="line"><span>access-list vty seq 5 permit 127.0.0.0/8</span></span>
<span class="line"><span>access-list vty seq 10 deny any</span></span>
<span class="line"><span>!</span></span>
<span class="line"><span>line vty</span></span>
<span class="line"><span> access-class vty</span></span>
<span class="line"><span>exit</span></span>
<span class="line"><span>!</span></span>
<span class="line"><span>end</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3>路由器 B (R-B):</h3>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>!</span></span>
<span class="line"><span>frr version 10.2.1</span></span>
<span class="line"><span>frr defaults traditional</span></span>
<span class="line"><span>hostname R-B</span></span>
<span class="line"><span>log syslog</span></span>
<span class="line"><span>!</span></span>
<span class="line"><span>password [YOUR_SECURE_PASSWORD]</span></span>
<span class="line"><span>!</span></span>
<span class="line"><span>ip route 192.168.0.0/16 reject        # 内部地址防环/黑洞策略</span></span>
<span class="line"><span>ip router-id 192.168.8.254            # 路由器B的Router ID (与隧道IP一致)</span></span>
<span class="line"><span>!</span></span>
<span class="line"><span>interface eth0</span></span>
<span class="line"><span> ip address 192.168.11.254/24         # 假设eth0的IP</span></span>
<span class="line"><span> ip ospf area 1.0.0.0</span></span>
<span class="line"><span> ip ospf network broadcast            # 这个接口是广播接口，可以通过交换机连接子 OSPF 交换机 </span></span>
<span class="line"><span> ip ospf priority 255                 # 主路由器给高优先级，DR/BDR 选举时成为 DR</span></span>
<span class="line"><span> ipv6 ospf6 area 1.0.0.0</span></span>
<span class="line"><span> no ip ospf passive</span></span>
<span class="line"><span>exit</span></span>
<span class="line"><span>!</span></span>
<span class="line"><span>interface wg4</span></span>
<span class="line"><span> ip address 192.168.8.254/32          # 隧道IPv4地址 (与Router ID一致)</span></span>
<span class="line"><span> ip ospf area 0</span></span>
<span class="line"><span> ip ospf network point-to-point</span></span>
<span class="line"><span> no ip ospf passive</span></span>
<span class="line"><span>exit</span></span>
<span class="line"><span>!</span></span>
<span class="line"><span>interface wg6</span></span>
<span class="line"><span> ipv6 address fd00:f000::2/128        # 隧道IPv6 ULA地址</span></span>
<span class="line"><span> ipv6 address fe80::192:168:8:254/64  # 链路本地地址</span></span>
<span class="line"><span> ipv6 ospf6 area 0</span></span>
<span class="line"><span> ipv6 ospf6 network point-to-point</span></span>
<span class="line"><span>exit</span></span>
<span class="line"><span>!</span></span>
<span class="line"><span>router ospf</span></span>
<span class="line"><span> passive-interface default</span></span>
<span class="line"><span> area 1.0.0.0 range 192.168.8.0/22    # 聚合/通告本地网络 (B的本地块)</span></span>
<span class="line"><span>exit</span></span>
<span class="line"><span>!</span></span>
<span class="line"><span>router ospf6</span></span>
<span class="line"><span> area 1.0.0.0 range fd00:20::/60      # 聚合/通告本地网络 (B的本地块)</span></span>
<span class="line"><span>exit</span></span>
<span class="line"><span>!</span></span>
<span class="line"><span>access-list vty seq 5 permit 127.0.0.0/8</span></span>
<span class="line"><span>access-list vty seq 10 deny any</span></span>
<span class="line"><span>!</span></span>
<span class="line"><span>line vty</span></span>
<span class="line"><span> access-class vty</span></span>
<span class="line"><span>exit</span></span>
<span class="line"><span>!</span></span>
<span class="line"><span>end</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3>效果</h3>
<p>查看路由表，可以看到对方宣告过来的路由以 <code>O&gt;*</code> 标记，这表明路由是 OSPF 宣告的，已被选中并安装到内核中。<br>
然后 ping 一下，双方都可以 ping 通。</p>
<p>EOF~</p>
]]></content:encoded>
    </item>
    <item>
      <title>浅谈 IPv6 地址设计与分配</title>
      <link>https://octz.net/blog/Note/thoughts-about-ipv6.html</link>
      <guid>https://octz.net/blog/Note/thoughts-about-ipv6.html</guid>
      <source url="https://octz.net/rss.xml">浅谈 IPv6 地址设计与分配</source>
      <description>免责声明 以下仅为个人观点，实际以 RFC 为准。 关于 IPv6 地址设计思想？ 地址总长度的选择 我们都知道，传统的 IP 地址（也就是 IPv4 地址）只有 32 位，其中的公网可用部分已经在前些年完全分配完毕。 IPv6 的提出，一方面要尽可能的缓解地址短缺的问题，另一方面也要尽力的缓解路由碎片化的问题，减少广域网骨干路由表的大小。 如果回到 ...</description>
      <category>Note</category>
      <pubDate>Wed, 26 Nov 2025 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<div class="hint-container tip">
<p class="hint-container-title">免责声明</p>
<p>以下仅为个人观点，实际以 RFC 为准。</p>
</div>
<!-- ## 什么是 IPv6 地址

IPv6，就是 Internet Protocol Version 6，是一个具有 128 位地址空间的，面向下一代互联网的互联网协议版本。

典型的 IPv6 地址分为高位和低位两部分，即 64 位的前缀和 64 位的接口ID:

```
+-->]]></content:encoded>
    </item>
    <item>
      <title>Step into Chromium (1) - GN 构建系统简述</title>
      <link>https://octz.net/blog/Chromium/1-SimpleGN.html</link>
      <guid>https://octz.net/blog/Chromium/1-SimpleGN.html</guid>
      <source url="https://octz.net/rss.xml">Step into Chromium (1) - GN 构建系统简述</source>
      <description>这是什么 源 https://gn.googlesource.com/gn/ GN 是一个可生成 Ninja 构建配置文件的源构建系统。常用 C/C++ 的同志们都知道 CMake，GN 在某种意义上和 CMake 同级，只不过它只能生成 Ninja makefile，但也提供比 CMake 更多更便利的功能。 和 CMake 类似，GN 也是一个 D...</description>
      <category>Chromium</category>
      <pubDate>Fri, 24 Oct 2025 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>这是什么</h2>
<div class="hint-container tip">
<p class="hint-container-title">源</p>
<p><a href="https://gn.googlesource.com/gn/" target="_blank" rel="noopener noreferrer">https://gn.googlesource.com/gn/</a></p>
</div>
<p>GN 是一个可生成 Ninja 构建配置文件的源构建系统。常用 C/C++ 的同志们都知道 CMake，GN 在某种意义上和 CMake 同级，只不过它只能生成 Ninja makefile，但也提供比 CMake 更多更便利的功能。</p>
<p>和 CMake 类似，GN 也是一个 DSL (领域特定语言)，像是 Python 和 C 的混合体。</p>
<p><strong>这并不是一个完整的教程，只是用到了就会来补充用法，权当一个速查手册。</strong></p>
<h2>如何：构建一个可执行文件/库</h2>
<p>写一个 <code>BUILD.gn</code>（不要改名）：</p>
<div class="language-gn line-numbers-mode" data-highlighter="shiki" data-ext="gn" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-gn"><span class="line"><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">executable</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"demo_exe"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) {</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">  sources</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> = [ </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"demo.cc"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ]</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>That's All!</p>
<p>这里我们创建了一个名叫 <code>demo_exe</code> 的 target，类型是可执行文件，源文件有 <code>demo.cc</code>。</p>
<p>对于静态库，使用 <code>static_library</code>；动态库是 <code>shared_library</code>。</p>
<h2>如何：引入一个组件/静态库</h2>
<p>这在 GN 中被描述为“依赖” (deps)。如果我们的 <code>demo_exe</code> 使用了 <code>base</code> 库的内容，则我们需要这样将依赖加入 deps 数组即可：</p>
<div class="language-gn line-numbers-mode" data-highlighter="shiki" data-ext="gn" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-gn"><span class="line"><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">executable</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"demo_exe"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) {</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">  sources</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> = [ </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"demo.cc"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ]</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">  deps</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> = [ </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"//base"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ] </span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"># here</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><code>//</code> 是指项目根目录。</p>
<h2>如何：预定义一个宏</h2>
<p>在 target 内部加入 defines 数组即可：</p>
<div class="language-gn line-numbers-mode" data-highlighter="shiki" data-ext="gn" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-gn"><span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">defines</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> = [</span></span>
<span class="line"><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">  "HELLO_SHARED_IMPLEMENTATION"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span></span>
<span class="line"><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">  "ENABLE_DOOM_MELON=0"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">]</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2>如何：条件编译</h2>
<p>GN 内部存在很多的变量，我们也可以可以定义变量，然后使用条件控制语句控制。</p>
<p>以常见的跨平台场景为例，我们有 <code>demo.h</code> 定义了接口，然后对于 Windows, linux 和 mac 有 <code>demo_win.cc</code>, <code>demo_linux.cc</code> 和 <code>demo_mac.cc</code> 作为实现。则可以这样写：</p>
<div class="language-gn line-numbers-mode" data-highlighter="shiki" data-ext="gn" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-gn"><span class="line"><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">executable</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"demo_exe"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) {</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">  sources</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> = [ </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"demo.h"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ]</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">is_win</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">){</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">    sources</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> += [</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"demo_win.cc"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">]</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">  }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">is_linux</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">){</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">    sources</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> += [</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"demo_linux.cc"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">]</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">  }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">is_mac</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) {</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">    sources</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> += [</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"demo_mac.cc"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">]</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">  }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这里的 <code>is_win</code>，<code>is_linux</code> 和 <code>is_mac</code> 都是 GN 的预定义变量。自定义变量只需要直接写 <code>var_name = value</code> 即可。</p>
<h2>如何：生成 Ninja 构建文件</h2>
<div class="language-shell line-numbers-mode" data-highlighter="shiki" data-ext="shell" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-shell"><span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">$</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> gn</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> gen</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> &#x3C;</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">out_di</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">r></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>随后转到 <code>out_dir</code> 执行 ninja 即可。</p>
]]></content:encoded>
    </item>
    <item>
      <title>面向 VRChat 的渲染入门 (2) 失败的透明</title>
      <link>https://octz.net/games/vrchat/tech/shader1.html</link>
      <guid>https://octz.net/games/vrchat/tech/shader1.html</guid>
      <source url="https://octz.net/rss.xml">面向 VRChat 的渲染入门 (2) 失败的透明</source>
      <description>前言 失败了，姑且看看图吧，拿来照玩家的话有些不好看... emmm...emmm... 前置/参考 主要需要了解颜色混合(Blend)、Stencil 和 ZTest。参见原课程 录播 和 课件。 密度较大，需要暂停理解 实现方法 如何：混合颜色 由于渲染管线的并行特性限制，我们并不能在一个 Pixel Shader 中读写同一个缓冲区。那么，我们如...</description>
      <category>Game</category>
      <pubDate>Wed, 29 Oct 2025 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>前言</h2>
<p>失败了，姑且看看图吧，拿来照玩家的话有些不好看...</p>
<figure><img src="https://imgcdn0.octz.net/vrchat/tech/image-5.png" alt="emmm..." tabindex="0" loading="lazy"><figcaption>emmm...</figcaption></figure>
<div class="hint-container tip">
<p class="hint-container-title">前置/参考</p>
<p>主要需要了解颜色混合(Blend)、Stencil 和 ZTest。参见原课程 <a href="https://www.bilibili.com/video/BV164xNz8EUd" target="_blank" rel="noopener noreferrer">录播</a> 和 <a href="https://docs.qq.com/slide/DUHFqWnJLb0JDcVdU" target="_blank" rel="noopener noreferrer">课件</a>。</p>
<p><strong>密度较大，需要暂停理解</strong></p>
</div>
<h2>实现方法</h2>
<h3>如何：混合颜色</h3>
<p>由于渲染管线的并行特性限制，我们并不能在一个 Pixel Shader 中读写同一个缓冲区。那么，我们如何将当前的颜色和已经绘制的颜色混合起来呢？答案是通过 Blend 指令。Blend 指令将在渲染管线的特定步骤执行，以将当前 Pixel Shader 的输出缓冲 (Source) 和屏幕缓冲区(Destination) 以指定的方式混合。典型操作表达式为：</p>
<p>其中 OP 代表某种操作，通常是加，也可以是下面这几十种（以 <code>[Enum(UnityEngine.Rendering.BlendOp)]</code> 注明）</p>
<figure><img src="https://imgcdn0.octz.net/vrchat/tech/image-6.png" alt="Blend Operation" tabindex="0" loading="lazy"><figcaption>Blend Operation</figcaption></figure>
<p>而 Blend 指令的基础格式是：</p>
<div class="language-hlsl line-numbers-mode" data-highlighter="shiki" data-ext="hlsl" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-hlsl"><span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">Blend [RT] &#x3C;Src> &#x3C;Dst> | &#x3C;SrcRGB> &#x3C;DstRGB>, &#x3C;SrcA> &#x3C;DstA></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p><code>Src</code> 等参数统称为 Blend Mode, 其取值以 <code>[Enum(UnityEngine.Rendering.BlendMode)]</code> 注明，有如下几个：</p>
<figure><img src="https://imgcdn0.octz.net/vrchat/tech/image-7.png" alt="Blend Mode" tabindex="0" loading="lazy"><figcaption>Blend Mode</figcaption></figure>
<p>我们要实现一种朦胧感，考虑让材质输出为一个灰色蒙版，随后配置 Source blend mode 为 <code>One</code>，Destination blend mode 为 <code>OneMinusSrcColor</code>。</p>
<h3>如何：选择范围</h3>
<p>我们当然不希望所有东西都被我们选中并且做颜色混合。总结起来，</p>
<ol>
<li>一帧画面有一个渲染队列，每个 Material 可以指定其排序优先级，渲染时从低到高执行渲染</li>
<li>在 PS 输出后，根据模板缓冲 (Stencil Buffer) 做 StencilTest，如果不通过，则该像素丢弃；测试后可以按情况修改 Stencil Buffer</li>
<li>在 StencilTest 后，根据深度缓冲 (Depth Buffer) 做 ZTest，如果不通过，则该像素丢弃；测试后可以按情况修改 Depth Buffer</li>
<li>都通过的像素进行 Blend 后输出</li>
</ol>
<p>所以实际上，我们可以控制的是 RenderQueue，StencilTest 和 ZTest 的行为。</p>
<p>这部分内容过多，建议查看原视频理解掌握。这里给出几张图和说明，帮助理解：</p>
<figure><img src="https://imgcdn0.octz.net/vrchat/tech/image-9.png" alt="可爱的 Eku 猫猫的手" tabindex="0" loading="lazy"><figcaption>可爱的 Eku 猫猫的手</figcaption></figure>
<p>其中，手是素体的一部分，其 RenderQueue 为 2451，Stencli 为 Always Keep (0)， ZWrite = true；<br>
衣服的 RenderQueue 为 2460，Stencli 和 ZWrite 都和素体保持一样的设定。</p>
<p>在这前面放置一个胶囊，应用我们的材质，然后 Blend Mode 设置和上面混合颜色设置一致。</p>
<figure><img src="https://imgcdn0.octz.net/vrchat/tech/image-10.png" alt="仅设定 RenderQueue 为 2455" tabindex="0" loading="lazy"><figcaption>仅设定 RenderQueue 为 2455</figcaption></figure>
<p>这种情况下，先绘制了素体，然后绘制我们的胶囊。胶囊绘制完成后，由于其 ZWrite 为 On，且胶囊比衣服离我们更近，所以深度缓冲被写入了更大的值；随后绘制衣服，在 ZTest 时已被胶囊绘制的部分会失败，从而维持胶囊的绘制结果，显示为部分透明。(如果设置 RenderQueue 为 2461 则这种透明消失)</p>
<p>在此基础上，我们再设置素体的 Stencil 为 Always Replace (22)，随后在胶囊材质设置 StencilTest Mode 为 Euqal 22，可以得到：</p>
<figure><img src="https://imgcdn0.octz.net/vrchat/tech/image-11.png" alt="部分可见的手臂" tabindex="0" loading="lazy"><figcaption>部分可见的手臂</figcaption></figure>
<p>这是因为 Stencil 测试通过的只有素体在胶囊这个范围内的部分，也只有这些东西被混合了并且写了深度。</p>
<p>当我们关闭深度写入，以上的一切都消失了，又回到了原本的样子。这是因为后续衣服在渲染的时候发现自身的Z小于缓冲区里的（ZTest 默认 LessEqual Pass），进行了覆盖。这就是 ZTest 的意义。</p>
<p>补充一点，正经的半透明物体一般做法是将渲染队列开高，然后将 ZWrite 关闭。这样就可以达到该透过的物品已经绘制了，但是位于半透明物品前（更靠近摄像机）的物体仍然可以进行正确的覆盖，符合预期。</p>
<h2>最终代码</h2>
<div class="language-shaderlab line-numbers-mode" data-highlighter="shiki" data-ext="shaderlab" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-shaderlab"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">Shader</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "Unlit/ScreenMaskShader"</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    Properties</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        _MainTex (</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Texture"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">2D</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) = </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"white"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> { }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        </span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        [</span><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">Enum</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(UnityEngine.Rendering.BlendMode)]</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        _SrcBlend (</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Source blend"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">Float</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) = </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        [</span><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">Enum</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(UnityEngine.Rendering.BlendMode)]</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        _DstBlend (</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Destination blend"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">Float</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) = </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        [</span><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">Enum</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(UnityEngine.Rendering.BlendOp)]</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        _BlendOp (</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Blend Operation"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">Float</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) = </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        _StencilRef (</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Stencil Ref Value"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">Range</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">255</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)) = </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        [</span><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">Enum</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(UnityEngine.Rendering.CompareFunction)]</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        _StencilComp (</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Stencil Compare Mode"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">Float</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) = </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        [</span><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">Enum</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(UnityEngine.Rendering.StencilOp)]</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        _StencilPassOp (</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Stencil Pass Operation"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">Float</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) = </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        [</span><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">Enum</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(UnityEngine.Rendering.StencilOp)]</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        _StencilFailOp (</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Stencil Fail Operation"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">Float</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) = </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        [</span><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">Enum</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(UnityEngine.Rendering.CompareFunction)]</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        _ZTestComp (</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"ZTest Compare function"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">Float</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) = </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        [</span><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">Enum</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(Off, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, On, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)]</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        _ZWrite (</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"ZWrite"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">Float</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) = </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    SubShader</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">        Tags</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> { </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"RenderType"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> = </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Opaque"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> }</span></span>
<span class="line"><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">        LOD</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 100</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        Pass</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">            Blend</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> [_SrcBlend] [_DstBlend]</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            // Blend Zero One, SrcAlpha OneMinusSrcAlpha</span></span>
<span class="line"><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">            BlendOp</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> [_BlendOp]</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            // ColorMask 0</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">            Stencil</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> </span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            { </span></span>
<span class="line"><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">                Ref</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> [_StencilRef]</span></span>
<span class="line"><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">                Comp</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> [_StencilComp]</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                Pass</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> [_StencilPassOp]</span></span>
<span class="line"><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">                Fail</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> [_StencilFailOp]</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">            ZTest</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> [_ZTestComp]</span></span>
<span class="line"><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">            ZWrite</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> [_ZWrite]</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            HLSLPROGRAM</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            #pragma</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> vertex vert</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            #pragma</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> fragment frag</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            // make fog work</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            #pragma</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> multi_compile_fog</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            #include</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "UnityCG.cginc"</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            struct</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> appdata</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                float4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> vertex : </span><span style="--shiki-light:#383A42;--shiki-dark:#E5C07B">POSITION</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                float2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> uv : </span><span style="--shiki-light:#383A42;--shiki-dark:#E5C07B">TEXCOORD0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            };</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            struct</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> v2f</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                float2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> uv : </span><span style="--shiki-light:#383A42;--shiki-dark:#E5C07B">TEXCOORD0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">                UNITY_FOG_COORDS</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                float4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> vertex : SV_POSITION;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            };</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">            sampler2D</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _MainTex;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            float4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _MainTex_ST;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            v2f </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">vert</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(appdata v)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                v2f o;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                o.vertex = </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">UnityObjectToClipPos</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(v.vertex);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                o.uv = </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">TRANSFORM_TEX</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(v.uv, _MainTex);</span></span>
<span class="line"><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">                UNITY_TRANSFER_FOG</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(o, o.vertex);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> o;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            fixed4</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2"> frag</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(v2f i) : SV_Target</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                fixed4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> col = </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">tex2D</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(_MainTex, i.uv);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                col *= </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0.08</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                </span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                // apply fog</span></span>
<span class="line"><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">                UNITY_APPLY_FOG</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(i.fogCoord, col);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> col;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            ENDHLSL</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>liltoon 啥都有，但是为了简化模型还是手搓了</strong></p>
<h2>附注</h2>
<p>关于各种缓冲区的结论，是使用 RenderDoc 抓帧得到的，但是仍然有如下几个点：</p>
<ol>
<li>抓到的帧上下颠倒：DX11 的 Y 轴倒置。</li>
<li>深度缓冲中，离摄像机越近的 Z 越大，但是 ZTest 时行为又是离摄像机越远越大：DX11 的 Z 轴倒置。</li>
<li>Game 中看到的提前写了更大深度的区域为黑色~白色闪动，但是场景中正常</li>
</ol>
<figure><img src="https://imgcdn0.octz.net/vrchat/tech/image-12.png" alt="例子" tabindex="0" loading="lazy"><figcaption>例子</figcaption></figure>
<p>暂未找到原因。</p>
]]></content:encoded>
      <enclosure url="https://imgcdn0.octz.net/vrchat/tech/image-5.png" type="image/png"/>
    </item>
    <item>
      <title>面向 VRChat 的渲染入门 (1) Shader 基础笔记</title>
      <link>https://octz.net/games/vrchat/tech/shader0.html</link>
      <guid>https://octz.net/games/vrchat/tech/shader0.html</guid>
      <source url="https://octz.net/rss.xml">面向 VRChat 的渲染入门 (1) Shader 基础笔记</source>
      <description>前言 算是一个作业记录？哈哈哈 任务是使用 shader 实现： 线性渐变 径向渐变 进度条 什么是线性渐变和径向渐变 不知道喵，看 MDN linear-gradient() 和 radial-gradient() 体会一下。 效果图效果图 环境预设 搭建一个场景，存在这样的一个 Cube: Cube InspectorCube Inspector ...</description>
      <category>Game</category>
      <pubDate>Mon, 20 Oct 2025 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>前言</h2>
<blockquote>
<p>算是一个作业记录？哈哈哈</p>
</blockquote>
<p>任务是使用 shader 实现：</p>
<ol>
<li>线性渐变</li>
<li>径向渐变</li>
<li>进度条</li>
</ol>
<div class="hint-container tip">
<p class="hint-container-title">什么是线性渐变和径向渐变</p>
<p>不知道喵，看 MDN <a href="https://developer.mozilla.org/zh-CN/docs/Web/CSS/gradient/linear-gradient" target="_blank" rel="noopener noreferrer">linear-gradient()</a> 和 <a href="https://developer.mozilla.org/zh-CN/docs/Web/CSS/gradient/radial-gradient" target="_blank" rel="noopener noreferrer">radial-gradient()</a> 体会一下。</p>
</div>
<figure><img src="https://imgcdn0.octz.net/vrchat/tech/image-2.png" alt="效果图" tabindex="0" loading="lazy"><figcaption>效果图</figcaption></figure>
<h2>环境预设</h2>
<p>搭建一个场景，存在这样的一个 Cube:</p>
<figure><img src="https://imgcdn0.octz.net/vrchat/tech/image-1.png" alt="Cube Inspector" tabindex="0" loading="lazy"><figcaption>Cube Inspector</figcaption></figure>
<p>一个 Cube 有 6 个面，考虑每个面渲染一个图像，主要工作在顶点着色器上，我们预先写下一个板子：</p>
<div class="language-shaderlab line-numbers-mode" data-highlighter="shiki" data-ext="shaderlab" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-shaderlab"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">Shader</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "Unlit/NewUnlitShader"</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    Properties</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        _MainTex (</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Texture"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">2D</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) = </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"white"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> { }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    SubShader</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">        Tags</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> { </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"RenderType"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> = </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Opaque"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> }</span></span>
<span class="line"><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">        LOD</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 100</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        Pass</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            HLSLPROGRAM</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            #pragma</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> vertex vert</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            #pragma</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> fragment frag</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            // make fog work</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            #pragma</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> multi_compile_fog</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            #include</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "UnityCG.cginc"</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            struct</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> v2f</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                float2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> uv : </span><span style="--shiki-light:#383A42;--shiki-dark:#E5C07B">TEXCOORD0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">                UNITY_FOG_COORDS</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                float4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> vertex : SV_POSITION;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                float3</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> worldNormal : </span><span style="--shiki-light:#383A42;--shiki-dark:#E5C07B">NORMAL</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            };</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#0184BC;--shiki-dark:#ABB2BF">            sampler2D</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _MainTex;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            float4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _MainTex_ST;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            v2f </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">vert</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">appdata_base</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> v)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                v2f o;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                o.vertex = </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">UnityObjectToClipPos</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(v.vertex);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                o.uv = </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">TRANSFORM_TEX</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(v.texcoord, _MainTex);</span></span>
<span class="line"><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">                UNITY_TRANSFER_FOG</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(o, o.vertex);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                o.worldNormal = </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">UnityObjectToWorldNormal</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(v.normal);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> o;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            fixed4</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2"> linear_gradient</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">float2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> uv, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">float4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> color1, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">float4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> color2)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            fixed4</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2"> radial_gradient</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">float2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> uv, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">float4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> color1, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">float4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> color2)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            fixed4</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2"> progress_bar</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">float2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> uv, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">float4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> color, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">float</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> percentage)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            fixed4</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2"> frag</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(v2f i) : SV_Target</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                float3</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> normal = </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">normalize</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(i.worldNormal);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                float</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> time = </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">abs</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">sin</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(_Time.y));</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                float4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> col = </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">step</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0.5</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">dot</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(normal, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">float3</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(-</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">))) * </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">linear_gradient</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(i.uv, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">float4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1.0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0.0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0.0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0.0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">), </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">float4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0.0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1.0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0.0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0.0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">))</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                + </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">step</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0.5</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">dot</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(normal, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">float3</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">))) * </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">radial_gradient</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(i.uv, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">float4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1.0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0.0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0.0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0.0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">), </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">float4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0.0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1.0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0.0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0.0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">))</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                + </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">step</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0.5</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">dot</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(normal, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">float3</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, -</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">))) * </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">progress_bar</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(i.uv, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">float4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0.0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1.0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0.0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0.0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">), time);</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                // apply fog</span></span>
<span class="line"><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">                UNITY_APPLY_FOG</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(i.fogCoord, col);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> col;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            ENDHLSL</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>工作就变成了实现 <code>linear_gradient</code> 、<code>radial_gradient</code> 和 <code>progress_bar</code> 这三个函数。</p>
<h2>线性渐变</h2>
<p>考虑最简单的无角度单向渐变，给定两个颜色 <code>color1</code> 和 <code>color2</code>，在一个方形平面内，我们有：</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>(0,1)     (1,1)</span></span>
<span class="line"><span>     +</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div>]]></content:encoded>
      <enclosure url="https://imgcdn0.octz.net/vrchat/tech/image-2.png" type="image/png"/>
    </item>
    <item>
      <title>AbydOS开发日记 (-1) - 第一次上板运行（C906）</title>
      <link>https://octz.net/blog/AbydOS/-1-onboard-c906.html</link>
      <guid>https://octz.net/blog/AbydOS/-1-onboard-c906.html</guid>
      <source url="https://octz.net/rss.xml">AbydOS开发日记 (-1) - 第一次上板运行（C906）</source>
      <description>来上板运行吧！ 写了那么久，也快一个月了，都是在 QEMU 调试，多没意思。电子人，就是干，火速弄了块 Sipeed 的 LicheeRV Nano，基于 C906 和 A53的 SG2002，不到一够水就有百兆网口和 WiFi。（深圳到广州居然发了两天，真是慢啊，还有这排线还要我自己焊，好傻） 拿到板子，插锭，开机，屏幕没有当然点不亮。电脑上不停的叮...</description>
      <category>ABYDOS</category>
      <pubDate>Fri, 05 Apr 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>来上板运行吧！</h2>
<p>写了那么久，也快一个月了，都是在 QEMU 调试，多没意思。电子人，就是干，火速弄了块 Sipeed 的 LicheeRV Nano，基于 C906 和 A53的 SG2002，不到一够水就有百兆网口和 WiFi。（深圳到广州居然发了两天，真是慢啊，还有这排线还要我自己焊，好傻）</p>
<p>拿到板子，插锭，开机，屏幕没有当然点不亮。电脑上不停的叮咚响，看了下是模拟出了一个串口。那就很简单，直接找到镜像，烧录！再把卡插进去，启动！好了，过了一会，多了一个网卡，ssh一下成功，测试功能正常。那么就开始我们的上板之旅吧！</p>
<h2>启动</h2>
<p>我们知道，嵌入式 Linux 的启动流程通常是，FSBL -&gt; 固件 -&gt; U-Boot -&gt; 内核，这里的固件就是 OpenSBI。根据 Sipeed 官网的<a href="https://wiki.sipeed.com/hardware/zh/lichee/RV_Nano/6_develop_mainline.html" target="_blank" rel="noopener noreferrer">描述</a>，这个片子的启动流程如下：</p>
<ol>
<li>bootrom(bl1) 判断sd卡第一个FAT分区内是否拥有 fip.bin，如果有，则执行2，如果没有，则进入usb烧录模式(提供一个ACM串口从机设备),bl1会初始化uart0，波特率128000</li>
<li>加载fip.bin(bl2)里面的代码到0x0C000000(TPU SRAM)，跳转到bl2,初始化clock,DRAM,执行3</li>
<li>加载opensbi到DRAM，执行，然后加载uboot到DRAM，执行，执行4</li>
<li>uboot加载第一个分区内的boot.sd文件到DRAM，如果文件没有问题,跳转到5</li>
<li>跳转到boot.sd内提供的代码(通常是Linux内核)</li>
</ol>
<p>再看 boot 分区的内容，果然如此：</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>Mode                 LastWriteTime         Length Name</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div>]]></content:encoded>
      <enclosure url="https://imgcdn0.octz.net/blog/2024/abydos-c906-1.png" type="image/png"/>
    </item>
    <item>
      <title>AbydOS开发日志 (0) - 工具链和构建系统的选择与调试</title>
      <link>https://octz.net/blog/AbydOS/0-toolchain.html</link>
      <guid>https://octz.net/blog/AbydOS/0-toolchain.html</guid>
      <source url="https://octz.net/rss.xml">AbydOS开发日志 (0) - 工具链和构建系统的选择与调试</source>
      <description>背景 这是 AbydOS 的第一篇博文。近期在学习操作系统，想着自己搞一个玩玩，结合之前开发嵌入式的经验，以及烂尾了的 RISCV 模拟器工程，选定了带有 OpenSBI 支持的 RISCV64 平台。 本文主要记录工具链和构建系统的选择与调试过程。 开端 既然选定了平台，就开始构建 OpenSBI。根据 OpenSBI 的文档，尝试在 Ubuntu ...</description>
      <category>ABYDOS</category>
      <pubDate>Fri, 08 Mar 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>背景</h2>
<p>这是 AbydOS 的第一篇博文。近期在学习操作系统，想着自己搞一个玩玩，结合之前开发嵌入式的经验，以及烂尾了的 RISCV 模拟器工程，选定了带有 OpenSBI 支持的 RISCV64 平台。</p>
<p>本文主要记录工具链和构建系统的选择与调试过程。</p>
<h2>开端</h2>
<p>既然选定了平台，就开始构建 OpenSBI。根据 <a href="https://github.com/riscv-software-src/opensbi/blob/master/docs" target="_blank" rel="noopener noreferrer">OpenSBI 的文档</a>，尝试在 Ubuntu 20.04 (WSL1) 上安装了 <code>gcc-riscv64-unknown-elf</code> 和 <code>qemu-system</code> 等软件包，使用</p>
<div class="language-shell line-numbers-mode" data-highlighter="shiki" data-ext="shell" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-shell"><span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">CROSS_COMPILE</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">riscv64-unknown-elf-</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> make</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> PLATFORM=generic</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>编译之，成功了。开跑，</p>
<div class="language-shell line-numbers-mode" data-highlighter="shiki" data-ext="shell" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-shell"><span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">CROSS_COMPILE</span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">=</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">riscv64-unknown-elf-</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> make</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> PLATFORM=generic</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> run</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>，测试 payload 转起来了。</p>
<h2>新建文件夹</h2>
<p>既然 OpenSBI 编译过了，那就可以新建文件夹了。一开始想，内核的构建比较复杂，OpenSBI 有现成的 Makefile，套娃一个目录结构然后稍微改一下 Makefile，应该可以单独编译 payload，然后再以 payload 为例搭建上层环境。经过一上午的努力，目录结构变成了这样：</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>AbydOS</span></span>
<span class="line"><span>  |</span></span>
<span class="line"><span>  +- kernel</span></span>
<span class="line"><span>  |     |</span></span>
<span class="line"><span>  |     +- main</span></span>
<span class="line"><span>  |          |</span></span>
<span class="line"><span>  |          +- objects.mk</span></span>
<span class="line"><span>  |          +- Kconfig</span></span>
<span class="line"><span>  |          +- test.c</span></span>
<span class="line"><span>  |          +- test.S</span></span>
<span class="line"><span>  |          +- test.ldS</span></span>
<span class="line"><span>  |</span></span>
<span class="line"><span>  +- platform</span></span>
<span class="line"><span>  |      |</span></span>
<span class="line"><span>  |      + qemu-virt</span></span>
<span class="line"><span>  |            |</span></span>
<span class="line"><span>  |            +- objects.mk</span></span>
<span class="line"><span>  |            +- Kconfig</span></span>
<span class="line"><span>  |            +- platform.c</span></span>
<span class="line"><span>  |</span></span>
<span class="line"><span>  +- Kconfig</span></span>
<span class="line"><span>  +- Makefile</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>爆改两个小时的 Makefile，终于是成功编译了。</p>
<h2>尝试 CMake</h2>
<p>改了两个小时的 Makefile，我已经在各种变量和奇怪的命令中晕头转向。这时候，我想到了现代 C++ 工程的神器：CMake。兴奋地写了两句：</p>
<div class="language-cmake line-numbers-mode" data-highlighter="shiki" data-ext="cmake" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cmake"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">cmake_minimum_required</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(VERSION 3.0.0)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">project</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(AbydOS_Kernel VERSION 0.1.0 LANGUAGES C ASM)</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p>VSCODE 选择工具链：<code>GCC 9.3.0 riscv64-unknown-elf</code>，Configure, 爆！</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>[cmake] CMake Error at /usr/share/cmake-3.16/Modules/CMakeTestCCompiler.cmake:60 (message):</span></span>
<span class="line"><span>[cmake]   The C compiler</span></span>
<span class="line"><span>[cmake] </span></span>
<span class="line"><span>[cmake]     "/usr/bin/riscv64-unknown-elf-gcc"</span></span>
<span class="line"><span>[cmake] </span></span>
<span class="line"><span>[cmake]   is not able to compile a simple test program.</span></span>
<span class="line"><span>[cmake] </span></span>
<span class="line"><span>[cmake]   It fails with the following output:</span></span>
<span class="line"><span>[cmake] </span></span>
<span class="line"><span>[cmake]     Change Dir: /home/wsl/AbydOS/build/CMakeFiles/CMakeTmp</span></span>
<span class="line"><span>[cmake]     </span></span>
<span class="line"><span>[cmake]     Run Build Command(s):/usr/bin/make cmTC_164d0/fast &#x26;&#x26; /usr/bin/make -f CMakeFiles/cmTC_164d0.dir/build.make CMakeFiles/cmTC_164d0.dir/build</span></span>
<span class="line"><span>[cmake]     make[1]: Entering directory '/home/wsl/AbydOS/build/CMakeFiles/CMakeTmp'</span></span>
<span class="line"><span>[cmake]     Building C object CMakeFiles/cmTC_164d0.dir/testCCompiler.c.o</span></span>
<span class="line"><span>[cmake]     /usr/bin/riscv64-unknown-elf-gcc    -o CMakeFiles/cmTC_164d0.dir/testCCompiler.c.o   -c /home/wsl/AbydOS/build/CMakeFiles/CMakeTmp/testCCompiler.c</span></span>
<span class="line"><span>[cmake]     Linking C executable cmTC_164d0</span></span>
<span class="line"><span>[cmake]     /usr/bin/cmake -E cmake_link_script CMakeFiles/cmTC_164d0.dir/link.txt --verbose=1</span></span>
<span class="line"><span>[cmake]     /usr/bin/riscv64-unknown-elf-gcc      -rdynamic CMakeFiles/cmTC_164d0.dir/testCCompiler.c.o  -o cmTC_164d0 </span></span>
<span class="line"><span>[cmake]     riscv64-unknown-elf-gcc: error: unrecognized command line option '-rdynamic'</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>于是上网开搜，一看 unknown-elf 工具链没有 crt，肯定不支持 '-rdynamic'，总共有两种解决方案：</p>
<ol>
<li>加入两个命令行参数：-DCMAKE_C_COMPILER_WORKS:STRING=1 -DCMAKE_CXX_COMPILER_WORKS:STRING=1，绕过检查</li>
<li>换工具链</li>
</ol>
<p>考虑到绕过 CMake 的编译器检查可能不太好，选2，安装 <code>gcc-riscv64-linux-gnu</code>。再次尝试 Configure，过了！</p>
<p>于是从原始的 Makefile 抽一点编译参数出来，把 <code>CMakeLists.txt</code> 补全，尝试编译，过了！运行，哎，结果和原来不一样，一个全局const char* 变量 test_args 没有正常初始化，期望是指向 .rodata 段的，可是运行起来是0。</p>
<h2>修修补补</h2>
<p>出现全局变量不初始化的问题，根据嵌入式裸机开发的经验，我第一时间想到的原因是 .data 段没有正常初始化。但是链接脚本没有划分 Memory Region，也没有做 LMA 和 VMA 的指定，.data 段的数据就应该完好地写在 ELF 文件里面。于是上 IDA 分析，一看，这不是初始化得好好的嘛，指向了0x1000。（注意这个坑点！）</p>
<p>由于 QEMU 的手册没有明确内存空间分布，所以 kernel 的起始地址我设成了 0 ，然后使用 -fPIC 参数编译。这样一来，理论上，无论内核被加载到哪里，都应该能够正常跑。搞不定，觉得可能是编译参数不对，改了半天的编译参数，试图去掉自动添加的 '-rdynamic'，无果。（后来明确，这个参数并不指示编译器动态链接）。一天就这样过去了。</p>
<p>第二天，继续修改。由于 ELF 中有 .dynamic 和 。rela.* 段，怀疑是需要重定位，从 OpenSBI 里面抄了一段重定位的汇编代码，再次编译，还是不行。实在没辙了，上 gdb-multiarch 调试，才发现固件运行的地址不是 0x0，不能正常调。找了半天，终于在 OpenSBI 的 platform/generic/objects.mk 里面看到：</p>
<div class="language-makefile line-numbers-mode" data-highlighter="shiki" data-ext="makefile" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-makefile"><span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">FW_TEXT_START</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">=</span><span style="--shiki-light:#383A42;--shiki-dark:#E5C07B">0x80000000</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">FW_DYNAMIC</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">=</span><span style="--shiki-light:#383A42;--shiki-dark:#E5C07B">y</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">FW_JUMP</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">=</span><span style="--shiki-light:#383A42;--shiki-dark:#E5C07B">y</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">ifeq</span><span style="--shiki-light:#383A42;--shiki-dark:#E5C07B"> (</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">$(</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">PLATFORM_RISCV_XLEN</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">)</span><span style="--shiki-light:#383A42;--shiki-dark:#E5C07B">, 32)</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">  # This needs to be 4MB aligned for 32-bit system</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">  FW_JUMP_OFFSET</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">=</span><span style="--shiki-light:#383A42;--shiki-dark:#E5C07B">0x400000</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">else</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">  # This needs to be 2MB aligned for 64-bit system</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">  FW_JUMP_OFFSET</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">=</span><span style="--shiki-light:#383A42;--shiki-dark:#E5C07B">0x200000</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">endif</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这样看，最终运行地址就是 0x80000000 + 0x200000，（</p>
<p>实际上这个值在 OpenSBI 的调试信息就有输出：</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>Domain0 Next Address      : 0x0000000080200000</span></span>
<span class="line"><span>Domain0 Next Arg1         : 0x0000000082200000</span></span>
<span class="line"><span>Domain0 Next Mode         : S-mode</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>)，这样就直接链接脚本改起始地址到 0x80200000，再编译测试，原来跑不通的 fw_jump 固件也正常了。</p>
<p>自此，上 gdb ，就可以正常 debug 了。看了 test_args 的地址，是 0x80203028，和 ELF 中指示的 .data 段范围一致，再 print 一下，就是 0x0 ! 再上 IDA , 这次它的值不是 0x1000 了，而是 0x100401000，一个很怪异的值。看到.rodata段对应地址是 0x80201000，计算器启动，得到 0x100401000 - 0x80201000 = 0x80200000，正好是内核起始地址。于是怀疑全局指针没设对，但是转念想，我都 -fPIC了，寻址应该没有问题，调试出来的 test_args 地址和 IDA 看到的也一致。</p>
<p>这时候想起直接看 ELF 的值了，7z 解压 .data 段， Hex Editor 一看，这TM写的就是0！还是工具链的锅！于是改回 unknown-elf，跳过了 CMake 的编译器检查，终于是 Configure 过了。尝试编译，还是卡在 '-rdynamic' 上，这问题没有根本解决。看报错知道是链接参数的锅，这个链接参数又是 CMake 加上去的，一顿搜索之后找到了 CMake 的一个<a href="https://github.com/Kitware/CMake/commit/9ef3f8e82036a28c4f0375ec65eb25864a5240ca" target="_blank" rel="noopener noreferrer">提交历史</a>，清晰地显示了：</p>
<div class="language-cmake line-numbers-mode" data-highlighter="shiki" data-ext="cmake" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cmake"><span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> # We pass this for historical reasons.  Projects may have</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">  # executables that use dlopen but do not set ENABLE_EXPORTS.</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  set</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(CMAKE_SHARED_LIBRARY_LINK_</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">${lang}</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">_FLAGS </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"-rdynamic"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这样就知道参数从哪里来了。直接在工程的配置里面重写：</p>
<div class="language-cmake line-numbers-mode" data-highlighter="shiki" data-ext="cmake" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cmake"><span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"># get rid of '-rdynamic'</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">set</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(CMAKE_STATIC_LINKER_FLAGS </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">" "</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">set</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">""</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">set</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">""</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这样再配置和编译，就顺利通过了。</p>
<h2>善后工作</h2>
<p>配置好了构建系统和工具链，就该考虑 C++ 支持了。还是老办法，既然 C 的环境由 ASM 初始化，那么 C++ 环境就可以由 C 来初始化。根据经验，只需使用 extern &quot;C&quot; 修饰函数 k_main，然后就可以在 C 里面调用之，之后在 k_main 里面就可以完全使用 C++ 写了。</p>
<p>实践确实如此，不过写了类测试，发现加上析构函数之后编译不过，爆链接错误，链接到了一个叫做 _UnWind_Resume 的函数，在 libstdc++ 里面。想到C++ 的异常捕获机制，析构时会捕获异常，这里没有捕获异常的环境，于是加入 <code>-fno-exceptions</code>参数，再编译就过了。</p>
<p>经过这样的配置，不到 60 行的 CMakeLists，支持了 C++ 写内核，真是太舒服啦！语法特性完全都是可用的！</p>
<h2>后记</h2>
<p>这个配置花了两天多的时间才完成，太痛苦啦！</p>
<p>今天在 <a href="https://gitlab.com/qemu-project/qemu/-/blob/master/hw/riscv/virt.c?ref_type=heads" target="_blank" rel="noopener noreferrer">QEMU 的源码</a> 查到了设备内存布局：</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>static const MemMapEntry virt_memmap[] = {</span></span>
<span class="line"><span>    [VIRT_DEBUG] =        {        0x0,         0x100 },</span></span>
<span class="line"><span>    [VIRT_MROM] =         {     0x1000,        0xf000 },</span></span>
<span class="line"><span>    [VIRT_TEST] =         {   0x100000,        0x1000 },</span></span>
<span class="line"><span>    [VIRT_RTC] =          {   0x101000,        0x1000 },</span></span>
<span class="line"><span>    [VIRT_CLINT] =        {  0x2000000,       0x10000 },</span></span>
<span class="line"><span>    [VIRT_ACLINT_SSWI] =  {  0x2F00000,        0x4000 },</span></span>
<span class="line"><span>    [VIRT_PCIE_PIO] =     {  0x3000000,       0x10000 },</span></span>
<span class="line"><span>    [VIRT_PLATFORM_BUS] = {  0x4000000,     0x2000000 },</span></span>
<span class="line"><span>    [VIRT_PLIC] =         {  0xc000000, VIRT_PLIC_SIZE(VIRT_CPUS_MAX * 2) },</span></span>
<span class="line"><span>    [VIRT_APLIC_M] =      {  0xc000000, APLIC_SIZE(VIRT_CPUS_MAX) },</span></span>
<span class="line"><span>    [VIRT_APLIC_S] =      {  0xd000000, APLIC_SIZE(VIRT_CPUS_MAX) },</span></span>
<span class="line"><span>    [VIRT_UART0] =        { 0x10000000,         0x100 },</span></span>
<span class="line"><span>    [VIRT_VIRTIO] =       { 0x10001000,        0x1000 },</span></span>
<span class="line"><span>    [VIRT_FW_CFG] =       { 0x10100000,          0x18 },</span></span>
<span class="line"><span>    [VIRT_FLASH] =        { 0x20000000,     0x4000000 },                       </span></span>
<span class="line"><span>    [VIRT_IMSIC_M] =      { 0x24000000, VIRT_IMSIC_MAX_SIZE },</span></span>
<span class="line"><span>    [VIRT_IMSIC_S] =      { 0x28000000, VIRT_IMSIC_MAX_SIZE },</span></span>
<span class="line"><span>    [VIRT_PCIE_ECAM] =    { 0x30000000,    0x10000000 },</span></span>
<span class="line"><span>    [VIRT_PCIE_MMIO] =    { 0x40000000,    0x40000000 },</span></span>
<span class="line"><span>    [VIRT_DRAM] =         { 0x80000000,           0x0 },                       </span></span>
<span class="line"><span>};</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>就这样吧，接着搞 MMU 去喽！</p>
]]></content:encoded>
    </item>
    <item>
      <title>AbydOS开发日记 (1) - 基础运行环境构建</title>
      <link>https://octz.net/blog/AbydOS/1-cxx-and-envs.html</link>
      <guid>https://octz.net/blog/AbydOS/1-cxx-and-envs.html</guid>
      <source url="https://octz.net/rss.xml">AbydOS开发日记 (1) - 基础运行环境构建</source>
      <description>基础环境是什么？ 上回说到，通过一点手段，我们成功启用了 C++ 的支持。但是，这样的支持并不完善，我们的内核到目前为止，还没有一个 C 运行库(libc)，更别提 C++ 标准库(libc++)了。这就意味着，所有需要用的函数和类都要手写一份，非常折磨人。所以，引入 C 和 C++ 基础库是接下来要做的事。 嵌入式里边，最常用的 libc 是 new...</description>
      <category>ABYDOS</category>
      <pubDate>Sat, 09 Mar 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>基础环境是什么？</h2>
<p>上回说到，通过一点手段，我们成功启用了 C++ 的支持。但是，这样的支持并不完善，我们的内核到目前为止，还没有一个 C 运行库(libc)，更别提 C++ 标准库(libc++)了。这就意味着，所有需要用的函数和类都要手写一份，非常折磨人。所以，引入 C 和 C++ 基础库是接下来要做的事。</p>
<p>嵌入式里边，最常用的 libc 是 newlib, 而 C++ 的实现则可以使用 libsupc++。</p>
<h2>动工</h2>
<p>之前的编译里边，为了最小化库的引入，我加入了一个编译参数：<code>-nostdlib</code>。这个参数指示 gcc 不要链接标准库。所以要引入标准库，第一步就是把这个参数去掉，但是又不能引入默认的 crt 初始文件，所以还得加上 <code>-nostartfiles</code>，然后测试编译器的支持。很不幸地，我只写了一句：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#include</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> &#x3C;stdio.h></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>然后编译就报错了。一开始，我怀疑是 Include Path 没有设置正确，但是 <code>gcc -v</code> 提示：</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>Using built-in specs.</span></span>
<span class="line"><span>COLLECT_GCC=riscv64-unknown-elf-gcc</span></span>
<span class="line"><span>COLLECT_LTO_WRAPPER=/usr/lib/gcc/riscv64-unknown-elf/9.3.0/lto-wrapper</span></span>
<span class="line"><span>Target: riscv64-unknown-elf</span></span>
<span class="line"><span>Configured with: ../configure --build=x86_64-linux-gnu --prefix=/usr </span></span>
<span class="line"><span>--includedir='/usr/include' </span></span>
<span class="line"><span>--mandir='/usr/share/man' --infodir='/usr/share/info' --sysconfdir=/etc --localstatedir=/var --disable-silent-rules --libdir='/usr/lib/x86_64-linux-gnu' --libexecdir='/usr/lib/x86_64-linux-gnu' --disable-maintainer-mode --disable-dependency-tracking --target=riscv64-unknown-elf --prefix=/usr --infodir=/usr/share/doc/gcc-riscv64-unknown-elf/info --mandir=/usr/share/man --htmldir=/usr/share/doc/gcc-riscv64-unknown-elf/html --pdfdir=/usr/share/doc/gcc-riscv64-unknown-elf/pdf --bindir=/usr/bin --libexecdir=/usr/lib --libdir=/usr/lib --with-pkgversion= --disable-shared --disable-threads --enable-languages=c,c++ --enable-tls --with-newlib --with-native-system-header-dir=/include --disable-libmudflap --disable-libssp --disable-libquadmath --disable-libgomp --disable-nls --with-system-zlib --enable-checking=yes --enable-multilib --with-abi=lp64d --disable-libstdcxx-pch --disable-libstdcxx --disable-fixinc --with-arch=rv64imafdc --with-gnu-as --with-gnu-ld --with-as=/usr/lib/riscv64-unknown-elf/bin/as --with-ld=/usr/lib/riscv64-unknown-elf/bin/ld AR_FOR_TARGET=/usr/lib/riscv64-unknown-elf/bin/ar AS_FOR_TARGET=/usr/lib/riscv64-unknown-elf/bin/as NM_FOR_TARGET=/usr/lib/riscv64-unknown-elf/bin/nm LD_FOR_TARGET=/usr/lib/riscv64-unknown-elf/bin/ld OBJDUMP_FOR_TARGET=/usr/lib/riscv64-unknown-elf/bin/objdump RANLIB_FOR_TARGET=/usr/lib/riscv64-unknown-elf/bin/ranlib READELF_FOR_TARGET=/usr/lib/riscv64-unknown-elf/bin/readelf STRIP_FOR_TARGET=/usr/lib/riscv64-unknown-elf/bin/strip CFLAGS='-g -O2 -fdebug-prefix-map=/build/gcc-riscv64-unknown-elf-3seJsn/gcc-riscv64-unknown-elf-9.3.0=. -fstack-protector-strong' CPPFLAGS='-Wdate-time -D_FORTIFY_SOURCE=2' CXXFLAGS='-g -O2 -fdebug-prefix-map=/build/gcc-riscv64-unknown-elf-3seJsn/gcc-riscv64-unknown-elf-9.3.0=. -fstack-protector-strong' FCFLAGS='-g -O2 -fdebug-prefix-map=/build/gcc-riscv64-unknown-elf-3seJsn/gcc-riscv64-unknown-elf-9.3.0=. -fstack-protector-strong' FFLAGS='-g -O2 -fdebug-prefix-map=/build/gcc-riscv64-unknown-elf-3seJsn/gcc-riscv64-unknown-elf-9.3.0=. -fstack-protector-strong' GCJFLAGS='-g -O2 -fdebug-prefix-map=/build/gcc-riscv64-unknown-elf-3seJsn/gcc-riscv64-unknown-elf-9.3.0=. -fstack-protector-strong' LDFLAGS='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now' OBJCFLAGS='-g -O2 -fdebug-prefix-map=/build/gcc-riscv64-unknown-elf-3seJsn/gcc-riscv64-unknown-elf-9.3.0=. -fstack-protector-strong' OBJCXXFLAGS='-g -O2 -fdebug-prefix-map=/build/gcc-riscv64-unknown-elf-3seJsn/gcc-riscv64-unknown-elf-9.3.0=. -fstack-protector-strong' 'CFLAGS_FOR_TARGET=-Os -mcmodel=medany' 'CXXFLAGS_FOR_TARGET=-Os </span></span>
<span class="line"><span>-mcmodel=medany'</span></span>
<span class="line"><span>Thread model: single</span></span>
<span class="line"><span>gcc version 9.3.0 ()</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这表明默认的 include 目录是 /usr/include ，内存模型是 medany 。到 /usr/include 一看，啥也没有，证明这个包没有附带头文件，更别说预编译的库了。（不愧是裸机工具链，真是全 naked 啊）。</p>
<h2>更换工具链</h2>
<p>手动编译运行时太麻烦，最容易的解决方案就是换一个相同架构的、带有预编译库的工具链。很快，我找到了 <a href="https://github.com/riscv-collab/riscv-gnu-toolchain" target="_blank" rel="noopener noreferrer">riscv-collab/riscv-gnu-toolchain</a> 这个官方的工具链仓库，它的 Release 有预编译的。兴致冲冲地下载下来，解压、配置，编译，爆！</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>...</span></span>
<span class="line"><span>findfp.c:(.text.global_stdio_init.part.0+0x2): relocation truncated to fit: R_RISCV_HI20 against `stdio_exit_handler'</span></span>
<span class="line"><span>/opt/riscv/lib/gcc/riscv64-unknown-elf/13.2.0/../../../../riscv64-unknown-elf/lib/libc.a(libc_a-findfp.o): in function `__sfp':</span></span>
<span class="line"><span>findfp.c:(.text.__sfp+0x0): relocation truncated to fit: R_RISCV_HI20 against symbol `__stdio_exit_handler' defined in .sbss.__stdio_exit_handler section in /opt/riscv/lib/gcc/riscv64-unknown-elf/13.2.0/../../../../riscv64-unknown-elf/lib/libc.a(libc_a-findfp.o)</span></span>
<span class="line"><span>/opt/riscv/lib/gcc/riscv64-unknown-elf/13.2.0/../../../../riscv64-unknown-elf/lib/libc.a(libc_a-findfp.o): in function `__sinit':</span></span>
<span class="line"><span>findfp.c:(.text.__sinit+0x6): additional relocation overflows omitted from the output</span></span>
<span class="line"><span>...</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这里注意到关键信息是 R_RISCV_HI20 。到这个仓库搜 issue，果然有很多问题都类似，问题指向了工具链附带的库使用的内存模型不对，看配置信息确认是使用了 medlow。关于这两种内存模型的区别，实际上要牵扯到 RISCV 的寻址方式，这里不展开，可以查看<a href="https://blog.csdn.net/qianniuwei321/article/details/123483576" target="_blank" rel="noopener noreferrer">这篇博文</a>，这里只要知道 medlow 在 RISCV64 上不能支持我们所设定的内核启动地址 0x80200000。怎么办呢？同样是两种办法，</p>
<ol>
<li>更改内核启动地址</li>
<li>重新编译一份 medany 的工具链</li>
</ol>
<p>第一种方案并不具有可行性，因为在目前的大多数 RISCV SoC 上，DRAM 的起始地址是 0x80000000，低于这个地址能存储内核的空间，只能是不一定存在的 Flash 设备，或者预先被映射过的内存。出于兼容性考虑，选择第二种方案。由于官方仓库采用了 Github Actions 进行构建，我正好可以利用这一点，<a href="https://github.com/DynamicLoader/riscv-gnu-toolchain" target="_blank" rel="noopener noreferrer">fork 一份仓库</a>然后改一下<a href="https://github.com/DynamicLoader/riscv-gnu-toolchain/commit/a7c0a83a39e82191367d30144e95ec9020487bfa" target="_blank" rel="noopener noreferrer">构建配置</a>就可以了。</p>
<p>经过两个多小时的睡觉，这套工具链终于编译好了。下载下来测试，编译顺利通过。</p>
<h2>添加 C printf 的支持</h2>
<p>在之前的代码里，我们的输出函数是直接通过 ecall 调用 SBI 的控制台扩展 (DBCN Extension), 没有任何格式化的支持。要使用 printf 输出到控制台，我们要做的就是重写 printf 调用链最底端的输出函数。这时候 newlib 的方便就体现出来了，它的底层总共也只有二十多个 POSIX 的桩函数，只要实现了它们，移植就算完成了。关系到 printf 的桩函数看起来只有一个，那就是：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> _write</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> fd</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">buf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> size</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>这里的 fd 是文件描述符。简单起见，这里我们可以这样实现：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">// Hook with libc</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> _write</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> fd</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">buf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> size</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    sbi_ecall</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_WRITE, size, (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">unsigned</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> long</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)buf, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> size;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>直接不管 fd。这样之后，添加一个 printf 的调用，编译，不出意料地，报错了：</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>sbrk.c:(.text._sbrk+0x14): undefined reference to `end'</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>这个 sbrk.c 实际上是堆内存分配相关的。这里爆了符号未定义的错误，原因就是我的链接器种没有定义 .heap 段，自然没有提供堆的结束地址。修改链接脚本，在内核末尾添加如下段：</p>
<div class="language-ld line-numbers-mode" data-highlighter="shiki" data-ext="ld" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-ld"><span class="line"><span>.heap : {</span></span>
<span class="line"><span>        __heap_start__ = .;</span></span>
<span class="line"><span>        end = __heap_start__;</span></span>
<span class="line"><span>        _end = end;</span></span>
<span class="line"><span>        __end = end;</span></span>
<span class="line"><span>        KEEP(*(.heap))</span></span>
<span class="line"><span>        __heap_end__ = .;</span></span>
<span class="line"><span>        __HeapLimit = __heap_end__;</span></span>
<span class="line"><span>    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>注意堆区是向上增长的，所以 end = <strong>heap_start</strong>。这样再编译就过了，测试也正常输出了。</p>
<h2>C++: 基础支持</h2>
<p>有了 printf，很容易想到 C++ 的 std::cout。按照依赖关系，不难想到 cout 的最终调用仍然是 _write()，所以输出的底层就不用管了。尝试添加如下代码：</p>
<div class="language-c++ line-numbers-mode" data-highlighter="shiki" data-ext="c++" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c++"><span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">std::cout </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;&#x3C;</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "Hello!</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>编译，又爆了 qwq</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>[build] system_error.cc:(.text.startup._GLOBAL__sub_I__ZSt20__throw_system_errori+0x2): undefined reference to `__dso_handle'</span></span>
<span class="line"><span>[build] /opt/riscv/lib/gcc/riscv64-unknown-elf/13.2.0/../../../../riscv64-unknown-elf/bin/ld: system_error.cc:(.text.startup._GLOBAL__sub_I__ZSt20__throw_system_errori+0x26): undefined reference to `__dso_handle'</span></span>
<span class="line"><span>[build] /opt/riscv/lib/gcc/riscv64-unknown-elf/13.2.0/../../../../riscv64-unknown-elf/bin/ld: AbydOS_KNL: hidden symbol `__dso_handle' isn't defined</span></span>
<span class="line"><span>[build] /opt/riscv/lib/gcc/riscv64-unknown-elf/13.2.0/../../../../riscv64-unknown-elf/bin/ld: final link failed: bad value</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这里提示 __dso_handle 符号找不到，搜索之后知道 DSO 就是 Dynamic Shared Object, 和虚函数那套东西有关系。而 std::cout 又恰好是虚基类派生的，出问题很正常。这里找到了 <a href="https://wiki.osdev.org/C++#GCC" target="_blank" rel="noopener noreferrer">OSDev Wiki</a> 的解释和解决办法，照着文档补上几个函数：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">__dso_handle</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(); </span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __cxa_atexit</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">f</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">),</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">objptr</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">dso</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __cxa_finalize</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">f</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __cxa_pure_virtual</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><ul>
<li>实际还要去除 -ffreestanding 参数，让标准库起作用</li>
</ul>
<p>然后再编译，过了。测试，哎，你怎么卡死了？GDB 一调，好家伙，直接干到 _start_hang 里了，看来是触发了异常然后重置了，由于原子量标记不为0，汇编代码就跳到挂起循环了。想到 std::cout 需要动态分配内存，但是全局new 和 delete 的 operator 没有显式重载，于是加入:</p>
<div class="language-c++ line-numbers-mode" data-highlighter="shiki" data-ext="c++" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c++"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *operator</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> new(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">size_t</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> size</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    return</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> malloc</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(size);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *operator</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> new[](</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">size_t</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> size</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    return</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> malloc</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(size);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> operator</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> delete(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">p</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    free</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(p);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> operator</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> delete[](</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">p</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    free</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(p);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>但是并不起作用，还是卡死。</p>
<h2>C++：异常与栈帧</h2>
<p>既然排除了内存分配问题，该考虑的就是异常处理了。如果它抛出了异常，但是没有被正常 catch，那就会直接调用 _exit()，在 gdb 调试中也能看到：</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>(gdb) backtrace</span></span>
<span class="line"><span>#0  0x000000008021caba in _exit ()</span></span>
<span class="line"><span>#1  0x000000008021190e in abort ()</span></span>
<span class="line"><span>Backtrace stopped: frame did not save the PC</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>然后就找到了 OSDev 关于 libsupc++ 的<a href="https://wiki.osdev.org/Libsupcxx#Full_C.2B.2B_Runtime_Support_Using_libgcc_And_libsupc.2B.2B" target="_blank" rel="noopener noreferrer">异常捕获的说明</a>：</p>
<blockquote>
<p>To make use of exception handling, you also have to tell libsupc++ where the .eh_frame section begins. Before you throw any exception: .<br>
Terminate the .eh_frame section with 4 bytes of zeros (somehow). If you forget this, libsupc++ will never find the end of .eh_frame and generate stupid page faults.</p>
</blockquote>
<p>打开 ELF 文件，确实有 .eh_frame 段产生，还有一堆 .gcc_except_table.* 以及 .srodata.*。这样就先修改链接脚本，把段的起始地址导出来(顺手把没归类的节都归入 .text 和 .srodata 段)：</p>
<div class="language-ld line-numbers-mode" data-highlighter="shiki" data-ext="ld" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-ld"><span class="line"><span>    .text :</span></span>
<span class="line"><span>	{</span></span>
<span class="line"><span>		PROVIDE(_text_start = .);</span></span>
<span class="line"><span>		*(.entry)</span></span>
<span class="line"><span>		*(.text)</span></span>
<span class="line"><span>		*(.text.*)</span></span>
<span class="line"><span>		*(.gcc.*)</span></span>
<span class="line"><span>		*(.gcc_except_table.*)</span></span>
<span class="line"><span>		. = ALIGN(8);</span></span>
<span class="line"><span>		PROVIDE(_text_end = .);</span></span>
<span class="line"><span>	}</span></span>
<span class="line"><span></span></span>
<span class="line"><span>    .eh_frame :</span></span>
<span class="line"><span>	{</span></span>
<span class="line"><span>		PROVIDE(__eh_frame_start = .);</span></span>
<span class="line"><span>		*(.eh_frame);</span></span>
<span class="line"><span>	}</span></span>
<span class="line"><span></span></span>
<span class="line"><span>    .srodata :</span></span>
<span class="line"><span>	{</span></span>
<span class="line"><span>		PROVIDE(_srodata_start = .);</span></span>
<span class="line"><span>    	*(.srodata.cst16)</span></span>
<span class="line"><span>    	*(.srodata.cst8)</span></span>
<span class="line"><span>    	*(.srodata.cst4)</span></span>
<span class="line"><span>    	*(.srodata.cst2)</span></span>
<span class="line"><span>    	*(.srodata .srodata.*)</span></span>
<span class="line"><span>		. = ALIGN(8);</span></span>
<span class="line"><span>		PROVIDE(_srodata_end = .);</span></span>
<span class="line"><span>	}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>然后猜一下 <code>__register_frame()</code> 的原型，在调用 k_main() 之前先调用：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">// Prepare C++ environment</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> k_prep_cxx</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">    // init C++ exceptions</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    extern</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">__eh_frame_start;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    extern</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __register_frame</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // not knowing the prototype of __register_frame, guess and OK!</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    __register_frame</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">__eh_frame_start);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这样再编译测试，成功了！</p>
<h2>善后：全局构造函数与析构函数</h2>
<p>看文档的时候注意到 <a href="https://wiki.osdev.org/Calling_Global_Constructors" target="_blank" rel="noopener noreferrer">Calling Global Constructors</a>，想起来我确实没有给全局构造函数啥的划分段，更别提调用了。再次修改链接脚本，增加：</p>
<div class="language-ld line-numbers-mode" data-highlighter="shiki" data-ext="ld" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-ld"><span class="line"><span>    .init_array :</span></span>
<span class="line"><span>	{</span></span>
<span class="line"><span>	  PROVIDE_HIDDEN (_init_array_start = .);</span></span>
<span class="line"><span>	  KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))</span></span>
<span class="line"><span>	  KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))</span></span>
<span class="line"><span>	  . = ALIGN(8);</span></span>
<span class="line"><span>	  PROVIDE_HIDDEN (_init_array_end = .);</span></span>
<span class="line"><span>	} </span></span>
<span class="line"><span>	</span></span>
<span class="line"><span>	. = ALIGN(0x1000);</span></span>
<span class="line"><span></span></span>
<span class="line"><span>	.fini_array :</span></span>
<span class="line"><span>	{</span></span>
<span class="line"><span>	  PROVIDE_HIDDEN (_fini_array_start = .);</span></span>
<span class="line"><span>	  KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))</span></span>
<span class="line"><span>	  KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))</span></span>
<span class="line"><span>	  . = ALIGN(8);</span></span>
<span class="line"><span>	  PROVIDE_HIDDEN (_fini_array_end = .);</span></span>
<span class="line"><span>	}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>之后增加两段代码，分别在 k_main() 前后调用这些构造函数和析构函数即可。</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">typedef</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">__init_func_ptr)();</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">extern</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> __init_func_ptr </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">_init_array_start</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">], </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">_init_array_end</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">];</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">extern</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> __init_func_ptr </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">_fini_array_start</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">], </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">_fini_array_end</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">];</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">// kernel init</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> k_before_main</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">unsigned</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> long</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">pa0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> unsigned</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> long</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">pa1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">===== Entered Test Kernel =====</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"a0: 0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%lx</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2"> \t</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> a1: 0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%lx</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">pa0, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">pa1);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Calling init_array...</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    for</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (__init_func_ptr </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">func </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _init_array_start; func </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">!=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _init_array_end; func</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">++</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">func)();</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">    // No args, use default</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">pa0 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">pa0 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">unsigned</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> long</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)default_args;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">// kernel exit</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> k_after_main</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> main_ret</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">Reached target k_after_main, clearing up...</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    for</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (__init_func_ptr </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">func </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _fini_array_start; func </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">!=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _fini_array_end; func</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">++</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">func)();</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"===== Test Kernel exited with </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%i</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> =====</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, main_ret);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>至此，基础环境就基本搭建完成，异常、内存分配测试基本通过。总耗时：一天！</p>
]]></content:encoded>
    </item>
    <item>
      <title>AbydOS开发日记 (2) - 驱动程序框架和系统参数配置</title>
      <link>https://octz.net/blog/AbydOS/2-device-detect-and-conf.html</link>
      <guid>https://octz.net/blog/AbydOS/2-device-detect-and-conf.html</guid>
      <source url="https://octz.net/rss.xml">AbydOS开发日记 (2) - 驱动程序框架和系统参数配置</source>
      <description>设备与系统参数 所有连接到系统上的部件，都可以视为设备，从而并入设备驱动框架统一管理。 但是在现代操作系统中，如果没有 ACPI，如何发现设备呢？主线 Linux 已经给出了答案，利用设备树 (Device Tree) 描述。 在设备树中，我们可以描述平台的特性、外设的接入情况、CPU 和 Memory 的数量，还可以携带配置参数，如命令行参数。 由于...</description>
      <category>ABYDOS</category>
      <pubDate>Mon, 11 Mar 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>设备与系统参数</h2>
<p>所有连接到系统上的部件，都可以视为设备，从而并入设备驱动框架统一管理。</p>
<p>但是在现代操作系统中，如果没有 ACPI，如何发现设备呢？主线 Linux 已经给出了答案，利用设备树 (Device Tree) 描述。</p>
<p>在设备树中，我们可以描述平台的特性、外设的接入情况、CPU 和 Memory 的数量，还可以携带配置参数，如命令行参数。</p>
<p>由于树状结构不好存储，所以 Linux 推出了一个工具 <a href="https://git.kernel.org/pub/scm/utils/dtc/dtc.git" target="_blank" rel="noopener noreferrer">DTC</a> (Device Tree Compiler)，用于将设备树源码 (DTS) 编译成扁平化的设备树 (Flattened Device Tree,FDT)，并且提供了一个 libfdt 库进行操作，可以进行增删改查。</p>
<p>本篇记录设备发现、驱动框架搭建和系统参数配置的设计和过程。关于设备树的详细解释，请参阅 <a href="https://www.cnblogs.com/raina/p/15059383.html" target="_blank" rel="noopener noreferrer">Linux设备树</a> 和 <a href="https://blog.csdn.net/qq_36525177/article/details/135377804" target="_blank" rel="noopener noreferrer">设备树的解析 LibFDT</a>。</p>
<h2>驱动框架搭建</h2>
<p>用 CS 的思维来考虑，设备都存在共同之处，也就可以抽象成一个基类。这里给出定义：</p>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> DRV_INSTALL_FUNC</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">V</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">__attribute__</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">((</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">constructor</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(V)))</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">typedef</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> enum</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">    DEV_TYPE_SYS</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> =</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">    DEV_TYPE_CHAR</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> =</span><span style="--shiki-light:#986801;--shiki-dark:#E06C75"> 0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">80</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">    DEV_TYPE_BLOCK</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">} </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">dev_type_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">class</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> DriverBase</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  public:</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">  // Returns 1 if driver can handle this device, or 2 for cover-all driver (will stop probing for sub nodes)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    virtual</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> probe</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">name</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">compatible</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    virtual</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> long</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> addDevice</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">fdt</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // returns handler</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    virtual</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> removeDevice</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">long</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> handler</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // unregister device by handler</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    virtual</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2"> dev_type_t</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> getDeviceType</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">() </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    virtual</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> ~DriverBase</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">() </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> default</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">};</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>通过这样的基类，我们就可以通过 <code>probe()</code> 函数进行设备驱动程序枚举，并在枚举成功时调用 <code>addDevice()</code> 请求驱动程序添加设备，使用 <code>removeDevice()</code> 删除设备。</p>
<p>比如，考虑一个系统根设备驱动，这个设备驱动继承 <code>DriverBase</code> 并重写其中的虚函数：</p>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">static</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> drv_register</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">class</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> SysDev</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> : </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> DriverBase</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  public:</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> probe</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">name</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">compatible</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">override</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        std::string id </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> name;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (id </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "chosen"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // Node to storage cmdline arguments</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (id </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> ""</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2"> &#x26;&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> std::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">string</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(compatible).</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">find</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"riscv"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">!=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> std::string::npos)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    long</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> addDevice</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">fdt</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">override</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> ++</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">hdl_count;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> removeDevice</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">long</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> handler</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">override</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">    dev_type_t</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> getDeviceType</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">() </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">override</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> DEV_TYPE_SYS;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  private:</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    static</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> hdl_count;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    friend</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> drv_register</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">};</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> SysDev::hdl_count </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> -</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">static</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> DRV_INSTALL_FUNC</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">200</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> drv_register</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    static</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> SysDev drv;</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">    drv</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">hdl_count</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> =</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    DriverManager::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">addDriver</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(drv);</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Driver SysRoot installed</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这里还有一个 <code>drv_register()</code> 函数，用于注册驱动到系统中。</p>
<h2>设备发现</h2>
<p>无论是 OpenSBI 还是 UBoot ，都将设备树加载到内存中并进行修补，随后通过一个寄存器传递到下一级。我们的系统目前从 OpenSBI 直接跳到内核的 _start 处开始执行，根据其文档，设备树地址通过寄存器 a1 传递。所以我们可以直接从 C 环境下的第二个参数接收设备树地址，并加以解析：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">long</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> k_early_boot</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> unsigned</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> long</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> hart_id</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">dtb_addr</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> **</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">sys_stack_base</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ret </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fdt_check_header</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(dtb_addr);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (ret </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">!=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">        puts</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"[EBOOT] FDT header check failed</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> -</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    ...</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这里要明确一点，由于内存的描述也在设备树中，所以我们需要先于 <code>k_cstart()</code> 将设备树解析并正确设置系统栈。这里我们通过修改汇编代码增加一个对 <code>k_early_boot()</code> 的调用，在该函数中调整系统栈底的地址 (sys_stack_base)，并将设备树数据全部转移到不会冲突的系统内存区域，供后续正常环境使用，随后返回到汇编中调整系统栈。这项工作稍后再讲述。</p>
<p>进入 <code>k_main()</code> 之后，我们就可以开始进行设备发现了。定义这样一个驱动管理类：</p>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">class</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> DriverManager</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  public:</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    static</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> addDriver</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">DriverBase</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> &#x26;</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">drv</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">        _drvlist</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">push_back</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">drv);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    static</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> removeDriver</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">DriverBase</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> &#x26;</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">drv</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  protected:</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    static</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> probe</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">fdt</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> node</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> =</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    friend</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> k_main</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> argc</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">argv</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[]);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  private:</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    static</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> std::vector</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">DriverBase </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*></span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _drvlist;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    static</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> _depth</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">32</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">];</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    static</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> _try</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">fdt</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> node</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">};</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>其中的 <code>probe()</code> 函数将递归地解析设备树，然后调用 <code>_try()</code> 依次调用注册的设备驱动的 <code>probe()</code> 函数，根据其返回值决定是否进行安装和跳过子节点解析。</p>
<p>到这里，我们只要在 <code>k_main()</code> 中调用 <code>DriverManager::probe()</code>，就可以完成设备发现了。</p>
<p>不过还有一个问题要解决，就是驱动程序要如何将自己在 <code>k_main()</code> 之前注册到 <code>DriverManager</code> 中，也就是由谁来调用 <code>drv_register()</code>。相信有经验的同志已经注意到上面的一个宏定义：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> DRV_INSTALL_FUNC</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">V</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">__attribute__</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">constructor</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(V)</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">)</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>这里的 <code>__attribute__((constructor(V)))</code> 是一个 GCC 支持的函数属性描述宏，指示 GCC 将函数当作全局构造器 (Global Constructor)，其中的 <code>V</code> 是优先级，越小的越早执行。通过这个修饰，函数指针将被放入 <code>.init_array</code> 段中，并在 <code>k_before_main()</code> 被执行。</p>
<p>此外，我们还需保证 <code>_drvlist</code> 能够较早地初始化，使用下面的定义：</p>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">__attribute__((init_priority(K_PR_INIT_DRV_LIST))) std::vector</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">DriverBase </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*></span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> DriverManager::_drvlist;</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>指示 GCC 将这个全局对象的构造函数优先级提升到 <code>K_PR_INIT_DRV_LIST</code>。</p>
<h2>系统参数配置</h2>
<p>前文提到要检测系统内存并设置栈，这里首先修改汇编启动代码，设置临时堆栈并调用 <code>k_early_boot()</code>：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">	/* Setup boot C stack */</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	lla	a3, _kernel_end</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	lla	a4, _KERNEL_BOOT_STACK_SIZE</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> /* this is fake a address provided from ld */</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	add	sp, a3, a4</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	lla a3, _sys_stack_base</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	REG_S	sp, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(a3)</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">	/* Early boot in C */</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	lla	a3, _boot_a0</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	REG_L	a0, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(a3)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	lla	a3, _boot_a1</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	REG_L	a1, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(a3)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	lla a2, _sys_stack_base</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	call k_early_boot</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	bne a0, zero, _start_hang </span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">_start_warm:</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    ...</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>随后在 k_early_boot 中解析内存节点：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">    // Detect system memory size</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    ret </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fdt_path_offset</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">dtb_addr</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "/memory"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (ret </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">        puts</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"[EBOOT] FDT memory node not found</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> -</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">3</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> regsize </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">memreg </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fdt_getprop</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">dtb_addr</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> ret</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "reg"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> &#x26;</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">regsize</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">memreg </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">||</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> regsize </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 16</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">        puts</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"[EBOOT] FDT memory reg invalid</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> -</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    unsigned</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> long</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> mem_start </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> be2le64</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(((</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> unsigned</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> long</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">memreg</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">[</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">]</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    unsigned</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> long</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> mem_len </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> be2le64</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(((</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> unsigned</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> long</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">memreg</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">[</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">]</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"[EBOOT] Memory Range: base= 0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%lx</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">, len= 0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%lx</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> mem_start</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> mem_len</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><ul>
<li>通过调试发现设备树的数据是大端序的，通过函数简单转换一下即可。</li>
</ul>
<p>系统命令行参数也包含在设备树中，通过节点 <code>/chosen</code> 下的 <code>bootargs</code>属性提供。所以我们还可以先在这里解析了命令行参数，允许手动指定系统可用内存：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">    // Get the kernel command line</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    ret </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fdt_path_offset</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">dtb_addr</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "/chosen"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (ret </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">        puts</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"[EBOOT] FDT chosen node not found</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> -</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">5</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">kcmdline </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fdt_getprop</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">dtb_addr</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> ret</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "bootargs"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> &#x26;</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">regsize</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">kcmdline </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">||</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> regsize </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">        puts</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"[EBOOT] FDT bootargs invalid</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> -</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">6</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    memcpy</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">kernel_args</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> kcmdline</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> regsize</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    puts</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"[EBOOT] Kernel command line: "</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    puts</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">kernel_args</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">    // Parse Kerenl command line args for memory size (force override if specified in cmdline, only the first one is</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">    // used!)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    kernel_cmdargc </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> split_args</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">((</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">kernel_args</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> kernel_args_array</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    unsigned</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> long</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> mem_len_cmdarg </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    char</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> mem_suffix </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> 'M'</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    for</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">; i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> kernel_cmdargc; </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">++</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">i)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">strncmp</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">kernel_args_array</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[i], </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"-mem"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> kernel_cmdargc </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">-</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> res </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> sscanf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">kernel_args_array</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">+</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">], </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%ld</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> %c</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">mem_len_cmdarg, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">mem_suffix);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (res </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                {</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">                    puts</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"[EBOOT] Invalid memory size specified, skipping</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                    mem_len_cmdarg </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    break</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (res </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                {</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">                    puts</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"[EBOOT] Memory size specified without suffix, assuming MB</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                    mem_len_cmdarg </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1024</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1024</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    break</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (res </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    switch</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (mem_suffix)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                    {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    case</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> 'K'</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    case</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> 'k'</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                        mem_len_cmdarg </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1024</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                        break</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    case</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> 'M'</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    case</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> 'm'</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                        mem_len_cmdarg </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1024</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1024</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                        break</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    case</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> 'G'</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    case</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> 'g'</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                        mem_len_cmdarg </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1024</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1024</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1024</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                        break</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    default</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">                        puts</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"[EBOOT] Invalid memory size suffix, skipping</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                        mem_len_cmdarg </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                        break</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                    }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    break</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            else</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            {</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">                puts</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"[EBOOT] Memory size not specified, skipping</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                mem_len_cmdarg </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                break</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>随后计算系统栈底：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    k_mem_size </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (mem_len_cmdarg </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">></span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">?</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> mem_len_cmdarg </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">:</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> mem_len;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">sys_stack_base </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)(mem_start </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">+</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> k_mem_size);</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"[EBOOT] Set SYS_SP: 0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%lx</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">unsigned</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> long</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">sys_stack_base</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>至此，这一部分宣告结束，来一段 Log：</p>
<details class="hint-container details"><summary>详情</summary>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>[EBOOT] Memory Range: base= 0x80000000, len= 0x10000000</span></span>
<span class="line"><span>[EBOOT] Kernel command line:</span></span>
<span class="line"><span></span></span>
<span class="line"><span>[EBOOT] Set SYS_SP: 0x90000000</span></span>
<span class="line"><span></span></span>
<span class="line"><span>===== Entered Test Kernel =====</span></span>
<span class="line"><span>a0: 0x0</span></span>
<span class="line"><span>Calling init_array...</span></span>
<span class="line"><span>Driver SysMem installed</span></span>
<span class="line"><span>Driver SysRoot installed</span></span>
<span class="line"><span>Driver UART8250 installed</span></span>
<span class="line"><span>cmd args: ''</span></span>
<span class="line"><span>Finding driver for #0  [riscv-virtio] ... Found! Installing... OK, handler: 1</span></span>
<span class="line"><span>Finding driver for #100 reserved-memory [] ... Found! Installing... OK, handler: 1</span></span>
<span class="line"><span>Finding driver for #164 mmode_resv1@80000000 [] ... Failed</span></span>
<span class="line"><span>Finding driver for #236 mmode_resv0@80040000 [] ... Failed</span></span>
<span class="line"><span>Finding driver for #312 flash@20000000 [cfi-flash] ... Failed</span></span>
<span class="line"><span>Finding driver for #420 chosen [] ... Found! Installing... OK, handler: 2</span></span>
<span class="line"><span>Driver has cover the node with offset: 420</span></span>
<span class="line"><span>Finding driver for #480 uart@10000000 [ns16550a] ... Found! Installing... OK, handler: 1</span></span>
<span class="line"><span>Finding driver for #604 test@100000 [sifive,test1] ... Failed</span></span>
<span class="line"><span>Finding driver for #692 virtio_mmio@10008000 [virtio,mmio] ... Failed</span></span>
<span class="line"><span>Finding driver for #808 virtio_mmio@10007000 [virtio,mmio] ... Failed</span></span>
<span class="line"><span>Finding driver for #924 virtio_mmio@10006000 [virtio,mmio] ... Failed</span></span>
<span class="line"><span>Finding driver for #1040 virtio_mmio@10005000 [virtio,mmio] ... Failed</span></span>
<span class="line"><span>Finding driver for #1156 virtio_mmio@10004000 [virtio,mmio] ... Failed</span></span>
<span class="line"><span>Finding driver for #1272 virtio_mmio@10003000 [virtio,mmio] ... Failed</span></span>
<span class="line"><span>Finding driver for #1388 virtio_mmio@10002000 [virtio,mmio] ... Failed</span></span>
<span class="line"><span>Finding driver for #1504 virtio_mmio@10001000 [virtio,mmio] ... Failed</span></span>
<span class="line"><span>Finding driver for #1620 cpus [] ... Failed</span></span>
<span class="line"><span>Finding driver for #1680 cpu-map [] ... Failed</span></span>
<span class="line"><span>Finding driver for #1692 cluster0 [] ... Failed</span></span>
<span class="line"><span>Finding driver for #1708 core0 [] ... Failed</span></span>
<span class="line"><span>Finding driver for #1748 cpu@0 [riscv] ... Failed</span></span>
<span class="line"><span>Finding driver for #1900 interrupt-controller [riscv,cpu-intc] ... Failed</span></span>
<span class="line"><span>Finding driver for #2012 memory@80000000 [] ... Found! Installing... OK, handler: 2</span></span>
<span class="line"><span>Finding driver for #2084 soc [simple-bus] ... Failed</span></span>
<span class="line"><span>Finding driver for #2160 pci@30000000 [pci-host-ecam-generic] ... Failed</span></span>
<span class="line"><span>Finding driver for #2852 interrupt-controller@c000000 [riscv,plic0] ... Failed</span></span>
<span class="line"><span>Finding driver for #3048 clint@2000000 [riscv,clint0] ... Failed</span></span>
<span class="line"><span></span></span>
<span class="line"><span>Reached k_after_main, clearing up...</span></span>
<span class="line"><span>===== Test Kernel exited with 0 =====</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div></details>
]]></content:encoded>
    </item>
    <item>
      <title>AbydOS开发日记 (3) - 基础驱动程序</title>
      <link>https://octz.net/blog/AbydOS/3-basic-drivers.html</link>
      <guid>https://octz.net/blog/AbydOS/3-basic-drivers.html</guid>
      <source url="https://octz.net/rss.xml">AbydOS开发日记 (3) - 基础驱动程序</source>
      <description>开始写驱动吧！ 上一篇我们已经搭建好了驱动框架，现在我们来实现三个基础驱动：根设备、内存、串口。 注：上一篇后驱动框架有小修小补，请参见相关提交 根设备驱动 根设备并不是一个具体设备，而是设备树的根节点，包含了模组信息和兼容信息，可以根据它区别平台。为了方便起见，我们让根设备驱动一并处理 /chosen 节点，因为平台相关的一些额外参数可以直接这样传入...</description>
      <category>ABYDOS</category>
      <pubDate>Wed, 13 Mar 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>开始写驱动吧！</h2>
<p>上一篇我们已经搭建好了驱动框架，现在我们来实现三个基础驱动：根设备、内存、串口。</p>
<ul>
<li>注：上一篇后驱动框架有小修小补，请参见相关提交</li>
</ul>
<h2>根设备驱动</h2>
<p>根设备并不是一个具体设备，而是设备树的根节点，包含了模组信息和兼容信息，可以根据它区别平台。为了方便起见，我们让根设备驱动一并处理 <code>/chosen</code> 节点，因为平台相关的一些额外参数可以直接这样传入。</p>
<p>首先定义一个基类 (顺便定义一个属性导出宏)：</p>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __K_PROP_EXPORT__</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">name</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">pri</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)                                                                                   </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> auto</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> &#x26;</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">name</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">() </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">                                                                                           \</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {                                                                                                                  </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> pri;                                                                                                    </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">class</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> SysRoot</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> : </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> DriverBase</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  public:</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    virtual</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2"> dev_type_t</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> getDeviceType</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">() </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">override</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> DEV_TYPE_SYS;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    __K_PROP_EXPORT__</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">compatible</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">_compatible</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    __K_PROP_EXPORT__</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(model, _model)</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    __K_PROP_EXPORT__</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(stdout_path, _stdout_path)</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  protected:</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    std::string _compatible;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    std::string _model;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    std::string _stdout_path;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">};</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>实现上，考虑提供一个通用的 fallback 驱动，在不匹配的时候也不会终止内核：</p>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">class</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> GenericRoot</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> : </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> SysRoot</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  public:</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> probe</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">name</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">compatible</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">override</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        std::string id </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> name;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (id </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> ""</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> DRV_CAP_THIS;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> DRV_CAP_NONE;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    long</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> addDevice</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">fdt</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> node</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">override</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> len;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (node </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // root node</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            auto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> prop </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fdt_get_property</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fdt, node, </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"compatible"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">len);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">prop)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                _compatible </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "Generic"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            else</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                _compatible </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> std::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">string</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">prop</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">-></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">data</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            prop </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fdt_get_property</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fdt, node, </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"model"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">len);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">prop)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                _model </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "Generic"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            else</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                _model </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> std::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">string</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">prop</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">-></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">data</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            auto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> rc </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fdt_path_offset</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fdt, </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"/chosen"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // property of chosen node may diff on other platform</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (rc </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">>=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                auto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> prop </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fdt_get_property</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fdt, rc, </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"stdout-path"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">len);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (prop)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                    _stdout_path </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> std::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">string</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">prop</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">-></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">data</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                DriverManager::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">markInstalled</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fdt, rc, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">this</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,DRV_CAP_THIS);</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // mark as installed</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                return</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // singleton device</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_ENODEV;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> removeDevice</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">long</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> handler</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">override</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">};</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>可以看到，这里的 <code>probe()</code> 条件是名称为空，按照定义看，只有根节点没有名称。由于我们要一并接管 <code>/chosen</code> 节点，所以在安装时，利用传入的完整 fdt 查找到节点偏移，提取属性后向 <code>DriverManager</code> 报告额外安装的节点，避免再次安装。</p>
<h2>内存驱动</h2>
<p>理论上，内存是不需要驱动的，但是为了更好地管理系统上的内存，在当前架构下还是引入一个驱动。</p>
<p>内存驱动主要的工作如下：</p>
<ol>
<li>获取并管理保留内存区、可用内存范围</li>
<li>提供接口，进行非连续内存分配（_sbrk）的底层调用</li>
</ol>
<p>由于是系统驱动，还是定义一个基类：</p>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">class</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> SysMem</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> : </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> DriverBase</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  public:</span></span>
<span class="line"><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">    dev_type_t</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> getDeviceType</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">() </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">override</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> DEV_TYPE_SYS;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    virtual</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> addReservedMem</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">uint64_t</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> addr</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">uint64_t</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> size</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    __K_PROP_EXPORT__</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">reservedMem</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">_mem_rsv</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    __K_PROP_EXPORT__</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">availableMem</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">_mem_avail</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    protected:</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        std::vector</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">std::pair</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;size_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">size_t>></span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _mem_rsv;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        std::vector</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">std::pair</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;size_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">size_t>></span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _mem_avail;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">};</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>然后提供一个通用实现：</p>
<details class="hint-container details"><summary>详情</summary>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">class</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> GenericMem</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> : </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> SysMem</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  public:</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> probe</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">name</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">compatible</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">override</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        std::string id </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> name;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">id</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">find</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"memory"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">!=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2"> &#x26;&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> id </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">!=</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "reserved-memory"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> DRV_CAP_NONE;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> DRV_CAP_COVER;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    long</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> addDevice</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">fdt</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> node</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">override</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        uint64_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> address, size;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">_fdt_rsv_mem_parsed)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            // fdt command reserved memory</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> n </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fdt_num_mem_rsv</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fdt);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            for</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">; i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> n; </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">++</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">i)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                auto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> rc </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fdt_get_mem_rsv</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fdt, i, </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">address, </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">size);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (rc </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                {</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                    _mem_rsv</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">push_back</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-dark:#E5C07B">std</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">make_pair</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(address, size));</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">                    printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"(0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%lx</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> - 0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%lx</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">) "</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, address, address </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">+</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> size);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            _fdt_rsv_mem_parsed </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> true</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            // Some mark should be done?</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        auto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> name </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fdt_get_name</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fdt, node, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">NULL</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (name </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> std::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">string</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"reserved-memory"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">))</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            /* process reserved-memory node */</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            auto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> nodeoffset </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fdt_subnode_offset</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fdt, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"reserved-memory"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (nodeoffset </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">>=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                auto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> subnode </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fdt_first_subnode</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fdt, nodeoffset);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                while</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (subnode </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">>=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                {</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">fdt_get_node_addr_size</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fdt, subnode, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">address, </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">size) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">>=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                    {</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // each subnode should have only one addr and size</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                        _mem_rsv</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">push_back</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-dark:#E5C07B">std</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">make_pair</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(address, size));</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">                        printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"(0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%lx</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> - 0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%lx</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">) "</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, address, address </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">+</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> size);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                    }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    else</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                    {</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">                        printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Failed to get reserved memory in #</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%d</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, subnode);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                    }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                    subnode </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fdt_next_subnode</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fdt, subnode);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        else</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // memory node, could have multiple</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            for</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">; </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">fdt_get_node_addr_size</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fdt, node, i, </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">address, </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">size) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">>=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">; </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">++</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">i)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            {</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                _mem_avail</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">push_back</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-dark:#E5C07B">std</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">make_pair</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(address, size));</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">                printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"(0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%lx</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> - 0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%lx</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">) "</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, address, address </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">+</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> size);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // Also singleton</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> removeDevice</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">long</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> handler</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">override</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> addReservedMem</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">uint64_t</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> addr</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">uint64_t</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> size</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">override</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">        _mem_rsv</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">push_back</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-dark:#E5C07B">std</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">make_pair</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(addr, size));</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  private:</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    bool</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _fdt_rsv_mem_parsed </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> false</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">};</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div></details>
<p>这里要考虑的问题在于，内存驱动在设备树上有多个设备与之对应，当存在平台特定驱动的时候，如果不作任何处理，那就容易导致不同的内存区可 <code>probe()</code> 到的驱动不一致，导致数据分散在多个驱动中。这时候，系统根设备就出场了，它总是能先于其他设备进行 <code>probe()</code>，并且知道兼容信息，我们只需要在系统根设备驱动 <code>probe()</code> 的时候，顺手将不兼容平台的驱动先行删除，保证其后不被 <code>probe()</code> 到。</p>
<h2>串口驱动</h2>
<p>接下来就是及其硬件的一个简单驱动了，串口驱动。在我们的系统上，参考 Linux 的设计，外设抽象成两种，即块设备和字符设备。这里首先继承 DriverChar：</p>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">class</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> Drv_Uart8250</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> : </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> DriverChar</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  private:</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    struct</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> uart8250_t</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">base;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        uint32_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> freq;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        uint32_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> baud;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        uint32_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> reg_width;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        uint32_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> reg_shift;</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        // uint32_t reg_offset;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        bool</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> opened </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> false</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    };</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> uint32_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> default_freq </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> uint32_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> default_baud </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 115200</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> uint32_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> default_reg_shift </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> uint32_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> default_reg_width </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> uint32_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> default_reg_offset </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> hdl_count </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> -</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    std::map</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;long</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">uart8250_t</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">></span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> hdl;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">};</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这里定义一个结构体存储数据。当然，也可以使用外部类的方法，更符合 C++ 的思想。</p>
<p>然后参照 openSBI 的实现，将几个 fdt_helper 函数以及 riscv_io 部分内容 cv 过来，然后定义两个辅助函数：</p>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    static</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> u32</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> get_reg</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2"> uart8250_t</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> &#x26;</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">u</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">u32</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> num</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        u32 offset </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> num </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;&#x3C;</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> u</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">reg_shift</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">u</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">reg_width</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> ==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> readb</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">u</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">base</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> +</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> offset);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        else</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">u</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">reg_width</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> ==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> readw</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">u</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">base</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> +</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> offset);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        else</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> readl</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">u</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">base</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> +</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> offset);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    static</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> set_reg</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2"> uart8250_t</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> &#x26;</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">u</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">u32</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> num</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">u32</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> val</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        u32 offset </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> num </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;&#x3C;</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> u</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">reg_shift</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">u</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">reg_width</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> ==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">            writeb</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(val, </span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">u</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">base</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> +</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> offset);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        else</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">u</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">reg_width</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> ==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">            writew</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(val, </span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">u</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">base</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> +</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> offset);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        else</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">            writel</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(val, </span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">u</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">base</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> +</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> offset);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这两个函数非常简单，就是进行寄存器的读写。后面的所以步骤都利用这两个函数进行 IO。</p>
<p>接着实现设备实例化功能：</p>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">long</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> addDevice</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">fdt</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> node</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">override</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">        uart8250_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> uart;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        uint64_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> regsize;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> len, rc;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        const</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2"> fdt32_t</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">val;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        rc </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fdt_get_node_addr_size</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fdt, node, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">uint64_t</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">uart</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">base</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">regsize);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (rc </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2"> ||</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2"> !</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">uart</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">base</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2"> ||</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2"> !</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">regsize)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_ENODEV;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        val </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">fdt32_t</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">fdt_getprop</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fdt, node, </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"clock-frequency"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">len);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (len </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">></span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2"> &#x26;&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> val)</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            uart</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">freq</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> =</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fdt32_to_cpu</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">val);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        else</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            uart</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">freq</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> default_freq;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        val </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">fdt32_t</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">fdt_getprop</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fdt, node, </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"current-speed"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">len);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (len </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">></span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2"> &#x26;&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> val)</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            uart</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">baud</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> =</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fdt32_to_cpu</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">val);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        else</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            uart</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">baud</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> default_baud;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        val </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">fdt32_t</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">fdt_getprop</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fdt, node, </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"reg-shift"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">len);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (len </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">></span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2"> &#x26;&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> val)</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            uart</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">reg_shift</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> =</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fdt32_to_cpu</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">val);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        else</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            uart</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">reg_shift</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> default_reg_shift;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        val </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">fdt32_t</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">fdt_getprop</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fdt, node, </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"reg-io-width"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">len);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (len </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">></span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2"> &#x26;&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> val)</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            uart</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">reg_width</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> =</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fdt32_to_cpu</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">val);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        else</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            uart</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">reg_width</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> default_reg_width;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        val </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">fdt32_t</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">fdt_getprop</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fdt, node, </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"reg-offset"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">len);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (len </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">></span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2"> &#x26;&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> val)</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            uart</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">base</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> +=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fdt32_to_cpu</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">val);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        else</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            uart</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">base</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> +=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> default_reg_offset;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        u16 bdiv </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">uart</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">baud</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            bdiv </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">uart</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">freq</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> +</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 8</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> uart</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">baud</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">/</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">16</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> uart</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">baud</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        /* Disable all interrupts */</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">        set_reg</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(uart, UART_IER_OFFSET, </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">00</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        /* Enable DLAB */</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">        set_reg</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(uart, UART_LCR_OFFSET, </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">80</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (bdiv)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            /* Set divisor low byte */</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">            set_reg</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(uart, UART_DLL_OFFSET, bdiv </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;</span><span style="--shiki-light:#986801;--shiki-dark:#E06C75"> 0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">ff</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            /* Set divisor high byte */</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">            set_reg</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(uart, UART_DLM_OFFSET, (bdiv </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">>></span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 8</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;</span><span style="--shiki-light:#986801;--shiki-dark:#E06C75"> 0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">ff</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        /* 8 bits, no parity, one stop bit */</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">        set_reg</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(uart, UART_LCR_OFFSET, </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">03</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        /* Enable FIFO */</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">        set_reg</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(uart, UART_FCR_OFFSET, </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">01</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        /* No modem control DTR RTS */</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">        set_reg</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(uart, UART_MCR_OFFSET, </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">00</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        /* Clear line status */</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">        get_reg</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(uart, UART_LSR_OFFSET);</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        /* Read receive buffer */</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">        get_reg</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(uart, UART_RBR_OFFSET);</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        /* Set scratchpad */</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">        set_reg</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(uart, UART_SCR_OFFSET, </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">00</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">        hdl</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">insert</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-dark:#E5C07B">std</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">pair</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">long</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">uart8250_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">>(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">++</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">hdl_count, uart));</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        // Test send here</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">        write</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(hdl_count, </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"TEST UART8250</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">14</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> hdl_count;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>关于各个寄存器操作的解释，可以参阅 <a href="https://wiki.qemu.org/File:PC16550D.pdf" target="_blank" rel="noopener noreferrer">UART 16650D Datasheet</a>。</p>
<p>实例化解决，把剩下的虚函数补完：</p>
<details class="hint-container details"><summary>详情</summary>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">   int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> probe</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">name</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">compatible</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">override</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        std::string id </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> name;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">id</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">find</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"uart"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> std::string::npos)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> DRV_CAP_NONE;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        id </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> compatible;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (id </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "ns16550"</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2"> ||</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> id </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "ns16550a"</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2"> ||</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> id </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "snps,dw-apb-uart"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">?</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> DRV_CAP_THIS </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">:</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> DRV_CAP_NONE;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> open</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">long</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> handler</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">override</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        auto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> u </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> hdl</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">find</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(handler);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (u </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> hdl</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">end</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">())</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_ENODEV;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        auto</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2"> &#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">uart </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> u</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">-></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">second</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">uart</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">opened</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_EALREADY;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        // lock here?</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">        uart</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">opened</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> =</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> true</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">        printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"UART8250 opened</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> close</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">long</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> handler</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">override</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        auto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> u </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> hdl</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">find</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(handler);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (u </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> hdl</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">end</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">())</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_ENODEV;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        auto</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2"> &#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">uart </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> u</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">-></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">second</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">uart</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">opened</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_EALREADY;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        // lock here?</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">        uart</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">opened</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> =</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> false</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">        printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"UART8250 closed</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> read</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">long</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> handler</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">buf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> len</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">override</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        auto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> u </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> hdl</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">find</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(handler);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (u </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> hdl</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">end</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">())</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_ENODEV;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        auto</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2"> &#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">uart </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> u</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">-></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">second</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        for</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">; i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> len; </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">++</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">i)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">get_reg</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(uart, UART_LSR_OFFSET) </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> UART_LSR_DR)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                ((</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)buf)[i] </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> get_reg</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(uart, UART_RBR_OFFSET);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            else</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> i;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        // printf("UART8250 read\n");</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> len;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> write</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">long</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> handler</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">buf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> len</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">override</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        auto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> u </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> hdl</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">find</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(handler);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (u </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> hdl</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">end</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">())</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_ENODEV;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        auto</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2"> &#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">uart </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> u</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">-></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">second</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        for</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">; i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> len; </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">++</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">i)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            while</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ((</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">get_reg</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(uart, UART_LSR_OFFSET) </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> UART_LSR_THRE) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                ;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">            set_reg</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(uart, UART_THR_OFFSET, ((</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)buf)[i]);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        // printf("UART8250 write\n");</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> ioctl</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">long</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> handler</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> cmd</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">arg</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">override</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">        printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"UART8250 ioctl -- not supported</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div></details>
<p>当然这里的 open() 和 close() 也是雏形，没有实质的意义。</p>
<p>编译运行，设备安装的时候就能打印出 &quot;TEST UART8250&quot; 了！</p>
<h2>后记</h2>
<p>这个驱动移植花了两个多小时，真是不容易。实现了各个资源的管理，下一步就可以考虑 MMU 相关的操作了。</p>
<ul>
<li>实际上，设备的安装目前还分成了两步，先安装系统设备，再安装外设。这是一点小小的更改，以适应启动流程的需要。</li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>AbydOS开发日记 (4) -  MMU 与内存布局</title>
      <link>https://octz.net/blog/AbydOS/4-mmu-init.html</link>
      <guid>https://octz.net/blog/AbydOS/4-mmu-init.html</guid>
      <source url="https://octz.net/rss.xml">AbydOS开发日记 (4) -  MMU 与内存布局</source>
      <description>关于内存 内存，即 Memory，是存储计算机运行过程数据的主要部件。不过在操作系统中，内存并不单单是主存，还有各种外设内存等。本文所说的内存布局，主要是指在可寻址空间中的布局，这关系到系统和后面应用程序的运行，是及其重要的。在有内存管理单元 (MMU) 的处理器上，寻址空间可以分为两种类型，即 物理地址空间 (Physical Memory Area...</description>
      <category>ABYDOS</category>
      <pubDate>Sat, 16 Mar 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>关于内存</h2>
<p>内存，即 Memory，是存储计算机运行过程数据的主要部件。不过在操作系统中，内存并不单单是主存，还有各种外设内存等。本文所说的内存布局，主要是指在可寻址空间中的布局，这关系到系统和后面应用程序的运行，是及其重要的。在有内存管理单元 (MMU) 的处理器上，寻址空间可以分为两种类型，即 物理地址空间 (Physical Memory Area, PMA) 和 虚拟地址空间 (Virtual Memory Area, VMA)。通过 MMU 的控制与转换，可以实现有效的隔离和保护，防止非法的内存访问。</p>
<p>本文仅浅读标准手册，未尽之处，敬请参阅标准手册。</p>
<h2>RISC-V 的地址空间</h2>
<p>根据 <a href="https://github.com/riscv/riscv-isa-manual/releases/tag/Priv-v1.12" target="_blank" rel="noopener noreferrer">The RISC-V Instruction Set Manual Volume II: Privileged Architecture</a>，目前 RV32 可用的物理地址空间为 32 位（或更多），而 RV64 可用的物理地址空间是 64 位。</p>
<p>而虚拟地址空间上，RV32 只有一种模式，即 SV32，对应了 32 位的虚拟地址空间，并且由于 MMU 配置上用的是 22位 的物理页号 (每页 4K, 即 12 位)，能够支持到 34 位的物理地址空间。</p>
<p>但是，RV64 因为地址空间足够大，普通应用可能不需要完全的虚拟地址空间支持，截止 V20211203，一共定义了三种模式，即 SV39, SV48, SV57，分别对应 39 位、48 位、57 位虚拟地址空间。</p>
<h2>RISC-V 的 MMU</h2>
<p>在标准文档中，MMU 被设计成一个带有 TLB 的硬件模块，实现可配置的从虚拟地址空间到物理地址空间的映射。由于原理相同，所以标准文档只对 SV32 作了详细描述，这里我们也同样先分析 SV32，然后推广到 SV39 等。</p>
<p>略语一览：</p>
<ul>
<li>PPN: Physical Page Number, 物理页号</li>
<li>VPN: Virtual Page Number, 虚拟页号</li>
<li>PTE: Page Table Entry，页表项</li>
<li>TLB: Translation Lookaside Buffer, 页表缓存</li>
</ul>
<h3>控制</h3>
<p>设计上，RV 的 MMU 由一个 CSR (控制与状态寄存器) 控制，名为 SATP (Supervisor Address Translation and Protection)，并带有专用指令用于刷新 TLB。寄存器字段如图所示：</p>
<figure><img src="https://imgcdn0.octz.net/blog/2024/rv32satp.png" alt="RV32 SATP 寄存器" tabindex="0" loading="lazy"><figcaption>RV32 SATP 寄存器</figcaption></figure>
<figure><img src="https://imgcdn0.octz.net/blog/2024/rv64satp.png" alt="RV64 SATP 寄存器" tabindex="0" loading="lazy"><figcaption>RV64 SATP 寄存器</figcaption></figure>
<ul>
<li>注：这里的 WARL 指的是 CSR 的访问策略，即 Write Any Read Legal。</li>
</ul>
<p>据标准描述，ASID 即 Address Space Identifier，用于标识不同的地址空间而无需频繁地进行刷新 TLB 操作。PPN 字段填入根页表的物理页号，而 Mode 字段用于标识 MMU 的工作模式，如表所示：</p>
<p>RV32:</p>
<p>|  值   | 名称  |          描述          |<br>
| :</p>
]]></content:encoded>
      <enclosure url="https://imgcdn0.octz.net/blog/2024/rv32satp.png" type="image/png"/>
    </item>
    <item>
      <title>AbydOS开发日记 (5) -  基本内存映射</title>
      <link>https://octz.net/blog/AbydOS/5-basic-mem-maps.html</link>
      <guid>https://octz.net/blog/AbydOS/5-basic-mem-maps.html</guid>
      <source url="https://octz.net/rss.xml">AbydOS开发日记 (5) -  基本内存映射</source>
      <description>基本内存布局 由于大部分的 RV64 SoC 都将 DRAM 放置在 0x80000000 以上，其下的空间保留给 IO，如 QEMU 的 virt，其布局如下： 由此，我们可以简单地将低 2G 空间直接映射，然后将 (可能不连续的) DRAM 从 0x80000000 开始进行映射，最后把 DRAM 的一小部分重映射到 VMA 的高地址空间。如下表所...</description>
      <category>ABYDOS</category>
      <pubDate>Mon, 18 Mar 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>基本内存布局</h2>
<p>由于大部分的 RV64 SoC 都将 DRAM 放置在 0x80000000 以上，其下的空间保留给 IO，如 QEMU 的 virt，其布局如下：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">static</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> const</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> MemMapEntry virt_memmap</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">[]</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    [VIRT_DEBUG] </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {        </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,         </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">100</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> },</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    [VIRT_MROM] </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">         {     </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,        </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">f000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> },</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    [VIRT_TEST] </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">         {   </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">100000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,        </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> },</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    [VIRT_RTC] </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">          {   </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">101000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,        </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> },</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    [VIRT_CLINT] </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {  </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">2000000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,       </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">10000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> },</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    [VIRT_ACLINT_SSWI] </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">  {  </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">2F00000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,        </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">4000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> },</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    [VIRT_PCIE_PIO] </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">     {  </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">3000000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,       </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">10000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> },</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    [VIRT_PLATFORM_BUS] </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {  </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">4000000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,     </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">2000000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> },</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    [VIRT_PLIC] </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">         {  </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">c000000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">VIRT_PLIC_SIZE</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(VIRT_CPUS_MAX </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) },</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    [VIRT_APLIC_M] </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">      {  </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">c000000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">APLIC_SIZE</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(VIRT_CPUS_MAX) },</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    [VIRT_APLIC_S] </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">      {  </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">d000000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">APLIC_SIZE</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(VIRT_CPUS_MAX) },</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    [VIRT_UART0] </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        { </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">10000000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,         </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">100</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> },</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    [VIRT_VIRTIO] </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">       { </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">10001000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,        </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> },</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    [VIRT_FW_CFG] </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">       { </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">10100000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,          </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">18</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> },</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    [VIRT_FLASH] </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        { </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">20000000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,     </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">4000000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> },</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    [VIRT_IMSIC_M] </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">      { </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">24000000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, VIRT_IMSIC_MAX_SIZE },</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    [VIRT_IMSIC_S] </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">      { </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">28000000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, VIRT_IMSIC_MAX_SIZE },</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    [VIRT_PCIE_ECAM] </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    { </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">30000000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,    </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">10000000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> },</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    [VIRT_PCIE_MMIO] </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    { </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">40000000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,    </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">40000000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> },</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    [VIRT_DRAM] </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">         { </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">80000000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,           </span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">0x</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> }, </span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">};</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>由此，我们可以简单地将低 2G 空间直接映射，然后将 (可能不连续的) DRAM 从 0x80000000 开始进行映射，最后把 DRAM 的一小部分重映射到 VMA 的高地址空间。如下表所示：</p>
<p>|   VMA Start    |   VMA End    |     PMA Start     |                Usage                |<br>
| :</p>
]]></content:encoded>
    </item>
    <item>
      <title>AbydOS开发日记 (6) -  多核初步</title>
      <link>https://octz.net/blog/AbydOS/6-multi-core-init.html</link>
      <guid>https://octz.net/blog/AbydOS/6-multi-core-init.html</guid>
      <source url="https://octz.net/rss.xml">AbydOS开发日记 (6) -  多核初步</source>
      <description>多核与多线程 一个 CPU 上可能不止一个核心 (Hart)，这些核心在物理上分开，独立运行，但是共享总线和外设。也就是说，它们的物理内存空间是一致的，只不过有自己单独的寄存器和 Cache、MMU。而多线程非常类似，只不过是通过调度的方式实现，将多个线程的寄存器等资源分时复用。在裸机的角度上看，我们可以把多核看成硬件的多线程，并利用类似的技术实现。 ...</description>
      <category>ABYDOS</category>
      <pubDate>Fri, 22 Mar 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>多核与多线程</h2>
<p>一个 CPU 上可能不止一个核心 (Hart)，这些核心在物理上分开，独立运行，但是共享总线和外设。也就是说，它们的物理内存空间是一致的，只不过有自己单独的寄存器和 Cache、MMU。而多线程非常类似，只不过是通过调度的方式实现，将多个线程的寄存器等资源分时复用。在裸机的角度上看，我们可以把多核看成硬件的多线程，并利用类似的技术实现。</p>
<h2>核心的启动</h2>
<p>在 RISCV 手册中，并没有规定 Hart 的启动顺序。比较通常的做法是，核心全部（近乎）同时从 M-mode 启动，随后 SBI 会通过原子量确定一个启动核心，并且执行初始化。至于 S-mode 中是否同时启动，我并没有明确看到文档指出，所以应该也是 SBI 实现自定义。通过实验，OpenSBI 只会将启动核心带入到 S-mode，其他核心会留在 M-mode 等待。但是，我们仍然有必要通过一个原子量保证 S-mode 初期只有一个核心运行，具体看，就是下面的汇编代码：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">_start:</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">	/* Pick one hart to run the main boot sequence */</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	lla	a3, _hart_lottery</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	li	a2, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	amoadd.w a3, a2, (a3)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	bnez	a3, _start_hang</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // in case multi core start at the same time</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这些代码在入口点立即执行，如果有多个核心，没有抢到控制权的就会跳到 _start_hang 的死循环里。当然，为了兼容性，后面肯定会设置一下中断再睡觉，不然在其他 SBI 上可能没法用。</p>
<p>那么我们如何通过 SBI 启动核心呢？答案是 SBI 的 HSM 扩展，即 Hart State Management。该扩展提供 4 个 ecall 调用，分别对应核心的 启动、（自）停止、状态查询和暂停。如下：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">struct</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> sbiret </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">sbi_hart_start</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">unsigned</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> long</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> hartid</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  unsigned</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> long</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> start_addr</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  unsigned</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> long</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> opaque</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">struct</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> sbiret </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">sbi_hart_stop</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">struct</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> sbiret </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">sbi_hart_get_status</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">unsigned</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> long</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> hartid</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">struct</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> sbiret </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">sbi_hart_suspend</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">uint32_t</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> suspend_type</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  unsigned</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> long</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> resume_addr</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  unsigned</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> long</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> opaque</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>文档说明，可以通过 sbi_hart_start 从指定的 <code>start_addr</code> 启动核心，并且其 <code>a0</code> = <code>hartid</code>，<code>a1</code> = <code>opaque</code>。</p>
<h2>核心的初始化</h2>
<p>基于之前的布局，确定启动其他核心的时机是设备外设驱动安装完成后。此时内存映射和系统栈已经确定，可以确定下一步的所有数据。启动后，执行环境非常原始，需要一点汇编来做初始化工作。</p>
<div class="hint-container tip">
<p class="hint-container-title">启动流程</p>
<ol>
<li>汇编初始化C环境</li>
<li>k_early_boot() 初始化 C++ 环境</li>
<li>k_boot() 探测并安装系统设备，开启 MMU，从系统堆分配并映射系统栈区</li>
<li>返回汇编，设置系统栈，进入 k_boot_perip()</li>
<li>k_boot_perip() 探测并安装外设，初始化系统输入输出等</li>
<li>返回汇编，设置启动核心栈，带入 k_boot_harts()</li>
<li>k_boot_harts() 调 SBI 启动其他核心</li>
<li>被启动核心初始化 MMU 和栈等，再进入 C++ 初始化执行环境，等待系统状态切换</li>
<li>全部启动完成，进入多核模式</li>
</ol>
</div>
<h3>内存映射</h3>
<p>核心启动后，其 SATP = 0 和 sstatus.SIE = 0，即 MMU 和中断是关闭的。我们的系统栈是布置在虚拟地址空间的，所以要先启用 MMU。在之前的启动步骤，我们保存了系统 MMU 配置寄存器 (SATP) 的值，我们将在所有核心上使用同样的映射。所以内存映射非常简单，只需将保存的值写入 satp 后，刷新 TLB 即可：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">_start_hart:</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">    /* a0: hartid a1: reserved */</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	lla   a2, _sys_satp</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	REG_L a2, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(a2)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	csrw  CSR_SATP, a2</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	sfence.vma zero, zero</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3>核心系统栈的设定</h3>
<p>在前面的步骤，我们确定了系统栈的空间，这里要根据 hart id，通过简单的乘法得到核心系统栈基址。如下：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">	/* Setup system stack base according to hart_id as offset */</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	lla a3, _sys_stack_base</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	REG_L sp, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(a3)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	li  a2, K_CONFIG_STACK_SIZE</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	mul a3, a0, a2</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	sub sp, sp, a3</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>理论上，这里开始就可以进入 C++ 了，但是不要忘记一件事，就是 libc 的上下文还没解决。</p>
<h2>多核下 Newlib 的上下文</h2>
<h3>可重入函数</h3>
<p>在 newlib 中，几乎所有函数都提供了两个版本，即不可重入的普通版本（ANSI），以及可重入的版本。不可重入的版本，其最终还是调用了可重入版本的函数，不过传入了一个全局重入结构。例如，printf:</p>
<p>不可重入版：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">	printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">__restrict</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> ...</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">               _ATTRIBUTE</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ((</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">__format__</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">__printf__</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)));</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p>可重入版：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">	_printf_r</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">struct</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> _reent </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">__restrict</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75"> ...</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">               _ATTRIBUTE</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ((</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">__format__</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">__printf__</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 3</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)));</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p>可以注意到，可重入版本多了一个 <code>_reent</code> 结构体，其在 <code>&lt;sys/reent.h&gt;</code> 定义，一并定义了全局的：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">/*</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> * All references to struct _reent are via this pointer.</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> * Internally, newlib routines that need to reference it should use _REENT.</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> */</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#ifndef</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __ATTRIBUTE_IMPURE_PTR__</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __ATTRIBUTE_IMPURE_PTR__</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#endif</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">extern</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> struct</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _reent </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">_impure_ptr __ATTRIBUTE_IMPURE_PTR__;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#ifndef</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __ATTRIBUTE_IMPURE_DATA__</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __ATTRIBUTE_IMPURE_DATA__</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#endif</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">extern</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> struct</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _reent _impure_data __ATTRIBUTE_IMPURE_DATA__;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">/* #define _REENT_ONLY define this to get only reentrant routines */</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#if</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> defined</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">__DYNAMIC_REENT__</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;&#x26;</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2"> !</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">defined</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">__SINGLE_THREAD__</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#ifndef</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __getreent</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  struct</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _reent </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __getreent</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#endif</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"># define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> _REENT</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">__getreent</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">()</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#else</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> /* __SINGLE_THREAD__ || !__DYNAMIC_REENT__ */</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"># define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> _REENT</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _impure_ptr</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#endif</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> /* __SINGLE_THREAD__ || !__DYNAMIC_REENT__ */</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> _REENT_IS_NULL</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">_ptr</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) ((_ptr) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> NULL</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> _GLOBAL_REENT</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">_impure_data)</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>在 newlib 内部，不可重入函数通过 <code>_REENT</code> 宏获取全局重入对象指针后传入可重入版本，完成后续操作。</p>
<h3>提供核心本地的 _reent</h3>
<p>从上面的定义可以看出，我们如果以 <code>__DYNAMIC_REENT__</code> 定义的情况编译 newlib，那么就可以通过 <code>__getreent()</code> 函数，提供核心本地的 <code>_reent</code> 结构。稍微修改编译脚本，重新编译工具链（参见<a href="https://github.com/DynamicLoader/riscv-gnu-toolchain/commit/e2b11aaa3734b4baded4510a73770a3b77a46a28" target="_blank" rel="noopener noreferrer">此处</a>），然后添加一个实现：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    struct</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _reent </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">__getreent</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (k_stage </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_MULTICORE)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> &#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">hl_reent;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _GLOBAL_REENT;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这里 hl_reent 是线程本地 (Hart Local) 的 <code>_reent</code>。</p>
<p><strong>读到这里，很容易想到一个问题，那就是我的 hl_reent 如何存储呢？</strong></p>
<h2>核心本地存储</h2>
<p>核心本地存储，就是每个核心所单独享有的存储空间。在不同核心上运行的系统程序，应该具有同样的需求，（代码都一样啊），即我们需要通过一些手段来区分核心并从不同的地方提供存储。</p>
<h3>原始方法</h3>
<p>一个简单而容易想到的方法是，不使用统一的 MMU 映射，而是通过差别映射，将核心系统栈固定在一个地址，然后在核心栈以上预留一段空间，作为核心本地存储。具体实现，可以参考<a href="https://github.com/DynamicLoader/ABYDOS/blob/71acf29d3e92d5acacadd12a7d01a4af192af7d6" target="_blank" rel="noopener noreferrer">此提交时的仓库</a>。</p>
<p>获取地址的函数示例：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">k_getHartLocal</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    extern</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> uintptr_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _sys_stack_base;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    extern</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _KERNEL_HART_LOCAL_DATA_SIZE;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)(_sys_stack_base </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">-</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">uintptr_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">_KERNEL_HART_LOCAL_DATA_SIZE);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3>改进方案：利用 TLS</h3>
<p>前面说过，多核可以看成硬件实现的多线程，那就可以利用一下多线程的技术。这里的 TLS 不是 计网的 TLS，而是 Thread Local Storage。其具体定义可以参考 <a href="https://www.akkadia.org/drepper/tls.pdf" target="_blank" rel="noopener noreferrer">ELF Handling For Thread-Local Storage</a>。</p>
<p>简单来说，通过 C++ 的 <code>thread_local</code> 关键字，或者 C 中的 <code>_Thread_local</code> 定义的变量，会被编译器放入特别的段：<code>.tbss</code> 和 <code>.tdata</code>。这些段并不是直接拿来用的，而是作为一个副本，由实现自行加载内存区域并初始化。那么，如何寻址呢？在 RISCV 上，静态链接的情况下，是通过 <code>tp</code> 寄存器。该寄存器持有一个基址，即 TLS 本地存储的最低地址。我们要做的，首先是创建这两个段，拿到其原始数据的地址：</p>
<div class="language-ld line-numbers-mode" data-highlighter="shiki" data-ext="ld" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-ld"><span class="line"><span>    .tdata :</span></span>
<span class="line"><span>	{</span></span>
<span class="line"><span></span></span>
<span class="line"><span>		PROVIDE(_tdata_start = .);</span></span>
<span class="line"><span></span></span>
<span class="line"><span>		*(.tdata)</span></span>
<span class="line"><span>		*(.tdata.*)</span></span>
<span class="line"><span>		. = ALIGN(8);</span></span>
<span class="line"><span>		PROVIDE(_tdata_end = .);</span></span>
<span class="line"><span>	} </span></span>
<span class="line"><span></span></span>
<span class="line"><span>	/* In TLS, do not add align 4K, otherwise addressing to tbss will need to add a 4k from $tp which cost much space */</span></span>
<span class="line"><span></span></span>
<span class="line"><span>	.tbss : {</span></span>
<span class="line"><span>		PROVIDE(_tbss_start = .);</span></span>
<span class="line"><span>		*(.tbss)</span></span>
<span class="line"><span>		*(.tbss.*)</span></span>
<span class="line"><span>		. = ALIGN(8);</span></span>
<span class="line"><span>		PROVIDE(_tbss_end = .);</span></span>
<span class="line"><span>		</span></span>
<span class="line"><span>	}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>要注意的是，由于依赖 <code>tp</code> 寻址，所以两个段中间的空闲区域也会算进去，应该不加对齐，否则会浪费内存，搞不好就非法访问了。（我才不会告诉你我调了一上午才发现 qwq）。</p>
<p>然后，在核心初始化时基于核心栈底，保留一段空间作为 TLS ，设置好 <code>tp</code> 寄存器通过汇编实现：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">	/* Reserve Exception stack */</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	li a3, K_CONFIG_EXCEPTION_BACKUP_SIZE</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	csrw CSR_SSCRATCH, sp</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	sub sp, sp, a3</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">_process_tbss:</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">	/* Setup tbss */</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	lla a4, _tbss_start</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	lla a5, _tbss_end</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	beq a4, a5, _process_tdata</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	sub a2, a5, a4</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	sub sp, sp, a2</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	mv  tp, sp</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	mv	a3, tp</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">	/* Zero-out tbss */</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">_tbss_zero:</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	REG_S	zero, (a3)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	add a3, a3, __SIZEOF_POINTER__</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	add	a4, a4, __SIZEOF_POINTER__</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	blt	a4, a5, _tbss_zero</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">_process_tdata:</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">	/* Setup tdata */</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	lla a3, _tdata_start</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	lla a2, _tdata_end</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	beq a3, a2, _fini_setup_hart</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	sub a2, a2, a3</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	sub sp, sp, a2</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	mv tp, sp</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">	/* Copy tdata */</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	lla a4, _tdata_end</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	mv a5, tp</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">_tdata_copy:</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	REG_L a2, (a3)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	REG_S a2, (a5)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	add a3, a3, __SIZEOF_POINTER__</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	add a5, a5, __SIZEOF_POINTER__</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	blt a3, a4, _tdata_copy</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">_fini_setup_hart:</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	ret</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这里顺便预留一下异常处理空间。处理完成后，整个布局如下：</p>
<figure><img src="https://imgcdn0.octz.net/blog/2024/mcores_stackmap.png" alt="核心存储布局" tabindex="0" loading="lazy"><figcaption>核心存储布局</figcaption></figure>
<h3>TLS 支持的 newlib</h3>
<p>NewLib 本身可以使用 TLS 来替代 <code>_reent</code>，但是我目前没有采用这种方案，原因是，</p>
<ol>
<li>在启动早期的单核阶段，TLS 需要额外的空间分配和复制，比较难以实现</li>
<li>在系统退出多核模式后，还要重新初始化 TLS，避免死锁和冲突</li>
</ol>
<h2>多核同步</h2>
<h3>进入多核模式</h3>
<p>由于核心启动需要时间，而我们不希望在所有核心都启动之前就开跑，就需要使用一个变量构造锁。</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    enum</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2"> k_stage_t</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        K_BEFORE_BOOT </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        K_BOOT </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        K_BOOT_PERIP </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        K_BOOT_HARTS </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 3</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        K_MULTICORE </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        K_CLEARUP </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 5</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    };</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    extern</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2"> k_stage_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> k_stage;</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>然后在核心启动到 <code>k_premain()</code> 中增加：</p>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    while</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (k_stage </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">!=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_MULTICORE)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        ;</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">          // wait for the boot core to finish</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p>这将导致所有后启动的核心等待启动核心完成。</p>
<h3>退出多核模式</h3>
<p>退出多核模式之前，需要保证后启动核心正常停止，然后由启动核心清理现场。通过 <code>k_after_main()</code> 函数实现：</p>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> k_after_main</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> hartid</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> main_ret</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (hartid </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // Non boot hart</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">        printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Hart </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%i</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> has returned with </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%d</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, ::hartid, main_ret);</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">        k_hart_state</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[::hartid] </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 3</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        // printf("Failed to stop hart: %ld\n", SBIF::HSM::stopHart());</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    else</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">        printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">> Waiting for other harts to return...</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> flag </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        do</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // a timeout can be added here</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            flag </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            for</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">; i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 8</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">; </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">++</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">i)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> hartid)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    continue</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">k_hart_state</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[i] </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2"> ||</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> k_hart_state</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[i] </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                    flag </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    break</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">k_hart_state</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[i] </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 3</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2"> ||</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> k_hart_state</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[i] </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    continue</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        } </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">while</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (flag);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        k_stdout_switched </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> false</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        k_stage </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_CLEARUP;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> main_ret;</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // pass to the lower</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3>newlib 的锁</h3>
<p>虽然我们使用 TLS 提供了核心专用的 _reent，但是 IO 方面仍然不支持多核，需要加锁。这里要利用 newlib 的 <code>retargetable locking</code>，提供自己的实现。首先看 <code>&lt;sys/lock.h&gt;</code> 定义：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#if</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2"> !</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">defined</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">_RETARGETABLE_LOCKING</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">typedef</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _LOCK_T;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">typedef</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _LOCK_RECURSIVE_T;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __LOCK_INIT</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">class</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">static</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> lock </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __LOCK_INIT_RECURSIVE</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">class</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">static</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> lock </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __lock_init</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) ((</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __lock_init_recursive</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) ((</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __lock_close</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) ((</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __lock_close_recursive</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) ((</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __lock_acquire</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) ((</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __lock_acquire_recursive</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) ((</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __lock_try_acquire</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) ((</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __lock_try_acquire_recursive</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) ((</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __lock_release</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) ((</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __lock_release_recursive</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) ((</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#else</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#ifdef</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __cplusplus</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">extern</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "C"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#endif</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">struct</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> __lock;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">typedef</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> struct</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> __lock </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _LOCK_T;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> _LOCK_RECURSIVE_T</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _LOCK_T</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __LOCK_INIT</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">class</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">extern</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> struct</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> __lock __lock_ ## lock; </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">	class _LOCK_T lock </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> &#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">__lock_ ## lock</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __LOCK_INIT_RECURSIVE</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">class</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">__LOCK_INIT</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(class</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">lock)</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">extern</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __retarget_lock_init</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">_LOCK_T </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __lock_init</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">__retarget_lock_init</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">lock)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">extern</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __retarget_lock_init_recursive</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">_LOCK_T </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __lock_init_recursive</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">__retarget_lock_init_recursive</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">lock)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">extern</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __retarget_lock_close</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">_LOCK_T </span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __lock_close</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">__retarget_lock_close</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(lock)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">extern</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __retarget_lock_close_recursive</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">_LOCK_T </span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __lock_close_recursive</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">__retarget_lock_close_recursive</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(lock)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">extern</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __retarget_lock_acquire</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">_LOCK_T </span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __lock_acquire</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">__retarget_lock_acquire</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(lock)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">extern</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __retarget_lock_acquire_recursive</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">_LOCK_T </span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __lock_acquire_recursive</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">__retarget_lock_acquire_recursive</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(lock)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">extern</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __retarget_lock_try_acquire</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">_LOCK_T </span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __lock_try_acquire</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">__retarget_lock_try_acquire</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(lock)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">extern</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __retarget_lock_try_acquire_recursive</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">_LOCK_T </span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __lock_try_acquire_recursive</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">  __retarget_lock_try_acquire_recursive</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(lock)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">extern</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __retarget_lock_release</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">_LOCK_T </span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __lock_release</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">__retarget_lock_release</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(lock)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">extern</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __retarget_lock_release_recursive</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">_LOCK_T </span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __lock_release_recursive</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">__retarget_lock_release_recursive</span><span style="--shiki-light:#383A42;--shiki-dark:#E06C75">(lock)</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#ifdef</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> __cplusplus</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#endif</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#endif</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> /* !defined(_RETARGETABLE_LOCKING) */</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>好了，你已经猜到要干嘛了，重新编译工具链，打开这个选项。</p>
<p>之后，利用 std:atomic 造一个锁结构：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    struct</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> __lock</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        std::atomic</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;int></span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> owner </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> -</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        std::atomic</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;int></span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> recursive_count </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">bool</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> recursive </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> false</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (k_stage </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">!=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_MULTICORE)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            // _write(0, (char*)"PLOCK\n",6);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (recursive)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (owner </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> hartid)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                    recursive_count</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">++</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> null_owner </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> -</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // helper for compare_exchange_weak</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            while</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">owner</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">compare_exchange_weak</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(null_owner, hartid))</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                null_owner </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> -</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            recursive_count </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">            // _write(0, (char *)"LOCK\n", 5);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> unlock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">bool</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> recursive </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> false</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (k_stage </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">!=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_MULTICORE)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (recursive)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (owner </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> hartid)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">--</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">recursive_count </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                        owner </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> -</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (owner </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> hartid)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                owner </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> -</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    };</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>由于声明中没有使用 __weak，所以我们要将整个编译单元的所有函数和变量全部覆盖，以通过编译，详情可以参见<a href="https://github.com/DynamicLoader/ABYDOS/blob/master/kernel/main/libc_hooks.cpp" target="_blank" rel="noopener noreferrer">libc_hooks.cpp</a>。</p>
<h2>后记</h2>
<p>通过这样的操作，多核环境就搭建好了，输出也没有冲突。当然，博客所示的代码还是比较少，详细实现还请参看<a href="https://github.com/DynamicLoader/ABYDOS" target="_blank" rel="noopener noreferrer">仓库代码</a>。</p>
<p>这一波用了 3 天，属实给我调试到麻了，各种冲突、异常，整个都是比较抽象的。不过，结果是好的，下一步，就可以折腾 CPU 的中断了。亲爱的读者，我们下期再会！</p>
]]></content:encoded>
      <enclosure url="https://imgcdn0.octz.net/blog/2024/mcores_stackmap.png" type="image/png"/>
    </item>
    <item>
      <title>AbydOS开发日记 (7) -  内部中断</title>
      <link>https://octz.net/blog/AbydOS/7-internal-int.html</link>
      <guid>https://octz.net/blog/AbydOS/7-internal-int.html</guid>
      <source url="https://octz.net/rss.xml">AbydOS开发日记 (7) -  内部中断</source>
      <description>RV64 的中断 搞了这么多基础设施，终于到中断的实现了。首先看下 RV 的中断和异常， 这里的 Interrupt 是 scause 这个 CSR 之中的最高位。 注：中断也叫异步异常，异常通常指同步异常，两者合并可以叫陷阱(Trap)。 控制 涉及到中断控制，一共有几个 CSR 需要考虑，如下: 中断控制寄存器中断控制寄存器 首先是 sstatus...</description>
      <category>ABYDOS</category>
      <pubDate>Tue, 26 Mar 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>RV64 的中断</h2>
<p>搞了这么多基础设施，终于到中断的实现了。首先看下 RV 的中断和异常，</p>
<p>| Interrupt | Exception Code | Description                    |<br>
| :</p>
]]></content:encoded>
      <enclosure url="https://imgcdn0.octz.net/blog/2024/intpr-cr.png" type="image/png"/>
    </item>
    <item>
      <title>AbydOS开发日记 (8) -  文件系统框架</title>
      <link>https://octz.net/blog/AbydOS/8-fs-framework.html</link>
      <guid>https://octz.net/blog/AbydOS/8-fs-framework.html</guid>
      <source url="https://octz.net/rss.xml">AbydOS开发日记 (8) -  文件系统框架</source>
      <description>好久不见！自从上一篇博客，上板成功，到现在已经过去了 3 个月。这几个月，主要是忙活一些学业上的东西，4月跟着老师探索了一点 IC design with LLM 的内容，5月忙活各种大作业、小组作业，6月忙活备考。终于考完试了，开完香槟就开始填坑啦！ 虚拟文件系统 由于 Unix 的 “文件即一切” 思想实在很好，所以我们采用这样的思路。 虚拟文件系...</description>
      <category>ABYDOS</category>
      <pubDate>Wed, 03 Jul 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<blockquote>
<p>好久不见！自从上一篇博客，上板成功，到现在已经过去了 3 个月。这几个月，主要是忙活一些学业上的东西，4月跟着老师探索了一点 IC design with LLM 的内容，5月忙活各种大作业、小组作业，6月忙活备考。终于考完试了，开完香槟就开始填坑啦！</p>
</blockquote>
<h2>虚拟文件系统</h2>
<p>由于 Unix 的 “文件即一切” 思想实在很好，所以我们采用这样的思路。<br>
虚拟文件系统，即 Virtual FileSystem, VFS, 是整个文件系统的抽象，向上层提供统一的访问接口。考虑简单的设计，VFS 只需实现真实文件系统的挂载、卸载，以及各种操作的代理即可。</p>
<h3>基础定义</h3>
<p>我们定义一个基类，作为基础文件系统，所有真实的文件系统都需要遵守之：</p>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">class</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> BasicFS</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  public:</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    virtual</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> open</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">path</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> flags</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> mode</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    virtual</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> close</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> fd</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    virtual</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> read</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> fd</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">buf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">size_t</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> count</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    virtual</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> write</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> fd</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">buf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">size_t</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> count</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    virtual</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> lseek</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> fd</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">off_t</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> offset</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> whence</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    virtual</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fstat</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> fd</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">struct</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> stat</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">buf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">    // virtual int stat(const char *path, struct stat *buf) = 0;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">    // virtual int opendir(const char *path) = 0;</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">    // virtual int readdir(int fd, struct dirent *dirp) = 0;</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">    // virtual int closedir(int fd) = 0;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">    // virtual int mkdir(const char *path, mode_t mode) = 0;</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">    // virtual int rmdir(const char *path) = 0;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    virtual</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> ~BasicFS</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">() </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> default</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">};</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3>初始框架</h3>
<p>针对 VFS 的初步功能，我们需要维护三张表，如下：</p>
<ol>
<li>文件系统驱动程序表，存放文件系统驱动程序的挂载、卸载函数</li>
<li>虚拟挂载点表，将挂载点路径映射到对应的文件系统驱动对象</li>
<li>全局文件描述符表，将全局 fd 号映射到文件系统驱动对象及内部 fd 号</li>
</ol>
<p>这里的设计类似于 DriverManager，但是不同的是，一个文件系统驱动可以拥有多个对象（在不同的挂载点上），而一个对象可以持有多个fd，是一个 1Ⓜ️n 的关系，而 DriverManager 是一个 1:m 的关系，即一个驱动对应多个设备。故而，引入工厂模式，通过专用函数进行构造和销毁，减轻 FS 内部管理的负担。同样的，我们本来可以委派一个 fd 给真实的 FS，但是这样并没有多大用处，只是转换的层级下放到了真实的 FS 中。</p>
<p>我们定义这样的类：</p>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">constexpr</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> FILE_STDIN </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">constexpr</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> FILE_STDOUT </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">constexpr</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> FILE_STDERR </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">class</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> VirtualFS</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  public:</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    using</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> newInstanceFunc_t</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> std::</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">function</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">&#x3C;std::</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">pair</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">BasicFS</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">>(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">devicePath</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)>;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    using</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> deleteInstanceFunc_t</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> std::</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">function</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">BasicFS</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)>;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    VirtualFS</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    ~VirtualFS</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    static</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> registerFS</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> std::</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">string</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> &#x26;</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">fs_name</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">newInstanceFunc_t</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> nf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">deleteInstanceFunc_t</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> df</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    static</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> unregisterFS</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> std::</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">string</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> &#x26;</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">fs_name</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    static</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> open</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">path</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> flags</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> mode</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    static</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> close</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> fd</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    static</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> read</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> fd</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">buf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> count</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    static</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> write</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> fd</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">buf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> count</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    static</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> lseek</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> fd</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">off_t</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> offset</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> whence</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    static</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fstat</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> fd</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">struct</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> stat</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">buf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    static</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> mount</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">path</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">devicePath</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> flags</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> mode</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">fs_name</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> =</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> nullptr</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    static</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> umount</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">path</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  private:</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    static</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> std::map</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">std::string, std::pair</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">BasicFS </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">deleteInstanceFunc_t</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">>></span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _fs_map;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    static</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> std::vector</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">std::tuple</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">std::string, </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">newInstanceFunc_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">deleteInstanceFunc_t</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">>></span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        _fs_factories;</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // fs-name, new-instance-func, delete-instance-func</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    static</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2"> lock_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _fs_lock;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    static</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> std::map</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, std::pair</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">BasicFS </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int>></span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _global_fd_map;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    static</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _global_fd_counter;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">};</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="hint-container tip">
<p class="hint-container-title">Note</p>
<p>遵守 POSIX 的规范，我们预留头三个文件号给 STDIO。<br>
所有操作都需要加锁，未来可以考虑细化锁的粒度。</p>
</div>
<h3>文件系统驱动的注册与反注册</h3>
<p>类似于设备驱动的，利用 global constructor 进行注册，要求我们的列表先于文件系统驱动初始化，详细请参阅设备驱动框架的描述。<br>
在 <code>registerFS()</code> 中，我们只需做参数校验并加入 <code>_fs_factories</code>；而反注册，只需找出来名称对应的项删除即可。<br>
需要注意的是，反注册一个 FS 并不会将其对应的对象销毁，而只能避免安装新的对象，虽然不符合一些原则，但是我们的系统目前没有动态加载和卸载内核模块的办法，先做到这里也无可厚非。</p>
<h3>文件系统的挂载与卸载</h3>
<p>对于挂载，我们遍历所有的安装函数，传入一个挂载设备字符串，驱动程序根据字符串寻找设备对象并进行操作。随后，如果挂载成功，返回一个 0 错误码；若不是支持的文件系统，则返回不支持；若挂载过程出现了错误，则返回错误码。当不支持时，遍历继续，否则终止。</p>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    static</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> mount</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">path</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">devicePath</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> flags</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> mode</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">fs_name</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> =</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> nullptr</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">        _fs_lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        for</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">auto</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2"> &#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">fs : _fs_factories)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ((fs_name </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> std::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">get</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">>(fs) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> fs_name) </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">||</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2"> !</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">fs_name)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                auto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> [ret, fs_instance] </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> std::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">get</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">>(fs)(devicePath);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (ret </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_OK)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                {</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                    _fs_map</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">insert</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-dark:#E5C07B">std</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">make_pair</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(path, std::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">make_pair</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fs_instance, std::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">get</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">>(fs))));</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                    _fs_lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">unlock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    return</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (ret </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">!=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_ENOTSUPP)</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // Something other than not supported happened</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                {</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                    _fs_lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">unlock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ret;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">        _fs_lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">unlock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_ENOTSUPP;</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // No FS could be mounted</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>对于卸载，简单的就是找到挂载点对应的对象，进行解除安装。已打开的文件暂时不受影响，以后完善。</p>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    static</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> umount</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">path</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // After unmounting, the FS instance is deleted</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">        _fs_lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        auto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> it </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> _fs_map</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">find</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(path);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (it </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">!=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> _fs_map</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">end</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">())</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            it</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">-></span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">second</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">second</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">it</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">-></span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">second</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">first</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            _fs_map</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">erase</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(it);</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            _fs_lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">unlock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">        _fs_lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">unlock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_ENOTSUPP;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3>操作代理</h3>
<p>主要涉及 <code>open()</code> <code>close()</code> <code>read()</code> <code>write()</code> <code>lseek()</code> 等。</p>
<p>只要维护全局文件描述符表并对应调用真实文件系统服务程序即可。此处以 <code>open()</code> 为例：</p>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    static</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> open</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">path</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> flags</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> mode</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        // printf("Open %s", path);</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">        _fs_lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        BasicFS </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">fs </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> nullptr</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        size_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> max_len </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        for</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">auto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> x : _fs_map)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#383A42;--shiki-dark:#E5C07B">std</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">string_view</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(path).</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">find</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">x</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">first</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (max_len </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> x</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">first</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">size</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">())</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                    max_len </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> x</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">first</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">size</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                    fs </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> x</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">second</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">first</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (fs)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ret </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> fs</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">-></span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">open</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(path</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">+</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">max_len, flags, mode);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (ret </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">>=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                auto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> fd </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _global_fd_counter</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">++</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                _global_fd_map</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">insert</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-dark:#E5C07B">std</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">make_pair</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fd, std::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">make_pair</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fs, ret)));</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                _fs_lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">unlock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> fd;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            _fs_lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">unlock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ret;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">        // printf("Failed!\n");</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">        _fs_lock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">unlock</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_ENOENT;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>各文件的锁以及权限等在真实文件系统驱动中维护，因其多样性。</p>
<h2>最简单的文件系统实现：CPIO</h2>
<p>CPIO 是 Linux 上用于同步文件的一种格式，完整地记录了文件在文件系统中的各个状态。其归档被用于 initrd，读取的代码总共也没有 500 行，也是只读的。要实现它，我们先引入 <code>libcpio</code>，然后适配我们的文件系统框架即可。</p>
<details class="hint-container details"><summary>详细实现</summary>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#include</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> &#x3C;cstdint></span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#include</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> &#x3C;cstring></span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#include</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> &#x3C;stdexcept></span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#include</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "libcpio/libcpio.h"</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#include</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "k_vfs.h"</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#include</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "k_defs.h"</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">class</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> CPIOFS</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> : </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">public</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> BasicFS</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  public:</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    CPIOFS</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">archive</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">unsigned</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> long</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> len</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) : </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">_archive_len</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(len)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">        printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%p</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%lu</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, archive, len);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">cpio_info</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(archive, len, </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">_info))</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            throw</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> std::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">runtime_error</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"cpio_info failed"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        else</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">            printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"[CPIOFS] cpio_info: </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%d</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> files, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%d</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> max_path_size</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">_info</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">file_count</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">_info</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">max_path_sz</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        _archive </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> uint8_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[len];</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">        memcpy</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(_archive, archive, len);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    ~CPIOFS</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (_archive)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            delete[]</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _archive;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        _archive </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> nullptr</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> open</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">path</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> flags</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> mode</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">override</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        unsigned</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> long</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> size </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">file </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> cpio_get_file</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(_archive, _archive_len, path, </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">size);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">file)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_ENOENT;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        for</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">; i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> MAX_FILES; i</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">++</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">_fcb</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[i].</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">used</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            {</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                _fcb</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[i].</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">used</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> =</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> true</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                _fcb</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[i].</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">file</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)file;</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                _fcb</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[i].</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">size</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> size;</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">                _fcb</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[i].</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">lpos</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> =</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> i;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_ENOMEM;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> close</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> fd</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">override</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (fd </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">>=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> MAX_FILES </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">||</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> fd </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_ENOENT;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">_fcb</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[fd].</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">used</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_ENOENT;</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">        _fcb</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[fd].</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">used</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> =</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> false</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">        _fcb</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[fd].</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">file</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> =</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> nullptr</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">        _fcb</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[fd].</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">size</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> =</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">        _fcb</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[fd].</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">lpos</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> =</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_OK;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> read</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> fd</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">buf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">size_t</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> count</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">override</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (fd </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">>=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> MAX_FILES </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">||</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> fd </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_ENOENT;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">_fcb</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[fd].</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">used</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_ENOENT;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">_fcb</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[fd].</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">lpos</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> +</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> count </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">></span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> _fcb</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[fd].</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">size</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            count </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> _fcb</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[fd].</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">size</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> -</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> _fcb</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[fd].</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">lpos</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">        memcpy</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(buf, (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">uint8_t</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">_fcb</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[fd].</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">file</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> +</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> _fcb</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[fd].</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">lpos</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, count);</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">        _fcb</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[fd].</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">lpos</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> +=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> count;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> count;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> write</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> fd</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">buf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">size_t</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> count</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">override</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> -</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // No write should be made to a CPIO archive</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> lseek</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> fd</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">off_t</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> offset</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> whence</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">override</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (fd </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">>=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> MAX_FILES </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">||</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> fd </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_ENOENT;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">_fcb</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[fd].</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">used</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_ENOENT;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (whence </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> SEEK_SET)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (offset </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_EINVAL;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (offset </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">></span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">long</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> long</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">_fcb</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[fd].</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">size</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_EINVAL;</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            _fcb</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[fd].</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">lpos</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> offset;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        else</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (whence </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> SEEK_CUR)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">_fcb</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[fd].</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">lpos</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> +</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> offset </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_EINVAL;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">_fcb</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[fd].</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">lpos</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> +</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> offset </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">></span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> _fcb</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[fd].</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">size</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_EINVAL;</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            _fcb</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[fd].</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">lpos</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> +=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> offset;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        else</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (whence </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> SEEK_END)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (offset </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">></span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_EINVAL;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (offset </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> -</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">long</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> long</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">_fcb</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[fd].</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">size</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_EINVAL;</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">            _fcb</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[fd].</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">lpos</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> =</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> _fcb</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[fd].</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">size</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> +</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> offset;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        else</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_EINVAL;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> K_OK;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fstat</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> fd</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">struct</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> stat</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">buf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">override</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> -</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  private:</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    static</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> constexpr</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> MAX_FILES </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1024</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    uint8_t</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">_archive </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> NULL</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    size_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _archive_len </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    struct</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> cpio_info</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> _info</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    struct</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> fcb_t</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        bool</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> used </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> false</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">file </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> nullptr</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        unsigned</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> long</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> size </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        unsigned</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> long</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> lpos </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    };</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    std::array</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">fcb_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, MAX_FILES</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">></span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _fcb;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">};</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">// Register the filesystem</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">FS_INSTALL_FUNC</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(K_PR_FS_BEGIN) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">static</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fs_register</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    VirtualFS::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">registerFS</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span></span>
<span class="line"><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">        "cpiofs"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        [](</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">devicePath</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) -> </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">std::pair&#x3C;int,</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> BasicFS</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *></span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            try</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                size_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> addr </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, len </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">sscanf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(devicePath, </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%lu</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">,</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%lu</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">addr, </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">len) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">!=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 2</span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2"> &#x26;&#x26;</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> sscanf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(devicePath, </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%lx</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">,</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%lx</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">addr, </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">len) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">!=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                    throw</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> std::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">runtime_error</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"invalid devicePath specified"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                auto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ret </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> new</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> CPIOFS</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">((</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)addr, len);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, ret};</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            catch</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (std::exception </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">e)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            {</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">                printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"[CPIO] Failed to create CPIOFS: </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%s</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">e</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">what</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">());</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">-</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">nullptr</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">};</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            catch</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (...)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            {</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">                printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"[CPIO] Failed to create CPIOFS: unknown exception</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">-</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">nullptr</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">};</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        },</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        [](</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">BasicFS</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">fs</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) -> </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            delete</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> fs;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        });</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"FS CPIO installed</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div></details>
<p>我们限定从内存中读取归档，需要一个起始地址和长度，从安装设备路径字符串获得。</p>
<h2>LibC 的适配</h2>
<p>我们想要比较容易在 OS 层进行使用文件系统，则需要进行 LibC 的适配。其实只需要将相关函数重写到 VFS 处理即可：</p>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">    // Hook with libc</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> _write</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> fd</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">buf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> size</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> VirtualFS::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">write</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fd, buf, size);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> _read</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> fd</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">char*</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> buf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> size</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">){</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> VirtualFS::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">read</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fd, buf, size);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> _close</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> fd</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> VirtualFS::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">close</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fd);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> _open</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">path</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> flags</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> mode</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> VirtualFS::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">open</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(path, flags, mode);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> _lseek</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> fd</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">off_t</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> offset</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> whence</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> VirtualFS::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">lseek</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fd, offset, whence);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> _fstat</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> fd</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">struct</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> stat</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">buf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> VirtualFS::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">fstat</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fd, buf);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>值得一提的是，之前我们直接重写 <code>_write()</code> 重定向 stdout 到串口，改动之后只需在 VFS 加入一个判断并写在那里即可。</p>
<h2>测试</h2>
<p>我们首先生成一个 cpio 归档，如下将 <code>2.txt</code> 加入：</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-bash"><span class="line"><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">echo</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> 2.txt</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> | </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">cpio</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -o</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -H</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> newc</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> > </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">1.cpio</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><blockquote>
<p>注意cpio 也有多种格式，这里使用 newc 变体。</p>
</blockquote>
<p>随后我们修改 sysroot 解析 initrd 参数，</p>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    prop </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fdt_get_property</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fdt, rc, </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"linux,initrd-start"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">len);</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // Just compatible with Linux</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (prop)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        size_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> t </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, e </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (len </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            t </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fdt32_to_cpu</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">((</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">fdt32_t</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">prop</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">-></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">data</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)));</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (len </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 8</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            t </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fdt64_to_cpu</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">((</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">fdt64_t</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">prop</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">-></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">data</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)));</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    </span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        prop </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fdt_get_property</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(fdt, rc, </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"linux,initrd-end"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">len);</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // Just compatible with Linux</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (prop)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (len </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                e </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fdt32_to_cpu</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">((</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">fdt32_t</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">prop</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">-></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">data</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)));</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (len </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 8</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                e </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> fdt64_to_cpu</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">((</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">fdt64_t</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> *</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">prop</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">-></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">data</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)));</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    </span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (t </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> e </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">&#x26;&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> e </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">></span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> t)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                _initrd_path </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> std::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">to_string</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(t) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">+</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> ","</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> +</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> std::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">to_string</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(e </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">-</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> t);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>然后在 boot 中挂载之:</p>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">    // Mount rootfs</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    auto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> rootfs </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> sysroot</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">-></span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">initrd</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">rootfs</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">empty</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">())</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        std::cout </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;&#x3C;</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "[W] Rootfs not specified!"</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> &#x3C;&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> std::endl;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">else</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        std::cout </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;&#x3C;</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "Mounting rootfs: "</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> &#x3C;&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> rootfs </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> std::endl;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        auto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> rc </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> VirtualFS::</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">mount</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"/"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">rootfs</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">c_str</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(), </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (rc </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            std::cout </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;&#x3C;</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "[E] Failed to mount rootfs: "</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> &#x3C;&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> rc </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> std::endl;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> rc;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        std::cout </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;&#x3C;</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "[I] Rootfs mounted successfully!"</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> &#x3C;&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> std::endl;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>接着在 k_main 中就可以直接使用 STL 的文件操作了：</p>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    std::</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">ifstream</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> f</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"/2.txt"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">f</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">is_open</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">())</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        std::string line;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        while</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">getline</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(f, line))</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">            printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"!!!Reading from 2.txt: </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%s</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">line</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">c_str</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">());</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">        f</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">close</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">();</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    else</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">        printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Failed to open file</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>编译运行，</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-bash"><span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">qemu-system-riscv64</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -M</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> virt</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -m</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> 256M</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -nographic</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -bios</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> build/opensbi/build/platform/generic/firmware/fw_jump.elf</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -kernel</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> build/AbydOS_KNL</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -initrd</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> build/1.cpio</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>得到：</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>Mounting rootfs: 2282749952,512</span></span>
<span class="line"><span>0x88100000, 512</span></span>
<span class="line"><span>[CPIOFS] cpio_info: 1 files, 5 max_path_size</span></span>
<span class="line"><span>[I] Rootfs mounted successfully!</span></span>
<span class="line"><span>> Booting harts... (Boot hart = 0)</span></span>
<span class="line"><span>> Switching to multicore mode</span></span>
<span class="line"><span>Timer interrupt for hart 0</span></span>
<span class="line"><span>Current Time: 2216260</span></span>
<span class="line"><span>Hello from hart 0!</span></span>
<span class="line"><span>!!!Reading from 2.txt: 114514</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>至此，文件系统框架搭建完成，也适配了 initrd，可以用于后续测试而不必急于编写真的文件系统驱动和存储设备驱动，总共耗时：一天。</p>
]]></content:encoded>
    </item>
    <item>
      <title>Step into Chromium (0) - 源码编译</title>
      <link>https://octz.net/blog/Chromium/0-Compile.html</link>
      <guid>https://octz.net/blog/Chromium/0-Compile.html</guid>
      <source url="https://octz.net/rss.xml">Step into Chromium (0) - 源码编译</source>
      <description>前言 玩玩 Chromium Native 开发呗？第一步当然是编译一个纯净的 Chromium 啦！ 原始文档 https://chromium.googlesource.com/chromium/src/+/main/docs/windows_build_instructions.md 本文主要记录在我的环境上如何干净的构建它。限制点： 非默认的 ...</description>
      <category>Chromium</category>
      <pubDate>Fri, 26 Sep 2025 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>前言</h2>
<p>玩玩 Chromium Native 开发呗？第一步当然是编译一个纯净的 Chromium 啦！</p>
<div class="hint-container info">
<p class="hint-container-title">原始文档</p>
<p><a href="https://chromium.googlesource.com/chromium/src/+/main/docs/windows_build_instructions.md" target="_blank" rel="noopener noreferrer">https://chromium.googlesource.com/chromium/src/+/main/docs/windows_build_instructions.md</a></p>
</div>
<p>本文主要记录在我的环境上如何干净的构建它。限制点：</p>
<ul>
<li>非默认的 Visual Studio 安装位置</li>
<li>连续磁盘空间不足 200 GB</li>
<li>不污染环境变量</li>
</ul>
<h2>系统环境准备</h2>
<p>硬件和系统要求并不低，可以参考我的配置：</p>
<ul>
<li>系统：Windows 11 (AMD64)</li>
<li>CPU: Intel Core i7-12700H</li>
<li>内存：DDR5 32GB</li>
</ul>
<p>在该笔记本上完整编译一次需要 7 小时以上。</p>
<div class="hint-container important">
<p class="hint-container-title">重要</p>
<p>你还需要一个稳定的可以访问 google source 的网络环境，至少 80GB 的流量开销。</p>
</div>
<h2>工具链和基建设施准备</h2>
<h3>Visual Studio (下称VS) 安装和配置</h3>
<p>Chromium 的工程化比较完善，工具链和依赖以 depot_tools 仓库的形式维护。但是在获取这个仓库之前，你还应该安装 Visual Studio 2022，以及下列包：</p>
<figure><img src="https://imgcdn0.octz.net/blog/2025/cr0-image.png" alt="组件" tabindex="0" loading="lazy"><figcaption>组件</figcaption></figure>
<figure><img src="https://imgcdn0.octz.net/blog/2025/cr0-image-1.png" alt="单个组件" tabindex="0" loading="lazy"><figcaption>单个组件</figcaption></figure>
<div class="hint-container warning">
<p class="hint-container-title">注意</p>
<p>随 Chromium 版本升级，源文档中对于 Windows SDK 的小版本号会逐渐变大，如果你发现当前找不到这么新的 Windows SDK，请升级 VS 主版本。</p>
</div>
<p>安装好以后，到应用中找到 Windows SDK，修改：</p>
<figure><img src="https://imgcdn0.octz.net/blog/2025/cr0-image-2.png" alt="Windows SDK" tabindex="0" loading="lazy"><figcaption>Windows SDK</figcaption></figure>
<figure><img src="https://imgcdn0.octz.net/blog/2025/cr0-image-3.png" alt="选择 Change, Next" tabindex="0" loading="lazy"><figcaption>选择 Change, Next</figcaption></figure>
<figure><img src="https://imgcdn0.octz.net/blog/2025/cr0-image-4.png" alt="勾选 Debugging Tools For Windows， 然后点 Change" tabindex="0" loading="lazy"><figcaption>勾选 Debugging Tools For Windows， 然后点 Change</figcaption></figure>
<h3>Git &amp; Depot Tools</h3>
<p>在等待上面步骤完成的过程中，我们还可以安装并配置 git:</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>$ git config --global user.name "My Name"</span></span>
<span class="line"><span>$ git config --global user.email "my-name@chromium.org"</span></span>
<span class="line"><span>$ git config --global core.autocrlf false</span></span>
<span class="line"><span>$ git config --global core.filemode false</span></span>
<span class="line"><span>$ git config --global core.preloadindex true</span></span>
<span class="line"><span>$ git config --global core.fscache true</span></span>
<span class="line"><span>$ git config --global branch.autosetuprebase always</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>然后在一个至少有 90GB 空间的分区上新建一个文件夹并进入，克隆 depot_tools 仓库：</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>$ mkdir chromium &#x26;&#x26; cd chromium</span></span>
<span class="line"><span>$ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p>完成后，使用喜欢的编辑器写一个环境设置脚本：</p>
<div class="code-block-with-title">
  <div class="code-block-title-bar" data-title="env.bat">
    <span>env.bat</span>
  </div>
  <div class="language-cmd line-numbers-mode" data-highlighter="shiki" data-ext="cmd" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cmd"><span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">pushd %~dp0</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">set </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">PATH</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">=%cd%\</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">depot_tools</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;%PATH%</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">set </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">DEPOT_TOOLS_WIN_TOOLCHAIN</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span></span>
<span class="line"></span>
<span class="line highlighted"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">call </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"D:\VisualStudio\IDE\Common7\Tools\VsDevCmd.bat"</span></span>
<span class="line highlighted"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">set </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">vs2022_install</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">=</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">D</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:\</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">VisualStudio</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">\</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">IDE</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">cmd</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> /</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">k</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>
</div><div class="hint-container important">
<p class="hint-container-title">重要</p>
<p>为了不污染环境变量，我们使用脚本定义这些环境变量，其仅在当前命令提示符及其子进程中生效。</p>
<p><strong>这也要求后面我们的所有操作都在这样的命令提示符上运行。</strong></p>
</div>
<div class="hint-container info">
<p class="hint-container-title">相关信息</p>
<p>注意高亮的行，这是非默认 VS 组件安装路径的解法，前一个是调用了 Developer Command Prompt 来设置正确的环境变量，后者是手动指定了 VS 的安装目录，与 VS Installer 中的设置对应：</p>
<figure><img src="https://imgcdn0.octz.net/blog/2025/cr0-image-5.png" alt="VS-安装位置" tabindex="0" loading="lazy"><figcaption>VS-安装位置</figcaption></figure>
<p>读者可参照修改。<strong>如果你按照默认的设置安装 VS，应该不太需要这两行。</strong></p>
</div>
<p>此后，启动这个 <code>env.bat</code>, 运行</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>$ gclient</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>，这会正确安装 python 和其他工具 在 depot_tools 内。</p>
<h2>克隆源码</h2>
<p>就在刚刚启动的 <code>env.bat</code> 环境中，执行</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>$ fetch chromium</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>这将一次性下载 chromium 主仓库，以及 200+ 个子仓库和配套工具（runhooks）。</p>
<p>好消息是，当主仓库拉取完成后，我们将可以中断这个过程，并通过</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>$ gclient sync</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>恢复。</p>
<div class="hint-container tip">
<p class="hint-container-title">提示</p>
<p>如果你中断后再恢复出现了 git conflict， 不要惊慌，进入对应的子仓库中执行</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>$ git reset --hard HEAD</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>此后重试。</p>
</div>
<p>当你成功完成了源码克隆，将得到一个 src 文件夹包含了所有的源码。</p>
<h2>编译</h2>
<p>Chromium 使用 GN 系统构建。 GN，即 <code>Generate Ninja</code>，是一个用于将 GN DSL 转换成 Ninja 构建配置文件的系统，支持灵活的模板配置和依赖管理。</p>
<p>进入 <code>src</code> 目录，执行：</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>$ gn gen --ide=vs2022 --filters=//chrome --no-deps out\Default --args="is_component_build = true is_debug = true"</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>这将在 <code>out\Default</code> 生成构建配置。需要注意的是，由于 Chromium 的构建配置假定输出目录是 <code>out\&lt;Name&gt;</code>，实际上使用了很多 <code>..\..\</code> 这样的相对路径来访问到源码，所以务必保证目录结构如预期，否则编译失败。</p>
<div class="hint-container tip">
<p class="hint-container-title">在其他磁盘上存储构建产物</p>
<p>针对我这样的磁盘空间不足的用户打造，或者 CI 环境，我们可以将 <code>out</code> 目录重定向到其他磁盘。</p>
<p><strong>这里的重定向不能够使用软链接/Junction，其在解析上级目录的时候会遇到问题。</strong></p>
<p>解法是使用 NTFS 挂载点，如果有条件，可以在磁盘上划分一个足够大的分区并挂载上，或者像我一样使用 VHD。</p>
<p>PS: 使用 VHD 还可以后面利用分层特性整点活？</p>
</div>
<p>此后就可以进行编译了。运行：</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>ninja -C out\Default chrome -j &#x3C;n></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>其中 <code>&lt;n&gt;</code> 为你期望的并行进程数。综合你的物理线程数和内存大小考量即可，我选用 <code>12</code>。</p>
<div class="hint-container tip">
<p class="hint-container-title">加快编译</p>
<p>在编译大型项目的时候，Windows Defender 的实时扫描会严重影响速度。建议关闭/加白相应文件夹处理。</p>
</div>
<p>剩下一个字，<strong>等</strong>！</p>
<h2>运行测试</h2>
<p>在经历了漫长的编译后，我们将会得到编译产物。这时候就可以在 <code>out\Default</code> 里面找到 <code>chrome.exe</code>，蓝色图标的。打开它，看一下 <code>about://version</code>：</p>
<figure><img src="https://imgcdn0.octz.net/blog/2025/cr0-image-6.png" alt="庆祝吧！" tabindex="0" loading="lazy"><figcaption>庆祝吧！</figcaption></figure>
<h2>Clangd 配置</h2>
<p>为了后面能好好编写代码，我们还需要配置好 clangd，并从构建中提取构建命令。</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>$ python3 tools\clang\scripts\generate_compdb.py -p out\Default -o compile_commands.json chrome</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>此后打开一个源文件，等待 clangd 构建索引（可能需要几天时间）。</p>
<h2>调试配置</h2>
<p>如果你完全按照上面进行了编译，应该可以在 <code>out\Default</code> 中找到一个 1 KB 大小的 <code>all.sln</code> 文件，双击打开它。</p>
<p>然后按图中说明操作，转到项目-&gt;属性,配置属性-&gt;配置，取消勾选“生成”：</p>
<figure><img src="https://imgcdn0.octz.net/blog/2025/cr0-image-8.png" alt="取消勾选“生成”" tabindex="0" loading="lazy"><figcaption>取消勾选“生成”</figcaption></figure>
<div class="hint-container tip">
<p class="hint-container-title">强推扩展 Microsoft Child Process Debugging Power Tool 2022</p>
<figure><img src="https://imgcdn0.octz.net/blog/2025/cr0-image-7.png" alt="扩展管理器搜索到" tabindex="0" loading="lazy"><figcaption>扩展管理器搜索到</figcaption></figure>
<figure><img src="https://imgcdn0.octz.net/blog/2025/cr0-image-9.png" alt="配置" tabindex="0" loading="lazy"><figcaption>配置</figcaption></figure>
</div>
<p>随后点击“调试”按钮，尝试下断点，应该好了。</p>
<figure><img src="https://imgcdn0.octz.net/blog/2025/cr0-image-10.png" alt="准备起飞！" tabindex="0" loading="lazy"><figcaption>准备起飞！</figcaption></figure>
]]></content:encoded>
      <enclosure url="https://imgcdn0.octz.net/blog/2025/cr0-image.png" type="image/png"/>
    </item>
    <item>
      <title>Pwn.College KernelSecurity WP</title>
      <link>https://octz.net/blog/CTF/PwnCollegeKernelSecurityWP.html</link>
      <guid>https://octz.net/blog/CTF/PwnCollegeKernelSecurityWP.html</guid>
      <source url="https://octz.net/rss.xml">Pwn.College KernelSecurity WP</source>
      <description>提示 以下为 PDF 渲染预览版本，没得复制（打印生成的PDF是这样的qwq） 原件戳这里</description>
      <category>CTF</category>
      <pubDate>Sun, 27 Oct 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<div class="hint-container tip">
<p class="hint-container-title">提示</p>
<p>以下为 PDF 渲染预览版本，没得复制（打印生成的PDF是这样的qwq） <a href="/files/pwncollege/knlsec.pdf">原件戳这里</a></p>
</div>
<div id="pdfrender"></div>
]]></content:encoded>
    </item>
    <item>
      <title>Pwn.College MemoryError WP</title>
      <link>https://octz.net/blog/CTF/PwnCollegeMemoryErrorWP.html</link>
      <guid>https://octz.net/blog/CTF/PwnCollegeMemoryErrorWP.html</guid>
      <source url="https://octz.net/rss.xml">Pwn.College MemoryError WP</source>
      <description>提示 以下为 PDF 渲染预览版本，没得复制（打印生成的PDF是这样的qwq） 原件戳这里</description>
      <category>CTF</category>
      <pubDate>Wed, 07 Aug 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<div class="hint-container tip">
<p class="hint-container-title">提示</p>
<p>以下为 PDF 渲染预览版本，没得复制（打印生成的PDF是这样的qwq） <a href="/files/pwncollege/memerr.pdf">原件戳这里</a></p>
</div>
<div id="pdfrender"></div>
]]></content:encoded>
    </item>
    <item>
      <title>Pwn.College ProgramExploitation WP</title>
      <link>https://octz.net/blog/CTF/PwnCollegeProgExpWP.html</link>
      <guid>https://octz.net/blog/CTF/PwnCollegeProgExpWP.html</guid>
      <source url="https://octz.net/rss.xml">Pwn.College ProgramExploitation WP</source>
      <description>提示 以下为 PDF 渲染预览版本，没得复制（打印生成的PDF是这样的qwq） 原件戳这里</description>
      <category>CTF</category>
      <pubDate>Wed, 14 Aug 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<div class="hint-container tip">
<p class="hint-container-title">提示</p>
<p>以下为 PDF 渲染预览版本，没得复制（打印生成的PDF是这样的qwq） <a href="/files/pwncollege/progexp.pdf">原件戳这里</a></p>
</div>
<div id="pdfrender"></div>
]]></content:encoded>
    </item>
    <item>
      <title>Pwn.College Race Conditions WP</title>
      <link>https://octz.net/blog/CTF/PwnCollegeRaceCondWP.html</link>
      <guid>https://octz.net/blog/CTF/PwnCollegeRaceCondWP.html</guid>
      <source url="https://octz.net/rss.xml">Pwn.College Race Conditions WP</source>
      <description>提示 以下为 PDF 渲染预览版本，没得复制（打印生成的PDF是这样的qwq） 原件戳这里</description>
      <category>CTF</category>
      <pubDate>Fri, 27 Sep 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<div class="hint-container tip">
<p class="hint-container-title">提示</p>
<p>以下为 PDF 渲染预览版本，没得复制（打印生成的PDF是这样的qwq） <a href="/files/pwncollege/racecond.pdf">原件戳这里</a></p>
</div>
<div id="pdfrender"></div>
]]></content:encoded>
    </item>
    <item>
      <title>Pwn.College Sandboxing WP</title>
      <link>https://octz.net/blog/CTF/PwnCollegeSandboxingWP.html</link>
      <guid>https://octz.net/blog/CTF/PwnCollegeSandboxingWP.html</guid>
      <source url="https://octz.net/rss.xml">Pwn.College Sandboxing WP</source>
      <description>提示 以下为 PDF 渲染预览版本，没得复制（打印生成的PDF是这样的qwq） 原件戳这里</description>
      <category>CTF</category>
      <pubDate>Fri, 13 Sep 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<div class="hint-container tip">
<p class="hint-container-title">提示</p>
<p>以下为 PDF 渲染预览版本，没得复制（打印生成的PDF是这样的qwq） <a href="/files/pwncollege/sandboxing.pdf">原件戳这里</a></p>
</div>
<div id="pdfrender"></div>
]]></content:encoded>
    </item>
    <item>
      <title>Pwn.College Shellcode WP</title>
      <link>https://octz.net/blog/CTF/PwnCollegeShellcodeWP.html</link>
      <guid>https://octz.net/blog/CTF/PwnCollegeShellcodeWP.html</guid>
      <source url="https://octz.net/rss.xml">Pwn.College Shellcode WP</source>
      <description>提示 以下为 PDF 渲染预览版本，没得复制（打印生成的PDF是这样的qwq） 原件戳这里</description>
      <category>CTF</category>
      <pubDate>Wed, 07 Aug 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<div class="hint-container tip">
<p class="hint-container-title">提示</p>
<p>以下为 PDF 渲染预览版本，没得复制（打印生成的PDF是这样的qwq） <a href="/files/pwncollege/shellcode.pdf">原件戳这里</a></p>
</div>
<div id="pdfrender"></div>
]]></content:encoded>
    </item>
    <item>
      <title>Arduino 单片机开发之入坑</title>
      <link>https://octz.net/blog/Embed/Arduino_0.html</link>
      <guid>https://octz.net/blog/Embed/Arduino_0.html</guid>
      <source url="https://octz.net/rss.xml">Arduino 单片机开发之入坑</source>
      <description>简介与开发环境 首先，Arduino是一种单片机开发板，其MCU大部分基于AVR架构，采用串口下载，板载USB转串口芯片，下载时可自动复位，无需手动重置；开发板大多支持7 ~ 12 V DC 供电以及5V USB供电。 要开发它，首先要安装Arduino的IDE (或者安装atmel公司提供的开发环境)，接着安装开发板USB转串口芯片的驱动程序,然后在...</description>
      <category>Embedded</category>
      <pubDate>Thu, 13 Feb 2020 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>简介与开发环境</h2>
<p>首先，Arduino是一种单片机开发板，其MCU大部分基于AVR架构，采用串口下载，板载USB转串口芯片，下载时可自动复位，无需手动重置；开发板大多支持7 ~ 12 V DC 供电以及5V USB供电。</p>
<p>要开发它，首先要安装Arduino的IDE<!--More--> (或者安装atmel公司提供的开发环境)，接着安装开发板USB转串口芯片的驱动程序,然后在Arduino IDE中的工具-开发板选择你的开发板型号(我这里用的是基于Atmega328P的Uno)，就可以愉快地coding了！</p>
<h2>程序代码结构</h2>
<p>Arduino是基于精简的C++的，所以他支持对象，但是对于STL的支持并不完整！</p>
<p>Arduino的工程文件后缀名为.ino，相当于.cpp（实际上，在编译时预处理器会把工程目录下的所有文件复制到临时文件夹并改名.ino为.cpp），工程目录文件夹名需与主ino文件名相同。</p>
<p>当你新建一个工程时，默认有两个函数，如下:</p>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> setup</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(){</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    </span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> loop</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(){</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    </span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这两个函数没有返回值，也没有入口参数，且不可更改名称。为啥？因为Arduino是在核心文件里包含工程文件来实现编译的，核心文件里就是这样定义这两个函数的，要改了的话会报错（改核心文件另说）。其中setup函数只在板子上电或重置时执行一次，loop则在setup后无限循环。</p>
<h2>第一个闪灯程序</h2>
<p>在文件-示例-Basics里找到Blink程序，如下：</p>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">//LED_BUILTIN 是板载LED的引脚号，是自动定义的，不用管直接用</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> setup</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">() {</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">  // 初始化LED引脚为OUTPUT</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">  //Arduino的引脚有3种模式，分别为</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">  //  OUTPUT  输出模式，向外输出电流，单个引脚最大40mA</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">  //  INPUT   输入模式，引脚为高阻抗态，对外部电平变化敏感</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">  //  INPUT_PULLUP  与INPUT作用相同，只是多开启了内部的10k上拉电阻</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">  pinMode</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(LED_BUILTIN, OUTPUT);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> loop</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">() {</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">  digitalWrite</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(LED_BUILTIN, HIGH);</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">   // 将LED引脚电平配置为高(HIGH=1)</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">  delay</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                       // 等待1000毫秒</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">  digitalWrite</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(LED_BUILTIN, LOW);</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">    // LED引脚电平配置为低(LOW=0)</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">  delay</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1000</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">                       // 等待1000毫秒</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>插上你的开发板的USB线，等待电脑识别后在工具-端口里选择对应串口，按Ctrl+U进行编译并下载，下载完成后，你就可以看到开发板上的LED亮一秒灭一秒地闪烁了。</p>
]]></content:encoded>
    </item>
    <item>
      <title>C51 单片机开发之开发环境搭建</title>
      <link>https://octz.net/blog/Embed/C51_0.html</link>
      <guid>https://octz.net/blog/Embed/C51_0.html</guid>
      <source url="https://octz.net/rss.xml">C51 单片机开发之开发环境搭建</source>
      <description>C51单片机简介 C51单片机，很老了，其基于 Intel 的 8051 内核，采用 C 语言开发。 下面说一下我将要使用的单片机基本信息: 开发环境搭建--软硬件准备 我开发用的硬件: 注意 我使用的STC8F1k08内置RC振荡器，无需外部晶振！其他51单片机请自行搜索并搭建最小系统电路！ 开发用软件: 下载烧写工具 安装好之后，就已完成环境的搭建...</description>
      <category>Embedded</category>
      <pubDate>Fri, 14 Feb 2020 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>C51单片机简介</h2>
<p>C51单片机，很老了，其基于 Intel 的 8051 内核，采用 C 语言开发。</p>
<p>下面说一下我将要使用的单片机基本信息:</p>
<!--More-->
<table>
<thead>
<tr>
<th style="text-align:center">项目</th>
<th style="text-align:center">属性</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">单片机名称</td>
<td style="text-align:center">STC8F1K08(S2)</td>
</tr>
<tr>
<td style="text-align:center">封装</td>
<td style="text-align:center">SOP-8 或 SOP-16</td>
</tr>
<tr>
<td style="text-align:center">内存</td>
<td style="text-align:center">128Byte data,128Byte idata,1024Byte xdata</td>
</tr>
<tr>
<td style="text-align:center">代码容量</td>
<td style="text-align:center">8KB</td>
</tr>
<tr>
<td style="text-align:center">EEPROM</td>
<td style="text-align:center">Flash模拟,3KB</td>
</tr>
<tr>
<td style="text-align:center">串口,IIC,SPI</td>
<td style="text-align:center">x1,x1,x1</td>
</tr>
<tr>
<td style="text-align:center">备注</td>
<td style="text-align:center">SOP-8封装版本的SPI少两根线，无法使用</td>
</tr>
</tbody>
</table>
<h2>开发环境搭建--软硬件准备</h2>
<p>我开发用的硬件:</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>STC8F1k08 SOP16封装或SOP8封装的芯片(使用串口下载程序)</span></span>
<span class="line"><span>Arduino Uno (其上有一个USB转串口的芯片CH340G可以利用，节省成本)(待测试)</span></span>
<span class="line"><span>PC (Windows 7 64位)</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="hint-container warning">
<p class="hint-container-title">注意</p>
<p>我使用的STC8F1k08内置RC振荡器，无需外部晶振！其他51单片机请自行搜索并搭建最小系统电路！</p>
</div>
<p>开发用软件:</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>Keil uVision4</span></span>
<span class="line"><span>STC-ISP (烧写工具)</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p><a href="http://www.stcmcu.com" title="下载地址" target="_blank" rel="noopener noreferrer">下载烧写工具</a></p>
<p>安装好之后，就已完成环境的搭建，可以写代码了。</p>
]]></content:encoded>
    </item>
    <item>
      <title>NOLOAD 在自定义段的应用 - CH573 HardFault排查日记</title>
      <link>https://octz.net/blog/Embed/custom_ld.html</link>
      <guid>https://octz.net/blog/Embed/custom_ld.html</guid>
      <source url="https://octz.net/rss.xml">NOLOAD 在自定义段的应用 - CH573 HardFault排查日记</source>
      <description>介绍在 CH571/CH573 嵌入式开发中，利用 NOLOAD 属性自定义链接脚本段以避免 HardFault 的排查过程。</description>
      <category>Embedded</category>
      <pubDate>Thu, 24 Aug 2023 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>前言</h2>
<p>想做一个低功耗的复合宏键鼠，看上了CH571这款片子，先去弄了个板子开发着。</p>
<p>根据数据手册，Data区域分为16K+2K，低电压时可以选择断电。又RV32的栈是向下增长的，原始链接脚本直接将栈底放在RAM最后部，无法满足需求。</p>
<h2>开始改造</h2>
<h3>先看一眼原始链接脚本</h3>
<div class="language-ld line-numbers-mode" data-highlighter="shiki" data-ext="ld" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-ld"><span class="line"><span></span></span>
<span class="line"><span>ENTRY( _start )</span></span>
<span class="line"><span></span></span>
<span class="line"><span>MEMORY</span></span>
<span class="line"><span>{</span></span>
<span class="line"><span>	FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 448K</span></span>
<span class="line"><span>	RAM (xrw) : ORIGIN = 0x20003800, LENGTH = 18K</span></span>
<span class="line"><span>}</span></span>
<span class="line"><span></span></span>
<span class="line"><span>SECTIONS</span></span>
<span class="line"><span>{</span></span>
<span class="line"><span></span></span>
<span class="line"><span>    /* 省略 */</span></span>
<span class="line"><span></span></span>
<span class="line"><span>	.stack ORIGIN(RAM)+LENGTH(RAM) :</span></span>
<span class="line"><span>	{</span></span>
<span class="line"><span>		. = ALIGN(4);</span></span>
<span class="line"><span>		PROVIDE(_eusrstack = . );</span></span>
<span class="line"><span>	} >RAM  </span></span>
<span class="line"><span></span></span>
<span class="line"><span>}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3>开改</h3>
<p>既然要将指定的数据放到后2K位置，容易想到自定义一个段，这里我叫他(.lram)，将段地址指定一下。</p>
<p>修改后的链接脚本：</p>
<div class="language-ld line-numbers-mode" data-highlighter="shiki" data-ext="ld" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-ld"><span class="line"><span></span></span>
<span class="line"><span>ENTRY( _start )</span></span>
<span class="line"><span></span></span>
<span class="line"><span>__lram_size = 256;</span></span>
<span class="line"><span></span></span>
<span class="line"><span>MEMORY</span></span>
<span class="line"><span>{</span></span>
<span class="line"><span>	FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 448K</span></span>
<span class="line"><span>	RAM (xrw) : ORIGIN = 0x20003800, LENGTH = 18K</span></span>
<span class="line"><span>}</span></span>
<span class="line"><span></span></span>
<span class="line"><span>SECTIONS</span></span>
<span class="line"><span>{</span></span>
<span class="line"><span></span></span>
<span class="line"><span>    /* 省略 */</span></span>
<span class="line"><span></span></span>
<span class="line"><span>	.stack ORIGIN(RAM)+LENGTH(RAM) - __lram_size :</span></span>
<span class="line"><span>	{</span></span>
<span class="line"><span>		. = ALIGN(4);</span></span>
<span class="line"><span>		PROVIDE(_eusrstack = . );</span></span>
<span class="line"><span>	} >RAM  </span></span>
<span class="line"><span>	</span></span>
<span class="line"><span>	.lram ORIGIN(RAM)+LENGTH(RAM) - __lram_size  :</span></span>
<span class="line"><span>	{</span></span>
<span class="line"><span>		. = ALIGN(4);</span></span>
<span class="line"><span>		*(.lram);</span></span>
<span class="line"><span>		*(.lram.*);</span></span>
<span class="line"><span>		. = ALIGN(4);</span></span>
<span class="line"><span>	} > RAM </span></span>
<span class="line"><span></span></span>
<span class="line"><span>}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>定义好以后，在源码中定义一个结构体，并按照 GCC 的规范加上 attribute，如下：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">typedef</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> struct</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    uint32_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> passCode;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    uint8_t</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> rsv</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">236</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">];</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">} </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">globalVar_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">*</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">pglobalVar_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // 256 Bytes max</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">__attribute__</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">((</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">section</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">".lram"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)))</span></span>
<span class="line"><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">globalVar_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> globalVar;</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>编译通过后，用WCHISPStudio <strong>3.40</strong> 烧录到板子上，成功获得一个不断重启且指示原因为 RPOR(真上电复位)的工程。</p>
<h2>排查原因</h2>
<h3>东找西找</h3>
<p>起初怀疑是破坏了栈，将栈地址前移4 Bytes，正常了，但是，还是有那么一点不对劲啊</p>
]]></content:encoded>
    </item>
    <item>
      <title>ESP-IDF 及 VSCode 插件在WSL下的安装及配置</title>
      <link>https://octz.net/blog/Embed/ESPIDF-WSL.html</link>
      <guid>https://octz.net/blog/Embed/ESPIDF-WSL.html</guid>
      <source url="https://octz.net/rss.xml">ESP-IDF 及 VSCode 插件在WSL下的安装及配置</source>
      <description>WSL 下安装 ESP-IDF 及 VSCode 扩展以实现快速编译的指南。</description>
      <category>Embedded</category>
      <pubDate>Fri, 22 Jul 2022 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>前言</h2>
<p>众所周知，ESP-IDF 在 Windows 下的安装十分困难，编译速度巨慢。通常情况下，编译一个 HelloWorld 程序也需要5分钟及以上。<br>
实测发现，ESP-IDF 在 Linux (WSL) 下的编译速度极快，一个同样的 HelloWorld 程序仅需 10 秒即可完成编译。</p>
<p>本文主要介绍在 WSL 上安装 ESP-IDF 及其 VSCode 插件的步骤。</p>
<h2>设置 Windows 环境</h2>
<h3>安装必需软件</h3>
<p>Windows 上所需软件有：</p>
<ul>
<li>Visual Studio Code</li>
<li>WSL 2</li>
<li>WSL Ubuntu 发行版 (Microsoft Store)</li>
<li>Python 3.9</li>
</ul>
<div class="hint-container tip">
<p class="hint-container-title">注意</p>
<ul>
<li>WSL 仅在 Windows 10+上可用，低版本 Windows 用户请使用虚拟机！</li>
<li>WSL Ubuntu 版本应为 20.04+，本文中使用 22.04 版。</li>
</ul>
</div>
<h3>设置 WSL</h3>
<p>打开 WSL 窗口，执行下列指令以安装必须软件包：</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-bash"><span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">sudo</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> apt</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> update</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">sudo</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> apt-get</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> install</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> git</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> wget</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> flex</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> bison</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> gperf</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> python3-pip</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> python3-venv</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> python3-setuptools</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> cmake</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> ninja-build</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> ccache</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> libffi-dev</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> libssl-dev</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> dfu-util</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><h3>配置 VSCode</h3>
<ol>
<li>
<p>请手动从 VSCode - 扩展 界面安装 <code>Remote - WSL</code>（扩展ID为 <code>ms-vscode-remote.remote-wsl</code>)；</p>
</li>
<li>
<p>点击 VSCode 左下角的绿色图标，出现类似图中的页面,选择<code>New WSL Window</code>，此时应打开一个新的 VSCode 窗口，左下角绿色图标变为<code>WSL:Ubuntu-22.04</code>;<br>
<img src="https://imgcdn0.octz.net/blog/2023/WSL-1.png" alt="WSL-1" loading="lazy"></p>
</li>
<li>
<p>在新打开的窗口中，找到 扩展 页面，搜索 <code>Espressif IDF</code>，点击如图中所示<code>安装在WSL:Ubuntu-22.04中</code>按钮，等待安装完成；<br>
<img src="https://imgcdn0.octz.net/blog/2023/WSL-2.png" alt="WSL-2" loading="lazy"></p>
</li>
<li>
<p>安装完成后，按图示操作，改好选择下载源，更改安装路径，点 [Install]，然后继续等待；<br>
<img src="https://imgcdn0.octz.net/blog/2023/WSL-3.png" alt="WSL-3" loading="lazy"></p>
</li>
</ol>
<h3>给 ESP-IDF 打补丁</h3>
<p>实测发现，进行到这里，已经可以超快速编译，但是仍不能烧录程序。按照官方文档，需要安装 usbipd 映射串口，然后会遇到权限问题。</p>
<p>这里我们利用 IDF 的一个神奇特性（Bug），即烧录的时候调用的是本地的 PowerShell.exe，顺理成章地，调用到的 Python 也是本地的。<br>
因此，我们只需在本地安装相应依赖，就可完美解决问题。下列步骤:</p>
<ol>
<li>从 WSL Ubuntu 中复制相应文件或者<a href="/files/esp-idf-wsl-patch.zip">下载</a></li>
</ol>
<ul>
<li>${IDF_PATH}/requirements.txt</li>
<li>${IDF_PATH}/tools/kconfig_new/esp-windows-curses</li>
</ul>
<div class="hint-container tip">
<p class="hint-container-title">提示</p>
<p>请将复制出来的 <code>requirements.txt</code> 及 <code>esp-windows-curses</code> 文件夹置于同一个文件夹下。</p>
</div>
<p>修改 <code>requirements.txt</code> ,将下列行（通常在末尾）</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>file://${IDF_PATH}/tools/kconfig_new/esp-windows-curses; sys_platform == 'win32'</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>改为</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>./esp-windows-curses; sys_platform == 'win32'</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>然后打开 Windows 终端（你喜欢就好），导航至保存的文件目录下，执行</p>
<div class="language-powershell line-numbers-mode" data-highlighter="shiki" data-ext="powershell" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-powershell"><span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">pip install </span><span style="--shiki-light:#383A42;--shiki-dark:#56B6C2">-</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">r requirements.txt</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>静待片刻，即可安装完成。（若不成功请尝试换源）</p>
<h2>测试 ESP-IDF 功能</h2>
<p>在连接到 WSL 的 VSCode 窗口内打开一个文件夹，<br>
按下 <code>Ctrl + E</code>，紧接着按下<code>C</code>，选择<code>Use current directory</code>，即可用模板创建一个 IDF 工程。<br>
接着，连接开发板，在下边栏 [/dev/ttyUSB1] 处选择串口；再进行编译、烧录；(点击🔥图标一步到位)</p>
<p>片刻过后，你将可以从串口监视器看到 Log！</p>
<h2>结束啦</h2>
<p>现在，您可以享受 10s 飞速编译和烧录啦！</p>
]]></content:encoded>
      <enclosure url="https://imgcdn0.octz.net/blog/2023/WSL-1.png" type="image/png"/>
    </item>
    <item>
      <title>ESP8266（ESP32）开发之入坑</title>
      <link>https://octz.net/blog/Embed/ESP_0.html</link>
      <guid>https://octz.net/blog/Embed/ESP_0.html</guid>
      <source url="https://octz.net/rss.xml">ESP8266（ESP32）开发之入坑</source>
      <description>简介与开发环境 首先，ESP8266/ESP32 是一款WiFi芯片，后者还带有蓝牙功能。有关的更多信息，请到官网查看。 开发它的方式： 通过安装 ESP8266 /ESP32 for Arduino Core从而在Arduino IDE 里进行开发 通过安装 ESP-IDF 开发（难度较大） NOTICE 请务必按照官网的操作说明进行安装！ 关于我所...</description>
      <category>Embedded</category>
      <pubDate>Fri, 14 Feb 2020 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h3>简介与开发环境</h3>
<p>首先，ESP8266/ESP32 是一款WiFi芯片，后者还带有蓝牙功能。有关的更多信息，请到<a href="https://www.espressif.com/" target="_blank" rel="noopener noreferrer">官网</a>查看。</p>
<p>开发它的方式：</p>
<ul>
<li>
<p>通过安装 <a href="https://github.com/esp8266/Arduino" target="_blank" rel="noopener noreferrer">ESP8266</a> /<a href="https://github.com/espressif/arduino-esp32%22%22" target="_blank" rel="noopener noreferrer">ESP32</a> for Arduino Core从而在Arduino IDE 里进行开发</p>
</li>
<li>
<p>通过安装 <a href="https://github.com/espressif/esp-idf" target="_blank" rel="noopener noreferrer">ESP-IDF</a> 开发（难度较大）</p>
</li>
</ul>
<!--More-->
<div class="hint-container tip">
<p class="hint-container-title">NOTICE</p>
<p>请务必按照官网的操作说明进行安装！</p>
</div>
<h3>关于我所使用的开发板及环境</h3>
<p>我使用 Wemos D1 作为ESP8266的开发板，其上的芯片为 ESP8266-12 ，有9个IO口。<br>
我使用 ESP32 Dev Kit 作为ESP32的开发板，其上为 ESP32 Dev Module ，无 PSRAM。<br>
开发方式选用 Arduino IDE 。</p>
]]></content:encoded>
    </item>
    <item>
      <title>基于 ESP8266 的微型复合 PC 控制器设计</title>
      <link>https://octz.net/blog/Embed/LittleCTL.html</link>
      <guid>https://octz.net/blog/Embed/LittleCTL.html</guid>
      <source url="https://octz.net/rss.xml">基于 ESP8266 的微型复合 PC 控制器设计</source>
      <description>起因 前几天终于是放了假，好好休息一番后，搞了一套 E3 平台玩，想着搞成服务器，又想在闲置时省点电。从开发板库里面找到了吃灰很久的 ESP8266 (WeMos D1 R1)，就它了。 功能要求 能够控制 PC 的电源，包括长短按电源键，短按重置键，并读取电源状态 能够接收 COM 口的 syslog 数据并记录和读出 能够提供串口控制台功能 要求 ...</description>
      <category>Embedded</category>
      <pubDate>Mon, 20 Jan 2025 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>起因</h2>
<p>前几天终于是放了假，好好休息一番后，搞了一套 E3 平台玩，想着搞成服务器，又想在闲置时省点电。从开发板库里面找到了吃灰很久的 ESP8266 (WeMos D1 R1)，就它了。</p>
<h2>功能要求</h2>
<ol>
<li>能够控制 PC 的电源，包括长短按电源键，短按重置键，并读取电源状态</li>
<li>能够接收 COM 口的 syslog 数据并记录和读出</li>
<li>能够提供串口控制台功能</li>
<li><s>读取硬盘灯、蜂鸣器</s></li>
</ol>
<p>要求 1 很容易实现，因为根据 Intel 的前面板 IO 设计文档并结合实际测试，可以知道按键都是 3v3 上拉输入，而电源灯是推挽 5V 输出。而 COM 口按照标准应该是 RS232 电平，但是我的主板(Z270-Dragon)没有引出来，用的是 COM_Debug 口正好是 TTL 电平。串口控制台最容易了，板子上的 CH340 直接接入 USB 就可以得到 ttyUSB 了。</p>
<p>至于4，原本打算搞的，但是硬盘灯是推挽 PWM 输出 5V，蜂鸣器更迷不知道是什么，猜测是开漏，ESP8266 的正常可用的 IO 就 5 个（别看引脚多，实际上上电有特殊状态/要求的很多），搞起来还得刮板加分压电路；加上硬盘灯不是刚需（正常用谁看啊），蜂鸣器要是响了那是低级硬件问题，远程也无法解决，不如不管。</p>
<h2>硬件设计和接线</h2>
<p>首先是供电的选择，我们的 IO 全部在机箱内部，所以直接怼 5VSB 就可以了；当然主板上哪里能找到 5VSB，就看具体的了，实在不行就从 ATX 接口那里引一根线好了！当然也必须把 USB 口的电给断开，不然短接 5V 和 5VSB 是有一点不好的。</p>
<p>然后是电源灯的电平问题，它是 5V 推挽输出，所以需要进行分压降压；在这块板子上，注意到 A0 接口有分压电路，ESP8266 只接收 1V 的电平，板子上原来设计的是 104 和 224 分压 3.3V 到 1V，我们直接改掉，用 202 和 123 分压 5V 即可。</p>
<p>魔改以下：</p>
<figure><img src="https://imgcdn0.octz.net/blog/2025/IMG_20250120_231421.jpg" alt="Board Modification" tabindex="0" loading="lazy"><figcaption>Board Modification</figcaption></figure>
<p>接下来就可以分配下 IO，</p>
<table>
<thead>
<tr>
<th style="text-align:center">ESP8266</th>
<th style="text-align:center">Func</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">D0 D1 (3 1)</td>
<td style="text-align:center">Serial Console</td>
</tr>
<tr>
<td style="text-align:center">TX1 (2)</td>
<td style="text-align:center">Debug Logger</td>
</tr>
<tr>
<td style="text-align:center">SCK (14)</td>
<td style="text-align:center">To PWR_BTN</td>
</tr>
<tr>
<td style="text-align:center">MISO (12)</td>
<td style="text-align:center">To RST_BTN</td>
</tr>
<tr>
<td style="text-align:center">A0 (17)</td>
<td style="text-align:center">From PWR_LED</td>
</tr>
<tr>
<td style="text-align:center">MOSI SS (13 15)</td>
<td style="text-align:center">To COM_Debug</td>
</tr>
</tbody>
</table>
<p>另外，部分华硕主板的 COM_Debug 定义是这样的：</p>
<figure><img src="https://imgcdn0.octz.net/blog/2025/COM_DEBUG_ASUS.png" alt="COM_DEBUG ASUS" tabindex="0" loading="lazy"><figcaption>COM_DEBUG ASUS</figcaption></figure>
<p>当然经过测试我这块主板就正好是了 :smile</p>
<div class="hint-container warning">
<p class="hint-container-title">警告</p>
<p>通常主板上的标准 COM 口是 RS232 规范的，这意味着它的电平和 TTL 电平不兼容。在该情况下，您还需要一个转换芯片。</p>
</div>
<h2>软件设计</h2>
<h3>交互接口和命令</h3>
<p>选定 23 端口作为串口转发，22 端口作为控制台。</p>
<p>电源控制命令前缀 # ，后缀 $ ，中间 R - 短接 RST，P - 长按 PWR_BTN，S - 短按PWR_BTN。</p>
<p>然后就是 L 列出所有日志文件，大于 0x80 的码作为日志读取 index。</p>
<p>D 开启/关闭 COM 实时转出，M 获取当前状态，V 获取版本信息。</p>
<h3>串口转发</h3>
<p>直接套用 WiFiToSerial 示例的工程，修改一下套个类封装即可。</p>
<p>因为 ESP8266 只有一个可以接收的串口，所以使用 swap 功能切换引脚，当串口端口连接时，切断日志并映射到 USB 串口上，其他时间则映射到 COM 上。</p>
<h3>日志记录</h3>
<p>基于 LittleFS 实现日志文件分块，3M 大小按 64K 分块，最多有 90 多个文件，为单字符命令读取作一点限制。由于 LittleFS 的掉电安全设计，必须定时进行 sync 才可以保证写入可见，我们也正好连同文件大小检测和删除旧文件一起做了。</p>
<h3>WiFi 管理和配置</h3>
<p>利用 WiFiManager 库，自动连 WiFi 和在失败时提供 Config Portal。<br>
另外注册一个断连事件重启 ESP8266 即可。</p>
<h2>后记</h2>
<p>安装的时候发现，进入系统以后长按电源开关的时间要长点才可以强制关机。另外，全金属机箱内的信号太差了，需要更换安装位置，比如前面板缝隙。。。</p>
<p>源码见 <a href="https://github.com/dynamicloader/littlectl" target="_blank" rel="noopener noreferrer">仓库</a>。</p>
]]></content:encoded>
      <enclosure url="https://imgcdn0.octz.net/blog/2025/IMG_20250120_231421.jpg" type="image/jpeg"/>
    </item>
    <item>
      <title>基于 CH551/CH552G 的模拟键鼠设计</title>
      <link>https://octz.net/blog/Embed/SoftKeyMouse.html</link>
      <guid>https://octz.net/blog/Embed/SoftKeyMouse.html</guid>
      <source url="https://octz.net/rss.xml">基于 CH551/CH552G 的模拟键鼠设计</source>
      <description>基于 CH552G 单片机和 CH340K USB 转串口芯片的 USB 键盘鼠标模拟器的设计与实现。</description>
      <category>Embedded</category>
      <pubDate>Sun, 23 Oct 2022 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>前言</h2>
<p>本月突发奇想，想制作一个模拟键鼠，于是打开了熟悉的 <a href="https://wch.cn" target="_blank" rel="noopener noreferrer">WCH 官网</a> ，然后找到了 CH552G 和 CH340K.<br>
话不多说，开整。（此时我还没有意识到我踏进了一个大坑，因为有 CH9326 这个现成的片子）</p>
<h2>原理图设计 &amp; PCB 设计</h2>
<p>先看原理图：<br>
<img src="https://imgcdn0.octz.net/blog/2023/softKM-1.png" alt="原理图" loading="lazy"></p>
<p>总体思路是用 CH340K 转串口与 CH552 连接，CH552 模拟 HID 设备，并根据串口0收到的命令向被控主机发送 HID 包，完成模拟的操作。<br>
图中，我将串口 RTS 和 DTR 接到了 CH552 的中断引脚上，以便进行流控。SRV05 是防静电的芯片。（为啥冬天了才考虑到这事...）</p>
<p>至于PCB，随手一画，双层小板，送 JLC 打样即可。（然后我就被 MicroUSB 的焊接坑惨了）</p>
<h2>程序编写：暂未焊接成功，有心无力</h2>
]]></content:encoded>
      <enclosure url="https://imgcdn0.octz.net/blog/2023/softKM-1.png" type="image/png"/>
    </item>
    <item>
      <title>网络启动原理与实践</title>
      <link>https://octz.net/blog/Maintaince/PXE.html</link>
      <guid>https://octz.net/blog/Maintaince/PXE.html</guid>
      <source url="https://octz.net/rss.xml">网络启动原理与实践</source>
      <description>前言 最近进行服务器的装维工作，为了节省安装系统的时间，研究了一下网络启动，经过实践成功，记录于此。 前置知识： 计算机网络（到 IP 层即可） x86 引导过程 引入 假设你是一名服务器管理员，每天都在进行服务器的装维工作。这一天，你的老板要求你给新购置的服务器装个系统。 于是，为了完成老板的压榨性任务，你不得不另辟蹊径。经过一番思考，你猛然想起，所...</description>
      <category>Maintaince</category>
      <pubDate>Fri, 19 Jan 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>前言</h2>
<p>最近进行服务器的装维工作，为了节省安装系统的时间，研究了一下网络启动，经过实践成功，记录于此。</p>
<p>前置知识：</p>
<ul>
<li>计算机网络（到 IP 层即可）</li>
<li>x86 引导过程</li>
</ul>
<h2>引入</h2>
<p>假设你是一名服务器管理员，每天都在进行服务器的装维工作。这一天，你的老板要求你给新购置的服务器装个系统。</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>Boss: 小管，给服务器装个 Ubuntu Server。</span></span>
<span class="line"><span>You : 没问题，等我烧个镜像先。</span></span>
<span class="line"><span>Boss: 好的，也不多，就 20 台，一个上午能搞定吧？</span></span>
<span class="line"><span>You : ... (20台？我哪有20个U盘啊啊啊啊，还TM要一上午搞定？？)</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>于是，为了完成老板的压榨性任务，你不得不另辟蹊径。经过一番思考，你猛然想起，所有的服务器都会事先连接到网络（Hardware Setup），而且要安装的系统都是 Ubuntu Server，如果能够通过网络分发安装镜像并启动安装，配合一下云端配置，就能快速解决这个问题了。</p>
<p>之后，你打开了浏览器，发现已经有了成熟的解决方案，而这个方案就是 PXE -- Preboot Execution Environment。</p>
<h2>PXE 与 iPXE</h2>
<p>观察传统 x86 的磁盘引导过程可以发现，引导是由 BIOS 读取活动磁盘的第一扇区(MBR)并载入到内存 0x7c00 处执行，再由 MBR 程序引导真正的启动管理器。不难想到，如果 BIOS 不是载入 MBR，而是从一个固定位置运行一个预置的程序，那只要这个程序能够驱动网卡，并从网络上拿到真正的引导程序，就可以支持网络启动了。这样的程序提供了启动程序的执行环境，我们称之为预启动执行环境，即PXE。</p>
<p>PXE 是由 Intel 开发的。PXE 通常由网卡提供，可以被 BIOS 执行。PXE是基于C/S架构的，原始的 PXE 一般只支持最基本的网络启动功能，如 DHCP 和 TFTP。DHCP 就不用多说，多台服务器的 IP 地址分配一定需要依赖 DHCP，而 DHCP 中可以选择带有自定义的节，这样就可以下发启动配置数据。而 TFTP 是 Trivial File Transfer Protocol 的缩写，即简单文件传输协议。与 FTP 最大的不同是“简单”，走 UDP 69 端口通信，且只有上传下载等基本功能，不能列出文件。这使得它易于实现，代码量也小。</p>
<p>原始的 PXE 支持的功能实在有限，且支持的速度很低，只有 10 Mbps。这对于通常大于 1G 的安装镜像是灾难性的，下载的速度实在太慢，还没有完整性保证。由此，前人也有高招，即 PXE 不直接载入安装镜像，而是载入一个更强大的 PXE，由新的 PXE 支持更高速率的网络、更多协议，再加载镜像启动。这样的二级 PXE ，也有很多，最常用的是 pxelinux 和 iPXE。pxelinux 是 linux 内核启动的附属工程，专用于支持 linux 的网络启动。而 iPXE 则是 GNU GPL 开源的网络启动固件。其官网为：<a href="https://ipxe.org/" target="_blank" rel="noopener noreferrer">ipxe.org</a>。描述如下：</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>iPXE is the leading open source network boot firmware. It provides a full PXE implementation enhanced with additional features such as:</span></span>
<span class="line"><span></span></span>
<span class="line"><span>- boot from a web server via HTTP</span></span>
<span class="line"><span>- boot from an iSCSI SAN</span></span>
<span class="line"><span>- boot from a Fibre Channel SAN via FCoE</span></span>
<span class="line"><span>- boot from an AoE SAN</span></span>
<span class="line"><span>- boot from a wireless network</span></span>
<span class="line"><span>- boot from a wide-area network</span></span>
<span class="line"><span>- boot from an Infiniband network</span></span>
<span class="line"><span>- control the boot process with a script</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>通过 iPXE，我们可以轻松地从 HTTP 服务器获得安装文件，还可以使用 sanboot 功能将 HTTP 服务器上得镜像挂载为一个 SAN 设备支持启动（当然也可以走诸如 iPXE + GRUB4DOS 这样弯曲的路）。</p>
<h2>PXE 的实现</h2>
<p>如上文所述，PXE 的主要依赖是 DHCP 和 TFTP。流程主要如下图所示：</p>
<figure><img src="https://imgcdn0.octz.net/blog/2024/pxe_flow.svg" alt="PXE流程" tabindex="0" loading="lazy"><figcaption>PXE流程</figcaption></figure>
<p>需要说明的是，iPXE 的启动配置文件名不是固定的，而是可以写死在启动文件里（需要重新编译），或者通过 DHCP 下发。这样一来，DHCP 服务器就不能一直返回初始的启动文件路径，而要根据条件选择。这个选择，只需利用 DHCP user class。具体而言，PXE请求DHCP时会使用机器的 user class，而 iPXE 在请求 DHCP 时会使用自定义的 user class，即 &quot;iPXE&quot;。官方推荐的配置 DHCP 服务器时 ISC DHCPd 或者 Microsoft DHCP server，方便起见，我使用了 dnsmasq 在 OpenWRT 软路由上搭建，TFTP 服务器也由dnsmasq 一并提供。参考配置文件如下：</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span></span></span>
<span class="line"><span>dhcp-name-match=set:dhcp_bogus_hostname,localhost</span></span>
<span class="line"><span>dhcp-name-match=set:dhcp_bogus_hostname,wpad</span></span>
<span class="line"><span></span></span>
<span class="line"><span>dhcp-match=set:iPXE,175</span></span>
<span class="line"><span></span></span>
<span class="line"><span>dhcp-vendorclass=set:flag,PXEClient:Arch:00000</span></span>
<span class="line"><span>dhcp-vendorclass=set:flag,PXEClient:Arch:00006</span></span>
<span class="line"><span>dhcp-vendorclass=set:flag,PXEClient:Arch:00007</span></span>
<span class="line"><span>dhcp-vendorclass=set:flag,PXEClient:Arch:00009</span></span>
<span class="line"><span></span></span>
<span class="line"><span>tag-if=set:load,tag:!iPXE,tag:flag</span></span>
<span class="line"><span></span></span>
<span class="line"><span>pxe-prompt="Press F8 or Enter key for PXE menu.", 5</span></span>
<span class="line"><span></span></span>
<span class="line"><span>#BIOS MENU</span></span>
<span class="line"><span>pxe-service=tag:load,X86PC, "BIOS IPXE (UNDI)", legacy/undionly.kpxe</span></span>
<span class="line"><span>pxe-service=tag:load,X86PC, "BIOS IPXE", legacy/ipxe.pxe</span></span>
<span class="line"><span># pxe-service=tag:load,X86PC, "BIOS Microsoft PXE", pxeboot.n12</span></span>
<span class="line"><span># pxe-service=tag:load,X86PC, "Memtest", memtest.bin</span></span>
<span class="line"><span>pxe-service=tag:load,X86PC, "Boot from local", 0</span></span>
<span class="line"><span></span></span>
<span class="line"><span></span></span>
<span class="line"><span>#UEFI MENU</span></span>
<span class="line"><span># pxe-service=tag:load,IA32_EFI, "Microsoft UEFI (IA32_EFI)", bootia32.efi</span></span>
<span class="line"><span># pxe-service=tag:load,X86-64_EFI, "Microsoft UEFI (X86-64_EFI)", bootx64.efi</span></span>
<span class="line"><span># pxe-service=tag:load,BC_EFI, "Microsoft UEFI(BC-EFI)", bootx64.efi</span></span>
<span class="line"><span></span></span>
<span class="line"><span># pxe-service=tag:load,6, "iPXE snponly UEFI32(6)", snponly32.efi</span></span>
<span class="line"><span>pxe-service=tag:load,7, "iPXE snponly UEFI", efi/snponly.efi</span></span>
<span class="line"><span>pxe-service=tag:load,9, "iPXE snponly UEFI", efi/snponly.efi</span></span>
<span class="line"><span></span></span>
<span class="line"><span># pxe-service=tag:load,06,  "iPXE UEFI32(06)", ipxe32.efi</span></span>
<span class="line"><span>pxe-service=tag:load,07,  "iPXE UEFI", efi/ipxe.efi</span></span>
<span class="line"><span>pxe-service=tag:load,09,  "iPXE UEFI", efi/ipxe.efi</span></span>
<span class="line"><span>pxe-service=tag:load,X86-64_EFI, "GRUB4 EFI", grub/BOOTX64.EFI</span></span>
<span class="line"><span># pxe-service=tag:load,X86-64_EFI, "Memtest", memtest.bin</span></span>
<span class="line"><span></span></span>
<span class="line"><span>dhcp-boot=tag:iPXE, boot.ipxe</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这个配置文件支持 BIOS 和 EFI 启动。所需的大部分文件可以从 <a href="https://boot.ipxe.org/" target="_blank" rel="noopener noreferrer">boot.ipxe.org</a> 获取。</p>
<h2>iPXE 启动 Ubuntu Server 镜像</h2>
<h3>启动镜像</h3>
<p>如前所述，经过一番配置，我们已经能够启动到 iPXE 中。接下来就是由 iPXE 启动 Ubuntu Server 镜像了。首先就要下载镜像，然后开启一个 HTTP 服务器提这个镜像，这里不再详细描述。在 iPXE 控制台中，使用</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>sanhook --drive 0x81 ${url}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>加载 url 为一个 SAN 设备 (设备号0x81，即磁盘1，可以为其他值，参考 x86 实模式的 BIOS 磁盘操作)。随后，使用</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>sanboot --no-describe --drive 0x81</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>启动镜像。</p>
<h3>修改启动参数</h3>
<p>到这里，应该可以进入 GRUB2 了。但是在真正启动内核之前，我们还需要修改启动参数，指定 url 供内核获取镜像并挂载。由于这里的 SAN 设备是虚拟的，即使用了 x86 的中断 Hook ，也只能在实模式下起效，ubuntu 的内核没有特殊支持，只能重新从 HTTP 服务器获取一份完整镜像并保存在内存中再挂载。</p>
<p>要做到这一点，只需按e编辑菜单命令，进入编辑器后，找到 linux 开头的一行，在该行末尾 （如有--，在这之前） 添加</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>ip=dhcp url="${url}"</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>此处需将<code>${url}</code>替换为具体值。</p>
<p>修改完成后，按 F10 启动，就可以了。</p>
<h2>使用第三方工具简化流程</h2>
<blockquote>
<p>你已经读到这里了，好厉害~</p>
</blockquote>
<p>相信你已经发现，手动搭建整个服务并不容易，即便是使用 dnsmasq 这样的集成了 DHCP 和 TFTP 的服务端也一样。</p>
<p>人的本性是偷懒，包括网络启动的初衷，也是偷懒。所以，一懒到底，使用第三方的集成工具快速解决问题。这里推荐一个，<a href="https://www.iventoy.com/cn/index.html" target="_blank" rel="noopener noreferrer">iVentoy</a>，可以傻瓜式操作，详细配置什么的看文档就行。</p>
<h2>进一步了解</h2>
<ul>
<li>ProxyDHCP</li>
<li>EFI</li>
<li>SAN</li>
<li>iSCSI</li>
</ul>
]]></content:encoded>
      <enclosure url="https://imgcdn0.octz.net/blog/2024/pxe_flow.svg" type="image/svg+xml"/>
    </item>
    <item>
      <title>树莓派NTP服务器搭建</title>
      <link>https://octz.net/blog/Maintaince/RasPi_NTP_SERVER.html</link>
      <guid>https://octz.net/blog/Maintaince/RasPi_NTP_SERVER.html</guid>
      <source url="https://octz.net/rss.xml">树莓派NTP服务器搭建</source>
      <description>准备 树莓派，已经配置好网络的 Xshell （鼠标键盘也行） 安装NTP服务器 配置NTP服务器(sudo下) 然后照着下面的中文注释改： 保存退出。 然后执行： 看到下面的内容，就配置好了NTP服务器： 配置防火墙(sudo下) 然后你会看到： 好了，现在重启系统(sudo reboot)，就OK了！</description>
      <category>Maintaince</category>
      <pubDate>Sat, 07 Mar 2020 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>准备</h2>
<ul>
<li>树莓派，已经配置好网络的</li>
<li>Xshell （鼠标键盘也行）</li>
</ul>
<!--more-->
<h2>安装NTP服务器</h2>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-bash"><span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">sudo</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -i</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">apt-get</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> install</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> ntp</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">apt-get</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> install</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> ufw</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">  #防火墙配置程序</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2>配置NTP服务器(sudo下)</h2>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-bash"><span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">nano</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> /etc/ntp.conf</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>然后照着下面的中文注释改：</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span> /etc/ntp.conf, configuration for ntpd; see ntp.conf(5) for help</span></span>
<span class="line"><span></span></span>
<span class="line"><span>driftfile /var/lib/ntp/ntp.drift</span></span>
<span class="line"><span></span></span>
<span class="line"><span># Leap seconds definition provided by tzdata</span></span>
<span class="line"><span>leapfile /usr/share/zoneinfo/leap-seconds.list</span></span>
<span class="line"><span></span></span>
<span class="line"><span># Enable this if you want statistics to be logged.</span></span>
<span class="line"><span>#statsdir /var/log/ntpstats/</span></span>
<span class="line"><span></span></span>
<span class="line"><span>statistics loopstats peerstats clockstats</span></span>
<span class="line"><span>filegen loopstats file loopstats type day enable</span></span>
<span class="line"><span>filegen peerstats file peerstats type day enable</span></span>
<span class="line"><span>filegen clockstats file clockstats type day enable</span></span>
<span class="line"><span></span></span>
<span class="line"><span># You do need to talk to an NTP server or two (or three).</span></span>
<span class="line"><span>#server ntp.your-provider.example</span></span>
<span class="line"><span>server ntp.ntsc.ac.cn  #这里写要同步的服务器地址</span></span>
<span class="line"><span></span></span>
<span class="line"><span># pool.ntp.org maps to about 1000 low-stratum NTP servers.  Your server will</span></span>
<span class="line"><span># pick a different set every time it starts up.  Please consider joining the</span></span>
<span class="line"><span># pool: &#x3C;http://www.pool.ntp.org/join.html></span></span>
<span class="line"><span>pool 0.debian.pool.ntp.org iburst</span></span>
<span class="line"><span>pool 1.debian.pool.ntp.org iburst</span></span>
<span class="line"><span>pool 2.debian.pool.ntp.org iburst</span></span>
<span class="line"><span>pool 3.debian.pool.ntp.org iburst</span></span>
<span class="line"><span></span></span>
<span class="line"><span># Access control configuration; see /usr/share/doc/ntp-doc/html/accopt.html for</span></span>
<span class="line"><span># details.  The web page &#x3C;http://support.ntp.org/bin/view/Support/AccessRestrictions></span></span>
<span class="line"><span># might also be helpful.</span></span>
<span class="line"><span>#</span></span>
<span class="line"><span># Note that "restrict" applies to both servers and clients, so a configuration</span></span>
<span class="line"><span># that might be intended to block requests from certain clients could also end</span></span>
<span class="line"><span># up blocking replies from your own upstream servers.</span></span>
<span class="line"><span></span></span>
<span class="line"><span># By default, exchange time with everybody, but don't allow configuration.</span></span>
<span class="line"><span>restrict -4 default kod notrap nomodify nopeer noquery limited</span></span>
<span class="line"><span>restrict -6 default kod notrap nomodify nopeer noquery limited</span></span>
<span class="line"><span></span></span>
<span class="line"><span>restrict 192.168.10.0 mask 255.255.255.0 nomodify </span></span>
<span class="line"><span># 上面的一行是限制访问，格式： </span></span>
<span class="line"><span># restrict &#x3C;IP地址，请填写本网地址，并把最后一个byte改成0> mask &#x3C;子网掩码> nomodify</span></span>
<span class="line"><span>#</span></span>
<span class="line"><span># nomodify是不允许客户端更改，允许对时</span></span>
<span class="line"><span></span></span>
<span class="line"><span></span></span>
<span class="line"><span># Local users may interrogate the ntp server more closely.</span></span>
<span class="line"><span>restrict 127.0.0.1</span></span>
<span class="line"><span>restrict ::1</span></span>
<span class="line"><span></span></span>
<span class="line"><span># Needed for adding pool entries</span></span>
<span class="line"><span>restrict source notrap nomodify noquery</span></span>
<span class="line"><span></span></span>
<span class="line"><span># Clients from this (example!) subnet have unlimited access, but only if</span></span>
<span class="line"><span># cryptographically authenticated.</span></span>
<span class="line"><span>#restrict 192.168.123.0 mask 255.255.255.0 notrust</span></span>
<span class="line"><span></span></span>
<span class="line"><span>......省略...........</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>保存退出。</p>
<p>然后执行：</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-bash"><span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">sudo</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> service</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> ntp</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> restart</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">ps</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -ef</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> | </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">grep</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> ntp</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p>看到下面的内容，就配置好了NTP服务器：</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>ntp        1066      1  0 18:10 ?        00:00:00 /usr/sbin/ntpd -p /var/run/ntpd.pid -g -u 104:110</span></span>
<span class="line"><span>pi         1069   1034  0 18:10 pts/0    00:00:00 grep --color=auto ntp</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><h2>配置防火墙(sudo下)</h2>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-bash"><span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">ufw</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> enable</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">ufw</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> deny</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">ufw</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> allow</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> 123/udp</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> #开启UDP协议123端口</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">ufw</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> allow</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> 22/tcp</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">  #开启ssh端口</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>然后你会看到：</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>Status: active</span></span>
<span class="line"><span></span></span>
<span class="line"><span>To                         Action      From</span></span>
<span class="line"><span>--</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>]]></content:encoded>
    </item>
    <item>
      <title>WireGuard 原理与使用</title>
      <link>https://octz.net/blog/Maintaince/WireGuard0.html</link>
      <guid>https://octz.net/blog/Maintaince/WireGuard0.html</guid>
      <source url="https://octz.net/rss.xml">WireGuard 原理与使用</source>
      <description>前言 WireGuard 是由 Jason Donenfeld 等人用 C 语言编写的一个开源3层网络隧道工具，被视为下一代 VPN 协议，旨在解决许多困扰 IPSec/IKEv2、OpenVPN 或 L2TP 等其他 VPN 协议的问题。它与 Tinc 和 MeshBird 等现代 VPN 产品有一些相似之处，即加密技术先进、配置简单。从 2020 ...</description>
      <category>Maintaince</category>
      <pubDate>Sun, 25 Feb 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>前言</h2>
<p>WireGuard 是由 Jason Donenfeld 等人用 C 语言编写的一个开源3层网络隧道工具，被视为下一代 VPN 协议，旨在解决许多困扰 IPSec/IKEv2、OpenVPN 或 L2TP 等其他 VPN 协议的问题。它与 Tinc 和 MeshBird 等现代 VPN 产品有一些相似之处，即加密技术先进、配置简单。从 2020 年 1 月开始，它已经并入了 Linux 内核的 5.6 版本，这意味着大多数 Linux 发行版的用户将拥有一个开箱即用的 WireGuard。</p>
<p>前置知识：</p>
<ul>
<li>计算机网络 (IP,UDP)</li>
<li>Linux 网络框架</li>
</ul>
<p><strong>本文仅对其原理和使用作技术上的探讨，不对用途担责。</strong></p>
<h2>WireGuard 的原理</h2>
<p>如前言所述，WireGuard (下称：WG) 完全工作在内核模式上，这是它和其它 VPN 的很大不同之处。这意味着，WG 在效率上要高于运行在用户空间中的其他 VPN 软件（少了来回切换上下文的开销），同时却也限制了其安装，即在无法获得 root / 修改内核的情况下无法正确配置。</p>
<p>所有的 VPN 实现上有两种途径，一是配置系统代理，二是通过虚拟网卡。WG 工作在内核模式下，最方便的就是创建一个虚拟网卡了，在 Linux 中就是一个 TAP 设备。有了虚拟网卡，就可以分配 IP ，然后修正路由表，使得特定的流量通过虚拟网卡发送/接收，从而被 WG 处理。WG 在接收到网卡数据包时，首先进行非对称加密，然后封包通过 UDP 发送。接收到对端 (Peer) 发送的 UDP 数据包则进行解密，然后放到虚拟网卡上。加解密的操作也通过内核模块的 25519 算法完成，开销很低。</p>
<p>不同于 SoftEther VPN 、L2TP 等二层 VPN 协议，WG 工作在三层，即 IP 层，这意味着它无法传输二层包，也就从根本上拒绝了 DHCP。不过，静态 IP 配置也基本够用。而这样做，也进一步减少了 WG 实现上的代码量，路由的工作完全无需在 WG 中实现，完全交给系统，保持了很好的系统兼容性。</p>
<h2>WireGuard 的连接</h2>
<p>上述，WG 是通过 UDP 进行端点间通信的，（并且明确不支持也不会支持 TCP），这就没有连接状态了，唯一能确定对端是否联通的方法就是可选的握手。这意味着，一旦 WG 接口启动，无论对端是否连接上，在系统中都是活动的连接，这一点在配置 DDNS 等功能的时候需要尤为注意。</p>
<p>WG 虽然借鉴了传统的 C/S 架构，但是没有明确端点的角色，默认情况下，由被链接的一方担任 Server，对方则为 Client。默认端口为 51820，作为 Client 时，如果不显式指定，则使用随机端口连接。典型的连接如图：</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>                        UDP</span></span>
<span class="line"><span> Client (Local port) &#x3C;</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div>]]></content:encoded>
    </item>
    <item>
      <title>PCIE 通道分配分析 -- 以 Z270 PCH 为例</title>
      <link>https://octz.net/blog/PC/PCIE_channel.html</link>
      <guid>https://octz.net/blog/PC/PCIE_channel.html</guid>
      <source url="https://octz.net/rss.xml">PCIE 通道分配分析 -- 以 Z270 PCH 为例</source>
      <description>背景 玩上了 E3，很好奇通道分配情况。使用的主板是 Z270-Dragon, CPU 是 E3 1240v6。 基础知识 PCIE 有很多种规格，为了清晰描述，给出以下方便的定义： 物理（插槽）规格：插槽的外形规格。如 PCIE x16, x8, x4, x1, 或者 M.2。 电气规格：连接到插槽的 PCIE 通道 (Lane) 数。一个 X16 ...</description>
      <category>PC</category>
      <pubDate>Mon, 03 Feb 2025 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>背景</h2>
<p>玩上了 E3，很好奇通道分配情况。使用的主板是 Z270-Dragon, CPU 是 E3 1240v6。</p>
<h2>基础知识</h2>
<p>PCIE 有很多种规格，为了清晰描述，给出以下方便的定义：</p>
<ul>
<li>物理（插槽）规格：插槽的外形规格。如 PCIE x16, x8, x4, x1, 或者 M.2。</li>
<li>电气规格：连接到插槽的 PCIE 通道 (Lane) 数。一个 X16 物理规格的插槽可能只有 x8 的通道，常见于带有多个 X16 的主板上，但是没有那么多通道。</li>
</ul>
<p>PCIE 在实现上可以有两种，即 <code>CPU 直连</code> 和 <code>PCH 提供</code>。CPU 直连的通道速度最快，不受其他限制；而 PCH 提供的通道虽然多，总体速度受 DMI Link 的速度限制。（小水管）<br>
PCIE 的通道拆分即指 CPU 直连的 PCIE 通道拆分，涉及到 CPU 相应 CFG 引脚的配置，高端芯片组通过 GPIO 连接到这些引脚来提供动态配置拆分的选项。</p>
<p>PCH 上的 PCIE 信号路径大致如下：</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>  +</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div>]]></content:encoded>
      <enclosure url="https://imgcdn0.octz.net/blog/2025/PCIE-image.png" type="image/png"/>
    </item>
    <item>
      <title>安卓平板远程开发解决方案记录</title>
      <link>https://octz.net/blog/Note/AndroidPad-vscode.html</link>
      <guid>https://octz.net/blog/Note/AndroidPad-vscode.html</guid>
      <source url="https://octz.net/rss.xml">安卓平板远程开发解决方案记录</source>
      <description>WireGuard 安全 VPN, 提供局域网能力 (也可改用 SSH port forward) VS Code serve-web，作为 code server（关掉 token 不然浏览器报错） Termux, 安卓本机命令行，用于运行 socat 伪装本机服务骗过浏览器的 SecureContext Edge，比较舒服的浏览器（主要是支持电脑模...</description>
      <category>Note</category>
      <pubDate>Tue, 19 Nov 2024 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<ol>
<li>WireGuard 安全 VPN, 提供局域网能力 (也可改用 SSH port forward)</li>
<li>VS Code serve-web，作为 code server（关掉 token 不然浏览器报错）</li>
<li>Termux, 安卓本机命令行，用于运行 socat 伪装本机服务骗过浏览器的 SecureContext</li>
<li>Edge，比较舒服的浏览器（主要是支持电脑模式，Chrome 好似）</li>
</ol>
<p>可选：<br>
5. Moonlight 远程桌面（没有 RDP qwq）<br>
6. 其他厂商的 安全键盘，如华子的 Secure IME，用于屏蔽自带输入法的抽象捕获（点名百度输入法捕获 Tab 键导致无法接受建议）</p>
]]></content:encoded>
    </item>
    <item>
      <title>Ubuntu Server 无头启动 + 配置</title>
      <link>https://octz.net/blog/Note/headless-ubuntu.html</link>
      <guid>https://octz.net/blog/Note/headless-ubuntu.html</guid>
      <source url="https://octz.net/rss.xml">Ubuntu Server 无头启动 + 配置</source>
      <description>Z270 平台下 Ubuntu Server 无头启动 + 配置。</description>
      <category>Note</category>
      <pubDate>Mon, 13 Jan 2025 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<p>最近整了一套 Z270 + 1240v6，打算无头启动（连显卡都无的那种！），结果踩坑了，拔了显卡之后网络挂壁，而且CPU风扇慢转。</p>
<p>以为是内核模块挂了导致 kernel panic，排查了好几个小时，终于看到<a href="https://weshallneversurrender.com/ubuntu-server-linux-19-10-%e6%8b%94%e6%8e%89%e6%98%be%e5%8d%a1%e4%b8%8a%e4%b8%8d%e4%ba%86%e7%bd%91%e7%9a%84%e9%97%ae%e9%a2%98/" target="_blank" rel="noopener noreferrer">这篇博文</a>，是 PCIE 变动导致网卡名称改变的问题，遂修改 netplan 为：</p>
<div class="language-yaml line-numbers-mode" data-highlighter="shiki" data-ext="yaml" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-yaml"><span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">network</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">  version</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">2</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">  ethernets</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">    enp1s0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">      dhcp4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">true</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">    enp2s0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">      dhcp4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">true</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">    enp3s0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">      dhcp4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">true</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">    enp4s0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">      dhcp4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">true</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">    enp5s0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">      dhcp4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">true</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>重启解决！后面进去一看，哎，正好是跑到了 enp1s0 的位置！</p>
<p>Edit: 其实可以使用 netplan 的 MAC match 功能进行指定，可以有效解决这些问题。</p>
]]></content:encoded>
    </item>
    <item>
      <title>lvm分层缓存失效恢复</title>
      <link>https://octz.net/blog/Note/lvm-cache-rec.html</link>
      <guid>https://octz.net/blog/Note/lvm-cache-rec.html</guid>
      <source url="https://octz.net/rss.xml">lvm分层缓存失效恢复</source>
      <description>文章描述了如何恢复使用内存盘作为缓存层的lvm设置。</description>
      <category>Note</category>
      <pubDate>Sat, 01 Feb 2025 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<p>Refer： <a href="https://serverfault.com/questions/932247/how-to-recover-a-cached-lvm-with-cache-on-ram-disk" target="_blank" rel="noopener noreferrer">https://serverfault.com/questions/932247/how-to-recover-a-cached-lvm-with-cache-on-ram-disk</a></p>
<ol>
<li>
<p>插入新盘，或者使用内存创建loop设备（不够大就寄了）</p>
</li>
<li>
<p>lvm 后执行以下 去除缓存</p>
</li>
</ol>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>pvs</span></span>
<span class="line"><span>pvcreate --norestore --uuid &#x3C;uuid_of_pv>  /dev/loop0</span></span>
<span class="line"><span>lvchange -a y vg</span></span>
<span class="line"><span>lvconvert --uncache vg/lv</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><ol start="3">
<li>从vg中移除盘，然后删掉为了恢复创建的pv，然后 <code>lvchange -ay lvroot</code></li>
<li>修复文件系统 <code>fsck.ext4 /dev/mapper/vg0-lvroot</code></li>
<li>^D 退出shell，继续启动，应该成功</li>
</ol>
]]></content:encoded>
    </item>
    <item>
      <title>GCC 工具链生成并嵌入资源文件</title>
      <link>https://octz.net/blog/Programming/gccResource.html</link>
      <guid>https://octz.net/blog/Programming/gccResource.html</guid>
      <source url="https://octz.net/rss.xml">GCC 工具链生成并嵌入资源文件</source>
      <description>利用 (MinGW) GCC 工具链生成并嵌入资源文件的指南，适用于跨平台应用程序。</description>
      <category>Programming</category>
      <pubDate>Mon, 12 Sep 2022 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>简介</h2>
<p>众所周知，资源文件对程序的运行具有不可或缺的作用。然而，想要实现跨平台的资源文件利用，我们就不得不摒弃 Win32 资源文件。本文介绍了利用 (MinGW) GCC 工具链生成并嵌入资源文件的一种方法。</p>
<h2>Step 1：利用 ld 生成资源对象文件</h2>
<p>在这一步，我们将利用 链接器(ld) 生成我们所需要的资源对象文件(.o)。</p>
<h3>准备资源文件</h3>
<p>资源文件可以是任意的格式，包括但不限于图片，文本；以下用两个文本文档为例：</p>
<p>文件：a.txt</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>dawdawwdwkjagcbsfgbcfgfjbkajkaadgad</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>文件：b.txt</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>Hello,txt1!</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3>生成资源对象文件</h3>
<p>在包含该资源文件的文件夹路径下打开 CMD，执行指令：</p>
<div class="language-batch line-numbers-mode" data-highlighter="shiki" data-ext="batch" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-batch"><span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">ld -r -b binary a.txt b.txt -o res.o</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><div class="hint-container tip">
<p class="hint-container-title">提示</p>
<p>指令模板为：<code>ld -r -b binary {文件1} {文件2} -o {输出文件路径}</code>；通配符可用。</p>
</div>
<p>这样，我们就得到了资源对象文件<code>res.o</code>。</p>
<h3>检查资源对象文件符号(可选)</h3>
<p>为了确保编译的成功，我们可以先行检查资源文件暴露的符号，得出符号命名规律。</p>
<p>在原先的 CMD 中执行指令</p>
<div class="language-batch line-numbers-mode" data-highlighter="shiki" data-ext="batch" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-batch"><span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">objdump -x res.o</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>我们便得到了一大段输出。找到输出的最后，有类似的表格：</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>SYMBOL TABLE:</span></span>
<span class="line"><span>[  0](sec -1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000023 _binary_a_txt_size</span></span>
<span class="line"><span>[  1](sec -1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x000000000000000b _binary_b_txt_size</span></span>
<span class="line"><span>[  2](sec  1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x000000000000002e _binary_b_txt_end</span></span>
<span class="line"><span>[  3](sec  1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000023 _binary_b_txt_start</span></span>
<span class="line"><span>[  4](sec  1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000023 _binary_a_txt_end</span></span>
<span class="line"><span>[  5](sec  1)(fl 0x00)(ty   0)(scl   2) (nx 0) 0x0000000000000000 _binary_a_txt_start</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这表示，我们的文本文档嵌入了资源对象文件之中，并生成了几个符号。可以总结得出：</p>
<div class="hint-container note">
<p class="hint-container-title">符号的命名规律</p>
<p>_binary_文件名_start<br><br>
_binary_文件名_end<br><br>
_binary_文件名_size</p>
<div style="text-align:right">
<p>注意：文件名中<code>.</code>转为<code>_</code>。</p>
</div>
</div>
<h2>Step 2：编写测试代码</h2>
<h3>符号的引入</h3>
<p>我们的最终目标是将资源文件嵌入可执行文件中并在程序中使用。为了实现这一目标，我们需要在源码文件中引入符号，例如：</p>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">extern</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _binary_a_txt_start[], _binary_a_txt_end[];</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">extern</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _binary_b_txt_start[], _binary_b_txt_end[];</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p>使用<code>extern</code>关键字，并复制符号名称，我们就可以将符号引入源码了。</p>
<div class="hint-container warning">
<p class="hint-container-title">特别注意</p>
<p>符号是一个地址，应定义为 const char[] 类型。</p>
</div>
<h3>符号的使用</h3>
<p>例如：</p>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> main</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(){</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    size_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> a_len </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _binary_a_txt_end </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">-</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _binary_a_txt_start;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    size_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> b_len </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _binary_b_txt_end </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">-</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _binary_b_txt_start;</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"a.txt len=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%u</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">,content= </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%.*s</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, a_len, a_len, _binary_a_txt_start );</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"b.txt len=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%u</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">,content= </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%.*s</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, b_len, b_len, _binary_b_txt_start );</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    return</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>保存为test.cpp，然后编译：</p>
<div class="language-batch line-numbers-mode" data-highlighter="shiki" data-ext="batch" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-batch"><span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">g++ res.o test.cpp -o test.exe</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>这样，我们就得到了可执行文件。执行的结果应如下所示：</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>a.txt len=35,content= dawdawwdwkjagcbsfgbcfgfjbkajkaadgad</span></span>
<span class="line"><span>b.txt len=11,content= Hello,txt1!</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><h2>Step 3：封装起来，便于使用</h2>
<p>这里利用 GCC 的宏定义展开特性，编写示例封装代码：</p>
<p>文件：customResource.hpp</p>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#pragma</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> once</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#include</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> &#x3C;cstdint></span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> RESDEF</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">name</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">extern</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _binary_</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">##name##_start</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[], _binary_</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">##name##_end</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[]</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#define</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> RES</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">name</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) _binary_</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">##name##_start</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, _binary_</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">##name##_end</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">namespace</span><span style="--shiki-light:#383A42;--shiki-dark:#E5C07B"> Utils</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">class</span><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B"> Resource</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">public:</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    Resource</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char*</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> begin</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char*</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> end</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        : </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">_begin</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(begin)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        , </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">_end</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(end)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    ~Resource</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">() { }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char*</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> begin</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">() { </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">return</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> this</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">-></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">_begin</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">; }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char*</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> end</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">() { </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">return</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> this</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">-></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">_end</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">; }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    size_t</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> length</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">() { </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">return</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> this</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">-></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">_end</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> -</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B"> this</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">-></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">_begin</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">; }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> uint8_t*</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> data</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">() { </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">return</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> uint8_t*</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">this</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">-></span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">_begin</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">; }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">private:</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char*</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _begin </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> nullptr</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char*</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> _end </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> nullptr</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">};</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>文件：main.cpp</p>
<div class="language-cpp line-numbers-mode" data-highlighter="shiki" data-ext="cpp" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-cpp"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#include</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> &#x3C;cstdio></span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#include</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "customResource.hpp"</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">using</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> namespace</span><span style="--shiki-light:#383A42;--shiki-dark:#E5C07B"> Utils</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">RESDEF</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(a_txt);</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">RESDEF</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(b_txt);</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Resource</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> a</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">RES</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(a_txt));</span></span>
<span class="line"><span style="--shiki-light:#C18401;--shiki-dark:#E5C07B">Resource</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> b</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">RES</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(b_txt));</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> main</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"a.txt len=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%u</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">,content= </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%.*s</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">a</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">length</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(), </span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">a</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">length</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">() , </span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">a</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">begin</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">());</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"b.txt len=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%u</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">,content= </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%.*s</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">b</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">length</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(), </span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">b</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">length</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">() , </span><span style="--shiki-light:#E45649;--shiki-dark:#E5C07B">b</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">.</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">begin</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">());</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    return</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>编译运行即可。</p>
<div class="hint-container tip">
<p class="hint-container-title">使用提示</p>
<p>先使用<code>RESDEF(文件名)</code>来引入符号，然后使用<code>Utils::Resource(RES(文件名))</code>来实例化对象</p>
</div>
<h2>后记</h2>
<p>本文参考了下列博文：</p>
<p><a href="https://www.jianshu.com/p/94cbc1379806" target="_blank" rel="noopener noreferrer">GCC 中实现添加资源</a></p>
<p><a href="https://blog.csdn.net/qq_72935001/article/details/126492466" target="_blank" rel="noopener noreferrer">详谈#define的替换规则以及宏定义中的#和##详解</a></p>
<p><a href="https://blog.csdn.net/Solmyr_biti/article/details/6601257" target="_blank" rel="noopener noreferrer">ld参数解释</a></p>
<p>并经 Windows 11 + MinGW-w64 11.2.0 Seh 测试通过再行编写而成。在此对原博文博主们表示感谢！</p>
]]></content:encoded>
    </item>
    <item>
      <title>Profile Guided Optimization (PGO) 初探 [GCC 篇]</title>
      <link>https://octz.net/blog/Programming/PGO0.html</link>
      <guid>https://octz.net/blog/Programming/PGO0.html</guid>
      <source url="https://octz.net/rss.xml">Profile Guided Optimization (PGO) 初探 [GCC 篇]</source>
      <description>前言 编译优化是一个很重要的课题。现代编译器不仅实现了 Link-Time Optimization (LTO)，针对跨编译单元优化；也实现了 PGO ，基于实际运行数据来进行优化。 多说无益，直接实验启动！ 测试程序与编译 在这之前，有必要提一下我们的环境和编译参数： 编译器：GCC 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.0...</description>
      <category>Programming</category>
      <pubDate>Sat, 05 Apr 2025 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>前言</h2>
<p>编译优化是一个很重要的课题。现代编译器不仅实现了 Link-Time Optimization (LTO)，针对跨编译单元优化；也实现了 PGO ，基于实际运行数据来进行优化。</p>
<p>多说无益，直接实验启动！</p>
<h2>测试程序与编译</h2>
<p>在这之前，有必要提一下我们的环境和编译参数：</p>
<ul>
<li>编译器：GCC 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2)</li>
<li>系统： WSL1 Ubuntu 20.04</li>
</ul>
<p>为了反编译的简单起见，使用 <code>-Og</code> 进行编译，链接器参数默认。</p>
<p>本次采用的测试程序如下：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#include</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> &#x3C;stdio.h></span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#include</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> &#x3C;stdlib.h></span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> main</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> argc</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char**</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> argv</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> num0 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> atoi</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">argv</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">]);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> num1 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> atoi</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">argv</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">]);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> branch </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> atoi</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">argv</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">]);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (branch </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        for</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">; i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> num0; i</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">++</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (num0 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">%</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) {</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">                printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%i</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,i);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                break</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    } </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">else</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        for</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">; i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> num1; i</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">++</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (num1 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">%</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) {</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">                printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%i</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,i);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                break</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    return</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>即存在两个一样内容的块，由命令行参数控制路径。</p>
<p>采用如下命令编译：</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-bash"><span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">gcc</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -Og</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -fprofile-generate</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> test.c</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -o</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> test_pgogen</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">gcc</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -Og</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> test.c</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -o</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> test</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div></div></div><p>这样得到两个不一样的程序:</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>-rwxrwxrwx 1 wsl wsl  16744 Apr  4 16:58 test</span></span>
<span class="line"><span>-rwxrwxrwx 1 wsl wsl    552 Apr  4 17:15 test.c</span></span>
<span class="line"><span>-rwxrwxrwx 1 wsl wsl  28480 Apr  4 17:15 test_pgogen</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>可以初步看到大小就不一样了。</p>
<h2>发生了什么？</h2>
<p>要搞清楚发生了什么，还是通过不同的阶段编译器的产物来比较一下。考虑编译的几个步骤(括号内为编译参数)：</p>
<ol>
<li>预处理 (-E)</li>
<li>编译 (-S)</li>
<li>汇编 (-c)</li>
<li>链接</li>
</ol>
<p>依次看下就知道了。</p>
<h3>预处理</h3>
<p>首先是预处理，加入 -E，除去头文件，是否启用 profile 生成结果均一致，输出如下：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"># </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">3</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "test.c"</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 2</span></span>
<span class="line"></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"># </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">4</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "test.c"</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> main</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> argc</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char**</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> argv</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> num0 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> atoi</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">argv</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">]);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> num1 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> atoi</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">argv</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">]);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> branch </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> atoi</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">argv</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">]);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (branch </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        for</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">; i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> num0; i</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">++</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (num0 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">%</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) {</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">                printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%i</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,i);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                break</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    } </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">else</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        for</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">; i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> num1; i</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">++</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (num1 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">%</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) {</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">                printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%i</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,i);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                break</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    return</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3>编译</h3>
<p>这里的编译特指生成汇编代码。有兴趣的读者可以看一下下面的汇编代码，比较下不同：</p>
<details class="hint-container details"><summary>详情</summary>

</details>
<p>不难发现里面多了一堆 <code>__gcov</code> 开头的符号引用，是 <code>libgcov</code> 提供的，想必这就是追踪代码了。</p>
<p>后面的汇编和链接，我们就先不考虑了，可以预见是有差异的。</p>
<h3>来反编译吧！</h3>
<p>简单起见，我们还是发挥传统艺能，启动 IDA 看一下：</p>

<p>稍微翻一下就可以知道，这个库的初始化是由 ctors 调用的，而退出函数是由 dtors 调用的。</p>
<p>对比一下，可以看到编译器主要做了两件事：</p>
<ol>
<li>为基本块和间接调用插桩</li>
<li>链接到 libgcov</li>
</ol>
<p>当程序执行时，会根据程序流经过插桩代码，从而在内存中记录下程序的 profile。当程序<strong>正常退出</strong>时，将会触发保存逻辑，将内存中的 profile dump 到磁盘上，供 PGO 使用。</p>
<h2>来看看数据</h2>
<p>我们测试一下，就运行一次，参数为<code>10201 1</code>，会发现多了一个 <code>test.gcda</code> 文件。</p>
<p>头在<a href="https://github.com/gcc-mirror/gcc/blob/master/gcc/gcov-io.h" target="_blank" rel="noopener noreferrer">这里</a>。hexdump 一下：</p>
<div class="language-hex line-numbers-mode" data-highlighter="shiki" data-ext="hex" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-hex"><span class="line"><span>00000000  61 64 63 67 2a 34 39 41  ec e2 15 00 00 00 00 a1  |adcg*49A........|</span></span>
<span class="line"><span>00000010  02 00 00 00 01 00 00 00  63 00 00 00 00 00 00 01  |........c.......|</span></span>
<span class="line"><span>00000020  03 00 00 00 eb 72 70 06  68 a7 65 eb 1d 12 f1 50  |.....rp.h.e....P|</span></span>
<span class="line"><span>00000030  00 00 a1 01 16 00 00 00  01 00 00 00 00 00 00 00  |................|</span></span>
<span class="line"><span>00000040  01 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00  |................|</span></span>
<span class="line"><span>00000050  01 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|</span></span>
<span class="line"><span>00000060  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|</span></span>
<span class="line"><span>00000070  00 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00  |................|</span></span>
<span class="line"><span>00000080  63 00 00 00 00 00 00 00  01 00 00 00 00 00 00 00  |c...............|</span></span>
<span class="line"><span>00000090  00 00 a7 01 0c 00 00 00  00 00 00 00 00 00 00 00  |................|</span></span>
<span class="line"><span>000000a0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|</span></span>
<span class="line"><span>000000b0  64 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |d...............|</span></span>
<span class="line"><span>000000c0  64 00 00 00 00 00 00 00  00 00 af 01 02 00 00 00  |d...............|</span></span>
<span class="line"><span>000000d0  01 00 00 00 00 00 00 00  00 00 00 00              |............|</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>包看不懂的。不过，我们有办法可以看，那就是使用 gcov 工具。不过，这个工具设计用于代码覆盖率的检查，而我们知道，程序流可以表示为一个图。</p>
<p>图的组成里面，有节点和边，我们的 .gcda 文件就只包含了边的数据，这对于有源代码的编译器来说已经足够，但是对于 gcov 生成覆盖率报告却不够。<br>
要注意的是，PGO 和 覆盖率测试不是一回事，但是其中的数据可以共用，不过是 GCC 正好用了同一套。对此，我们只需生成一下节点数据即可：</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-bash"><span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">gcc</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -Og</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> --coverage</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> test.c</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -S</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>这将生成 <code>test.s</code> 和 <code>test.gcno</code> 。gcno 文件一样是二进制格式文件，没有读的必要，我们只要提供给 gcov 解读即可。</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-bash"><span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">gcov</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -c</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> ./test.gcda</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>显示</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>./test.gcda:stamp mismatch with notes file</span></span>
<span class="line"><span>File 'test.c'</span></span>
<span class="line"><span>Lines executed:0.00% of 9</span></span>
<span class="line"><span>Creating 'test.c.gcov'</span></span>
<span class="line"><span></span></span>
<span class="line"><span>File '/usr/include/stdlib.h'</span></span>
<span class="line"><span>Lines executed:0.00% of 1</span></span>
<span class="line"><span>Creating 'stdlib.h.gcov'</span></span>
<span class="line"><span></span></span>
<span class="line"><span>File '/usr/include/x86_64-linux-gnu/bits/stdio2.h'</span></span>
<span class="line"><span>Lines executed:0.00% of 1</span></span>
<span class="line"><span>Creating 'stdio2.h.gcov'</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>这是因为我们后生成的 gcno 有不一样的时戳，参照头文件描述的格式，从 gcda 里面修正过来再执行即可，之后得到 <code>test.c.gcov</code>：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        -</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:    </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:Source:test.c</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        -</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:    </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:Graph:.</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">/</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">test.gcno</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        -</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:    </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:Data:.</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">/</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">test.gcda</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        -</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:    </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:Runs:</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        -</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:    </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:#include </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">stdio.h</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">></span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        -</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:    </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:#include </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">stdlib.h</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">></span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        -</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:    </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">3</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#986801;--shiki-dark:#D19A66">        1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:    </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> main</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> argc</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char**</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> argv</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        -</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:    </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">5</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:{</span></span>
<span class="line"><span style="--shiki-light:#986801;--shiki-dark:#D19A66">        1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:    </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">6</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:    </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> num0 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> atoi</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">argv</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">]);</span></span>
<span class="line"><span style="--shiki-light:#986801;--shiki-dark:#D19A66">        1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:    </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">7</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:    </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> num1 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> atoi</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">argv</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">]);</span></span>
<span class="line"><span style="--shiki-light:#986801;--shiki-dark:#D19A66">        1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:    </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">8</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:    </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> branch </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> atoi</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">argv</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">]);</span></span>
<span class="line"><span style="--shiki-light:#986801;--shiki-dark:#D19A66">        1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:    </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">9</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:    </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (branch </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    #####:   </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">10</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:        </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">for</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">; i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> num0; i</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">++</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    #####:   </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">11</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:            </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (num0 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">%</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        -</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:   </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">12</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:                </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%i</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,i);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        -</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:   </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">13</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:                </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">break</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        -</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:   </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">14</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:            }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        -</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:   </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">15</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:        }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        -</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:   </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">16</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:    } </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">else</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#986801;--shiki-dark:#D19A66">      100</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:   </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">17</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:        </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">for</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">; i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> num1; i</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">++</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) {</span></span>
<span class="line"><span style="--shiki-light:#986801;--shiki-dark:#D19A66">      100</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:   </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">18</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:            </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (num1 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">%</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        -</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:   </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">19</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:                </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%i</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,i);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        -</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:   </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">20</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:                </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">break</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        -</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:   </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">21</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:            }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        -</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:   </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">22</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:        }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        -</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:   </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">23</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:    }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        -</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:   </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">24</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:    </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">return</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        -</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:   </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">25</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>可以看到，随手测试的数据产生了分支情况的不同。分支 &lt; 1 的情况没有执行过，所以其计数值为0，显示为 #####。</p>
<h2>优化一下</h2>
<p>执行下面命令，生成使用 PGO 的程序：</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-bash"><span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">gcc</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -Og</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -fprofile-use</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> test.c</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -o</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> test_use</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>不看汇编了，我们直接启动 IDA:</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> __cdecl </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">main</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> argc</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> **</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">argv</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> **</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">envp</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> v3;</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // r12d</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> v4;</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // ebx</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> v5;</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // ecx</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> v6;</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // esi</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> v7;</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // r8d</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> i;</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // r9d</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">  v3 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> strtol</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">argv</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">], </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">LL</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">10</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">  v4 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> strtol</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">argv</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">], </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">LL</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">10</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line highlighted"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">strtol</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">argv</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">], </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">LL</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">10</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">></span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> )</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // 这里变成大于了</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">  {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    v5 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    v6 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ((_BYTE)v4 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">-</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x26;</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 7</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( (((_BYTE)v4 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">-</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x26;</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 7</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> )</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">      goto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> LABEL_23;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( v4 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> )</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">      return</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( v4 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">%</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> )</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">      v5 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 3</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">      if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( v6 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> )</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        goto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> LABEL_23;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">      if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( v6 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">!=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> )</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">      {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( v6 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">!=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 3</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> )</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">          if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( v6 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">!=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> )</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">          {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( v6 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">!=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 5</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> )</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">              if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( v6 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">!=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 6</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> )</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">              {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(v4 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">%</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 3</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) )</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                  goto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> LABEL_38;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">                v5 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">              }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">              if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(v4 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">%</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> v5) )</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                goto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> LABEL_38;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">              ++</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">v5;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">            }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(v4 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">%</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> v5) )</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">              goto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> LABEL_38;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            ++</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">v5;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">          }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">          if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(v4 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">%</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> v5) )</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            goto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> LABEL_38;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">          ++</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">v5;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(v4 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">%</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> v5) )</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">          goto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> LABEL_38;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        ++</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">v5;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">      }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">      if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( v4 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">%</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> v5 )</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">      {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        ++</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">v5;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">LABEL_23:</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        while</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( v5 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> v4 )</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">          if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(v4 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">%</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> v5) )</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            goto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> LABEL_38;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">          v7 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> v5 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">+</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">          v5 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> v7;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">          if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(v4 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">%</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> v7) )</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            goto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> LABEL_38;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">          v5 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> v7 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">+</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">          if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(v4 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">%</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (v7 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">+</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)) )</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            goto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> LABEL_38;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">          v5 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> v7 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">+</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">          if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(v4 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">%</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (v7 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">+</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)) )</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            goto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> LABEL_38;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">          v5 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> v7 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">+</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 3</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">          if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(v4 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">%</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (v7 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">+</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 3</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)) )</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            goto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> LABEL_38;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">          v5 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> v7 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">+</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">          if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(v4 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">%</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (v7 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">+</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 4</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)) )</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            goto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> LABEL_38;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">          v5 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> v7 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">+</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 5</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">          if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(v4 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">%</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (v7 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">+</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 5</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)) )</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            goto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> LABEL_38;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">          v5 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> v7 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">+</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 6</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">          if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(v4 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">%</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (v7 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">+</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 6</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)) )</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            goto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> LABEL_38;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">          v5 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> v7 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">+</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 7</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">      }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">LABEL_38:</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    __printf_chk</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">LL</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">unk_2004, (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">unsigned</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)v5);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    return</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">  }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  for</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">; i </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> v3; </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">++</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">i )</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">  {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( </span><span style="--shiki-light:#A626A4;--shiki-dark:#56B6C2">!</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(v3 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">%</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> i) )</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">      __printf_chk</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">LL</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x26;</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">unk_2004, (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">unsigned</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)i);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">      return</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">  }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  return</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>可以发现分支那里从 <code>&lt;</code> 变成了 <code>&gt;</code>，因为我们的 profile 表明，有极大概率 branch 是 &gt; 0 的，所以将顺序调过来，以便最大化地利用指令 Cache 提速。<br>
此外，针对执行多的分支，还进行了展开，对于最常见情况可以少做循环。<br>
反观没有执行过的分支，编译器倾向于保持不变。</p>
<h2>结语</h2>
<p>实验到这里就结束了，我们通过反编译的手段，清晰地看到编译器究竟做了什么，生成了什么代码。接下来，我们还将尝试 clang 编译器！</p>
]]></content:encoded>
    </item>
    <item>
      <title>Profile Guided Optimization (PGO) 初探 [Clang 篇]</title>
      <link>https://octz.net/blog/Programming/PGO1.html</link>
      <guid>https://octz.net/blog/Programming/PGO1.html</guid>
      <source url="https://octz.net/rss.xml">Profile Guided Optimization (PGO) 初探 [Clang 篇]</source>
      <description>前言 上一篇我们看了 GCC 的 PGO，是时候来看看 Clang 啦！ 源程序和编译参数都和 GCC 的一样，clang 的 wrapper 做的还是很好的！ 看一下段 话不多说，我们直接 IDA 启动： 段节选** 可以发现，多了几个段，顾名思义即可。相比之下，GCC 就不会多出来段，全部都混在一起非常难搞。 参考 Clang文档 ，看一下每个段的...</description>
      <category>Programming</category>
      <pubDate>Sun, 06 Apr 2025 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>前言</h2>
<p>上一篇我们看了 GCC 的 PGO，是时候来看看 Clang 啦！<br>
源程序和编译参数都和 GCC 的一样，clang 的 wrapper 做的还是很好的！</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>clang version 10.0.0-4ubuntu1 </span></span>
<span class="line"><span>Target: x86_64-pc-linux-gnu</span></span>
<span class="line"><span>Thread model: posix</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2>看一下段</h2>
<p>话不多说，我们直接 IDA 启动：</p>
<p><img src="https://imgcdn0.octz.net/blog/2025/pgo-image.png" alt="段节选" loading="lazy">**</p>
<p>可以发现，多了几个段，顾名思义即可。相比之下，GCC 就不会多出来段，全部都混在一起非常难搞。</p>
<p>参考 <a href="https://llvm.org/docs/InstrProfileFormat.html#profile-metadata" target="_blank" rel="noopener noreferrer">Clang文档</a> ，看一下每个段的数据：</p>
<figure><img src="https://imgcdn0.octz.net/blog/2025/pgo-image-1.png" alt="__llvm_prf_cnts" tabindex="0" loading="lazy"><figcaption>__llvm_prf_cnts</figcaption></figure>
<p><code>__llvm_prf_cnts</code> 这个段就全部都是计数器。</p>
<figure><img src="https://imgcdn0.octz.net/blog/2025/pgo-image-2.png" alt="__llvm_prf_data" tabindex="0" loading="lazy"><figcaption>__llvm_prf_data</figcaption></figure>
<p><code>__llvm_prf_data</code> 这个段主要是一些元数据。多编译一个单元，可以得到更多一份，这样就有规律可循：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">#include</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> &#x3C;stdio.h></span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> mm</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(){</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    puts</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"BBB"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">void</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> m</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(){ </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">puts</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"CC"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><figure><img src="https://imgcdn0.octz.net/blog/2025/pgo-image-6.png" alt="多加一个编译单元后的 __llvm_prf_data " tabindex="0" loading="lazy"><figcaption>多加一个编译单元后的 __llvm_prf_data </figcaption></figure>
<p>可以知道每个函数对应一个块，每个块具有如下结构：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">struct</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2"> meta_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  char</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> header</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">12</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">];</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  uint32_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> some_nums;</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // 和函数行数有关</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  void*</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ptr_to_cnt_start;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  void*</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> func;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  void*</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> reserved;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  uint64_t</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> num_cnts;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">};</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><figure><img src="https://imgcdn0.octz.net/blog/2025/pgo-image-3.png" alt="__llvm_prf_names" tabindex="0" loading="lazy"><figcaption>__llvm_prf_names</figcaption></figure>
<p><code>__llvm_prf_names</code>这个段主要提供了名称信息，在实际的 profdata 中通常是被复制写入的。<br>
根据文档的意思，数据是 zlib 压缩的，我们用 CyberChef 梭一下：</p>
<figure><img src="https://imgcdn0.octz.net/blog/2025/pgo-image-4.png" alt="decompress" tabindex="0" loading="lazy"><figcaption>decompress</figcaption></figure>
<p>可以看到是存储了函数名称。</p>
<p>另外注意到其后有一个 LOAD 段，这只是个 padding，不需要考虑。</p>
<p>然后是 <code>__llvm_prf_vnds</code> 这个段，全部都是 0，长度是 0x6000，即便多编译单元其长度也不变，暂不明确用途。</p>
<h2>反编译</h2>

<p>不难发现 clang 的默认优化都比 GCC 要激进一些。对比起来，Clang 没有生成关于间接调用追踪的代码，函数体内的插桩全部都是简单的加减法；而且插桩倾向于在基本块靠后的位置。插桩后似乎又进行了一次优化才生成的机器码，导致看起来稍显费劲。</p>
<h2>测试和调优</h2>
<p>还是按照 GCC 篇中的办法，使用 <code>10201 1</code> 参数运行一次，得到一个名字很长的文件：</p>
<div class="language- line-numbers-mode" data-highlighter="shiki" data-ext style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-"><span class="line"><span>-rwxrwxrwx 1 wsl wsl 192 Apr  6 11:03 default_15822678452419286522_0.profraw</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>这个是原始文件，要用它来调优，我们还需要做格式转换。</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-bash"><span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">llvm-profdata-10</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> merge</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -o=default.profdata</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> default_15822678452419286522_0.profraw</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>这将从原始数据合并出来一个 <code>default.profdata</code> 供 Clang PGO 优化使用。</p>
<p>随后，</p>
<div class="language-bash line-numbers-mode" data-highlighter="shiki" data-ext="bash" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-bash"><span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">clang</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -Og</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -fprofile-use</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> test.c</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -o</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> test_clang_pguse</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>得到优化后的程序。</p>
<p>很不幸的是，我们并没有观测到任何的变化，反编译的代码仍然是：</p>
<div class="language-c line-numbers-mode" data-highlighter="shiki" data-ext="c" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-c"><span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> __cdecl </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">main</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic"> argc</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> **</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">argv</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> const</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> char</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> **</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#E06C75;--shiki-dark-font-style:italic">envp</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">{</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> v3;</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // ebx</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">  __int64 v4;</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"> // rsi</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">  v3 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> strtol</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">argv</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">], </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">LL</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">10</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">strtol</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">argv</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">[</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">2</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">], </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">LL</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">10</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">&#x3C;=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> )</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">  {</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( v3 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">>=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 3</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> )</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">      v4 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 2</span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">LL</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">      while</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( v3 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">%</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)v4 )</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">      {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        v4 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">unsigned</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)(v4 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">+</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( v3 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (_DWORD)v4 )</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">          return</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">      }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">      goto</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> LABEL_12;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">  }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  else</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( v3 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">>=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 3</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> )</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">  {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    v4 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 2</span><span style="--shiki-light:#986801;--shiki-dark:#E06C75">LL</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    while</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( v3 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">%</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)v4 )</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    {</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">      v4 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">=</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">unsigned</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> int</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)(v4 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">+</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">      if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> ( v3 </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">==</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (_DWORD)v4 )</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        return</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    }</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">LABEL_12:</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">    printf</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">%i</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, v4);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">  }</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">  return</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> 0</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">;</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">}</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>即使我们重新以 -O3 编译也一样无法起效。看来，Clang 的默认优化就已经做的很好？</p>
<p>挺无奈的。。。</p>
]]></content:encoded>
      <enclosure url="https://imgcdn0.octz.net/blog/2025/pgo-image.png" type="image/png"/>
    </item>
    <item>
      <title>Codeblocks wxWidgets 安装与配置</title>
      <link>https://octz.net/blog/Programming/wxWidgetsInit.html</link>
      <guid>https://octz.net/blog/Programming/wxWidgetsInit.html</guid>
      <source url="https://octz.net/rss.xml">Codeblocks wxWidgets 安装与配置</source>
      <description>简介 wxWidgets是一个基于C++的GUI库，支持动、静态链接方式，还可以支持OpenGL！ 本篇记录我的配置过程。 下载与编译 用到的软件（Win7下）： Codeblocks 17.12 （附带GCC 5.10） wxWidgets 2.8.12 安装Codeblocks,并把Codeblocks安装目录下的MinGW\bin添加到path环...</description>
      <category>Programming</category>
      <pubDate>Sun, 01 Mar 2020 15:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>简介</h2>
<p><a href="https://www.wxwidgets.org" target="_blank" rel="noopener noreferrer">wxWidgets</a>是一个基于C++的GUI库，支持动、静态链接方式，还可以支持OpenGL！</p>
<p>本篇记录我的配置过程。</p>
<!--More-->
<h2>下载与编译</h2>
<p>用到的软件（Win7下）：</p>
<ul>
<li>Codeblocks 17.12  （附带GCC 5.10）</li>
<li>wxWidgets 2.8.12</li>
</ul>
<ol>
<li>
<p>安装Codeblocks,并把Codeblocks安装目录下的MinGW\bin添加到path环境变量；</p>
</li>
<li>
<p>到<a href="https://github.com/wxWidgets/wxWidgets/releases/download/v2.8.12/wxWidgets-2.8.12.tar.gz" target="_blank" rel="noopener noreferrer">这里</a>下载v2.8.12版的源码（其他版本请到简介中的链接下载）；</p>
</li>
<li>
<p>下载好之后，把它解压到C:\下，然后新建一个build.bat，命令如下：</p>
</li>
</ol>
<div class="language-batch line-numbers-mode" data-highlighter="shiki" data-ext="batch" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-batch"><span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">@</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">echo</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> off</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">  </span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">　　cd</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> build/msw  </span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">　　title</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> Compile wxWidgets  </span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">　　echo</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> Start Compile ...  </span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">　　echo</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div>]]></content:encoded>
    </item>
    <item>
      <title>JQuery 的使用</title>
      <link>https://octz.net/blog/Web/jquery-1.html</link>
      <guid>https://octz.net/blog/Web/jquery-1.html</guid>
      <source url="https://octz.net/rss.xml">JQuery 的使用</source>
      <description>简介 JQuery是一个开源的前端JS框架，能简化许多操作，比如 ajax 。。。 要使用他，只需要引入一个90KB左右的 JS 文档，网上的cdn多的是，本站也在用。 基本操作 引用 首先，你需要用&amp;lt;script&amp;gt;标签引入他，才能正常使用，像这样： 如果你在引入之前就使用它的语句，会报错，比如下面的例子： 基本语法 JQuery几乎所有的...</description>
      <category>Web</category>
      <pubDate>Sat, 18 Apr 2020 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>简介</h2>
<p>JQuery是一个开源的前端JS框架，能简化许多操作，比如 ajax 。。。<br>
要使用他，只需要引入一个90KB左右的 JS 文档，网上的cdn多的是，本站也在用。</p>
<h2>基本操作</h2>
<!--More-->
<h3>引用</h3>
<p>首先，你需要用<code>&lt;script&gt;</code>标签引入他，才能正常使用，像这样：</p>
<div class="language-html line-numbers-mode" data-highlighter="shiki" data-ext="html" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-html"><span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">script</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> src</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">=</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"https://code.jquery.com/jquery-2.2.4.min.js"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">>&#x3C;/</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">script</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>如果你在引入之前就使用它的语句，会报错，比如下面的例子：</p>
<div class="language-html line-numbers-mode" data-highlighter="shiki" data-ext="html" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-html"><span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">&#x3C;</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">html</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">></span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    &#x3C;</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">body</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">></span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        &#x3C;</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">script</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">></span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">            $</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"html"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">).</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">html</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"&#x3C;h1>Hello,World&#x3C;//h1>"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        &#x3C;/</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">script</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">></span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">        &#x3C;</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">script</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> src</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">=</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"https://code.jquery.com/jquery-2.2.4.min.js"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">>&#x3C;/</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">script</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">></span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    &#x3C;/</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">body</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">></span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">&#x3C;/</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">html</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">></span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3>基本语法</h3>
<p>JQuery几乎所有的函数都是以$开头。</p>
<p>目前用的最多的就是：</p>
<div class="language-js line-numbers-mode" data-highlighter="shiki" data-ext="js" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-js"><span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">$</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"元素选择器"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">).</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">attr</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"属性"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">,</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"值"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">);</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>元素选择器可以是：</p>
<ul>
<li>
<p>元素名称，如 &quot;html&quot; ,&quot;body&quot; ...</p>
</li>
<li>
<p>元素ID,在ID前加一个&quot;#&quot;表示通过ID选择要操作的元素，如 &quot;#main&quot; 表示选择页面中所有ID=&quot;main的元素&quot;；</p>
</li>
<li>
<p>元素的类(Class),在Class之前加一个&quot;.&quot;表示通过类选择元素，如&quot;.span8&quot;表示选择页面中所有Class=&quot;span8&quot;的元素。</p>
</li>
</ul>
<p>元素选择器之后有一个&quot;.&quot;，表示访问他的成员函数（这和VB有点像）</p>
<p>常用的成员函数（方法）有：</p>
<div class="language-js line-numbers-mode" data-highlighter="shiki" data-ext="js" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code class="language-js"><span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">attr</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"属性"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">，</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"值"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)    </span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">//将元素的属性设置为值     </span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">css</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"属性"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">，</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"值"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)     </span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">//将元素的CSS的某个属性改为值 </span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">html</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"值"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)           </span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">//将元素内的html改为值</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>如果上述函数括号内的“值”为空，则返回选定元素当前的属性值。</p>
<div class="hint-container tip">
<p class="hint-container-title">Not finished yet!</p>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>记一次 CDN 源站污染</title>
      <link>https://octz.net/blog/Web/Web0.html</link>
      <guid>https://octz.net/blog/Web/Web0.html</guid>
      <source url="https://octz.net/rss.xml">记一次 CDN 源站污染</source>
      <description>一次 CDN 源站 DNS 污染的分析及解决过程。</description>
      <category>Web</category>
      <pubDate>Thu, 01 Jun 2023 00:00:00 GMT</pubDate>
      <content:encoded><![CDATA[<h2>前言</h2>
<p>由于域名已经备案，故可以使用 CDN 加速访问速度。上了 CDN 之后一切正常，直到某一天，看了一眼 CDN 日志，发现回源错误率猛增。</p>
<h2>分析原因</h2>
<p>首先访问自己的网站，发现页面可以显示，但是样式和按钮全部没了。打开F12一看，woc，报了很多的403，怪不得回源错误率高。</p>
<p>然后就想到源站是不是寄了。但是，源站也是静态站点，不存在被攻击的可能。直接访问源站，也正常。</p>
<p>这时候，已经猜测出来是DNS污染的问题了。也就是说，CDN 服务器拿到的回源地址是被改写过的。为了进一步证实我的猜测，直接与 CDN 提供商沟通。<br>
经过他们测试，使用各地的虚拟机访问源站，发现在某些省份的结果不正确（被重定向了）。</p>
<p>至此，DNS污染实锤。</p>
<h2>解决问题</h2>
<p>既然被污染，那很简单，直接更换源站域名为一个未被污染的域名即可。虽然仍然存在被污染的风险，但是可以启用 DNSSEC，在一定程度上防止 DNS 污染。</p>
]]></content:encoded>
    </item>
  </channel>
</rss>