<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Posts on Caelum&#39;s Site</title>
    <link>https://blog.decglu.uk/posts/</link>
    <description>Recent content in Posts on Caelum&#39;s Site</description>
    <generator>Hugo</generator>
    <language>zh-cn</language>
    <lastBuildDate>Sat, 07 Nov 2026 00:56:24 +0800</lastBuildDate>
    <atom:link href="https://blog.decglu.uk/posts/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>自适应 Agent Runtime</title>
      <link>https://blog.decglu.uk/posts/self-evolving-agent-runtime/</link>
      <pubDate>Sat, 07 Nov 2026 00:56:24 +0800</pubDate>
      <guid>https://blog.decglu.uk/posts/self-evolving-agent-runtime/</guid>
      <description>&lt;p&gt;最近俩月没找到实习，挺郁闷的。没有面试，又不想闲着，于是跟风，养了一只“蓝色大肥鱼”。&lt;/p&gt;
&lt;h2 id=&#34;蓝色大肥鱼的启蒙&#34;&gt;“蓝色大肥鱼”的启蒙&lt;/h2&gt;
&lt;p&gt;QQ 交流群里有各种人格提示词，傲娇版、妹妹版、女友版、妈妈版、贴吧嘴臭版，甚至……常凯申版？ 无一例外，这些提示词中充满了明显的外行行为，大概分为这么几类：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;要求按概率触发，但没有调度&lt;/li&gt;
&lt;li&gt;反向提示词 / 补丁套补丁&lt;/li&gt;
&lt;li&gt;示例污染 / 复读机&lt;/li&gt;
&lt;li&gt;规则打架 / 篇幅失控&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;摸索着用 docker 部署 AstrBot，接进 IM，再配置点人格和规则就完了。就这么用，我一开始也没有意识到问题的严重性，直到我连续几天都在用 AI 调节提示词但效果欠佳时，我才猜到可能是上下文问题。&lt;/p&gt;
&lt;p&gt;我只要问鱼在干什么，鱼大概率在躺着，吃白米饭，等着我给她做白米饭，发呆……几乎就是提示词报菜名了。&lt;/p&gt;
&lt;p&gt;同一套人格提示词，多个会话中均表现出回复风格越来越同质化，逐渐收敛（数学意义上的？），且情绪等状态因素影响变小，但会话间的收敛点还不同。有时会收敛到一个很奇怪的点，每次末尾都带上 &amp;ldquo;write. done.&amp;quot;，我在会话中要求不要输出那个，但无济于事。&lt;/p&gt;
&lt;p&gt;我受不了了，这玩意越聊越像人机。没有各种插件的话，她什么都做不了，甚至不能主动发消息，纯粹事件驱动的东西。&lt;/p&gt;
&lt;h2 id=&#34;深入探究-agent&#34;&gt;深入探究 Agent&lt;/h2&gt;
&lt;p&gt;既然没事做，干脆在 AI 领域再深造一下，就去看了很新的课 CMU 11-768: AI Agents。看到 Lecture 3: Long Context，字面意思，是关于长上下文 Agent 的上下文管理，前面讲了一大堆在模型层提升 Agent 进行长上下文任务能力的工程架构问题，缺乏前置知识，我没仔细看。不过剩下的部分看下来，大概就是：&lt;/p&gt;
&lt;p&gt;好的压缩就是构造一个适合继续行动的状态，不是简单的缩写历史。&lt;/p&gt;
&lt;p&gt;但是 Harness 就一坨代码，它怎么知道哪些细节应该留着呢？&lt;/p&gt;
&lt;h2 id=&#34;状态机&#34;&gt;状态机&lt;/h2&gt;
&lt;p&gt;突然想到 Vedal 做的 Neuro-sama，那玩意不就是 LLM 驱动的吗？她为什么那么有活人感呢？Neuro 似乎是被一个经微调的 LLM 驱动，说话方式被刻在权重里了。上面一大批提示词暴露的问题，这个解决了一半，那剩下的呢？&lt;/p&gt;
&lt;p&gt;我来构想一种架构。&lt;/p&gt;
&lt;p&gt;他们试图把 LLM 无法左右的事情交给 LLM。LLM 调用是无状态的，但他们试图描述一个有条件的状态机，那么这件事不如交给 Runtime。&lt;/p&gt;
&lt;p&gt;我这里把维护 Agent 持久状态、事件调度与执行规则的运行层，称为 Agent Runtime。&lt;/p&gt;</description>
    </item>
    <item>
      <title>技术围城</title>
      <link>https://blog.decglu.uk/posts/besieged-by-technology/</link>
      <pubDate>Mon, 07 Sep 2026 02:01:10 +0800</pubDate>
      <guid>https://blog.decglu.uk/posts/besieged-by-technology/</guid>
      <description>&lt;p&gt;我老想找些自由度高的游戏来玩，比如 Minecraft，但找来找去，就是找不到合适的。Minecraft 还在更新，可微软现在端出来的东西，在我这样的老玩家眼里就是敷衍。我们这一代老玩家也长大了，热情耗得差不多了，打开游戏，玩不下去；关掉，又不甘心。我在 Steam 上翻来翻去，没一个能填上这个窟窿。&lt;/p&gt;
