{
  "version": "https://jsonfeed.org/version/1.1",
  "title": "Mark的自留地",
  "home_page_url": "https://markxu.icu",
  "feed_url": "https://markxu.icu/feeds/zh/feed.json",
  "description": "这里是 Mark Xu 的个人网站，记录技术与生活。",
  "language": "zh-CN",
  "authors": [
    {
      "name": "Mark Xu",
      "url": "https://markxu.icu"
    }
  ],
  "items": [
    {
      "id": "https://markxu.icu/blog/future-of-liberal-arts-and-engineering-cn",
      "url": "https://markxu.icu/blog/future-of-liberal-arts-and-engineering-cn",
      "title": "或许我们将来只有文科和工科，看3B1B视频有感",
      "content_text": "今天晚上看了 3Blue1Brown 的《投身数学，从未有过比现在更好的时候》的视频，有些感触，简单记录一下。链接贴在这里，大家可以直接在这里看。 看完整个视频后，我想先用一个吸引眼球暴论开始：如果真达到了 3Blue1Brown 所说的，AI 会比人类所做的所有事情都要更强，那么此后 所有的学习都将会成为文科。 Fun fact，艺术类和文科的英文都是 Art。 所以说，如果在国内说学文科，其实也可以说为学艺术。那么将来数学其实也可以成为一种所谓的“文科”。 将这个条件继续推广，那么所有研究，包括物理、化学，甚至其他所有的理论研究，都可以成为一种文科。 将来就不会区分文和理，而是“文”和“工” 。一个是将理论进行学习，另外一个是把理论落地到实践，和现实世界产生交互。 这个时候，大学就不再成为一种教育水平阶段，而是一种更高级的社团，需要有考核标准入场券的社团。大家进来的都是对学习有热情的，想去学习的，喜欢与具有相同热情的人一起讨论，去 social 去 connect。 大家进入这个社团的初衷，就是因为会被那种带有 passion 的人所感染而加入的，正如我开始建我的博客网站的初衷，也是受到了网上许多同好且付出实践的激励下去做的。这样大学就不再是单纯为了找到更好的工作而不得不耽误的几年时光。 这似乎又回到了17世纪、18世纪的时候，贵族们去研究科学的方式。大家在 AGI 的发展下实现了生产力的发展，加上合理的新的分配方式。因为生产资料不再由固定的资本所有，而是由 AGI 产生。那么将来的生产关系也会变化，分配必然得到改变。 如果有一个良好的分配机制的话。人们就不再会为了生计发愁，就可以去追求自己喜欢的事情。这样喜欢画画的会画画，喜欢运动的去运动，或是喜欢研究数学理论，把理论做成实践，甚至只是传播学习的乐趣，来拉更多人入坑，又或者是简单的教给小孩子们。 其实都变成了一种“服务业”，或者是人们去享受的一种生活方式。 这时候人们去做研究，就会像是《The Craftsman》里面所说的，做好一件事的初衷仅仅是因为想去完成一件事，所以就会把它去做好。 “为了把事情做好而把事情做好”的内心冲动（The desire to do a job well for its own sake） 我当然知道这很理想主义，但是确实听起来很美好，不是吗？ 在面临 AGI 的不断发展之下，或许整个行业，整个社会也都意识到自己将要去改变。结合现在的政策，很多研究生不再需要写一篇论文，而是有了这种卓工的培养机制，其实都是在为了适应社会发展而产生的一些变化。 在我看来，在社会发展面前，以不变应万变的事情很少发生，甚至在历史规律面前，这种事情几乎没有发生过，我们总之是要改变的，只有不断改变，我们才能用新思路去解决新问题。 如果不知道变成什么样，为什么不把它想的好一点呢？ ——写于被线代折磨的一晚上（来自语音转文字）",
      "content_html": "<p>今天晚上看了 3Blue1Brown 的《投身数学，从未有过比现在更好的时候》的视频，有些感触，简单记录一下。链接贴在这里，大家可以直接在这里看。</p>\n<p><VideoEmbed\n  url=\"https://www.bilibili.com/video/BV1HBnH6JEAZ/?share_source=copy_web&vd_source=3446a02e4deef26e9b4161a2ba03a1e3\"\n  title=\"投身数学，从未有过比现在更好的时候\"\n/></p>\n<p>看完整个视频后，我想先用一个吸引眼球暴论开始：如果真达到了 3Blue1Brown 所说的，AI 会比人类所做的所有事情都要更强，那么此后<strong>所有的学习都将会成为文科。</strong></p>\n<p>Fun fact，艺术类和文科的英文都是 Art。</p>\n<p>所以说，如果在国内说学文科，其实也可以说为学艺术。那么将来数学其实也可以成为一种所谓的“文科”。</p>\n<p>将这个条件继续推广，那么所有研究，包括物理、化学，甚至其他所有的理论研究，都可以成为一种文科。<strong>将来就不会区分文和理，而是“文”和“工”</strong>。一个是将理论进行学习，另外一个是把理论落地到实践，和现实世界产生交互。</p>\n<p>这个时候，大学就不再成为一种教育水平阶段，而是一种更高级的社团，需要有考核标准入场券的社团。大家进来的都是对学习有热情的，想去学习的，喜欢与具有相同热情的人一起讨论，去 social 去 connect。</p>\n<p>大家进入这个社团的初衷，就是因为会被那种带有 passion 的人所感染而加入的，正如我开始建我的博客网站的初衷，也是受到了网上许多同好且付出实践的激励下去做的。这样大学就不再是单纯为了找到更好的工作而不得不耽误的几年时光。</p>\n<p>这似乎又回到了17世纪、18世纪的时候，贵族们去研究科学的方式。大家在 AGI 的发展下实现了生产力的发展，加上合理的新的分配方式。因为生产资料不再由固定的资本所有，而是由 AGI 产生。那么将来的生产关系也会变化，分配必然得到改变。</p>\n<p>如果有一个良好的分配机制的话。人们就不再会为了生计发愁，就可以去追求自己喜欢的事情。这样喜欢画画的会画画，喜欢运动的去运动，或是喜欢研究数学理论，把理论做成实践，甚至只是传播学习的乐趣，来拉更多人入坑，又或者是简单的教给小孩子们。</p>\n<p>其实都变成了一种“服务业”，或者是人们去享受的一种生活方式。</p>\n<p>这时候人们去做研究，就会像是《The Craftsman》里面所说的，做好一件事的初衷仅仅是因为想去完成一件事，所以就会把它去做好。</p>\n<blockquote>\n<p>“为了把事情做好而把事情做好”的内心冲动（The desire to do a job well for its own sake）</p>\n</blockquote>\n<p>我当然知道这很理想主义，但是确实听起来很美好，不是吗？</p>\n<p>在面临 AGI 的不断发展之下，或许整个行业，整个社会也都意识到自己将要去改变。结合现在的政策，很多研究生不再需要写一篇论文，而是有了这种卓工的培养机制，其实都是在为了适应社会发展而产生的一些变化。</p>\n<p>在我看来，在社会发展面前，以不变应万变的事情很少发生，甚至在历史规律面前，这种事情几乎没有发生过，我们总之是要改变的，只有不断改变，我们才能用新思路去解决新问题。</p>\n<p>如果不知道变成什么样，为什么不把它想的好一点呢？</p>\n<p>——写于被线代折磨的一晚上（来自语音转文字）</p>\n",
      "summary": "今天晚上看完了 3Blue1Brown 的《投身数学，从未有过比现在更好的时候》的视频，有些感触，简单记录下。",
      "date_published": "2026-10-25T00:00:00.000Z",
      "image": "https://img.markxu.icu/imge1ca44fe-e495-4e4f-951f-46ea158d947b.png",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/blog/why-unix-signal-sender-is-called-kill-cn",
      "url": "https://markxu.icu/blog/why-unix-signal-sender-is-called-kill-cn",
      "title": "从408操作系统到生产环境：为什么发信号的函数叫 kill，而不是send？",
      "content_text": "最近在复习操作系统 408 课程的“进程”这一章时，复习到进程间通信（IPC）的信号机制，这一次由于是强化，所以很认真的在看书。 我当时整个人一愣：“等等，进程之间发信号，系统调用居然叫 kill ？” 不对吧，难道进程之间通信都是为了杀死对方？就打个比方：给朋友发了一条“下楼来玩”的消息，结果这个操作居然被别人叫做 。这也太离谱了，确实反直觉，于是我就稍微深入了下，去探索了探索。 为什么 UNIX 祖师爷们要起这么个容易让人误解的名字？今天我们就来扒一扒这个陪伴了我们几十年的“历史遗留命名”，顺便看看它在日常开发和面试中到底意味着什么。 被名字误导的“强杀” 在学习操作系统时，我第一次看到 这个系统调用或终端的 命令，都会产生一种理所当然的认知：它的唯一职责就是“干掉进程”。 平时我们在排查线上故障或调试程序时，习惯在终端敲下 甚至是暴力的 ，伴随着进程的瞬间消失，我自然而然地把这个操作等同于程序的终结方式。 但事实上，我的这种直觉隐藏了一个极大的技术误区。 的本质是 向指定的进程投递一个信号（Signal） ，而不是字面意义上的“杀”。终止进程只是进程在收到特定信号时的 默认行为 ，而不是这个系统调用本身的功能限制。换句话说， 仅仅是一种异步通知的 通信机制 ，而“杀死”只是众多信号处理方式中的一种默认结果。 究竟干了什么？ 我们先来看看 平时都该怎么用？ 在 C 语言中， 系统调用的原型非常简单： ：目标进程的身份证号。 ：你要发送的信号编号（比如 、 等）。如果 传 （称为空信号）， 并不发送信号，而是用来 探测该进程是否存在 以及当前用户是否有权限向它发信号（常用于写守护进程时的探活）。 一个简单的 C 语言示例 下面这段代码展示了如何向指定的进程发送一个自定义信号 ，以及如何检测进程状态： 在这里， 只是把信号投递到内核的进程控制块（PCB）中，完成了一次轻量级的事件通知。 历史谜题：为什么叫 而不叫 ？ 既然它的本质是发信号，为什么不叫 或者简称为 呢？这似乎会更符合直觉些。 这就要把时间拨回到上世纪 70 年代的 UNIX 早期蛮荒时代 了。 历史局限与初衷 ：在最初的 UNIX 设计中，进程间通信远没有现在这么复杂。早期的信号种类极少，设计出来的唯一目的、最核心的场景就是—— 终止那些失控、死循环或者占用资源不放的进程 。因此，当时这个系统调用的直观使命就是“干掉它”，命名为 在当时极其贴切。 POSIX 标准的路径依赖 ：随着系统演进，人们发现这种“异步通知机制”太好用了，不仅能用来杀进程，还能用来通知状态改变、重载配置、子进程退出等。于是信号的种类越来越多，功能也扩展成了通用的 IPC。但此时 这个名字已经在无数的系统源码和早期书籍中扎根。为了保持向后兼容（Backward Compatibility），POSIX 标准最终把这个名字保留了下来。 与数据传输型 API 的区分 ：像 、 这类名字，在网络编程和管道中通常伴随着 大块字节流数据的传输 。而传统的 UNIX 信号极其轻量，它 不携带额外的数据负载 （现代虽有 可以传少量数据，但属于扩展），它只传递一个“发生了某件事”的纯粹事件通知。因此，不用 也是为了避免和数据传输混淆。 常见信号速查/对照 在某些时候到开发和面试中，有些高频信号是需要了解的。这里我让AI帮我总结了下，也方便我日后使用： 信号名称 默认编号 默认行为 典型应用场景 / 含义 --- --- --- --- SIGHUP 1 终止进程 终端断开时发送；现代常被 Nginx/Daemon 借用为 “重载配置文件” SIGINT 2 终止进程 Ctrl + C ，中断前台进程 SIGQUIT 3 核心转储并终止 Ctrl + ，不仅退出还留下 core dump 文件供调试 SIGKILL 9 强杀进程 不可捕获、不可忽略 。内核直接回收，程序连说“再见”的机会都没有 SIGSEGV 11 核心转储并终止 段错误（非法内存访问，比如野指针、越界） SIGPIPE 13 终止进程 向一个没有读端的管道/socket 继续写数据触发 SIGALRM 14 终止进程 定时器超时（ 函数触发） SIGTERM 15 终止进程 软件终止 （默认的 命令发的就是它）。 可以被捕获 ，是实现优雅退出的首选 SIGSTOP 19 暂停进程 不可捕获、不可忽略 。暂停进程执行（类似按暂停键） SIGCONT 18 继续进程 让被 或其他原因暂停的进程继续运行 SIGUSR1/2 30/31 终止进程 用户自定义信号，开发者可以自由赋予业务含义 这还有ai自顾自的多写了一个考试题，也放在这里当做记录： 💡 面试常考高频题 ： 为什么 9 和 19 不能被捕获或忽略？ 答 ：因为它们是内核给管理员留的“绝对控制权”。如果允许用户代码捕获 ，万一写出一个死循环去捕获并不做处理，系统将再也无法通过常规手段杀死这个恶性进程，导致系统彻底失控。 实际应用场景 这个指令平时又会在哪里使用呢？这里我也简单让AI帮我总结下： Shell 中的日常运维 ：默认发送 SIGTERM 15 。给进程一个礼貌的提示：“兄弟，差不多得了，赶紧把手头的工作收尾然后退出吧。” ：发送 SIGKILL 9 。“别废话了，立刻给爷消失！”（注意：频繁用 容易导致数据库事务未提交、临时文件没删除、锁没释放等灾难）。 ：发送 SIGHUP 1 。在 Nginx 等服务器中，常用于热重载：主进程收到后重新加载配置并平滑重启 worker 进程，业务零中断。 后端开发与优雅退出（Graceful Shutdown） 在用 Go、Java、Node.js 编写 Web 服务时，当我们用 Docker 停止容器（发送 ）或者在终端按下 （发送 ），程序不能直接暴毙。 合格的后端框架都会 监听这些终止信号 ： 收到 后，停止接收新的 HTTP 请求。 把当前正在处理的请求处理完、写入数据库。 断开 Redis、MySQL 连接，安全释放资源，然后优雅退出。 简单的进程间通信 IPC 在一些多进程架构的守护程序中（如 Master-Worker 模式），主进程可以通过 来通知子进程：“日志文件已经轮转（Log Rotate）了，请重新打开日志文件句柄。” 普通开发者需要注意什么？ 即使你平时写的是上层业务代码，不直接调用系统级的 ，以下几个由信号引发的“暗礁”你也绝对踩过或者迟早会踩到： Ctrl+C 的威力 ：你在终端跑一个耗时脚本，手一抖按了 ，本质上就是终端驱动向前台进程组发送了 。 僵尸进程与 ：父进程派生了子进程，子进程死后如果父进程没有通过 回收其状态，子进程就会变成僵尸进程（Zombie）。而当子进程退出时，内核会向父进程发送 信号，很多高性能框架正是通过异步捕获 来高效回收子进程的。 系统调用被中断 ：如果你的程序正在进行阻塞的 I/O 操作（比如 某个 socket），此时刚好收到一个信号并进入了信号处理函数，那么这个 可能会被打断并返回 ，同时 被设为 。写底层网络库时，必须显式处理这种“被信号中断”的情况（通常需要外层套一个 循环重试）。 异步信号安全 Async-Signal-Safe ：在编写信号处理函数（Signal Handler）时，里面能做的事情极其有限。千万不要在信号处理函数里调用 、 等非线程安全/非异步信号安全的函数，否则极易引发难以排查的死锁或内存崩溃。 信号不排队（非实时信号会丢失） ：传统的标准信号（1-31）是不排队的。如果短时间内同一个信号连续发给进程多次，进程可能只感知到一次。如果业务上要求绝对不能漏掉任何一次事件，标准信号是无法胜任的（需要使用实时信号 RT signals）。 总结 学完这一圈，我才真正消化了进程之间通信的函数，通过简单的知识拓展，也让我对进程通信有了更深刻的理解。 但话说，这种误解确实吓人，如果不是有ai帮忙总结，回答我的问题，我估计一时半会儿也不想去自己研究为什么通信之间的函数为什么是 ，没准就自顾自的认为就是进程之间通信全是为了终结对方。也不知道这种历史债还有多少... 希望这篇笔记也能帮正在啃 408 操作系统或者被 Linux 信号折腾得头皮发麻的开发者们，彻底理清这个历史包袱背后的技术真相。",
      "content_html": "<p>最近在复习操作系统 408 课程的“进程”这一章时，复习到进程间通信（IPC）的信号机制，这一次由于是强化，所以很认真的在看书。</p>\n<p>我当时整个人一愣：“等等，进程之间发信号，系统调用居然叫 kill()？”</p>\n<p>不对吧，难道进程之间通信都是为了杀死对方？就打个比方：给朋友发了一条“下楼来玩”的消息，结果这个操作居然被别人叫做 <code>execute_friend(好兄弟)</code>。这也太离谱了，确实反直觉，于是我就稍微深入了下，去探索了探索。</p>\n<p>为什么 UNIX 祖师爷们要起这么个容易让人误解的名字？今天我们就来扒一扒这个陪伴了我们几十年的“历史遗留命名”，顺便看看它在日常开发和面试中到底意味着什么。</p>\n<hr>\n<h2>被名字误导的“强杀”</h2>\n<p>在学习操作系统时，我第一次看到 <code>kill()</code> 这个系统调用或终端的 <code>kill</code> 命令，都会产生一种理所当然的认知：它的唯一职责就是“干掉进程”。</p>\n<p>平时我们在排查线上故障或调试程序时，习惯在终端敲下 <code>kill &lt;pid&gt;</code> 甚至是暴力的 <code>kill -9 &lt;pid&gt;</code>，伴随着进程的瞬间消失，我自然而然地把这个操作等同于程序的终结方式。</p>\n<p>但事实上，我的这种直觉隐藏了一个极大的技术误区。</p>\n<p><code>kill()</code> 的本质是<strong>向指定的进程投递一个信号（Signal）</strong>，而不是字面意义上的“杀”。终止进程只是进程在收到特定信号时的<strong>默认行为</strong>，而不是这个系统调用本身的功能限制。换句话说，<code>kill</code> 仅仅是一种异步通知的<strong>通信机制</strong>，而“杀死”只是众多信号处理方式中的一种默认结果。</p>\n<h2><code>kill(pid, sig)</code> 究竟干了什么？</h2>\n<p>我们先来看看<code>kill()</code>平时都该怎么用？</p>\n<p>在 C 语言中，<code>kill()</code> 系统调用的原型非常简单：</p>\n<pre><code>#include &lt;sys/types.h&gt;\n#include &lt;signal.h&gt;\n\nint kill(pid_t pid, int sig);\n</code></pre>\n<ul>\n<li><strong><code>pid</code></strong>：目标进程的身份证号。</li>\n<li><strong><code>sig</code></strong>：你要发送的信号编号（比如 <code>SIGTERM</code>、<code>SIGUSR1</code> 等）。如果 <code>sig</code> 传 <code>0</code>（称为空信号），<code>kill()</code> 并不发送信号，而是用来<strong>探测该进程是否存在</strong>以及当前用户是否有权限向它发信号（常用于写守护进程时的探活）。</li>\n</ul>\n<h3>一个简单的 C 语言示例</h3>\n<p>下面这段代码展示了如何向指定的进程发送一个自定义信号 (<code>SIGUSR1</code>)，以及如何检测进程状态：</p>\n<pre><code class=\"language-c\">#include &lt;stdio.h&gt;\n#include &lt;stdlib.h&gt;\n#include &lt;sys/types.h&gt;\n#include &lt;signal.h&gt;\n#include &lt;unistd.h&gt;\n\nint main(int argc, char *argv[]){\n    if (argc != 2) {\n        fprintf(stderr, &quot;Usage: %s &lt;pid&gt;\\n&quot;, argv[0]);\n        exit(1);\n    }\n\n    pid_t target_pid = atoi(argv[1]);\n\n    // 1. 探测进程是否存在\n    if (kill(target_pid, 0) == 0) {\n        printf(&quot;进程 %d 存活，正在发送自定义信号 SIGUSR1...\\n&quot;, target_pid);\n        // 2. 发送 SIGUSR1 信号\n        kill(target_pid, SIGUSR1);\n    } else {\n        perror(&quot;进程不存在或无权限&quot;);\n    }\n\n    return 0;\n}\n</code></pre>\n<p>在这里，<code>kill()</code> 只是把信号投递到内核的进程控制块（PCB）中，完成了一次轻量级的事件通知。</p>\n<h2>历史谜题：为什么叫 <code>kill</code> 而不叫 <code>send</code>？</h2>\n<p>既然它的本质是发信号，为什么不叫 <code>send_signal()</code> 或者简称为 <code>send()</code> 呢？这似乎会更符合直觉些。</p>\n<p>这就要把时间拨回到上世纪 70 年代的 <strong>UNIX 早期蛮荒时代</strong>了。</p>\n<ol>\n<li><strong>历史局限与初衷</strong>：在最初的 UNIX 设计中，进程间通信远没有现在这么复杂。早期的信号种类极少，设计出来的唯一目的、最核心的场景就是——<strong>终止那些失控、死循环或者占用资源不放的进程</strong>。因此，当时这个系统调用的直观使命就是“干掉它”，命名为 <code>kill</code> 在当时极其贴切。</li>\n<li><strong>POSIX 标准的路径依赖</strong>：随着系统演进，人们发现这种“异步通知机制”太好用了，不仅能用来杀进程，还能用来通知状态改变、重载配置、子进程退出等。于是信号的种类越来越多，功能也扩展成了通用的 IPC。但此时 <code>kill()</code> 这个名字已经在无数的系统源码和早期书籍中扎根。为了保持向后兼容（Backward Compatibility），POSIX 标准最终把这个名字保留了下来。</li>\n<li><strong>与数据传输型 API 的区分</strong>：像 <code>send()</code>、<code>sendto()</code> 这类名字，在网络编程和管道中通常伴随着<strong>大块字节流数据的传输</strong>。而传统的 UNIX 信号极其轻量，它<strong>不携带额外的数据负载</strong>（现代虽有 <code>sigqueue</code> 可以传少量数据，但属于扩展），它只传递一个“发生了某件事”的纯粹事件通知。因此，不用 <code>send</code> 也是为了避免和数据传输混淆。</li>\n</ol>\n<h2>常见信号速查/对照</h2>\n<p>在某些时候到开发和面试中，有些高频信号是需要了解的。这里我让AI帮我总结了下，也方便我日后使用：</p>\n<table>\n<thead>\n<tr>\n<th><strong>信号名称</strong></th>\n<th><strong>默认编号</strong></th>\n<th><strong>默认行为</strong></th>\n<th><strong>典型应用场景 / 含义</strong></th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>SIGHUP</strong></td>\n<td>1</td>\n<td>终止进程</td>\n<td>终端断开时发送；现代常被 Nginx/Daemon 借用为**“重载配置文件”**</td>\n</tr>\n<tr>\n<td><strong>SIGINT</strong></td>\n<td>2</td>\n<td>终止进程</td>\n<td><strong>Ctrl + C</strong>，中断前台进程</td>\n</tr>\n<tr>\n<td><strong>SIGQUIT</strong></td>\n<td>3</td>\n<td>核心转储并终止</td>\n<td>**Ctrl + **，不仅退出还留下 core dump 文件供调试</td>\n</tr>\n<tr>\n<td><strong>SIGKILL</strong></td>\n<td>9</td>\n<td><strong>强杀进程</strong></td>\n<td><strong>不可捕获、不可忽略</strong>。内核直接回收，程序连说“再见”的机会都没有</td>\n</tr>\n<tr>\n<td><strong>SIGSEGV</strong></td>\n<td>11</td>\n<td>核心转储并终止</td>\n<td>段错误（非法内存访问，比如野指针、越界）</td>\n</tr>\n<tr>\n<td><strong>SIGPIPE</strong></td>\n<td>13</td>\n<td>终止进程</td>\n<td>向一个没有读端的管道/socket 继续写数据触发</td>\n</tr>\n<tr>\n<td><strong>SIGALRM</strong></td>\n<td>14</td>\n<td>终止进程</td>\n<td>定时器超时（<code>alarm()</code> 函数触发）</td>\n</tr>\n<tr>\n<td><strong>SIGTERM</strong></td>\n<td>15</td>\n<td>终止进程</td>\n<td><strong>软件终止</strong>（默认的 <code>kill</code> 命令发的就是它）。<strong>可以被捕获</strong>，是实现优雅退出的首选</td>\n</tr>\n<tr>\n<td><strong>SIGSTOP</strong></td>\n<td>19</td>\n<td><strong>暂停进程</strong></td>\n<td><strong>不可捕获、不可忽略</strong>。暂停进程执行（类似按暂停键）</td>\n</tr>\n<tr>\n<td><strong>SIGCONT</strong></td>\n<td>18</td>\n<td>继续进程</td>\n<td>让被 <code>SIGSTOP</code> 或其他原因暂停的进程继续运行</td>\n</tr>\n<tr>\n<td><strong>SIGUSR1/2</strong></td>\n<td>30/31</td>\n<td>终止进程</td>\n<td>用户自定义信号，开发者可以自由赋予业务含义</td>\n</tr>\n</tbody>\n</table>\n<p>这还有ai自顾自的多写了一个考试题，也放在这里当做记录：</p>\n<blockquote>\n<p>💡 <strong>面试常考高频题</strong>：</p>\n<p>为什么 <code>SIGKILL</code> (9) 和 <code>SIGSTOP</code> (19) 不能被捕获或忽略？</p>\n<p><strong>答</strong>：因为它们是内核给管理员留的“绝对控制权”。如果允许用户代码捕获 <code>SIGKILL</code>，万一写出一个死循环去捕获并不做处理，系统将再也无法通过常规手段杀死这个恶性进程，导致系统彻底失控。</p>\n</blockquote>\n<h2>实际应用场景</h2>\n<p><code>kill</code> 这个指令平时又会在哪里使用呢？这里我也简单让AI帮我总结下：</p>\n<h3>1. Shell 中的日常运维</h3>\n<ul>\n<li><code>kill &lt;pid&gt;</code>：默认发送 <strong>SIGTERM (15)</strong>。给进程一个礼貌的提示：“兄弟，差不多得了，赶紧把手头的工作收尾然后退出吧。”</li>\n<li><code>kill -9 &lt;pid&gt;</code>：发送 <strong>SIGKILL (9)</strong>。“别废话了，立刻给爷消失！”（注意：频繁用 <code>9</code> 容易导致数据库事务未提交、临时文件没删除、锁没释放等灾难）。</li>\n<li><code>kill -HUP &lt;pid&gt;</code>：发送 <strong>SIGHUP (1)</strong>。在 Nginx 等服务器中，常用于热重载：主进程收到后重新加载配置并平滑重启 worker 进程，业务零中断。</li>\n</ul>\n<h3>2. 后端开发与优雅退出（Graceful Shutdown）</h3>\n<p>在用 Go、Java、Node.js 编写 Web 服务时，当我们用 Docker 停止容器（发送 <code>SIGTERM</code>）或者在终端按下 <code>Ctrl+C</code>（发送 <code>SIGINT</code>），程序不能直接暴毙。<br>\n合格的后端框架都会<strong>监听这些终止信号</strong>：</p>\n<ul>\n<li>收到 <code>SIGTERM</code> 后，停止接收新的 HTTP 请求。</li>\n<li>把当前正在处理的请求处理完、写入数据库。</li>\n<li>断开 Redis、MySQL 连接，安全释放资源，然后优雅退出。</li>\n</ul>\n<h3>3. 简单的进程间通信 (IPC)</h3>\n<p>在一些多进程架构的守护程序中（如 Master-Worker 模式），主进程可以通过 <code>kill(worker_pid, SIGUSR1)</code> 来通知子进程：“日志文件已经轮转（Log Rotate）了，请重新打开日志文件句柄。”</p>\n<h2>普通开发者需要注意什么？</h2>\n<p>即使你平时写的是上层业务代码，不直接调用系统级的 <code>kill()</code>，以下几个由信号引发的“暗礁”你也绝对踩过或者迟早会踩到：</p>\n<ol>\n<li><strong>Ctrl+C 的威力</strong>：你在终端跑一个耗时脚本，手一抖按了 <code>Ctrl+C</code>，本质上就是终端驱动向前台进程组发送了 <code>SIGINT</code>。</li>\n<li><strong>僵尸进程与 <code>SIGCHLD</code></strong>：父进程派生了子进程，子进程死后如果父进程没有通过 <code>wait()</code> 回收其状态，子进程就会变成僵尸进程（Zombie）。而当子进程退出时，内核会向父进程发送 <strong><code>SIGCHLD</code></strong> 信号，很多高性能框架正是通过异步捕获 <code>SIGCHLD</code> 来高效回收子进程的。</li>\n<li><strong>系统调用被中断 (<code>EINTR</code>)</strong>：如果你的程序正在进行阻塞的 I/O 操作（比如 <code>read</code> 某个 socket），此时刚好收到一个信号并进入了信号处理函数，那么这个 <code>read</code> 可能会被打断并返回 <code>1</code>，同时 <code>errno</code> 被设为 <code>EINTR</code>。写底层网络库时，必须显式处理这种“被信号中断”的情况（通常需要外层套一个 <code>while</code> 循环重试）。</li>\n<li><strong>异步信号安全 (Async-Signal-Safe)</strong>：在编写信号处理函数（Signal Handler）时，里面能做的事情极其有限。千万不要在信号处理函数里调用 <code>printf()</code>、<code>malloc()</code> 等非线程安全/非异步信号安全的函数，否则极易引发难以排查的死锁或内存崩溃。</li>\n<li><strong>信号不排队（非实时信号会丢失）</strong>：传统的标准信号（1-31）是不排队的。如果短时间内同一个信号连续发给进程多次，进程可能只感知到一次。如果业务上要求绝对不能漏掉任何一次事件，标准信号是无法胜任的（需要使用实时信号 RT signals）。</li>\n</ol>\n<h2>总结</h2>\n<p>学完这一圈，我才真正消化了进程之间通信的函数，通过简单的知识拓展，也让我对进程通信有了更深刻的理解。</p>\n<p>但话说，这种误解确实吓人，如果不是有ai帮忙总结，回答我的问题，我估计一时半会儿也不想去自己研究为什么通信之间的函数为什么是<code>kill()</code>，没准就自顾自的认为就是进程之间通信全是为了终结对方。也不知道这种历史债还有多少...</p>\n<p>希望这篇笔记也能帮正在啃 408 操作系统或者被 Linux 信号折腾得头皮发麻的开发者们，彻底理清这个历史包袱背后的技术真相。</p>\n",
      "summary": "在408强化的阶段，我注意到进程之间的通信函数名是 kill()，让我不禁好奇其具体含义。",
      "date_published": "2026-10-22T00:00:00.000Z",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/blog/why-does-some-website-has-www-2-cn",
      "url": "https://markxu.icu/blog/why-does-some-website-has-www-2-cn",
      "title": "为什么有的网站有 www，有的没有？-现代配置篇",
      "content_text": "封面图：Tim Berners-Lee（蒂姆·伯纳斯-李）在2009年万维网诞生20周年的庆祝活动上，于欧洲核子研究中心（CERN）与那台具有历史意义的NeXT计算机重逢。他曾使用这台计算机开发并运行了世界上第一个Web服务器、多媒体浏览器以及网页编辑器。图片来源：CERN 上一篇讲了 是怎么来的——它是 Tim Berners-Lee 建议的命名惯例，也是早期区分服务的必要手段。 但是到了今天，Web 从“一台机器跑一个服务”变成“一个 IP 承载无数网站”之后， 为什么不再是必需品？部署网站时那些让人头疼的 DNS 细节又该怎么处理？我打算在这篇讲一讲。 为什么后来很多网站又不用 了？ 因为互联网的使用方式变了。 当网站还是一台机器提供一个服务的时候， 很有用，可以把 Web 服务和邮件服务区分开，方便管理。 后来随着机器的性能进步，管理也逐渐变得简单和容易维护。尤其是后续虚拟主机、HTTP 的 请求头（RFC 9110）、反向代理、CDN 和云平台逐渐普及，使得同一个 IP 地址可以根据域名把请求转给不同的网站，域名本身也就不再需要承担说明机器的使用用途的功能。 这也与上文Tim在回答Why www？中最后的想法一致。 与此同时， 比 短四个字符。这也就意味着出现在海报、名片、视频口播、广告牌和用户手动输入的每一个地方都更简短。这很明显更有利于宣传自己的品牌，让大众一眼注意到自己的品牌，于是越来越多网站选择把裸域，也就是不带子域名的 ，作为对外展示的地址。 但这也不代表 技术上落伍了。 保留 有一些现实好处。它明确告诉网络基础设施：这是 Web 站点；以后如果要把 、 或其他服务拆出去，边界会更为清楚。Cookie 的作用范围RFC 6265）也可以更谨慎地控制：放在 的站点，不会天然把只属于站点的主机级 Cookie 发给 。 真正麻烦的地方：裸域和 CNAME 讲到这里，可能会觉得既然 只是一个子域名，那不用就好了。但是事情在部署网站时会稍微复杂一点，尤其当是你第一次尝试 CDN、托管平台或云服务商的时候。 DNS 里最常见的两种记录，可以先这样理解： A 记录直接把名字指向 IP 地址。CNAME（RFC 1034 §3.6.2、RFC 1035）则说：这个名字请按照另一个名字继续查。 CNAME 很适合接入托管平台。平台换了服务器 IP，你不需要每天改自己的 DNS，只要继续指向平台提供的域名即可。但按照传统 DNS 模型，一个名字如果设了 CNAME，就不能同时拥有其他类型的记录——RFC 2181 §10.1 对此做了明确说明。 问题在于，裸域 不是一个普通的子域名。这个名字本身需要承载整个域的 NS、SOA 等基础记录；很多时候还会放邮件用的 MX、域名验证用的 TXT。按照传统规则，裸域不能简单地变成一个 CNAME，否则这些记录就没地方共存了。 这也是为什么过去很多托管平台会告诉你：请把 配成 CNAME，然后让裸域做一次跳转。 作为普通子域名，可以很自然地指向平台；裸域则因为 DNS 的历史结构，处理起来没有那么直接。 现代 DNS 服务商怎么解决这个问题？ 后来 DNS 服务商提供了不同名字的解决方案，例如 ALIAS、ANAME 或 CNAME flattening。它们的具体实现并不完全一样，但思路接近：你在后台写下一个类似 CNAME 的目标，服务商替你把目标解析成 IP，再以裸域可以使用的形式返回给查询者。例如 Cloudflare CNAME Flattening、DNSimple ANAME、AWS Route 53 Alias。IETF 曾有 草案，但尚未成为正式标准。 服务商在 DNS 边缘做了额外的解析工作,随着这些功能普及，裸域接入 CDN 和托管平台不再像以前那么别扭，于是「不带 」又变得更容易了。 所以我应该选哪一个？ 如果只是个人博客或小项目，其实按照各个平台的推荐来就可以，再说还有ai。 喜欢短一点的地址，就用裸域；希望保留传统习惯，或者以后可能把站点和其他子域服务拆得更清楚，就用 。两种方案都可以做好，也不会很麻烦。 不管选哪个做主地址，另一个都得把重定向和证书做好。得让DNS 能解析，HTTPS 证书覆盖，然后用 301 统一跳转。就拿我的网站例子来说，我把两个都配置好了。可以点击试一下。 www.markxu.icu markxu.icu Google Search Central 建议选一个规范地址并用 301 重定向，这样链接分享、缓存、统计和搜索引擎收录都更容易保持一致。 那为什么有时候加上 反而打不开？ 如果一个网站的裸域能打开，但手动加上 就报错，虽然不常见，但确实时有发生。原因大概是管理员只配置了上文说的其中一个地址。 一次完整的访问，大概会依次经过这些地方： 其中有一步没配好，就会出问题。 最简单的情况是 DNS 根本没有 的记录。查询结果是 NXDOMAIN，浏览器连服务器都找不到。 也可能 DNS 已经把 指到了正确的 IP，但 Nginx、Apache 或托管平台没有配置这个 Host，于是服务器返回默认页、404，或者干脆拒绝请求。 还有一个经常被忽略的顺序问题：如果用户访问的是 ，TLS 证书检查发生在 HTTP 重定向之前（RFC 9110 §4.2.2）。证书只覆盖 的话，浏览器会先在 HTTPS 这一步拦住请求，服务器还没有机会告诉它「请改去不带 的地址」。所以证书通常需要同时覆盖两个名字，或者使用包含它们的通配符证书。 一个配置完整的网站，往往会让两个地址都能找到它，然后选一个作为规范地址： 当然，你也可以反过来，把裸域重定向到 ，这个就看你的个人选择了，在技术上差别并不明显。 参考资料 RFC 1034：Domain Names - Concepts and Facilities RFC 1035：Domain Names - Implementation and Specification RFC 2181：Clarifications to DNS Specification §10.1 RFC 6265：HTTP State Management Mechanism RFC 9110：HTTP Semantics Cloudflare：DNS CNAME record Cloudflare：CNAME Flattening Google Search Central：Consolidate duplicate URLs",
      "content_html": "<blockquote>\n<p><a href=\"https://cerncourier.com/a/happy-20th-birthday-world-wide-web/\">封面图</a>：Tim Berners-Lee（蒂姆·伯纳斯-李）在2009年万维网诞生20周年的庆祝活动上，于欧洲核子研究中心（CERN）与那台具有历史意义的NeXT计算机重逢。他曾使用这台计算机开发并运行了世界上第一个Web服务器、多媒体浏览器以及网页编辑器。图片来源：CERN</p>\n</blockquote>\n<p>上一篇讲了 <code>www</code> 是怎么来的——它是 Tim Berners-Lee 建议的命名惯例，也是早期区分服务的必要手段。</p>\n<p>但是到了今天，Web 从“一台机器跑一个服务”变成“一个 IP 承载无数网站”之后，<code>www</code> 为什么不再是必需品？部署网站时那些让人头疼的 DNS 细节又该怎么处理？我打算在这篇讲一讲。</p>\n<h2>为什么后来很多网站又不用<code>www</code>了？</h2>\n<p>因为互联网的使用方式变了。</p>\n<p>当网站还是一台机器提供一个服务的时候，<code>www</code> 很有用，可以把 Web 服务和邮件服务区分开，方便管理。</p>\n<p>后来随着机器的性能进步，管理也逐渐变得简单和容易维护。尤其是后续虚拟主机、HTTP 的 <code>Host</code> 请求头（<a href=\"https://datatracker.ietf.org/doc/html/rfc9110\">RFC 9110</a>）、反向代理、CDN 和云平台逐渐普及，使得同一个 IP 地址可以根据域名把请求转给不同的网站，域名本身也就不再需要承担说明机器的使用用途的功能。</p>\n<p>这也与上文Tim在回答<a href=\"https://www.w3.org/Provider/Style/www.html\">Why www？</a>中最后的想法一致。</p>\n<p><img src=\"https://img.markxu.icu/img20261002120440228.png\" alt=\"CDN\"></p>\n<p>与此同时，<code>阿巴阿巴.com</code> 比 <code>www.阿巴阿巴.com</code> 短四个字符。这也就意味着出现在海报、名片、视频口播、广告牌和用户手动输入的每一个地方都更简短。这很明显更有利于宣传自己的品牌，让大众一眼注意到自己的品牌，于是越来越多网站选择把裸域，也就是不带子域名的 <code>阿巴阿巴.com</code>，作为对外展示的地址。</p>\n<p>但这也不代表 <code>www</code> 技术上落伍了。</p>\n<p>保留 <code>www</code> 有一些现实好处。它明确告诉网络基础设施：这是 Web 站点；以后如果要把 <code>api.阿巴阿巴.com</code>、<code>static.阿巴阿巴.com</code> 或其他服务拆出去，边界会更为清楚。Cookie 的作用范围<a href=\"https://datatracker.ietf.org/doc/html/rfc6265\">RFC 6265</a>）也可以更谨慎地控制：放在 <code>www.阿巴阿巴.com</code> 的站点，不会天然把只属于站点的主机级 Cookie 发给 <code>api.阿巴阿巴.com</code>。</p>\n<h2>真正麻烦的地方：裸域和 CNAME</h2>\n<p>讲到这里，可能会觉得既然 <code>www</code> 只是一个子域名，那不用就好了。但是事情在部署网站时会稍微复杂一点，尤其当是你第一次尝试 CDN、托管平台或云服务商的时候。</p>\n<p>DNS 里最常见的两种记录，可以先这样理解：</p>\n<pre><code class=\"language-text\">A     阿巴阿巴.com       -&gt; 203.0.113.10\nCNAME www.阿巴阿巴.com   -&gt; my-site.hosting-provider.com\n</code></pre>\n<p>A 记录直接把名字指向 IP 地址。<a href=\"https://www.cloudflare.com/learning/dns/dns-records/dns-cname-record/\">CNAME</a>（<a href=\"https://datatracker.ietf.org/doc/html/rfc1034\">RFC 1034</a> §3.6.2、<a href=\"https://datatracker.ietf.org/doc/html/rfc1035\">RFC 1035</a>）则说：这个名字请按照另一个名字继续查。</p>\n<p>CNAME 很适合接入托管平台。平台换了服务器 IP，你不需要每天改自己的 DNS，只要继续指向平台提供的域名即可。但按照传统 DNS 模型，一个名字如果设了 CNAME，就不能同时拥有其他类型的记录——<a href=\"https://datatracker.ietf.org/doc/html/rfc2181\">RFC 2181</a> §10.1 对此做了明确说明。</p>\n<p>问题在于，裸域 <code>阿巴阿巴.com</code> 不是一个普通的子域名。这个名字本身需要承载整个域的 NS、SOA 等基础记录；很多时候还会放邮件用的 MX、域名验证用的 TXT。按照传统规则，裸域不能简单地变成一个 CNAME，否则这些记录就没地方共存了。</p>\n<p>这也是为什么过去很多托管平台会告诉你：请把 <code>www.阿巴阿巴.com</code> 配成 CNAME，然后让裸域做一次跳转。<code>www</code> 作为普通子域名，可以很自然地指向平台；裸域则因为 DNS 的历史结构，处理起来没有那么直接。</p>\n<h2>现代 DNS 服务商怎么解决这个问题？</h2>\n<p>后来 DNS 服务商提供了不同名字的解决方案，例如 ALIAS、ANAME 或 CNAME flattening。它们的具体实现并不完全一样，但思路接近：你在后台写下一个类似 CNAME 的目标，服务商替你把目标解析成 IP，再以裸域可以使用的形式返回给查询者。例如 <a href=\"https://developers.cloudflare.com/dns/cname-flattening/\">Cloudflare CNAME Flattening</a>、<a href=\"https://docs.dnsimple.com/articles/alias-record/\">DNSimple ANAME</a>、<a href=\"https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-choosing-alias-non-alias.html\">AWS Route 53 Alias</a>。IETF 曾有 <code>draft-ietf-dnsop-aname</code> 草案，但尚未成为正式标准。</p>\n<p>服务商在 DNS 边缘做了额外的解析工作,随着这些功能普及，裸域接入 CDN 和托管平台不再像以前那么别扭，于是「不带 <code>www</code>」又变得更容易了。</p>\n<h2>所以我应该选哪一个？</h2>\n<p>如果只是个人博客或小项目，其实按照各个平台的推荐来就可以，再说还有ai。</p>\n<p>喜欢短一点的地址，就用裸域；希望保留传统习惯，或者以后可能把站点和其他子域服务拆得更清楚，就用 <code>www</code>。两种方案都可以做好，也不会很麻烦。</p>\n<p>不管选哪个做主地址，另一个都得把重定向和证书做好。得让DNS 能解析，HTTPS 证书覆盖，然后用 301 统一跳转。就拿我的网站例子来说，我把两个都配置好了。可以点击试一下。</p>\n<ul>\n<li><a href=\"https://www.markxu.icu\">www.markxu.icu</a></li>\n<li><a href=\"https://markxu.icu\">markxu.icu</a></li>\n</ul>\n<p><a href=\"https://developers.google.com/search/docs/crawling-indexing/consolidate-duplicate-urls\">Google Search Central 建议</a>选一个规范地址并用 301 重定向，这样链接分享、缓存、统计和搜索引擎收录都更容易保持一致。</p>\n<h2>那为什么有时候加上 <code>www</code> 反而打不开？</h2>\n<p>如果一个网站的裸域能打开，但手动加上 <code>www</code> 就报错，虽然不常见，但确实时有发生。原因大概是管理员只配置了上文说的其中一个地址。</p>\n<p>一次完整的访问，大概会依次经过这些地方：</p>\n<pre><code class=\"language-text\">浏览器\n  -&gt; DNS：www.example.com 有没有记录？\n  -&gt; 服务器：我是否接收 www.阿巴阿巴.com？\n  -&gt; HTTPS：证书是否覆盖 www.阿巴阿巴.com？\n  -&gt; Web 应用：返回页面，或重定向到规范地址\n</code></pre>\n<p>其中有一步没配好，就会出问题。</p>\n<p>最简单的情况是 DNS 根本没有 <code>www</code> 的记录。查询结果是 NXDOMAIN，浏览器连服务器都找不到。</p>\n<p>也可能 DNS 已经把 <code>www.阿巴阿巴.com</code> 指到了正确的 IP，但 Nginx、Apache 或托管平台没有配置这个 Host，于是服务器返回默认页、404，或者干脆拒绝请求。</p>\n<p>还有一个经常被忽略的顺序问题：如果用户访问的是 <code>https://www.阿巴阿巴.com</code>，TLS 证书检查发生在 HTTP 重定向之前（<a href=\"https://datatracker.ietf.org/doc/html/rfc9110\">RFC 9110</a> §4.2.2）。证书只覆盖 <code>阿巴.com</code> 的话，浏览器会先在 HTTPS 这一步拦住请求，服务器还没有机会告诉它「请改去不带 <code>www</code> 的地址」。所以证书通常需要同时覆盖两个名字，或者使用包含它们的通配符证书。</p>\n<p>一个配置完整的网站，往往会让两个地址都能找到它，然后选一个作为规范地址：</p>\n<pre><code class=\"language-text\">https://www.阿巴阿巴.com  -&gt; 301 -&gt; https://阿巴阿巴.com\nhttps://阿巴阿巴.com       -&gt; 200\n</code></pre>\n<p>当然，你也可以反过来，把裸域重定向到 <code>www</code>，这个就看你的个人选择了，在技术上差别并不明显。</p>\n<h2>参考资料</h2>\n<ul>\n<li><a href=\"https://datatracker.ietf.org/doc/html/rfc1034\">RFC 1034：Domain Names - Concepts and Facilities</a></li>\n<li><a href=\"https://datatracker.ietf.org/doc/html/rfc1035\">RFC 1035：Domain Names - Implementation and Specification</a></li>\n<li><a href=\"https://datatracker.ietf.org/doc/html/rfc2181\">RFC 2181：Clarifications to DNS Specification</a> §10.1</li>\n<li><a href=\"https://datatracker.ietf.org/doc/html/rfc6265\">RFC 6265：HTTP State Management Mechanism</a></li>\n<li><a href=\"https://datatracker.ietf.org/doc/html/rfc9110\">RFC 9110：HTTP Semantics</a></li>\n<li><a href=\"https://www.cloudflare.com/learning/dns/dns-records/dns-cname-record/\">Cloudflare：DNS CNAME record</a></li>\n<li><a href=\"https://developers.cloudflare.com/dns/cname-flattening/\">Cloudflare：CNAME Flattening</a></li>\n<li><a href=\"https://developers.google.com/search/docs/crawling-indexing/consolidate-duplicate-urls\">Google Search Central：Consolidate duplicate URLs</a></li>\n</ul>\n",
      "summary": "接着上一篇的内容继续，重点放在现在为什么不用www了，以及我们目前主要的操作是什么。",
      "date_published": "2026-10-01T00:00:00.000Z",
      "image": "https://img.markxu.icu/img20261001152633367.png",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/blog/why-does-some-website-has-www-1-cn",
      "url": "https://markxu.icu/blog/why-does-some-website-has-www-1-cn",
      "title": "为什么有的网站有 www，有的没有？-起源篇",
      "content_text": "封面图是世界上第一台网页服务器的照片，即蒂姆·伯纳斯-李（（Tim Berners-Lee）在 CERN 使用的 NeXT 计算机。 ，也就是万维网——World Wide Web，是一个很基础的概念，甚至在高中老师就已经教过了。 但今天在看一些博客网站的时候，突然注意到一件以前从来没有认真想过的事：有些网址是 ，有些网址却只有 。 在没仔细深究前，我还以为所有网站都有 ，只是浏览器觉得这几个字母可以不显示，给我们藏起来了。今天突发奇想，仔细研究了一下，发现其实背后不止是浏览器的隐藏，现在的技术早就没有必要使用 了，大部分现代网站也也已经不再使用，保留的则更多的是历史遗留习惯。 所以这篇文章主要是分享下我研究 这个网址前缀的起源来历，后面再写一篇讲讲为什么后续又消失了，和现在我们都怎么使用域名。 先从技术上讲讲为什么会有 最早期的互联网与现在的互联网从基础设施上就有很多差别，所以当初的很多协议和功能设计的初衷与现在也大不相同，所以如果好奇 为什么存在，我们或许需要从互联网的最开始讲起。 互联网初期-1969 大家通常认为的最早的互联网，或者说是互联网的前身 ARPANET （1969 年）诞生时，其连接的是几所大学和研究所的计算机，每台机器有一个主机名，直接注册在中心维护的 HOSTS.TXT 里（后来才被 DNS 替代）。 这个时候大家的初衷很简单，就是把几台机器连接起来，让他们可以相互通信。 因为机器很少，所以这个时候也还没有域名的概念，也不需要域名来多一层转换，只有\"机器名→地址\"的映射，这也足够了。 这段时间的发展具体可以看看这一篇文章，漫谈互联网历史【7】- ARPANET （虽然这个系列的其他文章与本文讨论的无关，但是写的真的很有意思，很推荐多去了解了解） DNS的出现（域名）-1983 后面随着越来越多的机器加入，整个网络已经完全与以往不一样了。 在1983年的1月1日，所有连网主机从 NCP 切换到 TCP/IP，也被称为TCP/IP Flag Day。 所有的机器都停止支持旧协议，并同时支持TCP/IP，让 以前“单网、扁平、中心化”的架构，变成了“多网、分层、可委托”的架构。 这样也满足了越来越多机器加入网络的需求。 随着越来越多的机器加入，原本由中心人力维护的 HOSTS.TXT 文件开始膨胀，在那时存储还不像今天这样量大管饱的时候，每台机器都要存储一个 HOST.TXT 文件愈发变得不现实，更难以接受的是，当时如果网络有些变动，管理员需要重新编译一遍 HOST.TXT 文件，然后通过 FTP 协议传输给所有机器，这通常一周更新一两次，这个延迟也是不可以接受的。 后来在 1983 年的 11 月 23 号，Paul Mockapetris（保罗·莫卡派乔斯） 设计 DNS，并提交了 RFC 882 和 RFC 883（后在1987年被 RFC 1034 / RFC 1035 替代）。 其核心思想可以总结为下面几条： 一致的名字空间：名字里不要塞网络号、地址、路由信息 分布式维护：全量数据库不能集中存，必须分片+缓存 管理权下放：谁拥有数据，谁控制更新/缓存策略 通用目录服务：不只查主机地址，还能查邮箱、以后未知类型 这样就保证了一个去中心化的（每个组织可以管理自己的机器的命名方式），方便网络更新的分布式系统。 存在的前提 前面讲到了所有组织都可以自己管理自己的机器，组织通过自己分配域名的方式就可以很方便的进行职责分配。 虽然从1980年就有了端口技术，一台机器可以跑多种服务，但早期机器贵、资源少，没法让一台机器同时处理web服务和邮件服务，所以早期采用的方式是不同机器运行不同服务，就像下面这样： 这同时带来的好处也有不少： 管理边界——邮件归系统管理员管，Web 归新来的网络组管，各管各的机器，互不背锅。 故障隔离——邮件服务崩了不能影响 Web，反之亦然。 DNS 设计理念——域名系统一开始就是\"主机名→IP\"的映射，不是\"服务名→IP\"。你给每台机器起个名字，跑什么服务就叫什么名。 所以 本质上就是一个三级域名，没有任何特殊特权。 的出现 -1989 1989 年 Tim （封面人物）在 CERN 提出了万维网概念，其重点不是简单规定网站前缀，呼吁大家都使用 作为网络服务域名，而是提出 URL/HTTP/HTML 这一套超文本系统，让文档可以跨机器互链、跨组织发布。 就比如CERN 第一台 Web 服务器用的是 info.cern.ch，不是 www.cern.ch。 到了 1990 年底，Tim 已经在 CERN 成功推出了第一个 Web 服务器和浏览器，从而证明了该提议背后的理念是可行的。他直接在 NeXT 计算机上编写了相关代码，并让这台服务器一直运行在办公室里。为了避免有人不小心关闭这台服务器，他在计算机上贴了一张用红墨水写的标签，上面写着：“这台机器是服务器，请勿关闭它！” 但 Web 作为一种新服务接入已有网络时，管理员通常会给它单独主机名。已有 ftp/mail/news 等按服务命名，Web 就沿用 www。 一点点后续 -1990s www命名的流行或许也与Mosaic 浏览器的发布有关系。1993年，NCSA 发布 Mosaic，第一个让大众能看图、点链接的浏览器。NCSA 自己的 Web 服务器叫 www.ncsa.uiuc.edu。Mosaic 内置的书签和示例链接全是这个地址，全球用户第一次接触 Web 时看到的就是 www。 在后面的Yahoo（1994）、Amazon（1994）、eBay（1995）这几个商业互联网的出现，其新网址也都沿用了 前缀。也因此被大众所熟知。 Why ? 那么这么多名字为什么要用 呢？ 其实这个问题也有人曾经发邮件问过Tim，可以点击链接看下 Tim 给的解释。 他的解释还蛮有意思的： www 是他\"建议\"的，不是\"规定\"的 \"It is a convention. I suggested it early on, in this guide...\" 他在一个 Style Guide（写给 webmaster 的指南）里建议的,就是他写了篇文章说\"你们可以这么干\"。 为什么不用机器本来的名字？ \"An alias was a better alternative to 'pegasus.foo.com' which typically resulted when someone who happened to have a machine called pegasus started to run a web server...\" 他的意思是：早期很多人随便拿手边一台叫 pegasus 的机器跑 Web，结果别人访问就得用 pegasus.foo.com。这名字毫无意义，用户记不住，也看不出这是干啥的。 所以他建议：起个别名叫 www，一看就知道是 Web 服务器。 为什么选 \"www\" 这三个字母？ 因为已有的惯例就是按服务缩写命名： 他只是把 Web 也塞进了这个已有的命名体系里。选 www 不是因为它特别，是因为它跟 ftp、mail 一个套路。 为什么不直接用裸域 foo.com？ 他说了两个原因： \"Typically early webmasters could not have comandeered the 'foo.com' address itself.\" 意思是：裸域 foo.com 是域的\"根标识\"，通常由系统管理员控制，早期跑 Web 的人（webmaster）没权限去改裸域的 DNS 记录。他们只能在自己能控制的范围内加个子域。 \"You don't have this flexibility of configuration if you point everyone at 'foo.com' itself for all services.\" 另一个原因是灵活性：用别名 www，以后 Web 服务长大了，可以轻松把 www 指向一台更大的机器，不影响裸域和其他服务。 一个有趣的细节 Tim 在回答的最后说到他是 \"of two minds about it now\"（现在对此心情复杂）。 因为到 1999 年，Web 已经成了很多公司最大的服务，他觉得也许该让 Web 占住裸域了。但他同时强调：只能选一个，不能两个都当主站，否则缓存效率减半。 这也与我们下一篇讲现在网络为什么又不使用 ，而是可以直接链接裸域名的想法一致。",
      "content_html": "<blockquote>\n<p>封面图是世界上第一台网页服务器的照片，即蒂姆·伯纳斯-李（（Tim Berners-Lee）在 CERN 使用的 NeXT 计算机。</p>\n</blockquote>\n<p><code>www</code>，也就是万维网——World Wide Web，是一个很基础的概念，甚至在高中老师就已经教过了。</p>\n<p>但今天在看一些博客网站的时候，突然注意到一件以前从来没有认真想过的事：有些网址是 <code>www.阿巴阿巴.com</code>，有些网址却只有 <code>阿巴阿巴.com</code>。</p>\n<p>在没仔细深究前，我还以为所有网站都有 <code>www</code>，只是浏览器觉得这几个字母可以不显示，给我们藏起来了。今天突发奇想，仔细研究了一下，发现其实背后不止是浏览器的隐藏，现在的技术早就没有必要使用<code>www</code>了，大部分现代网站也也已经不再使用，保留的则更多的是历史遗留习惯。</p>\n<p>所以这篇文章主要是分享下我研究<code>www</code>这个网址前缀的起源来历，后面再写一篇讲讲为什么后续又消失了，和现在我们都怎么使用域名。</p>\n<p><strong>先从技术上讲讲为什么会有<code>www</code></strong></p>\n<p>最早期的互联网与现在的互联网从基础设施上就有很多差别，所以当初的很多协议和功能设计的初衷与现在也大不相同，所以如果好奇<code>www</code>为什么存在，我们或许需要从互联网的最开始讲起。</p>\n<h2>互联网初期-1969</h2>\n<p>大家通常认为的最早的互联网，或者说是互联网的前身 ARPANET （1969 年）诞生时，其连接的是几所大学和研究所的计算机，每台机器有一个主机名，直接注册在中心维护的 HOSTS.TXT 里（后来才被 DNS 替代）。<br>\n<img src=\"https://img.markxu.icu/img20260926235052374.png\" alt=\"最开始的互联网草图\"></p>\n<p>这个时候大家的初衷很简单，就是把几台机器连接起来，让他们可以相互通信。</p>\n<p>因为机器很少，所以这个时候也还没有域名的概念，也不需要域名来多一层转换，只有&quot;机器名→地址&quot;的映射，这也足够了。</p>\n<p>这段时间的发展具体可以看看这一篇文章，<a href=\"https://www.cnblogs.com/xusheng/articles/2420494.html\">漫谈互联网历史【7】- ARPANET</a><em>（虽然这个系列的其他文章与本文讨论的无关，但是写的真的很有意思，很推荐多去了解了解）</em></p>\n<h2>DNS的出现（域名）-1983</h2>\n<p>后面随着越来越多的机器加入，整个网络已经完全与以往不一样了。</p>\n<p>在1983年的1月1日，所有连网主机从 NCP 切换到 TCP/IP，也被称为<a href=\"https://psu.pb.unizin.org/ist110/chapter/1-4-history-of-the-internet/\">TCP/IP Flag Day</a>。</p>\n<p>所有的机器都停止支持旧协议，并同时支持TCP/IP，让<strong>以前“单网、扁平、中心化”的架构，变成了“多网、分层、可委托”的架构。</strong> 这样也满足了越来越多机器加入网络的需求。</p>\n<p>随着越来越多的机器加入，原本由中心人力维护的 HOSTS.TXT 文件开始膨胀，在那时存储还不像今天这样量大管饱的时候，每台机器都要存储一个 HOST.TXT 文件愈发变得不现实，更难以接受的是，当时如果网络有些变动，管理员需要重新编译一遍 HOST.TXT 文件，然后通过 FTP 协议传输给所有机器，这通常一周更新一两次，这个延迟也是不可以接受的。</p>\n<p>后来在 1983 年的 11 月 23 号，<a href=\"https://awards.acm.org/award-recipients/mockapetris_3342151\">Paul Mockapetris</a>（保罗·莫卡派乔斯） 设计 DNS，并提交了 RFC 882 和 RFC 883（后在1987年被 <a href=\"https://datatracker.ietf.org/doc/html/rfc1034\">RFC 1034</a> / RFC 1035 替代）。</p>\n<p><img src=\"https://img.markxu.icu/img20261001130353957.png\" alt=\"Paul Mockapetris（保罗·莫卡派乔斯）\"></p>\n<p>其核心思想可以总结为下面几条：</p>\n<ul>\n<li>一致的名字空间：名字里不要塞网络号、地址、路由信息</li>\n<li>分布式维护：全量数据库不能集中存，必须分片+缓存</li>\n<li>管理权下放：谁拥有数据，谁控制更新/缓存策略</li>\n<li>通用目录服务：不只查主机地址，还能查邮箱、以后未知类型</li>\n</ul>\n<p>这样就保证了一个去中心化的（每个组织可以管理自己的机器的命名方式），方便网络更新的分布式系统。</p>\n<h2><code>www</code>存在的前提</h2>\n<p>前面讲到了所有组织都可以自己管理自己的机器，组织通过自己分配域名的方式就可以很方便的进行职责分配。</p>\n<p>虽然从1980年就有了端口技术，一台机器可以跑多种服务，但早期机器贵、资源少，没法让一台机器同时处理web服务和邮件服务，所以早期采用的方式是不同机器运行不同服务，就像下面这样：</p>\n<pre><code class=\"language-text\">ftp.example.com    文件传输\nmail.example.com   邮件\nnews.example.com   新闻组\n</code></pre>\n<p>这同时带来的好处也有不少：</p>\n<ol>\n<li>管理边界——邮件归系统管理员管，Web 归新来的网络组管，各管各的机器，互不背锅。</li>\n<li>故障隔离——邮件服务崩了不能影响 Web，反之亦然。</li>\n<li>DNS 设计理念——域名系统一开始就是&quot;主机名→IP&quot;的映射，不是&quot;服务名→IP&quot;。你给每台机器起个名字，跑什么服务就叫什么名。</li>\n</ol>\n<p><strong>所以<code>www</code>本质上就是一个三级域名，没有任何特殊特权。</strong></p>\n<h2><code>www</code>的出现 -1989</h2>\n<p>1989 年 Tim （封面人物）在 CERN 提出了万维网概念，其重点不是简单规定网站前缀，呼吁大家都使用<code>www</code>作为网络服务域名，而是提出 URL/HTTP/HTML 这一套超文本系统，让文档可以跨机器互链、跨组织发布。</p>\n<p>就比如CERN 第一台 Web 服务器用的是 <a href=\"info.cern.ch\">info.cern.ch</a>，不是 <a href=\"http://www.cern.ch\">www.cern.ch</a>。</p>\n<p>到了 1990 年底，Tim 已经在 CERN 成功推出了第一个 Web 服务器和浏览器，从而证明了该提议背后的理念是可行的。他直接在 NeXT 计算机上编写了相关代码，并让这台服务器一直运行在办公室里。为了避免有人不小心关闭这台服务器，他在计算机上贴了一张用红墨水写的标签，上面写着：“这台机器是服务器，请勿关闭它！”</p>\n<p><img src=\"https://img.markxu.icu/img20261001142450998.png\" alt=\"This machine is a server. DO NOT POWER IT DOWN!\"></p>\n<p>但 Web 作为一种新服务接入已有网络时，管理员通常会给它单独主机名。已有 ftp/mail/news 等按服务命名，Web 就沿用 www。</p>\n<h2>一点点后续 -1990s</h2>\n<p>www命名的流行或许也与Mosaic 浏览器的发布有关系。1993年，NCSA 发布 Mosaic，第一个让大众能看图、点链接的浏览器。NCSA 自己的 Web 服务器叫 <a href=\"http://www.ncsa.uiuc.edu\">www.ncsa.uiuc.edu</a>。Mosaic 内置的书签和示例链接全是这个地址，全球用户第一次接触 Web 时看到的就是 www。</p>\n<p><img src=\"https://img.markxu.icu/img20261001150413894.png\" alt=\"Mosaic浏览器\"></p>\n<p>在后面的Yahoo（1994）、Amazon（1994）、eBay（1995）这几个商业互联网的出现，其新网址也都沿用了<code>www</code>前缀。也因此被大众所熟知。</p>\n<h2>Why <code>www</code>?</h2>\n<p>那么这么多名字为什么要用<code>www</code>呢？</p>\n<p>其实这个问题也有人曾经<a href=\"https://www.w3.org/Provider/Style/www.html\">发邮件问过Tim</a>，可以点击链接看下 Tim 给的解释。</p>\n<p>他的解释还蛮有意思的：</p>\n<ol>\n<li>www 是他&quot;建议&quot;的，不是&quot;规定&quot;的</li>\n</ol>\n<blockquote>\n<p>&quot;It is a convention. I suggested it early on, in this guide...&quot;</p>\n</blockquote>\n<p>他在一个 Style Guide（写给 webmaster 的指南）里建议的,就是他写了篇文章说&quot;你们可以这么干&quot;。</p>\n<ol start=\"2\">\n<li>为什么不用机器本来的名字？</li>\n</ol>\n<blockquote>\n<p>&quot;An alias was a better alternative to '<a href=\"http://pegasus.foo.com\">pegasus.foo.com</a>' which typically resulted when someone who happened to have a machine called pegasus started to run a web server...&quot;</p>\n</blockquote>\n<p>他的意思是：早期很多人随便拿手边一台叫 pegasus 的机器跑 Web，结果别人访问就得用 <a href=\"http://pegasus.foo.com\">pegasus.foo.com</a>。这名字毫无意义，用户记不住，也看不出这是干啥的。</p>\n<p>所以他建议：起个别名叫 www，一看就知道是 Web 服务器。</p>\n<ol start=\"3\">\n<li>为什么选 &quot;www&quot; 这三个字母？</li>\n</ol>\n<p>因为已有的惯例就是按服务缩写命名：<br>\n他只是把 Web 也塞进了这个已有的命名体系里。选 www 不是因为它特别，是因为它跟 ftp、mail 一个套路。</p>\n<ol start=\"4\">\n<li>为什么不直接用裸域 <a href=\"http://foo.com\">foo.com</a>？</li>\n</ol>\n<p>他说了两个原因：</p>\n<blockquote>\n<p>&quot;Typically early webmasters could not have comandeered the '<a href=\"http://foo.com\">foo.com</a>' address itself.&quot;</p>\n</blockquote>\n<p>意思是：裸域 <a href=\"http://foo.com\">foo.com</a> 是域的&quot;根标识&quot;，通常由系统管理员控制，早期跑 Web 的人（webmaster）没权限去改裸域的 DNS 记录。他们只能在自己能控制的范围内加个子域。</p>\n<blockquote>\n<p>&quot;You don't have this flexibility of configuration if you point everyone at '<a href=\"http://foo.com\">foo.com</a>' itself for all services.&quot;</p>\n</blockquote>\n<p>另一个原因是灵活性：用别名 www，以后 Web 服务长大了，可以轻松把 www 指向一台更大的机器，不影响裸域和其他服务。</p>\n<h3>一个有趣的细节</h3>\n<p>Tim 在回答的最后说到他是 &quot;of two minds about it now&quot;（现在对此心情复杂）。</p>\n<p>因为到 1999 年，Web 已经成了很多公司最大的服务，他觉得也许该让 Web 占住裸域了。但他同时强调：只能选一个，不能两个都当主站，否则缓存效率减半。</p>\n<p>这也与我们下一篇讲现在网络为什么又不使用<code>www</code>，而是可以直接链接裸域名的想法一致。</p>\n",
      "summary": "一直以为地址栏里的 www 只是被浏览器藏起来了，随着深入了解，发现其实这连着早期互联网的服务分工、DNS 的限制，以及今天网站部署方式的变化。",
      "date_published": "2026-09-26T00:00:00.000Z",
      "image": "https://img.markxu.icu/img20260926225709745.png",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/blog/FingerBlock-A-game-Demo-by-AI-cn",
      "url": "https://markxu.icu/blog/FingerBlock-A-game-Demo-by-AI-cn",
      "title": "FingerBlock：由 AI 协助完成的游戏 Demo",
      "content_text": "前段时间，我偶然发现 GitHub 上很久以前 star 过的一个手势识别库又有了更新。都已经忘掉了为什么会给这个项目star了，可能是当初刚刚听说手势识别感觉很酷就关注了吧，其实从来也没看过，甚至没有了解过相关代码。 但是这一次偶然的注意，让我想到，这么多年过去了，ai都发展成现在这样了，手势识别一定也很厉害了吧，于是前去了解相关的消息，看到了Google 的 MediaPipe，又很快联想到小时候玩xbox 360的体感游戏，想着如果可以用这个来做一个游戏一定不错吧。 就是这么一个念头在睡觉前总会想起，然后一个类似《Beat Saber》的音乐游戏的概念如圣诞老人般，悄然从我脑中的烟囱中钻出，留下了这么一个礼物：面对笔记本的摄像头，游戏里的方块沿着轨道靠近判定网格，再用手指把它们击中。操作简单易懂，而且貌似也比较好实现。 于是我便利用ai，在做题空闲时描述下需求，一共五六次对话，就做出来了初版。（AI大人的实力真实愈发恐怖了。） 项目代码已经放在 GitHub：MarkXuJQ/finger-block 中。这篇文章记录下我是如何确定游戏的基础设定，以及选用了那些技术选型，和一点点优化的操作。 项目的基础技术结构 FingerBlock 是一个 Vite + React 的浏览器端项目，因为这个流程我也比较熟悉了。 渲染部分使用 React Three Fiber 和 Three.js，用这个来模仿我们的beatsaber的一点点空间感。 界面图标使用 Lucide，简单高效。 接下来就该说说游戏的核心内容了： 手势识别：MediaPipe 手势识别使用了 Google 的 MediaPipe Tasks Vision 中的 Hand Landmarker。它提供了手部关键点检测能力，我们利用这个把识别结果转换成 FingerBlock 所需的输入。 中的流程大致是： 摄像头启动后，按需加载 MediaPipe 的 WASM 文件和手部模型。 优先尝试 GPU delegate，失败时回退到 CPU delegate。 限制最多追踪两只手，并读取每只手的食指尖关键点，也就是第 8 个 landmark。 摄像头画面给玩家看到的是镜像画面，所以代码会对左右手标签进行交换，保持物理左右和画面左右的一致性。 通过 把视频坐标转换为视口坐标，再由 映射到 3×3 或 4×4 判定网格。 对坐标做简单平滑，减少摄像头逐帧检测带来的抖动。 这时，我想既然有了摄像头用手势进行输入的方法， 不如把触控的方式也做了，这样在手机端也可以玩了，于是我也让AI补齐了这个功能，但值得一提的是，在手机和平板端，常常会由于性能不是特别充足，有较大的延迟，或许这个部分可以后面逐渐优化。下面是具体的思路: 摄像头并不是唯一的输入方式。项目后来加入了 模式，鼠标和触控都可以直接在判定区域操作。触控使用 和 pointer capture 追踪多个手指，即使没有触发新的 ，也会通过持续的 presence loop 维持 Hold。这样即使浏览器已经取得摄像头权限，玩家仍然可以切换到触控完成一局。 音频分析：把音频处理放到 Worker 从固定谱子转向自动生成 在完成手势识别的功能，我让AI先完成了一段固定曲谱的小样，尝试我的想法是否可行，结果很不错，可以很好的捕捉我的食指位置，识别的也还算准确。 固定谱子跑通之后，内容制作的问题就出现了。 我没有任何音乐版权，也没有能力和时间为大量歌曲手工制作谱子。如果想要像其他音游一样，需要人工标记时间点、位置和方块类型，游戏的扩展成本会很高。但又如果不放音乐，只用固定的曲谱来玩的话，也未免太无聊了些。 这时我想到了 Steam 游戏《Dead as Disco》。我虽然从来没有上手玩过，但是看到过这个游戏的游戏视频。这个让我意识到，我们或许可以和这个游戏一样，尝试做一套音乐分析，然后把根据分析结果来自动生成曲谱，让玩家自己上传自己喜欢的音乐，岂不美哉？ 具体实现 音乐导入支持浏览器能够解码的 MP3、WAV、M4A/MP4 和 OGG，单个文件限制为 80 MB，时长限制为 12 分钟，这应该足以应付绝大部分的音乐了，不然一个人玩12分钟的音游也够累的。随后通过 Web Audio API 的 在当前浏览器中解码。 的处理过程比简单读取 BPM 更完整： 先把多声道混合成单声道，并统一重采样到 22,050 Hz； 以大约 50 毫秒为一帧计算整体 RMS 能量； 使用 180 Hz 的低通结果估计低频能量； 按时间窗口生成归一化能量曲线和波形预览； 根据当前帧与前几帧的能量差寻找瞬态，也就是可能对应鼓点或明显起音的时间点； 使用 的 Beatroot 算法分析 BPM 和节拍候选； 将歌曲切分为 quiet、normal 和 peak 三种能量乐段； 根据节拍匹配率和瞬态覆盖率计算一个置信度。 我使用的 music-tempo 是 MIT 许可证的轻量 BPM/节拍分析库。它适合在浏览器 Worker 中快速给出候选结果，但它不可能对所有弱节奏、自由速度或长时间静音的音乐都判断正确，所以界面保留了人工调整 BPM、首拍和 0.5×/1×/2× 倍速的能力。当然在绝大部分下还是可以卡上大部分的节奏的。 自动谱面生成：规则约束 使用固定种子的伪随机数生成器。种子由歌曲标识、网格大小、难度、BPM 和首拍共同决定，因此同一首音乐在同一组设置下会稳定得到同一份谱面，调整参数后才会得到新的结果。或许这样可以保证一定的稳定性。 生成器会从音频分析结果里读取节拍、能量和瞬态，再根据 easy、normal、hard 三种配置决定采样步长、密度、和弦概率、Hold 概率和最大移动距离。 方块的颜色也和音乐特征相关：重拍或强瞬态生成红色的 方块，普通方块是蓝色，部分非整拍的低强度事件会被标成黄色的可选 。这样来保证游戏的一定的可玩性，同时也利用视觉增强了音乐的节奏性。 不过，真正麻烦的地方在于“随机内容必须仍然可以被双手完成”。人最多就两个食指，天花乱坠的随机方块肯定不能让人类完成，所以我又在项目里加入了几类约束。 同一时间最多占用两根手指 首先把双手食指视为同时可用的最大输入数，生成器用 约束重叠判定窗口内的方块数量。即使两个方块的时间戳不完全相同，只要它们处于同一个击打窗口，也会被视为在竞争同样的两根手指。 在高能量的重拍上可以生成双击，但也会检查附近是否已经有足够的方块，避免意外生成第三个同时需要处理的目标。 中间格不放 Hold 从远处接近的 3D 轨道会让中央区域承担重要的视觉参照。如果长时间方块出现在中间，它可能遮住深度轮廓，也会干扰玩家观察后续方块。因此 先定义了 3×3 的一个中心格和 4×4 的四个中心格， 在校验时直接拒绝位于这些格子的 Hold。 这条规则同时存在于生成阶段和最终谱面校验阶段：生成器使用 避开中心，校验器则防止未来手工或外部谱面绕过生成器写入非法 Hold。这样规则就不只是一个“希望遵守”的约定，而是变成了数据层的约束。 Hold 会限制另一只手 Hold 不是一个只在起点判定一次的长方块。命中起点后，玩家需要让同一只手持续占据对应格子，项目每 0.25 秒结算一次持续分数，并允许约 0.18 秒的短暂追踪宽限。如果中途松开，已经获得的分数会保留，不会额外再记一次 Miss。 因为一只手被 Hold 占用，另一只手的活动空间就变小了。生成器因此会： 只在持续时间足够长、能量不低的非安静乐段中生成 Hold； Hold 期间把自由手的生成密度降到普通状态的一部分； 让自由手尽量在整拍出现，并预留更长的节拍间隔； 限制自由手的移动距离，并优先选择 Hold 所在区域的另一侧； Hold 结束后留出恢复空档，再逐渐恢复移动距离和密度。 普通难度的 Hold 持续时间约为两个节拍，简单难度更长，困难难度更短但密度更高。双 Hold 只在足够长的旋律乐段中低概率出现，而且会放在网格的相对两侧，让左右手各自有清楚的目标。 还会阻止同一格在 Hold 结束前生成新的音符。 最终还要校验谱面 所有生成的内容都会经过 ：检查版本、网格大小、难度、歌曲信息、音符排序、音符 ID、颜色与角色是否匹配、Hold 时长是否有效，以及同一格上的音符是否重叠。生成器负责创造内容，校验器负责确保内容符合数据契约，这让后续修改规则时更容易发现问题。 游戏音效：用少量素材组成一套鼓组 在AI时代，逻辑实现变得容易了，但是素材仍然是一个难题，好在网络上有着大量的cc0的开源素材可以使用。由于大部分的音乐都可以垫一层底鼓（不能垫鼓的音乐也不适合玩音游😄），所以很自然的想到使用架子鼓的声音来做打击音效，所有用到的音源都在 中记录了来源、许可证、获取时间、处理方式和 SHA-256 校验值。 当前的击打音效来自 Freesound 上显示为 CC0 的五条录音，包含 KEVOY 的 side stick 和 rimshot、TheEndOfACycle 的 closed hat 和 sub kick，以及 quatricise 的 shaker。项目使用 FFmpeg 对它们做了裁切、淡出、峰值限制、采样率和 Vorbis OGG 转换； 则是低通、低增益处理后的低音闷击。 运行时并不是把六个 OGG 当成六种互不相关的提示音，而是按鼓组分层： 普通 Hit 播放 side stick； Good 在其上叠加轻微 rim； Perfect 再加入 closed hat； Accent 额外叠加低音 kick； Bonus 叠加 shaker； Miss 使用单独的低音闷击。 这种设计让不同判定之间有共同的音色锚点，又能通过层数和音色变化区分反馈。音乐通道和效果音通道也分别经过 AudioContext 的 GainNode 控制，避免命中音效覆盖用户导入的音乐。 最后的微调和简单设计 核心逻辑跑通之后，剩下的工作主要是不断试玩和微调：方块的移动速度、轨道的深度感、判定网格的位置、摄像头游标的平滑程度、命中时的闪光和碎片、HUD 上的分数和连击、不同难度的密度，以及音乐和效果音的相对音量。 时钟、判定和反馈 游戏运行时没有把普通的 当作唯一时钟。音乐播放使用 Web Audio 的 和 ， 记录音频上下文中的开始时间和暂停位置，游戏逻辑再根据这条音乐时间轴计算方块位置和判定。 普通方块的判定窗口是 ±0.26 秒，其中 ±0.07 秒为 Perfect，±0.15 秒内为 Good，其余仍在总窗口内则为 Hit。普通命中分值分别是 1000、650 和 350，红色 Accent 方块还有 1.2 倍基础分加成。黄色 Bonus 不完全等同于普通漏击目标，它承担的是可选奖励的角色。 Hold 的持续分数也被写成了确定性的函数：每 0.25 秒只消费完整的计分区间，并把时间截断在 Hold 结束处。即使浏览器某一帧延迟了几百毫秒，也不会因为动画帧数量不同而得到不同的持续分数。 命中反馈由 统一生成，Three.js 场景负责播放闪光、扩散环、线框和碎片效果，来增强打击感；结算页还会绘制累计准确率曲线和 Miss 时间点。项目也会在页面隐藏时冻结音乐时钟和 Hold 的补偿逻辑，避免切到后台后回来，方块因为页面暂停而整体跳过判定区域。 当然这一部分完成的很粗糙，因为我感觉大体上已经实现了我的想法了，后续如果没有特殊情况应该也不会再继续优化了。 最后的感想 一天半完成一个可以玩的 Demo 从看到手势识别库更新，到最后完成一个可以运行的 FingerBlock Demo，整个过程大约用了一天半。而且这一天半也不是一直坐在电脑前写代码，中间还花了不少时间做题、看课，中午午休时间用来找找开源库、找找素材、研究音频分析方法，以及不断试玩和调整生成规则。 有一说一，AI 确实把这个 idea 的落地速度提高了一大截。从搭骨架、调音轨解析到塞各种约束规则，很多写起来繁琐的样板代码，现在只要把需求理清楚，然后发给ai，它就能一下子全给你搞定，我所需要做的就是检查和核实。 AI 很强，但这次快速实验不全靠AI 我不会把这次快速开发 FingerBlock 的demo完全归功于 AI。 正如我之前写过的一篇当开源只剩下一段 Prompt：我发现了一种“离谱”的开源方式，里面提到的一样，几段好的prompt、清晰的技术栈和恰到好处的素材链接，才是发挥ai最大作用，提高效率的关键。 AI 可以承担越来越多具体的执行工作，但我们不能因此把基本的思考和规划也全部交出去。掌握这些基础能力，才能更快判断一个想法是否可行，更准确地寻找合适的开源资源，也才能看懂 AI 生成的代码到底解决了什么问题、又留下了什么问题。 或许是从 Web coding 到当下 Vibe coding 还保留不变的技术关键。 9月23日 坏了，感觉现在再做一遍的话，ai貌似可以做到更多，更好，这是我在群里看到的消息，这些游戏真的可以玩。 以下内容皆使用 Claude Opus 5.5 一句话提示词生成 QQ飞车： 穿越火线之运输船 : 鹈鹕骑自行车: 9月25日 今天在网上刷视频刷到了这么个网站，感觉和我的思路有共同之处，还蛮惊喜的.不过这个就要求对音乐要有点点乐理基础，当然玩法也更自由。而且确实蛮cool。 视频： 网站：",
      "content_html": "<p>前段时间，我偶然发现 GitHub 上很久以前 star 过的一个手势识别库又有了更新。都已经忘掉了为什么会给这个项目star了，可能是当初刚刚听说手势识别感觉很酷就关注了吧，其实从来也没看过，甚至没有了解过相关代码。</p>\n<p>但是这一次偶然的注意，让我想到，这么多年过去了，ai都发展成现在这样了，手势识别一定也很厉害了吧，于是前去了解相关的消息，看到了Google 的 <a href=\"https://github.com/google-ai-edge/mediapipe\">MediaPipe</a>，又很快联想到小时候玩xbox 360的体感游戏，想着如果可以用这个来做一个游戏一定不错吧。</p>\n<p>就是这么一个念头在睡觉前总会想起，然后一个类似《Beat Saber》的音乐游戏的概念如圣诞老人般，悄然从我脑中的烟囱中钻出，留下了这么一个礼物：面对笔记本的摄像头，游戏里的方块沿着轨道靠近判定网格，再用手指把它们击中。操作简单易懂，而且貌似也比较好实现。</p>\n<p>于是我便利用ai，在做题空闲时描述下需求，一共五六次对话，就做出来了初版。（AI大人的实力真实愈发恐怖了。）</p>\n<p><WebsiteCard\n  url=\"https://finger-block.vercel.app/\"\n  title=\"FingerBlock\"\n  description=\"点击即可跳转尝试玩一玩\"\n/></p>\n<p>项目代码已经放在 <a href=\"https://github.com/MarkXuJQ/finger-block\">GitHub：MarkXuJQ/finger-block</a> 中。这篇文章记录下我是如何确定游戏的基础设定，以及选用了那些技术选型，和一点点优化的操作。</p>\n<h2>项目的基础技术结构</h2>\n<ul>\n<li>FingerBlock 是一个 <a href=\"https://vite.dev/\">Vite</a> + <a href=\"https://react.dev/\">React</a> 的浏览器端项目，因为这个流程我也比较熟悉了。</li>\n<li>渲染部分使用 <a href=\"https://github.com/pmndrs/react-three-fiber\">React Three Fiber</a> 和 <a href=\"https://threejs.org/\">Three.js</a>，用这个来模仿我们的beatsaber的一点点空间感。</li>\n<li>界面图标使用 <a href=\"https://lucide.dev/\">Lucide</a>，简单高效。</li>\n</ul>\n<p>接下来就该说说游戏的核心内容了：</p>\n<h2>手势识别：MediaPipe</h2>\n<p>手势识别使用了 Google 的 <a href=\"https://github.com/google-ai-edge/mediapipe\">MediaPipe Tasks Vision</a> 中的 Hand Landmarker。它提供了手部关键点检测能力，我们利用这个把识别结果转换成 FingerBlock 所需的输入。</p>\n<blockquote>\n<p><code>useHandTracking.ts</code> 中的流程大致是：</p>\n<ol>\n<li>摄像头启动后，按需加载 MediaPipe 的 WASM 文件和手部模型。</li>\n<li>优先尝试 GPU delegate，失败时回退到 CPU delegate。</li>\n<li>限制最多追踪两只手，并读取每只手的食指尖关键点，也就是第 8 个 landmark。</li>\n<li>摄像头画面给玩家看到的是镜像画面，所以代码会对左右手标签进行交换，保持物理左右和画面左右的一致性。</li>\n<li>通过 <code>videoLandmarkToViewport</code> 把视频坐标转换为视口坐标，再由 <code>getLaneFromPoint</code> 映射到 &gt;3×3 或 4×4 判定网格。</li>\n<li>对坐标做简单平滑，减少摄像头逐帧检测带来的抖动。</li>\n</ol>\n</blockquote>\n<p>这时，我想既然有了摄像头用手势进行输入的方法， 不如把触控的方式也做了，这样在手机端也可以玩了，于是我也让AI补齐了这个功能，但值得一提的是，在手机和平板端，常常会由于性能不是特别充足，有较大的延迟，或许这个部分可以后面逐渐优化。下面是具体的思路:</p>\n<blockquote>\n<p>摄像头并不是唯一的输入方式。项目后来加入了 <code>pointer</code> 模式，鼠标和触控都可以直接在判定区域操作。触控使用 <code>pointerId</code> 和 pointer capture 追踪多个手指，即使没有触发新的 <code>pointermove</code>，也会通过持续的 presence loop 维持 Hold。这样即使浏览器已经取得摄像头权限，玩家仍然可以切换到触控完成一局。</p>\n</blockquote>\n<h2>音频分析：把音频处理放到 Worker</h2>\n<h3>从固定谱子转向自动生成</h3>\n<p>在完成手势识别的功能，我让AI先完成了一段固定曲谱的小样，尝试我的想法是否可行，结果很不错，可以很好的捕捉我的食指位置，识别的也还算准确。</p>\n<p>固定谱子跑通之后，内容制作的问题就出现了。</p>\n<p>我没有任何音乐版权，也没有能力和时间为大量歌曲手工制作谱子。如果想要像其他音游一样，需要人工标记时间点、位置和方块类型，游戏的扩展成本会很高。但又如果不放音乐，只用固定的曲谱来玩的话，也未免太无聊了些。</p>\n<p><img src=\"https://img.markxu.icu/img20260921125520686.png\" alt=\"Dead as Disco\"></p>\n<p>这时我想到了 Steam 游戏《<a href=\"https://store.steampowered.com/app/3404260/Dead_as_Disco/\">Dead as Disco</a>》。我虽然从来没有上手玩过，但是看到过这个游戏的游戏视频。这个让我意识到，我们或许可以和这个游戏一样，尝试做一套音乐分析，然后把根据分析结果来自动生成曲谱，让玩家自己上传自己喜欢的音乐，岂不美哉？</p>\n<h3>具体实现</h3>\n<p>音乐导入支持浏览器能够解码的 MP3、WAV、M4A/MP4 和 OGG，单个文件限制为 80 MB，时长限制为 12 分钟，这应该足以应付绝大部分的音乐了，不然一个人玩12分钟的音游也够累的。随后通过 Web Audio API 的 <code>decodeAudioData()</code> 在当前浏览器中解码。</p>\n<blockquote>\n<p><code>analysis-core.ts</code> 的处理过程比简单读取 BPM 更完整：</p>\n<ul>\n<li>先把多声道混合成单声道，并统一重采样到 22,050 Hz；</li>\n<li>以大约 50 毫秒为一帧计算整体 RMS 能量；</li>\n<li>使用 180 Hz 的低通结果估计低频能量；</li>\n<li>按时间窗口生成归一化能量曲线和波形预览；</li>\n<li>根据当前帧与前几帧的能量差寻找瞬态，也就是可能对应鼓点或明显起音的时间点；</li>\n<li>使用 <code>music-tempo</code> 的 Beatroot 算法分析 BPM 和节拍候选；</li>\n<li>将歌曲切分为 quiet、normal 和 peak 三种能量乐段；</li>\n<li>根据节拍匹配率和瞬态覆盖率计算一个置信度。</li>\n</ul>\n</blockquote>\n<p>我使用的 <a href=\"https://github.com/killercrush/music-tempo\">music-tempo</a> 是 MIT 许可证的轻量 BPM/节拍分析库。它适合在浏览器 Worker 中快速给出候选结果，但它不可能对所有弱节奏、自由速度或长时间静音的音乐都判断正确，所以界面保留了人工调整 BPM、首拍和 0.5×/1×/2× 倍速的能力。当然在绝大部分下还是可以卡上大部分的节奏的。</p>\n<h2>自动谱面生成：规则约束</h2>\n<p><code>chart-generator.ts</code> 使用固定种子的伪随机数生成器。种子由歌曲标识、网格大小、难度、BPM 和首拍共同决定，因此同一首音乐在同一组设置下会稳定得到同一份谱面，调整参数后才会得到新的结果。或许这样可以保证一定的稳定性。</p>\n<p>生成器会从音频分析结果里读取节拍、能量和瞬态，再根据 easy、normal、hard 三种配置决定采样步长、密度、和弦概率、Hold 概率和最大移动距离。</p>\n<p>方块的颜色也和音乐特征相关：重拍或强瞬态生成红色的 <code>accent</code> 方块，普通方块是蓝色，部分非整拍的低强度事件会被标成黄色的可选 <code>bonus</code>。这样来保证游戏的一定的可玩性，同时也利用视觉增强了音乐的节奏性。</p>\n<p>不过，真正麻烦的地方在于“随机内容必须仍然可以被双手完成”。人最多就两个食指，天花乱坠的随机方块肯定不能让人类完成，所以我又在项目里加入了几类约束。</p>\n<h3>同一时间最多占用两根手指</h3>\n<p>首先把双手食指视为同时可用的最大输入数，生成器用 <code>MAX_SIMULTANEOUS_NOTES = 2</code> 约束重叠判定窗口内的方块数量。即使两个方块的时间戳不完全相同，只要它们处于同一个击打窗口，也会被视为在竞争同样的两根手指。</p>\n<p>在高能量的重拍上可以生成双击，但也会检查附近是否已经有足够的方块，避免意外生成第三个同时需要处理的目标。</p>\n<h3>中间格不放 Hold</h3>\n<p>从远处接近的 3D 轨道会让中央区域承担重要的视觉参照。如果长时间方块出现在中间，它可能遮住深度轮廓，也会干扰玩家观察后续方块。因此 <code>lane-rules.ts</code> 先定义了 3×3 的一个中心格和 4×4 的四个中心格，<code>beatmap.ts</code> 在校验时直接拒绝位于这些格子的 Hold。</p>\n<p>这条规则同时存在于生成阶段和最终谱面校验阶段：生成器使用 <code>excludeCenter</code> 避开中心，校验器则防止未来手工或外部谱面绕过生成器写入非法 Hold。这样规则就不只是一个“希望遵守”的约定，而是变成了数据层的约束。</p>\n<h3>Hold 会限制另一只手</h3>\n<p>Hold 不是一个只在起点判定一次的长方块。命中起点后，玩家需要让同一只手持续占据对应格子，项目每 0.25 秒结算一次持续分数，并允许约 0.18 秒的短暂追踪宽限。如果中途松开，已经获得的分数会保留，不会额外再记一次 Miss。</p>\n<blockquote>\n<p>因为一只手被 Hold 占用，另一只手的活动空间就变小了。生成器因此会：</p>\n<ul>\n<li>只在持续时间足够长、能量不低的非安静乐段中生成 Hold；</li>\n<li>Hold 期间把自由手的生成密度降到普通状态的一部分；</li>\n<li>让自由手尽量在整拍出现，并预留更长的节拍间隔；</li>\n<li>限制自由手的移动距离，并优先选择 Hold 所在区域的另一侧；</li>\n<li>Hold 结束后留出恢复空档，再逐渐恢复移动距离和密度。</li>\n</ul>\n</blockquote>\n<p>普通难度的 Hold 持续时间约为两个节拍，简单难度更长，困难难度更短但密度更高。双 Hold 只在足够长的旋律乐段中低概率出现，而且会放在网格的相对两侧，让左右手各自有清楚的目标。<code>laneBlockedUntil</code> 还会阻止同一格在 Hold 结束前生成新的音符。</p>\n<h3>最终还要校验谱面</h3>\n<p>所有生成的内容都会经过 <code>validateBeatmap()</code>：检查版本、网格大小、难度、歌曲信息、音符排序、音符 ID、颜色与角色是否匹配、Hold 时长是否有效，以及同一格上的音符是否重叠。生成器负责创造内容，校验器负责确保内容符合数据契约，这让后续修改规则时更容易发现问题。</p>\n<h2>游戏音效：用少量素材组成一套鼓组</h2>\n<p>在AI时代，逻辑实现变得容易了，但是素材仍然是一个难题，好在网络上有着大量的cc0的开源素材可以使用。由于大部分的音乐都可以垫一层底鼓（不能垫鼓的音乐也不适合玩音游😄），所以很自然的想到使用架子鼓的声音来做打击音效，所有用到的音源都在<code>public/assets/ATTRIBUTIONS.md</code> 中记录了来源、许可证、获取时间、处理方式和 SHA-256 校验值。</p>\n<blockquote>\n<p>当前的击打音效来自 <a href=\"https://freesound.org/\">Freesound</a> 上显示为 CC0 的五条录音，包含 KEVOY 的 side stick 和 rimshot、TheEndOfACycle 的 closed hat 和 sub kick，以及 quatricise 的 shaker。项目使用 FFmpeg 对它们做了裁切、淡出、峰值限制、采样率和 Vorbis OGG 转换；<code>miss.ogg</code> 则是低通、低增益处理后的低音闷击。</p>\n<p>运行时并不是把六个 OGG 当成六种互不相关的提示音，而是按鼓组分层：</p>\n<ul>\n<li>普通 Hit 播放 side stick；</li>\n<li>Good 在其上叠加轻微 rim；</li>\n<li>Perfect 再加入 closed hat；</li>\n<li>Accent 额外叠加低音 kick；</li>\n<li>Bonus 叠加 shaker；</li>\n<li>Miss 使用单独的低音闷击。</li>\n</ul>\n</blockquote>\n<p>这种设计让不同判定之间有共同的音色锚点，又能通过层数和音色变化区分反馈。音乐通道和效果音通道也分别经过 AudioContext 的 GainNode 控制，避免命中音效覆盖用户导入的音乐。</p>\n<h2>最后的微调和简单设计</h2>\n<p>核心逻辑跑通之后，剩下的工作主要是不断试玩和微调：方块的移动速度、轨道的深度感、判定网格的位置、摄像头游标的平滑程度、命中时的闪光和碎片、HUD 上的分数和连击、不同难度的密度，以及音乐和效果音的相对音量。</p>\n<h3>时钟、判定和反馈</h3>\n<p>游戏运行时没有把普通的 <code>setInterval</code> 当作唯一时钟。音乐播放使用 Web Audio 的 <code>AudioContext</code> 和 <code>AudioBufferSourceNode</code>，<code>MusicClock</code> 记录音频上下文中的开始时间和暂停位置，游戏逻辑再根据这条音乐时间轴计算方块位置和判定。</p>\n<blockquote>\n<p>普通方块的判定窗口是 ±0.26 秒，其中 ±0.07 秒为 Perfect，±0.15 秒内为 Good，其余仍在总窗口内则为 Hit。普通命中分值分别是 1000、650 和 350，红色 Accent 方块还有 1.2 倍基础分加成。黄色 Bonus 不完全等同于普通漏击目标，它承担的是可选奖励的角色。</p>\n<p>Hold 的持续分数也被写成了确定性的函数：每 0.25 秒只消费完整的计分区间，并把时间截断在 Hold 结束处。即使浏览器某一帧延迟了几百毫秒，也不会因为动画帧数量不同而得到不同的持续分数。</p>\n</blockquote>\n<p>命中反馈由 <code>judgement-events.ts</code> 统一生成，Three.js 场景负责播放闪光、扩散环、线框和碎片效果，来增强打击感；结算页还会绘制累计准确率曲线和 Miss 时间点。项目也会在页面隐藏时冻结音乐时钟和 Hold 的补偿逻辑，避免切到后台后回来，方块因为页面暂停而整体跳过判定区域。</p>\n<p>当然这一部分完成的很粗糙，因为我感觉大体上已经实现了我的想法了，后续如果没有特殊情况应该也不会再继续优化了。</p>\n<h2>最后的感想</h2>\n<h3>一天半完成一个可以玩的 Demo</h3>\n<p>从看到手势识别库更新，到最后完成一个可以运行的 FingerBlock Demo，整个过程大约用了一天半。而且这一天半也不是一直坐在电脑前写代码，中间还花了不少时间做题、看课，中午午休时间用来找找开源库、找找素材、研究音频分析方法，以及不断试玩和调整生成规则。</p>\n<p>有一说一，AI 确实把这个 idea 的落地速度提高了一大截。从搭骨架、调音轨解析到塞各种约束规则，很多写起来繁琐的样板代码，现在只要把需求理清楚，然后发给ai，它就能一下子全给你搞定，我所需要做的就是检查和核实。</p>\n<h3>AI 很强，但这次快速实验不全靠AI</h3>\n<p>我不会把这次快速开发 FingerBlock 的demo完全归功于 AI。</p>\n<p>正如我之前写过的一篇<a href=\"https://markxu.icu/blog/prompt-only-open-source-cn\">当开源只剩下一段 Prompt：我发现了一种“离谱”的开源方式</a>，里面提到的一样，几段好的prompt、清晰的技术栈和恰到好处的素材链接，才是发挥ai最大作用，提高效率的关键。</p>\n<p>AI 可以承担越来越多具体的执行工作，但我们不能因此把基本的思考和规划也全部交出去。掌握这些基础能力，才能更快判断一个想法是否可行，更准确地寻找合适的开源资源，也才能看懂 AI 生成的代码到底解决了什么问题、又留下了什么问题。<strong>或许是从 Web coding 到当下 Vibe coding 还保留不变的技术关键。</strong></p>\n<hr>\n<p>9月23日<br>\n坏了，感觉现在再做一遍的话，ai貌似可以做到更多，更好，这是我在群里看到的消息，这些游戏真的可以玩。</p>\n<blockquote>\n<p>以下内容皆使用 Claude Opus 5.5 一句话提示词生成</p>\n<p>QQ飞车：<a href=\"https://lf3-static.bytednsdoc.com/obj/eden-cn/nulojnulwlo/qqfeiche3d/index.html\">https://lf3-static.bytednsdoc.com/obj/eden-cn/nulojnulwlo/qqfeiche3d/index.html</a></p>\n<p>穿越火线之运输船 : <a href=\"https://lf3-static.bytednsdoc.com/obj/eden-cn/nulojnulwlo/cf-transport-ship/transport-ship.html\">https://lf3-static.bytednsdoc.com/obj/eden-cn/nulojnulwlo/cf-transport-ship/transport-ship.html</a></p>\n<p>鹈鹕骑自行车: <a href=\"https://lf3-static.bytednsdoc.com/obj/eden-cn/nulojnulwlo/pelican-bike/index.html\">https://lf3-static.bytednsdoc.com/obj/eden-cn/nulojnulwlo/pelican-bike/index.html</a></p>\n</blockquote>\n<hr>\n<p>9月25日</p>\n<p>今天在网上刷视频刷到了这么个网站，感觉和我的思路有共同之处，还蛮惊喜的.不过这个就要求对音乐要有点点乐理基础，当然玩法也更自由。而且确实蛮cool。</p>\n<p>视频：</p>\n<p><VideoEmbed\n  url=\"https://www.bilibili.com/video/BV16WYZ6mEb3/?spm_id_from=333.1007.top_right_bar_window_default_collection.content.click&vd_source=a1d2d12b1c9f3d1bf63ac9d24e2ff565\"\n  title=\"yesterday演唱视频\"\n/></p>\n<p>网站：<br>\n<WebsiteCard\n  url=\"https://gesture-synth-weld.vercel.app\"\n  title=\"gesture-synth-weld\"\n  description=\"刷视频刷到的网站\"\n/></p>\n",
      "summary": "偶然看到的一个手势识别库的更新消息，让我来了灵感，于是做了一个简易的音游 Demo。",
      "date_published": "2026-09-19T00:00:00.000Z",
      "date_modified": "2026-09-26T00:00:00.000Z",
      "image": "https://markxu.icu/images/fingerblock-preview.png",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/blog/rss-feed-beautification-cn",
      "url": "https://markxu.icu/blog/rss-feed-beautification-cn",
      "title": "RSS订阅界面美化历程",
      "content_text": "TLDR： 在三月份逐渐开发这个网站，做到 RSS 订阅的时候，我给 XML 文件加了一套美化方案，个人很是满意，没想到仅仅两天过后，原来能正常显示的页面突然又只剩下 XML 文档树。后来我去纸鹿大佬的博客交流群里问了一下，纸鹿大佬推荐了 Mayx 的《在 Google 杀死 XSLT 之后的 XML 美化方案》，我看完之后重新梳理了 RSS、Atom 和浏览器渲染之间的关系，于是有了现在这套版本。 为什么做 RSS 美化 所有博客都应该有一个订阅入口。 博客文章往往放在了个人网站上，网页当然可以慢慢看，但如果有人想要长期关注你发布的内容，就需要时不时打开你的个人网站；但如果读者使用 RSS 阅读器，那么新文章发布后就可以自动出现在订阅列表里，不需要每天专门打开网站看看有没有更新。 这听起来很棒不是吗？ 但对于一个不熟悉订阅源的人来说，一打开是一个裸xml文件，估计也会一脸懵。所以我当时就想，既然订阅源要给人看，那就顺便把它也做得像一个页面吧。 况且下面两个图，哪一个直观也不用多说吧。 初始版本 这件事发生在三月初，网站刚刚上线的那段时间，也就是那个时候我刚刚开始添加订阅功能，现在回头看 Git 记录还记录的蛮清楚的： 2 月 28日，添加 feed 依赖包，并创建脚本 generate-rss.js 以根据 content/posts 目录下的文章自动生成 RSS、Atom 和 JSON Feed 文件 3 月 1 日，先把 RSS、Atom 都接上，让文章可以自动生成订阅文件。 3 月 1 日晚上，第一次给 RSS 添加 XSLT。 3 月 2 日，尝试用 把文章内容转成 HTML，同时补了封面图、摘要和订阅链接。 3 月 2 日下午，把订阅源统一成 Atom（感觉实现最方便且适配性广，后续可以考虑加一下JSON Feed（2026.10.4已添加），并把文件移到 目录。 3 月 4 日，增加订阅页面，加入卡片、背景图和弹窗预览，浏览器里打开 时不再是干巴巴的 XML。 当时的思路和大部分有订阅源美化的博客一样： 脚本读取 下的文章，生成 Atom 文件；Atom 文件开头引用 ；浏览器拿到 XML 后，通过 XSLT 把它转换成一个有封面、摘要和日期的 HTML 页面。 效果简单高效，于是我很快就把它合进了网站。 我以为这事儿终于完成了。 第一次看到效果的时候还是挺开心的。点击下面的rss按钮，打开订阅链接，不再是密密麻麻的 XML 文件树，而是和我的博客风格差不多的页面。 就在此时，该来的转折还是来了。 美化方案突然失效 没过几天，我再次打开订阅链接，准备欣赏我的美化方案，也看看还有什么可以继续完善的方法，却发现之前做好的页面不见了。 浏览器里只剩下 XML 裸文件。我一开始以为是自己的问题，可能是后来不断更新网站内容的时候，不小心碰到了脚本的内容，加上睡的晚，可能不小心改了脚本，导致美化页面失效了。之后又怀疑是不是在vibe某一些页面的时候导致 Vercel 的 Atom MIME 类型搞错了？ 我按照自己的经验和AI给的可能性，检查了样式表路径、响应头和构建产物，也重新确认了 XML 文件里有没有 指令。每一项单独看都像是对的，但组合起来就是不工作。本地开发环境能看到效果，线上在chrome中却看不到效果。 随后调整了很多次（做了次消融实验），提交了好几次commit，都没有效果😭。这时候我想着，去问问群里的大佬吧。 大佬们的帮助 于是我去纸鹿大佬的博客交流群里问了一下。当时描述的很简单：我的rss订阅源美化好像不管用了，大佬们知道可能问题出在哪里嘛？ 才不到5分钟，纸鹿大佬甩来 Mayx 佬的文章：《在 Google 杀死 XSLT 之后的 XML 美化方案》。并说Mayx最近刚刚写了一篇有关这个的，你看看。 这篇文章直接解决了我的疑惑：Chrome 计划弃用 XSLT。所以我的美化方案会突然失效，原因不在我，而是浏览器更新后不支持了。 具体原因Mayx佬的博客讲的更好，我也没必要过多赘述。在这里贴一下： 从上面Chrome的弃用XSLT文档中，可以发现，这件事的始作俑者是Mason Freed，他在WHATWG中发起了一个Issue，因为XSLT用的人很少，以及实现XSLT的库很老而且容易出漏洞，所以建议把XSLT从Web标准中删除。在这个Issue中可以发现，有很多人表示不满，毕竟这个功能对想要给自己订阅做美化的博主来说还是很有用的。为了对抗谷歌，还有人做了个网站： 。 而且XSLT虽然用的人占比也许不高，但从总量上应该还是挺多的，除了用XSLT美化博客订阅的，甚至还有用XSLT作为博客框架的，另外还有一些人提出一部分政府网站也有使用XSLT。 不过Freed看起来对这件事早有准备，他做了一个Polyfill库，通过WASM的方式让XSLT可以正常工作，为了方便大家使用这个库，我顺手给CDNJS发了个PR，以后可以用CDN引用它了。不过使用这个库的前提是需要在订阅中加一段引用JS的代码，像我博客中的Atom订阅，用的是jekyll-feed插件，里面的格式都是写死的，就用不了了…… 只不过现在已经没办法阻止谷歌了……而且其他浏览器也表示会跟进，看来我们唯一能做的就是去适应了。 而且这篇博客不止说明了原因，还想了两条替代路线：纯 CSS，以及在 XML 里混入 XHTML。 纯 CSS 可以把标签排列得好看一些，但没办法真正操作文档内容，也不容易给文章加上正常的超链接；混合 XHTML 能补上这些能力，但 XML 依旧是 XML，和 HTML 的 DOM 行为并不完全一样，还会在验证器里出现 之类的警告。 看完之后，我想，如果 XSLT 终究要不支持，大势所趋，我也没有办法。那我不如自己写一个生成脚本，自己生成独立的HTML界面。 现在这版是怎么做的 现在网站使用的是 Atom 作为主要订阅格式，订阅地址放在 目录下。生成脚本 负责几件事： 递归读取文章。 解析语言、slug、日期、摘要和封面。 为不同语言生成 Atom。 同时生成独立静态 HTML 页面，并把 Atom、HTML、XSL 一起复制到 dist。 这个方案虽然看起来有些不太优雅，但至少把浏览器预览和 RSS 订阅拆开了。即使未来所有浏览器都不再支持 XSLT， 和 这样的静态 HTML 页面仍然可以正常访问，RSS 阅读器也仍然可以订阅对应的 Atom XML。当然，我也没有完全删掉 文件，想着留一下，毕竟也曾是互联网上极为高效的一种转换方式。 后续也可以在这里看我们的xsl美化效果. 一点感想 这次找bug的经历让我印象深刻，很感谢大佬们的热心分享，这次经历同时也说明，如果一个新的功能发生改变后，AI在训练的时候没有相关的经历，是没办法快速定位到bug的原因的，或许这也是在AI时代，博客还有一点价值的证明。只有不断的有人在互联网上分享，ai才可以获得足够多的信息，才可以更好的帮助更多的人。 同时我也为xslt这个技术的消失感到惋惜，在我关注的大佬做的这个网站 中，也可以看到还有很多人仍在坚持，想要维护他们习惯的技术栈，但是历史的车轮究竟会怎么样转，我们只能拭目以待。",
      "content_html": "<p>TLDR：</p>\n<p>在三月份逐渐开发这个网站，做到 RSS 订阅的时候，我给 XML 文件加了一套美化方案，个人很是满意，没想到仅仅两天过后，原来能正常显示的页面突然又只剩下 XML 文档树。后来我去纸鹿大佬的博客交流群里问了一下，纸鹿大佬推荐了 <a href=\"https://mayx.eu.org/2026/02/08/xslt.html\">Mayx 的《在 Google 杀死 XSLT 之后的 XML 美化方案》</a>，我看完之后重新梳理了 RSS、Atom 和浏览器渲染之间的关系，于是有了现在这套版本。</p>\n<h2>为什么做 RSS 美化</h2>\n<p><strong>所有博客都应该有一个订阅入口。</strong></p>\n<p>博客文章往往放在了个人网站上，网页当然可以慢慢看，但如果有人想要长期关注你发布的内容，就需要时不时打开你的个人网站；但如果读者使用 RSS 阅读器，那么新文章发布后就可以自动出现在订阅列表里，不需要每天专门打开网站看看有没有更新。</p>\n<p>这听起来很棒不是吗？</p>\n<p>但对于一个不熟悉订阅源的人来说，一打开是一个裸xml文件，估计也会一脸懵。所以我当时就想，既然订阅源要给人看，那就顺便把它也做得像一个页面吧。</p>\n<p>况且下面两个图，哪一个直观也不用多说吧。</p>\n<div class=\"img-grid-2\">\n  <img src=\"https://img.markxu.icu/imgSnipaste_2026-09-13_16-40-08.png\" alt=\"美化之前\" />\n  <img src=\"https://img.markxu.icu/imgSnipaste_2026-09-13_16-26-53.png\" alt=\"美化之后\" />\n</div>\n<h2>初始版本</h2>\n<p>这件事发生在三月初，网站刚刚上线的那段时间，也就是那个时候我刚刚开始添加订阅功能，现在回头看 Git 记录还记录的蛮清楚的：</p>\n<ul>\n<li>2 月 28日，添加 feed 依赖包，并创建脚本 generate-rss.js 以根据 content/posts 目录下的文章自动生成 RSS、Atom 和 JSON Feed 文件</li>\n<li>3 月 1 日，先把 RSS、Atom 都接上，让文章可以自动生成订阅文件。</li>\n<li>3 月 1 日晚上，第一次给 RSS 添加 XSLT。</li>\n<li>3 月 2 日，尝试用 <code>markdown-it</code> 把文章内容转成 HTML，同时补了封面图、摘要和订阅链接。</li>\n<li>3 月 2 日下午，把订阅源统一成 Atom（感觉实现最方便且适配性广，后续可以考虑加一下JSON Feed（2026.10.4已添加），并把文件移到 <code>/feeds/</code> 目录。</li>\n<li>3 月 4 日，增加订阅页面，加入卡片、背景图和弹窗预览，浏览器里打开 <code>/feeds/</code> 时不再是干巴巴的 XML。</li>\n</ul>\n<p>当时的思路和大部分有订阅源美化的博客一样：</p>\n<p>脚本读取 <code>content/posts</code> 下的文章，生成 Atom 文件；Atom 文件开头引用 <code>atom.xsl</code>；浏览器拿到 XML 后，通过 XSLT 把它转换成一个有封面、摘要和日期的 HTML 页面。</p>\n<p>效果简单高效，于是我很快就把它合进了网站。</p>\n<p><strong>我以为这事儿终于完成了。</strong></p>\n<p>第一次看到效果的时候还是挺开心的。点击下面的rss按钮，打开订阅链接，不再是密密麻麻的 XML 文件树，而是和我的博客风格差不多的页面。</p>\n<p>就在此时，该来的转折还是来了。</p>\n<h3>美化方案突然失效</h3>\n<p>没过几天，我再次打开订阅链接，准备欣赏我的美化方案，也看看还有什么可以继续完善的方法，却发现之前做好的页面不见了。</p>\n<p>浏览器里只剩下 XML 裸文件。我一开始以为是自己的问题，可能是后来不断更新网站内容的时候，不小心碰到了脚本的内容，加上睡的晚，可能不小心改了脚本，导致美化页面失效了。之后又怀疑是不是在vibe某一些页面的时候导致 Vercel 的 Atom MIME 类型搞错了？</p>\n<p>我按照自己的经验和AI给的可能性，检查了样式表路径、响应头和构建产物，也重新确认了 XML 文件里有没有 <code>xml-stylesheet</code> 指令。每一项单独看都像是对的，但组合起来就是不工作。本地开发环境能看到效果，线上在chrome中却看不到效果。</p>\n<p>随后调整了很多次（做了次消融实验），提交了好几次commit，都没有效果😭。这时候我想着，去问问群里的大佬吧。</p>\n<h2>大佬们的帮助</h2>\n<p>于是我去纸鹿大佬的博客交流群里问了一下。当时描述的很简单：我的rss订阅源美化好像不管用了，大佬们知道可能问题出在哪里嘛？</p>\n<p>才不到5分钟，纸鹿大佬甩来 Mayx 佬的文章：<a href=\"https://mayx.eu.org/2026/02/08/xslt.html\">《在 Google 杀死 XSLT 之后的 XML 美化方案》</a>。并说Mayx最近刚刚写了一篇有关这个的，你看看。</p>\n<p>这篇文章直接解决了我的疑惑：Chrome 计划弃用 XSLT。所以我的美化方案会突然失效，原因不在我，而是浏览器更新后不支持了。</p>\n<p>具体原因Mayx佬的博客讲的更好，我也没必要过多赘述。在这里贴一下：</p>\n<blockquote>\n<p>从上面Chrome的弃用XSLT文档中，可以发现，这件事的始作俑者是<a href=\"https://github.com/mfreed7\">Mason Freed</a>，他在WHATWG中发起了一个<a href=\"https://github.com/whatwg/html/issues/11523\">Issue</a>，因为XSLT用的人很少，以及实现XSLT的库很老而且容易出漏洞，所以建议把XSLT从Web标准中删除。在这个Issue中可以发现，有很多人表示不满，毕竟这个功能对想要给自己订阅做美化的博主来说还是很有用的。为了对抗谷歌，还有人做了个网站： <a href=\"https://xslt.rip/\">https://xslt.rip</a> 。</p>\n<p>而且XSLT虽然用的人占比也许不高，但从总量上应该还是挺多的，除了用XSLT美化博客订阅的，甚至还有用<a href=\"https://github.com/vgr-land/vgr-xslt-blog-framework\">XSLT作为博客框架的</a>，另外还有一些人提出<a href=\"https://github.com/whatwg/html/issues/11582\">一部分政府网站也有使用XSLT</a>。</p>\n<p>不过Freed看起来对这件事早有准备，他做了一个<a href=\"https://github.com/mfreed7/xslt_polyfill\">Polyfill库</a>，通过WASM的方式让XSLT可以正常工作，为了方便大家使用这个库，我顺手给CDNJS发了个<a href=\"https://github.com/cdnjs/packages/pull/2118\">PR</a>，以后可以用CDN引用它了。不过使用这个库的前提是需要在订阅中加一段引用JS的代码，像我博客中的Atom订阅，用的是<a href=\"https://github.com/jekyll/jekyll-feed\">jekyll-feed</a>插件，里面的格式都是写死的，就用不了了……</p>\n<p>只不过现在已经没办法阻止谷歌了……而且其他浏览器也表示会跟进，看来我们唯一能做的就是去适应了。</p>\n</blockquote>\n<p>而且这篇博客不止说明了原因，还想了两条替代路线：纯 CSS，以及在 XML 里混入 XHTML。</p>\n<p>纯 CSS 可以把标签排列得好看一些，但没办法真正操作文档内容，也不容易给文章加上正常的超链接；混合 XHTML 能补上这些能力，但 XML 依旧是 XML，和 HTML 的 DOM 行为并不完全一样，还会在验证器里出现 <code>Misplaced XHTML content</code> 之类的警告。</p>\n<p>看完之后，我想，如果 XSLT 终究要不支持，大势所趋，我也没有办法。那我不如自己写一个生成脚本，自己生成独立的HTML界面。</p>\n<h2>现在这版是怎么做的</h2>\n<p>现在网站使用的是 Atom 作为主要订阅格式，订阅地址放在 <code>/feeds/</code> 目录下。生成脚本<code>generate-rss.js</code>负责几件事：</p>\n<ol>\n<li>递归读取文章。</li>\n<li>解析语言、slug、日期、摘要和封面。</li>\n<li>为不同语言生成 Atom。</li>\n<li>同时生成独立静态 HTML 页面，并把 Atom、HTML、XSL 一起复制到 dist。</li>\n</ol>\n<p>这个方案虽然看起来有些不太优雅，但至少把浏览器预览和 RSS 订阅拆开了。即使未来所有浏览器都不再支持 XSLT，<code>/feeds/zh/</code> 和 <code>/feeds/en/</code> 这样的静态 HTML 页面仍然可以正常访问，RSS 阅读器也仍然可以订阅对应的 Atom XML。当然，我也没有完全删掉<code>.xsl</code>文件，想着留一下，毕竟也曾是互联网上极为高效的一种转换方式。</p>\n<p>后续也可以在<a href=\"https://markxu.icu/feeds/zh/atom.xml\">这里</a>看我们的xsl美化效果.</p>\n<h2>一点感想</h2>\n<p>这次找bug的经历让我印象深刻，很感谢大佬们的热心分享，这次经历同时也说明，如果一个新的功能发生改变后，AI在训练的时候没有相关的经历，是没办法快速定位到bug的原因的，或许这也是在AI时代，博客还有一点价值的证明。只有不断的有人在互联网上分享，ai才可以获得足够多的信息，才可以更好的帮助更多的人。</p>\n<p>同时我也为xslt这个技术的消失感到惋惜，在我关注的大佬做的这个网站<a href=\"https://xslt.rip/\">https://xslt.rip</a> 中，也可以看到还有很多人仍在坚持，想要维护他们习惯的技术栈，但是历史的车轮究竟会怎么样转，我们只能拭目以待。</p>\n",
      "summary": "记录了我的个人网站的 RSS 订阅的发展过程：能用->美化->突然失效->解决问题。",
      "date_published": "2026-09-13T00:00:00.000Z",
      "image": "https://img.markxu.icu/img16cadbcd5c793.png",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/blog/why-im-not-bullish-on-humanoid-robots-cn",
      "url": "https://markxu.icu/blog/why-im-not-bullish-on-humanoid-robots-cn",
      "title": "为什么我不看好人形机器人？",
      "content_text": "TLDR：我不否认人形机器人在控制、硬件和人工智能上的技术价值，也不认为它会彻底失败。我不看好的是另一件事： “像人”并不自然等于“通用”，“通用”也不自然等于“有用”。 在可靠性、成本、能源、数据和维护问题解决之前，人形机器人更可能先成为科研平台、工业试验品、表演项目和极客玩具，而 不是像个人电脑或智能手机一样铺开，甚至是成为“新质劳动力”，代替蓝领工人 。 未来已来？ 从 25 年春晚的《秧 BOT》开始，人形机器人再一次走入大众视野。宇树 H1 机器人灵活的动作让不少人感觉未来已来，那时的媒体更是原地高潮，让大家觉得未来的科技发展方向貌似又有了一个明确的指向标。 从那时起，我一方面惊叹于人形机器人的灵活性和可玩性，一方面又在怀疑：真的如这些媒体所说的，人形机器人就是未来吗？具身智能真的可以与人形机器人画一个约等号吗？而最近人形机器人运动大会的顺利举办，又让这个话题回到大众讨论的中心。 我想或许应该现在就明确说明自己的判断和立场， 留一个档，以便未来观察 。如果成功了，要看我现在忽略了什么；如果失败了，也要看失败原因是否与我的判断匹配。 明确范围 首先，我想先声明讨论的范围。 我并不是从技术上否定人形机器人。它当然集合了控制、机械、材料、传感器和人工智能等领域很前沿的成果。我不看好的是：人形机器人可以承担起某一部分人所说的“下一代通用生产力”。尤其是“ 像人”=“通用”=“实用 ”这条常见的逻辑链，里面暗含了许多逻辑漏洞，也包含了许多资本喜欢讲的故事。 接下来让我一步一步地讲明白这个问题。 技术难题 我想先试着说明白为什么最近几年国内机器人进步这么快。 进化路线 最早在互联网上持续引起大众关注的，应该是波士顿动力的机器人。早在 2004 年，互联网刚刚兴起，BigDog 项目就已经开始。随着 YouTube 的发展，大家都对这么一个机械狗的能力感到惊叹。其背后的控制技术、全身动力学建模、轨迹优化和接触力求解，这些名字背后是几十年来最聪明的工程师和昂贵硬件共同堆出来的护城河。波士顿动力的机器人一次又一次让人感到惊叹，其背后的技术和算法也无不让人震撼。 这个故事一直到2020年，才出现了变化。 苏黎世联邦理工 RSL 组在《Science Robotics》上发表了那篇著名的 ANYmal 强化学习越野论文，展示了在仿真中训练策略，再迁移到真实机器人上应对复杂地形的路线。 在RL仿真环境下不断训练，结果训练出的策略比BD手调的MPC在复杂地形上跑得还稳。完全不用手搓模型，而且还把代码开源了。 后来的 、 ，加上 NVIDIA Isaac Gym 等工具，又不断降低了训练和复现门槛；宇树等厂商则把电驱机器人的硬件价格打了下来。MPC几十年筑起的城墙，使用RL，轻松绕过去了。过去只有少数顶尖团队才能接触的能力，开始被更多实验室和公司复现。 这其实是一次很了不起的技术突破。通过RL把桌子掀掉，利用最前沿的技术段时间完成了以前超乎想象的工作：很多难以完整手工建模的动作，可以先在仿真里通过大量试错学出来，再和传统控制、状态估计、安全约束组合使用。原来高高的技术门槛，就这样被绕开了一部分。 从这之后，国内公司有了成本更低、迭代更快的路线去实现机器人的运动控制，于是各种各样的机器狗和人形机器人开始逐渐出现在市场上。 仍然面临的挑战 让我们从简单逐渐向难的来说。 首先是能源问题。当然，目前已经有换电池的解决方案，还说得过去，但这也意味着机器人的工作范围和工作时长仍然受到限制。对一个表演十分钟的机器人来说这不算致命问题，但对一个要连续工作八小时、还要携带负载的生产工具来说，这就是直接影响成本的问题。 其次是结构问题。目前许多人形机器人采用电机驱动关节，而关节又要同时面对 扭矩、散热、重量、冲击和寿命 等互相牵制的问题。这方面我了解得并不多，不敢展开谈具体方案，但我知道演示一个动作和每天重复几千次动作，面对的是完全不同的工程标准。摔倒一次能不能自己站起来，连续工作后精度会不会漂移，关节坏了多久能换好，这些小问题累加起来最终都会出现在账单里。 最后是大脑。强化学习让机器人的运动和平衡能力进步了很多，但这更接近“小脑”的部分：怎样落脚、怎样保持稳定、怎样完成已经定义好的动作。真正决定机器人能否被广泛使用的，是它能不能理解环境、规划任务、处理意外，并且知道自己什么时候做不到。 这也是当前 世界模型（World Model）（这里有一个很好的简单的介绍（并不是简短！））、长程任务规划、开放环境下的语义理解与异常应对这几个主流的研究方向。（其实这几个方向最后效果如何也有不少质疑的声音） 目前很多公司开始收集数据，希望像大语言模型一样通过 Scaling Law 实现一次突破。但现实世界的数据不像文本一样可以直接从互联网上下载。一段机器人数据需要真实硬件执行，需要标注动作和结果，还可能伴随磨损、碰撞和人工接管。 换句话说，语言模型可以用互联网上的文本“免费”训练， 而机器人模型每一次“学习”，都在磨损硬件、消耗电量和人力。 这种成本结构，决定了它很难简单复制大语言模型的爆发路径。 更麻烦的是，不同本体、不同相机位置、不同关节参数采集的数据能不能相互迁移，这与我所熟悉的医学图像领域遇到的难题类似，甚至要更为麻烦，而医学图像至今也没有像语言模型那样清晰的答案。 所以“大脑”不仅是模型够不够聪明的问题，也是数据从哪里来、错误由谁承担、能力能否稳定复现的问题。 都是谁在买机器人——市场与应用空间 有些机器人公司已经拥有不错的收入，而且宇树公司的数据也显示他们早已实现盈利，但这不能直接说明人形机器人已经有了广大的终端市场。我们首先要看都是谁在买这些机器人，又拿它们来做什么。 根据新闻和公开案例推断，目前真正稳定投入生产的人形机器人仍然很少，更多购买者是高校、研究机构、展厅和需要做二次开发的公司。我常常看到某些高校为实验室里有一台宇树机器人而宣传，也常看到机器人出现在发布会、商场和运动会上，但很少看到工厂公开展示它已经连续运行了多久、替代了多少成本、产生了多少稳定产能。 根据摩根士丹利的数据是，65%拿去展示、接待、搞科研，真上产线的只有35%。宇树给上交所交的材料更直白：2025年前三季度， 人形机器人收入73.6%来自科研教育。 而上产线的又有多少是为了讲故事？也暂时不可考纠。 这里的机器人更多的是一个论文生产工具、资本叙事对象、热度炒作方向。 我更愿意把它理解成一个昂贵的乐高模型，或者更贴切地说，类似于大疆 RoboMaster：它是一个很好的教学、研究和开发平台，也可以形成比赛、表演和爱好者文化，但这和它成为普遍生产工具是两回事。 当然，试验项目本来就是量产之前的必经阶段。我并不是说“现在没有，所以以后也没有”。我只是认为，在讨论市场时不能把送进实验室、展厅和试点产线的每一台机器人，都提前算作已经被验证的生产力。 那这时候就有人说了，当前没有市场，不代表其潜在市场不大。现在社会中的各种器械都是按照人体工程学设计的，所以将来最通用的也只能是人形机器人。 但这个逻辑并不闭环。 像人≠通用≠有用 这里有两个逻辑推理并不正确，首先像人≠通用，其次通用≠有用。 人手当然非常灵活，但它并不是为了现代工业环境而设计出来的。关于人手形态的演化有许多解释，抓握、投掷和使用工具都可能参与其中，可以参考这篇讨论投掷与人手演化关系的论文。但当今社会的发展已经远远快于生物进化的速度。我们会发明不同工具来做不同的事情，本来就是为了弥补手做不好的地方。 这本身就是“通用≠有用”的一个例子。螺丝用手也可以勉强扭动，但有螺丝刀会拧得更紧，有棘轮螺丝刀会拧得又快又紧，而产线上还会直接使用定扭矩电动工具。人手很通用，最后真正提高生产力的，往往是那些看起来一点也不通用的工具。 这些工具的演进都是工业积累，为什么不能平移到机器人上？轮式底盘移动效率更高，机械臂定位更稳定，夹具可以直接适配零件，传送带甚至不需要“理解”自己在运输什么。当一个场景足够固定时，企业通常会优先改造环境和流程，而不是购买一个具备两条腿、十根手指和全身平衡能力的复杂机器。 即使确实需要适应多种任务，也不一定非得完整模仿人。模块化的末端工具、可以快速更换的夹具、移动底盘加机械臂，再让本来就足够聪明的人类处理少数例外，或许是更便宜、更可靠的迁移方案。 人形机器人最大的悖论在于，它试图用最通用的身体，去解决最不通用的任务。 人形结构真正的优势，是可以直接进入为人设计的环境，不需要先改门、楼梯和工具。但这个优势也有一个隐藏前提： 改造环境的成本，必须高于维持人形结构复杂度的成本。 在家庭、灾区或老旧建筑里，这个前提可能成立；在可以重新规划的工厂和仓库里，它未必成立。 那么应用空间有哪些？ 在我看来，人形结构不可替代的应用，反而可能不是最常被宣传的流水线，而是那些“像人”本身就有价值的场景。如果未来真的能做出足够像人的机器人， 让人摸起来、看起来、聊起来都像人 ，它当然可以成为虚拟乐园里的 NPC 或者陪伴机器人。那时，人形不是为了勉强兼容一把扳手，而是产品体验本身。 从我认为又由简单到难的顺序排序，我认为更接近下面的进程： 《铁甲钢拳》里面的拳击机器人——体育赛事 《A.I》中的家庭陪护机器人——陪护情感机器人 《西部世界》里面的虚拟乐园NPC——娱乐设施 《底特律：变人》里面承担各种基础工作的通用机器人——蓝领工人替代者 而我们目前距离科幻作品里的状态很远。所以当下的市场和科技水平，只能证明“我们已经可以造出越来越灵活的人形机器人”，并不能直接证明“机器人越像人，就越接近一条正确的商业路线”。 为什么大家都在看好人形机器人？ 接下来我想谈谈人形机器人在当下讨论中有关的几点。 情绪怎样产生的？ 首先是电影等一系列科幻作品，让大家不自觉地对人形机器人抱有许多玫瑰色的幻想。相比一条机械臂，人形机器人更容易被拍摄、传播和理解。它只要走两步、挥挥手，在头部显示一个表情，观众就可以马上与其共情。 正如上面写的那些应用空间，人形机器人不是没有未来，而是我们经常把科幻作品已经替它完成的想象，当成了现实产品已经完成的能力。 现在的经济环境低迷，大家急需寻找一个突破口来拉动投资。我们的 唯物主义教育又反复强调生产力和科技进步的重要性 ，所以大家天然愿意支持看得见、摸得着的先进生产力，希望通过一次技术飞升改善现有处境。人形机器人恰好满足了这种期待：有人工智能的想象空间，又有实体机器的视觉冲击，还能连接制造业和供应链。 资本、地方政府、媒体和创业公司也都有动力把这个故事继续讲下去。资本需要足够大的潜在市场，地方需要新的产业名片，媒体需要吸引眼球的画面，创业公司则必须先说服别人未来足够大，才有钱把今天并不成熟的产品继续做下去。这些动力不一定意味着骗局，但会让讨论天然偏向最乐观的那个版本。 最常见观点的反驳 最有名也最好反驳的观点——所有技术一开始都不是一帆风顺的。 有人会举汽车作为例子，也有人会举飞机、手机和移动互联网。它们一开始都遭遇过质疑，后面却实打实地改变了人类生活。 但人形机器人并不是第一次出现在大众视野。 20 世纪 80 年代，Heathkit 推出过 HERO 1，Tomy 也推出过 Omnibot 这类“家庭机器人”。它们能移动、发声，有些还能通过简单机械臂夹取东西，当时同样承载了家庭自动化的想象，后来却没有成为家用电器的一部分。 大家记得住的只是已经成功的产品。当初被看好、后来却没有大规模普及的技术同样不少，只是人们在争论时选择性地跳过了它们，恰好进入了 幸存者偏差 。 比如氢气飞艇、协和式超音速客机、3D 电视、Google Glass 和前几年的元宇宙。它们并非每一个都在技术上彻底失败，有些甚至直到今天仍有小范围应用，但它们都没有兑现最热闹时期“即将改变每个人生活”的承诺。 这些例子或多或少都符合当前人形机器人的某些特征：演示很震撼，技术确实先进，也能找到真实需求，但成本、配套设施、可靠性或者社会接受度，让它们难以按照最初的想象扩张。 所以“以前有人看错过汽车”并不能证明今天质疑人形机器人也是错的。要完成这个论证，至少还需要回答几个更具体的问题：它解决了什么非它不可的问题？比人类或专用设备便宜多少？离开精心布置的演示环境还能完成多少任务？故障、维护和安全成本又由谁承担？ 可能的发展 但我又不至于悲观到认为人形机器人会一事无成。我认为它最终或许会更接近前几年同样大火的区块链技术。 区块链是一个经典的“过度承诺、兑现不足，但留下了一部分真实能力”的案例，与我心里想的机器人的发展路线大致重合，所以就用区块链来做例子。 2017 年 ICO 最热的时候，许多项目只要写一份白皮书就能融到大量资金，仿佛所有行业都应该上链；2018年—2019年，泡沫破裂后，大量项目归零，区块链又被整体骂成骗局。而到了今天，投机的那一批人退去，但底层技术稳定币、跨境结算等少数场景确实在继续发展。 也就是说，泡沫和技术并不是只能二选一。 一个方向可以同时包含真实的技术进步、过高的商业承诺和大量追逐风口的项目。 泡沫退去后，留下来的不一定是最初故事里的产品，却可能是训练框架、低成本关节、传感器、控制算法、供应链和一批真正懂机器人系统的工程师。积累一批真正有用的技术，然后被拆下来装进别的地方。 我猜人形机器人也会经历类似的过程： 在热潮中，每家公司都要做人形机器人，每个发布会都要让机器人走几步。 资本开始要求收入和复购后，一批找不到稳定场景的公司退出，行业进入幻灭期。 剩下的公司不再强调“通用”，而是进入几个具体场景，老老实实解决一个动作、一道工序或者一种危险环境。 人形结构的一部分技术被拆出来，进入机械臂、外骨骼、轮式机器人和其他专用设备。 人形结构的一部分和传感技术可以辅助残疾人，就像火箭和MRI的关系。 如果最后真是这样，我不会认为人形机器人失败了。失败的是“它很快就会成为每个家庭和每座工厂里的通用劳动力”这个过度膨胀的叙事，而不是这些年积累下来的技术。 在不看好人形机器人的时候，我会看好什么？ 我真正看好的，是人形机器人背后的 AI 模型、感知和推理能力。 一个可以理解现实世界的模型，能够识别物体之间的关系，理解人的意图，预测一个动作会产生什么结果，才可能是具身智能里真正通用的部分。它不一定非要装进人形身体里，也可以控制机械臂、无人机、汽车、轮式底盘，甚至只作为人的辅助系统存在。 相比于复刻人类的身体，我更看好以下几条路线： 针对明确任务设计的专用机器人，例如仓储、清洁、巡检、农业和手术机器人 移动底盘、机械臂和可更换末端工具组成的模块化系统 由人远程接管、模型逐渐学习的半自动系统，而不是一开始就追求完全自主 可以跨本体迁移的视觉语言动作模型、世界模型和机器人数据基础设施 这些方向没有一个完整人形机器人在舞台上翻跟头那么震撼，却更可能先进入真实世界。因为使用者购买的不是“智能感”，而是一个任务可以更便宜、更稳定、更安全地完成。 我认为人形机器人会怎么样？ 我认为后续的人形机器人不会铺开得特别广泛，但会成为一种新的玩具和社交文化。随着价格下降，会有越来越多学校、实验室和爱好者开发自己的动作、外观和 AI 模型，带着机器人参加格斗、足球、竞速和障碍赛。它可能会像 RoboMaster、无人机和早期个人电脑一样，先形成一个充满创造力的爱好者生态。 与此同时，它也会进入少量不适合改造环境、又需要人类形态的场景。在这些地方，一台机器人即使昂贵、缓慢，只要能避免人类进入危险环境，就已经有价值。还有一些机器人会以租赁、表演、营销和陪伴产品的形式存在。它们可能是一门不错的生意，只是不是“替代所有劳动”的那门生意。 当然，我也给未来的自己留几条可以被打脸的标准。如果未来的人形机器人能够： 在没有预先编排的家庭或工厂里连续工作数小时，并且很少需要人工接管； 换一个场地后，不需要重新采集大量数据就能学习新任务； 把购买、能耗、维护、停机和安全成本全部算进去后，仍然比人类或专用设备更划算； 从发布会上的演示品变成可以批量交付、稳定维护、明确承担责任的标准产品； 那么我会承认，现在的判断低估了通用模型的迁移能力，也低估了规模化生产降低复杂硬件成本的速度。到那时，“像人”或许真的不只是营销上最容易理解的外形，而是适应人类世界最经济的方案。 但在这些事情发生之前，我仍然不愿意把一段流畅的舞蹈、一场机器人足球赛，或者一条剪辑精美的工厂视频，当成下一代生产力已经到来的证据。 人形机器人当然代表未来的一部分，只是未来从来不会只长成科幻电影里最熟悉的样子。真正改变生活的技术，有时恰恰是那些不再像人、不再适合登上舞台，却已经安静工作了很多年的机器。 2026-9-19更新： 这篇文章在知乎上有收到两条评论，都提出我这篇文章有稻草人谬误的情况。即先立了一个容易击打且不会还手的靶子，然后去攻击他。现在看来确实有点这个意思。 可以点击这个卡片跳转过去看看。",
      "content_html": "<p>TLDR：我不否认人形机器人在控制、硬件和人工智能上的技术价值，也不认为它会彻底失败。我不看好的是另一件事：<strong>“像人”并不自然等于“通用”，“通用”也不自然等于“有用”。</strong> 在可靠性、成本、能源、数据和维护问题解决之前，人形机器人更可能先成为科研平台、工业试验品、表演项目和极客玩具，而<strong>不是像个人电脑或智能手机一样铺开，甚至是成为“新质劳动力”，代替蓝领工人</strong>。</p>\n<h2>未来已来？</h2>\n<p>从 25 年春晚的《秧 BOT》开始，人形机器人再一次走入大众视野。宇树 H1 机器人灵活的动作让不少人感觉未来已来，那时的媒体更是原地高潮，让大家觉得未来的科技发展方向貌似又有了一个明确的指向标。</p>\n<p><img src=\"https://img.markxu.icu/img20260915194338349.png\" alt=\"25 年春晚的《秧 BOT》\"></p>\n<p>从那时起，我一方面惊叹于人形机器人的灵活性和可玩性，一方面又在怀疑：真的如这些媒体所说的，人形机器人就是未来吗？具身智能真的可以与人形机器人画一个约等号吗？而最近人形机器人运动大会的顺利举办，又让这个话题回到大众讨论的中心。</p>\n<p>我想或许应该现在就明确说明自己的判断和立场，<strong>留一个档，以便未来观察</strong>。如果成功了，要看我现在忽略了什么；如果失败了，也要看失败原因是否与我的判断匹配。</p>\n<h2>明确范围</h2>\n<p>首先，我想先声明讨论的范围。</p>\n<p>我并不是从技术上否定人形机器人。它当然集合了控制、机械、材料、传感器和人工智能等领域很前沿的成果。我不看好的是：人形机器人可以承担起某一部分人所说的“下一代通用生产力”。尤其是“<strong>像人”=“通用”=“实用</strong>”这条常见的逻辑链，里面暗含了许多逻辑漏洞，也包含了许多资本喜欢讲的故事。</p>\n<p><img src=\"https://img.markxu.icu/imgbeedda696b2788.png\" alt=\"“像人”=“通用”=“实用”并不成立\"></p>\n<p>接下来让我一步一步地讲明白这个问题。</p>\n<h2>技术难题</h2>\n<p>我想先试着说明白为什么最近几年国内机器人进步这么快。</p>\n<h3>进化路线</h3>\n<p>最早在互联网上持续引起大众关注的，应该是波士顿动力的机器人。早在 2004 年，互联网刚刚兴起，BigDog 项目就已经开始。随着 YouTube 的发展，大家都对这么一个机械狗的能力感到惊叹。其背后的控制技术、全身动力学建模、轨迹优化和接触力求解，这些名字背后是几十年来最聪明的工程师和昂贵硬件共同堆出来的护城河。波士顿动力的机器人一次又一次让人感到惊叹，其背后的技术和算法也无不让人震撼。</p>\n<p><img src=\"https://img.markxu.icu/img20260915194918828.png\" alt=\"BigDog\"></p>\n<p>这个故事一直到2020年，才出现了变化。</p>\n<p>苏黎世联邦理工 RSL 组在《Science Robotics》上发表了那篇著名的 <a href=\"https://www.science.org/doi/10.1126/scirobotics.abc5986\">ANYmal 强化学习越野论文</a>，展示了在仿真中训练策略，再迁移到真实机器人上应对复杂地形的路线。</p>\n<p><img src=\"https://img.markxu.icu/img20260915195616416.png\" alt=\"图画的真好看啊\"></p>\n<p>在RL仿真环境下不断训练，结果训练出的策略比BD手调的MPC在复杂地形上跑得还稳。完全不用手搓模型，而且还把代码开源了。</p>\n<p>后来的 <code>rsl_rl</code>、<code>legged_gym</code>，加上 NVIDIA Isaac Gym 等工具，又不断降低了训练和复现门槛；宇树等厂商则把电驱机器人的硬件价格打了下来。MPC几十年筑起的城墙，使用RL，轻松绕过去了。过去只有少数顶尖团队才能接触的能力，开始被更多实验室和公司复现。</p>\n<p><img src=\"https://img.markxu.icu/imgjo2b13ed-fh26-4b7f-odr0-60q841b2-medium.webp\" alt=\"运行示例\"></p>\n<p>这其实是一次很了不起的技术突破。通过RL把桌子掀掉，利用最前沿的技术段时间完成了以前超乎想象的工作：很多难以完整手工建模的动作，可以先在仿真里通过大量试错学出来，再和传统控制、状态估计、安全约束组合使用。原来高高的技术门槛，就这样被绕开了一部分。</p>\n<p>从这之后，国内公司有了成本更低、迭代更快的路线去实现机器人的运动控制，于是各种各样的机器狗和人形机器人开始逐渐出现在市场上。</p>\n<h3>仍然面临的挑战</h3>\n<p>让我们从简单逐渐向难的来说。</p>\n<p>首先是能源问题。当然，目前已经有换电池的解决方案，还说得过去，但这也意味着机器人的工作范围和工作时长仍然受到限制。对一个表演十分钟的机器人来说这不算致命问题，但对一个要连续工作八小时、还要携带负载的生产工具来说，这就是直接影响成本的问题。</p>\n<p>其次是结构问题。目前许多人形机器人采用电机驱动关节，而关节又要同时面对<strong>扭矩、散热、重量、冲击和寿命</strong>等互相牵制的问题。这方面我了解得并不多，不敢展开谈具体方案，但我知道演示一个动作和每天重复几千次动作，面对的是完全不同的工程标准。摔倒一次能不能自己站起来，连续工作后精度会不会漂移，关节坏了多久能换好，这些小问题累加起来最终都会出现在账单里。</p>\n<p>最后是大脑。强化学习让机器人的运动和平衡能力进步了很多，但这更接近“小脑”的部分：怎样落脚、怎样保持稳定、怎样完成已经定义好的动作。真正决定机器人能否被广泛使用的，是它能不能理解环境、规划任务、处理意外，并且知道自己什么时候做不到。</p>\n<p>这也是当前 <a href=\"https://liyang.page/wm-tutorial/\">世界模型（World Model）</a>（这里有一个很好的简单的介绍（并不是简短！））、长程任务规划、开放环境下的语义理解与异常应对这几个主流的研究方向。（其实这几个方向最后效果如何也有不少质疑的声音）</p>\n<p><img src=\"https://img.markxu.icu/img20260915200112273.png\" alt=\"Training A World\"></p>\n<p>目前很多公司开始收集数据，希望像大语言模型一样通过 Scaling Law 实现一次突破。但现实世界的数据不像文本一样可以直接从互联网上下载。一段机器人数据需要真实硬件执行，需要标注动作和结果，还可能伴随磨损、碰撞和人工接管。</p>\n<p>换句话说，语言模型可以用互联网上的文本“免费”训练，<strong>而机器人模型每一次“学习”，都在磨损硬件、消耗电量和人力。</strong> 这种成本结构，决定了它很难简单复制大语言模型的爆发路径。</p>\n<p>更麻烦的是，不同本体、不同相机位置、不同关节参数采集的数据能不能相互迁移，这与我所熟悉的医学图像领域遇到的难题类似，甚至要更为麻烦，而医学图像至今也没有像语言模型那样清晰的答案。</p>\n<p>所以“大脑”不仅是模型够不够聪明的问题，也是数据从哪里来、错误由谁承担、能力能否稳定复现的问题。</p>\n<h2>都是谁在买机器人——市场与应用空间</h2>\n<p>有些机器人公司已经拥有不错的收入，而且宇树公司的数据也显示他们早已实现盈利，但这不能直接说明人形机器人已经有了广大的终端市场。我们首先要看都是谁在买这些机器人，又拿它们来做什么。</p>\n<p>根据新闻和公开案例推断，目前真正稳定投入生产的人形机器人仍然很少，更多购买者是高校、研究机构、展厅和需要做二次开发的公司。我常常看到某些高校为实验室里有一台宇树机器人而宣传，也常看到机器人出现在发布会、商场和运动会上，但很少看到工厂公开展示它已经连续运行了多久、替代了多少成本、产生了多少稳定产能。</p>\n<p><img src=\"https://img.markxu.icu/img20260915200554010.png\" alt=\"宇树机器人\"></p>\n<p>根据摩根士丹利的数据是，65%拿去展示、接待、搞科研，真上产线的只有35%。宇树给上交所交的材料更直白：2025年前三季度，<strong>人形机器人收入73.6%来自科研教育。</strong> 而上产线的又有多少是为了讲故事？也暂时不可考纠。</p>\n<p>这里的机器人更多的是一个论文生产工具、资本叙事对象、热度炒作方向。</p>\n<p>我更愿意把它理解成一个昂贵的乐高模型，或者更贴切地说，类似于大疆 RoboMaster：它是一个很好的教学、研究和开发平台，也可以形成比赛、表演和爱好者文化，但这和它成为普遍生产工具是两回事。</p>\n<p><img src=\"https://img.markxu.icu/img20260915200647133.png\" alt=\"RoboMaster比赛\"></p>\n<p>当然，试验项目本来就是量产之前的必经阶段。我并不是说“现在没有，所以以后也没有”。我只是认为，在讨论市场时不能把送进实验室、展厅和试点产线的每一台机器人，都提前算作已经被验证的生产力。</p>\n<p>那这时候就有人说了，当前没有市场，不代表其潜在市场不大。现在社会中的各种器械都是按照人体工程学设计的，所以将来最通用的也只能是人形机器人。</p>\n<p>但这个逻辑并不闭环。</p>\n<h3>像人≠通用≠有用</h3>\n<p>这里有两个逻辑推理并不正确，首先像人≠通用，其次通用≠有用。</p>\n<p>人手当然非常灵活，但它并不是为了现代工业环境而设计出来的。关于人手形态的演化有许多解释，抓握、投掷和使用工具都可能参与其中，可以参考这篇讨论<a href=\"https://onlinelibrary.wiley.com/doi/10.1046/j.1469-7580.2003.00185.x\">投掷与人手演化关系的论文</a>。但当今社会的发展已经远远快于生物进化的速度。我们会发明不同工具来做不同的事情，本来就是为了弥补手做不好的地方。</p>\n<p>这本身就是“通用≠有用”的一个例子。螺丝用手也可以勉强扭动，但有螺丝刀会拧得更紧，有棘轮螺丝刀会拧得又快又紧，而产线上还会直接使用定扭矩电动工具。人手很通用，最后真正提高生产力的，往往是那些看起来一点也不通用的工具。</p>\n<p><img src=\"https://img.markxu.icu/img20260915200814210.png\" alt=\"工业机器人\"></p>\n<p>这些工具的演进都是工业积累，为什么不能平移到机器人上？轮式底盘移动效率更高，机械臂定位更稳定，夹具可以直接适配零件，传送带甚至不需要“理解”自己在运输什么。当一个场景足够固定时，企业通常会优先改造环境和流程，而不是购买一个具备两条腿、十根手指和全身平衡能力的复杂机器。</p>\n<p>即使确实需要适应多种任务，也不一定非得完整模仿人。模块化的末端工具、可以快速更换的夹具、移动底盘加机械臂，再让本来就足够聪明的人类处理少数例外，或许是更便宜、更可靠的迁移方案。</p>\n<p>人形机器人最大的悖论在于，它试图用最通用的身体，去解决最不通用的任务。</p>\n<p>人形结构真正的优势，是可以直接进入为人设计的环境，不需要先改门、楼梯和工具。但这个优势也有一个隐藏前提：<strong>改造环境的成本，必须高于维持人形结构复杂度的成本。</strong>  在家庭、灾区或老旧建筑里，这个前提可能成立；在可以重新规划的工厂和仓库里，它未必成立。</p>\n<h3>那么应用空间有哪些？</h3>\n<p>在我看来，人形结构不可替代的应用，反而可能不是最常被宣传的流水线，而是那些“像人”本身就有价值的场景。如果未来真的能做出足够像人的机器人，<strong>让人摸起来、看起来、聊起来都像人</strong> ，它当然可以成为虚拟乐园里的 NPC 或者陪伴机器人。那时，人形不是为了勉强兼容一把扳手，而是产品体验本身。</p>\n<p>从我认为又由简单到难的顺序排序，我认为更接近下面的进程：</p>\n<ul>\n<li>《铁甲钢拳》里面的拳击机器人——体育赛事</li>\n<li>《A.I》中的家庭陪护机器人——陪护情感机器人</li>\n<li>《西部世界》里面的虚拟乐园NPC——娱乐设施</li>\n<li>《底特律：变人》里面承担各种基础工作的通用机器人——蓝领工人替代者</li>\n</ul>\n<p><img src=\"https://img.markxu.icu/img20260915200855629.png\" alt=\"《西部世界》的机器人\"></p>\n<p>而我们目前距离科幻作品里的状态很远。所以当下的市场和科技水平，只能证明“我们已经可以造出越来越灵活的人形机器人”，并不能直接证明“机器人越像人，就越接近一条正确的商业路线”。</p>\n<h2>为什么大家都在看好人形机器人？</h2>\n<p>接下来我想谈谈人形机器人在当下讨论中有关的几点。</p>\n<h3>情绪怎样产生的？</h3>\n<p>首先是电影等一系列科幻作品，让大家不自觉地对人形机器人抱有许多玫瑰色的幻想。相比一条机械臂，人形机器人更容易被拍摄、传播和理解。它只要走两步、挥挥手，在头部显示一个表情，观众就可以马上与其共情。</p>\n<p>正如上面写的那些应用空间，人形机器人不是没有未来，而是我们经常把科幻作品已经替它完成的想象，当成了现实产品已经完成的能力。</p>\n<p>现在的经济环境低迷，大家急需寻找一个突破口来拉动投资。我们的<strong>唯物主义教育又反复强调生产力和科技进步的重要性</strong> ，所以大家天然愿意支持看得见、摸得着的先进生产力，希望通过一次技术飞升改善现有处境。人形机器人恰好满足了这种期待：有人工智能的想象空间，又有实体机器的视觉冲击，还能连接制造业和供应链。</p>\n<p><img src=\"https://img.markxu.icu/img20260915201013436.png\" alt=\"黑格尔和马克思\"></p>\n<p>资本、地方政府、媒体和创业公司也都有动力把这个故事继续讲下去。资本需要足够大的潜在市场，地方需要新的产业名片，媒体需要吸引眼球的画面，创业公司则必须先说服别人未来足够大，才有钱把今天并不成熟的产品继续做下去。这些动力不一定意味着骗局，但会让讨论天然偏向最乐观的那个版本。</p>\n<h3>最常见观点的反驳</h3>\n<p>最有名也最好反驳的观点——所有技术一开始都不是一帆风顺的。</p>\n<p>有人会举汽车作为例子，也有人会举飞机、手机和移动互联网。它们一开始都遭遇过质疑，后面却实打实地改变了人类生活。</p>\n<p><strong>但人形机器人并不是第一次出现在大众视野。</strong></p>\n<p>20 世纪 80 年代，Heathkit 推出过 HERO 1，Tomy 也推出过 Omnibot 这类“家庭机器人”。它们能移动、发声，有些还能通过简单机械臂夹取东西，当时同样承载了家庭自动化的想象，后来却没有成为家用电器的一部分。</p>\n<p><img src=\"https://img.markxu.icu/img20260915201142303.png\" alt=\"Omnibot\"></p>\n<p>大家记得住的只是已经成功的产品。当初被看好、后来却没有大规模普及的技术同样不少，只是人们在争论时选择性地跳过了它们，恰好进入了<strong>幸存者偏差</strong> 。</p>\n<p>比如氢气飞艇、协和式超音速客机、3D 电视、Google Glass 和前几年的元宇宙。它们并非每一个都在技术上彻底失败，有些甚至直到今天仍有小范围应用，但它们都没有兑现最热闹时期“即将改变每个人生活”的承诺。</p>\n<p><img src=\"https://img.markxu.icu/img20260915201224958.png\" alt=\"飞艇\"></p>\n<p>这些例子或多或少都符合当前人形机器人的某些特征：演示很震撼，技术确实先进，也能找到真实需求，但成本、配套设施、可靠性或者社会接受度，让它们难以按照最初的想象扩张。</p>\n<p>所以“以前有人看错过汽车”并不能证明今天质疑人形机器人也是错的。要完成这个论证，至少还需要回答几个更具体的问题：它解决了什么非它不可的问题？比人类或专用设备便宜多少？离开精心布置的演示环境还能完成多少任务？故障、维护和安全成本又由谁承担？</p>\n<h2>可能的发展</h2>\n<p>但我又不至于悲观到认为人形机器人会一事无成。我认为它最终或许会更接近前几年同样大火的区块链技术。</p>\n<p>区块链是一个经典的“过度承诺、兑现不足，但留下了一部分真实能力”的案例，与我心里想的机器人的发展路线大致重合，所以就用区块链来做例子。</p>\n<p>2017 年 ICO 最热的时候，许多项目只要写一份白皮书就能融到大量资金，仿佛所有行业都应该上链；2018年—2019年，泡沫破裂后，大量项目归零，区块链又被整体骂成骗局。而到了今天，投机的那一批人退去，但底层技术稳定币、跨境结算等少数场景确实在继续发展。</p>\n<p><img src=\"https://img.markxu.icu/img20260915201304479.png\" alt=\"区块链技术催生的加密货币\"></p>\n<p>也就是说，泡沫和技术并不是只能二选一。<strong>一个方向可以同时包含真实的技术进步、过高的商业承诺和大量追逐风口的项目。</strong>  泡沫退去后，留下来的不一定是最初故事里的产品，却可能是训练框架、低成本关节、传感器、控制算法、供应链和一批真正懂机器人系统的工程师。积累一批真正有用的技术，然后被拆下来装进别的地方。</p>\n<p>我猜人形机器人也会经历类似的过程：</p>\n<ol>\n<li>在热潮中，每家公司都要做人形机器人，每个发布会都要让机器人走几步。</li>\n<li>资本开始要求收入和复购后，一批找不到稳定场景的公司退出，行业进入幻灭期。</li>\n<li>剩下的公司不再强调“通用”，而是进入几个具体场景，老老实实解决一个动作、一道工序或者一种危险环境。</li>\n<li>人形结构的一部分技术被拆出来，进入机械臂、外骨骼、轮式机器人和其他专用设备。</li>\n<li>人形结构的一部分和传感技术可以辅助残疾人，就像火箭和MRI的关系。</li>\n</ol>\n<p>如果最后真是这样，我不会认为人形机器人失败了。失败的是“它很快就会成为每个家庭和每座工厂里的通用劳动力”这个过度膨胀的叙事，而不是这些年积累下来的技术。</p>\n<h2>在不看好人形机器人的时候，我会看好什么？</h2>\n<p>我真正看好的，是人形机器人背后的 AI 模型、感知和推理能力。</p>\n<p>一个可以理解现实世界的模型，能够识别物体之间的关系，理解人的意图，预测一个动作会产生什么结果，才可能是具身智能里真正通用的部分。它不一定非要装进人形身体里，也可以控制机械臂、无人机、汽车、轮式底盘，甚至只作为人的辅助系统存在。</p>\n<p><img src=\"https://img.markxu.icu/img20260915201419981.png\" alt=\"手术机器人\"></p>\n<p>相比于复刻人类的身体，我更看好以下几条路线：</p>\n<ul>\n<li>针对明确任务设计的专用机器人，例如仓储、清洁、巡检、农业和手术机器人</li>\n<li>移动底盘、机械臂和可更换末端工具组成的模块化系统</li>\n<li>由人远程接管、模型逐渐学习的半自动系统，而不是一开始就追求完全自主</li>\n<li>可以跨本体迁移的视觉语言动作模型、世界模型和机器人数据基础设施</li>\n</ul>\n<p>这些方向没有一个完整人形机器人在舞台上翻跟头那么震撼，却更可能先进入真实世界。因为使用者购买的不是“智能感”，而是一个任务可以更便宜、更稳定、更安全地完成。</p>\n<h2>我认为人形机器人会怎么样？</h2>\n<p>我认为后续的人形机器人不会铺开得特别广泛，但会成为一种新的玩具和社交文化。随着价格下降，会有越来越多学校、实验室和爱好者开发自己的动作、外观和 AI 模型，带着机器人参加格斗、足球、竞速和障碍赛。它可能会像 RoboMaster、无人机和早期个人电脑一样，先形成一个充满创造力的爱好者生态。</p>\n<p><img src=\"https://img.markxu.icu/img20260915201547585.png\" alt=\"《铁甲钢拳》英国首映\"></p>\n<p>与此同时，它也会进入少量不适合改造环境、又需要人类形态的场景。在这些地方，一台机器人即使昂贵、缓慢，只要能避免人类进入危险环境，就已经有价值。还有一些机器人会以租赁、表演、营销和陪伴产品的形式存在。它们可能是一门不错的生意，只是不是“替代所有劳动”的那门生意。</p>\n<p>当然，我也给未来的自己留几条可以被打脸的标准。如果未来的人形机器人能够：</p>\n<ol>\n<li>在没有预先编排的家庭或工厂里连续工作数小时，并且很少需要人工接管；</li>\n<li>换一个场地后，不需要重新采集大量数据就能学习新任务；</li>\n<li>把购买、能耗、维护、停机和安全成本全部算进去后，仍然比人类或专用设备更划算；</li>\n<li>从发布会上的演示品变成可以批量交付、稳定维护、明确承担责任的标准产品；</li>\n</ol>\n<p>那么我会承认，现在的判断低估了通用模型的迁移能力，也低估了规模化生产降低复杂硬件成本的速度。到那时，“像人”或许真的不只是营销上最容易理解的外形，而是适应人类世界最经济的方案。</p>\n<p><img src=\"https://img.markxu.icu/img20260915202135584.png\" alt=\"机器人运动会\"></p>\n<p>但在这些事情发生之前，我仍然不愿意把一段流畅的舞蹈、一场机器人足球赛，或者一条剪辑精美的工厂视频，当成下一代生产力已经到来的证据。</p>\n<p>人形机器人当然代表未来的一部分，只是未来从来不会只长成科幻电影里最熟悉的样子。真正改变生活的技术，有时恰恰是那些不再像人、不再适合登上舞台，却已经安静工作了很多年的机器。</p>\n<hr>\n<p>2026-9-19更新：</p>\n<p>这篇文章在知乎上有收到两条评论，都提出我这篇文章有稻草人谬误的情况。即先立了一个容易击打且不会还手的靶子，然后去攻击他。现在看来确实有点这个意思。</p>\n<p><WebsiteCard\n  url=\"https://zhuanlan.zhihu.com/p/2083297787320583911\"\n  title=\"知乎链接\"\n  description=\"跳转到知乎看看大家的评论\"\n/></p>\n<p>可以点击这个卡片跳转过去看看。</p>\n",
      "summary": "我一直不看好人形机器人会成为下一代通用生产力。我想把现在的判断留个档：如果以后被打脸，也能回头看看行业究竟克服了哪些我不看好的问题。",
      "date_published": "2026-08-31T00:00:00.000Z",
      "date_modified": "2026-09-19T00:00:00.000Z",
      "image": "https://img.markxu.icu/img20260915182504981.png",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/blog/frontend-effects-resources-cn",
      "url": "https://markxu.icu/blog/frontend-effects-resources-cn",
      "title": "现在做网页特效有多简单？一些前端组件与动画资源分享",
      "content_text": "这一篇就是一个简短的资源分享，没有太多实际内容，分享一下我最近浏览到的很炫酷的网站组件资源。 CanvasUI-实验性产品 这是一个有着比较新技术组件库，它使用了chrome浏览器最近新的 HTML-in-Canvas 的试验性功能，让 DOM/HTML 内容可以参与 Canvas 中的渲染和视觉变换。目前这仍属于比较新的浏览器能力，其兼容性需要特别注意。好在 Canvas UI 本身考虑了 fallback，在不支持相关能力的浏览器下也可以提供降级方案，让你的网站有正常的功能，但是少了效果可能就不会那么好看了。 这尤其适合需要 3D、液态、玻璃、破碎等复杂视觉效果的网页，可以去看下网页提供的预览效果，然后决定是否是自己想要的效果。个人认为可以试验用着玩玩，不是很建议放到实际的生产端，一是适配性很受限，二是比较吃性能，对低端设备不是很友好。 React Bits-特殊效果 一个以 React 为核心的特效组件集合，同时提供 JavaScript / TypeScript、CSS / Tailwind 等不同实现方式。里面有着各种各样的炫酷效果，大部分专注于文字特效和背景交互特效。主要以比较特殊的视觉效果为主，有点花里胡哨的，可以多从中吸取些经验和灵感，但不建议大批量的使用。 Aceternity-务实落地 依旧是一个 React 的组件库，但整体风格比较务实，方便使用，且风格适用广。 虽然有付费使用的 template 效果也还不错，但是免费的权限就很够用了，我个人认为付费的那些 template 其实直接交给现在的ai去做效果不一定会更差，反而可能会很贴合你的需求，很适合去探索探索，获取些交互和设计上的灵感。 Magic UI -作为补充 仍然是一个react主要使用的小组件库，区别和上面的 Aceternity 差别不大，会有一些上方没有的交互效果，虽然这个站点的内容不是很多，但可以作为互补。 Motion-自己设计动画 Motion 更准确来说是一个动画库，而不是传统意义上的 UI 组件库。它提供了 JavaScript、React、Vue 等环境下的动画能力，可以用来处理页面过渡、手势、布局变化以及各种交互动画。 我的网站就用了些motion的效果，用起来还是很不错的。如果你不只是想“找一个现成组件”，而是希望自己控制动画，那么 Motion 比单纯的组件库更值得研究，可以多去探索探索。 anime JS-动画字典 这个网站本身就炫酷的不行，是一个主要注重动画效果的网页库，里面有着各种各样的动画曲线，也有着很多交互元素的设计效果。 你可以用它控制 DOM、SVG、CSS 属性等各种对象的动画，非常适合拿来研究各种动画节奏、缓动和交互方式。可以作为一个动画效果的字典去使用，十分推荐任何想要去学习设计的同学去学习。 Animate UI-微量调整 Animate UI 的组件数量相比前面的几个库少一些，但它比较值得看的地方是微交互，尤其是 Icon、Button 等组件的动画。对于已经有完整 UI，只是觉得页面“有点死”的项目来说，这类效果反而比较实用。 Inspira UI-专注Vue的组件库 上面的全都是 React 的组件库，那我们 Vue 用户吃什么？ 哈哈哈，这不就来了？ 这是一个主要服务于 Vue 和 Nuxt 架构的动画库，效果也很全面，从简单的 ui 到全局的特效都有，里面的大部分内容已经足够对齐上方提到的 React 的组件库了。 不过这里也不意味着 Vue 用户只能使用 Vue 的组件库。React 组件本身当然不能直接复制进 Vue 项目，但很多视觉效果实际上并不依赖 React 本身，尤其是 CSS、SVG、Canvas 和普通 JavaScript 实现的效果。现在有了 AI，把一个 React 组件改写成 Vue 版本通常已经比以前简单很多，所以我自己找组件的时候也不会特别在意它到底是 React 还是 Vue。 21st.dev-个人常用✨ 这是我自己个人用的最多的网站，包括我首页上的标题的动画效果，以及 电影页面 上的CINEMA的效果都是从这个网站上找的灵感，并融合了点自己的想法。网站里面的预览和分类让整体的操作很符合直觉，用起来很方便，效果也全面，很推荐大家去上面逛逛玩一下。 写在最后 以前看到一个很酷的效果，通常意味着你需要把它的代码研究一遍，再想办法塞进自己的项目里。现在有了AI，完全是两个世界了，要简单很多： 先找到自己喜欢的效果，再把组件的实现方式、依赖和自己的需求告诉 AI，让它帮你修改，已经变成了一个非常实用的工作流。 所以我现在逛这些网站的时候，已经不太会把它们单纯当成“组件库”了。很多时候我只是去找一个我喜欢的视觉效果，然后自己重新实现。 组件库负责提供灵感和参考，AI 负责帮你把它变成适合自己网站的东西。 上面推荐了很多动画效果的组件库，但是对于一个网页来说，最重要的不是看起来有多么炫酷，而是使用起来符不符合用户直觉，用户的体验是不是流畅。一个上手门槛、设备门槛合理的网站才是最好的网站。 动画应该帮助用户理解页面的结构、状态和反馈，而不是让用户为了看动画而等待。过多的视觉效果不仅可能影响信息获取，也会增加性能和设备方面的负担。",
      "content_html": "<p>这一篇就是一个简短的资源分享，没有太多实际内容，分享一下我最近浏览到的很炫酷的网站组件资源。</p>\n<h2>CanvasUI-实验性产品</h2>\n<p><WebsiteCard\n  url=\"https://canvasui.dev/\"\n  title=\"Canvas UI\"\n  description=\"依赖Chrome的HTML-in-Canvas这个实验功能的组件库\"\n/></p>\n<p>这是一个有着比较新技术组件库，它使用了chrome浏览器最近新的 HTML-in-Canvas 的试验性功能，让 DOM/HTML 内容可以参与 Canvas 中的渲染和视觉变换。目前这仍属于比较新的浏览器能力，其兼容性需要特别注意。好在 Canvas UI 本身考虑了 fallback，在不支持相关能力的浏览器下也可以提供降级方案，让你的网站有正常的功能，但是少了效果可能就不会那么好看了。</p>\n<p>这尤其适合需要 3D、液态、玻璃、破碎等复杂视觉效果的网页，可以去看下网页提供的预览效果，然后决定是否是自己想要的效果。个人认为可以试验用着玩玩，不是很建议放到实际的生产端，一是适配性很受限，二是比较吃性能，对低端设备不是很友好。</p>\n<h2>React Bits-特殊效果</h2>\n<p><WebsiteCard\n  url=\"https://reactbits.dev/\"\n  title=\"React Bits\"\n  description=\"一些React的特效小组件\"\n/></p>\n<p>一个以 React 为核心的特效组件集合，同时提供 JavaScript / TypeScript、CSS / Tailwind 等不同实现方式。里面有着各种各样的炫酷效果，大部分专注于文字特效和背景交互特效。主要以比较特殊的视觉效果为主，有点花里胡哨的，可以多从中吸取些经验和灵感，但不建议大批量的使用。</p>\n<h2>Aceternity-务实落地</h2>\n<p><WebsiteCard\n  url=\"https://ui.aceternity.com/\"\n  title=\"Aceternity\"\n  description=\"依旧一些React的小组件，但是主要比较务实\"\n/></p>\n<p>依旧是一个 React 的组件库，但整体风格比较务实，方便使用，且风格适用广。</p>\n<p>虽然有付费使用的 template 效果也还不错，但是免费的权限就很够用了，我个人认为付费的那些 template 其实直接交给现在的ai去做效果不一定会更差，反而可能会很贴合你的需求，很适合去探索探索，获取些交互和设计上的灵感。</p>\n<h2>Magic UI -作为补充</h2>\n<p><WebsiteCard\n  url=\"https://magicui.design/\"\n  title=\"Magic UI\"\n  description=\"还是小组件和template库，用React, Typescript, Tailwind CSS 和 Motion打造\"\n/></p>\n<p>仍然是一个react主要使用的小组件库，区别和上面的 Aceternity 差别不大，会有一些上方没有的交互效果，虽然这个站点的内容不是很多，但可以作为互补。</p>\n<h2>Motion-自己设计动画</h2>\n<p><WebsiteCard\n  url=\"https://motion.dev/\"\n  title=\"Motion\"\n  description=\"支持JS，React和Vue的动画效果库\"\n/></p>\n<p>Motion 更准确来说是一个动画库，而不是传统意义上的 UI 组件库。它提供了 JavaScript、React、Vue 等环境下的动画能力，可以用来处理页面过渡、手势、布局变化以及各种交互动画。</p>\n<p>我的网站就用了些motion的效果，用起来还是很不错的。如果你不只是想“找一个现成组件”，而是希望自己控制动画，那么 Motion 比单纯的组件库更值得研究，可以多去探索探索。</p>\n<h2>anime JS-动画字典</h2>\n<p><WebsiteCard\n  url=\"https://animejs.com/\"\n  title=\"anime JS\"\n  description=\"支持原生JS和React的动画效果库\"\n/></p>\n<p>这个网站本身就炫酷的不行，是一个主要注重动画效果的网页库，里面有着各种各样的动画曲线，也有着很多交互元素的设计效果。</p>\n<p>你可以用它控制 DOM、SVG、CSS 属性等各种对象的动画，非常适合拿来研究各种动画节奏、缓动和交互方式。可以作为一个动画效果的字典去使用，十分推荐任何想要去学习设计的同学去学习。</p>\n<h2>Animate UI-微量调整</h2>\n<p><WebsiteCard\n  url=\"https://animate-ui.com/\"\n  title=\"animate-ui\"\n  description=\"依旧是一个React的组件库\"\n/></p>\n<p>Animate UI 的组件数量相比前面的几个库少一些，但它比较值得看的地方是微交互，尤其是 Icon、Button 等组件的动画。对于已经有完整 UI，只是觉得页面“有点死”的项目来说，这类效果反而比较实用。</p>\n<h2>Inspira UI-专注Vue的组件库</h2>\n<p><WebsiteCard\n  url=\"https://inspira-ui.com/\"\n  title=\"Inspira UI\"\n  description=\"终于，一个专门服务于Vue和Nuxt架构的动画库\"\n/></p>\n<p>上面的全都是 React 的组件库，那我们 Vue 用户吃什么？</p>\n<p>哈哈哈，这不就来了？</p>\n<p>这是一个主要服务于 Vue 和 Nuxt 架构的动画库，效果也很全面，从简单的 ui 到全局的特效都有，里面的大部分内容已经足够对齐上方提到的 React 的组件库了。</p>\n<p>不过这里也不意味着 Vue 用户只能使用 Vue 的组件库。React 组件本身当然不能直接复制进 Vue 项目，但很多视觉效果实际上并不依赖 React 本身，尤其是 CSS、SVG、Canvas 和普通 JavaScript 实现的效果。现在有了 AI，把一个 React 组件改写成 Vue 版本通常已经比以前简单很多，所以我自己找组件的时候也不会特别在意它到底是 React 还是 Vue。</p>\n<h2>21st.dev-个人常用✨</h2>\n<p><WebsiteCard\n  url=\"https://21st.dev/\"\n  title=\"21st\"\n  description=\"我个人最常用的网站，效果感觉也是最多样的\"\n/></p>\n<p>这是我自己个人用的最多的网站，包括我首页上的标题的动画效果，以及 <a href=\"https://markxu.icu/movies\">电影页面</a> 上的CINEMA的效果都是从这个网站上找的灵感，并融合了点自己的想法。网站里面的预览和分类让整体的操作很符合直觉，用起来很方便，效果也全面，很推荐大家去上面逛逛玩一下。</p>\n<h2>写在最后</h2>\n<p>以前看到一个很酷的效果，通常意味着你需要把它的代码研究一遍，再想办法塞进自己的项目里。现在有了AI，完全是两个世界了，要简单很多：<strong>先找到自己喜欢的效果，再把组件的实现方式、依赖和自己的需求告诉 AI，让它帮你修改，已经变成了一个非常实用的工作流。</strong></p>\n<p>所以我现在逛这些网站的时候，已经不太会把它们单纯当成“组件库”了。很多时候我只是去找一个我喜欢的视觉效果，然后自己重新实现。</p>\n<p>组件库负责提供灵感和参考，AI 负责帮你把它变成适合自己网站的东西。</p>\n<p>上面推荐了很多动画效果的组件库，但是对于一个网页来说，最重要的不是看起来有多么炫酷，而是使用起来符不符合用户直觉，用户的体验是不是流畅。一个上手门槛、设备门槛合理的网站才是最好的网站。</p>\n<p><strong>动画应该帮助用户理解页面的结构、状态和反馈，而不是让用户为了看动画而等待。过多的视觉效果不仅可能影响信息获取，也会增加性能和设备方面的负担。</strong></p>\n",
      "summary": "分享下最近我在网上看到的很炫酷的前端组件！",
      "date_published": "2026-08-29T00:00:00.000Z",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/movies/reviews/%E9%BE%99%E9%A4%90%E5%8E%85",
      "url": "https://markxu.icu/movies/reviews/%E9%BE%99%E9%A4%90%E5%8E%85",
      "title": "欢迎来龙餐馆",
      "content_text": "版权归作者所有，任何形式转载请联系作者。 作者：MarkXu（来自豆瓣） 来源： 只是看到有人说不错就来看了，完全没有任何期待，主演是谁也不知道，以为欢迎来到龙餐厅是成龙演的喜剧呢。但是电影开头看到沈腾老师也很惊喜。 电影开始，讲的就是一个普通的小人物到外国打工然后白手起家的故事，没有人可以拒绝这种题材，前部分生活气息也很足，安安稳稳的过日子，也蛮有奔头。 影片正式进入主题 电影真正进入正题是在第一次轰炸，电影的场景做的很细致，看到拦截弹在城市上空飞旋，落下的炸弹炸倒一幢幢建筑物，真的让人感受到人对战争的无能为力和渺小感。 正是这场轰炸，让我们看到美帝国主义的邪恶嘴脸，我也以为这个电影的反派就是单纯的美军，像是国外的主旋律电影一样，就是纳粹德国，但是电影明显还要讨论更多。 随后进入电影的中期部分，主角利用身份，发战争财。这里出现了一个全新的角色身份，ABC 的大兵。这种角色的设定是在从前的剧本中几乎不存在的，李治廷演的也特别好，很完美的诠释这个角色在一个中国人面前，在一个陌生环境下，其具有的无根性和孤独感。让我们体会到，美国大兵也是普普通通的人，甚至由于受到的教育和其身份的原因，显得尤为孩子气和自卑。 到这里，可以说是美帝国主义是坏的，把美国的普通人也送到了战场，去侵略其他国家，都是政客的错，但电影又一次带给我惊喜，不像画靶射箭，而是让情节继续发展下去。 电影更高一层的升华 进入了电影的最后阶段-监禁，这里电影仍然很自然的放入了两个视角，被美方监禁和被极端分子监禁。在美方监禁期间，体现了美国的恃强凌弱，霸权主义思想盛行。而在极端组织监禁期间，又很好的体现了极端分子是如何利用宗教不择手段的使用儿童来进行恐怖活动，以谋求报复。 而一个中国人，与两方无关的一个局外人视角，充分的展现了战争的残酷性和人性的复杂。我们一直看美国拍的电影，虽然反战，但仍然是有正义的一方，比如黑鹰坠落，但是这一个电影的主旋律是中方一贯以来的反战思想，是一个世界人民大团结的主旋律。结合现在美帝国联合以色列对中东采取的行动，更是讽刺。 或许我们需要更多这样的主旋律电影，让世界看清楚我们的目的不是霸权主义再次崛起，而是为了天安门上的那两句话的后半部分，也是我们的最终理想。 ps：电影虽然有些瑕疵，节奏总体来说是比较不错，但是小细节上还是可以再优化一下，瑕不掩瑜。为这部电影的所有工作人员点赞，里面的军事行动真的很专业，其残酷性和荒诞感也展示的到位而不夸张煽情。更值得肯定的是中国还是有好演员在的，李治廷和蒋奇明演的也很好，沈腾更不必多说。最后的最后，里面角色的发展路线和情感铺垫都做的不错，有很多很出彩的设定和设计，包括老扎和赛夫的几次转变都很精彩 ๑•̀ㅂ•́ و✧",
      "content_html": "<p>版权归作者所有，任何形式转载请联系作者。<br>\n作者：MarkXu（来自豆瓣）<br>\n来源：<a href=\"https://movie.douban.com/review/17761941/\">https://movie.douban.com/review/17761941/</a></p>\n<p>只是看到有人说不错就来看了，完全没有任何期待，主演是谁也不知道，以为欢迎来到龙餐厅是成龙演的喜剧呢。但是电影开头看到沈腾老师也很惊喜。</p>\n<p>电影开始，讲的就是一个普通的小人物到外国打工然后白手起家的故事，没有人可以拒绝这种题材，前部分生活气息也很足，安安稳稳的过日子，也蛮有奔头。</p>\n<h2>影片正式进入主题</h2>\n<p>电影真正进入正题是在第一次轰炸，电影的场景做的很细致，看到拦截弹在城市上空飞旋，落下的炸弹炸倒一幢幢建筑物，真的让人感受到人对战争的无能为力和渺小感。</p>\n<p><img src=\"https://image.tmdb.org/t/p/original/lvbFIfbHWTOqS9gLHretfAz0gih.jpg\" alt=\"电影转折点\"></p>\n<p>正是这场轰炸，让我们看到美帝国主义的邪恶嘴脸，我也以为这个电影的反派就是单纯的美军，像是国外的主旋律电影一样，就是纳粹德国，但是电影明显还要讨论更多。</p>\n<p>随后进入电影的中期部分，主角利用身份，发战争财。这里出现了一个全新的角色身份，ABC 的大兵。这种角色的设定是在从前的剧本中几乎不存在的，李治廷演的也特别好，很完美的诠释这个角色在一个中国人面前，在一个陌生环境下，其具有的无根性和孤独感。让我们体会到，美国大兵也是普普通通的人，甚至由于受到的教育和其身份的原因，显得尤为孩子气和自卑。</p>\n<p><img src=\"https://image.tmdb.org/t/p/original/hgKtkrPT1mQEWRem7YO6kh3Jf7Q.jpg\" alt=\"\"></p>\n<p>到这里，可以说是美帝国主义是坏的，把美国的普通人也送到了战场，去侵略其他国家，都是政客的错，但电影又一次带给我惊喜，不像画靶射箭，而是让情节继续发展下去。</p>\n<h2>电影更高一层的升华</h2>\n<p>进入了电影的最后阶段-监禁，这里电影仍然很自然的放入了两个视角，被美方监禁和被极端分子监禁。在美方监禁期间，体现了美国的恃强凌弱，霸权主义思想盛行。而在极端组织监禁期间，又很好的体现了极端分子是如何利用宗教不择手段的使用儿童来进行恐怖活动，以谋求报复。</p>\n<p><img src=\"https://image.tmdb.org/t/p/original/hEVjc0rdp7XzvqKyysPu73TLDdw.jpg\" alt=\"\"></p>\n<p>而一个中国人，与两方无关的一个局外人视角，充分的展现了战争的残酷性和人性的复杂。我们一直看美国拍的电影，虽然反战，但仍然是有正义的一方，比如黑鹰坠落，但是这一个电影的主旋律是中方一贯以来的反战思想，是一个世界人民大团结的主旋律。结合现在美帝国联合以色列对中东采取的行动，更是讽刺。</p>\n<p>或许我们需要更多这样的主旋律电影，让世界看清楚我们的目的不是霸权主义再次崛起，而是为了天安门上的那两句话的后半部分，也是我们的最终理想。</p>\n<p>ps：电影虽然有些瑕疵，节奏总体来说是比较不错，但是小细节上还是可以再优化一下，瑕不掩瑜。为这部电影的所有工作人员点赞，里面的军事行动真的很专业，其残酷性和荒诞感也展示的到位而不夸张煽情。更值得肯定的是中国还是有好演员在的，李治廷和蒋奇明演的也很好，沈腾更不必多说。最后的最后，里面角色的发展路线和情感铺垫都做的不错，有很多很出彩的设定和设计，包括老扎和赛夫的几次转变都很精彩(๑•̀ㅂ•́)و✧</p>\n",
      "summary": "只是看到有人说不错就来看了，完全没有任何期待，主演是谁也不知道，以为欢迎来到龙餐厅是成龙演的喜剧呢。但是电影开头看到沈腾老师也很惊喜。",
      "date_published": "2026-08-13T00:00:00.000Z",
      "date_modified": "2026-09-19T00:00:00.000Z",
      "image": "https://image.tmdb.org/t/p/original/zr7om0GOLOcLo7SXMmNEG5rz6de.jpg",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/blog/queue-implementation-decision-tree-cn",
      "url": "https://markxu.icu/blog/queue-implementation-decision-tree-cn",
      "title": "队列的实现方式——从约束条件到决策树",
      "content_text": "最近回顾数据结构，发现自己在逻辑结构和物理结构的对应关系选择中总是做错，上网搜了搜方法也没有比较易于理解的方法，于是自己做了个决策树建模，有一个大致的印象，理清楚不少思路。 决策树中的关键约束 在画这棵树时，我固定了以下几个判断维度（也是 408 的高频考点）： 存储方式 ：顺序 / 链式 是否循环 ：解决“假溢出”与“双端访问” 链表类型 ：单向 / 双向 指针设置 ：头指针 / 尾指针 / 头尾双指针 头结点 ：是否引入哨兵结点简化边界 其中最关键的一条经验是： 非循环结构必须头尾双指针；循环结构才有可能只用一个指针。 各类实现的性能指标对比 实现方式 判空 判满 入队 出队 空间开销 推荐度 -------------------------- ------------------- -------------------- ---- ---- -------- ---------- 顺序循环队列 front == rear rear+1 %M == front O 1 O 1 低 ⭐⭐⭐ 非循环单链 + 头+尾（带头） front- next == NULL 无 O 1 O 1 中 ⭐⭐⭐ 非循环单链 + 头+尾（无头） front == NULL 无 O 1 O 1 中 ⭐⭐ 循环单链 + 仅尾指针 ⭐ rear- next == rear 无 O 1 O 1 最低 ⭐⭐⭐⭐⭐ 循环双链 + 仅尾指针 rear- next == rear 无 O 1 O 1 高 ⭐⭐⭐ 循环双链 + 头+尾 front == NULL 无 O 1 O 1 最高 ⭐⭐ 一个容易忽视的细节：头结点 头结点并不是为了“省时间”或“省空间”，而是为了 消除空队列的特殊性 ： 链队 ：删空后容易涉及 悬空，带头结点更安全。 链栈 ：操作单一， 已足够清晰，不带头结点更简洁。 循环链队 ：闭环结构天然解决了边界问题，通常不需要头结点。 栈的物理和逻辑关系 栈分为 顺序栈（数组实现）和 链栈（单链表） 用双链表完全没有必要，太过剩了，而且栈的最佳选择是唯一的，也就是下面的这种情况： 操作在表头 只有头指针 不带头结点 单向 非循环",
      "content_html": "<p>最近回顾数据结构，发现自己在逻辑结构和物理结构的对应关系选择中总是做错，上网搜了搜方法也没有比较易于理解的方法，于是自己做了个决策树建模，有一个大致的印象，理清楚不少思路。</p>\n<p><img src=\"https://img.markxu.icu/imgqueue.png\" alt=\"决策树图\"></p>\n<h2>决策树中的关键约束</h2>\n<p>在画这棵树时，我固定了以下几个判断维度（也是 408 的高频考点）：</p>\n<ol>\n<li><strong>存储方式</strong>：顺序 / 链式</li>\n<li><strong>是否循环</strong>：解决“假溢出”与“双端访问”</li>\n<li><strong>链表类型</strong>：单向 / 双向</li>\n<li><strong>指针设置</strong>：头指针 / 尾指针 / 头尾双指针</li>\n<li><strong>头结点</strong>：是否引入哨兵结点简化边界</li>\n</ol>\n<p>其中最关键的一条经验是：</p>\n<blockquote>\n<p><strong>非循环结构必须头尾双指针；循环结构才有可能只用一个指针。</strong></p>\n</blockquote>\n<h2>各类实现的性能指标对比</h2>\n<table>\n<thead>\n<tr>\n<th>实现方式</th>\n<th>判空</th>\n<th>判满</th>\n<th>入队</th>\n<th>出队</th>\n<th>空间开销</th>\n<th>推荐度</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>顺序循环队列</td>\n<td>front == rear</td>\n<td>(rear+1)%M == front</td>\n<td>O(1)</td>\n<td>O(1)</td>\n<td>低</td>\n<td>⭐⭐⭐</td>\n</tr>\n<tr>\n<td>非循环单链 + 头+尾（带头）</td>\n<td>front-&gt;next == NULL</td>\n<td>无</td>\n<td>O(1)</td>\n<td>O(1)</td>\n<td>中</td>\n<td>⭐⭐⭐</td>\n</tr>\n<tr>\n<td>非循环单链 + 头+尾（无头）</td>\n<td>front == NULL</td>\n<td>无</td>\n<td>O(1)</td>\n<td>O(1)</td>\n<td>中</td>\n<td>⭐⭐</td>\n</tr>\n<tr>\n<td>循环单链 + 仅尾指针 ⭐</td>\n<td>rear-&gt;next == rear</td>\n<td>无</td>\n<td>O(1)</td>\n<td>O(1)</td>\n<td>最低</td>\n<td>⭐⭐⭐⭐⭐</td>\n</tr>\n<tr>\n<td>循环双链 + 仅尾指针</td>\n<td>rear-&gt;next == rear</td>\n<td>无</td>\n<td>O(1)</td>\n<td>O(1)</td>\n<td>高</td>\n<td>⭐⭐⭐</td>\n</tr>\n<tr>\n<td>循环双链 + 头+尾</td>\n<td>front == NULL</td>\n<td>无</td>\n<td>O(1)</td>\n<td>O(1)</td>\n<td>最高</td>\n<td>⭐⭐</td>\n</tr>\n</tbody>\n</table>\n<h2>一个容易忽视的细节：头结点</h2>\n<p>头结点并不是为了“省时间”或“省空间”，而是为了<strong>消除空队列的特殊性</strong>：</p>\n<ul>\n<li><strong>链队</strong>：删空后容易涉及 <code>rear</code> 悬空，带头结点更安全。</li>\n<li><strong>链栈</strong>：操作单一，<code>top == NULL</code> 已足够清晰，不带头结点更简洁。</li>\n<li><strong>循环链队</strong>：闭环结构天然解决了边界问题，通常不需要头结点。</li>\n</ul>\n<h2>栈的物理和逻辑关系</h2>\n<p>栈分为 顺序栈（数组实现）和 链栈（单链表）</p>\n<p>用双链表完全没有必要，太过剩了，而且栈的最佳选择是唯一的，也就是下面的这种情况：</p>\n<ul>\n<li>操作在表头</li>\n<li>只有头指针</li>\n<li>不带头结点</li>\n<li>单向</li>\n<li>非循环</li>\n</ul>\n",
      "summary": "回顾数据结构，发现队列的实现方式总是做错，于是想利用决策树把考虑因素列出来，做个总结。",
      "date_published": "2026-07-30T00:00:00.000Z",
      "image": "https://img.markxu.icu/imgqueue.png",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/blog/Wuhan-food-walk-note1-cn",
      "url": "https://markxu.icu/blog/Wuhan-food-walk-note1-cn",
      "title": "武汉逛吃日志 1",
      "content_text": "来到武汉已经一月有余了，除了在市中心去考雅思和处理某些个人事项有机会来到市中心，还没有以单纯游玩的目的来好好看看这座城市。正好这周刷到了一个很有意思的武汉up主，用我最喜欢的动漫《孤独摇滚》里面的角色形象在武汉四处探店，视频剪的很有意思（又看一集），吃的东西还都是我喜欢吃的，正愁没有地方去，于是决定跟着这个博主走一走。 逛吃轨迹： 后面就跟着这个路径展开一天的游记 Up的推荐！ 或许也可说是推荐的 up，嘿嘿 ¬◡¬ ✧ 这个 up 在 bilibili 上发布视频，我是突然刷到了这一条，发现原来武汉还有这么便宜的米其林餐厅！刚好来到武汉不知道从何探起，于是暗下决心，打算在周末去一探究竟。 澳门陈光记烧味饭店 这就是 up 在上面的视频里提到的那一家，我一早出发，乘了一个多小时的地铁，来到了这家店铺门口。 店铺位置位于武汉的市中心，就在中山公园西北门沿道路走 200m 不到的距离。周围没有商业街，也没有特别招风的招牌，有的只是一个简单又朴素的门面。餐厅的对面是一个学校，所以它就好像小学门口常见的拉面店一样，在那里存在着，静静的守着自己的小生意。 接下来就是点餐了，我没有按照 up 的推荐去点，当做第一次来探店，点了些喜欢吃的，有下面这些。 冰豆花、双拼饭、叉烧酥、菠萝冰、漏奶华。 其中冰豆花和菠萝冰吃起来没有什么惊艳之处，但胜在扎实妥帖，都令人满意。 冰豆花完全没有豆腥味，有一股淡淡的豆香，又滑又嫩，配上不齁嗓的桂花蜜，吃起来冰冰凉凉，还蛮解渴过瘾。菠萝冰作为汽水来说几乎不甜，所有的甜味都来自与融化掉的部分冰激凌和菠萝，唯一的缺点就是分量不够爽喝。 令我惊喜的主要是双拼饭和叉烧酥。这两道菜一入嘴就是两个字—满足。 先说双拼饭。肥叉，肉质弹牙，还有浓郁的酱香，配上淋上中的少许蜂蜜，吃起来层次感更强，肥肉软弹，不会糊住嘴巴，让人感到反感。烧鸭，皮如薄纸，与其下面的酱料混在一起吃，恰到好处的弥补了鸭肉本身肉质偏柴的感觉。但也不是完全没有缺点，从照片就可以看出，盘子上飘着满满一层亮油，且混合着淋上的蜂蜜，在吃到后半段，多少会有些腻口，让我这个最近吃的偏清淡的一时难以消化。 再说蜜汁叉烧酥。叉烧酥一上桌就带来了一股新鲜出炉的酥皮月饼的酥油皮气息，一入嘴，更是将这种香气充满了鼻腔。里面的蜜汁不像别的饭店会有未充分溶解的糖粒在肉馅中磣牙，可能是新鲜出炉的缘故，也可能是将蜜水调的浓度恰好不会析出。里面的肉馅是刀切的，一粒一粒，但吃到嘴里舌头一压，又没有块块分明的感觉，我想大抵是挑的是结缔组织偏少的部分的肥肉，不会影响口感，很是令人满足。 漏奶华我确实没有很享受，在我看来纯纯的糖油混合物，前面吃了双拼饭加叉烧酥，急需一些清淡解腻的菜品，我选择了在饭后上漏奶华，确实耽误了享受，下次点餐肯定会注意。 作为我人生中的第一家米其林餐厅，吃的很是满足，且人均 100 左右，经济实惠，下次有机会再来尝尝 up 主的推荐。 中山公园 吃完饭，吃的好撑，预约的省博又在下午 3 点钟，距离还早，打算去附近的中山公园逛逛。 公园里的树都很粗很高，可见这里很早就是中山公园了，令我意外的是，这里还有一个大小相当可观的游乐园，有一个小型过山车和海盗船，还有不少其他的中型游乐设施，都是 2023 年建成的。同时还保留了经典的游船的项目，可谓“老树发新枝”，既留住了岁月的沉稳，还透着一股鲜活。 在中山公园简单转转，消消食，随后动身前往湖北省博物馆，去与期待了已久的越王勾践剑和曾侯乙打个照面。 湖北省博物馆 预约的 15 点，下午 14 点 20 就到了，为了让游客都有最好的体验， 只支持提前 20 分钟进（一定要注意！） 一进博物馆，就立马奔向越王勾践剑所在的南馆。 即使进了博物馆，想要一瞥越王勾践剑的真容，也要经过漫长的排队，才能在一群人围着的展台中，简单看上几秒。 剑长55.7厘米；剑宽4.6厘米；剑柄长8.4厘米；质量875克。剑身两面有深色菱形暗纹，护手正面镶蓝色琉璃，背面镶绿松石花纹。剑首为圆箍形，内有11道同心圆圈。剑身整体经过硫化处理，耐腐蚀性和强韧程度得到极大地提高，说明中国古人在金属的冶炼和表面处理方面的技术达到了极高的水准。该剑出土时仍寒光四射，锋利无比，反映了中国古代高超的制剑技术，为古代兵器中的奇宝。 —维基百科 整把剑不过一个小臂长短，比我想象的要小不少，感觉像是古人的手办（据资料说这把剑还是很实用的），见到实物还是与电视上看到的不一样。虽然看不到细节，但是围绕着越王勾践剑有一个完整的介绍和展厅，也是学习到了不少知识。 接下来就是奔着第二件国宝—曾侯乙编钟 曾侯乙编钟数量巨大，完整无缺。编钟的钟架高大，由长短不同的两面木架垂直相交组成，长面位于墓西，长7.48米，高2.65米；靠南的一面长3.35米，高2.73米。在木架中有7根彩绘木梁，两端以蟠龙纹铜套加固。6个铜铸佩剑武士和8根圆柱承托住整个编钟，形成上、中、下三层。钟架及挂钩有246个。铜人著长袍，腰束带，神情肃穆。 —维基百科 曾侯乙编钟的场馆就大了不少，展板上说明了曾侯乙的各种细节和发掘故事，以及配套使用的其他器械等等。 周围还有各种大大小小的青铜器，造型和细节都是我所不曾想过的，哪怕有现在的科技和手段，我都怀疑是否是可以完美的复刻出来。还有许许多多的国宝，我在这里简单记录下最令我印象深刻的几个。 花花披萨 看完博物馆，来到了开头提到的 up 主推荐的另外一家店—花花披萨。 店铺装修的简单好看，很是清新明亮，门外的街道也十分干净。 由于中午吃的实在太饱，就要了一个八寸的玛格丽特披萨（¥20），和一份炸鸡（店内销量 top1）。 先上来的是玛格丽特披萨，价格还算实惠（厦门我常去的一个地摊小车卖 9 寸的也是 20 人民币，但这里店铺环境要好很多），吃起来整体味道还算不错，是玛格丽特披萨的味道（这个披萨我也不知道还能做出什么花样就是了…），说几个我失望的点吧，首先是罗勒叶烤的有些发苦，失去了清香味，给的也少，我还是蛮喜欢罗勒的香味的，这里没有吃到。其次虽然是现做的，饼皮的麦香不够明显，吃起来也不够劲道，有点小小的失望。 接下来上场的是这家店铺卖的最好的无骨炸鸡，也是 up 强烈推荐的。即使有着如此高的期望，这盘炸鸡仍然让我感到惊喜。 不仅仅是外壳酥脆，外面裹的是超大的面包糠，单论外壳就足以与袋装薯片匹敌。里面的肉腌制的底味也很稳定，不至于抢了鸡肉本身的风味，又能吃出店家精心的调味。更重要的是里面的鸡肉汁水充足，沾上给的配酱，一个人吃了一整份都不觉得油腻。 如果想要小预算吃爽，这家店确实值得一来。 小结 跟着“氵皮ki酱”的脚步打卡了两家店，才发现武汉不仅有硬核的历史，还有这么丰富的美食。虽然肚子已经被美食填满，但心里却觉得空落落的——因为还有很多推荐的店没来得及去，很多风景没来得及看。 不过没关系，这只是我在武汉众多周末中的一个开始。备考的日子还在继续，但只要有空闲，我还会再来探索这座城市的更多面。毕竟，生活不止眼前的苟且（11408），还有武汉的隐藏小店和下一次的探索之旅。",
      "content_html": "<p>来到武汉已经一月有余了，除了在市中心去考雅思和处理某些个人事项有机会来到市中心，还没有以单纯游玩的目的来好好看看这座城市。正好这周刷到了一个很有意思的武汉up主，用我最喜欢的动漫《孤独摇滚》里面的角色形象在武汉四处探店，视频剪的很有意思（又看一集），吃的东西还都是我喜欢吃的，正愁没有地方去，于是决定跟着这个博主走一走。</p>\n<p>逛吃轨迹：<br>\n<PhotoRoute\n  route=\"wuhan1\"\n  title=\"武汉的一天\"\n  desc=\"从照片定位整理的武汉探店路线与停留点。\"\n/><br>\n后面就跟着这个路径展开一天的游记</p>\n<h2>Up的推荐！</h2>\n<p>或许也可说是推荐的 up，嘿嘿(¬◡¬)✧</p>\n<p>这个 up 在 bilibili 上发布视频，我是突然刷到了这一条，发现原来武汉还有这么便宜的米其林餐厅！刚好来到武汉不知道从何探起，于是暗下决心，打算在周末去一探究竟。<br>\n<VideoEmbed\n  url=\"https://www.bilibili.com/video/BV1ciTq6fEQ6/?spm_id_from=333.1365.list.card_archive.click&vd_source=a1d2d12b1c9f3d1bf63ac9d24e2ff565\"\n  title=\"氵皮ki酱的视频\"\n/></p>\n<h2>澳门陈光记烧味饭店</h2>\n<p>这就是 up 在上面的视频里提到的那一家，我一早出发，乘了一个多小时的地铁，来到了这家店铺门口。</p>\n<p>店铺位置位于武汉的市中心，就在中山公园西北门沿道路走 200m 不到的距离。周围没有商业街，也没有特别招风的招牌，有的只是一个简单又朴素的门面。餐厅的对面是一个学校，所以它就好像小学门口常见的拉面店一样，在那里存在着，静静的守着自己的小生意。</p>\n<div class=\"photo-scroll\">\n  <img src=\"https://img.markxu.icu/imgIMG_20260719_120004.jpg\" alt=\"店铺门面\" />\n  <img src=\"https://img.markxu.icu/imgIMG_20260719_120113.jpg\" alt=\"店内环境\" />\n  <img src=\"https://img.markxu.icu/imgIMG_20260719_120339.jpg\" alt=\"店内环境\" />\n  <img src=\"https://img.markxu.icu/imgIMG_20260719_120347.jpg\" alt=\"小小的米其林成就\" />\n  <img src=\"https://img.markxu.icu/imgIMG_20260719_120353.jpg\" alt=\"杯子上的米其林\" />\n</div>\n<p>接下来就是点餐了，我没有按照 up 的推荐去点，当做第一次来探店，点了些喜欢吃的，有下面这些。</p>\n<p>冰豆花、双拼饭、叉烧酥、菠萝冰、漏奶华。</p>\n<div class=\"photo-scroll\">\n  <img src=\"https://img.markxu.icu/imgIMG_20260719_120758.jpg\" alt=\"桂花冰豆花\" />\n  <img src=\"https://img.markxu.icu/imgIMG_20260719_121033.jpg\" alt=\"肥叉烧鸭双拼饭\" />\n  <img src=\"https://img.markxu.icu/imgIMG_20260719_121100.jpg\" alt=\"蜜汁叉烧酥\" />\n  <img src=\"https://img.markxu.icu/imgIMG_20260719_121406.jpg\" alt=\"咬开的叉烧酥\" />\n  <img src=\"https://img.markxu.icu/imgIMG_20260719_122136.jpg\" alt=\"菠萝冰\" />\n  <img src=\"https://img.markxu.icu/imgIMG_20260719_123444.jpg\" alt=\"漏奶华\" />\n  <img src=\"https://img.markxu.icu/imgIMG_20260719_123627.jpg\" alt=\"切开的漏奶华\" />\n</div>\n<p>其中冰豆花和菠萝冰吃起来没有什么惊艳之处，但胜在扎实妥帖，都令人满意。</p>\n<p>冰豆花完全没有豆腥味，有一股淡淡的豆香，又滑又嫩，配上不齁嗓的桂花蜜，吃起来冰冰凉凉，还蛮解渴过瘾。菠萝冰作为汽水来说几乎不甜，所有的甜味都来自与融化掉的部分冰激凌和菠萝，唯一的缺点就是分量不够爽喝。</p>\n<p>令我惊喜的主要是双拼饭和叉烧酥。这两道菜一入嘴就是两个字—满足。</p>\n<p>先说双拼饭。肥叉，肉质弹牙，还有浓郁的酱香，配上淋上中的少许蜂蜜，吃起来层次感更强，肥肉软弹，不会糊住嘴巴，让人感到反感。烧鸭，皮如薄纸，与其下面的酱料混在一起吃，恰到好处的弥补了鸭肉本身肉质偏柴的感觉。但也不是完全没有缺点，从照片就可以看出，盘子上飘着满满一层亮油，且混合着淋上的蜂蜜，在吃到后半段，多少会有些腻口，让我这个最近吃的偏清淡的一时难以消化。</p>\n<p>再说蜜汁叉烧酥。叉烧酥一上桌就带来了一股新鲜出炉的酥皮月饼的酥油皮气息，一入嘴，更是将这种香气充满了鼻腔。里面的蜜汁不像别的饭店会有未充分溶解的糖粒在肉馅中磣牙，可能是新鲜出炉的缘故，也可能是将蜜水调的浓度恰好不会析出。里面的肉馅是刀切的，一粒一粒，但吃到嘴里舌头一压，又没有块块分明的感觉，我想大抵是挑的是结缔组织偏少的部分的肥肉，不会影响口感，很是令人满足。</p>\n<p>漏奶华我确实没有很享受，在我看来纯纯的糖油混合物，前面吃了双拼饭加叉烧酥，急需一些清淡解腻的菜品，我选择了在饭后上漏奶华，确实耽误了享受，下次点餐肯定会注意。</p>\n<p>作为我人生中的第一家米其林餐厅，吃的很是满足，且人均 100 左右，经济实惠，下次有机会再来尝尝 up 主的推荐。</p>\n<h2>中山公园</h2>\n<p>吃完饭，吃的好撑，预约的省博又在下午 3 点钟，距离还早，打算去附近的中山公园逛逛。</p>\n<div class=\"photo-scroll\">\n  <img src=\"https://img.markxu.icu/imgIMG_20260719_125238.jpg\" alt=\"公园西北门\" />\n  <img src=\"https://img.markxu.icu/imgIMG_20260719_125707.jpg\" alt=\"园内游乐设施\" />\n  <img src=\"https://img.markxu.icu/imgIMG_20260719_130817.jpg\" alt=\"园内设施\" />\n  <img src=\"https://img.markxu.icu/imgIMG_20260719_130708.jpg\" alt=\"游船\" />\n  <img src=\"https://img.markxu.icu/imgIMG_20260719_130342.jpg\" alt=\"正门雕像\" />\n</div>\n<p><FloatImage\n  src=\"https://img.markxu.icu/imgIMG_20260719_125853.jpg\"\n  alt=\"自助图书机，真是好东西\"\n  side=\"left\"\n  width=\"40%\"\n/></p>\n<p>公园里的树都很粗很高，可见这里很早就是中山公园了，令我意外的是，这里还有一个大小相当可观的游乐园，有一个小型过山车和海盗船，还有不少其他的中型游乐设施，都是 2023 年建成的。同时还保留了经典的游船的项目，可谓“老树发新枝”，既留住了岁月的沉稳，还透着一股鲜活。</p>\n<p>在中山公园简单转转，消消食，随后动身前往湖北省博物馆，去与期待了已久的越王勾践剑和曾侯乙打个照面。</p>\n<h2>湖北省博物馆</h2>\n<p>预约的 15 点，下午 14 点 20 就到了，为了让游客都有最好的体验，<strong>只支持提前 20 分钟进（一定要注意！）</strong></p>\n<p>一进博物馆，就立马奔向越王勾践剑所在的南馆。</p>\n<p>即使进了博物馆，想要一瞥越王勾践剑的真容，也要经过漫长的排队，才能在一群人围着的展台中，简单看上几秒。</p>\n<p><img src=\"https://img.markxu.icu/imgIMG_20260719_150928.jpg\" alt=\"越王勾践剑\"></p>\n<AsideNote color=\"yellow\" width=\"large\">\n剑长55.7厘米；剑宽4.6厘米；剑柄长8.4厘米；质量875克。剑身两面有深色菱形暗纹，护手正面镶蓝色琉璃，背面镶绿松石花纹。剑首为圆箍形，内有11道同心圆圈。剑身整体经过硫化处理，耐腐蚀性和强韧程度得到极大地提高，说明中国古人在金属的冶炼和表面处理方面的技术达到了极高的水准。该剑出土时仍寒光四射，锋利无比，反映了中国古代高超的制剑技术，为古代兵器中的奇宝。  —维基百科\n</AsideNote>\n<p>整把剑不过一个小臂长短，比我想象的要小不少，感觉像是古人的手办（据资料说这把剑还是很实用的），见到实物还是与电视上看到的不一样。虽然看不到细节，但是围绕着越王勾践剑有一个完整的介绍和展厅，也是学习到了不少知识。</p>\n<p>接下来就是奔着第二件国宝—曾侯乙编钟</p>\n<p><img src=\"https://img.markxu.icu/imgIMG_20260719_152047.jpg\" alt=\"曾侯乙编钟\"></p>\n<AsideNote color=\"yellow\" width=\"large\">\n曾侯乙编钟数量巨大，完整无缺。编钟的钟架高大，由长短不同的两面木架垂直相交组成，长面位于墓西，长7.48米，高2.65米；靠南的一面长3.35米，高2.73米。在木架中有7根彩绘木梁，两端以蟠龙纹铜套加固。6个铜铸佩剑武士和8根圆柱承托住整个编钟，形成上、中、下三层。钟架及挂钩有246个。铜人著长袍，腰束带，神情肃穆。  —维基百科\n</AsideNote>\n<p>曾侯乙编钟的场馆就大了不少，展板上说明了曾侯乙的各种细节和发掘故事，以及配套使用的其他器械等等。</p>\n<p>周围还有各种大大小小的青铜器，造型和细节都是我所不曾想过的，哪怕有现在的科技和手段，我都怀疑是否是可以完美的复刻出来。还有许许多多的国宝，我在这里简单记录下最令我印象深刻的几个。</p>\n<div class=\"photo-scroll-vertical\">\n  <img src=\"https://img.markxu.icu/imgIMG_20260719_152607.jpg\" alt=\"曾侯乙尊盘\" />\n  <img src=\"https://img.markxu.icu/imgIMG_20260719_153359.jpg\" alt=\"蟠龙盖兽面纹铜罍（léi）\" />\n  <img src=\"https://img.markxu.icu/imgIMG_20260719_154121.jpg\" alt=\"战国楚国漆皮甲胄\" />\n  <img src=\"https://img.markxu.icu/imgIMG_20260719_155203.jpg\" alt=\"金环白玉葫芦饰\" />\n</div>\n<h2>花花披萨</h2>\n<p>看完博物馆，来到了开头提到的 up 主推荐的另外一家店—花花披萨。</p>\n<div class=\"photo-scroll\">\n  <img src=\"https://img.markxu.icu/imgIMG_20260719_172040.jpg\" alt=\"店铺门面\" />\n  <img src=\"https://img.markxu.icu/imgIMG_20260719_172248.jpg\" alt=\"店内环境\" />\n  <img src=\"https://img.markxu.icu/imgIMG_20260719_172252.jpg\" alt=\"店内环境\" />\n</div>\n<p>店铺装修的简单好看，很是清新明亮，门外的街道也十分干净。</p>\n<p>由于中午吃的实在太饱，就要了一个八寸的玛格丽特披萨（¥20），和一份炸鸡（店内销量 top1）。</p>\n<p><FloatImage\n  src=\"https://img.markxu.icu/imgIMG_20260719_173447.jpg\"\n  alt=\"玛格丽特披萨\"\n  side=\"left\"\n  width=\"45%\"\n/></p>\n<p>先上来的是玛格丽特披萨，价格还算实惠（厦门我常去的一个地摊小车卖 9 寸的也是 20 人民币，但这里店铺环境要好很多），吃起来整体味道还算不错，是玛格丽特披萨的味道（这个披萨我也不知道还能做出什么花样就是了…），说几个我失望的点吧，首先是罗勒叶烤的有些发苦，失去了清香味，给的也少，我还是蛮喜欢罗勒的香味的，这里没有吃到。其次虽然是现做的，饼皮的麦香不够明显，吃起来也不够劲道，有点小小的失望。</p>\n<p><FloatImage\n  src=\"https://img.markxu.icu/imgIMG_20260719_174708.jpg\"\n  alt=\"无骨炸鸡\"\n  side=\"right\"\n  width=\"55%\"\n/></p>\n<p>接下来上场的是这家店铺卖的最好的无骨炸鸡，也是 up 强烈推荐的。即使有着如此高的期望，这盘炸鸡仍然让我感到惊喜。</p>\n<p>不仅仅是外壳酥脆，外面裹的是超大的面包糠，单论外壳就足以与袋装薯片匹敌。里面的肉腌制的底味也很稳定，不至于抢了鸡肉本身的风味，又能吃出店家精心的调味。更重要的是里面的鸡肉汁水充足，沾上给的配酱，一个人吃了一整份都不觉得油腻。</p>\n<p>如果想要小预算吃爽，这家店确实值得一来。</p>\n<h2>小结</h2>\n<p>跟着“氵皮ki酱”的脚步打卡了两家店，才发现武汉不仅有硬核的历史，还有这么丰富的美食。虽然肚子已经被美食填满，但心里却觉得空落落的——因为还有很多推荐的店没来得及去，很多风景没来得及看。</p>\n<p>不过没关系，这只是我在武汉众多周末中的一个开始。备考的日子还在继续，但只要有空闲，我还会再来探索这座城市的更多面。毕竟，生活不止眼前的苟且（11408），还有武汉的隐藏小店和下一次的探索之旅。</p>\n",
      "summary": "在武汉备考二战，周末放一天假，跟着up主的路子出门转转，看了心心念念的湖北省博物馆，吃了许多美食。",
      "date_published": "2026-07-20T00:00:00.000Z",
      "image": "https://img.markxu.icu/img湖北省博.jpg",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/blog/tcp-slow-start-cwnd-growth-cn",
      "url": "https://markxu.icu/blog/tcp-slow-start-cwnd-growth-cn",
      "title": "TCP 慢启动的窗口增长：教材、RFC 与 Linux 内核实现的三层对照",
      "content_text": "在前几天备考的时候做到了这个题目： 可以跳转到这个链接去看！2025年真题 看到答案的解析说到： 由于当前拥塞窗口小于阈值，处于慢启动阶段，每收到一个ACK，拥塞窗口就加 1 MSS，故由 2000B 增至 3000B。 这一个小细节与我之前一直默认的每一个 RTT 后拥塞窗口翻倍理解不同，怎么回事？（虽然后面证实是我自己看书没看仔细🤪），而且 tcp 采用的是累积确认，这样岂不是就不会形成翻倍的效果了？ 抱着这个疑问，我问了下一个很厉害的同学，他的回答是： 发送端按被确认的字节数来增长 ，而不是 ACK 的个数（一个ACK确认一个MSS下是也可以看ACK个数来增长 ）。具体怎么实现的就要看协议的设计了。计网很多题都是比较理想的情况下的 我不禁好奇，怎么又来一个新的说法，按照字节确认？于是打算自己去探索下，看看 TCP 慢启动阶段，拥塞窗口 到底是怎么增长的？ 从“每个 RTT 翻倍”开始 先从计网教材和考试语境里最熟悉的描述切入： 初始拥塞窗口 通常设为 1 MSS（最新的 RFC 允许设置更多 MSS），慢开始算法规定：每收到一个对新报文段的确认，就将 加 1。这样，每经过一个传输轮次（一个往返时延 RTT）， 就会加倍，从而随着传输轮次呈指数增长。为了防止 无限制增长，还需要设置一个慢开始门限 ssthresh（阈值）。当 增长至 ssthresh 时，停止慢开始算法，转而采用拥塞避免算法。 可以这样简单概括： 慢启动阶段：每收到一个 ACK， 。 如果一个 RTT 内每个数据段都能各自触发一个 ACK，那么一轮 RTT 之后，cwnd 大约翻倍。 拥塞避免阶段：增长速度降下来，约等于每个 RTT 增加 1 MSS。 假设阈值设置为 16，下面就是一个例子 轮次 初始 cwnd 一个 RTT 内收到 ACK 数 RTT 结束后 cwnd ---- --------- ---------------------- ----------------------- 0 1 MSS 1 2 MSS 1 2 MSS 2 4 MSS 2 4 MSS 4 8 MSS 3 8 MSS 8 16 MSS The slow start algorithm is used when cwnd ssthresh. When cwnd and ssthresh are equal, the sender may use either slow start or congestion avoidance. During slow start, a TCP increments cwnd by at most SMSS bytes for each ACK received that cumulatively acknowledges new data. Slow start ends when cwnd exceeds ssthresh or, optionally, when it reaches it, as noted above or when congestion is observed. While traditionally TCP implementations have increased cwnd by precisely SMSS bytes upon receipt of an ACK covering new data, we RECOMMEND that TCP implementations increase cwnd, per: cwnd += min N, SMSS 2 where N is the number of previously unacknowledged bytes acknowledged in the incoming ACK. This adjustment is part of Appropriate Byte Counting RFC3465 and provides robustness against misbehaving receivers that may attempt to induce a sender to artificially inflate cwnd using a mechanism known as \"ACK Division\" SCWA99 . ACK Division consists of a receiver sending multiple ACKs for a single TCP data segment, each acknowledging only a portion of its data. A TCP that increments cwnd by SMSS for each such ACK will inappropriately inflate the amount of data injected into the network. RFC 5681 第 3.1 节的核心意思是： 在慢启动阶段，TCP 对每个累计确认了新数据的 ACK，增加确认的字节数的大小，最多把 增加 （发送方的 MSS）字节。 可以拆成三个关键词： ：触发点是收到 ACK。 ：这个 ACK 必须累计确认了新的数据。 ：N 是 ACK 确认收到的字节数，最大不超过发送端 MSS。 为什么这么设置？ 这样设置的原因也在原文中说明了： 这个调整是 Appropriate Byte Counting（ABC，RFC 3465）的一部分，它可以增强 TCP 对异常接收方的鲁棒性。因为有些不正常的接收方可能会使用一种叫做 ACK Division 的机制，诱导发送方人为地增大 cwnd。所谓 ACK Division，就是接收方针对同一个 TCP 数据段发送多个 ACK，每个 ACK 只确认这个数据段的一部分。如果某个 TCP 实现对每一个这样的 ACK 都把 cwnd 增加 SMSS，那么它就会不恰当地增加注入网络中的数据量。 简单来说，RFC 这里想防的是： 不要让接收方通过“拆 ACK”的方式骗发送方扩大拥塞窗口。 比如发送方只发了一个 SMSS 大小的数据段，正常情况下，接收方应该用一个 ACK 确认这个数据段。此时发送方在慢启动中把 增加 1 SMSS，这没有问题。 但如果接收方故意把这个确认拆成多个小 ACK： 如果发送方仍然采用“每收到一个 ACK，就增加 ”的规则，那么同一个数据段就会触发多次窗口增长。明明网络里只成功传输了一个段，发送方却以为可以继续大幅增加发送量，这就会让 被不正常地放大。 所以 RFC 5681 推荐使用： 这样做的含义是： 如果一个 ACK 只确认了很少的新字节， 就只增加这部分实际确认的字节数。 如果一个 ACK 确认了很多字节，单次增长最多也只能到 。 因此，它既保留了正常慢启动中“一个完整 MSS 确认带来约一个 MSS 增长”的效果，又避免了 ACK Division 把窗口恶意撑大的问题。 不过这只是 RFC 5681 / RFC 3465 从“字节计数”角度给出的规则。等到后面看 Linux 内核实现时会发现，Linux 的处理方式又换了一个视角：它不是直接按 ACK 新确认的字节数来加窗口，而是按“被完整确认的段数”来计算。这个差异也是这篇文章后面最有意思的地方。 Linux 内核实现：为什么看起来又不一样 源码位置：Linux kernel: net/ipv4/tcp cong.c，可以直接搜索 。 先看核心函数和它前面的注释： 这段注释的信息量很大，可以先翻译成更容易理解的话： 当拥塞窗口不大于慢启动阈值时，会使用慢启动。Linux 的实现以 RFC 2581 为基础，同时也正确处理 stretch ACK。 Linux 并没有严格实现 RFC 3465 里说的 Appropriate Byte Counting（ABC），而是采用了另一种处理方式：只有当一个 packet 被完整地 ACK 或 SACK 确认时，才认为它被确认。这样可以防御 RFC 中描述的 ACK 攻击。 对于一个 degree 为 N 的 stretch ACK，Linux 的慢启动会把它当作连续收到了 N 个普通 ACK 来处理；而 ABC 会把 N 限制到 2。 当这次增长本来会让 cwnd 越过 ssthresh 时，慢启动会先在阈值处停下，并把还没用完的 ACK 数量返回给拥塞避免阶段，让拥塞避免继续调整窗口。 同时，这里有几个词需要先解释一下： ：Selective Acknowledgment，选择确认，用来告诉发送方哪些非连续的数据块已经收到了。 ：内核注释里的写法，意思是 ACKed 或 SACKed。 ：一个 ACK 不是只确认一个段，而是一次性确认多个段。比如接收方延迟确认，可能收到两个或多个 TCP 段之后才回一个 ACK。 ：这个 stretch ACK 一次性确认了 N 个完整段。 acked 的确认单位不是字节 这里最关键的一点是：Linux 这段代码里的 不是“确认了多少字节”，而是“确认了多少个完整段”。 也就是说，RFC 5681 / RFC 3465 更偏向用字节来描述： 其中 N 是 ACK 新确认的字节数。 但 Linux 在这里的实现思路更接近： 其中 是新确认的完整段数。Linux 的 本身也是以段为单位维护的，所以这里的 不是把字节数直接加到窗口上，而是把“确认了几个完整段”加到窗口上。 这就解释了为什么内核代码看起来和 RFC 公式不一样： RFC 讨论时常以字节为单位描述 增长。 Linux 这里的 是“被确认的完整数据段数量”。 因此 的含义是：窗口按完整段数量增加。 这个增长方式在理想情况下就和教材里的“每收到一个 ACK， ”对应：如果一个 ACK 正好确认一个完整 MSS，那么 ，窗口就增加 1 个段。 为什么这样也能防 ACK Division? Linux 的防御方式与 RFC 不同：它不把一个段的一部分当作一次有效的“完整段确认”。只有当一个 packet 被完整确认时，才会计入 。所以恶意接收方把一个段拆成多个小 ACK，也不能让 变成多个完整段。 这就是注释里说的： Linux 并没有严格实现 ABC，而是做了“更好”的东西。 这里的“更好”可以理解为：它没有按字节粒度做 ABC，而是从“完整段确认”这个粒度上防住了 ACK Division。这样可以有更高的吞吐量，实现起来也没有浮点和字节的计算，而且与拥塞避免阶段衔接的更顺利（后面逐行讲解代码会仔细解释）。 stretch ACK 下 Linux 更激进 再看 stretch ACK。 假设一个 ACK 一次性确认了 3 个完整段，Linux 会把它当作连续收到 3 个普通 ACK，而 RFC 3465 的 ABC 会限制慢启动中的单次增长量，实验性建议里 不能超过 。所以在 stretch ACK 场景下，Linux 的处理会比 ABC 更激进一些。 这也解释了注释里的这句话： Linux 把一个确认 N 个段的 stretch ACK，当成连续来了 N 个普通 ACK；但 ABC 会把这个数量限制到 2。 详解代码：逐行看 现在再回头看代码： 先解释几个变量： ：当前 TCP 连接的控制块，里面保存了这个连接的拥塞控制状态。 ：当前发送端拥塞窗口，单位是完整段。 ：慢启动阈值。慢启动最多增长到这个阈值附近，之后就要进入拥塞避免。 ：拥塞窗口的硬上限，防止 超过系统允许的最大值。 ：这次 ACK 新确认的完整段数量。 第一行： 它先计算慢启动阶段能增长到的新窗口： 也就是说，慢启动阶段确实会按 增加窗口，但最多只能增加到 。 第二行： 这一行是在计算“这次 ACK 里，有多少确认量已经被慢启动消耗掉了”。 表示这次慢启动实际让窗口增加了多少。然后从 里减掉这一部分，剩下的就是慢启动没有用完的确认量。 碰到 时如何处理 举一个例子： 如果不考虑 ，窗口本来可以从 8 增长到 13。 但是慢启动最多只能增长到 ： 所以慢启动实际只消耗了 2 个 ： 第三行： 这一行真正更新 TCP 控制块里的 。更新时还要再和 取最小值，保证窗口不会超过系统设置的上限。 最后一行： 函数返回没有被慢启动消耗掉的 。 如果慢启动还没有碰到 ，通常返回 0，表示这次 ACK 的确认量已经全部用来增加慢启动窗口了。 如果刚好在这次 ACK 中跨过了 ，就会返回剩余的 ，让后面的拥塞避免逻辑继续使用它。这样做的好处是：同一个 ACK 中超过慢启动阈值的那部分确认量不会被浪费，而是平滑地交给拥塞避免阶段处理。 所以 Linux 这一段代码可以概括为： 这就是为什么看完 RFC 后再看 Linux，会觉得公式变了：RFC 5681 / RFC 3465 是以“确认字节数”为中心描述规则，而 Linux 这里是以“完整段数”为单位实现窗口增长。 总结：三层对照：同一个慢启动，三种表达 这里通过一个表格来总结或许最合适： 维度 教材模型 RFC 5681 / RFC 3465 Linux 内核 --------------------- ------------------------------- ------------------------------------------------------------------- --------------------------- 核心视角 建立直觉 规定协议边界 工程实现 增长依据 ACK 数量 ACK 新确认的字节数 ACK 新确认的完整段数 慢启动公式 每 ACK 确认一个报文段约 单位 通常按 MSS 抽象 字节 完整段 stretch ACK 确认 3 段 通常不讨论 RFC 5681 最多 ；RFC 3465 ABC 可用 调节但不超过 近似 个段 ACK Division 防御 不涉及 用 限制增长 只把完整段确认计入 理想每包一 ACK RTT 内翻倍 RTT 内近似翻倍 RTT 内近似翻倍 可以看出，针对慢启动的公式，教材给出的与 linux 源码的方式是一样的。但是这样设计的背后，还有很多细节和考量，如果不是同学的一句话，我也了解不到这么多细节，如果你也有相关的了解，欢迎评论告诉我！ 如果你想试试做一个实验验证下，可以参考Linux cwnd 实验 参考资料 RFC 5681: TCP Congestion Control RFC 3465: TCP Congestion Control with Appropriate Byte Counting Linux kernel: net/ipv4/tcp cong.c NJU Linux 镜像 Linux cwnd 实验 拓展阅读： TCP 拥塞控制演进：从 Reno 到 BBR TCP BBR拥塞控制算法深度解析",
      "content_html": "<p>在前几天备考的时候做到了这个题目：</p>\n<p><img src=\"https://img.markxu.icu/img2025408.png\" alt=\"2025计网真题\"></p>\n<p>可以跳转到这个链接去看！<a href=\"https://www.408os.cn/exercise?year=2025&amp;questionId=790\">2025年真题</a></p>\n<p>看到答案的解析说到：</p>\n<blockquote>\n<p>由于当前拥塞窗口小于阈值，处于慢启动阶段，每收到一个ACK，拥塞窗口就加 1 MSS，故由 2000B 增至 3000B。</p>\n</blockquote>\n<p>这一个小细节与我之前一直默认的每一个 RTT 后拥塞窗口翻倍理解不同，怎么回事？（虽然后面证实是我自己看书没看仔细🤪），而且 tcp 采用的是累积确认，这样岂不是就不会形成翻倍的效果了？</p>\n<p>抱着这个疑问，我问了下一个很厉害的同学，他的回答是：</p>\n<blockquote>\n<p>发送端按被确认的字节数来增长 <code>cwnd</code>，而不是 ACK 的个数（一个ACK确认一个MSS下是也可以看ACK个数来增长<code>cwnd</code>）。具体怎么实现的就要看协议的设计了。计网很多题都是比较理想的情况下的</p>\n</blockquote>\n<p>我不禁好奇，怎么又来一个新的说法，按照字节确认？于是打算自己去探索下，看看 TCP 慢启动阶段，拥塞窗口 <code>cwnd</code> 到底是怎么增长的？</p>\n<hr>\n<h2>从“每个 RTT 翻倍”开始</h2>\n<p>先从计网教材和考试语境里最熟悉的描述切入：</p>\n<p>初始拥塞窗口 <code>cwnd</code> 通常设为 1 MSS（最新的 RFC 允许设置更多 MSS），慢开始算法规定：每收到一个对新报文段的确认，就将 <code>cwnd</code> 加 1。这样，每经过一个传输轮次（一个往返时延 RTT），<code>cwnd</code> 就会加倍，从而随着传输轮次呈指数增长。为了防止 <code>cwnd</code> 无限制增长，还需要设置一个慢开始门限 ssthresh（阈值）。当 <code>cwnd</code> 增长至 ssthresh 时，停止慢开始算法，转而采用拥塞避免算法。</p>\n<p>可以这样简单概括：</p>\n<ul>\n<li>慢启动阶段：每收到一个 ACK，<code>cwnd += 1 MSS</code>。</li>\n<li>如果一个 RTT 内每个数据段都能各自触发一个 ACK，那么一轮 RTT 之后，cwnd 大约翻倍。</li>\n<li>拥塞避免阶段：增长速度降下来，约等于每个 RTT 增加 1 MSS。</li>\n</ul>\n<p>假设阈值设置为 16，下面就是一个例子</p>\n<!-- table-widths: 10%, 24%, 28%, 38% -->\n<table>\n<thead>\n<tr>\n<th>轮次</th>\n<th>初始 cwnd</th>\n<th>一个 RTT 内收到 ACK 数</th>\n<th>RTT 结束后 cwnd</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0</td>\n<td>1 MSS</td>\n<td>1</td>\n<td>2 MSS</td>\n</tr>\n<tr>\n<td>1</td>\n<td>2 MSS</td>\n<td>2</td>\n<td>4 MSS</td>\n</tr>\n<tr>\n<td>2</td>\n<td>4 MSS</td>\n<td>4</td>\n<td>8 MSS</td>\n</tr>\n<tr>\n<td>3</td>\n<td>8 MSS</td>\n<td>8</td>\n<td>16 MSS &lt;-(达到阈值了)</td>\n</tr>\n<tr>\n<td>4</td>\n<td>16 MSS</td>\n<td>16</td>\n<td>17 MSS &lt;-(拥塞避免算法)</td>\n</tr>\n</tbody>\n</table>\n<p>所以可以看出 <code>cwnd</code> 随着 RTT 增长，是呈现指数上升的趋势的。就算现在的 tcp 采用的是累积确认方法，其增长趋势也是近似一个指数增长的。</p>\n<h2>RFC 5681：标准如何定义慢启动</h2>\n<p>这里可以找到<a href=\"https://www.rfc-editor.org/info/rfc5681/#section-2:~:text=The%20slow%20start%20algorithm%20is%20used%20when,amount%20of%20data%20injected%20into%20the%20network.\">原文</a></p>\n<blockquote>\n<p>The slow start algorithm is used when cwnd &lt; ssthresh, while the congestion avoidance algorithm is used when cwnd &gt; ssthresh. When cwnd and ssthresh are equal, the sender may use either slow start or congestion avoidance.</p>\n<p>During slow start, a TCP increments cwnd by at most SMSS bytes for each ACK received that cumulatively acknowledges new data. Slow start ends when cwnd exceeds ssthresh (or, optionally, when it reaches it, as noted above) or when congestion is observed. While traditionally TCP implementations have increased cwnd by precisely SMSS bytes upon receipt of an ACK covering new data, we RECOMMEND that TCP implementations increase cwnd, per:</p>\n<p>cwnd += min (N, SMSS) (2)</p>\n<p>where N is the number of previously unacknowledged bytes acknowledged in the incoming ACK. This adjustment is part of Appropriate Byte Counting [RFC3465] and provides robustness against misbehaving receivers that may attempt to induce a sender to artificially inflate cwnd using a mechanism known as &quot;ACK Division&quot; [SCWA99]. ACK Division consists of a receiver sending multiple ACKs for a single TCP data segment, each acknowledging only a portion of its data. A TCP that increments cwnd by SMSS for each such ACK will inappropriately inflate the amount of data injected into the network.</p>\n</blockquote>\n<p>RFC 5681 第 3.1 节的核心意思是：</p>\n<blockquote>\n<p>在慢启动阶段，TCP 对每个累计确认了新数据的 ACK，增加确认的字节数的大小，最多把 <code>cwnd</code> 增加 <code>SMSS</code> （发送方的 MSS）字节。</p>\n</blockquote>\n<p>可以拆成三个关键词：</p>\n<ul>\n<li><code>for each ACK received</code>：触发点是收到 ACK。</li>\n<li><code>cumulatively acknowledges new data</code>：这个 ACK 必须累计确认了新的数据。</li>\n<li><code>cwnd += min (N, SMSS)</code>：N 是 ACK 确认收到的字节数，最大不超过发送端 MSS。</li>\n</ul>\n<h3>为什么这么设置？</h3>\n<p>这样设置的原因也在原文中说明了：</p>\n<blockquote>\n<p>这个调整是 Appropriate Byte Counting（ABC，RFC 3465）的一部分，它可以增强 TCP 对异常接收方的鲁棒性。因为有些不正常的接收方可能会使用一种叫做 ACK Division 的机制，诱导发送方人为地增大 cwnd。所谓 ACK Division，就是接收方针对同一个 TCP 数据段发送多个 ACK，每个 ACK 只确认这个数据段的一部分。如果某个 TCP 实现对每一个这样的 ACK 都把 cwnd 增加 SMSS，那么它就会不恰当地增加注入网络中的数据量。</p>\n</blockquote>\n<p>简单来说，RFC 这里想防的是：<strong>不要让接收方通过“拆 ACK”的方式骗发送方扩大拥塞窗口。</strong></p>\n<p>比如发送方只发了一个 SMSS 大小的数据段，正常情况下，接收方应该用一个 ACK 确认这个数据段。此时发送方在慢启动中把 <code>cwnd</code> 增加 1 SMSS，这没有问题。</p>\n<p>但如果接收方故意把这个确认拆成多个小 ACK：</p>\n<pre><code class=\"language-text\">第 1 个 ACK：确认前 200 字节\n第 2 个 ACK：确认前 400 字节\n第 3 个 ACK：确认前 600 字节\n...\n</code></pre>\n<p>如果发送方仍然采用“每收到一个 ACK，就增加 <code>1 SMSS</code>”的规则，那么同一个数据段就会触发多次窗口增长。明明网络里只成功传输了一个段，发送方却以为可以继续大幅增加发送量，这就会让 <code>cwnd</code> 被不正常地放大。</p>\n<p>所以 RFC 5681 推荐使用：</p>\n<pre><code class=\"language-text\">cwnd += min(N, SMSS)\n</code></pre>\n<p>这样做的含义是：</p>\n<ul>\n<li>如果一个 ACK 只确认了很少的新字节，<code>cwnd</code> 就只增加这部分实际确认的字节数。</li>\n<li>如果一个 ACK 确认了很多字节，单次增长最多也只能到 <code>1 SMSS</code>。</li>\n</ul>\n<p>因此，它既保留了正常慢启动中“一个完整 MSS 确认带来约一个 MSS 增长”的效果，又避免了 ACK Division 把窗口恶意撑大的问题。</p>\n<p>不过这只是 RFC 5681 / RFC 3465 从“字节计数”角度给出的规则。等到后面看 Linux 内核实现时会发现，Linux 的处理方式又换了一个视角：它不是直接按 ACK 新确认的字节数来加窗口，而是按“被完整确认的段数”来计算。这个差异也是这篇文章后面最有意思的地方。</p>\n<hr>\n<h2>Linux 内核实现：为什么看起来又不一样</h2>\n<p>源码位置：<a href=\"https://github.com/torvalds/linux/blob/master/net/ipv4/tcp_cong.c\">Linux kernel: net/ipv4/tcp_cong.c</a>，可以直接搜索 <code>tcp_slow_start()</code>。</p>\n<p>先看核心函数和它前面的注释：</p>\n<pre><code class=\"language-c\">/* Slow start is used when congestion window is no greater than the slow start\n * threshold. We base on RFC2581 and also handle stretch ACKs properly.\n * We do not implement RFC3465 Appropriate Byte Counting (ABC) per se but\n * something better;) a packet is only considered (s)acked in its entirety to\n * defend the ACK attacks described in the RFC. Slow start processes a stretch\n * ACK of degree N as if N acks of degree 1 are received back to back except\n * ABC caps N to 2. Slow start exits when cwnd grows over ssthresh and\n * returns the leftover acks to adjust cwnd in congestion avoidance mode.\n */\n__bpf_kfunc u32 tcp_slow_start(struct tcp_sock *tp, u32 acked)\n{\n\tu32 cwnd = min(tcp_snd_cwnd(tp) + acked, tp-&gt;snd_ssthresh);\n\n\tacked -= cwnd - tcp_snd_cwnd(tp);\n\ttcp_snd_cwnd_set(tp, min(cwnd, tp-&gt;snd_cwnd_clamp));\n\n\treturn acked;\n}\n</code></pre>\n<p>这段注释的信息量很大，可以先翻译成更容易理解的话：</p>\n<blockquote>\n<p>当拥塞窗口不大于慢启动阈值时，会使用慢启动。Linux 的实现以 RFC 2581 为基础，同时也正确处理 stretch ACK。</p>\n<p>Linux 并没有严格实现 RFC 3465 里说的 Appropriate Byte Counting（ABC），而是采用了另一种处理方式：只有当一个 packet 被完整地 ACK 或 SACK 确认时，才认为它被确认。这样可以防御 RFC 中描述的 ACK 攻击。</p>\n<p>对于一个 degree 为 N 的 stretch ACK，Linux 的慢启动会把它当作连续收到了 N 个普通 ACK 来处理；而 ABC 会把 N 限制到 2。</p>\n<p>当这次增长本来会让 cwnd 越过 ssthresh 时，慢启动会先在阈值处停下，并把还没用完的 ACK 数量返回给拥塞避免阶段，让拥塞避免继续调整窗口。</p>\n</blockquote>\n<p>同时，这里有几个词需要先解释一下：</p>\n<ul>\n<li><code>SACK</code>：Selective Acknowledgment，选择确认，用来告诉发送方哪些非连续的数据块已经收到了。</li>\n<li><code>(s)acked</code>：内核注释里的写法，意思是 ACKed 或 SACKed。</li>\n<li><code>stretch ACK</code>：一个 ACK 不是只确认一个段，而是一次性确认多个段。比如接收方延迟确认，可能收到两个或多个 TCP 段之后才回一个 ACK。</li>\n<li><code>degree N</code>：这个 stretch ACK 一次性确认了 N 个完整段。</li>\n</ul>\n<h3>acked 的确认单位不是字节</h3>\n<p>这里最关键的一点是：Linux 这段代码里的 <code>acked</code> 不是“确认了多少字节”，而是“确认了多少个完整段”。</p>\n<p>也就是说，RFC 5681 / RFC 3465 更偏向用字节来描述：</p>\n<pre><code class=\"language-text\">cwnd += min(N, SMSS)\n</code></pre>\n<p>其中 N 是 ACK 新确认的字节数。</p>\n<p>但 Linux 在这里的实现思路更接近：</p>\n<pre><code class=\"language-text\">cwnd += acked\n</code></pre>\n<p>其中 <code>acked</code> 是新确认的完整段数。Linux 的 <code>snd_cwnd</code> 本身也是以段为单位维护的，所以这里的 <code>+ acked</code> 不是把字节数直接加到窗口上，而是把“确认了几个完整段”加到窗口上。</p>\n<p>这就解释了为什么内核代码看起来和 RFC 公式不一样：</p>\n<ul>\n<li>RFC 讨论时常以字节为单位描述 <code>cwnd</code> 增长。</li>\n<li>Linux 这里的 <code>acked</code> 是“被确认的完整数据段数量”。</li>\n<li>因此 <code>tcp_snd_cwnd(tp) + acked</code> 的含义是：窗口按完整段数量增加。</li>\n</ul>\n<p>这个增长方式在理想情况下就和教材里的“每收到一个 ACK，<code>cwnd += 1 MSS</code>”对应：如果一个 ACK 正好确认一个完整 MSS，那么 <code>acked = 1</code>，窗口就增加 1 个段。</p>\n<h3>为什么这样也能防 ACK Division?</h3>\n<p>Linux 的防御方式与 RFC 不同：它不把一个段的一部分当作一次有效的“完整段确认”。只有当一个 packet 被完整确认时，才会计入 <code>acked</code>。所以恶意接收方把一个段拆成多个小 ACK，也不能让 <code>acked</code> 变成多个完整段。</p>\n<p>这就是注释里说的：</p>\n<blockquote>\n<p>Linux 并没有严格实现 ABC，而是做了“更好”的东西。</p>\n</blockquote>\n<p>这里的“更好”可以理解为：它没有按字节粒度做 ABC，而是从“完整段确认”这个粒度上防住了 ACK Division。这样可以有更高的吞吐量，实现起来也没有浮点和字节的计算，而且与拥塞避免阶段衔接的更顺利（后面逐行讲解代码会仔细解释）。</p>\n<h3>stretch ACK 下 Linux 更激进</h3>\n<p>再看 stretch ACK。</p>\n<p>假设一个 ACK 一次性确认了 3 个完整段，Linux 会把它当作连续收到 3 个普通 ACK，而 RFC 3465 的 ABC 会限制慢启动中的单次增长量，实验性建议里 <code>L</code> 不能超过 <code>2*SMSS</code>。所以在 stretch ACK 场景下，Linux 的处理会比 ABC 更激进一些。</p>\n<p>这也解释了注释里的这句话：</p>\n<blockquote>\n<p>Linux 把一个确认 N 个段的 stretch ACK，当成连续来了 N 个普通 ACK；但 ABC 会把这个数量限制到 2。</p>\n</blockquote>\n<h2>详解代码：逐行看 <code>tcp_slow_start()</code></h2>\n<p>现在再回头看代码：</p>\n<pre><code class=\"language-c\">__bpf_kfunc u32 tcp_slow_start(struct tcp_sock *tp, u32 acked)\n{\n\tu32 cwnd = min(tcp_snd_cwnd(tp) + acked, tp-&gt;snd_ssthresh);\n\n\tacked -= cwnd - tcp_snd_cwnd(tp);\n\ttcp_snd_cwnd_set(tp, min(cwnd, tp-&gt;snd_cwnd_clamp));\n\n\treturn acked;\n}\n</code></pre>\n<p>先解释几个变量：</p>\n<ul>\n<li><code>tp</code>：当前 TCP 连接的控制块，里面保存了这个连接的拥塞控制状态。</li>\n<li><code>tcp_snd_cwnd(tp)</code>：当前发送端拥塞窗口，单位是完整段。</li>\n<li><code>tp-&gt;snd_ssthresh</code>：慢启动阈值。慢启动最多增长到这个阈值附近，之后就要进入拥塞避免。</li>\n<li><code>tp-&gt;snd_cwnd_clamp</code>：拥塞窗口的硬上限，防止 <code>cwnd</code> 超过系统允许的最大值。</li>\n<li><code>acked</code>：这次 ACK 新确认的完整段数量。</li>\n</ul>\n<p>第一行：</p>\n<pre><code class=\"language-c\">u32 cwnd = min(tcp_snd_cwnd(tp) + acked, tp-&gt;snd_ssthresh);\n</code></pre>\n<p>它先计算慢启动阶段能增长到的新窗口：</p>\n<pre><code class=\"language-text\">新 cwnd = min(当前 cwnd + 新确认的完整段数, 慢启动阈值)\n</code></pre>\n<p>也就是说，慢启动阶段确实会按 <code>acked</code> 增加窗口，但最多只能增加到 <code>ssthresh</code>。</p>\n<p>第二行：</p>\n<pre><code class=\"language-c\">acked -= cwnd - tcp_snd_cwnd(tp);\n</code></pre>\n<p>这一行是在计算“这次 ACK 里，有多少确认量已经被慢启动消耗掉了”。</p>\n<p><code>cwnd - tcp_snd_cwnd(tp)</code> 表示这次慢启动实际让窗口增加了多少。然后从 <code>acked</code> 里减掉这一部分，剩下的就是慢启动没有用完的确认量。</p>\n<h3>碰到 <code>ssthresh</code> 时如何处理</h3>\n<p>举一个例子：</p>\n<pre><code class=\"language-text\">当前 cwnd = 8\nssthresh = 10\nacked = 5\n</code></pre>\n<p>如果不考虑 <code>ssthresh</code>，窗口本来可以从 8 增长到 13。</p>\n<p>但是慢启动最多只能增长到 <code>ssthresh = 10</code>：</p>\n<pre><code class=\"language-text\">实际新 cwnd = min(8 + 5, 10) = 10\n</code></pre>\n<p>所以慢启动实际只消耗了 2 个 <code>acked</code>：</p>\n<pre><code class=\"language-text\">实际增长量 = 10 - 8 = 2\n剩余 acked = 5 - 2 = 3\n</code></pre>\n<p>第三行：</p>\n<pre><code class=\"language-c\">tcp_snd_cwnd_set(tp, min(cwnd, tp-&gt;snd_cwnd_clamp));\n</code></pre>\n<p>这一行真正更新 TCP 控制块里的 <code>snd_cwnd</code>。更新时还要再和 <code>snd_cwnd_clamp</code> 取最小值，保证窗口不会超过系统设置的上限。</p>\n<p>最后一行：</p>\n<pre><code class=\"language-c\">return acked;\n</code></pre>\n<p>函数返回没有被慢启动消耗掉的 <code>acked</code>。</p>\n<p>如果慢启动还没有碰到 <code>ssthresh</code>，通常返回 0，表示这次 ACK 的确认量已经全部用来增加慢启动窗口了。</p>\n<p>如果刚好在这次 ACK 中跨过了 <code>ssthresh</code>，就会返回剩余的 <code>acked</code>，让后面的拥塞避免逻辑继续使用它。这样做的好处是：同一个 ACK 中超过慢启动阈值的那部分确认量不会被浪费，而是平滑地交给拥塞避免阶段处理。</p>\n<p>所以 Linux 这一段代码可以概括为：</p>\n<pre><code class=\"language-text\">在慢启动阶段：\n  cwnd 按新确认的完整段数 acked 增长；\n  但最多增长到 ssthresh；\n  如果这次 ACK 让 cwnd 碰到 ssthresh，就把剩余 acked 交给拥塞避免。\n</code></pre>\n<p>这就是为什么看完 RFC 后再看 Linux，会觉得公式变了：RFC 5681 / RFC 3465 是以“确认字节数”为中心描述规则，而 Linux 这里是以“完整段数”为单位实现窗口增长。</p>\n<hr>\n<h2>总结：三层对照：同一个慢启动，三种表达</h2>\n<p>这里通过一个表格来总结或许最合适：</p>\n<!-- table-widths: 20%, 26%, 27%, 27% -->\n<table>\n<thead>\n<tr>\n<th>维度</th>\n<th>教材模型</th>\n<th>RFC 5681 / RFC 3465</th>\n<th>Linux 内核</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>核心视角</td>\n<td>建立直觉</td>\n<td>规定协议边界</td>\n<td>工程实现</td>\n</tr>\n<tr>\n<td>增长依据</td>\n<td>ACK 数量</td>\n<td>ACK 新确认的字节数<code>N</code></td>\n<td>ACK 新确认的完整段数<code>acked</code></td>\n</tr>\n<tr>\n<td>慢启动公式</td>\n<td>每 ACK 确认一个报文段约<code>+1 MSS</code></td>\n<td><code>cwnd += min(N, SMSS)</code></td>\n<td><code>cwnd += acked</code></td>\n</tr>\n<tr>\n<td>单位</td>\n<td>通常按 MSS 抽象</td>\n<td>字节</td>\n<td>完整段</td>\n</tr>\n<tr>\n<td>stretch ACK 确认 3 段</td>\n<td>通常不讨论</td>\n<td>RFC 5681 最多<code>+1 SMSS</code>；RFC 3465 ABC 可用 <code>L</code> 调节但不超过 <code>2*SMSS</code></td>\n<td>近似<code>+3</code> 个段</td>\n</tr>\n<tr>\n<td>ACK Division 防御</td>\n<td>不涉及</td>\n<td>用<code>min(N, SMSS)</code> 限制增长</td>\n<td>只把完整段确认计入<code>acked</code></td>\n</tr>\n<tr>\n<td>理想每包一 ACK</td>\n<td>RTT 内翻倍</td>\n<td>RTT 内近似翻倍</td>\n<td>RTT 内近似翻倍</td>\n</tr>\n</tbody>\n</table>\n<p>可以看出，针对慢启动的公式，教材给出的与 linux 源码的方式是一样的。但是这样设计的背后，还有很多细节和考量，如果不是同学的一句话，我也了解不到这么多细节，如果你也有相关的了解，欢迎评论告诉我！</p>\n<p>如果你想试试做一个实验验证下，可以参考<a href=\"https://oneuptime.com/blog/post/2026-03-20-monitor-tcp-cwnd-real-time/view\">Linux cwnd 实验</a></p>\n<h2>参考资料</h2>\n<ul>\n<li><a href=\"https://www.rfc-editor.org/rfc/rfc5681\">RFC 5681: TCP Congestion Control</a></li>\n<li><a href=\"https://www.rfc-editor.org/rfc/rfc3465\">RFC 3465: TCP Congestion Control with Appropriate Byte Counting</a></li>\n<li><a href=\"https://github.com/torvalds/linux/blob/master/net/ipv4/tcp_cong.c\">Linux kernel: net/ipv4/tcp_cong.c</a></li>\n<li><a href=\"https://git.nju.edu.cn/nju/linux\">NJU Linux 镜像</a></li>\n<li><a href=\"https://oneuptime.com/blog/post/2026-03-20-monitor-tcp-cwnd-real-time/view\">Linux cwnd 实验</a></li>\n<li>拓展阅读：</li>\n<li><a href=\"https://blog.mickeyzzc.tech/posts/network/tcp-congestion-control-evolution/\">TCP 拥塞控制演进：从 Reno 到 BBR</a></li>\n<li><a href=\"https://blog.csdn.net/rjc_lihui/article/details/138302213\">TCP BBR拥塞控制算法深度解析</a></li>\n</ul>\n",
      "summary": "TCP 慢启动常被简化为“每个 RTT 拥塞窗口翻倍”，但教材模型、RFC 标准和 Linux 内核实现其实站在不同层面描述同一件事。我尝试把这三层放在一起对照，厘清 cwnd 到底按 ACK、字节还是完整段增长。",
      "date_published": "2026-07-06T00:00:00.000Z",
      "image": "https://img.markxu.icu/img2025408.png",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/blog/behind-localhost-cn",
      "url": "https://markxu.icu/blog/behind-localhost-cn",
      "title": "localhost 背后：一趟没有出门的网络旅行",
      "content_text": "从一个熟悉的地址说起 在终端里敲下 ，Vite 高高兴兴告诉你服务跑在 ；浏览器一点，页面出来了。或者调 Redis 时来一句 ，连的也是本机。这个场景我们再熟悉不过了，不过最近复习 408 的计网，学习到了网络分层。 于是一个很自然、也很容易被忽略的问题冒出来了： 既然我连的是“自己”，那它还算网络通信吗？是不是根本没走网络协议栈？走的话，又走了多少层？ 通过简单的调查，得到的答案有点反直觉：算，而且走了不少。于是想写下这篇文章，打算自顶向下的记录下 localhost 的背后流程。 简单来说：它不像访问外网那样经过网卡、交换机、路由器和网线，但在操作系统内部，应用层、传输层、网络层这几层依然认真上班。以前以为 是“程序直接找程序聊天”，但其实更像一份没有出小区的快递：没有上高速，但面单、分拣、签收流程都还在。 先说明一下： 是一个名字，不是一个 IP。它通常会解析到 IPv4 的 ，有些系统也可能优先解析到 IPv6 的 。下面为了讲清楚路径，我们默认讨论 这条 IPv4 回环路径。 前言：网络分层 在一切开始前，需要先来复习下 408 中的网络分层的知识，后面也好依据这个进行分析。 小故事环节： 网络分层如上图所示，OSI （Open System Interconnection）是国际标准化组织（ISO） 在 1977 年成立了一个专门委员会，开始研究网络互联的标准框架。他们希望制定一套通用的、开放的网络分层模型，让任何遵循该标准的系统都能互相通信。并在 1984 年正式发布的参考模型。其有着最标准的分层，不管什么网络都可以套用进来 TCP/IP 的故事要从美国国防部高级研究计划局（ARPA）说起。 1969 年，ARPANET（阿帕网）诞生，这是现代互联网的前身。它的最初目的是将大学和研究机构的计算机连接起来，实现资源共享。 1974 年，文特·瑟夫（Vint Cerf）和鲍勃·卡恩（Bob Kahn）发表了关于 TCP 协议的论文，首次提出了“网关”（后来演变为路由器）的概念，解决了不同网络之间的互联问题。 1983 年 1 月 1 日，ARPANET 正式将其核心协议从 NCP 切换到 TCP/IP，这一天被视为现代互联网的“生日”。 随后伯克利大学（BSD Unix）将 TCP/IP 的实现免费集成到 Unix 系统中，随着 Unix 在大学和科研机构的普及，TCP/IP 迅速传播开来。 由于 TCP/IP 的标准更简单高效，实现成本也更低，自然的取代了 OSI 的 方法，成为当今主流的网络分层方法。后面我们也将使用 TCP/IP 层进行具体的展开。 在继续之前，先借用几句AI话把 TCP/IP 五层都在干什么搞明白： 应用层负责“说什么”，比如 HTTP、Redis、MySQL 协议。 传输层负责“交给哪个进程、怎么传”，TCP/UDP 都在这里，端口号也是这一层的概念。 网络层负责“去哪个地址”，IP 就在这里，所以 是网络层地址。 链路层负责同一链路上的传输，比如以太网帧、MAC 地址这些通常在这里出现。 物理层负责把比特变成电信号、光信号或无线信号，真的让数据在硬件介质里跑起来。 基于上述描述，我们可以先来分析： 里的 是端口号，属于传输层； 是 IP 地址，属于网络层。很多网络问题一旦把这两个概念分清，脑子里就不会糊成一团。 TLDR： 层级 做了什么 关键点 ---------------- ------------------------------------------------------------------------------------------------------------------------------- --------------------------------------- 应用层 浏览器或客户端发起 HTTP 请求，目标地址为 这是数据的起点 传输层 操作系统根据端口号 找到对应的服务进程（比如你的 Web 服务器），并封装 TCP 段 端口号在这一层起作用 网络层 看到目标 IP 是 ，操作系统识别出这是一个 回环地址 ，不走物理网卡，直接交给回环接口（loopback interface）处理 这是最关键的一步——数据压根没离开本机 链路层 回环接口模拟了一个虚拟的链路层，把数据\"假装\"从网络发回来，实际上只是在内存里打了个转 没有真实的 MAC 地址交互 物理层 跳过 。因为没有真实硬件参与，数据不会变成电信号或光信号 这也是 localhost 比外网快得多的根本原因 所以最后的 localhost，其实走完了大部分的流程，只是没有走物理层。 应用层 —— 不经过 DNS 解析 我们先从最上层开始，看看 curl localhost:6370 的第一步做了什么。 实验对比：外网 vs localhost 我在终端中分别执行了两条命令，访问外网域名和自己的本地服务： 并通过 tcpdump 进行抓包 可以看到在运行访问外网域名的时候，终端有相关字样： 而在运行访问本地服务的时候什么都没有出现，这是因为 localhost 不是一个普通域名。根据 IETF 标准（RFC 6761），它被保留为特殊主机名。操作系统在处理 localhost 时，不会发起 DNS 查询，而是直接从 /etc/hosts 文件中读取映射关系 你可以自己验证这一点： 应用层还做了什么 解析完成后，curl 拿到了目标地址 127.0.0.1:6370。接下来它构造 HTTP 请求报文： 这段报文和访问外网时构造的报文在格式上没有任何区别。Host 头写的是 localhost:6370，但这只是内容不同，协议行为完全一致。 构造完成后，curl 将这个报文作为数据载荷，写入与 127.0.0.1:6370 关联的 TCP 套接字。至此，应用层的工作结束，数据交给下一层处理。 传输层 —— TCP 仍然会握手 应用层把 HTTP 报文写进 TCP 套接字后，接力棒交给了传输层。这一步与我一开始想的有所不同： 本机通信也需要 TCP 三次握手。 TCP 是一个面向连接的协议，无论通信双方是两台远程机器，还是同一台机器的两个进程，它都会完整执行三次握手：客户端发 SYN，服务端回 SYN-ACK，客户端再回 ACK。连接建立后，才开始传输 HTTP 报文数据。 唯一的区别在于：这个握手过程不会经过任何物理线路，而是在操作系统内核内部，通过回环接口 lo瞬间完成。RTT 趋近于零，不会触发重传，也不会经历拥塞控制——但协议状态机、序列号、确认号、端口号，一个都没少。 我们可以用 tcpdump来验证这一点。打开一个终端，监听回环接口上的 6370 端口： 然后在去运行下 curl localhost 的命令，可以得到下面的恢复： 我们可以逐行来插接下这个信息里面包含了什么。 请先把上面的代码块调整为横向滚动模式，方便对于行号 。 第二行：IPv6 尝试（被拒绝） 因为服务端（端口 6370）没有监听 IPv6，直接回了 ，这说明我的服务只绑定了 （IPv4），没有绑定 （IPv6） 第三行：TCP 三次握手（IPv4） curl 改用 IPv4 ，源端口变为 = SYN（客户端发起连接） = SYN-ACK（服务端同意连接） = ACK（客户端确认） 注意时间戳：三行都是 ，同一毫秒内完成 中间是 HTTP 的请求和相应 第六行：TCP 的四次挥手 可以看到时间戳，速度也很快。 网络层 —— 路由让它留在本机 应用层把 HTTP 报文交给 TCP 套接字，传输层封装好 TCP 段后，数据进入网络层。这里要做两件事：封装 IP 首部，以及查路由表决定“这个包往哪送”。 我们可以通过 的方式，去查看我们的 localhost 在网络层是什么样的 127.0.0.1的路由目的地就是它自己，接口是 lo0，flags 包含 LOCAL 外网 IP 的路由目的地是对应的网段，这里的接口不是物理网卡 en0，而是 utun1024，是因为我开启了代理服务，flags 包含 GATEWAY 同时注意到的一点，可以看到我们的 MTU（Maximum Transmission Unit，最大传输单元）在本地上的上限是 macos 设定的16384，而在连接外网的上面是标准的以太网的上限 1500。 链路层 —— 虚拟的\"假装传输\" 网络层做完路由决策后，数据包被标记为\"发往本地\"。按照正常的网络流程，下一步应该是链路层的工作：封装以太网帧、填充目标 MAC 地址，然后交给物理层发送。 但对于 ，事情在这里变得特殊了。 没有真正的 MAC 地址交互 我们可以用 命令来验证这一点： 你会发现没有任何输出。因为对于回环地址，操作系统根本不会发起 ARP 请求来询问\"谁的 IP 是 127.0.0.1？把你的 MAC 地址告诉我\"。 相比之下，如果你查局域网内的其他设备： 回环接口在做什么 操作系统内部有一个特殊的虚拟网络接口，叫做 loopback interface（在 macOS/Linux 上通常是 lo0）。 你可以用以下命令看到它的存在： 关键信息： ：标明这是一个回环接口 ：它绑定了这个 IP ：最大传输单元比以太网的 1500 大得多 网络层决定把数据包发给 127.0.0.1时，它实际上做的事情是：把数据包交给 lo0这个虚拟接口，lo0不会去找网卡驱动，而是直接把数据包\"镜像\"一份，放回操作系统的网络协议栈的接收队列。从接收端的角度看，就像是从网络上收到了一个数据包。 这个过程在操作系统内部被称为 loopback（回环），本质上是一次内存拷贝，没有任何硬件参与。 链路层还存在吗？ 严格来说，链路层的职责是\"在同一链路上传输数据帧\"。对于回环接口，操作系统模拟了一个极简的链路层：它会封装一个假的链路层头部（在 macOS 上是 NULL类型，Linux 上是 LOCALBACK），但它不会添加真实的 MAC 地址，也不会进行 CSMA/CD（载波侦听多点接入/碰撞检测），所以也不会有任何实际的帧传输延迟。 物理层呢？ 直接跳过了，不用写这部分真是太好了 ^∇^ 所以答案是：localhost 走了完整的 TCP/IP 五层中的四层，唯独跳过了物理层。 它不是\"程序直接找程序聊天\"这种简单的概念，而是依然经历了协议封装、端口寻址、路由决策、接口调度这一整套流程。只不过所有这些都发生在一台机器内部，像是一份永远不出小区门的快递：面单照贴、分拣照做、签收照办，只是快递员从来没上过马路。",
      "content_html": "<h2>从一个熟悉的地址说起</h2>\n<p>在终端里敲下 <code>npm run dev</code>，Vite 高高兴兴告诉你服务跑在 <code>localhost:5173</code>；浏览器一点，页面出来了。或者调 Redis 时来一句 <code>redis-cli -h 127.0.0.1 -p 6379</code>，连的也是本机。这个场景我们再熟悉不过了，不过最近复习 408 的计网，学习到了网络分层。</p>\n<p>于是一个很自然、也很容易被忽略的问题冒出来了：</p>\n<p><strong>既然我连的是“自己”，那它还算网络通信吗？是不是根本没走网络协议栈？走的话，又走了多少层？</strong></p>\n<p>通过简单的调查，得到的答案有点反直觉：算，而且走了不少。于是想写下这篇文章，打算自顶向下的记录下 localhost 的背后流程。</p>\n<p>简单来说：它不像访问外网那样经过网卡、交换机、路由器和网线，但在操作系统内部，应用层、传输层、网络层这几层依然认真上班。以前以为 <code>localhost</code> 是“程序直接找程序聊天”，但其实更像一份没有出小区的快递：没有上高速，但面单、分拣、签收流程都还在。</p>\n<p>先说明一下：<code>localhost</code> 是一个名字，不是一个 IP。它通常会解析到 IPv4 的 <code>127.0.0.1</code>，有些系统也可能优先解析到 IPv6 的 <code>::1</code>。下面为了讲清楚路径，我们默认讨论 <code>127.0.0.1</code> 这条 IPv4 回环路径。</p>\n<h2>前言：网络分层</h2>\n<p>在一切开始前，需要先来复习下 408 中的网络分层的知识，后面也好依据这个进行分析。</p>\n<p><img src=\"https://img.markxu.icu/imgnetwork-layer.png\" alt=\"网络分层\"></p>\n<blockquote>\n<p>小故事环节：</p>\n<p>网络分层如上图所示，OSI （Open System Interconnection）是国际标准化组织（ISO） 在 1977 年成立了一个专门委员会，开始研究网络互联的标准框架。他们希望制定一套通用的、开放的网络分层模型，让任何遵循该标准的系统都能互相通信。并在 1984 年正式发布的参考模型。其有着最标准的分层，不管什么网络都可以套用进来</p>\n<p>TCP/IP 的故事要从美国国防部高级研究计划局（ARPA）说起。</p>\n<ul>\n<li>1969 年，ARPANET（阿帕网）诞生，这是现代互联网的前身。它的最初目的是将大学和研究机构的计算机连接起来，实现资源共享。</li>\n<li>1974 年，文特·瑟夫（Vint Cerf）和鲍勃·卡恩（Bob Kahn）发表了关于 TCP 协议的论文，首次提出了“网关”（后来演变为路由器）的概念，解决了不同网络之间的互联问题。</li>\n<li>1983 年 1 月 1 日，ARPANET 正式将其核心协议从 NCP 切换到 TCP/IP，这一天被视为现代互联网的“生日”。</li>\n<li>随后伯克利大学（BSD Unix）将 TCP/IP 的实现免费集成到 Unix 系统中，随着 Unix 在大学和科研机构的普及，TCP/IP 迅速传播开来。</li>\n</ul>\n<p>由于 TCP/IP 的标准更简单高效，实现成本也更低，自然的取代了 OSI 的 方法，成为当今主流的网络分层方法。后面我们也将使用 TCP/IP 层进行具体的展开。</p>\n</blockquote>\n<p>在继续之前，先借用几句AI话把 TCP/IP 五层都在干什么搞明白：</p>\n<ul>\n<li>应用层负责“说什么”，比如 HTTP、Redis、MySQL 协议。</li>\n<li>传输层负责“交给哪个进程、怎么传”，TCP/UDP 都在这里，端口号也是这一层的概念。</li>\n<li>网络层负责“去哪个地址”，IP 就在这里，所以 <code>127.0.0.1</code> 是网络层地址。</li>\n<li>链路层负责同一链路上的传输，比如以太网帧、MAC 地址这些通常在这里出现。</li>\n<li>物理层负责把比特变成电信号、光信号或无线信号，真的让数据在硬件介质里跑起来。</li>\n</ul>\n<p>基于上述描述，我们可以先来分析：<code>localhost:8080</code> 里的 <code>8080</code> 是端口号，属于传输层；<code>127.0.0.1</code> 是 IP 地址，属于网络层。很多网络问题一旦把这两个概念分清，脑子里就不会糊成一团。</p>\n<h2>TLDR：</h2>\n<!-- table-widths: 16%, 56%, 28% -->\n<table>\n<thead>\n<tr>\n<th>层级</th>\n<th>做了什么</th>\n<th>关键点</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>应用层</strong></td>\n<td>浏览器或客户端发起 HTTP 请求，目标地址为<code>127.0.0.1:8080</code></td>\n<td>这是数据的起点</td>\n</tr>\n<tr>\n<td><strong>传输层</strong></td>\n<td>操作系统根据端口号<code>8080</code> 找到对应的服务进程（比如你的 Web 服务器），并封装 TCP 段</td>\n<td>端口号在这一层起作用</td>\n</tr>\n<tr>\n<td><strong>网络层</strong></td>\n<td>看到目标 IP 是<code>127.0.0.1</code>，操作系统识别出这是一个<strong>回环地址</strong>，不走物理网卡，直接交给回环接口（loopback interface）处理</td>\n<td>这是最关键的一步——数据压根没离开本机</td>\n</tr>\n<tr>\n<td><strong>链路层</strong></td>\n<td>回环接口模拟了一个虚拟的链路层，把数据&quot;假装&quot;从网络发回来，实际上只是在内存里打了个转</td>\n<td>没有真实的 MAC 地址交互</td>\n</tr>\n<tr>\n<td><strong>物理层</strong></td>\n<td><strong>跳过</strong>。因为没有真实硬件参与，数据不会变成电信号或光信号</td>\n<td>这也是 localhost 比外网快得多的根本原因</td>\n</tr>\n</tbody>\n</table>\n<p><strong>所以最后的 localhost，其实走完了大部分的流程，只是没有走物理层。</strong></p>\n<h2>应用层 —— 不经过 DNS 解析</h2>\n<p>我们先从最上层开始，看看 curl localhost:6370 的第一步做了什么。</p>\n<p>实验对比：外网 vs localhost</p>\n<p>我在终端中分别执行了两条命令，访问外网域名和自己的本地服务：</p>\n<pre><code class=\"language-Shell\">curl -v http://markxu.icu\ncurl -v localhost:6370\n</code></pre>\n<p>并通过 tcpdump 进行抓包</p>\n<pre><code class=\"language-Shell\">sudo tcpdump -i any port 53\n</code></pre>\n<p>可以看到在运行访问外网域名的时候，终端有相关字样：</p>\n<pre><code class=\"language-Shell\">12:26:00.381970 IP 198.18.0.1.56714 &gt; public1.114dns.com.domain: 53233+ A? markxu.icu. (28)\n12:26:00.382370 IP public1.114dns.com.domain &gt; 198.18.0.1.56714: 53233* 1/0/0 A 198.18.0.172 (44)\n12:26:00.387550 IP 192.168.20.80.49570 &gt; pdns.dnspod.cn.domain: 13415+ AAAA? markxu.icu. (28)\n12:26:00.387656 IP 192.168.20.80.63675 &gt; public1.alidns.com.domain: 13415+ AAAA? markxu.icu. (28)\n12:26:00.387763 IP 192.168.20.80.52301 &gt; public1.alidns.com.domain: 41468+ A? markxu.icu. (28)\n12:26:00.388014 IP 192.168.20.80.56763 &gt; pdns.dnspod.cn.domain: 41468+ A? markxu.icu. (28)\n</code></pre>\n<p>而在运行访问本地服务的时候什么都没有出现，这是因为 localhost 不是一个普通域名。根据 IETF 标准（RFC 6761），它被保留为特殊主机名。操作系统在处理 localhost 时，不会发起 DNS 查询，而是直接从 /etc/hosts 文件中读取映射关系</p>\n<p>你可以自己验证这一点：</p>\n<pre><code class=\"language-Shell\">cat /etc/hosts | grep localhost\n</code></pre>\n<p><img src=\"https://img.markxu.icu/imggrep-localhost.png\" alt=\"localhost 映射\"></p>\n<h3>应用层还做了什么</h3>\n<p>解析完成后，curl 拿到了目标地址 127.0.0.1:6370。接下来它构造 HTTP 请求报文：</p>\n<pre><code class=\"language-Shell\">GET / HTTP/1.1\nHost: localhost:6370\nUser-Agent: curl/8.7.1\nAccept: */*\n</code></pre>\n<p>这段报文和访问外网时构造的报文在格式上没有任何区别。Host 头写的是 localhost:6370，但这只是内容不同，协议行为完全一致。</p>\n<p>构造完成后，curl 将这个报文作为数据载荷，写入与 127.0.0.1:6370 关联的 TCP 套接字。至此，应用层的工作结束，数据交给下一层处理。</p>\n<h2>传输层 —— TCP 仍然会握手</h2>\n<p>应用层把 HTTP 报文写进 TCP 套接字后，接力棒交给了传输层。这一步与我一开始想的有所不同：</p>\n<p><strong>本机通信也需要 TCP 三次握手。</strong></p>\n<p>TCP 是一个面向连接的协议，无论通信双方是两台远程机器，还是同一台机器的两个进程，它都会完整执行三次握手：客户端发 SYN，服务端回 SYN-ACK，客户端再回 ACK。连接建立后，才开始传输 HTTP 报文数据。</p>\n<p>唯一的区别在于：这个握手过程不会经过任何物理线路，而是在操作系统内核内部，通过回环接口 lo瞬间完成。RTT 趋近于零，不会触发重传，也不会经历拥塞控制——但协议状态机、序列号、确认号、端口号，一个都没少。</p>\n<p>我们可以用 tcpdump来验证这一点。打开一个终端，监听回环接口上的 6370 端口：</p>\n<pre><code class=\"language-Shell\">sudo tcpdump -i lo0 port 6370\n</code></pre>\n<p>然后在去运行下 curl localhost 的命令，可以得到下面的恢复：</p>\n<pre><code class=\"language-Shell\">tcpdump: verbose output suppressed, use -v[v]... for full protocol decode\nlistening on lo0, link-type NULL (BSD loopback), snapshot length 524288 bytes\n14:17:36.505024 IP6 localhost.62464 &gt; localhost.6370: Flags [S], seq 3529818479, win 65535, options [mss 16324,nop,wscale 6,nop,nop,TS val 2294771787 ecr 0,sackOK,eol], length 0\n14:17:36.505080 IP6 localhost.6370 &gt; localhost.62464: Flags [R.], seq 0, ack 3529818480, win 0, length 0\n14:17:36.505206 IP localhost.62465 &gt; localhost.6370: Flags [S], seq 1917119642, win 65535, options [mss 16344,nop,wscale 6,nop,nop,TS val 3300697293 ecr 0,sackOK,eol], length 0\n14:17:36.505344 IP localhost.6370 &gt; localhost.62465: Flags [S.], seq 4137660183, ack 1917119643, win 65535, options [mss 16344,nop,wscale 6,nop,nop,TS val 4162405884 ecr 3300697293,sackOK,eol], length 0\n14:17:36.505365 IP localhost.62465 &gt; localhost.6370: Flags [.], ack 1, win 6380, options [nop,nop,TS val 3300697293 ecr 4162405884], length 0\n14:17:36.505379 IP localhost.6370 &gt; localhost.62465: Flags [.], ack 1, win 6380, options [nop,nop,TS val 4162405884 ecr 3300697293], length 0\n14:17:36.505607 IP localhost.62465 &gt; localhost.6370: Flags [P.], seq 1:78, ack 1, win 6380, options [nop,nop,TS val 3300697293 ecr 4162405884], length 77\n14:17:36.505631 IP localhost.6370 &gt; localhost.62465: Flags [.], ack 78, win 6379, options [nop,nop,TS val 4162405884 ecr 3300697293], length 0\n14:17:36.514104 IP localhost.6370 &gt; localhost.62465: Flags [P.], seq 1:1448, ack 78, win 6379, options [nop,nop,TS val 4162405893 ecr 3300697293], length 1447\n14:17:36.514168 IP localhost.62465 &gt; localhost.6370: Flags [.], ack 1448, win 6358, options [nop,nop,TS val 3300697302 ecr 4162405893], length 0\n14:17:36.514408 IP localhost.62465 &gt; localhost.6370: Flags [F.], seq 78, ack 1448, win 6358, options [nop,nop,TS val 3300697302 ecr 4162405893], length 0\n14:17:36.514434 IP localhost.6370 &gt; localhost.62465: Flags [.], ack 79, win 6379, options [nop,nop,TS val 4162405893 ecr 3300697302], length 0\n14:17:36.514744 IP localhost.6370 &gt; localhost.62465: Flags [F.], seq 1448, ack 79, win 6379, options [nop,nop,TS val 4162405894 ecr 3300697302], length 0\n14:17:36.514791 IP localhost.62465 &gt; localhost.6370: Flags [.], ack 1449, win 6358, options [nop,nop,TS val 3300697303 ecr 4162405894], length 0\n^C\n14 packets captured\n24 packets received by filter\n0 packets dropped by kernel\n</code></pre>\n<p>我们可以逐行来插接下这个信息里面包含了什么。</p>\n<p><strong>请先把上面的代码块调整为横向滚动模式，方便对于行号</strong>。</p>\n<h3>第二行：IPv6 尝试（被拒绝）</h3>\n<pre><code class=\"language-Shell\">14:17:36.505024 IP6 localhost.62464 &gt; localhost.6370: Flags [S], seq 3529818479, win 65535, options [mss 16324,nop,wscale 6,nop,nop,TS val 2294771787 ecr 0,sackOK,eol], length 0\n14:17:36.505080 IP6 localhost.6370 &gt; localhost.62464: Flags [R.], seq 0, ack 3529818480, win 0, length 0\n</code></pre>\n<p>因为服务端（端口 6370）没有监听 IPv6，直接回了<code> [R.]</code>，这说明我的服务只绑定了 <code>127.0.0.1</code>（IPv4），没有绑定 <code>::1</code>（IPv6）</p>\n<h3>第三行：TCP 三次握手（IPv4）</h3>\n<pre><code class=\"language-Shell\">14:17:36.505206 IP localhost.62465 &gt; localhost.6370: Flags [S], seq 1917119642, win 65535, options [mss 16344,nop,wscale 6,nop,nop,TS val 3300697293 ecr 0,sackOK,eol], length 0\n14:17:36.505344 IP localhost.6370 &gt; localhost.62465: Flags [S.], seq 4137660183, ack 1917119643, win 65535, options [mss 16344,nop,wscale 6,nop,nop,TS val 4162405884 ecr 3300697293,sackOK,eol], length 0\n14:17:36.505365 IP localhost.62465 &gt; localhost.6370: Flags [.], ack 1, win 6380, options [nop,nop,TS val 3300697293 ecr 4162405884], length 0\n</code></pre>\n<ul>\n<li>curl 改用 IPv4<code>（127.0.0.1）</code>，源端口变为 <code>62465</code></li>\n<li><code>[S]</code>= SYN（客户端发起连接）</li>\n<li><code>[S.]</code>= SYN-ACK（服务端同意连接）</li>\n<li><code>[.]</code>= ACK（客户端确认）<br>\n注意时间戳：三行都是 <code>14:17:36.505</code>，同一毫秒内完成</li>\n</ul>\n<p>中间是 HTTP 的请求和相应</p>\n<h3>第六行：TCP 的四次挥手</h3>\n<pre><code class=\"language-Shell\">14:17:36.514408 IP localhost.62465 &gt; localhost.6370: Flags [F.], seq 78, ack 1448, win 6358, options [nop,nop,TS val 3300697302 ecr 4162405893], length 0\n14:17:36.514434 IP localhost.6370 &gt; localhost.62465: Flags [.], ack 79, win 6379, options [nop,nop,TS val 4162405893 ecr 3300697302], length 0\n14:17:36.514744 IP localhost.6370 &gt; localhost.62465: Flags [F.], seq 1448, ack 79, win 6379, options [nop,nop,TS val 4162405894 ecr 3300697302], length 0\n14:17:36.514791 IP localhost.62465 &gt; localhost.6370: Flags [.], ack 1449, win 6358, options [nop,nop,TS val 3300697303 ecr 4162405894], length 0\n</code></pre>\n<p>可以看到时间戳，速度也很快。</p>\n<h2>网络层 —— 路由让它留在本机</h2>\n<p>应用层把 HTTP 报文交给 TCP 套接字，传输层封装好 TCP 段后，数据进入网络层。这里要做两件事：封装 IP 首部，以及查路由表决定“这个包往哪送”。<br>\n我们可以通过</p>\n<pre><code class=\"language-Shell\">route -n get 127.0.0.1\n</code></pre>\n<p>的方式，去查看我们的 localhost 在网络层是什么样的</p>\n<p><img src=\"https://img.markxu.icu/imgnetworklayer2.png\" alt=\"网络层\"></p>\n<ul>\n<li>127.0.0.1的路由目的地就是它自己，接口是 lo0，flags 包含 LOCAL</li>\n<li>外网 IP 的路由目的地是对应的网段，这里的接口不是物理网卡 en0，而是 utun1024，是因为我开启了代理服务，flags 包含 GATEWAY</li>\n</ul>\n<p>同时注意到的一点，可以看到我们的 MTU（Maximum Transmission Unit，最大传输单元）在本地上的上限是 macos 设定的16384，而在连接外网的上面是标准的以太网的上限 1500。</p>\n<h2>链路层 —— 虚拟的&quot;假装传输&quot;</h2>\n<p>网络层做完路由决策后，数据包被标记为&quot;发往本地&quot;。按照正常的网络流程，下一步应该是链路层的工作：封装以太网帧、填充目标 MAC 地址，然后交给物理层发送。</p>\n<p>但对于 <code>127.0.0.1</code>，事情在这里变得特殊了。</p>\n<h3>没有真正的 MAC 地址交互</h3>\n<p>我们可以用 <code>arp</code>命令来验证这一点：</p>\n<pre><code class=\"language-Shell\">arp -a | grep 127.0.0.1\n</code></pre>\n<p>你会发现没有任何输出。因为对于回环地址，操作系统根本不会发起 ARP 请求来询问&quot;谁的 IP 是 127.0.0.1？把你的 MAC 地址告诉我&quot;。<br>\n相比之下，如果你查局域网内的其他设备：</p>\n<pre><code class=\"language-Shell\">arp -a | grep 192.168\n</code></pre>\n<p><img src=\"https://img.markxu.icu/imgmac.png\" alt=\"mac地址对比\"></p>\n<h3>回环接口在做什么</h3>\n<p>操作系统内部有一个特殊的虚拟网络接口，叫做 loopback interface（在 macOS/Linux 上通常是 lo0）。<br>\n你可以用以下命令看到它的存在：</p>\n<pre><code class=\"language-Shell\">ifconfig lo0\n</code></pre>\n<p><img src=\"https://img.markxu.icu/imglo0.png\" alt=\"lo 0\"></p>\n<p>关键信息：</p>\n<ul>\n<li><code>LOOPBACK</code>：标明这是一个回环接口</li>\n<li><code>inet 127.0.0.1</code>：它绑定了这个 IP</li>\n<li><code>mtu 16384</code>：最大传输单元比以太网的 1500 大得多</li>\n</ul>\n<p>网络层决定把数据包发给 127.0.0.1时，它实际上做的事情是：把数据包交给 lo0这个虚拟接口，lo0不会去找网卡驱动，而是直接把数据包&quot;镜像&quot;一份，放回操作系统的网络协议栈的接收队列。从接收端的角度看，就像是从网络上收到了一个数据包。</p>\n<p>这个过程在操作系统内部被称为 loopback（回环），本质上是一次内存拷贝，没有任何硬件参与。</p>\n<h3>链路层还存在吗？</h3>\n<p>严格来说，链路层的职责是&quot;在同一链路上传输数据帧&quot;。对于回环接口，操作系统模拟了一个极简的链路层：它会封装一个假的链路层头部（在 macOS 上是 NULL类型，Linux 上是 LOCALBACK），但它不会添加真实的 MAC 地址，也不会进行 CSMA/CD（载波侦听多点接入/碰撞检测），所以也不会有任何实际的帧传输延迟。</p>\n<h3>物理层呢？</h3>\n<p>直接跳过了，不用写这部分真是太好了(^∇^)</p>\n<h2>所以答案是：localhost 走了完整的 TCP/IP 五层中的四层，唯独跳过了物理层。</h2>\n<p>它不是&quot;程序直接找程序聊天&quot;这种简单的概念，而是依然经历了协议封装、端口寻址、路由决策、接口调度这一整套流程。只不过所有这些都发生在一台机器内部，像是一份永远不出小区门的快递：面单照贴、分拣照做、签收照办，只是快递员从来没上过马路。</p>\n",
      "summary": "开发时我们天天访问的 localhost，它到底有没有走网络协议栈？又走了几层网络结构？",
      "date_published": "2026-06-25T00:00:00.000Z",
      "image": "https://img.markxu.icu/imgnetwork-layer.png",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/blog/anti-reward-hacking-college-cn",
      "url": "https://markxu.icu/blog/anti-reward-hacking-college-cn",
      "title": "拒绝 Reward Hacking：我的大学四年",
      "content_text": "近几日，纷纷与同学们道别，我在经过无数次的地方停了又停、看了又看，拍了许多照片，很是不舍。忍不住回忆下我的大学四年，但让我不断想到的，想让我目前记录下的，不只是我这几年都做了些什么事，还有我那时候为什么选择这样做？ 如果再来一次又会有什么不一样呢？ 我想蹭下最近比较火的概念： 拒绝 Reward Hacking，拒绝把自己的人生变成一个追求最大化单一指标的样子。 前面几篇的文章都是在毕业之际写的，或是一些各个方面的总结，或是一点点感想。大学四年的时光无疑是我这 22 年里面最浓墨重彩的四年，在离开学校的动车上，我写下这篇文章，记录下这四年的选择和经历，姑且算是一份私人小结吧。 Reward Hacking 原本是强化学习里的概念，意思是智能体利用奖励函数的漏洞，用非预期的方式拿到更高奖励。放到大学里，这个奖励函数很容易理解，无非是与绩点、排名、保研、奖学金、竞赛奖项这些沾边。这些当然重要，也确实能在各个场景中说明学生的优秀。但我想如果把这些指标当成了最终目的，忘记了学习和成长本身，那就很容易变成一种现实生活里的 Reward Hacking。 我在这四年里确实因为绩点不够高付出了些小代价，如果再来一次我或许会做得更 balance 一些。但我还是想认真记录一下，在一个几乎所有人都被提醒要“优化指标”的优绩主义盛行的社会中，我曾尝试坚持着把评价体系的奖励函数改成“是否真的学到了东西，是否更好的理解社会，是否更接近自己小时候想要成为的人”。 写下这篇文章并不是打算证明我做对了，因为这一点我自己也还不清楚答案，也没办法证明。所以更多的是记录下我把时间投向了哪里，以及这些选择怎样塑造了我，为以后的自己留下些此时的印记。 选择去外面看看 22 年的高考确实令人印象深刻。 那时我考出了人生中的最差排名。基本上我这个分数段的学生，为了上更好的学校，都会选择省内的学校，不太会选择出省上学。在看了许多曾经从来没有了解过的学校后，我与家里人商量，觉得还是想要出省，去外面看看，体验下别处的生活。好在家里人十分支持，我最终还是来到了南方，一个从来没有去过的城市上学。 既然是出省，想的是沿着东南沿海选择学校。那时一共可以填 90 个志愿，我填了 88 个，分为冲稳保三个层次。那一年张雪峰老师也正是最火的时候，经济虽然被疫情重创，但大家都认为我们可以快速恢复，仍然保留着疫情前的大体判断。我也根据当时的社会期望和自己的兴趣，选择了部分带电工科。 不出意外，那一年我感兴趣的专业排名档次全部比往年上升了许多，前面冲和稳的学校都够不上，一直到第 54 个志愿，华侨大学的计算机专业接受了我。 现在看来，我一点也不后悔当初的选择。来到一个与我生长环境不同的地方，身边全是有着与我家乡不同的文化氛围的同学，这本身就是我大学教育的一部分。 如果按照更稳妥的评价方式，我可能应该留在更熟悉、更可控的环境里，把风险降到最低。但那时我觉得，人生不该只是把已有路径走得更高效，更应该趁着时间还多，试错成本还低，去陌生的地方多去探索探索。 这大概是我第一次没有完全按照“最优解”来选择。 尝试追求新的东西 来到大学，我身边的大部分人仍然保留着高中的思想，想要追求保研，追求高绩点，很多学长学姐、家长老师也都这样嘱咐。确实， 一个可以快速量化并比较的指标最方便展示个人的实力。 尤其在高考之后，我们也没离开这种逻辑。 但从高中走出来后，我开始想试试追求些新的东西，追求我心里真正想要的。我当然也很在乎评价，只是不想自己继续沿着同一种奖励函数活下去：高中最大化考试分数，大学最大化绩点和简历，工作后最大化薪资和职级。这每一步看起来都合理且高效，但如果从来没有停下来问“这些指标究竟服务于什么？”，难免在一路优化中，把自己真正的好奇心、感受力和判断力都交出去。 我想看看那条别人不宣传的，少有脚印的路是怎么样的。 其实在高中时期，我就会买很多大学教材，比如陈阅增的《普通生物学》、《基础有机化学》，也会买很多科普类型的物理书籍去看，想要去了解我所学习的知识，看看有没有更进一步的解释，从高中就开始自学了许多知识。 虽然这些教材不全是积极的，比如大学的化学教材对我的高中成绩起了不小的反作用😂。高中的结论与大学教材的结论不一样，我总会按照大学教材的推理记混，导致做题的时候顾虑太多，速度慢了还总是做错。 或许从高中开始就有预兆，我不怎么关注怎么拿更多分，而是单纯的以为，如果我学会了这些知识，分数自然就上来了。 一直到高考结束后才认识到，针对考试这一件事，不仅要了解知识，还要了解为什么要考。只有两个方面都掌握了，才可以更好的拿到分数，以前我没有意识到“为什么要考“，所以或许走偏了些。 大一刚刚开学，我哥给我推荐了 csdiy 和 上海交通大学生存手册。我开始看这些在高考评价体系中最为优秀的人们写的内容，深以为然，也中二地想要成为他们这样有抱负有理想的人。于是我决定少花些精力内卷和争抢绩点，多学些真正感兴趣的东西，探索下这个社会里面的角落。 其实，今天在写下这句话时，也难免会想：“不追求绩点”这个决定可能是一种勇气，但也难说没有偷懒的想法在作祟。但关键不在口号，而在切实做到的事情。否则， 如此简单拒绝一个评价体系，不过是掉进另一个更模糊的自我感动里 。 接下来，我想谈谈我的收获。 友情：共同生活的人 不把绩点当唯一目标后，我最直接享受到的一点，是我与同学们之间的关系。 我与班级的同学相处都很融洽，绝大多数时候没有直接的利益冲突。我们之间也是能帮就帮，尽最大可能去分享快乐、感受快乐，大学期间获得了不少真挚的友谊。有不少同学受我的部分影响，学着去拓展自己的爱好，跟着我去锻炼身体，观看交响乐演出，在厦门这个大城市乐园里面留下了很多美好的回忆。我也通过他们的经历和爱好，混入了不少圈子，有了更多共同话题，渡过了一段充实且惬意的大学时光。 这件事对我很重要。根据我身边发生的故事来看，高强度的评价体系很容易把我身边人变成隐形的比较对象：他的成绩、她的排名、谁拿到了机会、谁又多了一项加分。久而久之，别人的成功会变成自己的威胁，别人的失败会变成自己的安全感。这种感觉并不舒服。 我很庆幸大学里没有长期陷在这种关系里。同学首先是和我共同生活的人，不该只被看成挡在我前面的竞争者。这样的关系让我在很多焦虑时刻都有可以求助、可以玩笑、可以一起吃饭散步的人。这些肯定没法放进简历里面，却是我大学四年最真实的收获之一。 阅读和社会：拓宽我眼中的世界 第二点是 我学习了很多与专业无关的知识，看了不少书。 期间我学了一部分曼昆的《经济学原理》，也尝试读了毛选和《共产党宣言》，让我意识到自己与共产党员的思想差距，也让我有了更为坚定的立场和更灵活的视角。因为同学对日本文化感兴趣，我学着看了几本村上春树、川端康成的小说，还有《菊与刀》，一个美国视角下的日本文化。还因为他们看了不少动漫和二次元。 这些东西都不能变成可以量化的成果，但它们确实让我变得更不像一个只会做题和完成任务的人，而是在遇到陌生人，也可以试着找找共同话题，快速添加共识和兴趣。人需要一些看似无用的输入，才会理解别人为什么这样生活，社会为什么这样运转，自己为什么会在某些公共事情上焦虑、愤怒或感动。 第三点或许是与社会接触吧。 我很少参加学校内部组织的志愿活动，也没有为了加志愿时长以获得保研优势而多去参加一些简单活动，更多是去街上与人聊天，去社区搭把手，认识了不少在厦门认真生活的人，也认识了不少没有和我一样幸运的学习条件、但仍然以自己的方法努力生活的同龄人。 这些经历让我对社会上的焦虑和内耗减少了许多。因为当我真的看见具体的人，很多抽象的、互联网上互相撕扯拉踩的叙事就会变得没那么两极化。大家都在用自己的方式活着，有人幸运，有人艰难，有人混乱，有人坚韧。认识这些人之后，我更难把人生简单理解成一张排名表，也更加确定了我的方向似乎有可取之处。 与社会接触其实也有利于我的心理健康。因为一个人只在优绩主义的坐标系里理解自己，那很容易永远处在不够好的状态：学校不够好、成绩不够高、项目不够强、出身不够亮眼、未来不够确定。但现实中的人比这些标签复杂得多，也丰富得多，正如毛主席说过： 与天奋斗，其乐无穷；与地奋斗，其乐无穷；与人奋斗，其乐无穷。 健身：意想不到的收获 我在大学之前一直都很胖，一直到高二下学期和我的好兄弟做了同桌后，突然瘦了 30 斤左右。他喜欢健身，我就跟着他学习 （看来我还蛮习惯向周围人学习，嘿嘿） ，从那以后，我也开始健身了。 虽然练了这么久，估计也有四年了，最终身上仍然有不少赘肉，也没有练得多么好看。但健身的这个决定让我受益匪浅，仍然在生活的方方面面给我提供便利。首先是身体素质上来了，不容易生病感冒；其次是身上有力量，有时候我居然能连着坐着打超过 24 小时游戏，之后躺下睡一觉起来后也神清气爽，不会腰酸背痛得不行。当然最重要的是，健身期间学习了身体的知识，结合高中对生物的学习，我也学会利用生活的方方面面控制和调节自己的激素分泌，养成了还算不错的习惯，知道身体需要什么，避免了许多智商税产品。也有一个还算健康的身体。 并且健身也让我认识了社会上很多朋友，他们来自各行各业，有着不同的经历，也有来自不同国家、不同地区的同学，都是通过健身了解到的。 如果从功利角度看，健身也可以被包装成自律、形象管理和效率工具。但是一个健康的身体，一种稳定的生活节律，一些真实的社交和共同训练的时刻，本身就是生活质量的一部分。它们的意义不在于让我在下一轮竞争里更能熬夜，而是尽可能的去发展自己，兼顾思想和身体。 比赛和项目：成果之外，学会真实地做事 本科期间我也参与了几个比赛，我学习最多的是数学建模这一类的比赛，还有一次大创的经历。除了专业方面的知识，团队合作的方法更让我印象深刻。 数学建模 针对数学建模这种为期 3 天的比赛，我们从拿到题目只有 3 天的时间，最终结果是要写一篇论文出来。不管怎么样还是有一定挑战性的。即使有了 AI，也要对基本的算法有基本了解，分析数据适合什么样的算法，才可以使用 AI 编程来解决具体问题。 在期间我们经历过很多意见不一致的情况。比如我一般认为类似于美赛的 A 题和 B 题，对现实问题进行建模并分析的内容更有挑战性些，也更有意思些，我更倾向于这种。但我的队友和我也考虑为了求稳，所有正式比赛都选择的数据分析类题目。因为我们是计算机专业，对物理上面的很多专业知识不如对应专业的同学清晰。选择数据分析类，反而更与我们的专业知识有些许重合，一般都是套用几个机器学习算法，拟合出一个差不多的结果，然后写一篇论文出来。 在比赛期间，我们通常要连着熬 2 天夜，情绪也难免有波动。作为队长（其实也是后来才意识到这个身份还是有一定的价值的），我主要要做的是：怎么在队员情绪不影响效率的情况下，按照既定计划和分工完成工作；确定我们的题目方向；结合自身的知识熟练度得出解法并说服队友为什么这样做是最适合我们的；以及在出错后及时回正方向盘，优先解决问题。 这些都是我在犯过一次错后，自己慢慢总结摸索出来的。我们第一次数模比赛在提交的前一天就直接放弃了，最主要的原因是作为组织同学一起比赛的人，我没有做好一个带头作用，而另外两个同学相互不算熟悉，导致大家相处起来有些尴尬，也不敢表达自己真实想法。类似的错误我也都是犯过一次才明白，比如沟通的重要性、如何快速对齐进度、如何迅速调整方向等等... 比赛当然也有很强的指标导向：获奖、评级、证书、综测加分。但我后来发现，真正留下来的并非那张证书，更多是失败后怎么复盘，团队意见不一致时怎么推进，压力很大时怎么让大家还愿意继续相信彼此。这些能力也没那么容易被评分表捕捉，却更接近“真实地做事”。 大创：浅尝科研之路 大创项目是学长推荐我做的，说可以学习到不少东西。我主动向我的本科生老师联系，并且找到了一个我和队友们都还算感兴趣的方向，确定了项目题目，开始了为期一年的科研经历。 刚刚开始主要是一大堆的文书工作。我也是第一次把我们的项目申请书改了又改，多谢我的导师耐心教导，我在不断修改的过程中，也逐渐摸索出了与导师的联系方法（与初高中的老师是两种相处思路），也慢慢摸清楚一个标准的文档应该怎么去写。我在我大学两年的简单科研实践中，也十分感谢我的导师。 说到团队合作，为期一年的项目以及 4 名同学作为队员，相较于数模比赛，难度又上升了许多。首先是确保同学们真的学习到了可以后续用到的知识，其次，是我作为组长，应该及时确定下来技术栈并安排好方向，组织线下活动让大家互相了解，确定责任划分以及进度的定期检查。这些我都没有做到。大家之间的交流也经常隔了一两周才能得到回复，让我们的项目推进远远落后于别的小组，那段时间也是我最焦虑的时间，既害怕结项不了耽误大家，也不想这么容易就认输。 在中期答辩后，我开始阅读我们大一计算机导论老师推荐的《人月神话》，开始意识到自己的管理和沟通问题，并及时调整，好在最后真的顺利结项了。 在大创期间，我也是第一次意识到了交流的重要性。在中期之前，一直由于自己进度慢不敢联系老师，怕被老师责备，后面才体会到老师的作用更偏向指引，而我也应该主动向老师报备交流。 同时我之前提到过的同学们和我的关系不错，听我倒了不少苦水，他们也都默默的支持和安慰我，甚至主动和我出去散心，我都十分感激。 大创最像一个可以被 Reward Hacking 的系统：像是结项材料、答辩、成果要求，有很多可操作的空间。大可以把它做成一套漂亮但空心的材料，也可以把它当成一次笨拙但真实的科研和协作训练。 我并不敢说自己做得多好，甚至很多地方做得很差，但至少这段经历让我知道，真实项目光靠热情很难完成，它需要沟通、计划、责任分配，也需要在进度很糟糕的时候承认问题并重新组织，最后的结果远没有我在过程中学到的东西重要。 虽然通过我的观察，也有不少同学的大创项目是所谓的“祖传项目”。我也亲眼看到在我前一届的某一项目结项答辩后，在我同届的大创中又成功立项了，且是同一批老师听完答辩又通过下一届的项目的。或许大家说大创水也是如此。但同时，我也在互联网上注意到了有许多和我一样，没有一开始拿到现有资源，仍然努力的同学们。不管是否有前提资源，还是推荐大家去试试，人真的会在做事的过程中成长许多。 租房：第一次独立生活 为了完成大创项目，我自己组装了一个电脑，而学校的四改六宿舍又不支持机箱的存在。并且我一旦需要完成项目，常常沉迷修 bug 忙到半夜三点到四点。为了不打扰室友，也为了有一个更专注的环境，我和家里说明情况，出来租房住了两年。离学校不远，但是独立的生活确实是我从来没有过的经历。 在租房期间，办理各种手续，打扫收拾卫生，甚至终于有机会自己给自己做饭吃，都是很新奇的体验。 这些经历很难被算进大学评价体系里。没有人会因为你学会做饭、交水电费、收拾房间、安排自己的作息而给你加分。但我越来越觉得，独立生活本身就是大学的一部分。它让我从一个被安排的人，慢慢变成一个需要自己维护生活秩序的人。 成长不一定都发生在教室、实验室和竞赛场里，有些成长就发生在某个凌晨收拾完桌子，发现自己真的可以把生活一点点维持起来的时候。 没有绩点神话，也没有轻松自由 写到这里，如果只写好的方面，那就是自我辩护，像是想要强行给自己洗脑。 坏的方面确实让我很受挫。由于没有追求绩点，最后的成绩落在了 3.97/5.00，与在我排名之前同学们的 4+ 绩点显得有些不够看。距离学校的保研名额就差 2 名，分数差也很小。如果把一些小课的成绩刷上来，或许我又可以多一年的时间去尝试些更大胆的事情。如果再来一遍的话，我也绝对会尝试更精妙地掌握些平衡，不要错失这个机会。尽管我也深刻意识到，如果时光倒退，我也依然会做出我当时的选择和决定。 这也是我现在对“拒绝 Reward Hacking”更谨慎的原因。拒绝单一指标，不等价于无视规则；追求真实学习，也不等于可以不对结果负责。评价体系虽然有问题，但它也确实掌握着很多机会的入口，我的绩点虽然不算特别高，但我还算不错的排名和学习经历也确确实实给了我不少机会。我爸也经常和我说： 一个人要了解规则，利用规则。如果完全不理解规则，就很容易在关键节点付出很高代价。 所以我不想把这四年总结成“我不卷，所以我自由”，这种只抓眼球不负责的口号。更准确地说，是我在自由和机会之间、兴趣和指标之间、长期成长和短期门票之间，一直做着不太成熟的权衡。有些选择我现在仍然认可，有些选择则会在夜里想起时感到遗憾。 我将这些遗憾也视作我现在的一部分。这些提醒我，真正好的生活策略不能只是简单反抗评价体系，为了反而反，而是要理解指标的力量，同时避免被指标完全支配，就像我高中的体会一样，要明白知识点，还要明白为什么考这个知识点。 优绩主义之外，还有什么？ 这几件事情几乎概括完了我的大学时光：自学、健身、比赛、项目、租房，还有许多和朋友一起浪费掉又珍贵无比的时间。说起来很快，期间的每一个细节，遇到的挑战和好运气我都历历在目。火车也快到站了，我也快点结束。 写完这篇，我仍然没有一个漂亮的答案。大学四年让我更深地理解了优绩主义的吸引力：它清晰、直接、可比较，能告诉你现在排在哪里，下一步该怎么努力。对于很多普通人来说，它又是一种相对公平的上升通道。 但我也越来越怀疑，它能不能作为贯彻人生的最高目标。因为当一个人总是通过“比别人更优秀”来确认自己，就很难真正停下来问：我学到的东西是否让我更自由？我创造的内容是否真的有意义？我和他人的关系是否更真诚？我是否在理解更大的世界，还是只是在更小的排行榜里爬升？ 或许，人生需要一种比优绩主义更好的目标。 它不应该否认努力，不应该轻视能力，不应该把懒散包装成清醒。但它应该比“赢过别人”更宽阔一些：能容纳真实的学习、具体的爱、对社会的理解、创造的快乐、身体的健康、与身边人共同生活的记忆，也能容纳那些没有被指标记录却确实让人成长的时刻。",
      "content_html": "<p>近几日，纷纷与同学们道别，我在经过无数次的地方停了又停、看了又看，拍了许多照片，很是不舍。忍不住回忆下我的大学四年，但让我不断想到的，想让我目前记录下的，不只是我这几年都做了些什么事，还有我那时候为什么选择这样做？</p>\n<p>如果再来一次又会有什么不一样呢？</p>\n<p>我想蹭下最近比较火的概念：<strong>拒绝 Reward Hacking，拒绝把自己的人生变成一个追求最大化单一指标的样子。</strong></p>\n<hr>\n<p>前面几篇的文章都是在毕业之际写的，或是一些各个方面的总结，或是一点点感想。大学四年的时光无疑是我这 22 年里面最浓墨重彩的四年，在离开学校的动车上，我写下这篇文章，记录下这四年的选择和经历，姑且算是一份私人小结吧。</p>\n<p>Reward Hacking 原本是强化学习里的概念，意思是智能体利用奖励函数的漏洞，用非预期的方式拿到更高奖励。放到大学里，这个奖励函数很容易理解，无非是与绩点、排名、保研、奖学金、竞赛奖项这些沾边。这些当然重要，也确实能在各个场景中说明学生的优秀。但我想如果把这些指标当成了最终目的，忘记了学习和成长本身，那就很容易变成一种现实生活里的 Reward Hacking。</p>\n<p>我在这四年里确实因为绩点不够高付出了些小代价，如果再来一次我或许会做得更 balance 一些。但我还是想认真记录一下，在一个几乎所有人都被提醒要“优化指标”的优绩主义盛行的社会中，我曾尝试坚持着把评价体系的奖励函数改成“是否真的学到了东西，是否更好的理解社会，是否更接近自己小时候想要成为的人”。</p>\n<p>写下这篇文章并不是打算证明我做对了，因为这一点我自己也还不清楚答案，也没办法证明。所以更多的是记录下我把时间投向了哪里，以及这些选择怎样塑造了我，为以后的自己留下些此时的印记。</p>\n<h2>选择去外面看看</h2>\n<p>22 年的高考确实令人印象深刻。</p>\n<p>那时我考出了人生中的最差排名。基本上我这个分数段的学生，为了上更好的学校，都会选择省内的学校，不太会选择出省上学。在看了许多曾经从来没有了解过的学校后，我与家里人商量，觉得还是想要出省，去外面看看，体验下别处的生活。好在家里人十分支持，我最终还是来到了南方，一个从来没有去过的城市上学。</p>\n<p>既然是出省，想的是沿着东南沿海选择学校。那时一共可以填 90 个志愿，我填了 88 个，分为冲稳保三个层次。那一年张雪峰老师也正是最火的时候，经济虽然被疫情重创，但大家都认为我们可以快速恢复，仍然保留着疫情前的大体判断。我也根据当时的社会期望和自己的兴趣，选择了部分带电工科。</p>\n<p>不出意外，那一年我感兴趣的专业排名档次全部比往年上升了许多，前面冲和稳的学校都够不上，一直到第 54 个志愿，华侨大学的计算机专业接受了我。</p>\n<p>现在看来，我一点也不后悔当初的选择。来到一个与我生长环境不同的地方，身边全是有着与我家乡不同的文化氛围的同学，这本身就是我大学教育的一部分。</p>\n<p>如果按照更稳妥的评价方式，我可能应该留在更熟悉、更可控的环境里，把风险降到最低。但那时我觉得，人生不该只是把已有路径走得更高效，更应该趁着时间还多，试错成本还低，去陌生的地方多去探索探索。</p>\n<p>这大概是我第一次没有完全按照“最优解”来选择。</p>\n<h2>尝试追求新的东西</h2>\n<p>来到大学，我身边的大部分人仍然保留着高中的思想，想要追求保研，追求高绩点，很多学长学姐、家长老师也都这样嘱咐。确实，<strong>一个可以快速量化并比较的指标最方便展示个人的实力。</strong> 尤其在高考之后，我们也没离开这种逻辑。</p>\n<p>但从高中走出来后，我开始想试试追求些新的东西，追求我心里真正想要的。我当然也很在乎评价，只是不想自己继续沿着同一种奖励函数活下去：高中最大化考试分数，大学最大化绩点和简历，工作后最大化薪资和职级。这每一步看起来都合理且高效，但如果从来没有停下来问“这些指标究竟服务于什么？”，难免在一路优化中，把自己真正的好奇心、感受力和判断力都交出去。<strong>我想看看那条别人不宣传的，少有脚印的路是怎么样的。</strong></p>\n<p>其实在高中时期，我就会买很多大学教材，比如陈阅增的《普通生物学》、《基础有机化学》，也会买很多科普类型的物理书籍去看，想要去了解我所学习的知识，看看有没有更进一步的解释，从高中就开始自学了许多知识。</p>\n<p>虽然这些教材不全是积极的，比如大学的化学教材对我的高中成绩起了不小的反作用😂。高中的结论与大学教材的结论不一样，我总会按照大学教材的推理记混，导致做题的时候顾虑太多，速度慢了还总是做错。</p>\n<div class=\"photo-scroll-vertical\">\n    <img src=\"https://img.markxu.icu/img20260614135429925.png\" alt=\"陈阅增普通生物学\" />\n    <img src=\"https://img.markxu.icu/img20260614135140509.png\" alt=\"基础有机化学\" />\n    <img src=\"https://img.markxu.icu/img20260614135516213.png\" alt=\"上帝掷骰子吗\" />\n</div>\n<p>或许从高中开始就有预兆，我不怎么关注怎么拿更多分，而是单纯的以为，如果我学会了这些知识，分数自然就上来了。</p>\n<p>一直到高考结束后才认识到，针对考试这一件事，不仅要了解知识，还要了解为什么要考。只有两个方面都掌握了，才可以更好的拿到分数，以前我没有意识到“为什么要考“，所以或许走偏了些。</p>\n<p>大一刚刚开学，我哥给我推荐了 <a href=\"https://csdiy.wiki/en/\">csdiy</a> 和 <a href=\"https://survivesjtu.gitbook.io/survivesjtumanual\">上海交通大学生存手册</a>。我开始看这些在高考评价体系中最为优秀的人们写的内容，深以为然，也中二地想要成为他们这样有抱负有理想的人。于是我决定少花些精力内卷和争抢绩点，多学些真正感兴趣的东西，探索下这个社会里面的角落。</p>\n<p>其实，今天在写下这句话时，也难免会想：“不追求绩点”这个决定可能是一种勇气，但也难说没有偷懒的想法在作祟。但关键不在口号，而在切实做到的事情。否则，<strong>如此简单拒绝一个评价体系，不过是掉进另一个更模糊的自我感动里</strong>。</p>\n<p>接下来，我想谈谈我的收获。</p>\n<h2>友情：共同生活的人</h2>\n<p>不把绩点当唯一目标后，我最直接享受到的一点，是我与同学们之间的关系。</p>\n<p>我与班级的同学相处都很融洽，绝大多数时候没有直接的利益冲突。我们之间也是能帮就帮，尽最大可能去分享快乐、感受快乐，大学期间获得了不少真挚的友谊。有不少同学受我的部分影响，学着去拓展自己的爱好，跟着我去锻炼身体，观看交响乐演出，在厦门这个大城市乐园里面留下了很多美好的回忆。我也通过他们的经历和爱好，混入了不少圈子，有了更多共同话题，渡过了一段充实且惬意的大学时光。</p>\n<p><img src=\"https://img.markxu.icu/imgb6fd11ce8b6196d81325726123b66c5f.jpg\" alt=\"一起去看交响乐\"></p>\n<p>这件事对我很重要。根据我身边发生的故事来看，高强度的评价体系很容易把我身边人变成隐形的比较对象：他的成绩、她的排名、谁拿到了机会、谁又多了一项加分。久而久之，别人的成功会变成自己的威胁，别人的失败会变成自己的安全感。这种感觉并不舒服。</p>\n<p>我很庆幸大学里没有长期陷在这种关系里。同学首先是和我共同生活的人，不该只被看成挡在我前面的竞争者。这样的关系让我在很多焦虑时刻都有可以求助、可以玩笑、可以一起吃饭散步的人。这些肯定没法放进简历里面，却是我大学四年最真实的收获之一。</p>\n<h2>阅读和社会：拓宽我眼中的世界</h2>\n<p>第二点是<strong>我学习了很多与专业无关的知识，看了不少书。</strong></p>\n<p>期间我学了一部分曼昆的《经济学原理》，也尝试读了毛选和《共产党宣言》，让我意识到自己与共产党员的思想差距，也让我有了更为坚定的立场和更灵活的视角。因为同学对日本文化感兴趣，我学着看了几本村上春树、川端康成的小说，还有《菊与刀》，一个美国视角下的日本文化。还因为他们看了不少动漫和二次元。</p>\n<p>这些东西都不能变成可以量化的成果，但它们确实让我变得更不像一个只会做题和完成任务的人，而是在遇到陌生人，也可以试着找找共同话题，快速添加共识和兴趣。人需要一些看似无用的输入，才会理解别人为什么这样生活，社会为什么这样运转，自己为什么会在某些公共事情上焦虑、愤怒或感动。</p>\n<p><strong>第三点或许是与社会接触吧。</strong> 我很少参加学校内部组织的志愿活动，也没有为了加志愿时长以获得保研优势而多去参加一些简单活动，更多是去街上与人聊天，去社区搭把手，认识了不少在厦门认真生活的人，也认识了不少没有和我一样幸运的学习条件、但仍然以自己的方法努力生活的同龄人。</p>\n<p>这些经历让我对社会上的焦虑和内耗减少了许多。因为当我真的看见具体的人，很多抽象的、互联网上互相撕扯拉踩的叙事就会变得没那么两极化。大家都在用自己的方式活着，有人幸运，有人艰难，有人混乱，有人坚韧。认识这些人之后，我更难把人生简单理解成一张排名表，也更加确定了我的方向似乎有可取之处。</p>\n<p>与社会接触其实也有利于我的心理健康。因为一个人只在优绩主义的坐标系里理解自己，那很容易永远处在不够好的状态：学校不够好、成绩不够高、项目不够强、出身不够亮眼、未来不够确定。但现实中的人比这些标签复杂得多，也丰富得多，正如毛主席说过：</p>\n<blockquote>\n<p>与天奋斗，其乐无穷；与地奋斗，其乐无穷；与人奋斗，其乐无穷。</p>\n</blockquote>\n<p><img src=\"https://img.markxu.icu/img20260616171705555.png\" alt=\"毛主席语录\"></p>\n<h2>健身：意想不到的收获</h2>\n<p>我在大学之前一直都很胖，一直到高二下学期和我的好兄弟做了同桌后，突然瘦了 30 斤左右。他喜欢健身，我就跟着他学习 <em>（看来我还蛮习惯向周围人学习，嘿嘿）</em>，从那以后，我也开始健身了。</p>\n<p>虽然练了这么久，估计也有四年了，最终身上仍然有不少赘肉，也没有练得多么好看。但健身的这个决定让我受益匪浅，仍然在生活的方方面面给我提供便利。首先是身体素质上来了，不容易生病感冒；其次是身上有力量，有时候我居然能连着坐着打超过 24 小时游戏，之后躺下睡一觉起来后也神清气爽，不会腰酸背痛得不行。当然最重要的是，健身期间学习了身体的知识，结合高中对生物的学习，我也学会利用生活的方方面面控制和调节自己的激素分泌，养成了还算不错的习惯，知道身体需要什么，避免了许多智商税产品。也有一个还算健康的身体。</p>\n<div class=\"img-grid-2\">\n    <img src=\"https://img.markxu.icu/img1000253384.jpg\" alt=\"大学健身房\" />\n    <img src=\"https://img.markxu.icu/img1000253385.jpg\" alt=\"环境\" />\n</div>\n<p>并且健身也让我认识了社会上很多朋友，他们来自各行各业，有着不同的经历，也有来自不同国家、不同地区的同学，都是通过健身了解到的。</p>\n<p>如果从功利角度看，健身也可以被包装成自律、形象管理和效率工具。但是一个健康的身体，一种稳定的生活节律，一些真实的社交和共同训练的时刻，本身就是生活质量的一部分。它们的意义不在于让我在下一轮竞争里更能熬夜，而是尽可能的去发展自己，兼顾思想和身体。</p>\n<h2>比赛和项目：成果之外，学会真实地做事</h2>\n<p>本科期间我也参与了几个比赛，我学习最多的是数学建模这一类的比赛，还有一次大创的经历。除了专业方面的知识，团队合作的方法更让我印象深刻。</p>\n<h3>数学建模</h3>\n<p>针对数学建模这种为期 3 天的比赛，我们从拿到题目只有 3 天的时间，最终结果是要写一篇论文出来。不管怎么样还是有一定挑战性的。即使有了 AI，也要对基本的算法有基本了解，分析数据适合什么样的算法，才可以使用 AI 编程来解决具体问题。</p>\n<p>在期间我们经历过很多意见不一致的情况。比如我一般认为类似于美赛的 A 题和 B 题，对现实问题进行建模并分析的内容更有挑战性些，也更有意思些，我更倾向于这种。但我的队友和我也考虑为了求稳，所有正式比赛都选择的数据分析类题目。因为我们是计算机专业，对物理上面的很多专业知识不如对应专业的同学清晰。选择数据分析类，反而更与我们的专业知识有些许重合，一般都是套用几个机器学习算法，拟合出一个差不多的结果，然后写一篇论文出来。</p>\n<p>在比赛期间，我们通常要连着熬 2 天夜，情绪也难免有波动。作为队长（其实也是后来才意识到这个身份还是有一定的价值的），我主要要做的是：怎么在队员情绪不影响效率的情况下，按照既定计划和分工完成工作；确定我们的题目方向；结合自身的知识熟练度得出解法并说服队友为什么这样做是最适合我们的；以及在出错后及时回正方向盘，优先解决问题。</p>\n<p>这些都是我在犯过一次错后，自己慢慢总结摸索出来的。我们第一次数模比赛在提交的前一天就直接放弃了，最主要的原因是作为组织同学一起比赛的人，我没有做好一个带头作用，而另外两个同学相互不算熟悉，导致大家相处起来有些尴尬，也不敢表达自己真实想法。类似的错误我也都是犯过一次才明白，比如沟通的重要性、如何快速对齐进度、如何迅速调整方向等等...</p>\n<p>比赛当然也有很强的指标导向：获奖、评级、证书、综测加分。但我后来发现，真正留下来的并非那张证书，更多是失败后怎么复盘，团队意见不一致时怎么推进，压力很大时怎么让大家还愿意继续相信彼此。这些能力也没那么容易被评分表捕捉，却更接近“真实地做事”。</p>\n<h3>大创：浅尝科研之路</h3>\n<img   src=\"https://img.markxu.icu/img20260614160854380.png\"   alt=\"大创logo\"   style=\"width: min(100%, 360px); height: auto; display: block; margin: 1.5rem auto;\" />\n<p><a href=\"https://github.com/MarkXuJQ/Pelvis-Fracture-Image-Segmentation\">大创项目</a>是学长推荐我做的，说可以学习到不少东西。我主动向我的本科生老师联系，并且找到了一个我和队友们都还算感兴趣的方向，确定了项目题目，开始了为期一年的科研经历。</p>\n<p>刚刚开始主要是一大堆的文书工作。我也是第一次把我们的项目申请书改了又改，多谢我的导师耐心教导，我在不断修改的过程中，也逐渐摸索出了与导师的联系方法（与初高中的老师是两种相处思路），也慢慢摸清楚一个标准的文档应该怎么去写。我在我大学两年的简单科研实践中，也十分感谢我的导师。</p>\n<p>说到团队合作，为期一年的项目以及 4 名同学作为队员，相较于数模比赛，难度又上升了许多。首先是确保同学们真的学习到了可以后续用到的知识，其次，是我作为组长，应该及时确定下来技术栈并安排好方向，组织线下活动让大家互相了解，确定责任划分以及进度的定期检查。这些我都没有做到。大家之间的交流也经常隔了一两周才能得到回复，让我们的项目推进远远落后于别的小组，那段时间也是我最焦虑的时间，既害怕结项不了耽误大家，也不想这么容易就认输。</p>\n<p>在中期答辩后，我开始阅读我们大一计算机导论老师推荐的《人月神话》，开始意识到自己的管理和沟通问题，并及时调整，好在最后真的顺利结项了。</p>\n<p>在大创期间，我也是第一次意识到了交流的重要性。在中期之前，一直由于自己进度慢不敢联系老师，怕被老师责备，后面才体会到老师的作用更偏向指引，而我也应该主动向老师报备交流。</p>\n<p>同时我之前提到过的同学们和我的关系不错，听我倒了不少苦水，他们也都默默的支持和安慰我，甚至主动和我出去散心，我都十分感激。</p>\n<p>大创最像一个可以被 Reward Hacking 的系统：像是结项材料、答辩、成果要求，有很多可操作的空间。大可以把它做成一套漂亮但空心的材料，也可以把它当成一次笨拙但真实的科研和协作训练。</p>\n<p>我并不敢说自己做得多好，甚至很多地方做得很差，但至少这段经历让我知道，真实项目光靠热情很难完成，它需要沟通、计划、责任分配，也需要在进度很糟糕的时候承认问题并重新组织，最后的结果远没有我在过程中学到的东西重要。</p>\n<blockquote>\n<p>虽然通过我的观察，也有不少同学的大创项目是所谓的“祖传项目”。我也亲眼看到在我前一届的某一项目结项答辩后，在我同届的大创中又成功立项了，且是同一批老师听完答辩又通过下一届的项目的。或许大家说大创水也是如此。但同时，我也在互联网上注意到了有许多和我一样，没有一开始拿到现有资源，仍然努力的同学们。不管是否有前提资源，还是推荐大家去试试，人真的会在做事的过程中成长许多。</p>\n</blockquote>\n<h2>租房：第一次独立生活</h2>\n<p>为了完成大创项目，我自己组装了一个电脑，而学校的四改六宿舍又不支持机箱的存在。并且我一旦需要完成项目，常常沉迷修 bug 忙到半夜三点到四点。为了不打扰室友，也为了有一个更专注的环境，我和家里说明情况，出来租房住了两年。离学校不远，但是独立的生活确实是我从来没有过的经历。</p>\n<p>在租房期间，办理各种手续，打扫收拾卫生，甚至终于有机会自己给自己做饭吃，都是很新奇的体验。</p>\n<div class=\"photo-scroll\">\n    <img src=\"https://img.markxu.icu/img8a5ffe6a937bf6209f6be61f55055631_720.jpg\" alt=\"租房环境\" />\n    <img src=\"https://img.markxu.icu/imga6b8f9e155aa93b80851e0c33adc3cd5_720.jpg\" alt=\"自己做的炒方便面\" />\n    <img src=\"https://img.markxu.icu/imgab9b3f561405b3cc78c74e9d2adec35d.jpg\" alt=\"炖番茄丸子\" />\n    <img src=\"https://img.markxu.icu/img18459215118775f8ddc9e793cbe58f66_720.jpg\" alt=\"蛋白粉饼干\" />\n</div>\n<p>这些经历很难被算进大学评价体系里。没有人会因为你学会做饭、交水电费、收拾房间、安排自己的作息而给你加分。但我越来越觉得，独立生活本身就是大学的一部分。它让我从一个被安排的人，慢慢变成一个需要自己维护生活秩序的人。</p>\n<p>成长不一定都发生在教室、实验室和竞赛场里，有些成长就发生在某个凌晨收拾完桌子，发现自己真的可以把生活一点点维持起来的时候。</p>\n<h2>没有绩点神话，也没有轻松自由</h2>\n<p>写到这里，如果只写好的方面，那就是自我辩护，像是想要强行给自己洗脑。</p>\n<p>坏的方面确实让我很受挫。由于没有追求绩点，最后的成绩落在了 3.97/5.00，与在我排名之前同学们的 4+ 绩点显得有些不够看。距离学校的保研名额就差 2 名，分数差也很小。如果把一些小课的成绩刷上来，或许我又可以多一年的时间去尝试些更大胆的事情。如果再来一遍的话，我也绝对会尝试更精妙地掌握些平衡，不要错失这个机会。尽管我也深刻意识到，如果时光倒退，我也依然会做出我当时的选择和决定。</p>\n<p>这也是我现在对“拒绝 Reward Hacking”更谨慎的原因。拒绝单一指标，不等价于无视规则；追求真实学习，也不等于可以不对结果负责。评价体系虽然有问题，但它也确实掌握着很多机会的入口，我的绩点虽然不算特别高，但我还算不错的排名和学习经历也确确实实给了我不少机会。我爸也经常和我说：</p>\n<blockquote>\n<p>一个人要了解规则，利用规则。如果完全不理解规则，就很容易在关键节点付出很高代价。</p>\n</blockquote>\n<p>所以我不想把这四年总结成“我不卷，所以我自由”，这种只抓眼球不负责的口号。更准确地说，是我在自由和机会之间、兴趣和指标之间、长期成长和短期门票之间，一直做着不太成熟的权衡。有些选择我现在仍然认可，有些选择则会在夜里想起时感到遗憾。</p>\n<p>我将这些遗憾也视作我现在的一部分。这些提醒我，真正好的生活策略不能只是简单反抗评价体系，为了反而反，而是要理解指标的力量，同时避免被指标完全支配，就像我高中的体会一样，要明白知识点，还要明白为什么考这个知识点。</p>\n<h2>优绩主义之外，还有什么？</h2>\n<p>这几件事情几乎概括完了我的大学时光：自学、健身、比赛、项目、租房，还有许多和朋友一起浪费掉又珍贵无比的时间。说起来很快，期间的每一个细节，遇到的挑战和好运气我都历历在目。火车也快到站了，我也快点结束。</p>\n<p>写完这篇，我仍然没有一个漂亮的答案。大学四年让我更深地理解了优绩主义的吸引力：它清晰、直接、可比较，能告诉你现在排在哪里，下一步该怎么努力。对于很多普通人来说，它又是一种相对公平的上升通道。</p>\n<p>但我也越来越怀疑，它能不能作为贯彻人生的最高目标。因为当一个人总是通过“比别人更优秀”来确认自己，就很难真正停下来问：我学到的东西是否让我更自由？我创造的内容是否真的有意义？我和他人的关系是否更真诚？我是否在理解更大的世界，还是只是在更小的排行榜里爬升？</p>\n<p>或许，人生需要一种比优绩主义更好的目标。</p>\n<p>它不应该否认努力，不应该轻视能力，不应该把懒散包装成清醒。但它应该比“赢过别人”更宽阔一些：能容纳真实的学习、具体的爱、对社会的理解、创造的快乐、身体的健康、与身边人共同生活的记忆，也能容纳那些没有被指标记录却确实让人成长的时刻。</p>\n",
      "summary": "离开学校的时候，我想记录大学四年的回忆，也想记录自己如何在一次次选择中，慢慢形成了拒绝把绩点、排名和简历当作唯一目标的价值观。",
      "date_published": "2026-06-14T00:00:00.000Z",
      "date_modified": "2026-06-17T00:00:00.000Z",
      "image": "https://img.markxu.icu/imgb8e606e4235578a4b05bc4b87ae8945f_720.jpg",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/blog/Amoy-food-walk-note1-cn",
      "url": "https://markxu.icu/blog/Amoy-food-walk-note1-cn",
      "title": "厦门逛吃日记",
      "content_text": "大学四年的时光过得飞快，当年大一刚刚进入宿舍和室友们第一次见面，互相打招呼的时光仿佛就在眼前。一瞬间，也要毕业了。 厦门这座城市很美丽，生活的也很舒服：温暖湿润的气候、干净有序的城建、富有特色的闽南建筑、各式各样的绿植、随处可见的三角梅和那广阔干净的海湾...所有的这些都让我感到珍惜和不舍，只可惜四年间没有太多时间和机会在厦门城里再仔细地去转一转。 为了弥补这个遗憾，在毕业临走之前，叫上了一位同学，再次出门去探一探店，去找一些富有特色和个人味道的小店，有惊喜也有失望。 所有图片都是手机拍的，也没有修过，大家理解下，哈哈。 PuKu-生甜甜圈专门店 营业时间：10:30-20:00 地址：集美区 集美大祠堂附近 价格：我们点的一个麻薯是 15￥ 本来是中午过来吃酸奶油咖喱的，结果店铺从14:30才开门，扑了个空，没办法只好转战下一家。回去的路上突然看见这家不起眼的小店，连个大点的招牌都没有，只是因为瞥见了路边的立牌上写的甜甜圈，我们就打算坐下看看。 小店环境很干净，几乎是极简的设计，主要都是木头家具，有一种简洁但温馨的感觉。很适合在阳光明媚的时候过来坐坐，拍两张照片。 话说“生活很苦，来点麻薯，大家好，我是…”咳咳，我们点了两个抹茶麻薯，一个话梅芭乐麻薯。 这麻薯的口感真的很好。内瓤极富弹性，外壳又酥脆。牙齿咬下去能感受到那种内部面筋撕扯的韧劲，但分寸拿捏得刚刚好，绝不会让人失态🥲。外壳也不会像普通点心那样掉渣，而是随着内部的牵扯自然碎裂，并附着在内瓤上，吃到嘴里，清晰可辨那种脆弹的质感。 馅料更是值得细说😋。大热天吃它，你会发现内馅是沁凉的，一种浓厚得像快要融化冰淇淋的质地，却不像冰块那样碜牙。抹茶味浓郁却没有常见的茶的涩感；话梅芭乐则更细腻些，透着熟透芭乐的清甜，里面还藏着微微的果碎，当舌头抵着上颚抿开时，那种丰富的层次感真的让人惊喜，只是话梅的味道我没怎么吃出来。 麻薯的甜味很淡，几乎全部来自馅料，且甜味是作为底味，衬托抹茶和果香的一种存在。哪怕馅料吃完了，嘴里留下的香气也足够让你享受完整个麻薯。 巷口红烧牛肉面 营业时间：11:00-14:00 17:00-21:00 地址： 思明区祥和广场1楼 退化公园 价格： 人均 45￥ 左右 吃完麻薯后，我们立刻动身，打的前往岛内，改吃这家牛肉面。门店很隐蔽，在一个很老的废旧商场下面，商场上的字也蛮有特色，一度以为世界出了bug。 小店环境仍然干净，但是多了些温馨的感觉，店铺不大，店内五六张双人桌，店外两张，一共七八张桌子。小店主打的就是一个精致。 上菜很快，点完大概七八分钟，面就端上来了。我们要了两份红烧牛肉面，39元一份。菜单上标着微辣，但实际一点辣味都没有，倒是很合我这“不能吃辣星人”的胃口。 面是配着一小碟小菜上的，那是店家自家用醋和小米辣腌的卷心菜，吃起来爽口又脆生。面碗看着不大，其实挺深，我们俩吃分量刚好。（加面要钱，但是量足够的） 汤头很足，主打一个咸鲜，细品能尝出一丝甜味和若有若无的酸辣，就是很正宗的红烧牛肉面味儿。面条爽滑劲道，很有韧性，关键是能挂住汤，不会吃起来面是面、汤是汤。面里还铺着烫软的生菜和一个卤溏心蛋。 当然，重头戏还得是这家的牛肉。正如墙上宣传写的“本店只选新鲜黄牛”，牛肉味儿特别浓，而且块头很大。炖得火候极到位，纤维都酥软了，完全不塞牙，也足够入味。最好吃的是肉中间那块软软糯糯的地方，（大概是牛腱芯？不太确定）那是口感的升级，给原本略显偏瘦偏柴的部位做了个缓冲，里面的胶质网甚至能在嘴里直接抿开。 野草莓自由市场 营业时间：11:00-20:00 地址：思明区鹭江道176号 价格：主食体感平均40，甜品体感平均30 吃完牛肉面后，我们两个撑的不行，没有变身成为 David Day 大胃袋 , 于是我们在公园转了转，一直到下午3点左右，我们来到了我们班同学常来的野草莓。其位置就在第一码头附近，这里有着双子塔，出门向西走不到200m就是中山路，有条件的话，旅游的同学们也可来看看。 这个店面不算小，整整两层，面积也算大，但是店主营造了一种特别的氛围，每一张桌子，每一把椅子，甚至每一个摆饰都是不一样的，看起来满满当当，像是店主从二手市场淘来的展品会。很有店主的特色风格。 菜单上的菜单很全面，从主食到甜品都有，我们实在是吃不下，没有点主食，各自点了个甜品，量也超乎我们的想象。 开心果gelato的口感很正常，是一个正宗gelato冰激凌的味道，空气感不强，不会在嘴里一含就化没，主要是以开心果的风味为主，少量开心果碎，少量的乳脂也让冰激淋吃起来更清爽，不油腻。 松露本质上是一个黑松露巧克力蛋糕，外卖有一层轻盈的奶油，上面洒满了巧克力粉。巧克力吃起来略微发苦，奶油发甜，掺起来吃达到了还算不错的平衡，即使我们吃了很多甜品，也没有觉得特别腻。只是黑松露的味道并不是特别明显，确实会有黑松露油后的留香感。 椰子舒芙蕾是让我感到比较惊艳的一个。最近舒芙蕾貌似在网上卷起来一场新潮，平地冒出来好多舒芙蕾的小店。这家舒芙蕾没有工厂质感，甚至凝固的都没有特别完全，我们用叉子叉开，喷向鼻腔的是一股淡淡的温暖的鸡蛋腥味。吃起来没有充满改良剂的空气感，而是弹软充实的感受，蘸着盘子旁边的咸奶油，吃起来解腻。还有酸酸的芒果和微微甜的椰子块。（杨梅没敢吃） 可可主角：厦门巧克力博物馆 营业时间：10:00-23:00 地址：思明区中山路步行街与泰山路路口交叉口西20米 价格：免费 这不会是最长见识的博物馆，也不会是最好看的博物馆，但很有可能是你去过最好闻的博物馆。 博物馆不大，一共两层楼，里面列满了使用巧克力做的各种雕塑，从小巧精致的，到大而震撼的都有，也贴心的贴上了价格标签，告诉你弄坏了要赔偿多少😂。一路上会有店员不断投喂你小零食，虽然不是一个专门值得来的地方，但是在中山路上，且离野草莓不远，可以顺路过来看看。 土头水吧（不推荐） 营业时间：14:30-20:30 地址：集美学村 集美大祠堂附近 价格：人均80 我们在一天的最后时刻，又回到了我们一开始打算吃的酸奶油咖喱。所以我们又转回来，来到了这家小店。 小店很小，在一个巷子里，不刻意寻找的话，肯定会错过。一共就四五张桌子，装修是比较经典的网红小众店，充满了不是很有特色的个性。老板服务很细心，会帮我找一个收纳筐随手把我的书包放进收纳筐然后推到我的身边，但是菜品的味道确实没有很让我满意，至少对不太起这个价格。 我们点了一个酸奶油鸡肉咖喱45￥，还有一个记不清名字，说是老板妈妈自己做的辣酱的意面 55￥，还有凤梨冰沙和甜奶冰沙各30￥。 先说冰沙，我要的是凤梨冰沙，味道就是很普通的凤梨速溶饮料，冲的淡些，然后用冰沙机做出来的感觉，没有很有特色，也没有什么好特别说的。 再说咖喱，这个菜是好吃的。但是作为招牌，风味和特色都不明显。咖喱味道是偏淡的，有切碎并碾压后的鸡肉块和随机大小的炖的很是软烂的土豆块，土豆块炖的几乎融入咖喱汤了，很适合拌着米饭吃；碎肉也有颗粒感且充满整个汤汁，鸡肉不柴（应该是鸡腿肉）。但是酸奶油的口感偏淡，并没有给这道菜添加多么独特的风味，完全可以花一半多一点的钱吃到同等品质的咖喱饭。米饭也是一大扣分点，没有米香味，也没有很充足的水份，吃起来平平无奇，可能是来到的比较晚，咖喱汤本来就有点凉，米饭也失去了水份。 最后是意面，我们开始是想点青酱意面的，但是出现了经典的主理人剧情：“你们之前吃过青酱吗？没有的话不是很推荐新手来吃，大多数都不会喜欢，我更推荐这个。”于是端上来的是老板推荐的。菜单上写的是手作意面，但从照片也可以看出来，明显不是手作意面，如果是手作的话，且不说形状有更合适酱汁的形状，鸡蛋和水份的配比也应该让意面更为劲道，而不是这种和超市里购买的一样。再说酱汁，有辣无香，吃饭都是一热顶三鲜，这个酱汁端上来确实有点索然无味，没有很深的记忆点。且不说价格贵，分量也不足以喂饱一个人。 最后放下旅程中的其他照片： 也给我的大学时光贴一张超速罚单吧！",
      "content_html": "<p>大学四年的时光过得飞快，当年大一刚刚进入宿舍和室友们第一次见面，互相打招呼的时光仿佛就在眼前。一瞬间，也要毕业了。</p>\n<p>厦门这座城市很美丽，生活的也很舒服：温暖湿润的气候、干净有序的城建、富有特色的闽南建筑、各式各样的绿植、随处可见的三角梅和那广阔干净的海湾...所有的这些都让我感到珍惜和不舍，只可惜四年间没有太多时间和机会在厦门城里再仔细地去转一转。</p>\n<p>为了弥补这个遗憾，在毕业临走之前，叫上了一位同学，再次出门去探一探店，去找一些富有特色和个人味道的小店，有惊喜也有失望。</p>\n<blockquote>\n<p>所有图片都是手机拍的，也没有修过，大家理解下，哈哈。</p>\n</blockquote>\n<h2>PuKu-生甜甜圈专门店</h2>\n<p>营业时间：10:30-20:00</p>\n<p>地址：集美区 集美大祠堂附近</p>\n<p>价格：我们点的一个麻薯是 15￥</p>\n<div class=\"photo-scroll\">\n  <img src=\"https://img.markxu.icu/img58f5cb7a0b3f1be094f1f95f35aa5b31.png\" alt=\"店铺门面\" />\n  <img src=\"https://img.markxu.icu/imgd15c3a7b56db1c7a96d1cc2b875c1821.png\" alt=\"麻薯\" />\n  <img src=\"https://img.markxu.icu/imgc2892ed8360fbc2529e909bab9d7705c.png\" alt=\"抹茶麻薯\" />\n  <img src=\"https://img.markxu.icu/img2547117f7870a557842c500371dc648e.png\" alt=\"话梅芭乐\" />\n  <img src=\"https://img.markxu.icu/imged40a5151fb57c4bffd74e0718716672.png\" alt=\"店铺环境\" />\n  <img src=\"https://img.markxu.icu/imgaa03b8055f8c200b1bab97a0bef95b44.png\" alt=\"店铺环境\" />\n</div>\n<p>本来是中午过来吃酸奶油咖喱的，结果店铺从14:30才开门，扑了个空，没办法只好转战下一家。回去的路上突然看见这家不起眼的小店，连个大点的招牌都没有，只是因为瞥见了路边的立牌上写的甜甜圈，我们就打算坐下看看。</p>\n<p>小店环境很干净，几乎是极简的设计，主要都是木头家具，有一种简洁但温馨的感觉。很适合在阳光明媚的时候过来坐坐，拍两张照片。</p>\n<p>话说“生活很苦，来点麻薯，大家好，我是…”咳咳，我们点了两个抹茶麻薯，一个话梅芭乐麻薯。</p>\n<p>这麻薯的口感真的很好。内瓤极富弹性，外壳又酥脆。牙齿咬下去能感受到那种内部面筋撕扯的韧劲，但分寸拿捏得刚刚好，绝不会让人失态🥲。外壳也不会像普通点心那样掉渣，而是随着内部的牵扯自然碎裂，并附着在内瓤上，吃到嘴里，清晰可辨那种脆弹的质感。</p>\n<p>馅料更是值得细说😋。大热天吃它，你会发现内馅是沁凉的，一种浓厚得像快要融化冰淇淋的质地，却不像冰块那样碜牙。抹茶味浓郁却没有常见的茶的涩感；话梅芭乐则更细腻些，透着熟透芭乐的清甜，里面还藏着微微的果碎，当舌头抵着上颚抿开时，那种丰富的层次感真的让人惊喜，只是话梅的味道我没怎么吃出来。</p>\n<p>麻薯的甜味很淡，几乎全部来自馅料，且甜味是作为底味，衬托抹茶和果香的一种存在。哪怕馅料吃完了，嘴里留下的香气也足够让你享受完整个麻薯。</p>\n<h2>巷口红烧牛肉面</h2>\n<p>营业时间：11:00-14:00 17:00-21:00</p>\n<p>地址： 思明区祥和广场1楼 退化公园</p>\n<p>价格： 人均 45￥ 左右</p>\n<div class=\"photo-scroll\">\n  <img src=\"https://img.markxu.icu/img70adb0dffff60c301974ed0161db6ece.png\" alt=\"店铺门面\" />\n  <img src=\"https://img.markxu.icu/img9836b25c5e83160778f4511c9c468349.png\" alt=\"店面环境\" />\n  <img src=\"https://img.markxu.icu/img1464c45b9c69648dee239b4d03b295ca.png\" alt=\"店面环境\" />\n  <img src=\"https://img.markxu.icu/imge7aae59d9657d5a40d014b77c76546a2.png\" alt=\"红烧牛肉面\" />\n  <img src=\"https://img.markxu.icu/img20260603000920074.png\" alt=\"红烧牛肉面\" />\n</div>\n<p>吃完麻薯后，我们立刻动身，打的前往岛内，改吃这家牛肉面。门店很隐蔽，在一个很老的废旧商场下面，商场上的字也蛮有特色，一度以为世界出了bug。</p>\n<p><img src=\"https://img.markxu.icu/img20260603001315979.png\" alt=\"就在这个商场右手边的入口处\"></p>\n<p>小店环境仍然干净，但是多了些温馨的感觉，店铺不大，店内五六张双人桌，店外两张，一共七八张桌子。小店主打的就是一个精致。</p>\n<p>上菜很快，点完大概七八分钟，面就端上来了。我们要了两份红烧牛肉面，39元一份。菜单上标着微辣，但实际一点辣味都没有，倒是很合我这“不能吃辣星人”的胃口。</p>\n<p>面是配着一小碟小菜上的，那是店家自家用醋和小米辣腌的卷心菜，吃起来爽口又脆生。面碗看着不大，其实挺深，我们俩吃分量刚好。（加面要钱，但是量足够的）</p>\n<p>汤头很足，主打一个咸鲜，细品能尝出一丝甜味和若有若无的酸辣，就是很正宗的红烧牛肉面味儿。面条爽滑劲道，很有韧性，关键是能挂住汤，不会吃起来面是面、汤是汤。面里还铺着烫软的生菜和一个卤溏心蛋。</p>\n<p>当然，重头戏还得是这家的牛肉。正如墙上宣传写的“本店只选新鲜黄牛”，牛肉味儿特别浓，而且块头很大。炖得火候极到位，纤维都酥软了，完全不塞牙，也足够入味。最好吃的是肉中间那块软软糯糯的地方，（大概是牛腱芯？不太确定）那是口感的升级，给原本略显偏瘦偏柴的部位做了个缓冲，里面的胶质网甚至能在嘴里直接抿开。</p>\n<h2>野草莓自由市场</h2>\n<p>营业时间：11:00-20:00</p>\n<p>地址：思明区鹭江道176号</p>\n<p>价格：主食体感平均40，甜品体感平均30</p>\n<div class=\"photo-scroll\">\n  <img src=\"https://img.markxu.icu/img20260603004114559.png\" alt=\"店铺门面\" />\n  <img src=\"https://img.markxu.icu/img20260603005149021.png\" alt=\"一楼环境\" />\n  <img src=\"https://img.markxu.icu/img9cbbcefce4c740db1ab7099ac0187734.png\" alt=\"二楼环境\" />\n  <img src=\"https://img.markxu.icu/imgb8a4fbc9460e559666e5136536fc5ee3.png\" alt=\"二楼环境\" />\n  <img src=\"https://img.markxu.icu/img3797e81b82eeeb75f991ea85d1f8e151.png\" alt=\"二楼环境\" />\n  <img src=\"https://img.markxu.icu/imgb7d3ab1d77ff01a5432bf12b1dc2b09a.png\" alt=\"二楼环境\" />\n  <img src=\"https://img.markxu.icu/img20260603005151612.png\" alt=\"二楼洗手间\" />\n  <img src=\"https://img.markxu.icu/img7cf4f4f2a2270538a3b10f2eb2a13a46.png\" alt=\"喝到了心心念念的黄瓜水\" />\n</div>\n<p>吃完牛肉面后，我们两个撑的不行，没有变身成为 David Day (大胃袋), 于是我们在公园转了转，一直到下午3点左右，我们来到了我们班同学常来的野草莓。其位置就在第一码头附近，这里有着双子塔，出门向西走不到200m就是中山路，有条件的话，旅游的同学们也可来看看。</p>\n<p>这个店面不算小，整整两层，面积也算大，但是店主营造了一种特别的氛围，每一张桌子，每一把椅子，甚至每一个摆饰都是不一样的，看起来满满当当，像是店主从二手市场淘来的展品会。很有店主的特色风格。</p>\n<div class=\"photo-scroll-vertical\">\n  <img src=\"https://img.markxu.icu/img20260603005418459.png\" alt=\"菜单1\" />\n  <img src=\"https://img.markxu.icu/img20260603005421759.png\" alt=\"菜单2\" />\n  <img src=\"https://img.markxu.icu/img20260603005424537.png\" alt=\"菜单3\" />\n  <img src=\"https://img.markxu.icu/img20260603005427148.png\" alt=\"菜单4\" />\n</div>\n<div class=\"photo-scroll\">\n  <img src=\"https://img.markxu.icu/img3b095270f69fdb5bedb37c42c7900dbe.png\" alt=\"开心果gelato\" />\n  <img src=\"https://img.markxu.icu/imgf69eb875161225768b94de2d46c9b80b.png\" alt=\"松露\" />\n  <img src=\"https://img.markxu.icu/imgff6fdca35317f25aac77d3515a27a379.png\" alt=\"松露内瓤\" />\n  <img src=\"https://img.markxu.icu/img20260602232937241.png\" alt=\"椰子舒芙蕾\" />\n  <img src=\"https://img.markxu.icu/imgc984cb0c70751d7ca0e4dd20f48bfc7b.png\" alt=\"椰子舒芙蕾\" />\n</div>\n<p>菜单上的菜单很全面，从主食到甜品都有，我们实在是吃不下，没有点主食，各自点了个甜品，量也超乎我们的想象。</p>\n<p>开心果gelato的口感很正常，是一个正宗gelato冰激凌的味道，空气感不强，不会在嘴里一含就化没，主要是以开心果的风味为主，少量开心果碎，少量的乳脂也让冰激淋吃起来更清爽，不油腻。</p>\n<p>松露本质上是一个黑松露巧克力蛋糕，外卖有一层轻盈的奶油，上面洒满了巧克力粉。巧克力吃起来略微发苦，奶油发甜，掺起来吃达到了还算不错的平衡，即使我们吃了很多甜品，也没有觉得特别腻。只是黑松露的味道并不是特别明显，确实会有黑松露油后的留香感。</p>\n<p>椰子舒芙蕾是让我感到比较惊艳的一个。最近舒芙蕾貌似在网上卷起来一场新潮，平地冒出来好多舒芙蕾的小店。这家舒芙蕾没有工厂质感，甚至凝固的都没有特别完全，我们用叉子叉开，喷向鼻腔的是一股淡淡的温暖的鸡蛋腥味。吃起来没有充满改良剂的空气感，而是弹软充实的感受，蘸着盘子旁边的咸奶油，吃起来解腻。还有酸酸的芒果和微微甜的椰子块。（杨梅没敢吃）</p>\n<h2>可可主角：厦门巧克力博物馆</h2>\n<p>营业时间：10:00-23:00</p>\n<p>地址：思明区中山路步行街与泰山路路口交叉口西20米</p>\n<p>价格：免费</p>\n<div class=\"photo-scroll\">\n  <img src=\"https://img.markxu.icu/img20260603011421693.png\" alt=\"巧克力双子塔\" />\n  <img src=\"https://img.markxu.icu/img20260603011424344.png\" alt=\"巧克力厦大\" />\n  <img src=\"https://img.markxu.icu/img20260603011426639.png\" alt=\"巧克力管风琴\" />\n  <img src=\"https://img.markxu.icu/img20260603011429410.png\" alt=\"巧克力郑成功\" />\n</div>\n<p>这不会是最长见识的博物馆，也不会是最好看的博物馆，但很有可能是你去过最好闻的博物馆。</p>\n<p>博物馆不大，一共两层楼，里面列满了使用巧克力做的各种雕塑，从小巧精致的，到大而震撼的都有，也贴心的贴上了价格标签，告诉你弄坏了要赔偿多少😂。一路上会有店员不断投喂你小零食，虽然不是一个专门值得来的地方，但是在中山路上，且离野草莓不远，可以顺路过来看看。</p>\n<h2>土头水吧（不推荐）</h2>\n<p>营业时间：14:30-20:30</p>\n<p>地址：集美学村 集美大祠堂附近</p>\n<p>价格：人均80</p>\n<div class=\"photo-scroll\">\n  <img src=\"https://img.markxu.icu/imgc1bfd7747db5d8cae090fb9e23d3583b.png\" alt=\"店面环境\" />\n  <img src=\"https://img.markxu.icu/img9173ba87266c98c6709241997dd3d7e6.png\" alt=\"店面环境\" />\n  <img src=\"https://img.markxu.icu/img01666273752a4da625dd8a43ca652a43.png\" alt=\"同学拍的晚餐\" />\n</div>\n<p>我们在一天的最后时刻，又回到了我们一开始打算吃的酸奶油咖喱。所以我们又转回来，来到了这家小店。</p>\n<p>小店很小，在一个巷子里，不刻意寻找的话，肯定会错过。一共就四五张桌子，装修是比较经典的网红小众店，充满了不是很有特色的个性。老板服务很细心，会帮我找一个收纳筐随手把我的书包放进收纳筐然后推到我的身边，但是菜品的味道确实没有很让我满意，至少对不太起这个价格。</p>\n<p>我们点了一个酸奶油鸡肉咖喱45￥，还有一个记不清名字，说是老板妈妈自己做的辣酱的意面 55￥，还有凤梨冰沙和甜奶冰沙各30￥。</p>\n<p>先说冰沙，我要的是凤梨冰沙，味道就是很普通的凤梨速溶饮料，冲的淡些，然后用冰沙机做出来的感觉，没有很有特色，也没有什么好特别说的。</p>\n<p>再说咖喱，这个菜是好吃的。但是作为招牌，风味和特色都不明显。咖喱味道是偏淡的，有切碎并碾压后的鸡肉块和随机大小的炖的很是软烂的土豆块，土豆块炖的几乎融入咖喱汤了，很适合拌着米饭吃；碎肉也有颗粒感且充满整个汤汁，鸡肉不柴（应该是鸡腿肉）。但是酸奶油的口感偏淡，并没有给这道菜添加多么独特的风味，完全可以花一半多一点的钱吃到同等品质的咖喱饭。米饭也是一大扣分点，没有米香味，也没有很充足的水份，吃起来平平无奇，可能是来到的比较晚，咖喱汤本来就有点凉，米饭也失去了水份。</p>\n<p>最后是意面，我们开始是想点青酱意面的，但是出现了经典的主理人剧情：“你们之前吃过青酱吗？没有的话不是很推荐新手来吃，大多数都不会喜欢，我更推荐这个。”于是端上来的是老板推荐的。菜单上写的是手作意面，但从照片也可以看出来，明显不是手作意面，如果是手作的话，且不说形状有更合适酱汁的形状，鸡蛋和水份的配比也应该让意面更为劲道，而不是这种和超市里购买的一样。再说酱汁，有辣无香，吃饭都是一热顶三鲜，这个酱汁端上来确实有点索然无味，没有很深的记忆点。且不说价格贵，分量也不足以喂饱一个人。</p>\n<p>最后放下旅程中的其他照片：</p>\n<div class=\"img-grid-2\">\n  <img src=\"https://img.markxu.icu/img541775d2fe5dc898c3d7f02a6b631784.png\" alt=\"夜间集美学村\" />\n  <img src=\"https://img.markxu.icu/imgfc52cce5512cb72afde54fe996e0f758.png\" alt=\"中山路的某处街道\" />\n</div>\n<p><img src=\"https://img.markxu.icu/imga45f872aac1ea98ec36e4d83f4332849.png\" alt=\"Someone give summer a speeding ticket\"></p>\n<p>也给我的大学时光贴一张超速罚单吧！</p>\n",
      "summary": "还有几天就要毕业了，对厦门这座城市很是不舍，于是在网上看了几家好吃的店，和同学出门去探一探店，途中也发现了惊喜，当然也有失望。",
      "date_published": "2026-06-02T00:00:00.000Z",
      "image": "https://img.markxu.icu/img20260602232937241.png",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/blog/what-do-computer-science-majors-learn-cn",
      "url": "https://markxu.icu/blog/what-do-computer-science-majors-learn-cn",
      "title": "计算机都学些什么？",
      "content_text": "之前和家里长辈聊天，或者给一些准备高考选专业的学弟学妹介绍专业时，经常会被问到一个问题： 你们计算机专业到底都在学些什么？ 这个问题看起来很简单，但真要回答的清楚并不容易。 因为“计算机”这个词在生活里太宽泛了，而对于科技有些许了解的人来说，方向也特别多，如果没有亲身学习过这个专业，还是会有不少误解。 有人觉得学计算机就是写代码，有人觉得是修电脑、装系统，也有人觉得是做游戏、做网站、搞人工智能。它们都和计算机有关，但都是这个专业的一个方向，与我们本科教育里面的“计算机”关系并不大。 本科的“计算机科学与技术”主要是一套围绕“如何让机器可靠、高效、自动地处理信息”的完整体系。从数学开始奠定逻辑基础、将一切用代码表达清楚，最重要的还是背后的 抽象、系统、工程和问题拆解能力。 所以我想写一个简单的说明书。以后如果有人问我“计算机都学些什么？”，我就可以直接把这篇文章发过去，好过每次都从头讲一遍，还讲的不够清晰全面。 当然，不同层次的学校的培养方案会有差异，我也没有亲身体会过顶尖学府的计算机课程，不过好在Berkeley、MIT都有很多公开课，我也通过这些公开课一窥顶尖学府的教育理念和思想。下面写的主要是以我的学校——一个普通一本大学，国内大部分“计算机科学与技术”本科培养方案里比较常见的内容，加上我通过公开课了解到的东西。 先说一个误区：计算机不是“学会某个软件” 很多人对计算机专业的第一印象，是会不会修电脑、会不会装系统、会不会做 PPT、会不会剪视频。 这些当然都是有用的技能，但并不是计算机专业的核心内容。不然学机械是为了会拧螺丝，学建筑是为了会搬砖，学食品是为了给趣多多点巧克力豆。 本科教育里的计算机专业，主要关心的是： 一个程序为什么能运行？ 程序里面的数据是怎么被组织和处理的？ 网络怎么把信息从一个地方送到另一个地方？ 操作系统为什么能同时运行很多软件？ 一个大型系统如何被设计、开发、测试和维护？ 算法如何在时间和资源利用最小的情况下解决问题？ 接下来我也会从人工智能、数据库、图形学、网络安全、嵌入式这些主流方向，探讨下我这几年对这些方向的理解，以及他们分别在解决什么问题？ 现在让我们自底向上的一层一层解决计算机的思路来源、我们的学习目标、以及我在学习过程中遇到的问题和走过的弯路。 第一层：数学基础 刚进大学时，很多同学会惊讶：“为什么我报的是计算机，结果一上来要学这么多数学？” 大一时候我们也凑在一起吐槽这一件事，但学到后面才发现数学原来并不只是小中高的代数，那些叫做初等数学，本科学的是更广且更深的数学，且基础也确实十分重要。 高等数学、线性代数、概率论与数理统计、离散数学，这些基本都是绕不开的课程。甚至有的学校还会学数值分析、组合数学、运筹学之类的内容。 高等数学主要针对的是连续变化、微分积分的思想；线性代数在图形学、机器学习、数据处理里非常常见；概率统计是人工智能、数据分析、随机过程的基础；而离散数学则和计算机关系尤其紧密，集合、逻辑、图、树、关系、递归，这些东西听起来像数学概念，但后面会不断出现在数据结构、算法、数据库、编译原理、人工智能里。 我就是当初的离散数学学的比较认真，后面会有一种触类旁通的感觉。 当然，也不用因此被吓到。对于普通学生来说，如果不想继续在技术前沿去苦苦探索， 数学其实没有必要抓的特别狠 ，即使后续忘得差不多了，也不会影响找工作或者简单的前后端编程问题。大部分本科阶段的数学课，只是培养一个思维，在后面遇到复杂概念时，不至于完全没有抓手。 现在遇到的问题： 而我在大学四年里面， 如果只是按部就班的上学校的课程的话，多半不会对数学有多么深的理解。 学校的课程为了方便量化考核，不会考你的数学理解和思维思想，而是主要抓你的做题能力。 这一点我认为是学校教育考核的问题。举一个最好体现的例子，我身边几乎每一个同学对线性代数的理解都是计算行列式，矩阵乘法，求特征向量... 而没有一个是从线性代数上几何的意义去考虑，给我的感觉是我们过于注重线性代数后面的“代数”部分，而忽略了“线性”的概念，导致 大部分同学即使学了人工智能或者图形学的知识，也不理解里面为什么要有矩阵 （后面有机会我再单独整理一篇文章） 。 而通过自学了解了 Gilbert Strang教授的 18.06课程，以及3B1B的动画讲解，才从其基本上去了解了数学的概念和意义。 第二层：编程基础 学计算机的一定要会编程👋😭👋！ 常见的入门语言可能是 C、C++、Python，不同学校选择不同。大部分学校一开始强调 C 语言，因为它更接近底层 （几乎可以说是万物起源） ，可以帮助理解内存、指针、数组、函数调用这些基础概念，在掌握后，对其他语言的学习会快很多（这里强烈推荐下CS 50）。有些学校会用 Python 或 Java 入门，因为更容易写出能运行的东西，降低初学门槛。 刚开始学编程时，内容通常包括变量、条件判断、循环、函数、数组、结构体、类和对象、文件读写这些内容。看起来就像是在学语言语法，但本质上是在 训练如何把一个现实问题拆成机器可以执行的步骤。 很多人以为写代码难在记住语法，实际上语法只是最表层的东西。真正难的是理解问题、拆分问题、设计流程、处理边界情况。 简单举个例子：写一个程序用来统计一组成绩的平均分。 这看起来很简单；但如果数据为空怎么办？如果输入格式错误怎么办？如果成绩太多，内存放不下怎么办？如果要在网页上实时展示又该怎么办？一个问题，一层一层往下挖，找准需求并采用基本的变量、逻辑就会逐渐从“写几行代码的小功能”变成“设计一个完整系统”。 编程基础课的意义不是是教你某门语言，而是第一次习惯用程序的方式组织思路。 遇到的问题： 1.考核带来的问题： 现在计算机课程的老师大多数是在念ppt，然后布置作业，写作业报告的考核方式为主。现在AI技术起来后，大部分的思维训练都可以通过直接给ai发要求来解决，几乎不用动脑。我身边追求绩点的同学，也为了拿到老师的高分，选择更为稳妥的解决思路，避免犯错，也会直接使用AI完成主要工作，把更多的精力放在完善工作报告上。导致我身边有很多编程几乎不通，但是文档能力较强的同学。 2.课程的设置问题： 我在这些基础课程的拿到的作业要求质量与 Berkeley的作业要求在难度上有着明显区别。我们最后完成的内容在难度上达到 Berkeley 的课后作业的大概期中前的水平，很难深入的通过一个项目让学术把问题拆的清楚，拆的明白。 而且我有一个很明显且强烈的感觉：教我们课程的老师大多是受制于课时要求来上的，其并不真懂得这门语言。比如C++的老师对指针的运用仅停留在基础用法，python老师对python的基础库的知识仅局限于课程ppt里的那些，更不用说上课会有尝试写代码运行不通，解释说写的是伪代码的闹剧。 这几个问题导致同学们的编程基础从从根本上就不是深入的、成体系的，所以后续甚至需要再去上一个语言编程班来加强。 第三层：数据结构与算法 如果只能选一门最能代表计算机专业基本功的课，我大概会选数据结构与算法。 数据结构研究的是数据怎么放，算法研究的是问题怎么解。 数组、链表、栈、队列、树、图、哈希表、堆，这些都是常见的数据结构。 排序、查找、递归、动态规划、贪心、图算法，这些则是常见的算法思想。 这门课一开始最让我感到痛苦，因为它不像写一个网页那样马上能看到结果，也不像做一个小软件那样有明确界面，有很及时的正反馈。它就像是在练内功，很多东西看着很好理解，很容易掌握，但大多数时间却是在不断失败中寻找出路。 数据结构和算法这两项构成了所有程序的底层。也常常会有用途一致，但是由于数据结构的不同产生了两种同生态位的优秀产品。 比如Notion 和 Obsidian 都用来“记笔记”，界面上同样支持页面、嵌套和链接，但底层的数据管理截然不同。Notion 把文档拆成 Block，用 树结构 管理层级与嵌套，一切操作本质上是子树的移动与折叠；Obsidian 则把每篇笔记当作 图中的一个节点 ，通过一个双向链接建立边，靠邻接表维护关联与反向索引。 简单来说，Notion 像是在整理一个多层文件夹，而 Obsidian 更像是在编织一张蜘蛛网，前者关心上下级，后者关心连接点。正因如此，同样是“整理笔记”，Notion 在思考“谁属于谁”，Obsidian 在思考“谁和谁有关”—— 数据结构并没有改变你能做什么，却决定了你是如何思考这件事的。 所以，数据结构与算法不是为了刷题而存在的。刷题只是训练方式之一，它真正训练的是： 面对问题时，如何选择合适的抽象和解决策略。 第四层：计算机整体系统 计算机专业和一些纯软件培训最大的不同，是它会要求你理解“代码下面发生了什么”。 这部分通常包括计算机组成原理、操作系统、计算机网络、数据库系统、编译原理等课程。 计算机组成原理 会告诉你，CPU、内存、指令、寄存器、缓存这些东西是怎么配合的。也就是屏幕上发生的一切，是如何通过二进制的0和1，在电子器件上进行变换，最后变成软件或者游戏的。 操作系统 会讲进程、线程、内存管理、文件系统、调度、死锁。你会理解为什么电脑可以同时开很多软件，为什么程序会卡死，为什么内存不够会变慢，为什么多线程写不好会出现奇怪 bug。 计算机网络 会讲 TCP/IP、HTTP、DNS、路由、拥塞控制。你每天打开网页、发消息、看视频，其实都在使用这些协议。学完之后，至少会知道“网络不好”不是一句万能解释，背后可能是延迟、丢包、带宽、DNS、服务器、客户端等一堆环节共同造成的。 数据库 会讲关系模型、SQL、索引、事务、并发控制、数据一致性。它解决的是数据怎么长期、可靠、有组织地存起来，并且在多人同时访问时尽量不出乱子。 编译原理 则会讲一门语言如何从源代码变成机器能执行的形式。词法分析、语法分析、语义分析、优化、代码生成，听起来很硬核，但它会让你理解编程语言不是凭空出现的，而是可以被设计和实现的系统。 （这门课确实很考验逻辑，难度不低） 这些课共同构成了计算机专业的系统底座。你不一定以后都直接做操作系统或编译器，但理解这些内容，会让你在面对复杂问题时更有“底层感”，如果学习的够深，甚至可以在面对奇怪bug时，找出底层方向，比如我在看这个帖子的问题描述到后期的时候，就猜到或许与历史原因导致的数字的浮点计算有关。 最后一层：专业方向课 到了大三、大四，很多学校会开设方向课或选修课。不同学校差异会比较明显，但常见方向大概有下面这些，也可以通过csdiy.wiki去寻找自己想要的课程 如果你很厉害的话，可以参考下作者的评价，对于我这种资质普通的学生来说，耗得时长比作者的高出不少，难度感觉要高一些，且学习完真不一定就记住了 。 人工智能与机器学习。 包括机器学习、深度学习、自然语言处理、计算机视觉、数据挖掘等内容。现在很热门，但真正学起来并不只是“调大模型”。你需要理解数据、模型、训练、评估、过拟合、损失函数、优化方法这些基本概念，还要学习pytorch等框架，刚刚上手确实令人兴奋，看到训练的时候损失在降，真得让人有种单纯的有点silly的高兴。 网络与信息安全。 包括密码学、网络安全、系统安全、Web 安全、逆向工程等内容。这个部分我几乎没有了解，只是有过一次机会采访过公安里面的网安人员和企业里的网安人员，浅浅的获得了部分知识。知道现在的市场对这方面的需求还在增加，但真要继续深入，就是网安这个专业的内容了。 嵌入式与物联网。 偏硬件和系统结合，可能会接触单片机、传感器、实时系统、嵌入式 Linux 等。它更关心程序如何在资源有限的设备上稳定运行。 软件开发与工程实践。 包括 Web 开发、移动开发、云计算、微服务、软件测试、DevOps 等。这个方向和实际就业联系很紧密，强调工程能力和系统开发经验。 大一的时候我们的院长（现在是副校）曾给我们上过《计算机导论》，他在课上推荐了《人月神话》这本书，我一看是上世纪70年代的书，还觉得院长真是个“老东西” （没有不尊敬的意思） 。一直到我组织大创，真的开发一个项目的时候，想起来老师的推荐，才发现自己踩得坑别人早在50年前就有了更好的解决思路。如果想要了解开发的过程，《人月神话》是一本没有门槛的贯彻开发全程的故事书。 图形学、游戏、虚拟现实。 会涉及几何、渲染、物理模拟、引擎、交互等内容。它看起来很酷，但背后有大量数学、算法和工程细节。我曾经学习过GAMES101，后续实在是没有时间，课程也有点点难，就放弃了。但是这不算短暂的接触也让我在玩游戏时，会很注重游戏引擎的渲染逻辑，也会时常看一些虚幻引擎的发布会，了解这炫酷的技术。其实图形学不仅仅是面对游戏引擎这一类的知识，背后的方向还有很多，后续再进行介绍吧。 大数据与数据库。 包括分布式系统、数据仓库、数据分析、推荐系统等内容。它处理的问题通常是数据规模大、并发高、系统复杂。大数据的内容我没有深入接触，不好做出有专业性的评价。 这些方向不是互相割裂的。比如人工智能需要算法和数学，也需要系统和工程；网络安全需要操作系统和网络基础；后端开发离不开数据库、网络和软件工程。 计算机专业的特点就是这样：越往后学，越会发现很多课程在互相连接。想要把上述的专业方向全部学明白，或者说全部学一遍，在我看来没有人可以做到，即使是专精一个方向，也需要以年来记的时光。我在大学四年的探索不算少，但后续的深入研究，大抵就是研究生的方向和目的了。 具体可以看这一篇知乎回答： 计算机本科生花大量时间写编译器，操作系统是不是不务正业？ - Freezy的回答 - 知乎 学计算机需要什么特质？ 我觉得最重要的不是“数学天才”，也不是“从小会写代码”。 更重要的是几种比较朴素但又少见的能力。 一是愿意自己查资料。计算机领域变化很快，很多问题不会再有老师一步一步带你解决，甚至好多同学也没有时间手把手教你。报错信息、官方文档、搜索引擎、开源项目、论文、社区讨论，都会成为你学习的一部分，这个能力即使在现在的ai时代，也显得尤为重要。 二是能忍受挫败感。程序报错是家常便饭，环境配不起来也很正常。我曾经配环境配了3天才成功跑通，一个bug修了一周，天天熬夜。可能是我菜，但据论坛上的经历，貌似并不少见。 三是喜欢拆问题。计算机很少直接解决一个巨大问题，而是不断把问题拆小，把模糊需求变成明确步骤，把复杂系统拆成模块，这种思维一旦形成，即使是在浏览网页，也会尝试不自觉地去抽象里面的数据结构。 （其实蛮像高中物理里的受力分析） 四是有一点持续学习的耐心。你可能刚学会一个框架，新的工具又出来了；刚理解一个方向，行业热点又变了。计算机专业不太适合只靠大学四年吃一辈子老本，更何况现在的ai时代来临，老本可能直接清零，保持学习或许是我们普通人唯一能与之抗衡的方法。 最后 计算机科学与技术专业学的东西很多，也很杂。 它既有数学，也有工程；既有理论，也有实践；既要理解底层系统，也要能做出上层应用。刚开始学的时候，很容易觉得这些课彼此之间没什么关系：数学是数学，C 语言是 C 语言，操作系统是操作系统，数据库是数据库。但学到后面会慢慢发现，它们其实都在回答同一个问题： 如何让信息被更好地表示、存储、传输、处理和使用？ 这篇文章是一个很粗略的介绍，主要作为我大学四年来，一直学习的心得体会，以及我感受到问题和最真诚的建议。虽然一个对未来充满迷茫的普通双非大学生的学习体验不能覆盖全面，但至少希望它能帮助家长和对计算机感兴趣的同学建立一个基本印象：计算机不是大段的数学，也不是简单敲代码。而是去理解计算机底层的方方面面。 如果你真的选择去学习它，后面大概率会遇到很多让人头疼的 bug、看不懂的课、配不好的环境、做不完的项目。 但也会有一些很开心的时刻：程序第一次跑通，网页第一次上线，模型第一次出结果，自己写的小工具真的帮到了别人。那些瞬间会让你觉得，自己确实在一点点把脑子里的想法变成现实。 这些微不足道的小确幸和正反馈，大概就是计算机专业最吸引我的地方。",
      "content_html": "<p>之前和家里长辈聊天，或者给一些准备高考选专业的学弟学妹介绍专业时，经常会被问到一个问题：<strong>你们计算机专业到底都在学些什么？</strong></p>\n<p>这个问题看起来很简单，但真要回答的清楚并不容易。</p>\n<p>因为“计算机”这个词在生活里太宽泛了，而对于科技有些许了解的人来说，方向也特别多，如果没有亲身学习过这个专业，还是会有不少误解。</p>\n<p>有人觉得学计算机就是写代码，有人觉得是修电脑、装系统，也有人觉得是做游戏、做网站、搞人工智能。它们都和计算机有关，但都是这个专业的一个方向，与我们本科教育里面的“计算机”关系并不大。</p>\n<p>本科的“计算机科学与技术”主要是一套围绕“如何让机器可靠、高效、自动地处理信息”的完整体系。从数学开始奠定逻辑基础、将一切用代码表达清楚，最重要的还是背后的<strong>抽象、系统、工程和问题拆解能力。</strong></p>\n<p>所以我想写一个简单的说明书。以后如果有人问我“计算机都学些什么？”，我就可以直接把这篇文章发过去，好过每次都从头讲一遍，还讲的不够清晰全面。</p>\n<p>当然，不同层次的学校的培养方案会有差异，我也没有亲身体会过顶尖学府的计算机课程，不过好在Berkeley、MIT都有很多公开课，我也通过这些公开课一窥顶尖学府的教育理念和思想。下面写的主要是以我的学校——一个普通一本大学，国内大部分“计算机科学与技术”本科培养方案里比较常见的内容，加上我通过公开课了解到的东西。</p>\n<hr>\n<h3>先说一个误区：计算机不是“学会某个软件”</h3>\n<p>很多人对计算机专业的第一印象，是会不会修电脑、会不会装系统、会不会做 PPT、会不会剪视频。</p>\n<p>这些当然都是有用的技能，但并不是计算机专业的核心内容。不然学机械是为了会拧螺丝，学建筑是为了会搬砖，学食品是为了给趣多多点巧克力豆。</p>\n<p>本科教育里的计算机专业，主要关心的是：</p>\n<ul>\n<li>一个程序为什么能运行？</li>\n<li>程序里面的数据是怎么被组织和处理的？</li>\n<li>网络怎么把信息从一个地方送到另一个地方？</li>\n<li>操作系统为什么能同时运行很多软件？</li>\n<li>一个大型系统如何被设计、开发、测试和维护？</li>\n<li>算法如何在时间和资源利用最小的情况下解决问题？</li>\n</ul>\n<p>接下来我也会从人工智能、数据库、图形学、网络安全、嵌入式这些主流方向，探讨下我这几年对这些方向的理解，以及他们分别在解决什么问题？</p>\n<p><strong>现在让我们自底向上的一层一层解决计算机的思路来源、我们的学习目标、以及我在学习过程中遇到的问题和走过的弯路。</strong></p>\n<h2>第一层：数学基础</h2>\n<p>刚进大学时，很多同学会惊讶：“为什么我报的是计算机，结果一上来要学这么多数学？”</p>\n<p>大一时候我们也凑在一起吐槽这一件事，但学到后面才发现数学原来并不只是小中高的代数，那些叫做初等数学，本科学的是更广且更深的数学，且基础也确实十分重要。</p>\n<p>高等数学、线性代数、概率论与数理统计、离散数学，这些基本都是绕不开的课程。甚至有的学校还会学数值分析、组合数学、运筹学之类的内容。</p>\n<p>高等数学主要针对的是连续变化、微分积分的思想；线性代数在图形学、机器学习、数据处理里非常常见；概率统计是人工智能、数据分析、随机过程的基础；而离散数学则和计算机关系尤其紧密，集合、逻辑、图、树、关系、递归，这些东西听起来像数学概念，但后面会不断出现在数据结构、算法、数据库、编译原理、人工智能里。<em>我就是当初的离散数学学的比较认真，后面会有一种触类旁通的感觉。</em></p>\n<p>当然，也不用因此被吓到。对于普通学生来说，如果不想继续在技术前沿去苦苦探索，<strong>数学其实没有必要抓的特别狠</strong>，即使后续忘得差不多了，也不会影响找工作或者简单的前后端编程问题。大部分本科阶段的数学课，只是培养一个思维，在后面遇到复杂概念时，不至于完全没有抓手。</p>\n<blockquote>\n<p><strong>现在遇到的问题：</strong></p>\n<p>而我在大学四年里面，<strong>如果只是按部就班的上学校的课程的话，多半不会对数学有多么深的理解。</strong></p>\n<p>学校的课程为了方便量化考核，不会考你的数学理解和思维思想，而是主要抓你的做题能力。</p>\n<p>这一点我认为是学校教育考核的问题。举一个最好体现的例子，我身边几乎每一个同学对线性代数的理解都是计算行列式，矩阵乘法，求特征向量... 而没有一个是从线性代数上几何的意义去考虑，给我的感觉是我们过于注重线性代数后面的“代数”部分，而忽略了“线性”的概念，导致<strong>大部分同学即使学了人工智能或者图形学的知识，也不理解里面为什么要有矩阵</strong> <em>（后面有机会我再单独整理一篇文章）</em> 。</p>\n<p>而通过自学了解了 <a href=\"https://www.youtube.com/watch?v=7UJ4CFRGd-U&amp;list=PLE7DDD91010BC51F8\">Gilbert Strang教授的 18.06课程</a>，以及<a href=\"https://www.bilibili.com/video/BV1ys411472E/?spm_id_from=333.1387.homepage.video_card.click&amp;vd_source=a1d2d12b1c9f3d1bf63ac9d24e2ff565\">3B1B的动画讲解</a>，才从其基本上去了解了数学的概念和意义。</p>\n</blockquote>\n<p><img src=\"https://imgs.markxu.icu/imgs20260527134223611.png\" alt=\"3B1B的视频讲解\"></p>\n<h2>第二层：编程基础</h2>\n<p>学计算机的一定要会编程👋😭👋！</p>\n<p>常见的入门语言可能是 C、C++、Python，不同学校选择不同。大部分学校一开始强调 C 语言，因为它更接近底层 <em>（几乎可以说是万物起源）</em>，可以帮助理解内存、指针、数组、函数调用这些基础概念，在掌握后，对其他语言的学习会快很多（这里强烈推荐下<a href=\"https://pll.harvard.edu/course/cs50-introduction-computer-science\">CS 50</a>）。有些学校会用 Python 或 Java 入门，因为更容易写出能运行的东西，降低初学门槛。</p>\n<p>刚开始学编程时，内容通常包括变量、条件判断、循环、函数、数组、结构体、类和对象、文件读写这些内容。看起来就像是在学语言语法，但本质上是在<strong>训练如何把一个现实问题拆成机器可以执行的步骤。</strong></p>\n<p>很多人以为写代码难在记住语法，实际上语法只是最表层的东西。真正难的是理解问题、拆分问题、设计流程、处理边界情况。</p>\n<p>简单举个例子：写一个程序用来统计一组成绩的平均分。</p>\n<p>这看起来很简单；但如果数据为空怎么办？如果输入格式错误怎么办？如果成绩太多，内存放不下怎么办？如果要在网页上实时展示又该怎么办？一个问题，一层一层往下挖，找准需求并采用基本的变量、逻辑就会逐渐从“写几行代码的小功能”变成“设计一个完整系统”。</p>\n<p>编程基础课的意义不是是教你某门语言，而是第一次习惯用程序的方式组织思路。</p>\n<blockquote>\n<p><strong>遇到的问题：</strong></p>\n<p>1.考核带来的问题：</p>\n<p>现在计算机课程的老师大多数是在念ppt，然后布置作业，写作业报告的考核方式为主。现在AI技术起来后，大部分的思维训练都可以通过直接给ai发要求来解决，几乎不用动脑。我身边追求绩点的同学，也为了拿到老师的高分，选择更为稳妥的解决思路，避免犯错，也会直接使用AI完成主要工作，把更多的精力放在完善工作报告上。导致我身边有很多编程几乎不通，但是文档能力较强的同学。</p>\n<p>2.课程的设置问题：</p>\n<p>我在这些基础课程的拿到的作业要求质量与 <a href=\"https://fa25.datastructur.es/\">Berkeley的作业</a>要求在难度上有着明显区别。我们最后完成的内容在难度上达到 Berkeley 的课后作业的大概期中前的水平，很难深入的通过一个项目让学术把问题拆的清楚，拆的明白。</p>\n<p>而且我有一个很明显且强烈的感觉：教我们课程的老师大多是受制于课时要求来上的，其并不真懂得这门语言。比如C++的老师对指针的运用仅停留在基础用法，python老师对python的基础库的知识仅局限于课程ppt里的那些，更不用说上课会有尝试写代码运行不通，解释说写的是伪代码的闹剧。</p>\n<p>这几个问题导致同学们的编程基础从从根本上就不是深入的、成体系的，所以后续甚至需要再去上一个语言编程班来加强。</p>\n</blockquote>\n<p><img src=\"https://img.markxu.icu/img20260527141237484.png\" alt=\"Berkeley DS最后的作业\"></p>\n<h2>第三层：数据结构与算法</h2>\n<p>如果只能选一门最能代表计算机专业基本功的课，我大概会选数据结构与算法。</p>\n<p>数据结构研究的是数据怎么放，算法研究的是问题怎么解。</p>\n<ul>\n<li>数组、链表、栈、队列、树、图、哈希表、堆，这些都是常见的数据结构。</li>\n<li>排序、查找、递归、动态规划、贪心、图算法，这些则是常见的算法思想。</li>\n</ul>\n<p>这门课一开始最让我感到痛苦，因为它不像写一个网页那样马上能看到结果，也不像做一个小软件那样有明确界面，有很及时的正反馈。它就像是在练内功，很多东西看着很好理解，很容易掌握，但大多数时间却是在不断失败中寻找出路。</p>\n<p>数据结构和算法这两项构成了所有程序的底层。也常常会有用途一致，但是由于数据结构的不同产生了两种同生态位的优秀产品。</p>\n<p>比如Notion 和 Obsidian 都用来“记笔记”，界面上同样支持页面、嵌套和链接，但底层的数据管理截然不同。Notion 把文档拆成 Block，用<strong>树结构</strong>管理层级与嵌套，一切操作本质上是子树的移动与折叠；Obsidian 则把每篇笔记当作 <strong>图中的一个节点</strong> ，通过一个双向链接建立边，靠邻接表维护关联与反向索引。</p>\n<p>简单来说，<a href=\"https://www.notion.com/help/what-is-a-block\">Notion 像是在整理一个多层文件夹</a>，而<a href=\"https://obsidian.md/zh/help/plugins/graph\"> Obsidian 更像是在编织一张蜘蛛网</a>，前者关心上下级，后者关心连接点。正因如此，同样是“整理笔记”，Notion 在思考“谁属于谁”，Obsidian 在思考“谁和谁有关”——<strong>数据结构并没有改变你能做什么，却决定了你是如何思考这件事的。</strong></p>\n<div class=\"img-grid-2\">\n  <img src=\"https://img.markxu.icu/img20260527144633900.png\" alt=\"Notion的Block\" />\n  <img src=\"https://img.markxu.icu/img20260527144337463.png\" alt=\"Obsidian关系图谱\" />\n</div>\n<p>所以，数据结构与算法不是为了刷题而存在的。刷题只是训练方式之一，它真正训练的是：<strong>面对问题时，如何选择合适的抽象和解决策略。</strong></p>\n<h2>第四层：计算机整体系统</h2>\n<p>计算机专业和一些纯软件培训最大的不同，是它会要求你理解“代码下面发生了什么”。</p>\n<p>这部分通常包括计算机组成原理、操作系统、计算机网络、数据库系统、编译原理等课程。</p>\n<p><strong>计算机组成原理</strong>会告诉你，CPU、内存、指令、寄存器、缓存这些东西是怎么配合的。也就是屏幕上发生的一切，是如何通过二进制的0和1，在电子器件上进行变换，最后变成软件或者游戏的。</p>\n<p><strong>操作系统</strong>会讲进程、线程、内存管理、文件系统、调度、死锁。你会理解为什么电脑可以同时开很多软件，为什么程序会卡死，为什么内存不够会变慢，为什么多线程写不好会出现奇怪 bug。</p>\n<p><strong>计算机网络</strong>会讲 TCP/IP、HTTP、DNS、路由、拥塞控制。你每天打开网页、发消息、看视频，其实都在使用这些协议。学完之后，至少会知道“网络不好”不是一句万能解释，背后可能是延迟、丢包、带宽、DNS、服务器、客户端等一堆环节共同造成的。</p>\n<p><strong>数据库</strong>会讲关系模型、SQL、索引、事务、并发控制、数据一致性。它解决的是数据怎么长期、可靠、有组织地存起来，并且在多人同时访问时尽量不出乱子。</p>\n<p><strong>编译原理</strong>则会讲一门语言如何从源代码变成机器能执行的形式。词法分析、语法分析、语义分析、优化、代码生成，听起来很硬核，但它会让你理解编程语言不是凭空出现的，而是可以被设计和实现的系统。<em>（这门课确实很考验逻辑，难度不低）</em></p>\n<p>这些课共同构成了计算机专业的系统底座。你不一定以后都直接做操作系统或编译器，但理解这些内容，会让你在面对复杂问题时更有“底层感”，如果学习的够深，甚至可以在面对奇怪bug时，找出底层方向，比如我在看<a href=\"https://mastodon.gamedev.place/@TomF/115589875974658415\">这个帖子</a>的问题描述到后期的时候，就猜到或许与历史原因导致的数字的浮点计算有关。</p>\n<p><img src=\"https://img.markxu.icu/img20260527150240665.png\" alt=\"猜到的时机\"></p>\n<h2>最后一层：专业方向课</h2>\n<p>到了大三、大四，很多学校会开设方向课或选修课。不同学校差异会比较明显，但常见方向大概有下面这些，也可以通过<a href=\"https://csdiy.wiki/\">csdiy.wiki</a>去寻找自己想要的课程 <em>(如果你很厉害的话，可以参考下作者的评价，对于我这种资质普通的学生来说，耗得时长比作者的高出不少，难度感觉要高一些，且学习完真不一定就记住了)</em>。</p>\n<p><strong>人工智能与机器学习。</strong><br>\n包括机器学习、深度学习、自然语言处理、计算机视觉、数据挖掘等内容。现在很热门，但真正学起来并不只是“调大模型”。你需要理解数据、模型、训练、评估、过拟合、损失函数、优化方法这些基本概念，还要学习pytorch等框架，刚刚上手确实令人兴奋，看到训练的时候损失在降，真得让人有种单纯的有点silly的高兴。</p>\n<p><strong>网络与信息安全。</strong><br>\n包括密码学、网络安全、系统安全、Web 安全、逆向工程等内容。这个部分我几乎没有了解，只是有过一次机会采访过公安里面的网安人员和企业里的网安人员，浅浅的获得了部分知识。知道现在的市场对这方面的需求还在增加，但真要继续深入，就是网安这个专业的内容了。</p>\n<p><strong>嵌入式与物联网。</strong><br>\n偏硬件和系统结合，可能会接触单片机、传感器、实时系统、嵌入式 Linux 等。它更关心程序如何在资源有限的设备上稳定运行。</p>\n<p><strong>软件开发与工程实践。</strong><br>\n包括 Web 开发、移动开发、云计算、微服务、软件测试、DevOps 等。这个方向和实际就业联系很紧密，强调工程能力和系统开发经验。</p>\n<p>大一的时候我们的院长（现在是副校）曾给我们上过《计算机导论》，他在课上推荐了《人月神话》这本书，我一看是上世纪70年代的书，还觉得院长真是个“老东西”<em>（没有不尊敬的意思）</em>。一直到我组织大创，真的开发一个项目的时候，想起来老师的推荐，才发现自己踩得坑别人早在50年前就有了更好的解决思路。如果想要了解开发的过程，《人月神话》是一本没有门槛的贯彻开发全程的故事书。</p>\n<p><strong>图形学、游戏、虚拟现实。</strong><br>\n会涉及几何、渲染、物理模拟、引擎、交互等内容。它看起来很酷，但背后有大量数学、算法和工程细节。我曾经学习过GAMES101，后续实在是没有时间，课程也有点点难，就放弃了。但是这不算短暂的接触也让我在玩游戏时，会很注重游戏引擎的渲染逻辑，也会时常看一些虚幻引擎的发布会，了解这炫酷的技术。其实图形学不仅仅是面对游戏引擎这一类的知识，背后的方向还有很多，后续再进行介绍吧。</p>\n<p><strong>大数据与数据库。</strong><br>\n包括分布式系统、数据仓库、数据分析、推荐系统等内容。它处理的问题通常是数据规模大、并发高、系统复杂。大数据的内容我没有深入接触，不好做出有专业性的评价。</p>\n<p>这些方向不是互相割裂的。比如人工智能需要算法和数学，也需要系统和工程；网络安全需要操作系统和网络基础；后端开发离不开数据库、网络和软件工程。</p>\n<p>计算机专业的特点就是这样：越往后学，越会发现很多课程在互相连接。想要把上述的专业方向全部学明白，或者说全部学一遍，在我看来没有人可以做到，即使是专精一个方向，也需要以年来记的时光。我在大学四年的探索不算少，但后续的深入研究，大抵就是研究生的方向和目的了。</p>\n<p>具体可以看这一篇知乎回答：</p>\n<p>计算机本科生花大量时间写编译器，操作系统是不是不务正业？ - Freezy的回答 - 知乎<br>\n<a href=\"https://www.zhihu.com/question/321433640/answer/2066636784763720375\">https://www.zhihu.com/question/321433640/answer/2066636784763720375</a></p>\n<h2>学计算机需要什么特质？</h2>\n<p>我觉得最重要的不是“数学天才”，也不是“从小会写代码”。</p>\n<p>更重要的是几种比较朴素但又少见的能力。</p>\n<p>一是愿意自己查资料。计算机领域变化很快，很多问题不会再有老师一步一步带你解决，甚至好多同学也没有时间手把手教你。报错信息、官方文档、搜索引擎、开源项目、论文、社区讨论，都会成为你学习的一部分，这个能力即使在现在的ai时代，也显得尤为重要。</p>\n<p>二是能忍受挫败感。程序报错是家常便饭，环境配不起来也很正常。我曾经配环境配了3天才成功跑通，一个bug修了一周，天天熬夜。可能是我菜，但据论坛上的经历，貌似并不少见。</p>\n<p>三是喜欢拆问题。计算机很少直接解决一个巨大问题，而是不断把问题拆小，把模糊需求变成明确步骤，把复杂系统拆成模块，这种思维一旦形成，即使是在浏览网页，也会尝试不自觉地去抽象里面的数据结构。<em>（其实蛮像高中物理里的受力分析）</em></p>\n<p>四是有一点持续学习的耐心。你可能刚学会一个框架，新的工具又出来了；刚理解一个方向，行业热点又变了。计算机专业不太适合只靠大学四年吃一辈子老本，更何况现在的ai时代来临，老本可能直接清零，保持学习或许是我们普通人唯一能与之抗衡的方法。</p>\n<h2>最后</h2>\n<p>计算机科学与技术专业学的东西很多，也很杂。</p>\n<p>它既有数学，也有工程；既有理论，也有实践；既要理解底层系统，也要能做出上层应用。刚开始学的时候，很容易觉得这些课彼此之间没什么关系：数学是数学，C 语言是 C 语言，操作系统是操作系统，数据库是数据库。但学到后面会慢慢发现，它们其实都在回答同一个问题：</p>\n<p><strong>如何让信息被更好地表示、存储、传输、处理和使用？</strong></p>\n<p>这篇文章是一个很粗略的介绍，主要作为我大学四年来，一直学习的心得体会，以及我感受到问题和最真诚的建议。虽然一个对未来充满迷茫的普通双非大学生的学习体验不能覆盖全面，但至少希望它能帮助家长和对计算机感兴趣的同学建立一个基本印象：计算机不是大段的数学，也不是简单敲代码。而是去理解计算机底层的方方面面。</p>\n<p>如果你真的选择去学习它，后面大概率会遇到很多让人头疼的 bug、看不懂的课、配不好的环境、做不完的项目。</p>\n<p>但也会有一些很开心的时刻：程序第一次跑通，网页第一次上线，模型第一次出结果，自己写的小工具真的帮到了别人。那些瞬间会让你觉得，自己确实在一点点把脑子里的想法变成现实。</p>\n<p>这些微不足道的小确幸和正反馈，大概就是计算机专业最吸引我的地方。</p>\n",
      "summary": "写给想要了解计算机科学与技术专业到底学些什么的朋友，它不只是写代码，也不只是修电脑，而是一套围绕计算、系统、软件和工程实践展开的训练。",
      "date_published": "2026-05-27T00:00:00.000Z",
      "date_modified": "2026-08-05T00:00:00.000Z",
      "image": "https://img.markxu.icu/img20260527160205221.png",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/blog/why-I-recommend-everyone-to-write-blog-cn",
      "url": "https://markxu.icu/blog/why-I-recommend-everyone-to-write-blog-cn",
      "title": "为什么会推荐大学生写博客？",
      "content_text": "在高考结束后，来到离家有1800公里远的城市上学，走出以高考成绩为唯一标准的人生阶段，遇到很多让我开始思考的事情，面临很多需要自己决定的选择。有时一件事会让我持续想到半夜，睡前不断的重复，攒了一肚子话。第二天试着记下来，才发现其实也不过是一两个自然段就说完了的碎碎念，没有多少内容。写作帮助我减轻了不少焦虑，也为我后来回顾提供了线索。 现在翻回来看，我可以清楚地看到自己的世界观是怎么由生活中的一个个碎片拼凑起来的。 写博客可以很好的记录这些生活的点点滴滴，让思想来源有迹可循。 作为一个大学生，可以写什么内容呢？ 博客最主要的观众是自己。 很多人不写，甚至有些怕写，会有“我又不是专家，写出来也没人看”的想法。可恰恰相反，写博客最宝贵的就是“还没想透”的阶段，写下来本身就是在梳理自己的知识和掌握的信息。在写作的时候，为了表达自己的想法，去搜集相关资料，查看相关内容，理清逻辑链条，目的就是把脑子里那片飘忽不定的云，捏成看得见的形状。 其实博客没有这么多的条条框框。 你可以记录自己的爱好，记录遭遇的不顺，记录自己“与众不同”的想法 （你的“与众不同”，其实就是给自己的同类提供找到自己的线索和痕迹） ； 也可以分享对于网络时间的热点事件看法。比如最近比较火的“嘉豪”行为，我会觉得这是人生中一段回想起来会有尴尬，但仍然充满了混乱和热烈的人生时光。像《FLCL》里面描述的，青春期的思维变化。没必要在长大后拿起放大镜开始审判，压制了还在青春期少年们的表达和情绪。 分享自己学习到的知识，比如自己折腾的小项目中，遇到的bug和解决思路，遇到的困难和挑战。搞定一个实验的思路，啃完一本书的感悟，与linux系统斗志斗勇的经历，这些都是可以成为一篇小文章，作为人生的存储点，时不时回来看看。 写出来后怎么发布呢？ 博客是要让人看到的，发布出来，就好像把商店门口的牌子转到“OPEN”，在互联网上开了扇门，Andy Matuschak说这叫“把车库门支起来”，路过的人瞥见你在里面敲敲打打，自然知道这里有人在工作； 手头宽裕的话，可以尝试自己买个域名，利用ai和开源项目做一个符合自己审美的小网站。网上也有很多现成的博客模板，学着套一下模板，也可以直接部署一个属于自己的网站。要是暂时不想折腾，也可以随便在任何笔记软件写下，挑选受众广的发布到知乎、B站、公众号都可以，好的内容总会找到愿意读它的人。 而没有公开发布的，可以自己留作存档，作为自己的思想线索，后续翻看，也不是件坏事。 一个好的博客大概是什么样？ 说到什么样的博客算“好”，我倒觉得不用一开始就想得太复杂。但有几点在我想这里说说。 博客的受众 博客是发布出来的公共文章，首先要考虑受众，搞清楚是谁在看？ 虽然前文说到博客最大的观众是自己，但你所写的内容还是要有一定的公共性。可以是一个理清自己思路的地方，在自己从思考和整理中获益的时候，也要让别人从中看到些东西。越是专业小众的方向，就越要考虑这一点。 当然，也可以将自己的博客作为一个“QQ空间”。虽然这个概念很多博主不喜欢，觉得幼稚，但如果你的目的就是用于社交、分享的话，倒也没有什么不可以的，我也通过很多类似的个人博客网站看到了许多与我类似的同龄人的困扰和喜悦，就像认识了一个陌生的朋友，觉得也不错。 博客的标签化 博客要有自己的主题。 一个好的博客如果想要被人记住，最好可以让人轻易的贴上标签 。就比如看新闻热点分析、哲学阅读、历史解析、经济变化、技术博客分别该去谁的网站。 但这样的要求对于一个大学生有些太高了。一个正常的大学生，在从高考的经历出来后，难有什么阅历，也难有深入的阅读，甚至写作习惯都还有着高考作文的感觉，这很正常。面对选题较少的情况，可以应写尽写，记录自己生活的方方面面。此时，你可以通过一个分类管理，让需要的人去进行一个简单的筛选，可以把你生活的碎碎念屏蔽掉，只专注于你重点的生产内容。这或许是一个还算凑合的解决思路。等到自己的经验积累够多后，再开一个专栏也不迟。 参考2750words博主的思路，他的理念我是大部分认可的，但或许人生阶段不一样，又或许接触博客的契机不同。我认为博客还是应该以博主为基准，既然已经是个人博客了，还要考虑别人的设计哲学是不合理的，不喜欢的网站可以直接选择不看，总有喜欢的人，只要保留你自己的强作者性就好。毕竟， 博客的主人是你自己，舒服永远比“正确”重要。 博客的字数要求 字数要有一定限制，很多人都不喜欢读过长的文章，或者说过于啰嗦的文章。如果一个简单事情很难用较少的字数描述清楚，大概说明写作水平还不到位，啰嗦而不清晰的表达是一个大问题。我的导师曾给我提过要求： “你写的内容要有要点，让读者可以在30s内大体明白意图，有两分钟的读法，也有5分钟的读法。” 适当的加粗文字，足够优秀的标签分段是解决这个问题还算是不错的方法。 理性讨论：收益与成本 前面说了许多，好像写博客是一个“稳赚不赔”的买卖，但这里如果不告诉你相应的成本和代价，未免有些不负责任。 写博客不是一个社交捷径，其实更像是开了一个鲜有人迹的冷清小店。一个好的博客是在网上发声的好方法，写的东西代表了你关注的事情，思考问题的方式。但这并不能带来流量、让你个人IP的爆火、突然被大佬发现、自动带来机会。更多时候，写博客是一个人慢慢的耕耘。 从个人角度来看，博客的维护和坚持并不是每个人都可以做到的。我看过太多博客在记录了初始的三五篇文章后就杳无音讯，甚至域名都不再续费。坦白说，现在的我也是如此，还处在“三分钟热度”，后面的更新也不会像现在一样频繁。再加上，“被误解也是表达者的宿命”，如果比较敏感，还要付出一些情绪成本。甚至维持网站的运行还要持续投入一部分资金，后续的发展如何，也确实难以断定。 写博客这已式微的活动能带来的收益不多。现在正处于新自媒体时代，做视频，短视频是一个更为大众且主流的选择，有平台的加持，会更有流量，也会被更多人看见。 考虑到这么多缺点，为什么我还是推荐？ 首先，正如前文讨论的，写文章是目前为止， 输出最快、最逼人思考、逻辑最裸露 的方式，真正有价值的是文字背后的思想，写作可以极大的锻炼一个人的思考能力。其次，写文章作为一种灵活性高，时间成本低、存储成本低、入门门槛低的输出方式，有着所有输出爱好里面最高的性价比，正如纯文字的发布方式有众多平台去支撑，且一个好的文章可以通过简单的修改成为视频脚本，作为其他输出方式的基础存在。 大胆去创造吧 现在经历的迷茫、拧巴、突然的开心和没来由的难过，都是独属于我们这个人生阶段的礼物。等再回头看，或许会庆幸当年做出那个愿意把想法摊开并记录下的决定。毕竟，在互联网这片空旷的地方，你亮着灯，才会有人循着光走过来，跟你说一句：“嘿，我也在呢。” 我并不确定这盏灯能照亮多远，也不确定能亮多久。 我只是单纯地相信，有些事，不需要证明值得，才值得开始。",
      "content_html": "<p>在高考结束后，来到离家有1800公里远的城市上学，走出以高考成绩为唯一标准的人生阶段，遇到很多让我开始思考的事情，面临很多需要自己决定的选择。有时一件事会让我持续想到半夜，睡前不断的重复，攒了一肚子话。第二天试着记下来，才发现其实也不过是一两个自然段就说完了的碎碎念，没有多少内容。写作帮助我减轻了不少焦虑，也为我后来回顾提供了线索。</p>\n<p>现在翻回来看，我可以清楚地看到自己的世界观是怎么由生活中的一个个碎片拼凑起来的。<strong>写博客可以很好的记录这些生活的点点滴滴，让思想来源有迹可循。</strong></p>\n<h2>作为一个大学生，可以写什么内容呢？</h2>\n<p><strong>博客最主要的观众是自己。</strong> 很多人不写，甚至有些怕写，会有“我又不是专家，写出来也没人看”的想法。可恰恰相反，写博客最宝贵的就是“还没想透”的阶段，写下来本身就是在梳理自己的知识和掌握的信息。在写作的时候，为了表达自己的想法，去搜集相关资料，查看相关内容，理清逻辑链条，目的就是把脑子里那片飘忽不定的云，捏成看得见的形状。</p>\n<p>其实博客没有这么多的条条框框。</p>\n<p>你可以记录自己的爱好，记录遭遇的不顺，记录自己“与众不同”的想法 <em>（你的“与众不同”，其实就是给自己的同类提供找到自己的线索和痕迹）</em>；</p>\n<p>也可以分享对于网络时间的热点事件看法。比如最近比较火的“嘉豪”行为，我会觉得这是人生中一段回想起来会有尴尬，但仍然充满了混乱和热烈的人生时光。像《FLCL》里面描述的，青春期的思维变化。没必要在长大后拿起放大镜开始审判，压制了还在青春期少年们的表达和情绪。</p>\n<p><img src=\"https://img.markxu.icu/imgflcl.gif\" alt=\"FLCL\"></p>\n<p>分享自己学习到的知识，比如自己折腾的小项目中，遇到的bug和解决思路，遇到的困难和挑战。搞定一个实验的思路，啃完一本书的感悟，与linux系统斗志斗勇的经历，这些都是可以成为一篇小文章，作为人生的存储点，时不时回来看看。</p>\n<h2>写出来后怎么发布呢？</h2>\n<p>博客是要让人看到的，发布出来，就好像把商店门口的牌子转到“OPEN”，在互联网上开了扇门，<a href=\"https://notes.andymatuschak.org/Work_with_the_garage_door_up\">Andy Matuschak</a>说这叫“把车库门支起来”，路过的人瞥见你在里面敲敲打打，自然知道这里有人在工作；</p>\n<p><img\n  src=\"https://img.markxu.icu/img20260520161119114.png\"\n  alt=\"图来自淘宝\"\n  style=\"width: min(100%, 360px); height: auto; display: block; margin: 1.5rem auto;\"\n/></p>\n<p>手头宽裕的话，可以尝试自己买个域名，利用ai和开源项目做一个符合自己审美的小网站。网上也有很多现成的博客模板，学着套一下模板，也可以直接部署一个属于自己的网站。要是暂时不想折腾，也可以随便在任何笔记软件写下，挑选受众广的发布到知乎、B站、公众号都可以，好的内容总会找到愿意读它的人。</p>\n<p>而没有公开发布的，可以自己留作存档，作为自己的思想线索，后续翻看，也不是件坏事。</p>\n<h2>一个好的博客大概是什么样？</h2>\n<p>说到什么样的博客算“好”，我倒觉得不用一开始就想得太复杂。但有几点在我想这里说说。</p>\n<h3>博客的受众</h3>\n<p>博客是发布出来的公共文章，首先要考虑受众，搞清楚是谁在看？</p>\n<p>虽然前文说到博客最大的观众是自己，但你所写的内容还是要有一定的公共性。可以是一个理清自己思路的地方，在自己从思考和整理中获益的时候，也要让别人从中看到些东西。越是专业小众的方向，就越要考虑这一点。</p>\n<p>当然，也可以将自己的博客作为一个“QQ空间”。虽然这个概念很多博主不喜欢，觉得幼稚，但如果你的目的就是用于社交、分享的话，倒也没有什么不可以的，我也通过很多类似的个人博客网站看到了许多与我类似的同龄人的困扰和喜悦，就像认识了一个陌生的朋友，觉得也不错。</p>\n<h3>博客的标签化</h3>\n<p>博客要有自己的主题。<strong>一个好的博客如果想要被人记住，最好可以让人轻易的贴上标签</strong>。就比如看新闻热点分析、哲学阅读、历史解析、经济变化、技术博客分别该去谁的网站。</p>\n<p>但这样的要求对于一个大学生有些太高了。一个正常的大学生，在从高考的经历出来后，难有什么阅历，也难有深入的阅读，甚至写作习惯都还有着高考作文的感觉，这很正常。面对选题较少的情况，可以应写尽写，记录自己生活的方方面面。此时，你可以通过一个分类管理，让需要的人去进行一个简单的筛选，可以把你生活的碎碎念屏蔽掉，只专注于你重点的生产内容。这或许是一个还算凑合的解决思路。等到自己的经验积累够多后，再开一个专栏也不迟。</p>\n<p>参考<a href=\"https://pathos.page/about/\">2750words博主</a>的思路，他的理念我是大部分认可的，但或许人生阶段不一样，又或许接触博客的契机不同。我认为博客还是应该以博主为基准，既然已经是个人博客了，还要考虑别人的设计哲学是不合理的，不喜欢的网站可以直接选择不看，总有喜欢的人，只要保留你自己的强作者性就好。毕竟，<strong>博客的主人是你自己，舒服永远比“正确”重要。</strong></p>\n<h3>博客的字数要求</h3>\n<p>字数要有一定限制，很多人都不喜欢读过长的文章，或者说过于啰嗦的文章。如果一个简单事情很难用较少的字数描述清楚，大概说明写作水平还不到位，啰嗦而不清晰的表达是一个大问题。我的导师曾给我提过要求：<strong>“你写的内容要有要点，让读者可以在30s内大体明白意图，有两分钟的读法，也有5分钟的读法。”</strong> 适当的加粗文字，足够优秀的标签分段是解决这个问题还算是不错的方法。</p>\n<h2>理性讨论：收益与成本</h2>\n<p>前面说了许多，好像写博客是一个“稳赚不赔”的买卖，但这里如果不告诉你相应的成本和代价，未免有些不负责任。</p>\n<p>写博客不是一个社交捷径，其实更像是开了一个鲜有人迹的冷清小店。一个好的博客是在网上发声的好方法，写的东西代表了你关注的事情，思考问题的方式。但这并不能带来流量、让你个人IP的爆火、突然被大佬发现、自动带来机会。更多时候，写博客是一个人慢慢的耕耘。</p>\n<p>从个人角度来看，博客的维护和坚持并不是每个人都可以做到的。我看过太多博客在记录了初始的三五篇文章后就杳无音讯，甚至域名都不再续费。坦白说，现在的我也是如此，还处在“三分钟热度”，后面的更新也不会像现在一样频繁。再加上，“被误解也是表达者的宿命”，如果比较敏感，还要付出一些情绪成本。甚至维持网站的运行还要持续投入一部分资金，后续的发展如何，也确实难以断定。</p>\n<p>写博客这已式微的活动能带来的收益不多。现在正处于新自媒体时代，做视频，短视频是一个更为大众且主流的选择，有平台的加持，会更有流量，也会被更多人看见。</p>\n<p>考虑到这么多缺点，为什么我还是推荐？</p>\n<p>首先，正如前文讨论的，写文章是目前为止，<strong>输出最快、最逼人思考、逻辑最裸露</strong>的方式，真正有价值的是文字背后的思想，写作可以极大的锻炼一个人的思考能力。其次，写文章作为一种灵活性高，时间成本低、存储成本低、入门门槛低的输出方式，有着所有输出爱好里面最高的性价比，正如纯文字的发布方式有众多平台去支撑，且一个好的文章可以通过简单的修改成为视频脚本，作为其他输出方式的基础存在。</p>\n<h2>大胆去创造吧</h2>\n<p>现在经历的迷茫、拧巴、突然的开心和没来由的难过，都是独属于我们这个人生阶段的礼物。等再回头看，或许会庆幸当年做出那个愿意把想法摊开并记录下的决定。毕竟，在互联网这片空旷的地方，你亮着灯，才会有人循着光走过来，跟你说一句：“嘿，我也在呢。”</p>\n<p>我并不确定这盏灯能照亮多远，也不确定能亮多久。<strong>我只是单纯地相信，有些事，不需要证明值得，才值得开始。</strong></p>\n",
      "summary": "虽然写博客的概念已经优点过时了，但是我仍然推荐，可以在理清自己思路的同时，记录下自己成长的过程，些许还会认识到志同道合的朋友。",
      "date_published": "2026-05-20T00:00:00.000Z",
      "date_modified": "2026-05-22T00:00:00.000Z",
      "image": "https://img.markxu.icu/imgflcl.gif",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/blog/websurf-tools-recommendation-cn",
      "url": "https://markxu.icu/blog/websurf-tools-recommendation-cn",
      "title": "上网小工具推荐",
      "content_text": "开一个随时更新的帖子吧，有些工具我确实蛮想去推荐一下的，但一次一个又感觉有些碎片化，在这里做一个汇总，如果有新的我也会随时更新！为了方便大家使用，我会把原链接也贴出来。 沉浸式翻译 在互联网时代，多语言教育也逐渐普及到所有的义务教育中，跨语言获取信息也比以往都更简单，但是一个人的精力总是有限的，大家大多数都能看懂两个语言的内容，更多就有些挠头了。而在互联网上，中文信息占比并不够多，居维基百科统计，才排名第十，虽然不准确，但也可以说明些问题。好多计算机相关的知识都要去用英文去搜才搜得到。而有关于个别国家特殊文化的信息，则更是充满挑战。 名次 语言 百分比 ---- -------- ------ 1 英语 59.3% 2 俄语 8.4% 3 西班牙语 4.2% 4 德语 2.9% 5 土耳其语 2.9% 6 波斯语 2.8% 7 法语 2.8% 8 日语 2.4% 9 葡萄牙语 2.2% 10 中文 1.3% 11 越南语 1.3% 12 意大利语 1.0% 此时，掌握一个有效且能兼顾部分原文对比的翻译软件就如同羽扇纶巾般，让信息的搜索渠道一下子变宽了。 油猴 Tampermonkey 这个插件不必多说，堪称浏览器的作弊器，通过在浏览器中运行脚本，解锁或者获得全新的功能！但是也有个奇怪的现象，大家都知道这个插件很厉害，但是却不怎么常用。原因是不知道有什么需求，或者又不知道哪里需要用，去浏览脚本市场发现都是自己用不太到的功能。这里我推荐几个我自己用的比较好的，大家可以去尝试下。 UserScript+--：发现脚本的脚本 正如描述所说，其效果就是用于发现脚本的一个脚本。在一个你常去的网站使用这个脚本，就可以发现前面有多少人针对这个网站进行了怎么样的功能添加，而且用法也极其简单，只需要点击下插件上的按钮，就会自动跳转到展示相关内容的列表 这个脚本轻量高效，我直接贴上源代码，对我来说已经足够了： 微博知乎B站小红书关键词屏蔽器 有时候在网上浏览信息的时候，总会有很多有特殊关键词的信息推送给你，有时候又会渲染焦虑的情绪，使用这个插件，可以减少一些本来就没有意义的焦虑，并且可以自己定制的添加，还是很不错的。 解除不允许复制的脚本 这个功能其实有很多脚本在greasyfork上面就有，甚至github上，或者互联网随便一个地方也都有，我就不贴具体链接了，确实很好用，大家可以自己搜搜看。 B站自动跳过恰饭环节 这个使用起来有些道德约束在，可能会有看盗版的嫌疑... 但是如果你真的不喜欢刷视频的时候花时间看二手手机回收广告、按摩仪、扫地机、除螨仪广告，或许可以适当用用？总之不鼓励使用，但是放在这里，有需要的可以试试！ Wappalyzer : 显示浏览网页的技术栈 这个还是很有意思的，可以看到你目前浏览的网页用的是什么技术栈，运用了什么JS库，如果你是前端开发入门的话，可以看看喜欢的网站都用了什么技术？或者看到一个炫酷的动画效果，也可以直接看到他用了什么动画库。 不过也要说明一下，Wappalyzer 的识别结果只适合当作技术线索，不能完全等同于网站真实的技术栈。比如我确实使用了 React、React Router、GSAP、Lenis、Framer Motion ；但 WordPress、PHP 其实属于误判。这个网站主体实际是基于 Vite + React + TypeScript + Tailwind CSS 搭建的半静态网站，并没有使用 WordPress CMS 或 PHP 后端。 至于误判的原因，大概率还和我在链接预览功能里使用了 WordPress.com 的 mShots 截图服务有关，曾经有同学告诉我，一个陌生的链接大部分人不敢直接点，所以加上了这个功，交互起来也有意思。至于 MySQL，我的评论区使用的是 Twikoo，Twikoo使用的是MySQL作为评论存储，或许是这个原因。 目前先记录下这些，如果你有推荐的也欢迎评论分享！",
      "content_html": "<p>开一个随时更新的帖子吧，有些工具我确实蛮想去推荐一下的，但一次一个又感觉有些碎片化，在这里做一个汇总，如果有新的我也会随时更新！为了方便大家使用，我会把原链接也贴出来。</p>\n<hr>\n<h2>沉浸式翻译</h2>\n<p><a href=\"https://chromewebstore.google.com/detail/immersive-translate-trans/bpoadfkcbjbfhfodiogcnhhhpibjhbnh\">https://chromewebstore.google.com/detail/immersive-translate-trans/bpoadfkcbjbfhfodiogcnhhhpibjhbnh</a></p>\n<p>在互联网时代，多语言教育也逐渐普及到所有的义务教育中，跨语言获取信息也比以往都更简单，但是一个人的精力总是有限的，大家大多数都能看懂两个语言的内容，更多就有些挠头了。而在互联网上，中文信息占比并不够多，居<a href=\"https://zh.wikipedia.org/wiki/%E4%BA%92%E8%81%94%E7%BD%91%E4%BD%BF%E7%94%A8%E8%AF%AD%E8%A8%80\">维基百科统计</a>，才排名第十，虽然不准确，但也可以说明些问题。好多计算机相关的知识都要去用英文去搜才搜得到。而有关于个别国家特殊文化的信息，则更是充满挑战。</p>\n<table>\n<thead>\n<tr>\n<th>名次</th>\n<th>语言</th>\n<th>百分比</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>1</td>\n<td>英语</td>\n<td>59.3%</td>\n</tr>\n<tr>\n<td>2</td>\n<td>俄语</td>\n<td>8.4%</td>\n</tr>\n<tr>\n<td>3</td>\n<td>西班牙语</td>\n<td>4.2%</td>\n</tr>\n<tr>\n<td>4</td>\n<td>德语</td>\n<td>2.9%</td>\n</tr>\n<tr>\n<td>5</td>\n<td>土耳其语</td>\n<td>2.9%</td>\n</tr>\n<tr>\n<td>6</td>\n<td>波斯语</td>\n<td>2.8%</td>\n</tr>\n<tr>\n<td>7</td>\n<td>法语</td>\n<td>2.8%</td>\n</tr>\n<tr>\n<td>8</td>\n<td>日语</td>\n<td>2.4%</td>\n</tr>\n<tr>\n<td>9</td>\n<td>葡萄牙语</td>\n<td>2.2%</td>\n</tr>\n<tr>\n<td>10</td>\n<td>中文</td>\n<td>1.3%</td>\n</tr>\n<tr>\n<td>11</td>\n<td>越南语</td>\n<td>1.3%</td>\n</tr>\n<tr>\n<td>12</td>\n<td>意大利语</td>\n<td>1.0%</td>\n</tr>\n</tbody>\n</table>\n<p>此时，掌握一个有效且能兼顾部分原文对比的翻译软件就如同羽扇纶巾般，让信息的搜索渠道一下子变宽了。</p>\n<p><img src=\"https://img.markxu.icu/img20260517181359803.png\" alt=\"大阪美食推荐网\"></p>\n<h2>油猴 Tampermonkey</h2>\n<p><a href=\"https://chromewebstore.google.com/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo\">https://chromewebstore.google.com/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo</a></p>\n<p>这个插件不必多说，堪称浏览器的作弊器，通过在浏览器中运行脚本，解锁或者获得全新的功能！但是也有个奇怪的现象，大家都知道这个插件很厉害，但是却不怎么常用。原因是不知道有什么需求，或者又不知道哪里需要用，去浏览脚本市场发现都是自己用不太到的功能。这里我推荐几个我自己用的比较好的，大家可以去尝试下。</p>\n<h3>UserScript+--：发现脚本的脚本</h3>\n<p><a href=\"https://greasyfork.org/zh-CN/scripts/409727-userscript-show-site-all-userjs-num-%E6%98%BE%E7%A4%BA%E9%80%82%E7%94%A8%E7%9A%84userjs%E8%84%9A%E6%9C%AC%E6%95%B0%E5%8F%8A%E8%B7%B3%E8%BD%AC\">https://greasyfork.org/zh-CN/scripts/409727-userscript-show-site-all-userjs-num-%E6%98%BE%E7%A4%BA%E9%80%82%E7%94%A8%E7%9A%84userjs%E8%84%9A%E6%9C%AC%E6%95%B0%E5%8F%8A%E8%B7%B3%E8%BD%AC</a></p>\n<p>正如描述所说，其效果就是用于发现脚本的一个脚本。在一个你常去的网站使用这个脚本，就可以发现前面有多少人针对这个网站进行了怎么样的功能添加，而且用法也极其简单，只需要点击下插件上的按钮，就会自动跳转到展示相关内容的列表</p>\n<p><img src=\"https://img.markxu.icu/img20260517192034039.png\" alt=\"点击OpenuserJS即可\"></p>\n<p>这个脚本轻量高效，我直接贴上源代码，对我来说已经足够了：</p>\n<pre><code class=\"language-javascript\">// ==UserScript==\n// @name         Userscript+-- : Show Site All UserJS num 显示适用的UserJS脚本数及跳转\n// @name:zh      UserScript+--: 显示适用的UserJS脚本数及跳转\n// @name:zh-CN   UserScript+--: 显示适用的UserJS脚本数及跳转\n// @name:zh-TW   UserScript+--: 显示適用的UserJS脚本数及跳转\n// @namespace    https://github.com/ultranity/Userscript-Plus--\n// @version      1.0.0\n// @description        在脚本菜单显示适用于当前网站的油猴脚本数及跳转 Show the num of all Tampermonkey scripts for the current site.\n// @description:zh      在脚本菜单显示适用于当前网站的油猴脚本数及跳转\n// @description:zh-CN   在脚本菜单显示适用于当前网站的油猴脚本数及跳转\n// @description:zh-TW   在脚本菜单顯示適用於當前網站的油猴腳本数及跳转\n// @author       momoos\n// @include        *\n// @resource     siteData  https://greasyfork.org/scripts/by-site.json\n// @run-at       document-idle\n// @noframes\n// @grant        GM_xmlHttpRequest\n// @grant        GM_getResourceText\n// @grant        GM_registerMenuCommand\n// @grant        GM_openInTab\n// @grant        unsafeWindow\n// @connect      greasyfork.org\n// @downloadURL https://update.greasyfork.org/scripts/409727/Userscript%2B--%20%3A%20Show%20Site%20All%20UserJS%20num%20%E6%98%BE%E7%A4%BA%E9%80%82%E7%94%A8%E7%9A%84UserJS%E8%84%9A%E6%9C%AC%E6%95%B0%E5%8F%8A%E8%B7%B3%E8%BD%AC.user.js\n// @updateURL https://update.greasyfork.org/scripts/409727/Userscript%2B--%20%3A%20Show%20Site%20All%20UserJS%20num%20%E6%98%BE%E7%A4%BA%E9%80%82%E7%94%A8%E7%9A%84UserJS%E8%84%9A%E6%9C%AC%E6%95%B0%E5%8F%8A%E8%B7%B3%E8%BD%AC.meta.js\n// ==/UserScript==\n\n/* #eslint-disable no-undef */\n(function() {\n  'use strict';\n\n  // ==============================参数配置\n  let thisDomain =  document.domain.split('.').slice(-2).join('.').toLowerCase();\n\n  // 检查域名对应的脚本数量\n  let getDomainCount = function(domain) {\n      let siteData = GM_getResourceText('siteData');\n      siteData = JSON.parse(siteData);\n      let count = 0;\n      if (siteData.hasOwnProperty(domain)) {\n          count = siteData[domain];\n      }\n      return count;\n  };\n\n  function goGreasyfork() {\n      let url = `https://greasyfork.org/zh-CN/scripts/by-site/${thisDomain}?filter_locale=0`;\n      GM_openInTab(url, {\n          active: true\n      });\n  }\n\n  function goOpenuserJS() {\n      let url = `https://openuserjs.org/?q=${thisDomain}`;\n      GM_openInTab(url, {\n          active: true\n      });\n  }\n  // END\n\n  // ############### 开始\n\n  // 检查当前域名是否有对应油猴脚本\n  let domainCount = getDomainCount(thisDomain);\n // if (domainCount === 0) return;\n\n  GM_registerMenuCommand('Greasyfork:'+domainCount, goGreasyfork); // 设置油猴插件的菜单\n  GM_registerMenuCommand('OpenuserJS', goOpenuserJS) // 设置油猴插件的菜单\n  // ########\n})();\n\n\n</code></pre>\n<h3>微博知乎B站小红书关键词屏蔽器</h3>\n<p><a href=\"https://greasyfork.org/zh-CN/scripts/543102-%E5%BE%AE%E5%8D%9A%E7%9F%A5%E4%B9%8Eb%E7%AB%99%E5%B0%8F%E7%BA%A2%E4%B9%A6%E5%85%B3%E9%94%AE%E8%AF%8D%E5%B1%8F%E8%94%BD%E5%99%A8\">https://greasyfork.org/zh-CN/scripts/543102-%E5%BE%AE%E5%8D%9A%E7%9F%A5%E4%B9%8Eb%E7%AB%99%E5%B0%8F%E7%BA%A2%E4%B9%A6%E5%85%B3%E9%94%AE%E8%AF%8D%E5%B1%8F%E8%94%BD%E5%99%A8</a></p>\n<p>有时候在网上浏览信息的时候，总会有很多有特殊关键词的信息推送给你，有时候又会渲染焦虑的情绪，使用这个插件，可以减少一些本来就没有意义的焦虑，并且可以自己定制的添加，还是很不错的。</p>\n<p><img src=\"https://img.markxu.icu/img20260517193440719.png\" alt=\"插件示例\"></p>\n<h3>解除不允许复制的脚本</h3>\n<p>这个功能其实有很多脚本在greasyfork上面就有，甚至github上，或者互联网随便一个地方也都有，我就不贴具体链接了，确实很好用，大家可以自己搜搜看。</p>\n<h2>B站自动跳过恰饭环节</h2>\n<p><a href=\"https://chromewebstore.google.com/detail/%E5%B0%8F%E7%94%B5%E8%A7%86%E7%A9%BA%E9%99%8D%E5%8A%A9%E6%89%8B/eaoelafamejbnggahofapllmfhlhajdd\">https://chromewebstore.google.com/detail/%E5%B0%8F%E7%94%B5%E8%A7%86%E7%A9%BA%E9%99%8D%E5%8A%A9%E6%89%8B/eaoelafamejbnggahofapllmfhlhajdd</a></p>\n<p>这个使用起来有些道德约束在，可能会有看盗版的嫌疑... 但是如果你真的不喜欢刷视频的时候花时间看二手手机回收广告、按摩仪、扫地机、除螨仪广告，或许可以适当用用？总之不鼓励使用，但是放在这里，有需要的可以试试！</p>\n<p><img src=\"https://img.markxu.icu/img20260517194010162.png\" alt=\"空降小助手\"></p>\n<h2>Wappalyzer : 显示浏览网页的技术栈</h2>\n<p><a href=\"https://chromewebstore.google.com/detail/wappalyzer-technology-pro/gppongmhjkpfnbhagpmjfkannfbllamg\">https://chromewebstore.google.com/detail/wappalyzer-technology-pro/gppongmhjkpfnbhagpmjfkannfbllamg</a></p>\n<p>这个还是很有意思的，可以看到你目前浏览的网页用的是什么技术栈，运用了什么JS库，如果你是前端开发入门的话，可以看看喜欢的网站都用了什么技术？或者看到一个炫酷的动画效果，也可以直接看到他用了什么动画库。</p>\n<div class=\"img-grid-2\">\n  <img src=\"https://img.markxu.icu/img20260517194335017.png\" alt=\"我的小网站\" />\n  <img src=\"https://img.markxu.icu/img20260517194523519.png\" alt=\"Bilibili\" />\n</div>\n<p>不过也要说明一下，Wappalyzer 的识别结果只适合当作技术线索，不能完全等同于网站真实的技术栈。比如我确实使用了 React、React Router、GSAP、Lenis、Framer Motion ；但 WordPress、PHP 其实属于误判。这个网站主体实际是基于 Vite + React + TypeScript + Tailwind CSS 搭建的半静态网站，并没有使用 WordPress CMS 或 PHP 后端。</p>\n<p>至于误判的原因，大概率还和我在链接预览功能里使用了 <a href=\"http://WordPress.com\">WordPress.com</a> 的 mShots 截图服务有关，曾经有同学告诉我，一个陌生的链接大部分人不敢直接点，所以加上了这个功，交互起来也有意思。至于 MySQL，我的评论区使用的是 Twikoo，Twikoo使用的是MySQL作为评论存储，或许是这个原因。</p>\n<hr>\n<p>目前先记录下这些，如果你有推荐的也欢迎评论分享！</p>\n",
      "summary": "这里记录着我是如何使用浏览器的小插件，或者一些其他推荐的上网小工具",
      "date_published": "2026-05-17T00:00:00.000Z",
      "date_modified": "2026-05-17T00:00:00.000Z",
      "image": "https://img.markxu.icu/img20260517181359803.png",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/blog/ai-through-meme-death-stranding-2-cn",
      "url": "https://markxu.icu/blog/ai-through-meme-death-stranding-2-cn",
      "title": "从 Meme 的视角看 AI：死亡搁浅2 游玩启发",
      "content_text": "最近通关了《死亡搁浅2》。里面的演出的抽象程度让我大为震撼，搞不懂为什么要这样设计这个环节：为什么这里突然开始唱歌了？为什么反派最后要演奏美国国歌？pizza功夫又为什么这么厉害？在简单研究后，我忽然意识到：这种游戏好像很难被复制，不仅仅是玩法，更多的是文化表达。 死亡搁浅是怎么样的游戏？ 与市面上已有的游戏类型不同，他有着自己一套新的玩法体验和世界观。 它不像《刺客信条》系列那样，已经形成了一套相对成熟的 3A 工业模板：大开放世界、重复的据点清理、RPG式的装备成长、满地图问号 （巫师3的问号还是不错的） 、站桩剧情演出，似乎只要预算够、团队够、产线够，就能做出一个“像那么回事”的产品 （不过听说育碧要重置黑旗，我高低还是得尝尝咸淡😋） ；它也不像魂类那样，有一个非常清晰的玩法骨架：篝火、死亡惩罚、精力条、Boss 设计、碎片化叙事，换一套世界观和美术主题，依然能很快让玩家理解“哦，这有点魂味儿”；也不像线性3A大作一样，在一个有限的流程里面，给你尽可能多的演出震撼和精妙的地图设计。 《死亡搁浅》不太一样。 它的玩法是全新的，游戏理念是不曾见过的，带来的爽感又是有独特味道的。 别人可以模仿它的美术，可以模仿它的长镜头，可以模仿它那种荒凉、荒诞、现实、或者略微带点神秘主义的气质，甚至可以做一个一模一样的“送货游戏”或者“基建游戏”。但却很难真正的复制它带给玩家的感受。因为它最核心的东西并不是某一个系统，而是一个完整的体验：带着货物在荒野里行走，规划路线，保持平衡，和陌生的玩家完成异步合作 或者对抗 ，在原本荒芜坎坷的荒原上慢慢踩出一条路来，一个自洽且丰富的世界观，一个有自己哲学探讨和思想表达的作品。 游戏是交互的艺术，所以来谈谈他的玩法。 单论玩法的话看上去有点无聊，它所注重的是所有开放世界里面的最垃圾的步行时间。大多数游戏厂商都在优化传送功能，以避免玩家在赶路上花费太多时间而感到疲惫，而它却以这个作为主要卖点，游戏主打的就是将货物从A送到B。 一旦真的玩进去之后，悄悄地与游戏对上电波，产生共鸣，就会发现这种“无聊”里面有一种很强的黏性：爬过陡峭的高山，潜行过窥视者的领地，引出并打败BT，在路上建成基建方便后续的送货，最后将身上的货物0受损的送到NPC的手中，获得NPC的点赞和新装备的设计图纸。且这一路上所做的所有事情，包括走过的路，都会悄然同步到另外一个玩家的世界：或是给别人提供自己的基建，又或是最简单的告诉别人，从这里走可以到达目的地。 在游戏过程中体会到获得新装备的喜悦感和与其他玩家产生“链接”的成就感。 而其世界观也巧妙的达到了一种平衡。时间雨、脐带、冥滩、开罗尔网络，一系列新的名词和设定，互相有着关系，同时与现实世界中的含义对应，产生了某种隐喻，让人很快可以理解，并代入到这个世界里 （这里吐槽下二游文案的小作文和所谓“设定”名词） 。所有的设定都参与到玩家游玩过程遇到的困难和挑战中，或是特殊机制，或是最终目的，又或是需要提防的潜在危机。同时，Kojima桑还在这个世界里添加了许多彩蛋，也可以说是“幽默抽象”的内容，正如文章开篇提到过的那些演出，一开始让我感慨，这难道不会打破这个精心设计的世界观吗？作为这么大投入的一个3A游戏，游戏导演这样夹带私货会不会太冒险了？ 但结果却如网上流传的： “商业化迫于压力，向小岛秀夫妥协了。” 对于浅尝辄止的玩家来说，给了游戏过程中会心一笑的体验，而仔细深究后，发现不仅没有打破世界观，反而让游戏多了一层隐喻和哲学思维在，恰如其分的突兀感会勾引玩家思考，在感到惊喜的同时体会对应的含义。理解或是不理解，都会慢慢接受这个突兀感，也成为了这款游戏独有的特点。 于是我开始好奇：小岛秀夫（Kojima桑）究竟是一个怎样的游戏制作者？ 为什么他能在全球范围内拥有这么多粉丝？为什么他敢用如此巨大的投入，冒险做一个看起来“不符合爆款公式”的游戏？为什么第一部刚出来时风评一度那么分裂，到了第二部，却已经能被很多玩家认真拿来讨论年度最佳？ Meme 的含义 带着这种好奇，我去 B 站看了一些《死亡搁浅2》的设定解析，也翻了一些小岛秀夫的采访。了解到一段有着大多数宅男影子的、充满不幸和巧合的跌宕起伏的经历。了解电影、游戏、阅读和思考带给他制作生涯中的启发。其中里面有一场采访让我尤为注意：说到自己的 第一部指导作品——《合金装备》，主要探讨的是 Meme。 一开始看到这个词，第一反应是“梗图”怎么会在近40年前就作为探讨对象？毕竟现在互联网语境里的 Meme，最常见的中文翻译就是“梗图”，猫猫狗狗配字、表情包、抽象模板，好像都可以叫 Meme。但小岛秀夫说的那个 Meme ，明显不是这个意思。 所以我去查了一下。 根据 Wikipedia 的 Meme 条目，meme 这个概念来自 Richard Dawkins 在 1976 年出版的《The Selfish Gene》（《自私的基因》）。Dawkins 想表达的是：文化中也存在类似“基因”的传播单位。它可以是一段旋律、一个观念、一句口号、一种时尚、一种技艺，或者某种会被人们模仿、复制、变形、继续传播的文化片段。 换句话说，meme 原本并不是互联网上的梗图。 梗图当然是 meme，但 meme 远比梗图大得多。我们的歇后语是 meme，成语是 meme，书籍是meme，电影是meme，网络热梗是 meme，B 站弹幕里的集体复读是 meme，游戏玩家之间的黑话是 meme （你没资格啊你没资格，正因为如此你没资格啊你没资格） ，甚至某些创作方法、审美趣味、叙事套路，也都是 meme。它们像文化里的基因一样，被一代又一代人复制、改写、有时误读、然后再创造，继续活下去。 AI 创造不了文化基因 了解了meme的含义，又会想到死亡搁浅2的剧情设置和背后的隐喻思想，不禁联想到这个时代最火的概念——AI，我觉得事情突然变得有意思了。 现在的大语言模型，本质上并不是一个真正拥有生活经验的人。它没有童年模糊的记忆，没有通宵打游戏之后的畅快，没有第一次走进荒野时的惊喜感，也没有深夜emo的时候被一句歌词或一段旋律击中的感受。它本质上就是一个巨大的概率计算器，吸收了大量人类已经留下的文本、图像、代码、音乐和知识，然后在这些已有文本材料之间寻找向量关系，给出一个“最像人类会说出来”的答案。 也就是说，AI 通过人类的大量语料，已经很擅长使用已有的 meme。 你让它写一个赛博朋克故事，它知道霓虹灯、雨夜、义体、垄断公司、底层街区这些文化符号应该怎么组合。你让它写一个魂类游戏设定，它知道破败王国、失落神明、诅咒、Boss、晦涩物品描述这些东西大概该长什么样。你让它做一张“互联网感”的图，它也知道当代审美里有哪些常见模板。 但问题在于，这些大多还是对既有文化基因的调用、拼接和再分配。AI 可以很快地把我们熟悉的东西重新排列组合，甚至排列得很漂亮、很完整、很像那么回事。 但有时候，新的文化思潮往往来源于大胆尝试和一次错误 回顾人类历史上新的文化思潮，有不少令人印象深刻的来自于一次大胆的尝试，一次误解，或是简单的一个失误。 拿文艺复兴为例子，一些古希腊罗马的哲学、文学、艺术和科学知识。在中世纪，这些知识许多被教会保存、过滤和用于神学目的，以巩固自己的统治和阶级。文艺复兴时期的人文主义者们（如彼特拉克、薄伽丘）从阿拉伯世界和修道院重新发现了大量古典文献。并没有简单地、原教旨地复原，而是 用自己时代的眼光和需求去解读 ，他们强调古典文化中对人的理性、世俗生活和肉体美的赞美，而这在一定程度上是忽略或淡化了古典时代同样存在的迷信、奴役和悲观的一面 。创造了一个历史文化的大爆发。包括现在我们批判有些封建传统的儒学，在当时的社会也是反叛的不得了的存在。 AI只会基于现有的Meme（文化内容）做出一个大概率正确的东西，从底层逻辑上就出现了差别，所以如果问它能不能创造一种真正新的 meme，能不能源源不断的创造让人类从此多出一种表达方式、多出一种体验结构、多出一种“以后大家都会理解的文化基因”，我现在还是会有点怀疑 。 话说回来，这也是《死亡搁浅》的演出安排与玩法设置让我觉得特别珍贵的地方。 它不是把好莱坞明星请来之后，拍一堆豪华过场，再塞进一个大家都熟悉的开放世界玩法里。它确实请了 Norman Reedus、Léa Seydoux、Mads Mikkelsen 这些很有辨识度的演员，也确实有电影化的镜头、音乐和叙事野心。但它没有把这些东西只当作噱头来圈钱，而是用一整套很奇怪、很冒险、也很不稳定的玩法，把一个新的体验推到了玩家面前。 “送货”这件事本来很日常，甚至听起来很无聊。 可是在《死亡搁浅》里，它变成了连接人与人的方式。你背的不只是货物，也是重量、责任、路线选择、风险和时间。你搭的一座桥，可能会被另一个你永远不会见到的玩家使用。你放下的一架充电桩，可能刚好把某一个绝望的玩家救过来。游戏里的“连接”不是一句台词，而是被做进了地形、物理、资源和异步联机系统里面。就连我在后续游玩建设设施的时候，也会开始考虑到这个设备到了其他玩家的世界中是否仍然可以帮到他们。 这就很像一种新的 meme 诞生了。 在它之前，我们很难想象一个大制作游戏可以把“走路”和“送货”变成核心体验；在它之后，大家一看到类似的异步互助或者对抗，可能就会说：“有点死亡搁浅味。”这句话本身就说明，它已经变成了一个可以被识别、被引用、被传播的文化单位。 从此以后，世界上有两种人，一种是没有玩过《死亡搁浅》的，一种是玩过《死亡搁浅》的。 说到之前提到的离奇的演出效果，我想也正是这些离奇的演出，反过来又成为奇怪的Meme，让这个具有特色的游戏额外产生了一种与其他文化和粉丝之间的\"链接\"，也创造了属于自己游戏粉丝之间的新的meme，作为本游戏粉丝之间“链接”的密钥。 换个角度看，AI 和 meme 的关系也许没有那么悲观。 如果 AI 只是不断复读旧的 meme，那它当然会让文化变得越来越平均、越来越像、越来越“正确但无聊”。我们已经能在很多地方看到这种味道：像模板一样漂亮却呆板的文案，像模板一样精美却不完整的图片，像模板一样流畅但没有个人经验的表达。它们都不差，但也很难留下长久的痕迹。 可是反过来想，AI 也可能成为 meme 继续生长的工具。 过去，一个人有一个很奇怪的 idea，想把它做成游戏、动画、软件、短片这种的文化作品，往往需要大量资金、团队、技术积累或者试错成本。很多想法不是没有价值，而是在落地之前就死掉了。建模、程序、美术、音效、剪辑、测试，这些并不只是“重复劳动”，但它们确实是把想法变成作品之前必须跨过去的高墙。 如果 AI 继续发展，能够在建模、代码、动画、脚本、关卡原型这些环节里真正降低成本，让更多人以更小的规模、更少的资金、更短的试错周期，把自己的想法做出来，那也许会是一件很美的事。 （包括本人的小网站，正是由于AI才可以发展的这么快，做的效果这么多） 因为文化并不是只由大公司和大预算创造的。 很多新的 meme，最开始可能只是一个人的怪念头、一个小团队的执念、一个看起来不太商业的玩法，或者一句 “我就是想试试这样行不行” 。如果 AI 能把这些念头从脑子里拖到现实里，让更多原本没有机会成形的作品被看见，那它并不是在替代文化，而是在扩大文化发生的入口。当然，前提是我们仍然愿意提供真正来自人的东西，AI 就可以帮我们更快地抵达作品。但新的 meme，可能仍然要从人的孤独、好奇、偏执、失败和经验里长出来。 《死亡搁浅2》给我的启发大概就在这里：当一个创作者真的把自己的感受、审美和问题意识压进一个作品里，它就有机会变成新的文化基因。也许一开始大家会觉得奇怪，觉得另类，觉得不像一个“正常游戏”。但只要它真的击中了某些东西，它就会被记住，被讨论，被模仿，或者被误读，然后继续传播。 最后用《死亡搁浅2》里，小岛秀夫给予玩家们的结语，来展望我们在AI时代的未来和发展，即使不知道未来如何，我们也不要停止探索，不要停止尝试。 尽管未来是当下每一刻的产物，明日依然不属于今日。 活着就是想象未来的自己，我们终将抵达未来。 然而，我们未必能在那未来成为想象中的自己。 ——安部公房《执着探寻当下》",
      "content_html": "<p>最近通关了《死亡搁浅2》。里面的演出的抽象程度让我大为震撼，搞不懂为什么要这样设计这个环节：为什么这里突然开始唱歌了？为什么反派最后要演奏美国国歌？pizza功夫又为什么这么厉害？在简单研究后，我忽然意识到：这种游戏好像很难被复制，不仅仅是玩法，更多的是文化表达。</p>\n<hr>\n<h2>死亡搁浅是怎么样的游戏？</h2>\n<p><img src=\"https://img.markxu.icu/img3fb98aadb2ed7fe1f555e6139a76c72919300662.png\" alt=\"\"></p>\n<p>与市面上已有的游戏类型不同，他有着自己一套新的玩法体验和世界观。</p>\n<p>它不像《刺客信条》系列那样，已经形成了一套相对成熟的 3A 工业模板：大开放世界、重复的据点清理、RPG式的装备成长、满地图问号 <em>（巫师3的问号还是不错的）</em>、站桩剧情演出，似乎只要预算够、团队够、产线够，就能做出一个“像那么回事”的产品 <em>（不过听说育碧要重置黑旗，我高低还是得尝尝咸淡😋）</em> ；它也不像魂类那样，有一个非常清晰的玩法骨架：篝火、死亡惩罚、精力条、Boss 设计、碎片化叙事，换一套世界观和美术主题，依然能很快让玩家理解“哦，这有点魂味儿”；也不像线性3A大作一样，在一个有限的流程里面，给你尽可能多的演出震撼和精妙的地图设计。</p>\n<p>《死亡搁浅》不太一样。</p>\n<p><img src=\"https://img.markxu.icu/img820493971faa912767921b744a29bc6219300662.png\" alt=\"\"></p>\n<p>它的玩法是全新的，游戏理念是不曾见过的，带来的爽感又是有独特味道的。</p>\n<p>别人可以模仿它的美术，可以模仿它的长镜头，可以模仿它那种荒凉、荒诞、现实、或者略微带点神秘主义的气质，甚至可以做一个一模一样的“送货游戏”或者“基建游戏”。但却很难真正的复制它带给玩家的感受。因为它最核心的东西并不是某一个系统，而是一个完整的体验：带着货物在荒野里行走，规划路线，保持平衡，和陌生的玩家完成异步合作<em>或者对抗</em>，在原本荒芜坎坷的荒原上慢慢踩出一条路来，一个自洽且丰富的世界观，一个有自己哲学探讨和思想表达的作品。</p>\n<p><img src=\"https://img.markxu.icu/img5fa4345c95279387582d4c01011e86b019300662.png\" alt=\"从bilibili上面拿的别人的截图\"></p>\n<p>游戏是交互的艺术，所以来谈谈他的玩法。</p>\n<p>单论玩法的话看上去有点无聊，它所注重的是所有开放世界里面的最垃圾的步行时间。大多数游戏厂商都在优化传送功能，以避免玩家在赶路上花费太多时间而感到疲惫，而它却以这个作为主要卖点，游戏主打的就是将货物从A送到B。</p>\n<p>一旦真的玩进去之后，悄悄地与游戏对上电波，产生共鸣，就会发现这种“无聊”里面有一种很强的黏性：爬过陡峭的高山，潜行过窥视者的领地，引出并打败BT，在路上建成基建方便后续的送货，最后将身上的货物0受损的送到NPC的手中，获得NPC的点赞和新装备的设计图纸。且这一路上所做的所有事情，包括走过的路，都会悄然同步到另外一个玩家的世界：或是给别人提供自己的基建，又或是最简单的告诉别人，从这里走可以到达目的地。</p>\n<p>在游戏过程中体会到获得新装备的喜悦感和与其他玩家产生“链接”的成就感。</p>\n<p><img src=\"https://img.markxu.icu/img20260515235156594.png\" alt=\"一起送货吧peko\"></p>\n<p>而其世界观也巧妙的达到了一种平衡。时间雨、脐带、冥滩、开罗尔网络，一系列新的名词和设定，互相有着关系，同时与现实世界中的含义对应，产生了某种隐喻，让人很快可以理解，并代入到这个世界里 <em>（这里吐槽下二游文案的小作文和所谓“设定”名词）</em>。所有的设定都参与到玩家游玩过程遇到的困难和挑战中，或是特殊机制，或是最终目的，又或是需要提防的潜在危机。同时，Kojima桑还在这个世界里添加了许多彩蛋，也可以说是“幽默抽象”的内容，正如文章开篇提到过的那些演出，一开始让我感慨，这难道不会打破这个精心设计的世界观吗？作为这么大投入的一个3A游戏，游戏导演这样夹带私货会不会太冒险了？</p>\n<p>但结果却如网上流传的：<strong>“商业化迫于压力，向小岛秀夫妥协了。”</strong></p>\n<p>对于浅尝辄止的玩家来说，给了游戏过程中会心一笑的体验，而仔细深究后，发现不仅没有打破世界观，反而让游戏多了一层隐喻和哲学思维在，恰如其分的突兀感会勾引玩家思考，在感到惊喜的同时体会对应的含义。理解或是不理解，都会慢慢接受这个突兀感，也成为了这款游戏独有的特点。</p>\n<p><img src=\"https://img.markxu.icu/img20260515234853420.png\" alt=\"小岛秀夫与他的工作室Logo\"></p>\n<p><strong>于是我开始好奇：小岛秀夫（Kojima桑）究竟是一个怎样的游戏制作者？</strong></p>\n<p>为什么他能在全球范围内拥有这么多粉丝？为什么他敢用如此巨大的投入，冒险做一个看起来“不符合爆款公式”的游戏？为什么第一部刚出来时风评一度那么分裂，到了第二部，却已经能被很多玩家认真拿来讨论年度最佳？</p>\n<h2>Meme 的含义</h2>\n<p>带着这种好奇，我去 B 站看了一些《死亡搁浅2》的设定解析，也翻了一些小岛秀夫的采访。了解到一段有着大多数宅男影子的、充满不幸和巧合的跌宕起伏的经历。了解电影、游戏、阅读和思考带给他制作生涯中的启发。其中里面有一场采访让我尤为注意：说到自己的<strong>第一部指导作品——《合金装备》，主要探讨的是 Meme。</strong></p>\n<p>一开始看到这个词，第一反应是“梗图”怎么会在近40年前就作为探讨对象？毕竟现在互联网语境里的 Meme，最常见的中文翻译就是“梗图”，猫猫狗狗配字、表情包、抽象模板，好像都可以叫 Meme。但小岛秀夫说的那个 Meme ，明显不是这个意思。</p>\n<p><img src=\"https://img.markxu.icu/img20260516003944566.png\" alt=\"让人熟知的Meme\"></p>\n<p>所以我去查了一下。</p>\n<p>根据 <a href=\"https://en.wikipedia.org/wiki/Meme\">Wikipedia 的 Meme 条目</a>，meme 这个概念来自 Richard Dawkins 在 1976 年出版的《The Selfish Gene》（《自私的基因》）。Dawkins 想表达的是：文化中也存在类似“基因”的传播单位。它可以是一段旋律、一个观念、一句口号、一种时尚、一种技艺，或者某种会被人们模仿、复制、变形、继续传播的文化片段。</p>\n<p>换句话说，meme 原本并不是互联网上的梗图。</p>\n<p>梗图当然是 meme，但 meme 远比梗图大得多。我们的歇后语是 meme，成语是 meme，书籍是meme，电影是meme，网络热梗是 meme，B 站弹幕里的集体复读是 meme，游戏玩家之间的黑话是 meme <em>（你没资格啊你没资格，正因为如此你没资格啊你没资格）</em> ，甚至某些创作方法、审美趣味、叙事套路，也都是 meme。它们像文化里的基因一样，被一代又一代人复制、改写、有时误读、然后再创造，继续活下去。</p>\n<h2>AI 创造不了文化基因</h2>\n<p>了解了meme的含义，又会想到死亡搁浅2的剧情设置和背后的隐喻思想，不禁联想到这个时代最火的概念——AI，我觉得事情突然变得有意思了。</p>\n<p>现在的大语言模型，本质上并不是一个真正拥有生活经验的人。它没有童年模糊的记忆，没有通宵打游戏之后的畅快，没有第一次走进荒野时的惊喜感，也没有深夜emo的时候被一句歌词或一段旋律击中的感受。它本质上就是一个<a href=\"https://ynarwal.github.io/how-llms-work/\">巨大的概率计算器</a>，吸收了大量人类已经留下的文本、图像、代码、音乐和知识，然后在这些已有文本材料之间寻找向量关系，给出一个“最像人类会说出来”的答案。</p>\n<p><img src=\"https://img.markxu.icu/img20260516010924848.png\" alt=\"大模型计算下一个词的概率\"></p>\n<p>也就是说，AI 通过人类的大量语料，已经很擅长使用已有的 meme。</p>\n<p>你让它写一个赛博朋克故事，它知道霓虹灯、雨夜、义体、垄断公司、底层街区这些文化符号应该怎么组合。你让它写一个魂类游戏设定，它知道破败王国、失落神明、诅咒、Boss、晦涩物品描述这些东西大概该长什么样。你让它做一张“互联网感”的图，它也知道当代审美里有哪些常见模板。</p>\n<p>但问题在于，这些大多还是对既有文化基因的调用、拼接和再分配。AI 可以很快地把我们熟悉的东西重新排列组合，甚至排列得很漂亮、很完整、很像那么回事。</p>\n<h3>但有时候，新的文化思潮往往来源于大胆尝试和一次错误</h3>\n<p>回顾人类历史上新的文化思潮，有不少令人印象深刻的来自于一次大胆的尝试，一次误解，或是简单的一个失误。</p>\n<p>拿文艺复兴为例子，一些古希腊罗马的哲学、文学、艺术和科学知识。在中世纪，这些知识许多被教会保存、过滤和用于神学目的，以巩固自己的统治和阶级。文艺复兴时期的人文主义者们（如彼特拉克、薄伽丘）从阿拉伯世界和修道院重新发现了大量古典文献。并没有简单地、原教旨地复原，而是 <strong>用自己时代的眼光和需求去解读</strong>，他们强调古典文化中对人的理性、世俗生活和肉体美的赞美，而这在一定程度上是忽略或淡化了古典时代同样存在的迷信、奴役和悲观的一面 。创造了一个历史文化的大爆发。包括现在我们批判有些封建传统的儒学，在当时的社会也是反叛的不得了的存在。</p>\n<p>AI只会基于现有的Meme（文化内容）做出一个大概率正确的东西，从底层逻辑上就出现了差别，所以如果问它能不能创造一种真正新的 meme，能不能源源不断的创造让人类从此多出一种表达方式、多出一种体验结构、多出一种“以后大家都会理解的文化基因”，我现在还是会有点怀疑 。</p>\n<p><img src=\"https://img.markxu.icu/img20260516011336588.png\" alt=\"我会稳稳的接住你\"></p>\n<p>话说回来，这也是《死亡搁浅》的演出安排与玩法设置让我觉得特别珍贵的地方。</p>\n<p>它不是把好莱坞明星请来之后，拍一堆豪华过场，再塞进一个大家都熟悉的开放世界玩法里。它确实请了 Norman Reedus、Léa Seydoux、Mads Mikkelsen 这些很有辨识度的演员，也确实有电影化的镜头、音乐和叙事野心。但它没有把这些东西只当作噱头来圈钱，而是用一整套很奇怪、很冒险、也很不稳定的玩法，把一个新的体验推到了玩家面前。</p>\n<p><img src=\"https://img.markxu.icu/img20260516012130003.png\" alt=\"大牌云集\"></p>\n<p>“送货”这件事本来很日常，甚至听起来很无聊。</p>\n<p>可是在《死亡搁浅》里，它变成了连接人与人的方式。你背的不只是货物，也是重量、责任、路线选择、风险和时间。你搭的一座桥，可能会被另一个你永远不会见到的玩家使用。你放下的一架充电桩，可能刚好把某一个绝望的玩家救过来。游戏里的“连接”不是一句台词，而是被做进了地形、物理、资源和异步联机系统里面。就连我在后续游玩建设设施的时候，也会开始考虑到这个设备到了其他玩家的世界中是否仍然可以帮到他们。</p>\n<p>这就很像一种新的 meme 诞生了。</p>\n<p>在它之前，我们很难想象一个大制作游戏可以把“走路”和“送货”变成核心体验；在它之后，大家一看到类似的异步互助或者对抗，可能就会说：“有点死亡搁浅味。”这句话本身就说明，它已经变成了一个可以被识别、被引用、被传播的文化单位。</p>\n<p><strong>从此以后，世界上有两种人，一种是没有玩过《死亡搁浅》的，一种是玩过《死亡搁浅》的。</strong></p>\n<p>说到之前提到的离奇的演出效果，我想也正是这些离奇的演出，反过来又成为奇怪的Meme，让这个具有特色的游戏额外产生了一种与其他文化和粉丝之间的&quot;链接&quot;，也创造了属于自己游戏粉丝之间的新的meme，作为本游戏粉丝之间“链接”的密钥。</p>\n<p><img src=\"https://img.markxu.icu/img20260516012207764.png\" alt=\"这里响起了初代奥特曼的背景音乐\"></p>\n<h2>换个角度看，AI 和 meme 的关系也许没有那么悲观。</h2>\n<p>如果 AI 只是不断复读旧的 meme，那它当然会让文化变得越来越平均、越来越像、越来越“正确但无聊”。我们已经能在很多地方看到这种味道：像模板一样漂亮却呆板的文案，像模板一样精美却不完整的图片，像模板一样流畅但没有个人经验的表达。它们都不差，但也很难留下长久的痕迹。</p>\n<p><strong>可是反过来想，AI 也可能成为 meme 继续生长的工具。</strong></p>\n<p>过去，一个人有一个很奇怪的 idea，想把它做成游戏、动画、软件、短片这种的文化作品，往往需要大量资金、团队、技术积累或者试错成本。很多想法不是没有价值，而是在落地之前就死掉了。建模、程序、美术、音效、剪辑、测试，这些并不只是“重复劳动”，但它们确实是把想法变成作品之前必须跨过去的高墙。</p>\n<p>如果 AI 继续发展，能够在建模、代码、动画、脚本、关卡原型这些环节里真正降低成本，让更多人以更小的规模、更少的资金、更短的试错周期，把自己的想法做出来，那也许会是一件很美的事。<em>（包括本人的小网站，正是由于AI才可以发展的这么快，做的效果这么多）</em></p>\n<p>因为文化并不是只由大公司和大预算创造的。</p>\n<p>很多新的 meme，最开始可能只是一个人的怪念头、一个小团队的执念、一个看起来不太商业的玩法，或者一句 <strong>“我就是想试试这样行不行”</strong>。如果 AI 能把这些念头从脑子里拖到现实里，让更多原本没有机会成形的作品被看见，那它并不是在替代文化，而是在扩大文化发生的入口。当然，前提是我们仍然愿意提供真正来自人的东西，AI 就可以帮我们更快地抵达作品。但新的 meme，可能仍然要从人的孤独、好奇、偏执、失败和经验里长出来。</p>\n<p>《死亡搁浅2》给我的启发大概就在这里：当一个创作者真的把自己的感受、审美和问题意识压进一个作品里，它就有机会变成新的文化基因。也许一开始大家会觉得奇怪，觉得另类，觉得不像一个“正常游戏”。但只要它真的击中了某些东西，它就会被记住，被讨论，被模仿，或者被误读，然后继续传播。</p>\n<p>最后用《死亡搁浅2》里，小岛秀夫给予玩家们的结语，来展望我们在AI时代的未来和发展，即使不知道未来如何，我们也不要停止探索，不要停止尝试。</p>\n<blockquote>\n<p>尽管未来是当下每一刻的产物，明日依然不属于今日。</p>\n<p>活着就是想象未来的自己，我们终将抵达未来。</p>\n<p>然而，我们未必能在那未来成为想象中的自己。</p>\n<p>——安部公房《执着探寻当下》</p>\n</blockquote>\n<p><img src=\"https://img.markxu.icu/img20260516013501617.png\" alt=\"游戏结尾字幕\"></p>\n",
      "summary": "通关死亡搁浅2之后，我开始理解 MEME：作为人类文化基因继续生长的方式。AI 可以复用这些文化基因，但新的文化基因，或许仍然要从人的经验里长出来。",
      "date_published": "2026-05-16T00:00:00.000Z",
      "image": "https://img.markxu.icu/img69e8647962c8ab32d1d0e0fbf1e40b61.png",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/blog/my-graduation-project-cn",
      "url": "https://markxu.icu/blog/my-graduation-project-cn",
      "title": "从大创到毕设，我的“科研思想”进化之路",
      "content_text": "毕业设计结束之后，是时候记录下了，我想。 在做毕业设计的时候，我就一直想为这段时间发生的各种事，以及我的成长想个方式记录下来，正好自己的博客也完成的差不多了，或许是个记录的好方法。 整个毕业设计从最开始连方向都不确定，从壮着胆子去问本科的指导老师有没有“合适项目”的尝试；后来不断长成为我的大创项目、我与队友们一起完成了一个系统、最后还实现了算法的小创新。 现在回头看，整个过程最让人记忆深刻的不是学习到的知识，也不是读了多少论文和多少尝试，更不是最后的看起来蛮不错的成果，而是一个看起来很通俗但又明确的教训和经验： 有时候遇到了失败，不要着急画句号，把他当作一个具体的指路牌，会更好的看清接下来的方向。 起点：一个挑战赛 大二下学期，我去找本科阶段的导师，想问问有没有适合参与的项目，去参加大学生创新创业项目，因为当时学长十分推荐我去试一试。那时我对“医学图像”还没有多清晰的概念，对“分割”这个词的理解也停留在把图像里的某个区域圈出来，正如计算机导论中那些经典的yolo算法一样。老师给我介绍了 PENGWIN 2024 骨盆骨折分割挑战赛，让我先围绕这个比赛自己试一试，往下发挥。 PENGWIN 的任务很直观：给定骨盆骨折患者的 CT 或 X-ray 数据，让算法自动分割骨折碎片。公开说明里提到，这类任务之所以困难，是因为骨盆结构复杂，骨折碎片形态和位置变化很大，骨折面又常常因为碰撞、压缩、粘连而变得模糊。 这是研究的行业前沿，而我一个纯纯小白，很难上手去做这种工作，但当时的我并不懂，觉得只是分离一个目标应该不难，所以当初我还有着创新的野心。 PENGWIN Task 1 的训练集在 Zenodo 上公开了 100 例 CT 及标签，完整数据来自 150 名患者，有50例作为官方的测试集，给出比赛最后的评分效果，这些数据清晰的标注了骶骨、左右髋骨及其碎片，并给出了详细的介绍说明，是理想的数据集。 当时的我对这些困难并没有真正的体感。我的第一反应更像是： 既然有数据、有比赛、有任务，那就先把系统搭起来 。 于是“折磨”我一整年的大创就这样开始了。 那一年，我和几位队友一起做了一个基本的医疗管理系统。系统本身要完成数据管理、模型调用、结果展示等功能，听起来像一个完整项目，做起来也确实花了很多时间。前端、后端、数据流、模型接口，很多东西都是边查边写，边写边推翻，常常熬到了凌晨四五点钟，才发觉必须要休息下了。 而其过程中最难的，在我看来或许是与队友的合作，需要解释清楚任务需求，预期效果等等，队友们要相互知道每个人的负责的部分以及对方的工作进度，而这一段团队合作的开发经历也让我深受其苦 （后面有机会再写一个文章记录下，不是这次的重点） 。 到了中期，系统终于有了基础的样子，但老师指出了一个更关键的问题：系统可以展示结果，可我们的医学图像分割算法也需要有创新，直接拿来别人的工作不够达到大创的要求。 这句话其实挺扎心的。因为系统一点点磨出来以后，人很容易误以为自己已经完成了大部分工作，至少给人感觉的工作量很清晰。但在医学图像分割里， 界面只是“把结果端出来”，真正难的是结果从哪里来 ，而这一点，却很难明确和别人介绍背后的工作量。 第一个 U-Net，以及第一次失败 我就是从那个时候正式开始补医学图像分割的知识。 最开始当然绕不开 U-Net。它是医学图像分割里很经典的编码器-解码器结构，一边下采样提取语义，一边上采样恢复空间细节，中间再用跳跃连接把浅层纹理信息带回来。听上去不复杂，所以我也很自然地产生了一种朴素自信：那我自己写一个试试。 于是我手撸了第一个 U-Net。 现在想想，那大概是最有意义的一段代码。模型能跑，loss 会降，结果也能可视化，看到自己的显卡资源吃满，终端一点点的报出新一轮的信息，loss曲线一点点的下降，真是令人幸福的一件事。 但效果仍然不好。后来我又试着跟着AI的建议加深度可分离卷积、空间通道双注意力、SE block 之类的小模块。那个阶段的我读论文还很少，更多是在已有模块里挑一些看起来“可能有用”的东西往网络里胡乱放，再听取ai的奉承，觉得自己做的还算不错。 结果并没有因为模块变多就突然变好，虽然有些许提升，但仍然不够。 更残酷的是，它仍然打不过比赛的 baseline。 这件事给我的冲击不小。忙了一年，系统做出来了，模型也改了不少，熬了几个月的夜，健身也废弃了 （真的怕猝死了） ，但最后算法效果并不理想。那时候我第一次意识到，深度学习不是把几个“高级模块”拼起来就会自动变强。尤其在医学图像里，数据量、标注方式、预处理、损失函数、后处理、评价指标，每个环节都可能比“再加一个 attention”更重要。 也正是这次失败，把我推向了毕业设计真正的问题：不要急着发明一个复杂网络，先理解强 baseline 为什么强，再看它到底还有什么提升的空间。 从 nnU-Net 开始重新学 毕设阶段，在学长的帮助下，我把 nnU-Net 复现了出来。 nnU-Net 的厉害之处不只是网络结构，而是它把医学图像分割里大量“工程经验”系统化了。它会根据数据属性自动配置预处理、patch 大小、网络拓扑、训练策略和后处理，所以很多时候它不是一个普通 baseline，而是一条很扎实的分割流水线。nnU-Net 的论文也提到，它可以在无需大量人工调参的情况下，在多个公开医学分割任务上超过许多专门设计的方法。 复现 nnU-Net 之后，我终于有了一个更可靠的参照物。接着我读到了 FracSegNet 相关工作。它把任务拆成两步：第一步先定位左右髋骨和骶骨，第二步在目标骨区域内分割主要碎片和次要碎片。还引入了骨折距离图，也就是 FDM，让模型更关注骨折接触面附近的区域。 这个思路对我启发很大。 因为骨折分割最麻烦的地方，往往不是一整块骨头能不能分出来，而是相邻碎片之间那一点点缝隙有没有被填平，小碎片有没有被漏掉，断端附近有没有冒出奇怪的假阳性。整体 Dice 看起来可能已经很高了，但如果两个本该分开的骨片被模型粘在一起，三维重建和术前规划里就会出现完全不同的空间关系，分割的质量也不能说是多么好。 换句话说，这个任务需要的与现实世界的物体分割不同，现实世界的分割看起来差不多，然后可以识别出来物体在大部分情况下就足够了。而医学图像的要求更高，漏掉了碎片或者没有找到骨裂的部分，这次分割无论怎么也不能说是成功。 三月的那篇新文章 就在我做完 nnU-Net 和 FracSegNet 复现，正愁着怎么进一步提升的时候，和老师的一次谈话，老师又给了我一篇三月份的新文章，方法叫 SCNP，全称是 Same Class Neighbor Penalization。 这篇文章的出发点很巧妙：很多分割模型在整体区域上表现不错，但无法保证拓扑结构准确。比如细长结构断开、小区域凭空出现、原本分离的结构被粘连。SCNP 的做法是在训练时对 logits 做一个邻域传播：前景位置会受到同类邻域中较弱响应的影响，背景位置会受到同类邻域中更容易混淆响应的影响。直观地说，它让模型可以额外照顾周围同类邻居里最容易出错的地方。 这个想法一下子和骨折分割对上了。 骨折碎片的问题恰好就是局部结构问题。一个窄缝被填平，一个小碎片被吞掉，一个断端附近冒出假阳性，都是“整体大区域看起来还行，但局部连接关系错了”的典型情况。SCNP 的设计很对口，更值得一提的是其有一个工程上的特点，让人很难拒绝：它主要改变训练阶段损失计算前的 logits，不需要改推理流程，也不需要重新设计一整套复杂网络。 不过，直接把 SCNP 用到骨盆 CT 上也有风险。CT 里有噪声，也有远离骨折面的稳定骨区域。如果在所有地方都做邻域传播，可能会把一些无关区域的局部错误也放大。 于是我在毕业设计中，取FracSegNet和SCNP的特点，做了一个折中：把 FracSegNet 里的 FDM 思想和 SCNP 结合起来，用骨折距离图做空间门控，让 SCNP 更多作用在骨折接触面附近的高风险区域。 这也相当于构造了一个与SCNP表现最好的狭窄空间的状况相符的空间。 我的毕业设计做了什么 最后，我认为核心可以概括成三件事。 第一，复现并整理骨盆骨折 CT 分割的基线流程。实验以 nnU-Net 为统一框架，对比 Max-flow、标准 nnU-Net、FracSegNet 基线以及不同 SCNP 变体。标签也被整理为背景、主要碎片、次要碎片三类语义空间。 第二，在损失计算前引入 SCNP 邻域结构传播。它不改变网络推理结构，而是在训练时让局部困难区域更直接地参与优化，从而补充 CE + Dice 对碎片边界、小缝隙和局部连接关系约束不足的问题。 第三，把 FDM 和 SCNP 结合成门控版本。FDM-gated SCNP 会把结构传播集中在骨折面附近，减少稳定骨区域或噪声区域里不必要的传播。实验里我粗略的比较了不同感受野和不同门控阈值，最后发现 是一个比较均衡的设置。 在本地统一后处理和统一评价口径下，FDM-gated SCNP 相较 FracSegNet 复现基线取得了更均衡的结果：All DSC 达到 ，All LDSC 达到 ，All HD95 为 ，IoU 为 。其中 HD95 相较 FracSegNet 基线降低约 ，IoU 提升约 。 这些数字当然不能被理解成“问题解决了”。医学图像里没有这么轻松的胜利。它们更像是说明了一件小而具体的事：在强 baseline 之上，如果把训练目标往局部结构上推一把，模型确实能在边界距离、局部 Dice 和碎片分离质量上变得更稳定一些。 结果之外：我真正学到的东西 这次毕设最让我受用的地方，是我对“创新”的理解变了。 最开始我以为“创新”就是加模块、换结构、把网络画得更复杂（现在看来很不可思议，当初为什么会这样想🤔）。后来发现，在一个真实任务里，创新的第一步是把问题讲清楚：到底是整体分割不准，还是局部边界不稳？是模型容量不够，还是损失函数没有惩罚到真正重要的错误？是需要更大的感受野，还是需要把传播范围收住？ 我的第一次 U-Net 没有打过 baseline，这逼着我不得不承认自己对任务理解太浅。后来复现 nnU-Net 和 FracSegNet，又让我看到强方法往往不是凭空强，而是把数据组织、标签设计、训练策略、后处理和评价指标等等整个流程的所有环节都考虑进去了。而最后引入 SCNP，也不是因为它看起来新，而是它刚好回应了这个任务里反复出现的局部结构错误。 从大创到毕设，这个项目像是绕了一圈。最开始我想做一个系统，后来发现系统背后的算法不够好；我去改模型结构，结果发现随手加模块没有意义；我开始复现强 baseline，才逐渐看清真正的问题；最后回到一个很小的改动：训练时，让模型多看看附近区域里最难的那一块。 有时候毕业设计的意义大概就在这里。它不一定让你做出一个改变世界的东西，但它会让你经历一次完整的、带着挫败感的学习过程。你会知道一个结果是怎么来的，也会知道它为什么还不够好。 还没有结束的问题 当然，这个工作仍然有很多局限。 目前的标签空间仍然是背景、主要碎片、次要碎片三类语义分割，并不能真正输出每一个碎片的实例编号。对于复杂多碎片病例，尤其是非常小的碎片，统一后处理仍然可能漏掉或合并。FDM 门控也依赖任务先验，阈值和感受野主要来自实验选择，还没有变成自适应机制。 未来如果要继续做，应该把结果放进三维重建、复位规划、路径设计这些下游任务里，看局部边界的改善究竟能不能带来真实流程上的收益。 但至少对我来说，这个毕设已经完成了它最重要的任务：它让我从“能不能跑起来”走到了“为什么这样设计”，也让我第一次真正理解， 一个算法项目最难的地方，往往不是写出网络，而是找到值得被优化的错误。 PENGWIN 2024 Challenge 说明 PENGWIN Task 1 数据集 PENGWIN 2024 Challenge Report nnU-Net 论文 FracSegNet / 多尺度距离加权骨盆骨折分割 SCNP 论文",
      "content_html": "<p>毕业设计结束之后，是时候记录下了，我想。</p>\n<p>在做毕业设计的时候，我就一直想为这段时间发生的各种事，以及我的成长想个方式记录下来，正好自己的博客也完成的差不多了，或许是个记录的好方法。</p>\n<p>整个毕业设计从最开始连方向都不确定，从壮着胆子去问本科的指导老师有没有“合适项目”的尝试；后来不断长成为我的大创项目、我与队友们一起完成了一个系统、最后还实现了算法的小创新。</p>\n<p>现在回头看，整个过程最让人记忆深刻的不是学习到的知识，也不是读了多少论文和多少尝试，更不是最后的看起来蛮不错的成果，而是一个看起来很通俗但又明确的教训和经验：<strong>有时候遇到了失败，不要着急画句号，把他当作一个具体的指路牌，会更好的看清接下来的方向。</strong></p>\n<hr>\n<h2>起点：一个挑战赛</h2>\n<p>大二下学期，我去找本科阶段的导师，想问问有没有适合参与的项目，去参加大学生创新创业项目，因为当时学长十分推荐我去试一试。那时我对“医学图像”还没有多清晰的概念，对“分割”这个词的理解也停留在把图像里的某个区域圈出来，正如计算机导论中那些经典的yolo算法一样。老师给我介绍了 <a href=\"https://doi.org/10.5281/zenodo.10990768\">PENGWIN 2024 骨盆骨折分割挑战赛</a>，让我先围绕这个比赛自己试一试，往下发挥。</p>\n<p>PENGWIN 的任务很直观：给定骨盆骨折患者的 CT 或 X-ray 数据，让算法自动分割骨折碎片。公开说明里提到，这类任务之所以困难，是因为骨盆结构复杂，骨折碎片形态和位置变化很大，骨折面又常常因为碰撞、压缩、粘连而变得模糊。</p>\n<p>这是研究的行业前沿，而我一个纯纯小白，很难上手去做这种工作，但当时的我并不懂，觉得只是分离一个目标应该不难，所以当初我还有着创新的野心。</p>\n<p>PENGWIN Task 1 的训练集在 Zenodo 上公开了 100 例 CT 及标签，完整数据来自 150 名患者，有50例作为官方的测试集，给出比赛最后的评分效果，这些数据清晰的标注了骶骨、左右髋骨及其碎片，并给出了详细的介绍说明，是理想的数据集。</p>\n<p>当时的我对这些困难并没有真正的体感。我的第一反应更像是：<strong>既然有数据、有比赛、有任务，那就先把系统搭起来</strong>。</p>\n<p>于是“折磨”我一整年的大创就这样开始了。</p>\n<p>那一年，我和几位队友一起做了一个基本的医疗管理系统。系统本身要完成数据管理、模型调用、结果展示等功能，听起来像一个完整项目，做起来也确实花了很多时间。前端、后端、数据流、模型接口，很多东西都是边查边写，边写边推翻，常常熬到了凌晨四五点钟，才发觉必须要休息下了。</p>\n<p>而其过程中最难的，在我看来或许是与队友的合作，需要解释清楚任务需求，预期效果等等，队友们要相互知道每个人的负责的部分以及对方的工作进度，而这一段团队合作的开发经历也让我深受其苦 <em>（后面有机会再写一个文章记录下，不是这次的重点）</em>。</p>\n<p>到了中期，系统终于有了基础的样子，但老师指出了一个更关键的问题：系统可以展示结果，可我们的医学图像分割算法也需要有创新，直接拿来别人的工作不够达到大创的要求。</p>\n<p>这句话其实挺扎心的。因为系统一点点磨出来以后，人很容易误以为自己已经完成了大部分工作，至少给人感觉的工作量很清晰。但在医学图像分割里，<strong>界面只是“把结果端出来”，真正难的是结果从哪里来</strong>，而这一点，却很难明确和别人介绍背后的工作量。</p>\n<h2>第一个 U-Net，以及第一次失败</h2>\n<p>我就是从那个时候正式开始补医学图像分割的知识。</p>\n<p>最开始当然绕不开 U-Net。它是医学图像分割里很经典的编码器-解码器结构，一边下采样提取语义，一边上采样恢复空间细节，中间再用跳跃连接把浅层纹理信息带回来。听上去不复杂，所以我也很自然地产生了一种朴素自信：那我自己写一个试试。</p>\n<p>于是我手撸了第一个 U-Net。</p>\n<p><img src=\"https://img.markxu.icu/img20260515191007353.png\" alt=\"我的第一个U-net\"></p>\n<p>现在想想，那大概是最有意义的一段代码。模型能跑，loss 会降，结果也能可视化，看到自己的显卡资源吃满，终端一点点的报出新一轮的信息，loss曲线一点点的下降，真是令人幸福的一件事。</p>\n<p>但效果仍然不好。后来我又试着跟着AI的建议加深度可分离卷积、空间通道双注意力、SE block 之类的小模块。那个阶段的我读论文还很少，更多是在已有模块里挑一些看起来“可能有用”的东西往网络里胡乱放，再听取ai的奉承，觉得自己做的还算不错。</p>\n<p>结果并没有因为模块变多就突然变好，虽然有些许提升，但仍然不够。</p>\n<p><strong>更残酷的是，它仍然打不过比赛的 baseline。</strong></p>\n<p>这件事给我的冲击不小。忙了一年，系统做出来了，模型也改了不少，熬了几个月的夜，健身也废弃了 <em>（真的怕猝死了）</em>，但最后算法效果并不理想。那时候我第一次意识到，深度学习不是把几个“高级模块”拼起来就会自动变强。尤其在医学图像里，数据量、标注方式、预处理、损失函数、后处理、评价指标，每个环节都可能比“再加一个 attention”更重要。</p>\n<p>也正是这次失败，把我推向了毕业设计真正的问题：不要急着发明一个复杂网络，先理解强 baseline 为什么强，再看它到底还有什么提升的空间。</p>\n<h2>从 nnU-Net 开始重新学</h2>\n<p>毕设阶段，在学长的帮助下，我把 nnU-Net 复现了出来。</p>\n<p>nnU-Net 的厉害之处不只是网络结构，而是它把医学图像分割里大量“工程经验”系统化了。它会根据数据属性自动配置预处理、patch 大小、网络拓扑、训练策略和后处理，所以很多时候它不是一个普通 baseline，而是一条很扎实的分割流水线。nnU-Net 的论文也提到，它可以在无需大量人工调参的情况下，在多个公开医学分割任务上超过许多专门设计的方法。</p>\n<p>复现 nnU-Net 之后，我终于有了一个更可靠的参照物。接着我读到了 FracSegNet 相关工作。它把任务拆成两步：第一步先定位左右髋骨和骶骨，第二步在目标骨区域内分割主要碎片和次要碎片。还引入了骨折距离图，也就是 FDM，让模型更关注骨折接触面附近的区域。</p>\n<p>这个思路对我启发很大。</p>\n<p>因为骨折分割最麻烦的地方，往往不是一整块骨头能不能分出来，而是相邻碎片之间那一点点缝隙有没有被填平，小碎片有没有被漏掉，断端附近有没有冒出奇怪的假阳性。整体 Dice 看起来可能已经很高了，但如果两个本该分开的骨片被模型粘在一起，三维重建和术前规划里就会出现完全不同的空间关系，分割的质量也不能说是多么好。</p>\n<p>换句话说，这个任务需要的与现实世界的物体分割不同，现实世界的分割看起来差不多，然后可以识别出来物体在大部分情况下就足够了。而医学图像的要求更高，漏掉了碎片或者没有找到骨裂的部分，这次分割无论怎么也不能说是成功。</p>\n<h2>三月的那篇新文章</h2>\n<p>就在我做完 nnU-Net 和 FracSegNet 复现，正愁着怎么进一步提升的时候，和老师的一次谈话，老师又给了我一篇三月份的新文章，方法叫 SCNP，全称是 Same Class Neighbor Penalization。</p>\n<p>这篇文章的出发点很巧妙：很多分割模型在整体区域上表现不错，但无法保证拓扑结构准确。比如细长结构断开、小区域凭空出现、原本分离的结构被粘连。SCNP 的做法是在训练时对 logits 做一个邻域传播：前景位置会受到同类邻域中较弱响应的影响，背景位置会受到同类邻域中更容易混淆响应的影响。直观地说，它让模型可以额外照顾周围同类邻居里最容易出错的地方。</p>\n<p><img src=\"https://img.markxu.icu/imgSCNP-method.png\" alt=\"SCNP方法图示\"></p>\n<p>这个想法一下子和骨折分割对上了。</p>\n<p>骨折碎片的问题恰好就是局部结构问题。一个窄缝被填平，一个小碎片被吞掉，一个断端附近冒出假阳性，都是“整体大区域看起来还行，但局部连接关系错了”的典型情况。SCNP 的设计很对口，更值得一提的是其有一个工程上的特点，让人很难拒绝：它主要改变训练阶段损失计算前的 logits，不需要改推理流程，也不需要重新设计一整套复杂网络。</p>\n<p>不过，直接把 SCNP 用到骨盆 CT 上也有风险。CT 里有噪声，也有远离骨折面的稳定骨区域。如果在所有地方都做邻域传播，可能会把一些无关区域的局部错误也放大。</p>\n<p>于是我在毕业设计中，取FracSegNet和SCNP的特点，做了一个折中：把 FracSegNet 里的 FDM 思想和 SCNP 结合起来，用骨折距离图做空间门控，让 SCNP 更多作用在骨折接触面附近的高风险区域。</p>\n<p>这也相当于构造了一个与SCNP表现最好的狭窄空间的状况相符的空间。</p>\n<h2>我的毕业设计做了什么</h2>\n<p>最后，我认为核心可以概括成三件事。</p>\n<p>第一，复现并整理骨盆骨折 CT 分割的基线流程。实验以 nnU-Net 为统一框架，对比 Max-flow、标准 nnU-Net、FracSegNet 基线以及不同 SCNP 变体。标签也被整理为背景、主要碎片、次要碎片三类语义空间。</p>\n<p>第二，在损失计算前引入 SCNP 邻域结构传播。它不改变网络推理结构，而是在训练时让局部困难区域更直接地参与优化，从而补充 CE + Dice 对碎片边界、小缝隙和局部连接关系约束不足的问题。</p>\n<p>第三，把 FDM 和 SCNP 结合成门控版本。FDM-gated SCNP 会把结构传播集中在骨折面附近，减少稳定骨区域或噪声区域里不必要的传播。实验里我粗略的比较了不同感受野和不同门控阈值，最后发现 <code>rf = 3, tau = 0.3</code> 是一个比较均衡的设置。</p>\n<p><img src=\"https://img.markxu.icu/imgSCNP-pipeline.png\" alt=\"我的方法pipeline\"></p>\n<p>在本地统一后处理和统一评价口径下，FDM-gated SCNP 相较 FracSegNet 复现基线取得了更均衡的结果：All DSC 达到 <code>0.990 ± 0.012</code>，All LDSC 达到 <code>0.990 ± 0.013</code>，All HD95 为 <code>0.868 ± 3.766 mm</code>，IoU 为 <code>0.883 ± 0.142</code>。其中 HD95 相较 FracSegNet 基线降低约 <code>40.3%</code>，IoU 提升约 <code>3.2%</code>。</p>\n<p>这些数字当然不能被理解成“问题解决了”。医学图像里没有这么轻松的胜利。它们更像是说明了一件小而具体的事：在强 baseline 之上，如果把训练目标往局部结构上推一把，模型确实能在边界距离、局部 Dice 和碎片分离质量上变得更稳定一些。</p>\n<h2>结果之外：我真正学到的东西</h2>\n<p>这次毕设最让我受用的地方，是我对“创新”的理解变了。</p>\n<p>最开始我以为“创新”就是加模块、换结构、把网络画得更复杂（现在看来很不可思议，当初为什么会这样想🤔）。后来发现，在一个真实任务里，创新的第一步是把问题讲清楚：到底是整体分割不准，还是局部边界不稳？是模型容量不够，还是损失函数没有惩罚到真正重要的错误？是需要更大的感受野，还是需要把传播范围收住？</p>\n<p>我的第一次 U-Net 没有打过 baseline，这逼着我不得不承认自己对任务理解太浅。后来复现 nnU-Net 和 FracSegNet，又让我看到强方法往往不是凭空强，而是把数据组织、标签设计、训练策略、后处理和评价指标等等整个流程的所有环节都考虑进去了。而最后引入 SCNP，也不是因为它看起来新，而是它刚好回应了这个任务里反复出现的局部结构错误。</p>\n<p>从大创到毕设，这个项目像是绕了一圈。最开始我想做一个系统，后来发现系统背后的算法不够好；我去改模型结构，结果发现随手加模块没有意义；我开始复现强 baseline，才逐渐看清真正的问题；最后回到一个很小的改动：训练时，让模型多看看附近区域里最难的那一块。</p>\n<p>有时候毕业设计的意义大概就在这里。它不一定让你做出一个改变世界的东西，但它会让你经历一次完整的、带着挫败感的学习过程。你会知道一个结果是怎么来的，也会知道它为什么还不够好。</p>\n<h2>还没有结束的问题</h2>\n<p>当然，这个工作仍然有很多局限。</p>\n<p>目前的标签空间仍然是背景、主要碎片、次要碎片三类语义分割，并不能真正输出每一个碎片的实例编号。对于复杂多碎片病例，尤其是非常小的碎片，统一后处理仍然可能漏掉或合并。FDM 门控也依赖任务先验，阈值和感受野主要来自实验选择，还没有变成自适应机制。</p>\n<p>未来如果要继续做，应该把结果放进三维重建、复位规划、路径设计这些下游任务里，看局部边界的改善究竟能不能带来真实流程上的收益。</p>\n<p>但至少对我来说，这个毕设已经完成了它最重要的任务：它让我从“能不能跑起来”走到了“为什么这样设计”，也让我第一次真正理解，<strong>一个算法项目最难的地方，往往不是写出网络，而是找到值得被优化的错误。</strong></p>\n<article-references>\n  <a href=\"https://doi.org/10.5281/zenodo.10990768\" data-note=\"骨盆骨折 CT 与 X-ray 分割挑战赛，介绍任务背景、数据来源和挑战目标。\">PENGWIN 2024 Challenge 说明</a>\n  <a href=\"https://doi.org/10.5281/zenodo.10927452\" data-note=\"公开的 CT 训练集与标签说明。\">PENGWIN Task 1 数据集</a>\n  <a href=\"https://arxiv.org/abs/2504.02382\" data-note=\"挑战赛总结，包含多团队结果、CT/X-ray 任务差异和碎片定义不确定性的讨论。\">PENGWIN 2024 Challenge Report</a>\n  <a href=\"https://www.nature.com/articles/s41592-020-01008-z\" data-note=\"医学图像分割里非常重要的自配置 baseline。\">nnU-Net 论文</a>\n  <a href=\"https://conferences.miccai.org/2023/papers/490-Paper1597.html\" data-note=\"两阶段骨盆骨折分割、FDM 距离加权损失和公开代码数据的相关工作。\">FracSegNet / 多尺度距离加权骨盆骨折分割</a>\n  <a href=\"https://arxiv.org/abs/2603.18671\" data-note=\"通过惩罚同类邻域中最难预测的位置，提升分割拓扑结构准确性的训练方法。\">SCNP 论文</a>\n</article-references>\n",
      "summary": "从一次大创项目、一套医疗管理系统，到骨盆骨折 CT 分割算法的复现与改进。这篇文章记录我的毕业设计，也记录一次从失败里慢慢摸到问题核心的经历。",
      "date_published": "2026-05-15T00:00:00.000Z",
      "date_modified": "2026-09-20T00:00:00.000Z",
      "image": "https://img.markxu.icu/img20260515191007353.png",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/blog/university-info-drawers-cn",
      "url": "https://markxu.icu/blog/university-info-drawers-cn",
      "title": "大学四年，我的几个“小抽屉”",
      "content_text": "我一直很喜欢在互联网上冲浪，收集各种奇奇怪怪的网站、信息源，与其他同学相互分享的时候，也获取到许多，也逐渐成为了我们的共同话题。大学的四年，可以说是我人生中社会化成长最快的四年，经历了许多，也看过了许多，这篇文章想要分享的都是我一直有在看的，也是我喜欢的信息源。如果 大家也有想要分享的，欢迎在评论区里评论！ 👏 科技新闻 阮一峰的网络日志 阮老师的博客估计是中文个人博客里面最家喻户晓、人尽皆知的一个，这个网站下的“科技爱好者周刊”已经成为很多人（包括我）每周五雷打不动的必读文章。 它不局限于纯技术，更像是一本数字时代的综合杂志，内容涵盖了作者的科技思想见闻、科技动态、优秀文章、新工具推荐、文摘、有意思的评论等等，加上作者精心挑选的封面图和介绍，内容很是丰富🤩，足够作为一周的科技热点汇总来看。 我最喜欢的部分是作者的科技见闻，里面包含了很多有意思的思考和启发，常常给我一种大脑皮层换新的感觉。再就是文章推荐的部分，可以说我主要通过这个周刊，了解到了很多优秀的个人博主和新鲜思想 （可以引领潮流的那种！） 。 差评公众号 每晚0点准时更新，差评更像是一个“科技夜宵”，在许许多多我忙着修改bug的夜晚🥱，到了0点都会打开看看，消遣一下。它会快速扫过每天重要的科技小新闻，更多的是与我们用户息息相关的内容。同时有根据当前热度较高的话题，有小的分析和讨论的文章。 差评最主要的特点在于他会用非常通俗，带些网梗的语言，来解读硬核的科技新闻与商业动态，评论区的互动往往也很有梗，甚至还设立了 每日一笑 和 互动板块 ，发起评论区讨论，放松下一天紧绷的神经。 Hacker News 这是一个由 Y Combinator 运营的极简风科技社区，也是我获取“原始信息”的重要窗口。对我来说，最吸引我的是他的排名算法： $$ Score = \\frac{P - 1}{ T + 2 ^G} $$ 其中， $P$ 是条目的得分，减去 $1$ 是为了抵消提交者自己的投票； $T$ 是条目提交后经过的时间，单位为小时，+2是为了防止最新的帖子导致分母过小 （之所以选择2，可能是因为从原始文章出现在其他网站，到转贴至 Hacker News，平均需要两个小时） ； $G$ 是重力因子，在算法中默认值为 $1.8$，其决定了帖子排名下降的速度，类似于重力加速度的概念。 这套机制能自动筛选出社区公认有价值且不过时的内容，让高质量的技术讨论、创业洞察和前沿论文始终浮在水面，而且基本上足够全面，虽然我平时看的并不是很多，但还是在这里分享给大家。 时政新闻 然后是时政新闻： 《睡前消息编辑部》公众号 每晚更新。《睡前消息编辑部》公众号是马督工工作室的主要业务，虽然马督工在互联网的风评 颇有微词 ，但《睡前消息编辑部》公众号里面的新闻质量仍然处于较高质量的梯队。将所有的新闻都提炼为要点，刷牙的时候打开看看，对今天发生的事情可以有个基本了解。 如果你看问题的思路偏向“实事求是”，不喜欢预设立场，那么他的B站账号 马督工 也可以关注下，他的分析框架（尤其是 B 站长视频版）也能提供很多“反直觉”的视角。几乎每一期都能在知乎引发讨论，没事的时候还可以去知乎看看对于一件事情不同的看法，还是很不错的！ 军情D7处 这是我关注的少有的对信息来源要求高、且不怎么情绪化的时政 up 主 （没有“赢赢赢”😭） 。他的介绍思路非常清晰，通常是按地域（如伊朗、俄乌、亚太、美国）划分，梳理近期的事态发展。忙的时候几乎日更，近期频率有所放缓，但内容依然保持着高信息密度和客观性，避免了军事类内容常见的煽动性语言，比较对我的胃口。 技术沉淀 其实偏向于具体技术的信息源有很多，但是随着ai的发展，具体的技术栈问题直接去问大模型似乎是个更快更全面的选择😅，尤其是如果有具体的技术栈的话，也不需要我在这里分享，大家都有合适的对口的博客、文章等信息来源。所以在这里简单的罗列两个我觉得还不错的。 美团技术团队 不定期更新。这是我个人认为国内互联网大厂技术博客中“干货”含量最高的。它不写虚的，全是美团在大规模、高并发业务场景下的真实实战总结。内容覆盖架构设计、AI 工程化 （如 LongCat 系列模型） 、大数据与算法优化等。可以很好的在真实案例中提升自己的系统的思维。 Google Research Google 研究部门（现与 DeepMind 深度整合）的官方博客。这里是许多前沿技术的“源头”，如 Transformer、BERT 等奠基性技术的解读最早都出自这里。它主要发布机器学习、自然语言处理、计算机视觉及量子计算等领域的最新进展 （都是一些很酷的科技😯！） 。虽然部分内容偏科研，但通过它的通俗博文，你能直观感受到“未来技术”的演进方向，看到这些，多少也会有些兴奋的感觉。 上面分享的就是些我在这四年里面比较常关注的信息源，换句话说，就是我逐渐找到的神秘“小抽屉”，给我打开了许多视野，也让我的步伐不至于落后时代太多。本篇文章主要还是抛砖引玉， 如果你有自己珍藏的信息源，很期待你可以在评论区进行分享！",
      "content_html": "<p>我一直很喜欢在互联网上冲浪，收集各种奇奇怪怪的网站、信息源，与其他同学相互分享的时候，也获取到许多，也逐渐成为了我们的共同话题。大学的四年，可以说是我人生中社会化成长最快的四年，经历了许多，也看过了许多，这篇文章想要分享的都是我一直有在看的，也是我喜欢的信息源。如果<strong>大家也有想要分享的，欢迎在评论区里评论！</strong> 👏</p>\n<hr>\n<h2>科技新闻</h2>\n<h3>阮一峰的网络日志</h3>\n<p><a href=\"https://www.ruanyifeng.com/blog/\">https://www.ruanyifeng.com/blog/</a></p>\n<p>阮老师的博客估计是中文个人博客里面最家喻户晓、人尽皆知的一个，这个网站下的“科技爱好者周刊”已经成为很多人（包括我）每周五雷打不动的必读文章。</p>\n<p>它不局限于纯技术，更像是一本数字时代的综合杂志，内容涵盖了作者的科技思想见闻、科技动态、优秀文章、新工具推荐、文摘、有意思的评论等等，加上作者精心挑选的封面图和介绍，内容很是丰富🤩，足够作为一周的科技热点汇总来看。</p>\n<p><img src=\"https://img.markxu.icu/img20260511165922614.png\" alt=\"阮一峰的网络日志\"></p>\n<p>我最喜欢的部分是作者的科技见闻，里面包含了很多有意思的思考和启发，常常给我一种大脑皮层换新的感觉。再就是文章推荐的部分，可以说我主要通过这个周刊，了解到了很多优秀的个人博主和新鲜思想 <em>（可以引领潮流的那种！）</em>。</p>\n<h3>差评公众号</h3>\n<p>每晚0点准时更新，差评更像是一个“科技夜宵”，在许许多多我忙着修改bug的夜晚🥱，到了0点都会打开看看，消遣一下。它会快速扫过每天重要的科技小新闻，更多的是与我们用户息息相关的内容。同时有根据当前热度较高的话题，有小的分析和讨论的文章。</p>\n<p><img src=\"https://img.markxu.icu/img20260511171312528.png\" alt=\"差评公众号\"></p>\n<p>差评最主要的特点在于他会用非常通俗，带些网梗的语言，来解读硬核的科技新闻与商业动态，评论区的互动往往也很有梗，甚至还设立了<strong>每日一笑</strong>和<strong>互动板块</strong>，发起评论区讨论，放松下一天紧绷的神经。</p>\n<h3>Hacker News</h3>\n<p><a href=\"https://news.ycombinator.com/\">https://news.ycombinator.com/</a></p>\n<p>这是一个由 Y Combinator 运营的极简风科技社区，也是我获取“原始信息”的重要窗口。对我来说，最吸引我的是他的<a href=\"https://medium.com/hacking-and-gonzo/how-hacker-news-ranking-algorithm-works-1d9b0cf2c08d\">排名算法</a>：</p>\n<p>$$<br>\nScore = \\frac{P - 1}{(T + 2)^G}<br>\n$$</p>\n<p>其中，</p>\n<ul>\n<li>$P$ 是条目的得分，减去 $1$ 是为了抵消提交者自己的投票；</li>\n<li>$T$ 是条目提交后经过的时间，单位为小时，+2是为了防止最新的帖子导致分母过小 <em>（之所以选择2，可能是因为从原始文章出现在其他网站，到转贴至 Hacker News，平均需要两个小时）</em>；</li>\n<li>$G$ 是重力因子，在算法中默认值为 $1.8$，其决定了帖子排名下降的速度，类似于重力加速度的概念。</li>\n</ul>\n<p>这套机制能自动筛选出社区公认有价值且不过时的内容，让高质量的技术讨论、创业洞察和前沿论文始终浮在水面，而且基本上足够全面，虽然我平时看的并不是很多，但还是在这里分享给大家。</p>\n<p><img src=\"https://img.markxu.icu/img20260511181313296.png\" alt=\"Hacker News网站\"></p>\n<hr>\n<h2>时政新闻</h2>\n<p>然后是时政新闻：</p>\n<h3>《睡前消息编辑部》公众号</h3>\n<p>每晚更新。《睡前消息编辑部》公众号是马督工工作室的主要业务，虽然马督工在互联网的风评<strong>颇有微词</strong>，但《睡前消息编辑部》公众号里面的新闻质量仍然处于较高质量的梯队。将所有的新闻都提炼为要点，刷牙的时候打开看看，对今天发生的事情可以有个基本了解。</p>\n<p><img src=\"https://img.markxu.icu/img20260511181953046.png\" alt=\"睡前消息编辑部\"></p>\n<p>如果你看问题的思路偏向“实事求是”，不喜欢预设立场，那么他的B站账号 <a href=\"https://space.bilibili.com/316568752?spm_id_from=333.337.0.0\">马督工</a> 也可以关注下，他的分析框架（尤其是 B 站长视频版）也能提供很多“反直觉”的视角。几乎每一期都能在知乎引发讨论，没事的时候还可以去知乎看看对于一件事情不同的看法，还是很不错的！</p>\n<h3>军情D7处</h3>\n<p><a href=\"https://space.bilibili.com/448165099\">https://space.bilibili.com/448165099</a></p>\n<p>这是我关注的少有的对信息来源要求高、且不怎么情绪化的时政 up 主 <em>（没有“赢赢赢”😭）</em>。他的介绍思路非常清晰，通常是按地域（如伊朗、俄乌、亚太、美国）划分，梳理近期的事态发展。忙的时候几乎日更，近期频率有所放缓，但内容依然保持着高信息密度和客观性，避免了军事类内容常见的煽动性语言，比较对我的胃口。</p>\n<hr>\n<h2>技术沉淀</h2>\n<p>其实偏向于具体技术的信息源有很多，但是随着ai的发展，具体的技术栈问题直接去问大模型似乎是个更快更全面的选择😅，尤其是如果有具体的技术栈的话，也不需要我在这里分享，大家都有合适的对口的博客、文章等信息来源。所以在这里简单的罗列两个我觉得还不错的。</p>\n<h3>美团技术团队</h3>\n<p><a href=\"https://tech.meituan.com/\">https://tech.meituan.com/</a></p>\n<p>不定期更新。这是我个人认为国内互联网大厂技术博客中“干货”含量最高的。它不写虚的，全是美团在大规模、高并发业务场景下的真实实战总结。内容覆盖架构设计、AI 工程化 <em>（如 LongCat 系列模型）</em>、大数据与算法优化等。可以很好的在真实案例中提升自己的系统的思维。</p>\n<p><img src=\"https://img.markxu.icu/img20260511190239663.png\" alt=\"美团技术团队\"></p>\n<h3>Google Research</h3>\n<p><a href=\"https://research.google/blog/\">https://research.google/blog/</a></p>\n<p>Google 研究部门（现与 DeepMind 深度整合）的官方博客。这里是许多前沿技术的“源头”，如 Transformer、BERT 等奠基性技术的解读最早都出自这里。它主要发布机器学习、自然语言处理、计算机视觉及量子计算等领域的最新进展 <em>（都是一些很酷的科技😯！）</em>。虽然部分内容偏科研，但通过它的通俗博文，你能直观感受到“未来技术”的演进方向，看到这些，多少也会有些兴奋的感觉。<br>\n<img src=\"https://img.markxu.icu/img20260511191040419.png\" alt=\"Google Research\"></p>\n<hr>\n<p>上面分享的就是些我在这四年里面比较常关注的信息源，换句话说，就是我逐渐找到的神秘“小抽屉”，给我打开了许多视野，也让我的步伐不至于落后时代太多。本篇文章主要还是抛砖引玉，<strong>如果你有自己珍藏的信息源，很期待你可以在评论区进行分享！</strong></p>\n",
      "summary": "一直有搜集各种有趣的信息源的习惯，想要把我印象中高质量，经常更新且好玩好读的几个信息源记录下，留给未来的自己，也分享给大家。",
      "date_published": "2026-05-11T00:00:00.000Z",
      "image": "https://img.markxu.icu/img06bdb9ed7cc5e8.png",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/blog/mac-terminal-setup-notes-cn",
      "url": "https://markxu.icu/blog/mac-terminal-setup-notes-cn",
      "title": "配置Mac终端日记",
      "content_text": "以前为了探索和好玩，我的终端被 oh-my-zsh 和各类插件塞的满满的，都记不住已经安装哪些插件了，而且界面还丑到自己都不愿意用。最近在Bilibili上看到了ghostty 这个命令行工具，同时刷到了些美化的操作，让我很是喜欢。于是这次我决定从0开始，完整的构建并美化一下我的终端。 说起终端命令行，在我刚刚购入 Mac 并配置好环境后，我就开始使用了，对于 Raycast，Bartender 等等这类自定义的美化工具完全不知晓，更不用说以前从来没有使用习惯的命令行了。后来我哥打算教我些知识，打开我的电脑发出一声惊呼：“你的电脑怎么这么原始？\" 从那以后，我才注意到原来 Mac 的使用习惯与 Windows差别这么大 （其实 Windows 我也是以简洁为主） ，开始探索开自定义的美化效果。 混乱的开始 后面很长的一段时间，我的终端都是类似于默认情况下的样子 （忘记截图留证了） ，是那种灰色打底，只有文字的样子，也跟着网上各种视频安装了iterm2 以及 oh-my-zsh，还有一大堆插件，后来太乱要么忘记怎么使用，或者说根本用不到。虽说这个终端也可以正常使用，但常常要进行不同插件的更新，而且开启终端都要一秒多的滞后，确实很麻烦啊。 于是我决定开始重构，顺便记录下来，也为最近新购置 Mac 的同学终端配置提供一份思路。 工欲善其事，必先利其器 选择一个合适且好用的工具是我们这次重构的重点，先简单介绍下我选择的标准： 性能优先：启动时间短，渲染快。 维护成本低：开箱即用，且适合定制，而且定制路径清晰，不依赖插件堆叠。 好看：好看是第一生产力。🥰 所以我选择了以 Ghostty + 原生Zsh + Starship + Yazi 的组合，这些完全覆盖了我现在有的需求 还有些小的后面会添加上 ，其他的插件在这么长的时间内我都没有用到过，所以安装oh-my-zsh目前的意义也不大，可以看这篇文章，里面也是这个思想。 接下来我来介绍下这几个软件吧 Ghostty：终端模拟器 官方回答： Ghostty is a fast, feature-rich, and cross-platform terminal emulator that uses platform-native UI and GPU acceleration. 同生态位的工具：Terminal（原装）、iTerm2、Warp、WezTerm、Alacritty、Kitty... 为什么这么多选项选择Ghostty呢？其实我是看到了 Boris Cherny 推荐的才想去试一试，结果发现这居然很适合我！ 采用的Zig编译为原生机器码，省掉了虚拟机/解释器的开销，没有GC暂停。 字符缓冲区直接映射到GPU显存，跳过了CPU中转。 启动的时候一次性解析TOML配置，没有插件热重载，大大加快了其运行的速度。而且配置都放在一个TOML里面，让他的设置也很简单明了。 使用下来，他的启动速度要快的多，而且内存占用也不算大。是一个我能想到现代终端最好的样子了。 Starship：提示符引擎 同生态位的工具：oh-my-posh 使用 Rust 编写，是编译好的程序，启动速度贼快，而且作为提示符引擎 （上皮肤） ，替换掉了我之前安装oh-my-zsh （每次启动要跑一堆shell脚本） 的主要用途，现在启动速度快了，用起来自然也就舒服了😊。 Yazi：异步文件管理器 这个其实和macOS finder差不多，只是通过键盘操作全部解决了，而且在对自己机器环境了解的情况下使用起来更舒服些。 同样是使用 Rust 编写，加载速度快，而且支持实时预览，不用再找到文件按空格查看具体内容，图片也可以预览，代替了大量的cd 和 ls，舒服许多许多。 更不用说其使用了原生的Vim键位，操作起来舒服很多，就算没有用过vim的用户，大概率上手也可以使用的七七八八，而且 ？帮助菜单很友好。 配置过程：简单的可复现操作 前提要求 安装好Homebrew （命令行应用商店？） 、Nerdfont （终端的有趣图标字体） 安装Homebrew命令 更新Homebrew 下载软件 软件配置 打开Ghostty，点击 会弹出一个toml文件，在里面可以直接复制我的内容： 现在终端应该已经很好看了 接下来是Starship,官方文档。 创建配置文件： 打开配置文件： （如果不熟悉nano或者vim的话，可以安装vscode使用code + 地址进行打开，这样有图形化界面） 我的配置： 如果你想要别的主题，可以用下这个命令查看其支持的主题，如果你想要别的可以问下ai怎么办 运行后会列出一组可选预设，比如 、 、 等等。 选中安装 最后就是配置一下Zsh了，建议直接复制到后面，不要覆盖 （因为里面包含了conda环境，node环境等等，可以考虑先问下ai） 验证阶段 如果你有安装vscode 如果你有安装vscode等编译器，想要在里面也使用正常的终端，但是却看到很多奇异字符，那是由于字体不对导致的。可以打开设置，搜索 然后输入 即可。 这样你就完成了一个美观又实用的终端了！ 为什么这值得花时间 终端不仅仅是工具，更是开发者每天面对最长时间的工作台，更不用说现在vibe coding盛行的情况下，终端的使用越来越多。如果配置得当的话，会让你的整个思路都更清晰明了。 Ghostty: 官网 GitHub Starship: 官网 GitHub Yazi: 官网 GitHub 💡 本文配置基于以下版本验证： Ghostty 1.3.1 stable Starship 1.24.2 Yazi 0.3.0 不同版本配置语法可能有差异，如遇问题请先查看官网确认版本。",
      "content_html": "<p>以前为了探索和好玩，我的终端被 oh-my-zsh 和各类插件塞的满满的，都记不住已经安装哪些插件了，而且界面还丑到自己都不愿意用。最近在Bilibili上看到了ghostty 这个命令行工具，同时刷到了些美化的操作，让我很是喜欢。于是这次我决定从0开始，完整的构建并美化一下我的终端。</p>\n<hr>\n<p>说起终端命令行，在我刚刚购入 Mac 并配置好环境后，我就开始使用了，对于 Raycast，Bartender 等等这类自定义的美化工具完全不知晓，更不用说以前从来没有使用习惯的命令行了。后来我哥打算教我些知识，打开我的电脑发出一声惊呼：“你的电脑怎么这么原始？&quot; 从那以后，我才注意到原来 Mac 的使用习惯与 Windows差别这么大 <em>（其实 Windows 我也是以简洁为主）</em>，开始探索开自定义的美化效果。</p>\n<h2>混乱的开始</h2>\n<p>后面很长的一段时间，我的终端都是类似于默认情况下的样子  <em>（忘记截图留证了）</em>，是那种灰色打底，只有文字的样子，也跟着网上各种视频安装了iterm2 以及 oh-my-zsh，还有一大堆插件，后来太乱要么忘记怎么使用，或者说根本用不到。虽说这个终端也可以正常使用，但常常要进行不同插件的更新，而且开启终端都要一秒多的滞后，确实很麻烦啊。</p>\n<p>于是我决定开始重构，顺便记录下来，也为最近新购置 Mac 的同学终端配置提供一份思路。</p>\n<h2>工欲善其事，必先利其器</h2>\n<p>选择一个合适且好用的工具是我们这次重构的重点，先简单介绍下我选择的标准：</p>\n<ol>\n<li>性能优先：启动时间短，渲染快。</li>\n<li>维护成本低：开箱即用，且适合定制，而且定制路径清晰，不依赖插件堆叠。</li>\n<li>好看：好看是第一生产力。🥰</li>\n</ol>\n<p>所以我选择了以 Ghostty + 原生Zsh + Starship + Yazi 的组合，这些完全覆盖了我现在有的需求  <em>(还有些小的后面会添加上)</em>，其他的插件在这么长的时间内我都没有用到过，所以安装oh-my-zsh目前的意义也不大，可以看<a href=\"https://thevaluable.dev/zsh-install-configure-mouseless/\">这篇文章</a>，里面也是这个思想。</p>\n<p>接下来我来介绍下这几个软件吧</p>\n<h3>Ghostty：终端模拟器</h3>\n<p><a href=\"https://ghostty.org/docs\">官方回答：</a></p>\n<blockquote>\n<p>Ghostty is a fast, feature-rich, and cross-platform terminal emulator that uses platform-native UI and GPU acceleration.</p>\n</blockquote>\n<p>同生态位的工具：Terminal（原装）、iTerm2、Warp、WezTerm、Alacritty、Kitty...</p>\n<p>为什么这么多选项选择Ghostty呢？其实我是看到了 <a href=\"https://x.com/bcherny/status/2017742753971769626\">Boris Cherny 推荐的</a>才想去试一试，结果发现这居然很适合我！</p>\n<p><img src=\"https://img.markxu.icu/imgBorisRecommendGhostty.png\" alt=\"Boris Cherny 推荐\"></p>\n<ul>\n<li>采用的Zig编译为原生机器码，省掉了虚拟机/解释器的开销，没有GC暂停。</li>\n<li>字符缓冲区直接映射到GPU显存，跳过了CPU中转。</li>\n<li>启动的时候一次性解析TOML配置，没有插件热重载，大大加快了其运行的速度。而且配置都放在一个TOML里面，让他的设置也很简单明了。</li>\n</ul>\n<p>使用下来，他的启动速度要快的多，而且内存占用也不算大。是一个我能想到现代终端最好的样子了。</p>\n<h3>Starship：提示符引擎</h3>\n<p>同生态位的工具：oh-my-posh</p>\n<p>使用 Rust 编写，是编译好的程序，启动速度贼快，而且作为提示符引擎 <em>（上皮肤）</em>，替换掉了我之前安装oh-my-zsh <em>（每次启动要跑一堆shell脚本）</em> 的主要用途，现在启动速度快了，用起来自然也就舒服了😊。</p>\n<h3>Yazi：异步文件管理器</h3>\n<p>这个其实和macOS finder差不多，只是通过键盘操作全部解决了，而且在对自己机器环境了解的情况下使用起来更舒服些。</p>\n<p>同样是使用 Rust 编写，加载速度快，而且支持实时预览，不用再找到文件按空格查看具体内容，图片也可以预览，代替了大量的cd 和 ls，舒服许多许多。</p>\n<p><img src=\"https://img.markxu.icu/imgyazi.png\" alt=\"Yazi预览效果真的很好\"></p>\n<p>更不用说其使用了原生的Vim键位，操作起来舒服很多，就算没有用过vim的用户，大概率上手也可以使用的七七八八，而且 ？帮助菜单很友好。</p>\n<h2>配置过程：简单的可复现操作</h2>\n<h3>前提要求</h3>\n<p>安装好Homebrew <em>（命令行应用商店？）</em>、Nerdfont <em>（终端的有趣图标字体）</em></p>\n<p>安装Homebrew命令</p>\n<pre><code class=\"language-Bash\">/bin/bash -c &quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)&quot;\n</code></pre>\n<p>更新Homebrew</p>\n<pre><code class=\"language-Bash\">brew update\n</code></pre>\n<h3>下载软件</h3>\n<pre><code class=\"language-Bash\"># 字体\nbrew install --cask font-jetbrains-mono-nerd-font\n\n# 终端模拟器\nbrew install --cask ghostty\n\n# 提示符引擎\nbrew install starship\n\n# 文件管理器 + 预览依赖\nbrew install yazi ffmpegthumbnailer sevenzip poppler jq fd ripgrep fzf\n\n#其他使用工具\n#命令自动建议+高亮\nbrew install zsh-autosuggestions zsh-syntax-highlighting\n</code></pre>\n<h3>软件配置</h3>\n<p>打开Ghostty，点击 <code>command + ，</code> 会弹出一个toml文件，在里面可以直接复制我的内容：</p>\n<pre><code class=\"language-toml\"># ===== 字体设置（必须！） =====\nfont-family = JetBrainsMono Nerd Font\nfont-size = 14\n\n# ===== 窗口大小 =====\nwindow-padding-x = 12\nwindow-padding-y = 12\n\n# ===== 指针模式为block，可以替换 =====\ncursor-style = block\nscrollback-limit = 10000\ncopy-on-select = true\n\n# ===== 我觉得好看的主题 =====\ntheme = Catppuccin Mocha\n\n# ===== 快捷按钮，cmd加数字前面的波浪线触发 =====\nkeybind = cmd+`=toggle_quick_terminal\n</code></pre>\n<p>现在终端应该已经很好看了</p>\n<p>接下来是Starship,<a href=\"https://starship.rs/config/#:~:text=To%20get%20started%20configuring%20starship%2C\">官方文档</a>。</p>\n<p>创建配置文件：</p>\n<pre><code class=\"language-Bash\">mkdir -p ~/.config &amp;&amp; touch ~/.config/starship.toml\n</code></pre>\n<p>打开配置文件：<br>\n（如果不熟悉nano或者vim的话，可以安装vscode使用code + 地址进行打开，这样有图形化界面）</p>\n<pre><code class=\"language-Bash\">nano ~/.config/starship.toml\n</code></pre>\n<p>我的配置：</p>\n<pre><code class=\"language-toml\">&quot;$schema&quot; = 'https://starship.rs/config-schema.json'\n\nformat = &quot;&quot;&quot;\n[](red)\\\n$os\\\n$username\\\n[](bg:peach fg:red)\\\n$directory\\\n[](bg:yellow fg:peach)\\\n$git_branch\\\n$git_status\\\n[](fg:yellow bg:green)\\\n$c\\\n$rust\\\n$golang\\\n$nodejs\\\n$php\\\n$java\\\n$kotlin\\\n$haskell\\\n$python\\\n[](fg:green bg:sapphire)\\\n$conda\\\n[](fg:sapphire bg:lavender)\\\n$time\\\n[ ](fg:lavender)\\\n$cmd_duration\\\n$line_break\\\n$character&quot;&quot;&quot;\n\npalette = 'catppuccin_mocha'\n\n[os]\ndisabled = false\nstyle = &quot;bg:red fg:crust&quot;\n\n[os.symbols]\nWindows = &quot;&quot;\nUbuntu = &quot;󰕈&quot;\nSUSE = &quot;&quot;\nRaspbian = &quot;󰐿&quot;\nMint = &quot;󰣭&quot;\nMacos = &quot;󰀵&quot;\nManjaro = &quot;&quot;\nLinux = &quot;󰌽&quot;\nGentoo = &quot;󰣨&quot;\nFedora = &quot;󰣛&quot;\nAlpine = &quot;&quot;\nAmazon = &quot;&quot;\nAndroid = &quot;&quot;\nAOSC = &quot;&quot;\nArch = &quot;󰣇&quot;\nArtix = &quot;󰣇&quot;\nCentOS = &quot;&quot;\nDebian = &quot;󰣚&quot;\nRedhat = &quot;󱄛&quot;\nRedHatEnterprise = &quot;󱄛&quot;\n\n[username]\nshow_always = true\nstyle_user = &quot;bg:red fg:crust&quot;\nstyle_root = &quot;bg:red fg:crust&quot;\nformat = '[ $user]($style)'\n\n[directory]\nstyle = &quot;bg:peach fg:crust&quot;\nformat = &quot;[ $path ]($style)&quot;\ntruncation_length = 3\ntruncation_symbol = &quot;…/&quot;\n\n[directory.substitutions]\n&quot;Documents&quot; = &quot;󰈙 &quot;\n&quot;Downloads&quot; = &quot; &quot;\n&quot;Music&quot; = &quot;󰝚 &quot;\n&quot;Pictures&quot; = &quot; &quot;\n&quot;Developer&quot; = &quot;󰲋 &quot;\n\n[git_branch]\nsymbol = &quot;&quot;\nstyle = &quot;bg:yellow&quot;\nformat = '[[ $symbol $branch ](fg:crust bg:yellow)]($style)'\n\n[git_status]\nstyle = &quot;bg:yellow&quot;\nformat = '[[($all_status$ahead_behind )](fg:crust bg:yellow)]($style)'\n\n[nodejs]\nsymbol = &quot;&quot;\nstyle = &quot;bg:green&quot;\nformat = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'\n\n[c]\nsymbol = &quot; &quot;\nstyle = &quot;bg:green&quot;\nformat = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'\n\n[rust]\nsymbol = &quot;&quot;\nstyle = &quot;bg:green&quot;\nformat = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'\n\n[golang]\nsymbol = &quot;&quot;\nstyle = &quot;bg:green&quot;\nformat = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'\n\n[php]\nsymbol = &quot;&quot;\nstyle = &quot;bg:green&quot;\nformat = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'\n\n[java]\nsymbol = &quot; &quot;\nstyle = &quot;bg:green&quot;\nformat = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'\n\n[kotlin]\nsymbol = &quot;&quot;\nstyle = &quot;bg:green&quot;\nformat = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'\n\n[haskell]\nsymbol = &quot;&quot;\nstyle = &quot;bg:green&quot;\nformat = '[[ $symbol( $version) ](fg:crust bg:green)]($style)'\n\n[python]\nsymbol = &quot;&quot;\nstyle = &quot;bg:green&quot;\nformat = '[[ $symbol( $version)(\\(#$virtualenv\\)) ](fg:crust bg:green)]($style)'\n\n[docker_context]\nsymbol = &quot;&quot;\nstyle = &quot;bg:sapphire&quot;\nformat = '[[ $symbol( $context) ](fg:crust bg:sapphire)]($style)'\n\n[conda]\nsymbol = &quot;  &quot;\nstyle = &quot;fg:crust bg:sapphire&quot;\nformat = '[$symbol$environment ]($style)'\nignore_base = false\n\n[time]\ndisabled = false\ntime_format = &quot;%R&quot;\nstyle = &quot;bg:lavender&quot;\nformat = '[[  $time ](fg:crust bg:lavender)]($style)'\n\n[line_break]\ndisabled = true\n\n[character]\ndisabled = false\nsuccess_symbol = '[❯](bold fg:green)'\nerror_symbol = '[❯](bold fg:red)'\nvimcmd_symbol = '[❮](bold fg:green)'\nvimcmd_replace_one_symbol = '[❮](bold fg:lavender)'\nvimcmd_replace_symbol = '[❮](bold fg:lavender)'\nvimcmd_visual_symbol = '[❮](bold fg:yellow)'\n\n[cmd_duration]\nshow_milliseconds = true\nformat = &quot; in $duration &quot;\nstyle = &quot;bg:lavender&quot;\ndisabled = false\nshow_notifications = true\nmin_time_to_notify = 45000\n\n[palettes.catppuccin_mocha]\nrosewater = &quot;#f5e0dc&quot;\nflamingo = &quot;#f2cdcd&quot;\npink = &quot;#f5c2e7&quot;\nmauve = &quot;#cba6f7&quot;\nred = &quot;#f38ba8&quot;\nmaroon = &quot;#eba0ac&quot;\npeach = &quot;#fab387&quot;\nyellow = &quot;#f9e2af&quot;\ngreen = &quot;#a6e3a1&quot;\nteal = &quot;#94e2d5&quot;\nsky = &quot;#89dceb&quot;\nsapphire = &quot;#74c7ec&quot;\nblue = &quot;#89b4fa&quot;\nlavender = &quot;#b4befe&quot;\ntext = &quot;#cdd6f4&quot;\nsubtext1 = &quot;#bac2de&quot;\nsubtext0 = &quot;#a6adc8&quot;\noverlay2 = &quot;#9399b2&quot;\noverlay1 = &quot;#7f849c&quot;\noverlay0 = &quot;#6c7086&quot;\nsurface2 = &quot;#585b70&quot;\nsurface1 = &quot;#45475a&quot;\nsurface0 = &quot;#313244&quot;\nbase = &quot;#1e1e2e&quot;\nmantle = &quot;#181825&quot;\ncrust = &quot;#11111b&quot;\n\n[palettes.catppuccin_frappe]\nrosewater = &quot;#f2d5cf&quot;\nflamingo = &quot;#eebebe&quot;\npink = &quot;#f4b8e4&quot;\nmauve = &quot;#ca9ee6&quot;\nred = &quot;#e78284&quot;\nmaroon = &quot;#ea999c&quot;\npeach = &quot;#ef9f76&quot;\nyellow = &quot;#e5c890&quot;\ngreen = &quot;#a6d189&quot;\nteal = &quot;#81c8be&quot;\nsky = &quot;#99d1db&quot;\nsapphire = &quot;#85c1dc&quot;\nblue = &quot;#8caaee&quot;\nlavender = &quot;#babbf1&quot;\ntext = &quot;#c6d0f5&quot;\nsubtext1 = &quot;#b5bfe2&quot;\nsubtext0 = &quot;#a5adce&quot;\noverlay2 = &quot;#949cbb&quot;\noverlay1 = &quot;#838ba7&quot;\noverlay0 = &quot;#737994&quot;\nsurface2 = &quot;#626880&quot;\nsurface1 = &quot;#51576d&quot;\nsurface0 = &quot;#414559&quot;\nbase = &quot;#303446&quot;\nmantle = &quot;#292c3c&quot;\ncrust = &quot;#232634&quot;\n\n[palettes.catppuccin_latte]\nrosewater = &quot;#dc8a78&quot;\nflamingo = &quot;#dd7878&quot;\npink = &quot;#ea76cb&quot;\nmauve = &quot;#8839ef&quot;\nred = &quot;#d20f39&quot;\nmaroon = &quot;#e64553&quot;\npeach = &quot;#fe640b&quot;\nyellow = &quot;#df8e1d&quot;\ngreen = &quot;#40a02b&quot;\nteal = &quot;#179299&quot;\nsky = &quot;#04a5e5&quot;\nsapphire = &quot;#209fb5&quot;\nblue = &quot;#1e66f5&quot;\nlavender = &quot;#7287fd&quot;\ntext = &quot;#4c4f69&quot;\nsubtext1 = &quot;#5c5f77&quot;\nsubtext0 = &quot;#6c6f85&quot;\noverlay2 = &quot;#7c7f93&quot;\noverlay1 = &quot;#8c8fa1&quot;\noverlay0 = &quot;#9ca0b0&quot;\nsurface2 = &quot;#acb0be&quot;\nsurface1 = &quot;#bcc0cc&quot;\nsurface0 = &quot;#ccd0da&quot;\nbase = &quot;#eff1f5&quot;\nmantle = &quot;#e6e9ef&quot;\ncrust = &quot;#dce0e8&quot;\n\n[palettes.catppuccin_macchiato]\nrosewater = &quot;#f4dbd6&quot;\nflamingo = &quot;#f0c6c6&quot;\npink = &quot;#f5bde6&quot;\nmauve = &quot;#c6a0f6&quot;\nred = &quot;#ed8796&quot;\nmaroon = &quot;#ee99a0&quot;\npeach = &quot;#f5a97f&quot;\nyellow = &quot;#eed49f&quot;\ngreen = &quot;#a6da95&quot;\nteal = &quot;#8bd5ca&quot;\nsky = &quot;#91d7e3&quot;\nsapphire = &quot;#7dc4e4&quot;\nblue = &quot;#8aadf4&quot;\nlavender = &quot;#b7bdf8&quot;\ntext = &quot;#cad3f5&quot;\nsubtext1 = &quot;#b8c0e0&quot;\nsubtext0 = &quot;#a5adcb&quot;\noverlay2 = &quot;#939ab7&quot;\noverlay1 = &quot;#8087a2&quot;\noverlay0 = &quot;#6e738d&quot;\nsurface2 = &quot;#5b6078&quot;\nsurface1 = &quot;#494d64&quot;\nsurface0 = &quot;#363a4f&quot;\nbase = &quot;#24273a&quot;\nmantle = &quot;#1e2030&quot;\ncrust = &quot;#181926&quot;\n</code></pre>\n<p>如果你想要别的主题，可以用下这个命令查看其支持的主题，如果你想要别的可以问下ai怎么办</p>\n<pre><code class=\"language-Bash\">starship preset --list\n</code></pre>\n<p>运行后会列出一组可选预设，比如 <code>bracketed-segments</code>、<code>catppuccin-powerline</code>、<code>tokyo-night</code> 等等。</p>\n<p>选中安装</p>\n<pre><code class=\"language-Bash\">starship preset tokyo-night &gt; ~/.config/starship.toml\n</code></pre>\n<p>最后就是配置一下Zsh了，建议直接复制到后面，不要覆盖  <em>（因为里面包含了conda环境，node环境等等，可以考虑先问下ai）</em></p>\n<pre><code class=\"language-Bash\">nano ~/.zshrc\n</code></pre>\n<pre><code class=\"language-Bash\"># ===== Homebrew: macOS 包管理器=====\nexport PATH=&quot;/opt/homebrew/bin:$PATH&quot;\n\n# ===== Starship ======\neval &quot;$(starship init zsh)&quot;\n\n# ===== 自动补全 ======\nautoload -Uz compinit &amp;&amp; compinit\n\n# ===== Yazi（终端文件管理器）=====\nfunction y() {\n  local tmp=&quot;$(mktemp -t &quot;yazi-cwd.XXXXXX&quot;)&quot; cwd\n  yazi &quot;$@&quot; --cwd-file=&quot;$tmp&quot;\n  if cwd=&quot;$(command cat -- &quot;$tmp&quot;)&quot; &amp;&amp; [ -n &quot;$cwd&quot; ] &amp;&amp; [ &quot;$cwd&quot; != &quot;$PWD&quot; ]; then\n    builtin cd -- &quot;$cwd&quot;\n  fi\n  rm -f -- &quot;$tmp&quot;\n}\n\n# yy 是 yazi 的快捷命令\nalias yy=&quot;y&quot;\n\n#=====Zsh Autosuggestions =====\nsource /opt/homebrew/share/zsh-autosuggestions/zsh-autosuggestions.zsh\n\n# ===== Zsh Syntax Highlighting =====\nsource /opt/homebrew/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh\n\n</code></pre>\n<h3>验证阶段</h3>\n<pre><code class=\"language-Bash\">exec zsh\n</code></pre>\n<h3>如果你有安装vscode</h3>\n<p>如果你有安装vscode等编译器，想要在里面也使用正常的终端，但是却看到很多奇异字符，那是由于字体不对导致的。可以打开设置，搜索 <code>terminal font</code> 然后输入 <code>JetBrainsMono Nerd Font</code>即可。</p>\n<p>这样你就完成了一个美观又实用的终端了！</p>\n<h2>为什么这值得花时间</h2>\n<p><img src=\"https://img.markxu.icu/imgfinalshowTerminal.png\" alt=\"最后可以配置出来的结果\"></p>\n<p>终端不仅仅是工具，更是开发者每天面对最长时间的工作台，更不用说现在vibe coding盛行的情况下，终端的使用越来越多。如果配置得当的话，会让你的整个思路都更清晰明了。</p>\n<ul>\n<li>Ghostty: <a href=\"https://ghostty.org\">官网</a> | <a href=\"https://github.com/ghostty-org/ghostty\">GitHub</a></li>\n<li>Starship: <a href=\"https://starship.rs\">官网</a> | <a href=\"https://github.com/starship/starship\">GitHub</a></li>\n<li>Yazi: <a href=\"https://yazi-rs.github.io\">官网</a> | <a href=\"https://github.com/sxyazi/yazi\">GitHub</a></li>\n</ul>\n<blockquote>\n<p>💡 本文配置基于以下版本验证：</p>\n<ul>\n<li>Ghostty 1.3.1 (stable)</li>\n<li>Starship 1.24.2</li>\n<li>Yazi 0.3.0<br>\n不同版本配置语法可能有差异，如遇问题请先查看官网确认版本。</li>\n</ul>\n</blockquote>\n",
      "summary": "我以前的终端被 oh-my-zsh 和各类插件塞的满满的，界面还丑到自己都不愿意用。所以这次我打算从0开始，完整的重新构建一下我的终端。",
      "date_published": "2026-04-07T00:00:00.000Z",
      "image": "https://img.markxu.icu/img4d29eab0f1dc8.jpeg",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/blog/prompt-only-open-source-cn",
      "url": "https://markxu.icu/blog/prompt-only-open-source-cn",
      "title": "当开源只剩下一段 Prompt：我发现了一种“离谱”的开源方式",
      "content_text": "最近在 GitHub 上闲逛，看到了一个另我感到些许震撼又好笑的项目： voice-input-src 。一个为Mac而生的语音输入插件。打开代码仓库你会发现，里面根本没有我们传统认知中的 Swift 这类的具体代码，只有一段写给 AI（Claude）的，极其详细的包含中英文两种的一段 Prompt。 我开始好奇： 这种开源的方式真的有效嘛？这样开源用户做出来的东西真的能用吗？ 刚好我也有一个Macbook，便想着在我的 Mac 上尝试复现一下，验证下这个开源模式的可行性。 项目解构：这真的是“源码”吗？ 1. 极简的仓库结构 README.md ：项目说明里面包含了所需的 Prompt 文本，再无其他。 不得不说，这种开源方式真的很方便理解项目😂。 2. Prompt 即源码（哈哈哈） 传统的开源是“人读代码，编译器执行”，而这个项目是“人读Prompt，AI 执行”。作者 yetone 甚至专门建立了一个 voice-input-dist的repo 来存放他利用ai最终构建出的 App源码，以方便将“源”与“产物”彻底分离 （小巧思说是） ，也方便用户进行对比。 Prompt 里藏了什么？ 仔细看这个项目，我们能探索的只有这一端prompt，为了尝试后续的复现，我分析了下这段 Prompt 。这不是一个程序小白随手写出来的需求文档，告诉ai我需要什么样的软件，而是一个对 macOS 底层 API 有精准的调用要求的程序员所构建出来的文档： 模块 实现细节 -------------------- -------------------------------------------------------------------------------------------- 语音识别 使用 Apple Speech Recognition 框架，支持流式转录（边听边说），默认中文。 全局热键 监听 Fn 键（需全局事件监听 CGEvent tap），并 抑制默认行为 （防止弹出 emoji 面板）。 悬浮窗 UI 无边框 NSPanel、视觉模糊效果、 实时波形动画 （基于音频 RMS 驱动，非假动画）。 输入法兼容 检测当前输入法，粘贴前自动切换至 ABC 键盘（防 Cmd+V 拦截），粘贴后恢复。 LLM 后处理 调用 OpenAI 兼容 API 进行纠错（仅修正明显错误，如“配森”- “Python”）。 从上面具体的专业术语可以看出作者在写这段 prompt 的时候，清晰的知道需要调用什么框架，有什么组件可以去使用，后续会遇到什么冲突问题，又应该如何去解决。因为作者足够了解相关的技术知识和实现难题，才可以这样精准的写出整个项目的完整 prompt。甚至有Github上issue的留言： 这玩意才是真正的 prompt 开发教程 我的复现 On My Mac 为了真的去验证下这种开源是否真的有效，也体验下这种有点逆天的prompt engineer，我在我的 Mac 上进行一次“从 Prompt 到 App”的完整实验。 1. 环境 Mac ：我的2021款的 M1 pro，系统是Tahoe 26.3.1 AI 工具 ：Codex，调用的是GPT 5.4 Extra High （想要试试与作者不一样的ai能否成功） 。 下面是我的设备配置图： 2. 具体步骤 Prompt 投喂 ：将仓库中的完整 Prompt 发送给 Codex。 功能验收测试 ：（才不是因为我不太会Swift才不去读源码） 功能检查： x Fn 键是否能稳定录音且不弹 emoji？ x 悬浮窗波形是否随音量实时变化？ x 中文识别准确率如何？LLM 纠错是否生效？ 3.具体实现： 其实在我这里并没有一次就生成成功，让程序可以正确的build出来，第一次完整的构建花了大概 23min ，花了 $1.3994 （USD）,后面有两个小问题在运行的时候出现了报错， 于是我接着让codex进行了两次修复，加上修复一共花了 $1.9734（USD）。 下面是codex对于这两次修复内容的简单概括： 这两次修复，本质上分别解决了一个“编译期问题”和一个“运行期崩溃问题”。 第一处是 PasteboardInjector.swift line 18 的修复。那里原来写法里，pasteboard.pasteboardItems?.map { ... } ?? 这个表达式要靠 Swift 自己推断 items 的类型。在某些情况下，编译器会对这个可选链加空数组兜底的写法推断不稳定，最后在 return PasteboardBackup items: items 这一行报错。修复方式很简单，就是把 items 明确写成 Item 。这样做没有改变任何业务逻辑，只是把“你自己猜类型”改成了“我明确告诉你类型”，让编译器稳定通过。 第二处是 FloatingPanelController.swift line 93 的修复。这里原来给 NSPanel 设置了 collectionBehavior = .canJoinAllSpaces, .fullScreenAuxiliary, .moveToActiveSpace, .ignoresCycle 。问题在于，.canJoinAllSpaces 和 .moveToActiveSpace 这两个行为语义上是冲突的：一个强调“加入所有 Space”，另一个强调“跟随当前活跃 Space 移动”。AppKit 对这类窗口行为组合比较敏感，有时会直接触发断言，最终表现成 abort signal 崩溃。修复后我把它改成了更稳妥的组合：保留 .moveToActiveSpace、.fullScreenAuxiliary、.ignoresCycle，再加上 .transient，去掉 .canJoinAllSpaces。这样浮窗依然能在当前空间和全屏应用旁边正常显示，但不会再因为窗口行为冲突而在初始化时崩掉。 效果展示 其实你们应该能想到，这整篇文章就是我用这个软件进行转述的，效果还蛮不错的。而且出字很快，比苹果原装带有的语音输入要反馈更加及时，而且调用也方便些。 具体的效果正如现在： 说到其具体缺点，可以看到我们的字没有居中有些难受，后续通过codex进行提示也修复了。总体看下来也不如作者使用claude做出来的效果要好，但是至少能用，不是吗？ 这是否是开源的未来（哪怕是部分），还是只是一次恶搞？ 1. 积极视角：极致的 DRY Don't Repeat Yourself 维护成本极低 ：作者无需关心 Xcode 版本升级、Swift 语法迭代，只需提供一份“要求文档”。 可复现性 ：只要 AI 模型能力在线，任何人在任何时间都能生成出功能一致的 App。 分享便捷 ：这样的分享干脆直接，比分享一个纯vibe出来的一大堆代码库相比起来或许还要好些。 2. 略微消极的视角：（不是那种俗套的说辞） 不可控性 ：生成的代码质量高度依赖 AI 的“心情”，难以确保每一次生成的效果一致，比如我的Codex的版本虽然可用，但确实不如作者的演示好看。 不方便操作 ：如果要生成代码，还是得确保用户本身有AI环境，而且有足够的资金配置，这种项目比较小还好说，如果是较大的项目的话就比较贵了。而且需要用户等待其结果生成，并不如直接下载作者发布的release。 总的来说，我认为这一次尝试不是件坏事，相反作者特别具有创意的repo发布方式还带给了我点小小的震撼。其实可以把这次看作一个更好的AI教程，而不是具体实现项目的方式，因为如果想要达到作者这样的prompt的话,还是需要一定的功底和基础知识。不说高手的情况，单论我自己，是无法做到一次性就写出像作者这么完美的提示词的。 如果大家有空闲的话也推荐大家都去试一试！😉",
      "content_html": "<p>最近在 GitHub 上闲逛，看到了一个另我感到些许震撼又好笑的项目： <strong><a href=\"https://github.com/yetone/voice-input-src?tab=readme-ov-file\">voice-input-src</a></strong> 。一个为Mac而生的语音输入插件。打开代码仓库你会发现，里面根本没有我们传统认知中的 Swift 这类的具体代码，只有一段写给 AI（Claude）的，极其详细的包含中英文两种的一段 Prompt。</p>\n<p>我开始好奇：<strong>这种开源的方式真的有效嘛？这样开源用户做出来的东西真的能用吗？</strong> 刚好我也有一个Macbook，便想着在我的 Mac 上尝试复现一下，验证下这个开源模式的可行性。</p>\n<hr>\n<h2>项目解构：这真的是“源码”吗？</h2>\n<h3><strong>1. 极简的仓库结构</strong></h3>\n<p><strong><a href=\"http://README.md\">README.md</a></strong> ：项目说明里面包含了所需的<strong>Prompt 文本，再无其他。</strong></p>\n<p><img src=\"https://img.markxu.icu/imgvoiceInputRepo.png\" alt=\"项目仓库\"></p>\n<p>不得不说，这种开源方式真的很方便理解项目😂。</p>\n<h3><strong>2. Prompt 即源码（哈哈哈）</strong></h3>\n<p>传统的开源是“人读代码，编译器执行”，而这个项目是“人读Prompt，AI 执行”。作者 yetone 甚至专门建立了一个 <a href=\"https://github.com/yetone/voice-input-dist\">voice-input-dist的repo</a> 来存放他利用ai最终构建出的 App源码，以方便将“源”与“产物”彻底分离 <em>（小巧思说是）</em>，也方便用户进行对比。</p>\n<h2>Prompt 里藏了什么？</h2>\n<p>仔细看这个项目，我们能探索的只有这一端prompt，为了尝试后续的复现，我分析了下这段 Prompt 。这不是一个程序小白随手写出来的需求文档，告诉ai我需要什么样的软件，而是一个对 macOS 底层 API 有精准的调用要求的程序员所构建出来的文档：</p>\n<table>\n<thead>\n<tr>\n<th>模块</th>\n<th>实现细节</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><strong>语音识别</strong></td>\n<td>使用 Apple Speech Recognition 框架，支持流式转录（边听边说），默认中文。</td>\n</tr>\n<tr>\n<td><strong>全局热键</strong></td>\n<td>监听 Fn 键（需全局事件监听 CGEvent tap），并<strong>抑制默认行为</strong> （防止弹出 emoji 面板）。</td>\n</tr>\n<tr>\n<td><strong>悬浮窗 UI</strong></td>\n<td>无边框 NSPanel、视觉模糊效果、<strong>实时波形动画</strong> （基于音频 RMS 驱动，非假动画）。</td>\n</tr>\n<tr>\n<td><strong>输入法兼容</strong></td>\n<td>检测当前输入法，粘贴前自动切换至 ABC 键盘（防 Cmd+V 拦截），粘贴后恢复。</td>\n</tr>\n<tr>\n<td><strong>LLM 后处理</strong></td>\n<td>调用 OpenAI 兼容 API 进行纠错（仅修正明显错误，如“配森”-&gt;“Python”）。</td>\n</tr>\n</tbody>\n</table>\n<p>从上面具体的专业术语可以看出作者在写这段 prompt 的时候，清晰的知道需要调用什么框架，有什么组件可以去使用，后续会遇到什么冲突问题，又应该如何去解决。因为作者足够了解相关的技术知识和实现难题，才可以这样精准的写出整个项目的完整 prompt。甚至有Github上issue的留言：</p>\n<blockquote>\n<p>这玩意才是真正的 prompt 开发教程</p>\n</blockquote>\n<h2>我的复现 (On My Mac)</h2>\n<p>为了真的去验证下这种开源是否真的有效，也体验下这种有点逆天的prompt engineer，我在我的 Mac 上进行一次“从 Prompt 到 App”的完整实验。</p>\n<h3><strong>1. 环境</strong></h3>\n<ul>\n<li><strong>Mac</strong> ：我的2021款的 M1 pro，系统是Tahoe 26.3.1</li>\n<li><strong>AI 工具</strong> ：Codex，调用的是GPT 5.4 Extra High <em>（想要试试与作者不一样的ai能否成功）</em>。</li>\n</ul>\n<p>下面是我的设备配置图：</p>\n<p><img src=\"https://img.markxu.icu/imgComputerConfig.png\" alt=\"我的电脑配置\"></p>\n<h3><strong>2. 具体步骤</strong></h3>\n<ol>\n<li><strong>Prompt 投喂</strong> ：将仓库中的完整 Prompt 发送给 Codex。</li>\n<li><strong>功能验收测试</strong> ：（才不是因为我不太会Swift才不去读源码）</li>\n</ol>\n<p>功能检查：</p>\n<ul>\n<li>[x] Fn 键是否能稳定录音且不弹 emoji？</li>\n<li>[x] 悬浮窗波形是否随音量实时变化？</li>\n<li>[x] 中文识别准确率如何？LLM 纠错是否生效？</li>\n</ul>\n<p><img src=\"https://img.markxu.icu/imgSendItToCodex.png\" alt=\"发给Codex的Prompt\"></p>\n<p><strong>3.具体实现：</strong><br>\n其实在我这里并没有一次就生成成功，让程序可以正确的build出来，第一次完整的构建花了大概<strong>23min</strong>，花了 <strong>$1.3994</strong>（USD）,后面有两个小问题在运行的时候出现了报错， 于是我接着让codex进行了两次修复，加上修复一共花了 $1.9734（USD）。</p>\n<p>下面是codex对于这两次修复内容的简单概括：</p>\n<blockquote>\n<p>这两次修复，本质上分别解决了一个“编译期问题”和一个“运行期崩溃问题”。</p>\n<p>第一处是 PasteboardInjector.swift (line 18) 的修复。那里原来写法里，pasteboard.pasteboardItems?.map { ... } ?? [] 这个表达式要靠 Swift 自己推断 items 的类型。在某些情况下，编译器会对这个可选链加空数组兜底的写法推断不稳定，最后在 return PasteboardBackup(items: items) 这一行报错。修复方式很简单，就是把 items 明确写成 [Item]。这样做没有改变任何业务逻辑，只是把“你自己猜类型”改成了“我明确告诉你类型”，让编译器稳定通过。</p>\n<p>第二处是 FloatingPanelController.swift (line 93) 的修复。这里原来给 NSPanel 设置了 collectionBehavior = [.canJoinAllSpaces, .fullScreenAuxiliary, .moveToActiveSpace, .ignoresCycle]。问题在于，.canJoinAllSpaces 和 .moveToActiveSpace 这两个行为语义上是冲突的：一个强调“加入所有 Space”，另一个强调“跟随当前活跃 Space 移动”。AppKit 对这类窗口行为组合比较敏感，有时会直接触发断言，最终表现成 abort signal 崩溃。修复后我把它改成了更稳妥的组合：保留 .moveToActiveSpace、.fullScreenAuxiliary、.ignoresCycle，再加上 .transient，去掉 .canJoinAllSpaces。这样浮窗依然能在当前空间和全屏应用旁边正常显示，但不会再因为窗口行为冲突而在初始化时崩掉。</p>\n</blockquote>\n<h2>效果展示</h2>\n<p>其实你们应该能想到，这整篇文章就是我用这个软件进行转述的，效果还蛮不错的。而且出字很快，比苹果原装带有的语音输入要反馈更加及时，而且调用也方便些。<br>\n具体的效果正如现在：</p>\n<p><img src=\"https://img.markxu.icu/imgAppEffect.png\" alt=\"我的效果\"></p>\n<p>说到其具体缺点，可以看到我们的字没有居中有些难受，后续通过codex进行提示也修复了。总体看下来也不如<a href=\"https://private-user-images.githubusercontent.com/1206493/570996776-3228f78a-f035-447d-98ef-8826798a122c.mp4?jwt=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NzU0ODU4NTksIm5iZiI6MTc3NTQ4NTU1OSwicGF0aCI6Ii8xMjA2NDkzLzU3MDk5Njc3Ni0zMjI4Zjc4YS1mMDM1LTQ0N2QtOThlZi04ODI2Nzk4YTEyMmMubXA0P1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUtJQVZDT0RZTFNBNTNQUUs0WkElMkYyMDI2MDQwNiUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNjA0MDZUMTQyNTU5WiZYLUFtei1FeHBpcmVzPTMwMCZYLUFtei1TaWduYXR1cmU9OWY5YTBiZjNmNDNlYmVjMThjZTkyYmVlMzhhNWE5ZGVkMDUzYjE2NTA0Y2M0NmUxYWI4ODg0NmYxMmZjMDljMSZYLUFtei1TaWduZWRIZWFkZXJzPWhvc3QifQ.hn6EDW1eCK1AOOo7I77njFUspVoIxag2_bk1BwJxfQE\">作者使用claude做出来的效果</a>要好，但是至少能用，不是吗？</p>\n<h2>这是否是开源的未来（哪怕是部分），还是只是一次恶搞？</h2>\n<p><strong>1. 积极视角：极致的 DRY (Don't Repeat Yourself)</strong></p>\n<ul>\n<li><strong>维护成本极低</strong> ：作者无需关心 Xcode 版本升级、Swift 语法迭代，只需提供一份“要求文档”。</li>\n<li><strong>可复现性</strong> ：只要 AI 模型能力在线，任何人在任何时间都能生成出功能一致的 App。</li>\n<li><strong>分享便捷</strong> ：这样的分享干脆直接，比分享一个纯vibe出来的一大堆代码库相比起来或许还要好些。</li>\n</ul>\n<p><strong>2. 略微消极的视角：（不是那种俗套的说辞）</strong></p>\n<ul>\n<li><strong>不可控性</strong> ：生成的代码质量高度依赖 AI 的“心情”，难以确保每一次生成的效果一致，比如我的Codex的版本虽然可用，但确实不如作者的演示好看。</li>\n<li><strong>不方便操作</strong> ：如果要生成代码，还是得确保用户本身有AI环境，而且有足够的资金配置，这种项目比较小还好说，如果是较大的项目的话就比较贵了。而且需要用户等待其结果生成，并不如直接下载作者发布的release。</li>\n</ul>\n<p><img src=\"https://img.markxu.icu/imgContrastBetweenMineandAuthor.png\" alt=\"我与作者的结构对比\"></p>\n<p>总的来说，我认为这一次尝试不是件坏事，相反作者特别具有创意的repo发布方式还带给了我点小小的震撼。其实可以把这次看作一个更好的AI教程，而不是具体实现项目的方式，因为如果想要达到作者这样的prompt的话,还是需要一定的功底和基础知识。不说高手的情况，单论我自己，是无法做到一次性就写出像作者这么完美的提示词的。</p>\n<p>如果大家有空闲的话也推荐大家都去试一试！😉</p>\n",
      "summary": "最近在 GitHub 上看到了一个项目：voice-input-src。一个为mac写的语音输入软件。震惊的是打开仓库你会发现只有一段写给AI的Prompt。",
      "date_published": "2026-04-05T00:00:00.000Z",
      "date_modified": "2026-04-06T00:00:00.000Z",
      "image": "https://img.markxu.icu/imgvoiceinput.jpeg",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/blog/first-blog-post-cn",
      "url": "https://markxu.icu/blog/first-blog-post-cn",
      "title": "第一篇博客",
      "content_text": "网站上线运行近30天，这才有了这个实际意义上的第一篇blog，其实是想等到初步设想的网站完全写完后再开始动笔，也是为了记录下这个小网站的开始和经过。那我们就开始吧！ 为什么要写这个个人网站? 说起个人网站，或者说是个人博客这个概念，我从小就接触过不少书籍就是由一篇篇个人的网络博客和文章缀起来的，比如说我很喜欢万维钢的《万万没想到》，就是由他的一篇篇网络日志凑起来的。从小一直认为写博客是件很酷的事情，但从来没有想到有一天自己也想去写，去记录。 从看别人的博客到写自己的博客的转变其实是一个偶然。那天在刷知乎，看到了个回答，问题是：“趁着年轻应该干些什么事？”类似于那种俗套的给年轻人建议的问题，闲着无聊便看了几篇回答。其中一篇至今令我印象深刻，大体上在说 “应该趁着年轻多留下些美好的回忆，以后就算遇到了难关，至少还有些美好的回忆撑着。” 确实如此，想起小时候爸妈给我记录的 童年照片 ，想起来都心里感觉暖暖的，那一段日子虽然我记不得了，但长久的和爸妈看录像，听他们一遍又一遍的说，让本不存在的记忆印象也深刻起来，这或许也是很多同学感叹我怎么能记得那么久远的事情的原因。 在大学这几年，我也经历了从原来按部就班的学习考试（小中高）到了自己安排生活和时间的变化。参加了很多需要合作的比赛，做出了很多不合大流的选择。有过连着几个月天天通宵改模型学习的日子，也有过说走就走，出门旅行的快活日子。认识了社会上不同年龄的，来自不同地方的朋友，同学。也开始从两耳不闻窗外事到关心社会时事变化。经历过这些，难免会想记录下自己的生活和转变。 想法止于想象，落地全靠事撞 。 我是在考研复习期间，刷到了一个个人网站，下面挂了许多友链，开始四处看些有意思的个人网站。许多都是大学生记录自己学习的心得和日常，并没有那么多像是大佬的博客网站多么有启发意义（虽然也有不少）。但仍然，我好像通过这个网站里面记录的日常认识了一个新朋友。加上自己一直就有点想法，这才下定了写网站的决心。于是考研结束后，我开始了网站的构建之路。 网站是怎么建成的？ 众所周知，网站也就是前端，ai在这个领域已经很厉害了，不仅仅是构建方便，而且看起来又好交互感又强。如果一个人还是保持古法编程，一点点的手敲出来自己的网站，放到今天，难说到底是令人仰慕还是招人嘲笑。同时，还有很多开源的博客模板（Hexo上面就有很多很漂亮的模板），如果直接套用，可以避免重复造轮子，快捷好用不说，样式还比一个人自己画的草图要精美的多。所以在网站初期，构建的时候就考虑过怎么方便，尤其是怎么使用ai方便。 整个互联网上的前端代码，react占比是最高的，这也意味着ai学习react的知识是最多的，在将来使用ai修改也就最方便。而且大二的时候，我哥让我学了些react框架，一直没有实践，其实一直想要试试。所以总体来看React确实很合适我，一个想要从头开始构建，体验react的完整开发，有自己想法的网站。 图来自eleopardsolutions 因此我开始使用了react + vite + tailwind CSS作为我的网站的基础技术栈，在自己搭完了整个框架和结构后，后面就是ai大显身手的时候了。随着网站一点一点的完善，动画不断地调整，我的初步设想的样子逐渐实现了（可以详细看我们的 时间线页 ）。后面加上Vercel 和 Cloudflare提供的免费托管和图床，我们的网站终于上线了，而且经济实惠。（具体的流程网上有很多，就不多赘述了。） 后面的计划 这个小站我已经很满意了，但是内容空空，只有壳子。因此我后续会记录下我的生活，尤其想要写一写我的大学生活。如果有人在上大学之前看到，或许可以提前吸取些我的教训，学习点我的经验？哈哈哈。 为了拓展我的小站，我还会再努力在空闲时间多去完成两个项目，或许也可以做一个项目集？又或许分享几篇我看到的好的论文，好的博客？ Who knows？ Just let everything happen！",
      "content_html": "<p>网站上线运行近30天，这才有了这个实际意义上的第一篇blog，其实是想等到初步设想的网站完全写完后再开始动笔，也是为了记录下这个小网站的开始和经过。那我们就开始吧！</p>\n<h2>为什么要写这个个人网站?</h2>\n<p>说起个人网站，或者说是个人博客这个概念，我从小就接触过不少书籍就是由一篇篇个人的网络博客和文章缀起来的，比如说我很喜欢万维钢的《万万没想到》，就是由他的一篇篇网络日志凑起来的。从小一直认为写博客是件很酷的事情，但从来没有想到有一天自己也想去写，去记录。</p>\n<p>从看别人的博客到写自己的博客的转变其实是一个偶然。那天在刷知乎，看到了个回答，问题是：“趁着年轻应该干些什么事？”类似于那种俗套的给年轻人建议的问题，闲着无聊便看了几篇回答。其中一篇至今令我印象深刻，大体上在说 <strong>“应该趁着年轻多留下些美好的回忆，以后就算遇到了难关，至少还有些美好的回忆撑着。”</strong></p>\n<p>确实如此，想起小时候爸妈给我记录的<strong>童年照片</strong>，想起来都心里感觉暖暖的，那一段日子虽然我记不得了，但长久的和爸妈看录像，听他们一遍又一遍的说，让本不存在的记忆印象也深刻起来，这或许也是很多同学感叹我怎么能记得那么久远的事情的原因。</p>\n<div class=\"img-grid-2\">\n  <img src=\"https://img.markxu.icu/img2012turtle.png\" alt=\"2012年家里养的小乌龟\" />\n  <img src=\"https://img.markxu.icu/img07cartoon.png\" alt=\"07年在爷爷家陪哥哥看数码宝贝\" />\n</div>\n<p>在大学这几年，我也经历了从原来按部就班的学习考试（小中高）到了自己安排生活和时间的变化。参加了很多需要合作的比赛，做出了很多不合大流的选择。有过连着几个月天天通宵改模型学习的日子，也有过说走就走，出门旅行的快活日子。认识了社会上不同年龄的，来自不同地方的朋友，同学。也开始从两耳不闻窗外事到关心社会时事变化。经历过这些，难免会想记录下自己的生活和转变。</p>\n<h3><strong>想法止于想象，落地全靠事撞</strong> 。</h3>\n<p>我是在考研复习期间，刷到了一个个人网站，下面挂了许多友链，开始四处看些有意思的个人网站。许多都是大学生记录自己学习的心得和日常，并没有那么多像是大佬的博客网站多么有启发意义（虽然也有不少）。但仍然，我好像通过这个网站里面记录的日常认识了一个新朋友。加上自己一直就有点想法，这才下定了写网站的决心。于是考研结束后，我开始了网站的构建之路。</p>\n<h2>网站是怎么建成的？</h2>\n<p>众所周知，网站也就是前端，ai在这个领域已经很厉害了，不仅仅是构建方便，而且看起来又好交互感又强。如果一个人还是保持古法编程，一点点的手敲出来自己的网站，放到今天，难说到底是令人仰慕还是招人嘲笑。同时，还有很多开源的博客模板（<a href=\"https://hexo.io/zh-cn/\">Hexo</a>上面就有很多很漂亮的模板），如果直接套用，可以避免重复造轮子，快捷好用不说，样式还比一个人自己画的草图要精美的多。所以在网站初期，构建的时候就考虑过怎么方便，尤其是怎么使用ai方便。</p>\n<p>整个互联网上的前端代码，<a href=\"https://gist.github.com/tkrotoff/b1caa4c3a185629299ec234d2314e190?permalink_comment_id=5072574\">react占比是最高的</a>，这也意味着ai学习react的知识是最多的，在将来使用ai修改也就最方便。而且大二的时候，我哥让我学了些react框架，一直没有实践，其实一直想要试试。所以总体来看React确实很合适我，一个想要从头开始构建，体验react的完整开发，有自己想法的网站。</p>\n<p><img src=\"https://img.markxu.icu/imgmarketshareofReactVueAngular.png\" alt=\"React市场占比\"></p>\n<p>图来自<a href=\"https://eleopardsolutions.com/react-vs-vue-vs-angular-key-differences/\">eleopardsolutions</a></p>\n<p>因此我开始使用了react + vite + tailwind CSS作为我的网站的基础技术栈，在自己搭完了整个框架和结构后，后面就是ai大显身手的时候了。随着网站一点一点的完善，动画不断地调整，我的初步设想的样子逐渐实现了（可以详细看我们的(<a href=\"https://markxu.icu/timeline\">时间线页</a>)）。后面加上Vercel 和 Cloudflare提供的免费托管和图床，我们的网站终于上线了，而且经济实惠。（具体的流程网上有很多，就不多赘述了。）</p>\n<h2>后面的计划</h2>\n<p>这个小站我已经很满意了，但是内容空空，只有壳子。因此我后续会记录下我的生活，尤其想要写一写我的大学生活。如果有人在上大学之前看到，或许可以提前吸取些我的教训，学习点我的经验？哈哈哈。</p>\n<p>为了拓展我的小站，我还会再努力在空闲时间多去完成两个项目，或许也可以做一个项目集？又或许分享几篇我看到的好的论文，好的博客？</p>\n<p><strong>Who knows？ Just let everything happen！</strong></p>\n",
      "summary": "个人网站字面意义上的第一篇博客，分享下个人感受和经历。",
      "date_published": "2026-03-24T00:00:00.000Z",
      "date_modified": "2026-03-26T00:00:00.000Z",
      "image": "https://img.markxu.icu/imgmarketshareofReactVueAngular.png",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/movies/reviews/ProjectHailMary",
      "url": "https://markxu.icu/movies/reviews/ProjectHailMary",
      "title": "挽救计划",
      "content_text": "看完爽到的电影，在我心里的科幻可以排前三的水平，让我想起一开始喜欢电影的感觉，一种处在梦中和幻想的感觉，感谢这些造梦人，也很喜欢高司令的演出😋 26-9-17日，三刷 我晚上实在是学习不动了，在B站上进行了三刷。 令我惊喜的是B站上居然是IMAX画幅版本的。又是可以爽爽看的一部片子。 我很喜欢看我曾经看过的电影，常常把一部喜欢的电影翻来覆去的看上好多遍，一是已经了解了剧情，对大脑的消耗要少不少，往往会更放松。二是每一次看我喜欢的电影，不仅可以再一次被电影的画面和剧情震撼，还可以想到第一次见到这个场面的感受。 本来想的是快速重温一遍，而且也知道这部电影后面的剧情了，有点一直期待电影爆点的感觉。但看的时候仍然十分沉浸，一点也不觉得电影前期枯燥乏味。 仔细想想，或许正是这部电影的节奏安排的好，让情绪有着连贯性，同时出色的BGM让电影始终保持着一种轻松的基调。让大家观影的时候不必时刻紧绷着。 总之这部电影真的让人感到轻松和美好，没有勾心斗角，没有主旋律，没有狗血剧情。 简单明快，或许是我对生活也追求的方向。",
      "content_html": "<p>看完爽到的电影，在我心里的科幻可以排前三的水平，让我想起一开始喜欢电影的感觉，一种处在梦中和幻想的感觉，感谢这些造梦人，也很喜欢高司令的演出😋</p>\n<hr>\n<h2>26-9-17日，三刷</h2>\n<p>我晚上实在是学习不动了，在B站上进行了三刷。</p>\n<p>令我惊喜的是B站上居然是IMAX画幅版本的。又是可以爽爽看的一部片子。</p>\n<p>我很喜欢看我曾经看过的电影，常常把一部喜欢的电影翻来覆去的看上好多遍，一是已经了解了剧情，对大脑的消耗要少不少，往往会更放松。二是每一次看我喜欢的电影，不仅可以再一次被电影的画面和剧情震撼，还可以想到第一次见到这个场面的感受。</p>\n<p><img src=\"https://image.tmdb.org/t/p/original/8EmbaG1ydsmMakFWwD0MeEudAgz.jpg\" alt=\"电影造梦\"></p>\n<p>本来想的是快速重温一遍，而且也知道这部电影后面的剧情了，有点一直期待电影爆点的感觉。但看的时候仍然十分沉浸，一点也不觉得电影前期枯燥乏味。</p>\n<p>仔细想想，或许正是这部电影的节奏安排的好，让情绪有着连贯性，同时出色的BGM让电影始终保持着一种轻松的基调。让大家观影的时候不必时刻紧绷着。</p>\n<p>总之这部电影真的让人感到轻松和美好，没有勾心斗角，没有主旋律，没有狗血剧情。</p>\n<p><strong>简单明快，或许是我对生活也追求的方向。</strong></p>\n<p><img src=\"https://image.tmdb.org/t/p/original/utqkJ3YPvRgMryVSRCTaaT9Knh8.jpg\" alt=\"轻松愉快的画面\"></p>\n",
      "summary": "看完爽到的电影，在我心里的科幻可以排前三的水平，让我想起一开始喜欢电影的感觉，一种处在梦中和幻想的感觉，感谢这些造梦人，也很喜欢高司令的演出😋",
      "date_published": "2026-03-21T00:00:00.000Z",
      "date_modified": "2026-09-19T00:00:00.000Z",
      "image": "https://image.tmdb.org/t/p/original/o8d54pvtPMYQdR5uPSYaMzKZJdB.jpg",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/movies/reviews/Nixinrensheng",
      "url": "https://markxu.icu/movies/reviews/Nixinrensheng",
      "title": "逆行人生",
      "content_text": "片子总体不错，我认为是有值4颗星的水平的，但我还是想要给结尾扣一颗星，但同时由于电影立意，再加一个，达到了一种平衡吧。 整部电影讲的就是一个中年人，由于现实的大环境经济不好而被裁掉的故事，其身份的转变，处境的尴尬，以及现金流的实际压力都展现的不错。我相信社会上或许会有不少这种类似的人生。 但电影里面很多情节会有为了增加戏剧张力而构造的情节，也有点不知道写什么好而添加上的情节，最后在想要构造一个所谓的“好结局”上，转变又颇为生硬和草率。让人容易感觉结尾这所以这样写，也是考虑到电影播出后，舆论环境的压力。这一点让故事的可信程度和代入感降低了不少。 终究沦为了一部有着理想主义但受现实限制太多的作品，显得十分拧巴。 但总的来说，社会是需要这种作品来反映社会现实和问题的，当年这部电影的上线也引起了不少关注，也掀起了一些舆论，总的来说也算是对社会有部分积极贡献。 放到现在来看，或许我们能做的不只是拍这部电影来记录这一段经济的真实场景，我们同时也可以做更多，来试图改变这个现状。",
      "content_html": "<p>片子总体不错，我认为是有值4颗星的水平的，但我还是想要给结尾扣一颗星，但同时由于电影立意，再加一个，达到了一种平衡吧。</p>\n<p>整部电影讲的就是一个中年人，由于现实的大环境经济不好而被裁掉的故事，其身份的转变，处境的尴尬，以及现金流的实际压力都展现的不错。我相信社会上或许会有不少这种类似的人生。</p>\n<p><img src=\"https://image.tmdb.org/t/p/original/fL1taHfNljQnbXTr6fbmrCnrCnt.jpg\" alt=\"共享单车坟场\"></p>\n<p>但电影里面很多情节会有为了增加戏剧张力而构造的情节，也有点不知道写什么好而添加上的情节，最后在想要构造一个所谓的“好结局”上，转变又颇为生硬和草率。让人容易感觉结尾这所以这样写，也是考虑到电影播出后，舆论环境的压力。这一点让故事的可信程度和代入感降低了不少。</p>\n<p>终究沦为了一部有着理想主义但受现实限制太多的作品，显得十分拧巴。</p>\n<p>但总的来说，社会是需要这种作品来反映社会现实和问题的，当年这部电影的上线也引起了不少关注，也掀起了一些舆论，总的来说也算是对社会有部分积极贡献。</p>\n<p>放到现在来看，或许我们能做的不只是拍这部电影来记录这一段经济的真实场景，我们同时也可以做更多，来试图改变这个现状。<br>\n<img src=\"https://image.tmdb.org/t/p/original/8lG6RQ27HnaldhdJrTmWtryAwxt.jpg\" alt=\"剧照\"></p>\n",
      "summary": "片子总体不错，我认为是有值4颗星的水平的，但我还是想要给结尾扣一颗星，但同时由于电影立意，再加一个，达到了一种平衡吧。",
      "date_published": "2026-03-18T00:00:00.000Z",
      "date_modified": "2026-09-19T00:00:00.000Z",
      "image": "https://image.tmdb.org/t/p/original/zYpdT02cJJrNaOD0I9lq30e9GY5.jpg",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/movies/reviews/Her",
      "url": "https://markxu.icu/movies/reviews/Her",
      "title": "她",
      "content_text": "来源： 看的有点沉不住气，剧情总体不多，发展的有点点慢，但同时也给观众很多的时间去沉浸在电影要表达的情感里。 我觉得本片最好的一点（也是此电影与其他相同题材有优势的一点）是主角的工作——代人写信（代替别人长时间给别人的联系对象写信，表达关心和爱），这个工作放到现实里感觉十分荒诞，会让人质疑这个工作的必要性，或者放到今天，是一个毫无“价值”的工作，容易被取代（正如本篇的ai可以取代），但这份工作代表的含义却是与本篇电影所要讨论的：一个情感如果来自ai，它是否真实（或者对于一份明知道虚假的情感），人们对它应该如何反应，这个主要讨论点相印证，形成了对比实验。 同样是虚假的情感，一个来自ai训练，一个来自真人的代写。作为情感的表达一方，一个是暂时不清楚是否是真实的情感（ai），一个是真人所共感产生的情绪和感受（信）。 收到信的人和ai的使用者做为情感接受的一方，一个体会到的是自以为是真实对方写的信（在电影中也表达了其情感十分动人，甚至出版成实体书籍），电影中的人们对此感到感动和欣赏。一个收到的是明知道对方是虚假的不存在的但却无比依赖的情感，电影中的人们对此感受也不一样，有的鄙视（男主前妻），有的并不过于关心（办公室的同事），有的体验（7000多人绝大多数都没有发展成爱情），有的则像男主一样沉溺（还有600多人已经发展成为爱情）。 而剧情虽然进展很慢，也并没有特别令人惊喜的跌宕起伏，却很好的将这个话题的各个方面都讨论到，且有详略得当，融入的很好。讨论并不严肃，而是主要让观众沉浸在男主（精彩的表演）的情感中，随着主角的情感一边体会，一边思考🤔。 影片最后还是希望大家可以建立起与真人的关系，但同时也给人们留下了对ai产生情感的可能的畅想。细细品味过来，是留给人们一种救赎、美丽与遗憾、绝望并存的令人回味的暂时感受。还蛮令人着迷的",
      "content_html": "<p>来源：<a href=\"https://movie.douban.com/review/17307180/\">https://movie.douban.com/review/17307180/</a></p>\n<p>看的有点沉不住气，剧情总体不多，发展的有点点慢，但同时也给观众很多的时间去沉浸在电影要表达的情感里。</p>\n<p>我觉得本片最好的一点（也是此电影与其他相同题材有优势的一点）是主角的工作——代人写信（代替别人长时间给别人的联系对象写信，表达关心和爱），这个工作放到现实里感觉十分荒诞，会让人质疑这个工作的必要性，或者放到今天，是一个毫无“价值”的工作，容易被取代（正如本篇的ai可以取代），但这份工作代表的含义却是与本篇电影所要讨论的：一个情感如果来自ai，它是否真实（或者对于一份明知道虚假的情感），人们对它应该如何反应，这个主要讨论点相印证，形成了对比实验。</p>\n<p>同样是虚假的情感，一个来自ai训练，一个来自真人的代写。作为情感的表达一方，一个是暂时不清楚是否是真实的情感（ai），一个是真人所共感产生的情绪和感受（信）。</p>\n<p><img src=\"https://image.tmdb.org/t/p/original/omotn6dolqAvtwlfbrWQ1wQwhuG.jpg\" alt=\"剧照\"></p>\n<p>收到信的人和ai的使用者做为情感接受的一方，一个体会到的是自以为是真实对方写的信（在电影中也表达了其情感十分动人，甚至出版成实体书籍），电影中的人们对此感到感动和欣赏。一个收到的是明知道对方是虚假的不存在的但却无比依赖的情感，电影中的人们对此感受也不一样，有的鄙视（男主前妻），有的并不过于关心（办公室的同事），有的体验（7000多人绝大多数都没有发展成爱情），有的则像男主一样沉溺（还有600多人已经发展成为爱情）。</p>\n<p>而剧情虽然进展很慢，也并没有特别令人惊喜的跌宕起伏，却很好的将这个话题的各个方面都讨论到，且有详略得当，融入的很好。讨论并不严肃，而是主要让观众沉浸在男主（精彩的表演）的情感中，随着主角的情感一边体会，一边思考🤔。</p>\n<p><img src=\"https://image.tmdb.org/t/p/original/3kshoGvi6hegSc9tXUNv7wT27d7.jpg\" alt=\"剧照\"></p>\n<p>影片最后还是希望大家可以建立起与真人的关系，但同时也给人们留下了对ai产生情感的可能的畅想。细细品味过来，是留给人们一种救赎、美丽与遗憾、绝望并存的令人回味的暂时感受。还蛮令人着迷的</p>\n",
      "summary": "看的有点沉不住气，剧情总体不多，发展的有点点慢，但同时也给观众很多的时间去沉浸在电影要表达的情感里。",
      "date_published": "2025-12-05T00:00:00.000Z",
      "image": "https://image.tmdb.org/t/p/original/9M1HfKvb6vWp3iJkVxr6ooPfViR.jpg",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/movies/reviews/EVA",
      "url": "https://markxu.icu/movies/reviews/EVA",
      "title": "天鹰战士：最后的冲击",
      "content_text": "俄狄浦斯和耶稣救世的结合，但同时故事一直以淀真嗣的视角展开，也很好的体现了个人情感以及成长的意义，前面有很长的铺垫，使得故事虽然很经典，但不落于俗套，在大一只看过TV的前几集就没兴趣继续看下去了，这次大四重新看，自己的阅历长了不少，更能理解并一定程度上感受到作者表达的意图，后面想要赶紧补完，再看一遍。",
      "content_html": "<p>俄狄浦斯和耶稣救世的结合，但同时故事一直以淀真嗣的视角展开，也很好的体现了个人情感以及成长的意义，前面有很长的铺垫，使得故事虽然很经典，但不落于俗套，在大一只看过TV的前几集就没兴趣继续看下去了，这次大四重新看，自己的阅历长了不少，更能理解并一定程度上感受到作者表达的意图，后面想要赶紧补完，再看一遍。</p>\n",
      "summary": "俄狄浦斯和耶稣救世的结合，但同时故事一直以淀真嗣的视角展开，也很好的体现了个人情感以及成长的意义，前面有很长的铺垫，使得故事虽然很经典，但不落于俗套，在大一只看过TV的前几集就没兴趣继续看下去了，这次大四重新看，自己的阅历长了不少，更能理解并一定程度上感受到作者表达的意图，后面想…",
      "date_published": "2025-11-02T00:00:00.000Z",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/blog/guangzhou-trip-notes-cn",
      "url": "https://markxu.icu/blog/guangzhou-trip-notes-cn",
      "title": "广州游记",
      "content_text": "流程： 3.22： 早8:50火车——12:30到达广州——点都德吃早茶——陈家祠——荔湾湖——永庆坊——上下九——沙面岛——粤海关——圣心教堂——北京路——民宿——大佛寺 3.23： 早起在中山纪念堂与新朋友见面——步行去南越王博物馆——吃竹升面——越秀公园——东山口——太古汇——健身——萨莉亚——花城广场——广州塔——海心沙——民宿 3.24: 早起去广州美术博物馆——中山大学——apm线——西华路——火车站 上个周五数据库老师请假，得来一天空闲，成了一个三天的小长假，借此机会，我和好兄弟规划好了去广州的旅程，顺便去见见好兄弟的发小，周五的早上就早早出发了。 我买的票是到广州东站，一般来说，什么东站或西站都是比较新的站，会比较大。但这个站却是正好相反，看来广州发展已久，就连后来建的站都是用过很久的了。一出来，就是闹市，一片繁华的商业街，以及老旧的居民区混杂在一起，几棵粗、老、富有生机的树在道路两旁，给宽阔的人行道留满了阴凉。我们开始渐渐的融入到这个城市的节奏，这也花了我们一段时间，才真正掌握了这个城市的节奏——历史悠久、生活丰富、年轻、有活力。 我们很快决定去吃早茶，我的好兄弟联系了几个同学，都推荐点都德，虽然价格偏贵，但品质上乘，服务到位。来到火车站最近的点都德（对面有几家居酒屋，一进门好像穿越到日剧里，和店外的中国热闹的街道格格不入），便开始大吃特吃，两个人花了250，可算是把新花样吃了个遍。吃完后我们还坐了电梯，结果发现电梯是上行的，每一个楼层都按满了4-11层，还取消不掉。我们和一个老爷爷在电梯里，就这样，一层层的上去，又从原本的2楼会到地面。电梯里老爷爷讲着与港片里不同的粤语，和我们吐槽，说了不少我只听懂一句：“他妈的”。真是如鲁迅所写，这一句全国统一。 随后我们按照小红书的推荐快速打卡了所有景点，在此期间，我们也逐渐与广州这座城市共振，欣赏珠江边公园里的老年乐队，看老年交谊舞，公园戏台，与外国友人一起录像，看年轻的网红在拍照打卡点各显风姿，看年轻的白领匆忙赶路，看已立足脚跟的中年人锻炼身体，与放学的小学生一起选雪糕，看刚下班的家长去接孩子，以及还没有被父母接到的孩子的游戏。 第一天很快的就结束了，我们筋疲力竭，期待着晚上痛快的睡眠。 三人徒步 第二天一早，我们撇开精致的早餐店，来到不忙的十字路口的路边摊，吃了五块钱的粉，味道却是出奇的棒🎉。我们与好兄弟的发小约好在中山纪念馆碰面，开始还不熟悉，只是认识，没有多说很多话，一起逛完了中山纪念堂，随后又在去往南越王博物馆的时候看了道士馆，在这一路上，我们把诡异的尴尬驱赶走了，对话也渐渐多了起来。 南越王博物馆后，我们去吃朋友发小说不错的面馆，谁想里面的竹升面是用鱼骨汤，我一口没吃（不爱吃海鲜 😟），便接着赶路了。玩了许久，大家都不知道干嘛，我便提出不如去健身房练练（朋友发小练的超级牛！）。我们找好一个便宜的健身房，结果需要预约，并不让我们健身。于是我们又换了一个更好的，服务态度好不说，设备也是又新又好。我跟朋友发小学到了好多，我的训练计划有了更新，训练目的有了方向，以及好多新的动作和动作细节，还顺便看了看我已经会的动作是否标准，学会了不少东西，受益颇深。 然后就是去广州塔，精疲力竭的又是一天。 火车晚点 早起又是徒步去广州美术博物馆，原因是广东省博物馆忘记预约了，没法进去。简单参观后，来到了中山大学门口。由于提前和我的另一位在中山上学的好兄弟打好招呼，他告诉我们一个小门，可以直接进去而不用提前预约（没有预约上），随后好兄弟还很好心的告诉我们校园的哪里值得一去，看到他在这样美丽的地方上学，羡慕死了，幻想着自己也可以在这里上学。 随后我们打车去了apm线，说是可以看花，但排队的人很多，随后退票转战小吃街。在小吃街我们尝了不少新东西，有一个叫簸簯炊的点心，看着以为是类似于米糕加上红糖浆，结果是蒜蓉油，吃的嘴里发臭，还咸咸的不是很好吃。吃完后立马赶往规划好应该准时到的火车站，结果是意想不到的堵车和晚点，我们在火车站插了队，一路快跑到进站口，还是被拦下了，如果早五分钟都可以进去（太遗憾了）。然后就是改签，（好兄弟由于火车开车后改签不能退票，亏了 388块钱，我则付了110多的手续费），一直到晚上10点才回到厦门。 总的来说，三天是充实且快乐的，经历丰富多样，有悲有喜。这个时节去广州正好，虽然太阳会晒，但总体不会太热，我们一路走下来也是累到不行，平均下来每天有38000步，也是累的够呛。真心希望自己有一天能够在广州上学，甚至是可以留下来，好好生活一段时间试试。",
      "content_html": "<p>流程：</p>\n<p>3.22： 早8:50火车——12:30到达广州——点都德吃早茶——陈家祠——荔湾湖——永庆坊——上下九——沙面岛——粤海关——圣心教堂——北京路——民宿——大佛寺</p>\n<p>3.23： 早起在中山纪念堂与新朋友见面——步行去南越王博物馆——吃竹升面——越秀公园——东山口——太古汇——健身——萨莉亚——花城广场——广州塔——海心沙——民宿</p>\n<p>3.24:   早起去广州美术博物馆——中山大学——apm线——西华路——火车站</p>\n<p><img src=\"https://img.markxu.icu/imgRedNoteGuide.jpg\" alt=\"小红书指南\"></p>\n<p>上个周五数据库老师请假，得来一天空闲，成了一个三天的小长假，借此机会，我和好兄弟规划好了去广州的旅程，顺便去见见好兄弟的发小，周五的早上就早早出发了。</p>\n<p>我买的票是到广州东站，一般来说，什么东站或西站都是比较新的站，会比较大。但这个站却是正好相反，看来广州发展已久，就连后来建的站都是用过很久的了。一出来，就是闹市，一片繁华的商业街，以及老旧的居民区混杂在一起，几棵粗、老、富有生机的树在道路两旁，给宽阔的人行道留满了阴凉。我们开始渐渐的融入到这个城市的节奏，这也花了我们一段时间，才真正掌握了这个城市的节奏——历史悠久、生活丰富、年轻、有活力。</p>\n<p>我们很快决定去吃早茶，我的好兄弟联系了几个同学，都推荐点都德，虽然价格偏贵，但品质上乘，服务到位。来到火车站最近的点都德（对面有几家居酒屋，一进门好像穿越到日剧里，和店外的中国热闹的街道格格不入），便开始大吃特吃，两个人花了250，可算是把新花样吃了个遍。吃完后我们还坐了电梯，结果发现电梯是上行的，每一个楼层都按满了4-11层，还取消不掉。我们和一个老爷爷在电梯里，就这样，一层层的上去，又从原本的2楼会到地面。电梯里老爷爷讲着与港片里不同的粤语，和我们吐槽，说了不少我只听懂一句：“他妈的”。真是如鲁迅所写，这一句全国统一。</p>\n<p>随后我们按照小红书的推荐快速打卡了所有景点，在此期间，我们也逐渐与广州这座城市共振，欣赏珠江边公园里的老年乐队，看老年交谊舞，公园戏台，与外国友人一起录像，看年轻的网红在拍照打卡点各显风姿，看年轻的白领匆忙赶路，看已立足脚跟的中年人锻炼身体，与放学的小学生一起选雪糕，看刚下班的家长去接孩子，以及还没有被父母接到的孩子的游戏。</p>\n<p><img src=\"https://img.markxu.icu/imgGuangZhouStreet.jpg\" alt=\"广州街道\"></p>\n<p>第一天很快的就结束了，我们筋疲力竭，期待着晚上痛快的睡眠。</p>\n<h2>三人徒步</h2>\n<p>第二天一早，我们撇开精致的早餐店，来到不忙的十字路口的路边摊，吃了五块钱的粉，味道却是出奇的棒🎉。我们与好兄弟的发小约好在中山纪念馆碰面，开始还不熟悉，只是认识，没有多说很多话，一起逛完了中山纪念堂，随后又在去往南越王博物馆的时候看了道士馆，在这一路上，我们把诡异的尴尬驱赶走了，对话也渐渐多了起来。</p>\n<p><img src=\"https://img.markxu.icu/imgzhongshan_park.jpg\" alt=\"越秀公园\"></p>\n<p>南越王博物馆后，我们去吃朋友发小说不错的面馆，谁想里面的竹升面是用鱼骨汤，我一口没吃（不爱吃海鲜 😟），便接着赶路了。玩了许久，大家都不知道干嘛，我便提出不如去健身房练练（朋友发小练的超级牛！）。我们找好一个便宜的健身房，结果需要预约，并不让我们健身。于是我们又换了一个更好的，服务态度好不说，设备也是又新又好。我跟朋友发小学到了好多，我的训练计划有了更新，训练目的有了方向，以及好多新的动作和动作细节，还顺便看了看我已经会的动作是否标准，学会了不少东西，受益颇深。</p>\n<p>然后就是去广州塔，精疲力竭的又是一天。</p>\n<h2>火车晚点</h2>\n<p>早起又是徒步去广州美术博物馆，原因是广东省博物馆忘记预约了，没法进去。简单参观后，来到了中山大学门口。由于提前和我的另一位在中山上学的好兄弟打好招呼，他告诉我们一个小门，可以直接进去而不用提前预约（没有预约上），随后好兄弟还很好心的告诉我们校园的哪里值得一去，看到他在这样美丽的地方上学，羡慕死了，幻想着自己也可以在这里上学。</p>\n<p>随后我们打车去了apm线，说是可以看花，但排队的人很多，随后退票转战小吃街。在小吃街我们尝了不少新东西，有一个叫簸簯炊的点心，看着以为是类似于米糕加上红糖浆，结果是蒜蓉油，吃的嘴里发臭，还咸咸的不是很好吃。吃完后立马赶往规划好应该准时到的火车站，结果是意想不到的堵车和晚点，我们在火车站插了队，一路快跑到进站口，还是被拦下了，如果早五分钟都可以进去（太遗憾了）。然后就是改签，（好兄弟由于火车开车后改签不能退票，亏了 388块钱，我则付了110多的手续费），一直到晚上10点才回到厦门。</p>\n<p><img src=\"https://img.markxu.icu/imgGuangzhouArtMuseum.jpg\" alt=\"广州美术博物馆\"></p>\n<p>总的来说，三天是充实且快乐的，经历丰富多样，有悲有喜。这个时节去广州正好，虽然太阳会晒，但总体不会太热，我们一路走下来也是累到不行，平均下来每天有38000步，也是累的够呛。真心希望自己有一天能够在广州上学，甚至是可以留下来，好好生活一段时间试试。</p>\n",
      "summary": "这是我在广州的游记，主要是流水账，但也记录了我和好兄弟在旅程中经历的小故事。",
      "date_published": "2024-03-22T00:00:00.000Z",
      "date_modified": "2026-03-03T00:00:00.000Z",
      "image": "https://img.markxu.icu/imgIMG_20240323_广州tower.png",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/blog/Xian-trip-notes-cn",
      "url": "https://markxu.icu/blog/Xian-trip-notes-cn",
      "title": "西安游记",
      "content_text": "10.27 早4.30起床，去机场 —— 9:50 到西安 —— 午饭第一站（广东牛肉火锅）—— 兵马俑博物馆 —— 钟楼 —— 回民街 —— 鼓楼 —— 钟楼 —— 民宿 10.28 早6.50起床 —— 买药 —— 与乐哥碰面 —— 上城墙 —— 碑林博物馆 —— 陕西历史博物馆 —— 民宿 —— 大雁塔 —— 大唐不夜城 —— 民宿 10.29 早7.00起床 —— 小雁塔 —— 机场 激动的一天 10.27 这天有着早上6：50的飞机，所以要4:30左右起床，所以需要早睡，我十一点半躺下，迟迟想到一点才睡着觉，一晚上都在想着明天早上就可以吹到和家里一样的秋天的风了，很是兴奋。到点起床，居然不困，精神的很，兴冲冲的迈上了前往西安的旅程。 来到西安，坐上地铁，就按计划前往兵马俑，途中吃饭，由于传单很有意思，就进去吃了，味道倒还好，只是跑老远来吃广东菜，让我们三人中的广东人破防了。 西安这个城市还是很会做旅游的，地铁站里有纸条，告诉你有名的景点应该做什么公共交通线路，打车的话又该有多少钱，多少时间，防止很多黑车宰客。我不禁为这个为游客着想的城市所作出的努力而感动。 之后来到 兵马俑 ，有些许遗憾，我们三人中有两个人决定不要讲解，所以没有讲解，草草逛完三个坑俑后由于时间不够，没有看成秦始皇陵，华清池虽说不好，但也没有看成。 晚上吃饭倒是不错，虽然吃的店没有名气，也不显眼，但至少根据桂花糕老板说，是正宗的。在问“老刘家羊肉泡馍”时，小卖部的老板娘眼神一亮，很高兴的介绍道路，或许真的不错。 城墙的风 10.28 早上起床由于民宿卫生环境不好，眼睛有些过敏，直接开了血轮眼，一早去买药，花了80多的冤枉钱，以后出门一定要带一些常用的药。 与乐哥碰头后，在街边要了个鸡蛋灌饼，在微微冷的清晨的秋风里，吃一顿简单平凡的热热的早餐，是人间的幸福。比在温暖的厦门的学校食堂心满意足的吃一顿还要让人幸福。 在北城墙上，人不多，骑着自行车。空气中的湿度不高，感觉空气都轻盈许多，好像不需要吸气，空气会自己灌到肺中，把人充满，身体也好似由于浮力轻盈了些。城墙远望，西安城的格局尽收眼底，之前的期待不被辜负的感觉真的很棒，秋天的风吹的人精神抖擞，吹散人的压力，对于一个年轻的人，这秋风或许还吹不来忧郁。看着在城墙上跑”马拉松“的幼儿园的孩子们，更是有活力了许多。 陕西历史博物馆仍然是没有任何讲解，馆内人很拥挤，场地也比较小，比较闷热，让人难静下心来观赏。虽然文物都是国宝级别的，讲解员也都还蛮专业的，但看完一遍印象不是很深。 逛博物馆时也很难不去和之前去过的博物馆做对比，毕竟也是很厉害的博物馆了。如果可以把文物和其他国家一起相互交流一下，可以在一座博物馆里看到同一时期的各个地区的历史，有个横行对比，或许会更惊喜，就像大英博物馆一样。而说到场地，又难和国博相比，一个狭小拥挤，一个气派空阔。 虽说种种不足，但陕历博给我留下的印象还是很深刻，希望有时间有机会的话，可以再听讲解去一次。 晚上的大雁塔和大唐不夜城真的给人很多震撼。街道设计很有心思，让大家伙在逛街时也有互动，比如钢琴的地砖，迪厅般可以换颜色的地砖，还有随着人群声音控制流量的喷泉……街道上还有很多演出，如网红的 密谋 还有一个演唱会，街道很宽，即使中间摆上气派的历史雕塑，两旁摆满小吃摊，街道旁拍照的穿着唐衣的女孩子，仍然可以很自由的逛街。 街道两旁的建筑里的设计也不含糊，新华书店的阅读室内陈列的书，小众但不荒诞，数量多但不杂乱，华丽又不惹眼。还有人在弹钢琴，环境很适合一个人从外面的热闹静下来阅读，不受人打扰。书店里的书也很适合西安这个城市，书店也确实是一个城市的灵魂所在了。 晚上喝的茶话弄的 桂花米酿 确实好喝，在10.30喝的茶百道的差不多东西，味道就没有这么惊艳了。相比之下，茶话弄在突出米酿和茶的味道，而茶百道却一味追求桂花的甜味，反倒失了桂花清香的感觉。 返程 10.29 今天起的晚了一些，大家都睡的很舒服。但我的身体开始换季了，鼻子很难受。 小雁塔在门口看了一眼，时间不够，接着前往机场，一路上我们没有说很多话，回味着这段说走就走的略带奇幻的旅程，坐上飞机，回到了厦门，这次好像对厦门又有了些许的归属感，还有两年多，不知道什么时候我才能真正的感觉自己也是厦门的一份子吧",
      "content_html": "<p>10.27 早4.30起床，去机场 —— 9:50 到西安 —— 午饭第一站（广东牛肉火锅）—— 兵马俑博物馆 —— 钟楼 —— 回民街 —— 鼓楼 —— 钟楼 —— 民宿</p>\n<p>10.28 早6.50起床 —— 买药 —— 与乐哥碰面 —— 上城墙 —— 碑林博物馆 —— 陕西历史博物馆 —— 民宿 —— 大雁塔 —— 大唐不夜城 —— 民宿</p>\n<p>10.29 早7.00起床 —— 小雁塔 —— 机场</p>\n<h1>激动的一天 10.27</h1>\n<p>这天有着早上6：50的飞机，所以要4:30左右起床，所以需要早睡，我十一点半躺下，迟迟想到一点才睡着觉，一晚上都在想着明天早上就可以吹到和家里一样的秋天的风了，很是兴奋。到点起床，居然不困，精神的很，兴冲冲的迈上了前往西安的旅程。</p>\n<p>来到西安，坐上地铁，就按计划前往兵马俑，途中吃饭，由于传单很有意思，就进去吃了，味道倒还好，只是跑老远来吃广东菜，让我们三人中的广东人破防了。</p>\n<p><img\n  src=\"https://img.markxu.icu/imgIMG_20231027_120440.jpg\"\n  alt=\"好看的传单\"\n  style=\"width: min(100%, 360px); height: auto; display: block; margin: 1.5rem auto;\"\n/></p>\n<p>西安这个城市还是很会做旅游的，地铁站里有纸条，告诉你有名的景点应该做什么公共交通线路，打车的话又该有多少钱，多少时间，防止很多黑车宰客。我不禁为这个为游客着想的城市所作出的努力而感动。</p>\n<p>之后来到 <em>兵马俑</em>，有些许遗憾，我们三人中有两个人决定不要讲解，所以没有讲解，草草逛完三个坑俑后由于时间不够，没有看成秦始皇陵，华清池虽说不好，但也没有看成。</p>\n<p>晚上吃饭倒是不错，虽然吃的店没有名气，也不显眼，但至少根据桂花糕老板说，是正宗的。在问“老刘家羊肉泡馍”时，小卖部的老板娘眼神一亮，很高兴的介绍道路，或许真的不错。</p>\n<h1>城墙的风 10.28</h1>\n<p>早上起床由于民宿卫生环境不好，眼睛有些过敏，直接开了血轮眼，一早去买药，花了80多的冤枉钱，以后出门一定要带一些常用的药。</p>\n<p>与乐哥碰头后，在街边要了个鸡蛋灌饼，在微微冷的清晨的秋风里，吃一顿简单平凡的热热的早餐，是人间的幸福。比在温暖的厦门的学校食堂心满意足的吃一顿还要让人幸福。</p>\n<p>在北城墙上，人不多，骑着自行车。空气中的湿度不高，感觉空气都轻盈许多，好像不需要吸气，空气会自己灌到肺中，把人充满，身体也好似由于浮力轻盈了些。城墙远望，西安城的格局尽收眼底，之前的期待不被辜负的感觉真的很棒，秋天的风吹的人精神抖擞，吹散人的压力，对于一个年轻的人，这秋风或许还吹不来忧郁。看着在城墙上跑”马拉松“的幼儿园的孩子们，更是有活力了许多。</p>\n<p><img\n  src=\"https://img.markxu.icu/imgIMG_20231028_091700.jpg\"\n  alt=\"我们还花了点小钱看了一下望远镜🔭\"\n  style=\"width: min(100%, 360px); height: auto; display: block; margin: 1.5rem auto;\"\n/></p>\n<p>陕西历史博物馆仍然是没有任何讲解，馆内人很拥挤，场地也比较小，比较闷热，让人难静下心来观赏。虽然文物都是国宝级别的，讲解员也都还蛮专业的，但看完一遍印象不是很深。</p>\n<p>逛博物馆时也很难不去和之前去过的博物馆做对比，毕竟也是很厉害的博物馆了。如果可以把文物和其他国家一起相互交流一下，可以在一座博物馆里看到同一时期的各个地区的历史，有个横行对比，或许会更惊喜，就像大英博物馆一样。而说到场地，又难和国博相比，一个狭小拥挤，一个气派空阔。</p>\n<p>虽说种种不足，但陕历博给我留下的印象还是很深刻，希望有时间有机会的话，可以再听讲解去一次。</p>\n<p><img src=\"https://img.markxu.icu/img03947BD4DA13A06C044082A55B46DB0C.jpg\" alt=\"忘记什么文物了\"></p>\n<p>晚上的大雁塔和大唐不夜城真的给人很多震撼。街道设计很有心思，让大家伙在逛街时也有互动，比如钢琴的地砖，迪厅般可以换颜色的地砖，还有随着人群声音控制流量的喷泉……街道上还有很多演出，如网红的 密谋 还有一个演唱会，街道很宽，即使中间摆上气派的历史雕塑，两旁摆满小吃摊，街道旁拍照的穿着唐衣的女孩子，仍然可以很自由的逛街。</p>\n<p>街道两旁的建筑里的设计也不含糊，新华书店的阅读室内陈列的书，小众但不荒诞，数量多但不杂乱，华丽又不惹眼。还有人在弹钢琴，环境很适合一个人从外面的热闹静下来阅读，不受人打扰。书店里的书也很适合西安这个城市，书店也确实是一个城市的灵魂所在了。</p>\n<p>晚上喝的茶话弄的 桂花米酿 确实好喝，在10.30喝的茶百道的差不多东西，味道就没有这么惊艳了。相比之下，茶话弄在突出米酿和茶的味道，而茶百道却一味追求桂花的甜味，反倒失了桂花清香的感觉。</p>\n<h1>返程 10.29</h1>\n<p>今天起的晚了一些，大家都睡的很舒服。但我的身体开始换季了，鼻子很难受。</p>\n<p>小雁塔在门口看了一眼，时间不够，接着前往机场，一路上我们没有说很多话，回味着这段说走就走的略带奇幻的旅程，坐上飞机，回到了厦门，这次好像对厦门又有了些许的归属感，还有两年多，不知道什么时候我才能真正的感觉自己也是厦门的一份子吧</p>\n<p><img src=\"https://img.markxu.icu/imgBBBADE1069239D8271E46821A343C364.jpg\" alt=\"\"></p>\n",
      "summary": "偶然翻到了当初去西安游玩的游记，虽然也是流水账，但也足以让我回味，也放上来当作记录好了，不至于后面再看到又是一次偶然。",
      "date_published": "2023-10-29T00:00:00.000Z",
      "date_modified": "2026-07-01T00:00:00.000Z",
      "image": "https://img.markxu.icu/img西安.jpg",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/blog/chaoshan-trip-notes-cn",
      "url": "https://markxu.icu/blog/chaoshan-trip-notes-cn",
      "title": "潮汕游记",
      "content_text": "流水账： 9.24 ： 车站——潮汕站——（K2线）——中心医院—— （步行）——许驸马府（路过）——木棉公馆，入住（视频电话（直播）） 9.25 ：早6:00起床，7:00出门——租电动车——逛牌坊街——吃早饭（牌坊街内）——开元寺——广济桥——广济门——潮州古城——图书馆——菜市（吃午饭，牛肉粿条）——还车——过广济桥——韩文公祠——泰佛殿——慧如公园——坐车（改签）去汕头——公寓入住——万象城——看电影（《封神》） 9.26 ： 眼肿——去汕头医院挂号——早饭（肠粉）——汕头博物馆——中山公园——午饭（粿汁）——医院拿药——汕头小公园——电影博物馆——汕头开埠文化陈列馆——邮局——侨批文物馆——汕头旅社——西堤公园——人民广场，广场轮渡——万象城——晚饭（牛肉火锅）——成川治茶 2023.9.22 潮州 车站，对于不同的人有不同的感受。与我来说，车站充满了浪漫。它意味着未来，自由，家乡还有前途。 周五晚上，就赶上火车前往潮汕。在BRT上，发觉今天的云比以往更好看，阳光也更明媚，也许旅行这件事可以让一个人的眼睛四处打量，发现更加美好的东西。 晚上到了潮州，等K2等了好久，坐公交又是一个小时，好不容易才到了目的地，这时给家里打了个视频电话，一边“直播”，一边走到了民宿。如果不打电话的话，我肯定会比现在疲惫，但是这个电话让我感觉旅行让我离家的距离更近了，走的很起劲。 民宿也意外的好看，很像东南亚里早期电视剧里的大户人家的房子。 9.23 业精于勤，荒于嬉；行成于思，毁于随。——韩愈 早上早起，骑上电动车。不得不说，这真的省了我很大力气，虽然租的车子贵了一些，但值得，靠着这个电动车，我窜遍了潮州古城（牌坊街）还去了菜市（市里）看看，无疑让我对潮州理解的更加深刻些。牌坊街上标着的全是各种优秀考生，联系我最近看的《明朝那些事儿》，自以为了解的更深入些了（至少明白不管什么官职，只要考中，就足矣立一个牌坊，让后人记住。） 广济门，广济桥。在我走完整个广济桥之后才明白广济二字由来，是由海内外的有钱人或机构，捐钱建成的桥。由于起得早，我成为那一天第一个踏上广济桥的人，也是第一个走到断桥处的。看完了浮桥的链接，作为四大古桥之一确实有意思。 这一天逛了不少地方，最让我失望的是泰佛寺和慧如公园，他们隔着一条道路脸对着脸，都是一股年久失修的状态，还有一大批不怀好意的人在周围疯狂的揽客来利用这最后的一点价值，苦了很多跟着攻略来的游客。 要说今天有什么让我记忆十分深刻，除了这些景点，当属一张没有拍下的照片（当时在品凉茶，太难喝了些☹️）。照片的内容本该是韩文公祠入口台阶上的一句话—— 业精于勤荒于嬉，行成于思毁于随 “精” “荒” “嬉” “毁” “随” 五个字一直让我思考，不禁感叹韩愈用词的精准，不愧是唐宋八大家之首。虽然没有拍下，但在临行前装作样子的读了一遍，然后一路上思考着。这不就说的是我吗？ 勤 —— 是我所没达到的，但却是我一直想做到的。 荒于嬉 —— 则是我所能见的我正在干的事情。尤其是“嬉“字，并不是勤的反义词——懒、怠慢或是不坚定，而是嬉戏，当一个人忙着嬉戏时，很难意识到自己的过错。”战士军前半死生，美人帐下犹歌舞“、“暖风熏得游人醉，直把杭州作汴州。“ 毁于随 —— “跟随舆论思考的，都是自己耳塞眼闭的人。“我马上联系到了尼采的这句话。我时刻提醒自己要自己去寻找更多方面的观点，但奈何跟随舆论思考是如此简单，而且罚不责众，即使你错了，也不会被嘲笑，更不用承担任何后果。而且很难发现自己被舆论所框住。 9.24 不好好利用时间，怎么知道有多珍贵。 来到汕头，我完全被前一天（昨天）晚上的状况虎住了，我住在汕头的商业中心，人有很多。又逛了万象城，看到很多各种各样的人，很多没见过的店，尤其是看到了一些小学年龄段的孩子，没有父母跟着，就约着一起在万象城转，（我小时候可只是在小区周围骑自行车啊），他们随手就拿出手机，拍照，发帖，嘴里说着网络上的流行梗，小姑娘们学着网红化妆拍照（在电动扶梯前面），让我感到时代确实不同了，很好奇他们的童年再回忆起来又是什么样子。 以上的种种景象然我觉得这个城市好发达，早上起来去了医院（昨天眼睛莫名其妙发炎，肿了个大包），看到熟悉的环境后才放下心来，只是昨天晚上太黑没看清楚，被那灯光炫晕了眼，这个城市和所有的城市一样（只有发达的地方有灯光的原因吧），很宜人，但也只是个宜人的城市。晃晃过了一天。刚好怕玩太晚的我也早早改签，回到了学校。 这次旅行让我充分的利用了时间，如果这个周末待在寝室，无非就是看了看网页，发发牢骚，低效率的学点知识。但这次利用等挂号的时间（两个半小时），逛了一整个博物馆，逛了一整个公园，还吃了没吃过的粿汁。 时间很久没有这么慢了（或是说充实？），这个时间放在以往就是起床，吃饭，看电脑。只有好好的把每个时间都利用起来，才感到时间如此的充实宝贵。 一个人旅行 一个人旅行，放在我以前是不敢的，网上也有人试图说明自己有多孤独，举了很多例子：一个人看电影，一个人吃火锅，一个人看病，一个人旅行。这次旅行之后，上面的这些我都干过了。 孤独，还是避免不了的。不论是景点还是饭店，看到别人成双成对，好友成群，天伦之乐，难免不心生羡慕。好在有微信分享，我把旅行的照片和视频分享给爸妈，有人分享，旅行再无聊也有其意义。 自由，更是一个人旅行的最大特点，我眼睛难受就去医院看（不用担心耽误别人时间，还可以看到当地的医院是怎么样的），不用考虑别人胃口，不用考虑别人想法。自己决定好了，就去做，省了不少功夫，毕竟要说服的只有自己一个人。 因此我的速度快了不少，想去哪里去哪里，逛腻了就换地方，没逛够就呆着发会儿呆。而且身边没人和我一起吐槽，让我的思维也更专注，不再是一群人嘻嘻哈哈的打闹，错过了某些只有一个人才会注意到的事情。有更多的时间去观察周边的事物，并试着去理解。好像有种更成熟的感觉。",
      "content_html": "<p>流水账：</p>\n<p>9.24 ： 车站——潮汕站——（K2线）——中心医院—— （步行）——许驸马府（路过）——木棉公馆，入住（视频电话（直播））</p>\n<p>9.25 ：早6:00起床，7:00出门——租电动车——逛牌坊街——吃早饭（牌坊街内）——开元寺——广济桥——广济门——潮州古城——图书馆——菜市（吃午饭，牛肉粿条）——还车——过广济桥——韩文公祠——泰佛殿——慧如公园——坐车（改签）去汕头——公寓入住——万象城——看电影（《封神》）</p>\n<p>9.26 ： 眼肿——去汕头医院挂号——早饭（肠粉）——汕头博物馆——中山公园——午饭（粿汁）——医院拿药——汕头小公园——电影博物馆——汕头开埠文化陈列馆——邮局——侨批文物馆——汕头旅社——西堤公园——人民广场，广场轮渡——万象城——晚饭（牛肉火锅）——成川治茶</p>\n<h2>2023.9.22 潮州</h2>\n<h4>车站，对于不同的人有不同的感受。与我来说，车站充满了浪漫。它意味着未来，自由，家乡还有前途。</h4>\n<p><img src=\"https://img.markxu.icu/imgIMG_20230922_173547.jpg\" alt=\"厦门北站\"></p>\n<p>周五晚上，就赶上火车前往潮汕。在BRT上，发觉今天的云比以往更好看，阳光也更明媚，也许旅行这件事可以让一个人的眼睛四处打量，发现更加美好的东西。</p>\n<p>晚上到了潮州，等K2等了好久，坐公交又是一个小时，好不容易才到了目的地，这时给家里打了个视频电话，一边“直播”，一边走到了民宿。如果不打电话的话，我肯定会比现在疲惫，但是这个电话让我感觉旅行让我离家的距离更近了，走的很起劲。</p>\n<p><img src=\"https://img.markxu.icu/imgIMG_20230922_221454.jpg\" alt=\"夜游潮州\"></p>\n<p>民宿也意外的好看，很像东南亚里早期电视剧里的大户人家的房子。</p>\n<p><img src=\"https://img.markxu.icu/imgIMG_20230922_230309.jpg\" alt=\"晚上住的民宿\"></p>\n<h2>9.23 业精于勤，荒于嬉；行成于思，毁于随。——韩愈</h2>\n<p>早上早起，骑上电动车。不得不说，这真的省了我很大力气，虽然租的车子贵了一些，但值得，靠着这个电动车，我窜遍了潮州古城（牌坊街）还去了菜市（市里）看看，无疑让我对潮州理解的更加深刻些。牌坊街上标着的全是各种优秀考生，联系我最近看的《明朝那些事儿》，自以为了解的更深入些了（至少明白不管什么官职，只要考中，就足矣立一个牌坊，让后人记住。）</p>\n<p>广济门，广济桥。在我走完整个广济桥之后才明白广济二字由来，是由海内外的有钱人或机构，捐钱建成的桥。由于起得早，我成为那一天第一个踏上广济桥的人，也是第一个走到断桥处的。看完了浮桥的链接，作为四大古桥之一确实有意思。</p>\n<div class=\"img-grid-2\">\n  <img src=\"https://img.markxu.icu/imgIMG_20230923_075529.jpg\" alt=\"潮州古城\" />\n  <img src=\"https://img.markxu.icu/imgIMG_20230923_091203.jpg\" alt=\"广济桥浮桥连接之前\" />\n</div>\n<p>这一天逛了不少地方，最让我失望的是泰佛寺和慧如公园，他们隔着一条道路脸对着脸，都是一股年久失修的状态，还有一大批不怀好意的人在周围疯狂的揽客来利用这最后的一点价值，苦了很多跟着攻略来的游客。</p>\n<p>要说今天有什么让我记忆十分深刻，除了这些景点，当属一张没有拍下的照片（当时在品凉茶，太难喝了些☹️）。照片的内容本该是韩文公祠入口台阶上的一句话——</p>\n<p><strong>业精于勤荒于嬉，行成于思毁于随</strong></p>\n<p>“精” “荒” “嬉” “毁” “随” 五个字一直让我思考，不禁感叹韩愈用词的精准，不愧是唐宋八大家之首。虽然没有拍下，但在临行前装作样子的读了一遍，然后一路上思考着。这不就说的是我吗？</p>\n<p>勤 —— 是我所没达到的，但却是我一直想做到的。</p>\n<p>荒于嬉 —— 则是我所能见的我正在干的事情。尤其是“嬉“字，并不是勤的反义词——懒、怠慢或是不坚定，而是嬉戏，当一个人忙着嬉戏时，很难意识到自己的过错。”战士军前半死生，美人帐下犹歌舞“、“暖风熏得游人醉，直把杭州作汴州。“</p>\n<p>毁于随 —— “跟随舆论思考的，都是自己耳塞眼闭的人。“我马上联系到了尼采的这句话。我时刻提醒自己要自己去寻找更多方面的观点，但奈何跟随舆论思考是如此简单，而且罚不责众，即使你错了，也不会被嘲笑，更不用承担任何后果。而且很难发现自己被舆论所框住。</p>\n<h2>9.24 不好好利用时间，怎么知道有多珍贵。</h2>\n<p>来到汕头，我完全被前一天（昨天）晚上的状况虎住了，我住在汕头的商业中心，人有很多。又逛了万象城，看到很多各种各样的人，很多没见过的店，尤其是看到了一些小学年龄段的孩子，没有父母跟着，就约着一起在万象城转，（我小时候可只是在小区周围骑自行车啊），他们随手就拿出手机，拍照，发帖，嘴里说着网络上的流行梗，小姑娘们学着网红化妆拍照（在电动扶梯前面），让我感到时代确实不同了，很好奇他们的童年再回忆起来又是什么样子。</p>\n<p>以上的种种景象然我觉得这个城市好发达，早上起来去了医院（昨天眼睛莫名其妙发炎，肿了个大包），看到熟悉的环境后才放下心来，只是昨天晚上太黑没看清楚，被那灯光炫晕了眼，这个城市和所有的城市一样（只有发达的地方有灯光的原因吧），很宜人，但也只是个宜人的城市。晃晃过了一天。刚好怕玩太晚的我也早早改签，回到了学校。</p>\n<p>这次旅行让我充分的利用了时间，如果这个周末待在寝室，无非就是看了看网页，发发牢骚，低效率的学点知识。但这次利用等挂号的时间（两个半小时），逛了一整个博物馆，逛了一整个公园，还吃了没吃过的粿汁。</p>\n<p><img src=\"https://img.markxu.icu/imgIMG_20230924_100815.jpg\" alt=\"中山公园，看来全国都有这个么公园\"></p>\n<p>时间很久没有这么慢了（或是说充实？），这个时间放在以往就是起床，吃饭，看电脑。只有好好的把每个时间都利用起来，才感到时间如此的充实宝贵。</p>\n<h2>一个人旅行</h2>\n<p>一个人旅行，放在我以前是不敢的，网上也有人试图说明自己有多孤独，举了很多例子：一个人看电影，一个人吃火锅，一个人看病，一个人旅行。这次旅行之后，上面的这些我都干过了。</p>\n<p>孤独，还是避免不了的。不论是景点还是饭店，看到别人成双成对，好友成群，天伦之乐，难免不心生羡慕。好在有微信分享，我把旅行的照片和视频分享给爸妈，有人分享，旅行再无聊也有其意义。</p>\n<p>自由，更是一个人旅行的最大特点，我眼睛难受就去医院看（不用担心耽误别人时间，还可以看到当地的医院是怎么样的），不用考虑别人胃口，不用考虑别人想法。自己决定好了，就去做，省了不少功夫，毕竟要说服的只有自己一个人。</p>\n<p>因此我的速度快了不少，想去哪里去哪里，逛腻了就换地方，没逛够就呆着发会儿呆。而且身边没人和我一起吐槽，让我的思维也更专注，不再是一群人嘻嘻哈哈的打闹，错过了某些只有一个人才会注意到的事情。有更多的时间去观察周边的事物，并试着去理解。好像有种更成熟的感觉。</p>\n",
      "summary": "这是我在潮汕的游记，记录了大二第一次独自出去玩的经历。",
      "date_published": "2023-09-27T00:00:00.000Z",
      "date_modified": "2026-02-25T00:00:00.000Z",
      "image": "https://img.markxu.icu/imgIMG_20230922_汕头.png",
      "tags": [
        "blog",
        "zh"
      ]
    },
    {
      "id": "https://markxu.icu/movies/reviews/%E5%A4%AA%E9%98%B3%E7%85%A7%E5%B8%B8%E5%8D%87%E8%B5%B7",
      "url": "https://markxu.icu/movies/reviews/%E5%A4%AA%E9%98%B3%E7%85%A7%E5%B8%B8%E5%8D%87%E8%B5%B7",
      "title": "太阳照常升起",
      "content_text": "今天把暑假里看到一半的《太阳照常升起》看完了，有些恍惚，好久没有这种心里空落落，又有点受惊的感觉了，电影没有看懂，但一句弹幕又似乎让我明白了，“没有看明白，但感受到了”, 或许我确确实实的感受到了。 感觉这部全是隐喻的电影可以给人很多思考，思考没有限制，便有了离奇的脑洞，有的无趣，有的吓人，我明显是被吓人的脑洞惊住了，现在记录的语言也有些乱套。 感觉讲的是国家（苏联和中国），又讲的是社会（回避的历史），也讲了人性，还有社会中的压抑的动物本能。以如此潇洒自在，不成风格的风格拍的电影有些令人着迷，让我一时分不清自己是在家里还是学校宿舍，又开始对周围的环境有了些许怀疑，有点像 Matrix 里的 red pill，带我到了另一个世界，些许的让人着迷，也让人受惊，好像使自己站在了另一个生物的角度来看人类，对周围环境有一种陌生的感觉。 记得没有头绪，只是感觉。2022/9/24",
      "content_html": "<p>今天把暑假里看到一半的《太阳照常升起》看完了，有些恍惚，好久没有这种心里空落落，又有点受惊的感觉了，电影没有看懂，但一句弹幕又似乎让我明白了，“没有看明白，但感受到了”, 或许我确确实实的感受到了。</p>\n<p>感觉这部全是隐喻的电影可以给人很多思考，思考没有限制，便有了离奇的脑洞，有的无趣，有的吓人，我明显是被吓人的脑洞惊住了，现在记录的语言也有些乱套。</p>\n<p>感觉讲的是国家（苏联和中国），又讲的是社会（回避的历史），也讲了人性，还有社会中的压抑的动物本能。以如此潇洒自在，不成风格的风格拍的电影有些令人着迷，让我一时分不清自己是在家里还是学校宿舍，又开始对周围的环境有了些许怀疑，有点像 Matrix 里的 red pill，带我到了另一个世界，些许的让人着迷，也让人受惊，好像使自己站在了另一个生物的角度来看人类，对周围环境有一种陌生的感觉。</p>\n<p>记得没有头绪，只是感觉。2022/9/24</p>\n",
      "summary": "今天把暑假里看到一半的《太阳照常升起》看完了，有些恍惚，好久没有这种心里空落落，又有点受惊的感觉了，电影没有看懂，但一句弹幕又似乎让我明白了，“没有看明白，但感受到了”, 或许我确确实实的感受到了。",
      "date_published": "2022-09-24T00:00:00.000Z",
      "image": "https://image.tmdb.org/t/p/original/yGNBtSLAD49Rtzev5jpzAgQZTso.jpg",
      "tags": [
        "blog",
        "zh"
      ]
    }
  ]
}
