<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Str Cat</title>
  
  <subtitle>记录技术、学习与生活</subtitle>
  <link href="https://wawoscarqaq.github.io/atom.xml" rel="self"/>
  
  <link href="https://wawoscarqaq.github.io/"/>
  <updated>2026-11-01T16:00:00.000Z</updated>
  <id>https://wawoscarqaq.github.io/</id>
  
  <author>
    <name>WaWOscarQAQ</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Linux 存储栈</title>
    <link href="https://wawoscarqaq.github.io/2026/11/01/Linux_storage_stack/"/>
    <id>https://wawoscarqaq.github.io/2026/11/01/Linux_storage_stack/</id>
    <published>2026-11-01T16:00:00.000Z</published>
    <updated>2026-11-01T16:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<h1 id="Linux-存储栈"><a href="#Linux-存储栈" class="headerlink" title="Linux 存储栈"></a>Linux 存储栈</h1><h2 id="1-Linux-块设备层-IO-请求"><a href="#1-Linux-块设备层-IO-请求" class="headerlink" title="1 Linux 块设备层 IO 请求"></a>1 Linux 块设备层 IO 请求</h2><p>在用户空间发起读写请求时，如果 page cache 没有需要的数据，需要从存储介质中进行读取&#x2F;写入。Linux 为了兼容各种各样的存储设备，同样抽象出了通用块层作为统一接口向上层文件系统或页缓存提供高效读写服务。</p><p>在块通用块层，Linux 使用 <code>struct bio</code>和<code>struct request</code>这两种结构体抽象，把上层的IO请求与下层实际能够高效处理 IO 单元进行了完美的解耦和桥接，实现了高性能、高兼容性的通用存储框架：</p><ul><li><p>上层文件系统将需求包装成 <code>struct bio</code>，表达自己要读写什么地方的多少数据；</p></li><li><p>通用块层在<code>struct bio</code>基础上进一步将IO请求处理成 <code>struct request</code>结构，并下发给设备驱动处理；</p></li></ul><p>其中，<code>bio</code>和<code>request</code>之间的关系可以是：</p><ul><li><p>多个<code>bio</code>合并到一个 <code>request</code>；</p></li><li><p>一个<code>bio</code>拆解成多个<code>request</code>；</p></li></ul><p>通用块层在<code>submit_bio</code>到<code>queue_rq</code>这段对话中，负责从<code>bio-&gt;request</code>的调度，极大提升了系统IO性能和硬件利用率</p><h3 id="1-1-struct-bio"><a href="#1-1-struct-bio" class="headerlink" title="1.1 struct bio"></a>1.1 <code>struct bio</code></h3><p>是文件系统&#x2F;页缓存&#x2F;RAID&#x2F;dm 到通用块层的IO请求描述，主要包括：</p><ul><li><p>数据页；</p></li><li><p>IO 方向；</p></li><li><p>起始扇区；</p></li></ul><p>其中<code>struct bio</code>定义于<code>include/linux/blk_types.h</code>中：</p><div class="code-container" data-rel="C"><figure class="iseeu highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">bio</span> &#123;</span></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">bio</span>*<span class="title">bi_next</span>;</span><span class="comment">// bio 之间串联成链表，方便 request quene 调度</span></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">block_device</span>*<span class="title">bi_bdev</span>;</span> <span class="comment">// bio 要操作的设备指针</span></span><br><span class="line"><span class="type">blk_opf_t</span>bi_opf;<span class="comment">// 表明 bio 执行什么操作的</span></span><br><span class="line">                        <span class="comment">// 低八位操作类型</span></span><br><span class="line">                        <span class="comment">// 高 24 位代表请求 flag</span></span><br><span class="line"><span class="type">unsigned</span> <span class="type">short</span>bi_flags; <span class="comment">// 这个 bio 怎么被管理和请求, 对象内部标志</span></span><br><span class="line"><span class="type">unsigned</span> <span class="type">short</span>bi_ioprio; <span class="comment">// IO 优先级</span></span><br><span class="line"><span class="class"><span class="keyword">enum</span> <span class="title">rw_hint</span><span class="title">bi_write_hint</span>;</span> <span class="comment">// 写入数据的预期生命周期提示</span></span><br><span class="line">u8bi_write_stream; <span class="comment">// 写入流的分组, 用于写入分类分组</span></span><br><span class="line"><span class="type">blk_status_t</span>bi_status; <span class="comment">// bio 执行结果, 记录 IO 操作的返回状态</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 这一项表示所有 bi_io_vec 之间的地址偏移量中，</span></span><br><span class="line">    <span class="comment">// 最低的 &quot;1&quot; 出现在第几位</span></span><br><span class="line">    <span class="comment">// 一个 BIO 的 bi_io_vec 可以描述多段物理上不连续的内存</span></span><br><span class="line">    <span class="comment">// IOMMU 在进行内存映射的时候，需要对这些向量内存对其做检查</span></span><br><span class="line">u8bi_bvec_gap_bit;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 代表一个 bio 链中还有几个 bio 没有处理完，默认值为 1</span></span><br><span class="line">    <span class="comment">// 对于链类型的 bio 来说，回调函数为 bio_chain_endio</span></span><br><span class="line">    <span class="comment">// 函数回调流程为 bio_chain_endio -&gt; bio_endio -&gt; bio_remaining_done</span></span><br><span class="line">    <span class="comment">// 此时该数值 -1</span></span><br><span class="line">    <span class="comment">// 这个值如果不是 0 说明当前链中的 bio 还没有处理完</span></span><br><span class="line">    <span class="comment">// bio_endio 直接返回, 只有当 这个数值为 0 时，bio_endio才会继续执行</span></span><br><span class="line"><span class="type">atomic_t</span>__bi_remaining;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* The actual vec list, preserved by bio_reset() */</span></span><br><span class="line"><span class="comment">// 其中记录内存的页数、长度、起始位置</span></span><br><span class="line"><span class="comment">// 注意，这里每个 bio_vec 记录一段内存片段</span></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">bio_vec</span>*<span class="title">bi_io_vec</span>;</span></span><br><span class="line">    <span class="comment">// struct bvec_iter</span></span><br><span class="line">    <span class="comment">// &#123;</span></span><br><span class="line"><span class="comment">//     sector_tbi_sector; 在哪个扇区</span></span><br><span class="line"><span class="comment">//     unsigned intbi_size; 还剩下多少没有读</span></span><br><span class="line"><span class="comment">//     unsigned intbi_idx; // 读到几号 bi_vect</span></span><br><span class="line"><span class="comment">//     unsigned intbi_offset; // 现在正在读取的 bvec 的 offset</span></span><br><span class="line">    <span class="comment">// &#125;</span></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">bvec_iter</span><span class="title">bi_iter</span>;</span> <span class="comment">// 描述当前 bio 的遍历状态</span></span><br><span class="line">                             <span class="comment">// 存储器端启示位置, 还有多少字节需要写</span></span><br><span class="line">                             <span class="comment">// 内存端当前操作的 vector 是哪个,</span></span><br><span class="line">                             <span class="comment">// 当前 vector 中完成了多少字节</span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">union</span> &#123;</span></span><br><span class="line"><span class="comment">/* for polled bios: */</span></span><br><span class="line"><span class="type">blk_qc_t</span>bi_cookie;</span><br><span class="line"><span class="comment">/* for plugged zoned writes only: */</span></span><br><span class="line"><span class="type">unsigned</span> <span class="type">int</span>__bi_nr_segments;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="type">bio_end_io_t</span>*bi_end_io;</span><br><span class="line"><span class="type">void</span>*bi_private;</span><br><span class="line"><span class="meta">#<span class="keyword">ifdef</span> CONFIG_BLK_CGROUP</span></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> * Represents the association of the css and request_queue for the bio.</span></span><br><span class="line"><span class="comment"> * If a bio goes direct to device, it will not have a blkg as it will</span></span><br><span class="line"><span class="comment"> * not have a request_queue associated with it.  The reference is put</span></span><br><span class="line"><span class="comment"> * on release of the bio.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">blkcg_gq</span>*<span class="title">bi_blkg</span>;</span></span><br><span class="line"><span class="comment">/* Time that this bio was issued. */</span></span><br><span class="line">u64issue_time_ns;</span><br><span class="line"><span class="meta">#<span class="keyword">ifdef</span> CONFIG_BLK_CGROUP_IOCOST</span></span><br><span class="line">u64bi_iocost_cost;</span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">ifdef</span> CONFIG_BLK_INLINE_ENCRYPTION</span></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">bio_crypt_ctx</span>*<span class="title">bi_crypt_context</span>;</span></span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">if</span> defined(CONFIG_BLK_DEV_INTEGRITY)</span></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">bio_integrity_payload</span> *<span class="title">bi_integrity</span>;</span> <span class="comment">/* data integrity */</span></span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line"></span><br><span class="line"><span class="type">unsigned</span> <span class="type">short</span>bi_vcnt; <span class="comment">// 存了多少 bio_vect</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> * Everything starting with bi_max_vecs will be preserved by bio_reset()</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 表示一个 bio 可以容纳的 bio_vect 有多少个</span></span><br><span class="line"><span class="type">unsigned</span> <span class="type">short</span>bi_max_vecs;</span><br><span class="line">    </span><br><span class="line">    <span class="comment">// bio 引用计数, 防止被提前释放</span></span><br><span class="line"><span class="type">atomic_t</span>__bi_cnt;<span class="comment">/* pin count */</span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">bio_set</span>*<span class="title">bi_pool</span>;</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></div><p>其中，一个 bio 中重要的对应指针为：</p><ul><li><p><code>bi_next</code>串联下一个 <code>bio</code>结构体；</p></li><li><p><code>bi_vect</code>记录一条<code>bio</code>需要访问的连续内存片段；</p></li><li><p><code>bi_iter</code>负责记录现在所有<code>bio</code>结构体处理到哪里，以及正在处理的<code>bio_vect</code>是哪个，同时负责调度<code>bi_vect</code>。</p></li><li><p>当 <code>biv_cnt</code>小于<code>bi_inline_vecs</code>时，直接指向<code>bi_inline_vecs</code></p></li></ul><p><img                       lazyload                     src="/images/loading.svg"                     data-src="/images/contents/Linux_Kernel/bio_struct.png"                                     ></p><h4 id="1-1-1-bi-opf"><a href="#1-1-1-bi-opf" class="headerlink" title="1.1.1 bi_opf"></a>1.1.1 <code>bi_opf</code></h4><p>其中，具体的<code>bi_opf</code>中的可选值如下：其中低 8 位为操作类型，高 24 位为请求处理 flag</p><div class="code-container" data-rel="C"><figure class="iseeu highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">enum</span> <span class="title">req_op</span> &#123;</span> <span class="comment">// 低八位</span></span><br><span class="line"><span class="comment">/** @REQ_OP_READ: 从设备中读取扇区 */</span></span><br><span class="line">REQ_OP_READ= (__force <span class="type">blk_opf_t</span>)<span class="number">0</span>,</span><br><span class="line"><span class="comment">/** @REQ_OP_WRITE: 向设备中扇区写入内容 */</span></span><br><span class="line">REQ_OP_WRITE= (__force <span class="type">blk_opf_t</span>)<span class="number">1</span>,</span><br><span class="line"><span class="comment">/** @REQ_OP_FLUSH: 刷新易失性写缓存*/</span></span><br><span class="line">REQ_OP_FLUSH= (__force <span class="type">blk_opf_t</span>)<span class="number">2</span>,</span><br><span class="line"><span class="comment">/** @REQ_OP_DISCARD: 丢弃扇区 */</span></span><br><span class="line">REQ_OP_DISCARD= (__force <span class="type">blk_opf_t</span>)<span class="number">3</span>,</span><br><span class="line"><span class="comment">/** @REQ_OP_SECURE_ERASE: 安全擦除扇区 */</span></span><br><span class="line">REQ_OP_SECURE_ERASE= (__force <span class="type">blk_opf_t</span>)<span class="number">5</span>,</span><br><span class="line"><span class="comment">/** @REQ_OP_ZONE_APPEND: 从当前扇区的写入指针位置开始写数据 */</span></span><br><span class="line">REQ_OP_ZONE_APPEND= (__force <span class="type">blk_opf_t</span>)<span class="number">7</span>,</span><br><span class="line"><span class="comment">/** @REQ_OP_WRITE_ZEROES: 将扇区用 0 多次填充 */</span></span><br><span class="line">REQ_OP_WRITE_ZEROES= (__force <span class="type">blk_opf_t</span>)<span class="number">9</span>,</span><br><span class="line"><span class="comment">/** @REQ_OP_ZONE_OPEN: 打开管理分区 */</span></span><br><span class="line">REQ_OP_ZONE_OPEN= (__force <span class="type">blk_opf_t</span>)<span class="number">11</span>,</span><br><span class="line"><span class="comment">/** @REQ_OP_ZONE_CLOSE: 关闭管理分区 */</span></span><br><span class="line">REQ_OP_ZONE_CLOSE= (__force <span class="type">blk_opf_t</span>)<span class="number">13</span>,</span><br><span class="line"><span class="comment">/** @REQ_OP_ZONE_FINISH: 将分区标记为写满, 不再写入内容 */</span></span><br><span class="line">REQ_OP_ZONE_FINISH= (__force <span class="type">blk_opf_t</span>)<span class="number">15</span>,</span><br><span class="line"><span class="comment">/** @REQ_OP_ZONE_RESET: 重置一个分区写指针 */</span></span><br><span class="line">REQ_OP_ZONE_RESET= (__force <span class="type">blk_opf_t</span>)<span class="number">17</span>,</span><br><span class="line"><span class="comment">/** @REQ_OP_ZONE_RESET_ALL: 重置设备上的所有分区 */</span></span><br><span class="line">REQ_OP_ZONE_RESET_ALL= (__force <span class="type">blk_opf_t</span>)<span class="number">19</span>,</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 设备私有请求</span></span><br><span class="line"><span class="comment">/* private: */</span></span><br><span class="line">REQ_OP_DRV_IN= (__force <span class="type">blk_opf_t</span>)<span class="number">34</span>,</span><br><span class="line">REQ_OP_DRV_OUT= (__force <span class="type">blk_opf_t</span>)<span class="number">35</span>,</span><br><span class="line"></span><br><span class="line">REQ_OP_LAST= (__force <span class="type">blk_opf_t</span>)<span class="number">36</span>,</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">enum</span> <span class="title">req_flag_bits</span> &#123;</span></span><br><span class="line">__REQ_FAILFAST_DEV =<span class="comment">/* 设备层错误直接显示失败, 不重试 */</span></span><br><span class="line">REQ_OP_BITS,</span><br><span class="line">__REQ_FAILFAST_TRANSPORT, <span class="comment">/* 传输错误不重试 */</span></span><br><span class="line">__REQ_FAILFAST_DRIVER,<span class="comment">/* 驱动错误不重试 */</span></span><br><span class="line">__REQ_SYNC,<span class="comment">/* 请求是同步的 */</span></span><br><span class="line">__REQ_META,<span class="comment">/* 请求元数据 */</span></span><br><span class="line">__REQ_PRIO,<span class="comment">/* 提升 io 优先级 */</span></span><br><span class="line">__REQ_NOMERGE,<span class="comment">/* 不允许与其他请求合并 */</span></span><br><span class="line">__REQ_IDLE,<span class="comment">/* 预期之后还有更多 IO */</span></span><br><span class="line">__REQ_INTEGRITY,<span class="comment">/* IO 中包含数据完整性 payload */</span></span><br><span class="line">__REQ_FUA,<span class="comment">/* 强制单元访问 */</span></span><br><span class="line">__REQ_PREFLUSH,<span class="comment">/* 强制缓存刷盘 */</span></span><br><span class="line">__REQ_RAHEAD,<span class="comment">/* 预先读（可以随时失败） */</span></span><br><span class="line">__REQ_BACKGROUND,<span class="comment">/* 后台 IO */</span></span><br><span class="line">__REQ_NOWAIT,           <span class="comment">/* 遇到阻塞直接返回，用于高并发 */</span></span><br><span class="line">__REQ_POLLED,<span class="comment">/* 调用方使用 bio_poll 主动轮询完成 */</span></span><br><span class="line">__REQ_ALLOC_CACHE,<span class="comment">/* 可用时从缓存分配 IO */</span></span><br><span class="line">__REQ_SWAP,<span class="comment">/* 交换分区 I/O */</span></span><br><span class="line">__REQ_DRV,<span class="comment">/* 驱动自用标志 */</span></span><br><span class="line">__REQ_FS_PRIVATE,<span class="comment">/* 文件系统自用标志 */</span></span><br><span class="line">__REQ_ATOMIC,<span class="comment">/* 原子写入标志 */</span></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> * Command specific flags, keep last:</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="comment">/* for REQ_OP_WRITE_ZEROES: */</span></span><br><span class="line">__REQ_NOUNMAP,<span class="comment">/* 全 0 不放块 */</span></span><br><span class="line"></span><br><span class="line">__REQ_NR_BITS,<span class="comment">/* 标志位数量上限 */</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></div><h4 id="1-1-2-bio-flags"><a href="#1-1-2-bio-flags" class="headerlink" title="1.1.2 bio_flags"></a>1.1.2 <code>bio_flags</code></h4><p><code>bio_flags</code> 有如下几种：</p><div class="code-container" data-rel="C"><figure class="iseeu highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> * bio flags</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="class"><span class="keyword">enum</span> &#123;</span></span><br><span class="line">BIO_PAGE_PINNED,<span class="comment">/* 解除在 bio_release_pages() 中固定的页面 */</span></span><br><span class="line">                    <span class="comment">/* 确保释放 bio 时正确释放页面引用 */</span></span><br><span class="line">BIO_CLONED,<span class="comment">/* bio 是克隆的，没有数据，vector 不是自己分配的 */</span></span><br><span class="line">                <span class="comment">/* 不能主动释放数据 */</span></span><br><span class="line">BIO_QUIET,<span class="comment">/* 静默模式，不能主动释放数据 */</span></span><br><span class="line">BIO_CHAIN,<span class="comment">/* bio是 链式, bi_remaining 字段生效 */</span></span><br><span class="line">BIO_REFFED,<span class="comment">/* bio 已经被引用 -&gt;bi_cnt */</span></span><br><span class="line">BIO_BPS_THROTTLED,<span class="comment">/* 已经执行带宽限制，不需要限速 */</span></span><br><span class="line">BIO_TRACE_COMPLETION,<span class="comment">/* bio_endio() 应该记录该 bio 的完成 */</span></span><br><span class="line">                        <span class="comment">/* 用于 trace / 调试 */</span></span><br><span class="line">BIO_CGROUP_ACCT,<span class="comment">/* 被计入 cgroup IO 统计 */</span></span><br><span class="line">BIO_QOS_THROTTLED,<span class="comment">/* bio 经过了 rq_qos 的限速路径 */</span></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> * This bio has completed bps throttling at the single tg granularity,</span></span><br><span class="line"><span class="comment"> * which is different from BIO_BPS_THROTTLED. When the bio is enqueued</span></span><br><span class="line"><span class="comment"> * into the sq-&gt;queued of the upper tg, or is about to be dispatched,</span></span><br><span class="line"><span class="comment"> * this flag needs to be cleared. Since blk-throttle and rq_qos are not</span></span><br><span class="line"><span class="comment"> * on the same hierarchical level, reuse the value.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line">BIO_TG_BPS_THROTTLED = BIO_QOS_THROTTLED,</span><br><span class="line">BIO_QOS_MERGED,<span class="comment">/* bio 经过了 rq_qos 的合并路径 */</span></span><br><span class="line">BIO_REMAPPED,</span><br><span class="line">BIO_ZONE_WRITE_PLUGGING, <span class="comment">/* bio handled through zone write plugging */</span></span><br><span class="line">BIO_EMULATES_ZONE_APPEND, <span class="comment">/* bio emulates a zone append operation */</span></span><br><span class="line">BIO_COMPLETE_IN_TASK, <span class="comment">/* complete bi_end_io() in task context */</span></span><br><span class="line">BIO_FLAG_LAST</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></div><h4 id="1-1-3-bio-vec与bio-iter"><a href="#1-1-3-bio-vec与bio-iter" class="headerlink" title="1.1.3 bio_vec与bio_iter"></a>1.1.3 <code>bio_vec</code>与<code>bio_iter</code></h4><p><code>bio_vec</code>和<code>bio_iter</code>分工明确：</p><ul><li><code>bio_vec</code>一个是对应 IO 请求的具体内存块；</li><li><code>bio_iter</code>是请求的具体情况；</li></ul><p>其中<code>bvec_iter</code>内容如下：</p><div class="code-container" data-rel="C"><figure class="iseeu highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">bvec_iter</span> &#123;</span></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> * Current device address in 512 byte sectors. Only updated by the bio</span></span><br><span class="line"><span class="comment"> * iter wrappers and not the bvec iterator helpers themselves.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="type">sector_t</span>bi_sector; <span class="comment">// 现在正在处理的 bio 处于的分区</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> * Remaining size in bytes.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="type">unsigned</span> <span class="type">int</span>bi_size; <span class="comment">// 还剩多少字节没有处理</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> * Current index into the bvec array. This indexes into `bi_io_vec` when</span></span><br><span class="line"><span class="comment"> * iterating a bvec array that is part of a `bio`.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="type">unsigned</span> <span class="type">int</span>bi_idx; <span class="comment">// 目前处理到多少 bio_vec</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> * Current offset in the bvec entry pointed to by `bi_idx`.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="type">unsigned</span> <span class="type">int</span>bi_offset; <span class="comment">// 现在处理的 bio_vec 的 offset</span></span><br><span class="line">&#125; __packed __aligned(<span class="number">4</span>);</span><br></pre></td></tr></table></figure></div><p><code>bio_vec</code>如下：</p><div class="code-container" data-rel="C"><figure class="iseeu highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">bio_vec</span> &#123;</span></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">page</span>*<span class="title">bv_page</span>;</span> <span class="comment">// 指向该地址区间的第一个内存页</span></span><br><span class="line"><span class="type">unsigned</span> <span class="type">int</span>bv_len; <span class="comment">// 大小</span></span><br><span class="line"><span class="type">unsigned</span> <span class="type">int</span>bv_offset; <span class="comment">// 开始位置</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></div><h3 id="1-2-执行流程-submit-bio"><a href="#1-2-执行流程-submit-bio" class="headerlink" title="1.2 执行流程 submit_bio"></a>1.2 执行流程 <code>submit_bio</code></h3><p>函数的功能是：将一个 bio IO 请求提交到对应的块设备上。这个函数首先完全初始化了<code>struct bio</code>结构体。这个结构体之后会被提交到被<code>bi_bdev</code>描述的指定设备上。本次请求的成功 &#x2F; 失败状态，以及完成的通知，都会通过 <code>bio-&gt;bi_end_io ()</code> 回调函数以异步方式传递，在 <code>bi_end_io ()</code> 被调用之前，调用者【不得】修改或访问该 <code>bio</code>。</p><div class="code-container" data-rel="C"><figure class="iseeu highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">void</span> <span class="title function_">submit_bio</span><span class="params">(<span class="keyword">struct</span> bio *bio)</span></span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">if</span> (bio_op(bio) == REQ_OP_READ) &#123; <span class="comment">// 从设备中读取 IO</span></span><br><span class="line">task_io_account_read(bio-&gt;bi_iter.bi_size); <span class="comment">// 记录当前任务的读取字节数</span></span><br><span class="line">count_vm_events(PGPGIN, bio_sectors(bio)); <span class="comment">// 给指定的内核项加一定数值</span></span><br><span class="line">&#125; <span class="keyword">else</span> <span class="keyword">if</span> (bio_op(bio) == REQ_OP_WRITE) &#123; <span class="comment">// 向扇区内写</span></span><br><span class="line">count_vm_events(PGPGOUT, bio_sectors(bio));</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">bio_set_ioprio(bio); <span class="comment">// 确定 bio 的 IO 优先级</span></span><br><span class="line">submit_bio_noacct(bio);</span><br><span class="line">&#125;</span><br><span class="line">EXPORT_SYMBOL(submit_bio);</span><br></pre></td></tr></table></figure></div><p>其中：</p><ul><li><code>task_io_account_read</code>记录系统读取或写入的扇区数，<code>PGPGIN</code>表示读取，<code>PGPGOUT</code>表示写入；</li><li><code>task_io_account_read</code>表示在这次任务内读取的字节数，在启用<code>CONFIG_TASK_IO_ACCOUNTING</code>时生效。</li></ul><h4 id="1-2-1-submit-bio-noacct"><a href="#1-2-1-submit-bio-noacct" class="headerlink" title="1.2.1 submit_bio_noacct"></a>1.2.1 <code>submit_bio_noacct</code></h4><p>这个函数主要实现提交 <code>bio</code> 请求的细节，同时不再统计相关参数。它是更底层的提交请求，只能被 stacking block drivers 用于将 IO 操作交给更底层的驱动。对于用户和文件系统，应该使用<code>submit_bio</code> 。</p><p>在这个函数中，主要对 bio 请求的细节进行检查（<code>REQ_XXX</code>），之后交给更底层的函数进行处理。</p><div class="code-container" data-rel="C"><figure class="iseeu highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">void</span> <span class="title function_">submit_bio_noacct</span><span class="params">(<span class="keyword">struct</span> bio *bio)</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="comment">// 获取 bio 对应的 bi_bdev 设备</span></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">block_device</span> *<span class="title">bdev</span> =</span> bio-&gt;bi_bdev;</span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">request_queue</span> *<span class="title">q</span> =</span> bdev_get_queue(bdev); <span class="comment">// 查询设备对应的请求队列对象</span></span><br><span class="line"><span class="type">blk_status_t</span> status = BLK_STS_IOERR;</span><br><span class="line"></span><br><span class="line">might_sleep();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 这里首先检查是否支持不等待直接报错的选项 (遇到阻塞直接返回)</span></span><br><span class="line">    <span class="comment">// 不支持直接返回 not_support 报错</span></span><br><span class="line"><span class="keyword">if</span> ((bio-&gt;bi_opf &amp; REQ_NOWAIT) &amp;&amp; !bdev_nowait(bdev))</span><br><span class="line"><span class="keyword">goto</span> not_supported;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 有加密上下文时，检查是否有数据，没有数据以IO错误结束</span></span><br><span class="line">    <span class="comment">// 再监测块设备是否支持 bio 不支持就进行报错</span></span><br><span class="line"><span class="keyword">if</span> (bio_has_crypt_ctx(bio)) &#123; </span><br><span class="line"><span class="keyword">if</span> (WARN_ON_ONCE(!bio_has_data(bio)))</span><br><span class="line"><span class="keyword">goto</span> end_io;</span><br><span class="line"><span class="keyword">if</span> (!blk_crypto_supported(bio))</span><br><span class="line"><span class="keyword">goto</span> not_supported;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 一些会出错的情形检查</span></span><br><span class="line"><span class="keyword">if</span> (should_fail_bio(bio))</span><br><span class="line"><span class="keyword">goto</span> end_io;</span><br><span class="line">    <span class="comment">// 检查是否在写一个只读设备</span></span><br><span class="line">bio_check_ro(bio);</span><br><span class="line">    <span class="comment">// 检查 IO 是否越界，即是否越过当前块设备</span></span><br><span class="line"><span class="keyword">if</span> (!bio_flagged(bio, BIO_REMAPPED)) &#123;</span><br><span class="line"><span class="keyword">if</span> (unlikely(bio_check_eod(bio)))</span><br><span class="line"><span class="keyword">goto</span> end_io;</span><br><span class="line"><span class="keyword">if</span> (bdev_is_partition(bdev) &amp;&amp;</span><br><span class="line">    unlikely(blk_partition_remap(bio)))</span><br><span class="line"><span class="keyword">goto</span> end_io;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> * Filter flush bio&#x27;s early so that bio based drivers without flush</span></span><br><span class="line"><span class="comment"> * support don&#x27;t have to worry about them.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line">    <span class="comment">// 提前过滤 flush 请求</span></span><br><span class="line">    <span class="comment">// 就是将易失性的缓存进行持久化保存，防止断电消失</span></span><br><span class="line"><span class="keyword">if</span> (op_is_flush(bio-&gt;bi_opf)) &#123;</span><br><span class="line"><span class="keyword">if</span> (WARN_ON_ONCE(bio_op(bio) != REQ_OP_WRITE &amp;&amp;</span><br><span class="line"> bio_op(bio) != REQ_OP_ZONE_APPEND))</span><br><span class="line"><span class="keyword">goto</span> end_io;</span><br><span class="line"><span class="keyword">if</span> (!bdev_write_cache(bdev)) &#123;</span><br><span class="line">bio-&gt;bi_opf &amp;= ~(REQ_PREFLUSH | REQ_FUA);</span><br><span class="line"><span class="keyword">if</span> (!bio_sectors(bio)) &#123;</span><br><span class="line">status = BLK_STS_OK;</span><br><span class="line"><span class="keyword">goto</span> end_io;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">switch</span> (bio_op(bio)) &#123;</span><br><span class="line"><span class="keyword">case</span> REQ_OP_READ:</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> REQ_OP_WRITE:</span><br><span class="line"><span class="keyword">if</span> (bio-&gt;bi_opf &amp; REQ_ATOMIC) &#123;</span><br><span class="line">status = blk_validate_atomic_write_op_size(q, bio);</span><br><span class="line"><span class="keyword">if</span> (status != BLK_STS_OK)</span><br><span class="line"><span class="keyword">goto</span> end_io;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> REQ_OP_FLUSH:</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> * REQ_OP_FLUSH 不是通过 bio 提交的, 只能在 struct request 中</span></span><br><span class="line"><span class="comment"> * 使用 flush 状态机合成。</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">goto</span> not_supported;</span><br><span class="line"><span class="keyword">case</span> REQ_OP_DISCARD:</span><br><span class="line"><span class="keyword">if</span> (!bdev_max_discard_sectors(bdev))</span><br><span class="line"><span class="keyword">goto</span> not_supported;</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> REQ_OP_SECURE_ERASE:</span><br><span class="line"><span class="keyword">if</span> (!bdev_max_secure_erase_sectors(bdev))</span><br><span class="line"><span class="keyword">goto</span> not_supported;</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> REQ_OP_ZONE_APPEND:</span><br><span class="line">status = blk_check_zone_append(q, bio);</span><br><span class="line"><span class="keyword">if</span> (status != BLK_STS_OK)</span><br><span class="line"><span class="keyword">goto</span> end_io;</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> REQ_OP_WRITE_ZEROES:</span><br><span class="line"><span class="keyword">if</span> (!q-&gt;limits.max_write_zeroes_sectors)</span><br><span class="line"><span class="keyword">goto</span> not_supported;</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> REQ_OP_ZONE_OPEN:</span><br><span class="line"><span class="keyword">case</span> REQ_OP_ZONE_CLOSE:</span><br><span class="line"><span class="keyword">case</span> REQ_OP_ZONE_RESET:</span><br><span class="line"><span class="keyword">case</span> REQ_OP_ZONE_FINISH:</span><br><span class="line"><span class="comment">/* Zone management operations require sequential zones. */</span></span><br><span class="line"><span class="keyword">if</span> (!bdev_zone_is_seq(bio-&gt;bi_bdev, bio-&gt;bi_iter.bi_sector))</span><br><span class="line"><span class="keyword">goto</span> end_io;</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> REQ_OP_ZONE_RESET_ALL:</span><br><span class="line"><span class="keyword">if</span> (!bdev_is_zoned(bio-&gt;bi_bdev))</span><br><span class="line"><span class="keyword">goto</span> not_supported;</span><br><span class="line"><span class="keyword">break</span>;</span><br><span class="line"><span class="keyword">case</span> REQ_OP_DRV_IN:</span><br><span class="line"><span class="keyword">case</span> REQ_OP_DRV_OUT:</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> * Driver private operations are only used with passthrough</span></span><br><span class="line"><span class="comment"> * requests.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line">fallthrough;</span><br><span class="line"><span class="keyword">default</span>:</span><br><span class="line"><span class="keyword">goto</span> not_supported;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (blk_throtl_bio(bio))</span><br><span class="line"><span class="keyword">return</span>;</span><br><span class="line">submit_bio_noacct_nocheck(bio, <span class="literal">false</span>); <span class="comment">// 更底层的封装</span></span><br><span class="line"><span class="keyword">return</span>;</span><br><span class="line"></span><br><span class="line">not_supported:</span><br><span class="line">status = BLK_STS_NOTSUPP;</span><br><span class="line">end_io:</span><br><span class="line">bio_endio_status(bio, status);</span><br><span class="line">&#125;</span><br><span class="line">EXPORT_SYMBOL(submit_bio_noacct);</span><br></pre></td></tr></table></figure></div>]]></content>
    
    
    <summary type="html">简单了解 Linux 存储栈的架构</summary>
    
    
    
    
    <category term="学习笔记" scheme="https://wawoscarqaq.github.io/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    
    <category term="Linux Kernel" scheme="https://wawoscarqaq.github.io/tags/Linux-Kernel/"/>
    
    <category term="存储栈" scheme="https://wawoscarqaq.github.io/tags/%E5%AD%98%E5%82%A8%E6%A0%88/"/>
    
  </entry>
  
  <entry>
    <title>Hello World</title>
    <link href="https://wawoscarqaq.github.io/2025/02/26/hello-world/"/>
    <id>https://wawoscarqaq.github.io/2025/02/26/hello-world/</id>
    <published>2025-02-26T04:38:14.484Z</published>
    <updated>2025-02-26T04:38:14.484Z</updated>
    
    <content type="html"><![CDATA[<p>Welcome to <a class="link"   href="https://hexo.io/" >Hexo<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a>! This is your very first post. Check <a class="link"   href="https://hexo.io/docs/" >documentation<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a> for more info. If you get any problems when using Hexo, you can find the answer in <a class="link"   href="https://hexo.io/docs/troubleshooting.html" >troubleshooting<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a> or you can ask me on <a class="link"   href="https://github.com/hexojs/hexo/issues" >GitHub<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a>.</p><h2 id="Quick-Start"><a href="#Quick-Start" class="headerlink" title="Quick Start"></a>Quick Start</h2><h3 id="Create-a-new-post"><a href="#Create-a-new-post" class="headerlink" title="Create a new post"></a>Create a new post</h3><div class="code-container" data-rel="Bash"><figure class="iseeu highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo new <span class="string">&quot;My New Post&quot;</span></span><br></pre></td></tr></table></figure></div><p>More info: <a class="link"   href="https://hexo.io/docs/writing.html" >Writing<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a></p><h3 id="Run-server"><a href="#Run-server" class="headerlink" title="Run server"></a>Run server</h3><div class="code-container" data-rel="Bash"><figure class="iseeu highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo server</span><br></pre></td></tr></table></figure></div><p>More info: <a class="link"   href="https://hexo.io/docs/server.html" >Server<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a></p><h3 id="Generate-static-files"><a href="#Generate-static-files" class="headerlink" title="Generate static files"></a>Generate static files</h3><div class="code-container" data-rel="Bash"><figure class="iseeu highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo generate</span><br></pre></td></tr></table></figure></div><p>More info: <a class="link"   href="https://hexo.io/docs/generating.html" >Generating<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a></p><h3 id="Deploy-to-remote-sites"><a href="#Deploy-to-remote-sites" class="headerlink" title="Deploy to remote sites"></a>Deploy to remote sites</h3><div class="code-container" data-rel="Bash"><figure class="iseeu highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo deploy</span><br></pre></td></tr></table></figure></div><p>More info: <a class="link"   href="https://hexo.io/docs/one-command-deployment.html" >Deployment<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a></p>]]></content>
    
    
    <summary type="html">Welcome to Hexo! This is your very first post.</summary>
    
    
    
    
  </entry>
  
</feed>