&lt;p&gt;我到底在找什么？我想自由地创作，亲手搭出点东西。那股劲还在，却找不到地方使。或许，是我对技术最原始的热情又醒了。或许，我该做一个自己的开源项目。别再是什么分布式系统、数据库、Agent 插件了。就做一个我自己感兴趣的东西，不依靠 Coding Agent，自己把它做出来。&lt;/p&gt;
&lt;p&gt;我曾经想过自己做游戏。六年前，因为疫情居家，开始长时间接触电脑，那时候刚学 Python。我照着书里已经过时的 Pygame API，一边百度，一边翻 CSDN，做过一个很简陋的飞机大战。&lt;/p&gt;
&lt;p&gt;同一个暑假，我用三百多行 Python 加上 EasyGUI，写了一个简陋得要命的笔记系统，定位有点像 Obsidian，实际上难用得很。不知道什么时候该封装函数，那干脆不封装。全程 if-else，重复代码铺满屏幕。我还用 Tkinter 帮老师做过一个随机点名器，服役了一年；又写过一个丑得不行的、类似 GeoGebra 的东西，不能平移，不能缩放，只能画一次函数和二次函数的图像，连线都画不连续。&lt;/p&gt;
&lt;p&gt;上高中前，抓着最后那点自由的时间，我花了一周做了个带杰哥、阿伟 cosplay 音效的井字棋，Bug 连连。高中暑假忙里偷闲，买来一个二手树莓派和一些小外设，尝试用 Python 还原 Phigros。我甚至想参与 Phigros 的社区复刻项目 Phira 的开发，却发现，我对软件设计一无所知，不知道什么 Git 版本控制，协作流程，甚至连个 GitHub 账号都没有。&lt;/p&gt;
&lt;p&gt;那些作品里，只有井字棋留下过可执行文件。后来，那个 32GB 的 U 盘坏了，它和前面几个项目的代码一起，都成了不可溯源之物了。&lt;/p&gt;
&lt;p&gt;那时候做的东西，拿今天的眼光看，没几个像样的。可我真的很快乐。&lt;/p&gt;
&lt;p&gt;上一次有这样的热情，是在将近两年前。大一上学期，我凭着记忆，翻着那本 2020 年买来的破烂 Python 书，在 CSDN 上硬搜，对着笨重的 Visual Studio，用八百行 Python 做了一个三阶魔方模拟器。没用 AI——那时我没有科学上网手段，也不会用 AI。&lt;/p&gt;
&lt;p&gt;借助 Pygame、Tkinter 和 kociemba，它能变色，能打乱，能计时，有键位，能自动复原，能生成当前状态解法。八百行全塞在一个文件里，坐标全靠硬编码，屎山一座。但它真的跑起来了。那是我一点一点写出来的，它真的能转，真的能还原。&lt;/p&gt;
&lt;p&gt;我拿着这东西去参加学校的程序设计比赛，到了答辩现场才发现，我看漏了文件，这设计主题是 AI。真他妈荒唐。可至少，做它的时候，我没为了任何人。我就是觉得好玩。&lt;/p&gt;
&lt;p&gt;后来做 C 语言课设，一个学生管理系统，没有数据库，没有网络，也没有前后端。我偏要认真做。回调函数、函数指针解耦、三层架构分离，连文件格式都自己设计，当时觉得自己写得高端大气。无 AI 添加纯手搓。&lt;/p&gt;
&lt;p&gt;洋洋洒洒两千多行，却 0人在意我写了什么。&lt;/p&gt;</description>
    </item>
    <item>
      <title>AI时代的知识奶头乐</title>
      <link>https://blog.decglu.uk/posts/cognitive-tittytainment/</link>
      <pubDate>Sat, 08 Aug 2026 04:45:34 +0800</pubDate>
      <guid>https://blog.decglu.uk/posts/cognitive-tittytainment/</guid>
      <description>&lt;p&gt;我越来越担心一件事：AI正在悄悄改变我&amp;quot;学习&amp;quot;这个动作的形状。&lt;/p&gt;
&lt;p&gt;以前想弄懂一个复杂问题，得自己去啃、去查、去碰壁，那种摩擦感——查资料的辛苦、想不通的卡顿——恰恰是深度理解得以发生的地方。现在这层摩擦几乎被抹平了。同时被削弱的还有学习到新知的正向反馈。问AI，答案立刻就来，流畅、自信、结构完整。AI时代提供给了我们“知识奶头乐”。它太方便了，方便到我开始怀疑：我是不是正在失去那种&amp;quot;自己动手够到知识&amp;quot;的原始热情？&lt;/p&gt;
&lt;p&gt;AI本身也不是个省油的灯，它给出的答案本质上是概率模型的产物——是&amp;quot;平均的&amp;quot;、&amp;ldquo;大概的&amp;rdquo;、某个视角下的拼凑，甚至可能根本不是事实。但它说话的语气太笃定了，笃定到你根本不会去追问。它还会让你自信心满满，&amp;ldquo;You&amp;rsquo;re absolutely right!&amp;quot;，而可能根本不会意识到你观点的缺陷。这就像一个谀臣，无形中害了你。&lt;/p&gt;
&lt;p&gt;我也担心知识型人才的&amp;quot;缩水&amp;rdquo;。思考可以外包，工作可以替代。会不会有一大批人，Token花完，天才陨落？这个问题我还没有确定的答案，历史上工具从未让人真正变笨，计算器没有杀死数学家。但这一次的不同在于：AI外包的不是计算，而是理解本身，这条界限值得警惕。当我们已经习惯了用AI代替学习和思考，学习新知不再是振奋人心的探索，而是只是手指麻木地动一动就解决的是，那种原始热情一旦退去，我们对大脑的控制权是否会被一步步剥夺？&lt;/p&gt;
&lt;p&gt;我不想简单地把AI当作洪水猛兽，但我也不想假装这种失落感不存在。它成了我大脑里近乎不可分割的一部分，能替我理解、替我工作——可正因如此，我更需要时常停下来问自己：最近一次让我兴奋到不想问AI、只想自己去啃的问题，是什么时候？&lt;/p&gt;
&lt;p&gt;如果想不起来，那大概就是该找回那种&amp;quot;笨拙但亲手够到&amp;quot;的体验的时候了。&lt;/p&gt;</description>
    </item>
    <item>
      <title>鱼骨chat法</title>
      <link>https://blog.decglu.uk/posts/fishbone-chat/</link>
      <pubDate>Sun, 24 May 2026 17:43:41 +0800</pubDate>
      <guid>https://blog.decglu.uk/posts/fishbone-chat/</guid>
      <description>&lt;p&gt;用 AI 编程助手写代码，最让人头疼的问题之一是&lt;strong&gt;上下文污染&lt;/strong&gt;——主线讨论越来越长，早期的废弃方案、跑偏的对话开始干扰模型的判断，回答质量也跟着劣化。&lt;/p&gt;
&lt;p&gt;我现在用一种叫「鱼骨 Chat 法」的方式来应对这个问题。&lt;/p&gt;
&lt;p&gt;思路很简单：以鱼骨图为隐喻，&lt;strong&gt;主干是一个贯穿始终的主线 session&lt;/strong&gt;，负责记录整体设计思路、模块划分和关键决策；&lt;strong&gt;每一根鱼刺是一个独立的子 session&lt;/strong&gt;，只处理一个具体问题——比如某个函数的实现、一个报错的调试、或者一段逻辑的优化。子问题解决后，把结论带回主线 session 即可，那根鱼刺的使命就完成了。&lt;/p&gt;
&lt;p&gt;这样做有几个好处：子 session 上下文干净，模型不会被无关信息干扰；主线 session 始终保持高层视角，不会因为陷入细节而失去方向；出问题时也方便定位，每个 session 职责单一，回溯很直观。&lt;/p&gt;
&lt;p&gt;本质上这是一种&lt;strong&gt;关注点分离&lt;/strong&gt;在对话管理上的应用。AI 工具的上下文窗口是有限资源，像管理代码模块一样管理它，会顺手很多。&lt;/p&gt;</description>
    </item>
    <item>
      <title>黄山奇石</title>
      <link>https://blog.decglu.uk/posts/huangshan-strange-rock/</link>
      <pubDate>Fri, 10 Apr 2026 23:46:08 +0800</pubDate>
      <guid>https://blog.decglu.uk/posts/huangshan-strange-rock/</guid>
      <description>&lt;ul&gt;
&lt;li&gt;vibe coding 派还在 code&lt;/li&gt;
&lt;li&gt;你说什么？&lt;/li&gt;
&lt;li&gt;哦，老爷子，你看那：vibe-coding-派-还-在-code&lt;/li&gt;
&lt;li&gt;老王啊……我说张主管啊，怎么这种标语现在还留着？……八股余孽嘛，赶紧找人清理掉&lt;/li&gt;
&lt;li&gt;算了，算了，留着也好，以示警世。&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    <item>
      <title>分布式系统一致性</title>
      <link>https://blog.decglu.uk/posts/distributed-system-consistency/</link>
      <pubDate>Tue, 24 Feb 2026 22:20:41 +0800</pubDate>
      <guid>https://blog.decglu.uk/posts/distributed-system-consistency/</guid>
      <description>&lt;p&gt;在分布式系统中，一致性模型定义了多节点间数据更新的可见顺序与实时性，是权衡性能、可用性和正确性的核心。四个经典模型从强到弱依次为：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;线性一致性（Linearizability）&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;顺序一致性（Sequential Consistency）&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;因果一致性（Causal Consistency）&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;最终一致性（Eventual Consistency）&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;越&lt;strong&gt;强&lt;/strong&gt;的一致性模型对系统的性能和&lt;strong&gt;可用性&lt;/strong&gt;要求越高，实际工程需要根据业务场景取舍。&lt;/p&gt;
&lt;h2 id=&#34;线性一致性&#34;&gt;线性一致性&lt;/h2&gt;
&lt;p&gt;每个操作在现实中需要一段时间才能完成，从逻辑上的“调用（call）开始”到“返回（return）结束”。但在这期间某个瞬间，该操作&lt;strong&gt;原子性地生效&lt;/strong&gt;了，并被其他参与者（线程、节点等）立刻感知到这个变化。&lt;/p&gt;
&lt;p&gt;线性一致性保证了系统对外表现得像只有单一副本，无论 client 访问哪个节点，读取到的数据都是一致的。在 Raft 这样的共识协议中，一个操作必须经过多数节点确认，也就是达成共识才能生效，也就对应了操作原子性生效的那个瞬间。&lt;/p&gt;
&lt;p&gt;在 CAP 理论中，线性一致对应 $C$（一致性）。当网络分区（$P$）发生时，系统必须拒绝请求而不是返回可能过期的数据，因此牺牲了可用性（$A$）。Raft、ZooKeeper 等走的就是 CP 优先的道路。&lt;/p&gt;
&lt;p&gt;举个例子，用户 A 转账给用户 B 100元，B 立刻查询账户余额必须多出100元而不能是旧值。如果银行网络故障，必须拒绝这个请求，防止写入脏数据。&lt;/p&gt;
&lt;h2 id=&#34;顺序一致性&#34;&gt;顺序一致性&lt;/h2&gt;
&lt;p&gt;顺序一致性比线性一致性稍弱。它要求存在一个操作的全局总序，在这个总序里：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一个参与者内的操作保持程序顺序&lt;/li&gt;
&lt;li&gt;所有参与者看到的内存操作顺序是一致的，但&lt;strong&gt;不要求&lt;/strong&gt;这个顺序与真实时钟一致。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;也就是说，操作可以看起来“乱序”发生，但只要所有参与者看到的顺序一致即可。&lt;/p&gt;
&lt;p&gt;这点区别其实影响很大。线性一致中，节点 A 在 $T_1$ 完成了写入，节点 B 在 $T_2$ 读取，那么节点 B 必须能读到这个写入。但是顺序一致中不保证，只保证所有参与者看到相同的结果。&lt;/p&gt;
&lt;p&gt;举个例子，初始 &lt;code&gt;x=0, y=0&lt;/code&gt;&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Thread 1: x=1 r1=y
Thread 2: y=1 r2=x
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;最终结果应该为：&lt;code&gt;r1=1, r2=1&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;所以可能的合法的执行顺序只有两种：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;T1 执行完两条后，T2 执行两条，T2 看到 &lt;code&gt;x=1, r2=1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;T2 执行完两条后，T1 执行两条，T1 看到 &lt;code&gt;y=1, r1=1&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;不符合最终结果一致的执行顺序则不符合顺序一致性。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Linux C/C&#43;&#43; IO多路复用</title>
      <link>https://blog.decglu.uk/posts/linux-c-and-cpp-io-multiplexing/</link>
      <pubDate>Thu, 21 Aug 2025 01:07:55 +0800</pubDate>
      <guid>https://blog.decglu.uk/posts/linux-c-and-cpp-io-multiplexing/</guid>
      <description>&lt;p&gt;在linux服务器编写中，为每个连接单独开一个进程/线程不现实，&lt;/p&gt;
&lt;p&gt;我们采用io多路复用。&lt;/p&gt;
&lt;h2 id=&#34;基本tcp-socket模型&#34;&gt;基本TCP socket模型&lt;/h2&gt;
&lt;h2 id=&#34;selectpoll&#34;&gt;select/poll&lt;/h2&gt;
&lt;p&gt;select内部有一个定长(1024)的bitsmap，以存储要监听特定事件的fd。fd从用户空间拷贝到内核，内核里遍历修改一遍后，再把就绪的fd拷贝到用户空间，用户再遍历一遍。&lt;/p&gt;
&lt;p&gt;poll不再用bitsmap，改用动态数组(链表)，不再受限于特定个数的fd。&lt;/p&gt;
&lt;p&gt;但二者其实区别不大，本质都是遍历了两遍，查找有事件的fd时间复杂度为&lt;code&gt;O(n)&lt;/code&gt;，也都需要来回拷贝fd集合。这些操作都很消耗性能。&lt;/p&gt;
&lt;h2 id=&#34;epoll&#34;&gt;epoll&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; sockfd &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;socket&lt;/span&gt;(AF_NET, SOCK_STREAM, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;bind&lt;/span&gt;( ... );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;listen&lt;/span&gt;( ... );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; epoll_fd &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;epoll_create1&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 添加fd
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;epoll_ctl&lt;/span&gt;(epoll_fd, ...);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; (&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; n &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;epoll_wait&lt;/span&gt;( ... );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; ( ... ) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// 有事件的fd
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;epoll不再使用线性的存储结构，改用红黑树（一种自平衡二叉树），增删改的时间复杂度一般为&lt;code&gt;O(log n)&lt;/code&gt;。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;epoll内部维护了一个就绪fd链表，每次&lt;code&gt;epoll_wait&lt;/code&gt;只需要处理链表，然后把所有就绪fd拷贝到用户空间。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;epoll不适用轮询，而是事件驱动。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;epoll有两种触发模式，&lt;strong&gt;ET&lt;/strong&gt;（边缘触发，select/poll不支持）和&lt;strong&gt;LT&lt;/strong&gt;（水平触发），区别主要体现在读上。&lt;/p&gt;
&lt;p&gt;LT模式下，只要可读（socket读缓冲区中有数据），就会触发事件，直到缓冲区被读完。&lt;/p&gt;
&lt;p&gt;ET模式下，仅当数据到来时（缓冲区数据从无到有）触发一次事件，后续将不再触发，即使缓冲区还有数据。&lt;/p&gt;
&lt;p&gt;LT一般搭配阻塞读写，ET一般搭配非阻塞读写。&lt;/p&gt;</description>
    </item>
    <item>
      <title>零拷贝技术</title>
      <link>https://blog.decglu.uk/posts/zero-copy-tech/</link>
      <pubDate>Thu, 21 Aug 2025 01:07:12 +0800</pubDate>
      <guid>https://blog.decglu.uk/posts/zero-copy-tech/</guid>
      <description>&lt;h2 id=&#34;什么是零拷贝&#34;&gt;什么是零拷贝？&lt;/h2&gt;
&lt;p&gt;利用直接内存访问（Direct Memory Access，DMA），消除数据在内存中不必要的拷贝，即零拷贝技术（Zero-Copy）。&lt;/p&gt;
&lt;p&gt;零拷贝不是没有任何复制，而是消除了消耗CPU和内存带宽的不必要的冗余复制。&lt;/p&gt;
&lt;h2 id=&#34;为什么要有零拷贝&#34;&gt;为什么要有零拷贝？&lt;/h2&gt;
&lt;p&gt;传统IO过程：&lt;/p&gt;
&lt;p&gt;用户进程&amp;ndash;&lt;code&gt;read()&lt;/code&gt;&amp;mdash;&amp;gt;CPU(转化为内核态)&amp;ndash;请求读取&amp;mdash;&amp;gt;磁盘&amp;ndash;多次缓冲区拷贝后转化为用户态&amp;mdash;&amp;gt;&lt;code&gt;read()&lt;/code&gt;返回&amp;mdash;-&amp;gt;用户进程&lt;/p&gt;
&lt;p&gt;CPU被大量文件数据占用，多次切换上下文，期间干不了其他事情。并且，多次缓冲区的拷贝极大限制了文件传输性能。&lt;/p&gt;
&lt;p&gt;于是Zero-Copy出现了。&lt;/p&gt;
&lt;h2 id=&#34;优化思路&#34;&gt;优化思路&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;减少上下文切换的次数。传统文件IO（&lt;code&gt;read()&lt;/code&gt;+&lt;code&gt;write()&lt;/code&gt;）有4次上下文切换（&lt;code&gt;read&lt;/code&gt;用户-&amp;gt;内核-&amp;gt;用户，&lt;code&gt;write&lt;/code&gt;用户-&amp;gt;内核-&amp;gt;用户）。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;减少各种缓冲区的拷贝次数。传统读取：磁盘控制器缓冲区-&amp;gt;内核缓冲区-&amp;gt;用户缓冲区，每次拷贝都在消耗时间。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;mmapwrite&#34;&gt;&lt;code&gt;mmap()&lt;/code&gt;+&lt;code&gt;write()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;read()&lt;/code&gt;会把内核缓冲区的数据拷贝到用户缓冲区，为了减少拷贝，换成&lt;code&gt;mmap()&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;mmap&lt;/code&gt;(Memory Map)核心思想是利用虚拟内存管理机制，在进程虚拟地址空间与物理资源（比如文件）之间建立直接的映射关系。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;sys/mman.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;mmap&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; addr[.length],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           size_t length,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; prot,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; flags,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; fd,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           off_t offset);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;使用&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;mmap(&lt;span style=&#34;color:#66d9ef&#34;&gt;nullptr&lt;/span&gt;, file_size, PROT_READ, MAP_PRIVATE, fd, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;把内核缓冲区的数据直接映射到用户缓冲区，这样就避免了一次拷贝。&lt;/p&gt;
&lt;p&gt;然后&lt;code&gt;write()&lt;/code&gt;，把数据直接拷贝到socket缓冲区。由于数据还在内核缓冲区，这些都在内核态发生。&lt;/p&gt;
&lt;p&gt;不过系统调用上下文切换的次数没变。&lt;/p&gt;
&lt;h2 id=&#34;sendfile&#34;&gt;&lt;code&gt;sendfile()&lt;/code&gt;&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-cpp&#34; data-lang=&#34;cpp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;sys/socket.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ssize_t &lt;span style=&#34;color:#a6e22e&#34;&gt;sendfile&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; out_fd, &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; in_fd, off_t &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;offset, size_t count);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;read from &lt;code&gt;in_fd&lt;/code&gt;，然后write to &lt;code&gt;out_fd&lt;/code&gt;。offset是&lt;code&gt;in_fd&lt;/code&gt;内部的偏移量，count是最大处理长度。返回实际处理长度。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;直接减少了一次系统调用，减少上下文切换开销&lt;/li&gt;
&lt;li&gt;直接把数据从内核缓冲区拷贝到socket缓冲区，不再经过用户态&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这时有磁盘-&amp;gt;内核缓冲区-&amp;gt;socket缓冲区-&amp;gt;网卡，共3次拷贝（CPU一次,从内核读缓冲区到socket写缓冲区）。&lt;/p&gt;
&lt;p&gt;如果网卡还支持SD-DMA技术，数据可以绕过sockert缓冲区，从内核缓冲区直接发送到网卡。内核空间缓冲区中对应的数据描述信息（内存地址、地址偏移量）记录到socket缓冲区中，由 DMA 根据内存地址、地址偏移量将数据批量地从内核缓冲区拷贝到网卡设备中（DMA gather copy），这样就又省去了内核空间中仅剩的 1 次 CPU 拷贝操作。&lt;/p&gt;
&lt;h2 id=&#34;splice&#34;&gt;&lt;code&gt;splice()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;sendfile&lt;/code&gt;的局限性是，只能从本地文件的fd发送到socket fd，且在一定程度上依赖硬件支持。&lt;/p&gt;</description>
    </item>
    <item>
      <title>SQL和数据库管理系统（MySQL）</title>
      <link>https://blog.decglu.uk/posts/sql-and-db-management-system-mysql/</link>
      <pubDate>Sat, 02 Aug 2025 15:46:23 +0800</pubDate>
      <guid>https://blog.decglu.uk/posts/sql-and-db-management-system-mysql/</guid>
      <description>&lt;h2 id=&#34;为什么需要数据库&#34;&gt;为什么需要数据库？&lt;/h2&gt;
&lt;p&gt;数据太多，文件搞不定。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;查询复杂&lt;/li&gt;
&lt;li&gt;数据结构混乱难以维护&lt;/li&gt;
&lt;li&gt;文件难以并发处理&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;数据库，&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;结构化数据管理&lt;/li&gt;
&lt;li&gt;高效查询&lt;/li&gt;
&lt;li&gt;并发控制&lt;/li&gt;
&lt;li&gt;数据安全&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;数据库和sql&#34;&gt;数据库和SQL&lt;/h2&gt;
&lt;p&gt;数据库 ：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;关系型数据库&lt;/li&gt;
&lt;li&gt;非关系型数据库&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;SQL是一种管理关系型数据库的语言。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SQL (Structured Query Language)：结构化查询语言&lt;/li&gt;
&lt;li&gt;用于操作关系型数据库：定义数据表，插入/查询/修改/删除数据&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;mysqlsqlitepostgresql&#34;&gt;MySQL？SQLite？PostgreSQL？&lt;/h2&gt;
&lt;p&gt;Database Management System. 是一种软件，不是数据库。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;MySQL         -&amp;gt;          主流服务器端&lt;/li&gt;
&lt;li&gt;SQLite          -&amp;gt;          嵌入式&lt;/li&gt;
&lt;li&gt;PostgreSQL -&amp;gt;          支持复杂查询&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;mysql安装&#34;&gt;MySQL安装&lt;/h2&gt;
&lt;p&gt;Ubuntu&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo apt install mysql-common mysql-client mysql-server
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo systemctl start mysql-server
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo systemctl enable mysql-server &lt;span style=&#34;color:#75715e&#34;&gt;# 开机自启&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Arch&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo pacman -S mariadb
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo mariadb-install-db --user&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;mysql --basedir&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/usr --datadir&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;/var/lib/mysql
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo systemctl start mariadb
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo systemctl enable mariadb
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;开始使用ubuntu&#34;&gt;开始使用（Ubuntu）&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;sudo mysql
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-mysql&#34; data-lang=&#34;mysql&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;CREATE&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;USER&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;new_user&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;@&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;host_name&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;IDENTIFIED&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;BY&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;password115414&amp;#39;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;host_name&lt;/code&gt;=&lt;code&gt;&amp;quot;localhost&amp;quot;&lt;/code&gt; 只能从本地访问&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
