<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-CN">
    <title>whx&#x27;s Blog</title>
    <subtitle>记录生活</subtitle>
    <link rel="self" type="application/atom+xml" href="https://whx828.com/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://whx828.com"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-07-17T00:00:00+00:00</updated>
    <id>https://whx828.com/atom.xml</id>
    <entry xml:lang="zh-CN">
        <title>博客更新：从 zine 到 Zola</title>
        <published>2026-07-17T00:00:00+00:00</published>
        <updated>2026-07-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://whx828.com/posts/zine-to-zola/"/>
        <id>https://whx828.com/posts/zine-to-zola/</id>
        
        <summary type="html">&lt;p&gt;时间过得真快，转眼我已经工作近两年了（我现在做的事情离代码很远），再次打开博客一看，上一篇文章还停在 2023 年 5 月的《xv6 学习记录》。&lt;&#x2F;p&gt;
&lt;p&gt;最近重新动了写博客的念头，索性先把房子翻新一遍：把博客从 &lt;strong&gt;zine&lt;&#x2F;strong&gt; 迁移到了 &lt;strong&gt;Zola&lt;&#x2F;strong&gt;。这篇就当作迁移记录，也算是重新开张的第一篇。&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="zh-CN">
        <title>xv6 学习记录</title>
        <published>2023-05-07T00:00:00+00:00</published>
        <updated>2023-05-07T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://whx828.com/posts/xv6-learning/"/>
        <id>https://whx828.com/posts/xv6-learning/</id>
        
        <content type="html" xml:base="https://whx828.com/posts/xv6-learning/">&lt;blockquote&gt;
&lt;p&gt;本文会不定期更新&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;最近（就这两天）在学习 MIT 的 &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;pdos.csail.mit.edu&#x2F;6.S081&#x2F;2021&#x2F;&quot;&gt;6.S081&lt;&#x2F;a&gt;，打算补一补操作系统的课，毕竟我对操作系统还是很感兴趣的（&lt;del&gt;至于以前的坑嘛，笑&lt;&#x2F;del&gt;）。&lt;&#x2F;p&gt;
&lt;p&gt;大致翻了下 6.S081 的组成：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;课程视频：https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=L6YqHxYHa7A&lt;&#x2F;li&gt;
&lt;li&gt;课程教材：https:&#x2F;&#x2F;pdos.csail.mit.edu&#x2F;6.828&#x2F;2021&#x2F;xv6&#x2F;book-riscv-rev2.pdf&lt;&#x2F;li&gt;
&lt;li&gt;课程作业：https:&#x2F;&#x2F;pdos.csail.mit.edu&#x2F;6.828&#x2F;2021&#x2F;schedule.html&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;如果要把课程视频一一看过去太累，好在已经有好心人提供了课程视频的&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;mit-public-courses-cn-translatio.gitbook.io&#x2F;mit6-s081&#x2F;&quot;&gt;中文字幕翻译&lt;&#x2F;a&gt;，配合官方教材，可以在不看视频的情况下大致走一遍，对我而言够用了。&lt;&#x2F;p&gt;
&lt;p&gt;走完字幕后需要做一些 lab 练习才能巩固好所学，却没想到标注 easy 的 lab，其实也不是那么 easy。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;lab-xv6-and-unix-utilities&quot;&gt;Lab: Xv6 and Unix utilities&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;boot-xv6-easy&quot;&gt;Boot xv6 (easy)&lt;&#x2F;h3&gt;
&lt;p&gt;这个小 lab 是获取 xv6 的实验环境，做 xv6 实验所用的环境并不是 GitHub 上的那个仓库，而是需要你手动 clone 这个：&lt;code&gt;git clone git:&#x2F;&#x2F;g.csail.mit.edu&#x2F;xv6-labs-2020&lt;&#x2F;code&gt;，之后你可以切到当前 lab 的分支：&lt;code&gt;git checkout util&lt;&#x2F;code&gt;，做什么实验就切到什么分支，非常方便。&lt;br &#x2F;&gt;
之后是最常用的命令：&lt;code&gt;make qemu&lt;&#x2F;code&gt;，顺利的话你就得到这么一堆玩意：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D3C6AA; background-color: #2D353B;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;riscv64-unknown-elf-gcc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; -Wall -Werror -O -fno-omit-frame-pointer -ggdb -gdwarf-2 -DSOL_UTIL -MD -mcmodel=medany -ffreestanding -fno-common -nostdlib -mno-relax -I. -fno-stack-protector -fno-pie -no-pie   -c -o user&#x2F;pingpong.o user&#x2F;pingpong.c&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;riscv64-unknown-elf-ld&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; -z max-page-size=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;4096&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; -N -e main -Ttext&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; -o user&#x2F;_pingpong user&#x2F;pingpong.o user&#x2F;ulib.o user&#x2F;usys.o user&#x2F;printf.o user&#x2F;umalloc.o&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;riscv64-unknown-elf-objdump&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; -S user&#x2F;_pingpong&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; user&#x2F;pingpong.asm&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;riscv64-unknown-elf-objdump&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; -t user&#x2F;_pingpong&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; sed &amp;#39;1,&#x2F;SYMBOL TABLE&#x2F;d; s&#x2F; .* &#x2F; &#x2F;; &#x2F;^$&#x2F;d&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; user&#x2F;pingpong.sym&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;mkfs&#x2F;mkfs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; fs.img README  user&#x2F;xargstest.sh user&#x2F;_cat user&#x2F;_echo user&#x2F;_forktest user&#x2F;_grep user&#x2F;_init user&#x2F;_kill user&#x2F;_ln user&#x2F;_ls user&#x2F;_mkdir user&#x2F;_rm user&#x2F;_sh user&#x2F;_sleep user&#x2F;_pingpong user&#x2F;_primes user&#x2F;_stressfs user&#x2F;_usertests user&#x2F;_grind user&#x2F;_wc user&#x2F;_zombie&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;nmeta&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 46&lt;&#x2F;span&gt;&lt;span&gt; (boot,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; super, log blocks&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 30&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; inode blocks 13, bitmap blocks&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;) blocks 954 total 1000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;balloc:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; first&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 727&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; blocks have been allocated&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;balloc:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; write bitmap block at sector&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 45&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;qemu-system-riscv64&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; -machine virt -bios none -kernel kernel&#x2F;kernel -m 128M -smp&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; -nographic -drive file=fs.img,if=none,format=raw,id=x0 -device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;xv6&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; kernel is booting&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;hart&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; starting&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;hart&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; starting&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;init:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; starting sh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;才怪！在我的 MacBook 上卡住了，具体修改请看：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D3C6AA; background-color: #2D353B;&quot;&gt;&lt;code data-lang=&quot;diff&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;diff --git a&#x2F;kernel&#x2F;kernelvec.S b&#x2F;kernel&#x2F;kernelvec.S&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;index 3370ae5..3e9d3e9 100644&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;---&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; a&#x2F;kernel&#x2F;kernelvec.S&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+++ b&#x2F;kernel&#x2F;kernelvec.S&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;@@&lt;&#x2F;span&gt;&lt;span&gt; -85,11 +85,6&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; @@&lt;&#x2F;span&gt;&lt;span&gt; kernelvec:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         &#x2F;&#x2F; return to whatever we were doing in the kernel.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         sret&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-&#x2F;&#x2F; help: if you hit these, an unexpected exception&#x2F;interrupt happened in M-mode.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-&#x2F;&#x2F; use `info registers` in the qemu monitor to get the relevant CSRs.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-unexpected_exc: j unexpected_exc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-unexpected_int: j unexpected_int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         #&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         # machine-mode timer interrupt.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         #&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;@@&lt;&#x2F;span&gt;&lt;span&gt; -106,15 +101,6&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; @@&lt;&#x2F;span&gt;&lt;span&gt; timervec:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         sd a2, 8(a0)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         sd a3, 16(a0)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-        csrr a1, mcause&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-        &#x2F;&#x2F; we should not get exceptions in M-mode. if we do, something went&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-        &#x2F;&#x2F; very wrong and we should explicitly jump to an infinite loop for the&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-        &#x2F;&#x2F; purpose.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-        bgez a1, unexpected_exc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-        li a2, (1&amp;lt;&amp;lt;63 | 7)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-        &#x2F;&#x2F; likewise for any interrupts that are not machine timer interrupts.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-        bne a1, a2, unexpected_int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         # schedule the next timer interrupt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         # by adding interval to mtimecmp.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         ld a1, 32(a0) # CLINT_MTIMECMP(hart)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;@@&lt;&#x2F;span&gt;&lt;span&gt; -124,7 +110,7&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; @@&lt;&#x2F;span&gt;&lt;span&gt; timervec:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         sd a3, 0(a1)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         # raise a supervisor software interrupt.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-           li a1, 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;+       li a1, 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         csrw sip, a1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         ld a3, 16(a0)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;diff --git a&#x2F;kernel&#x2F;riscv.h b&#x2F;kernel&#x2F;riscv.h&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;index 5f6c3d9..0aec003 100644&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;---&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; a&#x2F;kernel&#x2F;riscv.h&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+++ b&#x2F;kernel&#x2F;riscv.h&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;@@&lt;&#x2F;span&gt;&lt;span&gt; -38,29 +38,6&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; @@&lt;&#x2F;span&gt;&lt;span&gt; w_mepc(uint64 x)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   asm volatile(&amp;quot;csrw mepc, %0&amp;quot; : : &amp;quot;r&amp;quot; (x));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-&#x2F;&#x2F; physical memory protection CSRs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-#define PMP_R (1L &amp;lt;&amp;lt; 0)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-#define PMP_W (1L &amp;lt;&amp;lt; 1)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-#define PMP_X (1L &amp;lt;&amp;lt; 2)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-&#x2F;&#x2F; naturally aligned power of two&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-#define PMP_MATCH_NAPOT (3L &amp;lt;&amp;lt; 3)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-&#x2F;&#x2F; we only implement accessing one PMP register&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-&#x2F;&#x2F; write to the first 8 PMP configuration registers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-static inline void&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-w_pmpcfg0(uint64 x)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-    asm volatile(&amp;quot;csrw pmpcfg0, %0&amp;quot; : : &amp;quot;r&amp;quot; (x));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-&#x2F;&#x2F; write to the address for PMP region 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-static inline void&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-w_pmpaddr0(uint64 x)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-    asm volatile(&amp;quot;csrw pmpaddr0, %0&amp;quot; : : &amp;quot;r&amp;quot; (x));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &#x2F;&#x2F; Supervisor Status Register, sstatus&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; #define SSTATUS_SPP (1L &amp;lt;&amp;lt; 8)  &#x2F;&#x2F; Previous mode, 1=Supervisor, 0=User&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;diff --git a&#x2F;kernel&#x2F;start.c b&#x2F;kernel&#x2F;start.c&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;index 1c9fffc..4eb6c2d 100644&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;---&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; a&#x2F;kernel&#x2F;start.c&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+++ b&#x2F;kernel&#x2F;start.c&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;@@&lt;&#x2F;span&gt;&lt;span&gt; -7,8 +7,6&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; @@&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; void main();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; void timerinit();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-static void pmpinit();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &#x2F;&#x2F; entry.S needs one stack per CPU.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; __attribute__ ((aligned (16))) char stack0[4096 * NCPU];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;@@&lt;&#x2F;span&gt;&lt;span&gt; -47,36 +45,10&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; @@&lt;&#x2F;span&gt;&lt;span&gt; start()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   int id = r_mhartid();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   w_tp(id);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-  &#x2F;&#x2F; allow access to all physical memory by S mode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-  pmpinit();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   &#x2F;&#x2F; switch to supervisor mode and jump to main().&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   asm volatile(&amp;quot;mret&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-&#x2F;&#x2F; configures the pmp registers trivially so we can boot. it is not permitted&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-&#x2F;&#x2F; to jump to S mode without having these configured as instruction fetch will&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-&#x2F;&#x2F; fail, however we do not actually use them for protection in xv6, so we just&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-&#x2F;&#x2F; need to put something trivial there.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-&#x2F;&#x2F; see section 3.6.1 &amp;quot;Physical Memory Protection CSRs&amp;quot; in the RISC-V privileged&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-&#x2F;&#x2F; specification (v20190608)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-&#x2F;&#x2F; &amp;quot;If no PMP entry matches an M-mode access, the access succeeds. If no PMP&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-&#x2F;&#x2F; entry matches an S-mode or U-mode access, but at least one PMP entry is&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-&#x2F;&#x2F; implemented, the access fails.&amp;quot; (3.6.1)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-static void&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-pmpinit()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-    &#x2F;&#x2F; see figure 3.27 &amp;quot;PMP address register format, RV64&amp;quot; and table 3.10 &amp;quot;NAPOT&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-    &#x2F;&#x2F; range encoding in PMP address and configuration registers&amp;quot; in the RISC-V&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-    &#x2F;&#x2F; privileged specification&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-    &#x2F;&#x2F; we set the bits such that this matches any 56-bit physical address&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-    w_pmpaddr0((~0ULL) &amp;gt;&amp;gt; 10);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-    &#x2F;&#x2F; then we allow the access&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-    w_pmpcfg0(PMP_R | PMP_W | PMP_X | PMP_MATCH_NAPOT);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;-&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &#x2F;&#x2F; set up to receive timer interrupts in machine mode,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &#x2F;&#x2F; which arrive at timervec in kernelvec.S,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; &#x2F;&#x2F; which turns them into software interrupts for&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;一顿修改后编译终于不再卡住了（觉得乱没关系，看后文就好），但是我调试的时候有个奇怪的问题——用 gdb 打印的时候会报：&lt;code&gt;dwarf2_find_location_expression: Corrupted DWARF expression.&lt;&#x2F;code&gt; 的错。&lt;br &#x2F;&gt;
最开始我以为这是 macOS 的问题，想换到 Ubuntu，但我的 Ubuntu 版本是 18.04，而 Xv6 在 Ubuntu 上的安装需要：&lt;code&gt;sudo apt-get install git build-essential gdb-multiarch qemu-system-misc gcc-riscv64-linux-gnu binutils-riscv64-linux-gnu&lt;&#x2F;code&gt;，其中 &lt;code&gt;qemu-system-misc&lt;&#x2F;code&gt; 需要 Ubuntu 的版本为 20 以上，所以我继续回来在 macOS 上想办法，最后在这个 &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mit-pdos&#x2F;xv6-riscv&#x2F;pull&#x2F;129&quot;&gt;PR&lt;&#x2F;a&gt; 中找到了答案：&lt;&#x2F;p&gt;
&lt;p&gt;修改 makefile：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D3C6AA; background-color: #2D353B;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;- CFLAGS = -Wall -Werror -Wno-error=infinite-recursion -O -fno-omit-frame-pointer -ggdb&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;+ CFLAGS = -Wall -Werror -Wno-error=infinite-recursion -O -fno-omit-frame-pointer -ggdb -gdwarf-2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;然后重新编译：&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;make clean &amp;amp;&amp;amp; make CPUS=1 qemu-gdb&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;问题解决！&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;悲报：其实你不用像我这么改，因为我所遇到的问题似乎都被人解决了，只要你把 clone 的 &lt;code&gt;2020&lt;&#x2F;code&gt; 换成 &lt;code&gt;2021&lt;&#x2F;code&gt; 即可，悲伤，两天白玩。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;现在终于可以敲代码做 lab 了。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sleep-easy&quot;&gt;sleep (easy)&lt;&#x2F;h3&gt;
&lt;p&gt;Implement the UNIX program sleep for xv6; your sleep should pause for a user-specified number of ticks. A tick is a notion of time defined by the xv6 kernel, namely the time between two interrupts from the timer chip. Your solution should be in the file user&#x2F;sleep.c.&lt;br &#x2F;&gt;
为 xv6 实现 UNIX 程序 sleep；您的 sleep 应暂停用户指定的 tick 数。tick 是由 xv6 内核定义的时间概念，即来自计时器芯片的两个中断之间的时间。您的解决方案应位于文件 user&#x2F;sleep.c 中。&lt;&#x2F;p&gt;
&lt;p&gt;Some hints:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D3C6AA; background-color: #2D353B;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Before you start coding, read Chapter 1 of the xv6 book.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Look at some of the other programs in user&#x2F; (e.g., user&#x2F;echo.c, user&#x2F;grep.c, and user&#x2F;rm.c) &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    to see how you can obtain the command-line arguments passed to a program.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    If the user forgets to pass an argument, sleep should print an error message.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    The command-line argument is passed as a string; you can convert it to an integer using atoi (see user&#x2F;ulib.c).&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Use the system call sleep.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    See kernel&#x2F;sysproc.c for the xv6 kernel code that implements the sleep system call (look for sys_sleep), &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    user&#x2F;user.h for the C definition of sleep callable from a user program, &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    and user&#x2F;usys.S for the assembler code that jumps from user code into the kernel for sleep.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Make sure main calls exit() in order to exit your program.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Add your sleep program to UPROGS in Makefile; once you&amp;#39;ve done that, &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    make qemu will compile your program and you&amp;#39;ll be able to run it from the xv6 shell.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Look at Kernighan and Ritchie&amp;#39;s book The C programming language (second edition) (K&amp;amp;R) to learn about C.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;这玩意还是相对简单：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D3C6AA; background-color: #2D353B;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;kernel&#x2F;types.h&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;kernel&#x2F;stat.h&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;user&#x2F;user.h&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; argc,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;argv[])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; (argc &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        fprintf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;Usage: sleep x&#x2F;10th of a second...&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        exit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;    sleep&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;atoi&lt;&#x2F;span&gt;&lt;span&gt;(argv[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]));&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;    exit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;测试一下：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D3C6AA; background-color: #2D353B;&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;.&#x2F;grade-lab-util&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; sleep&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;make:&lt;&#x2F;span&gt;&lt;span&gt; `&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;kernel&#x2F;kernel&amp;#39; is up to date.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;== Test sleep, no arguments == sleep, no arguments: OK (1.3s) &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;== Test sleep, returns == sleep, returns: OK (1.1s) &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;== Test sleep, makes syscall == sleep, makes syscall: OK (0.8s) &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;搞定。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;pingpong-easy&quot;&gt;pingpong (easy)&lt;&#x2F;h3&gt;
&lt;p&gt;Write a program that uses UNIX system calls to ‘ping-pong’ a byte between two processes over a pair of pipes, one for each direction. The parent should send a byte to the child; the child should print “&amp;lt;pid&amp;gt;: received ping”, where &amp;lt;pid&amp;gt; is its process ID, write the byte on the pipe to the parent, and exit; the parent should read the byte from the child, print “&amp;lt;pid&amp;gt;: received pong”, and exit. Your solution should be in the file user&#x2F;pingpong.c.&lt;br &#x2F;&gt;
编写一个程序，该程序使用 UNIX 系统调用，通过一对管道在两个进程之间“乒乓”一个字节，每个方向一个。父进程应该向子进程发送一个字节；子进程应打印“&amp;lt;pid&amp;gt;: received ping”，&amp;lt;pid&amp;gt;表示其进程ID，后将管道上的字节写入父进程，然后退出；父进程应从子进程的 pipe 中读取字节，打印“&amp;lt;pid&amp;gt;: received ping”，然后退出。您的解决方案应位于文件 user&#x2F;pingpong.c 中。&lt;&#x2F;p&gt;
&lt;p&gt;Some hints:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D3C6AA; background-color: #2D353B;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Use pipe to create a pipe.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Use fork to create a child.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Use read to read from the pipe, and write to write to the pipe.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Use getpid to find the process ID of the calling process.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Add the program to UPROGS in Makefile.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    User programs on xv6 have a limited set of library functions available to them. &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    You can see the list in user&#x2F;user.h; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    the source (other than for system calls) is in user&#x2F;ulib.c, user&#x2F;printf.c, and user&#x2F;umalloc.c.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;这个就是并不 easy 的 easy lab 了，最开始的时候怎么都有问题，不是交错打印就是提前退出，上网查找，主流的解决方案是用两个 pipe：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D3C6AA; background-color: #2D353B;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;kernel&#x2F;types.h&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;user&#x2F;user.h&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;#define&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; READEND 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;#define&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; WRITEEND 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; argc,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;argv[]) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;    int&lt;&#x2F;span&gt;&lt;span&gt; p1[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;    int&lt;&#x2F;span&gt;&lt;span&gt; p2[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;    int&lt;&#x2F;span&gt;&lt;span&gt; pid;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;    char&lt;&#x2F;span&gt;&lt;span&gt; buf[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;    pipe&lt;&#x2F;span&gt;&lt;span&gt;(p1);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;    pipe&lt;&#x2F;span&gt;&lt;span&gt;(p2);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    pid &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; fork&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; (pid &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        exit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;    else if&lt;&#x2F;span&gt;&lt;span&gt; (pid &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        close&lt;&#x2F;span&gt;&lt;span&gt;(p1[WRITEEND]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        close&lt;&#x2F;span&gt;&lt;span&gt;(p2[READEND]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        read&lt;&#x2F;span&gt;&lt;span&gt;(p1[READEND], buf,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;: received ping&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; getpid&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        write&lt;&#x2F;span&gt;&lt;span&gt;(p2[WRITEEND],&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot; &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        close&lt;&#x2F;span&gt;&lt;span&gt;(p1[READEND]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        close&lt;&#x2F;span&gt;&lt;span&gt;(p2[WRITEEND]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        exit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        close&lt;&#x2F;span&gt;&lt;span&gt;(p1[READEND]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        close&lt;&#x2F;span&gt;&lt;span&gt;(p2[WRITEEND]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        write&lt;&#x2F;span&gt;&lt;span&gt;(p1[WRITEEND],&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot; &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        read&lt;&#x2F;span&gt;&lt;span&gt;(p2[READEND], buf,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;: received pong&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; getpid&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        close&lt;&#x2F;span&gt;&lt;span&gt;(p1[WRITEEND]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        close&lt;&#x2F;span&gt;&lt;span&gt;(p2[READEND]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        exit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;这个 lab 如果需要提示，就是用两个 pipe，一个接一个发（没有化很遗憾，对不起马老师）；&lt;br &#x2F;&gt;
但我最开始写的时候想用一个 pipe 就解决问题，所以更接近这个答案：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D3C6AA; background-color: #2D353B;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;kernel&#x2F;types.h&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;kernel&#x2F;stat.h&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;user&#x2F;user.h&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; argc,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;argv[]) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;    int&lt;&#x2F;span&gt;&lt;span&gt; p[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;    char&lt;&#x2F;span&gt;&lt;span&gt; buf[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;    char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;parmsg &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;    char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;chimsg &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;b&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;    pipe&lt;&#x2F;span&gt;&lt;span&gt;(p);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;fork&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;){&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(p[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;], buf,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;){&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;            fprintf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;Can&amp;#39;t read from parent!&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;            exit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;child receive: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;%c\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, buf[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        close&lt;&#x2F;span&gt;&lt;span&gt;(p[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;: received ping&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; getpid&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(p[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;], chimsg,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;){&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;            fprintf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;Can&amp;#39;t write to parent!&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        close&lt;&#x2F;span&gt;&lt;span&gt;(p[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        exit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(p[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;], parmsg,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;){&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;            fprintf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;Can&amp;#39;t write to child!&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;            exit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        close&lt;&#x2F;span&gt;&lt;span&gt;(p[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        wait&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(p[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;], buf,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;){&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;            fprintf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;Can&amp;#39;t read from child!&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;            exit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;parent receive: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;%c\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, buf[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        close&lt;&#x2F;span&gt;&lt;span&gt;(p[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;: received pong&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; getpid&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        exit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;如果我一上来就写成这样也不会说这道题难了，我写的是这样的：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D3C6AA; background-color: #2D353B;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;kernel&#x2F;types.h&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;kernel&#x2F;stat.h&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;user&#x2F;user.h&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; argc,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;argv[]) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;    int&lt;&#x2F;span&gt;&lt;span&gt; p[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;    char&lt;&#x2F;span&gt;&lt;span&gt; buf[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;    char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;parmsg &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;    char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;chimsg &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;b&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;    pipe&lt;&#x2F;span&gt;&lt;span&gt;(p);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;fork&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;){&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(p[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;], buf,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;){&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;            fprintf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;Can&amp;#39;t read from parent!&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;            exit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;child receive: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;%c\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, buf[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        close&lt;&#x2F;span&gt;&lt;span&gt;(p[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;: received ping&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; getpid&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(p[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;], chimsg,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;){&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;            fprintf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;Can&amp;#39;t write to parent!&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        close&lt;&#x2F;span&gt;&lt;span&gt;(p[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        exit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(p[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;], parmsg,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;){&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;            fprintf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;Can&amp;#39;t write to child!&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;            exit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        close&lt;&#x2F;span&gt;&lt;span&gt;(p[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(p[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;], buf,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;){&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;            fprintf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;Can&amp;#39;t read from child!&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;            exit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;parent receive: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;%c\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, buf[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        close&lt;&#x2F;span&gt;&lt;span&gt;(p[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;: received pong&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; getpid&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        wait&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        exit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;区别在于 &lt;code&gt;wait(0)&lt;&#x2F;code&gt; 的位置。我的版本，输出一般是这样的：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D3C6AA; background-color: #2D353B;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ pingpong&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;parent receive: a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3: received pong&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;代码会直接阻塞住，为了找出 Bug，我去掉了 &lt;code&gt;wait(0)&lt;&#x2F;code&gt;，输出开始有一些变化了：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D3C6AA; background-color: #2D353B;&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;kernel&#x2F;types.h&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;kernel&#x2F;stat.h&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;#include&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;user&#x2F;user.h&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;int&lt;&#x2F;span&gt;&lt;span&gt; argc,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;argv[]){&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;    int&lt;&#x2F;span&gt;&lt;span&gt; p[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;    char&lt;&#x2F;span&gt;&lt;span&gt; buf[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;    char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;parmsg &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;a&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;    char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt;chimsg &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;b&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;    pipe&lt;&#x2F;span&gt;&lt;span&gt;(p);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;fork&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt;){&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(p[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;], buf,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;){&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;            fprintf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;Can&amp;#39;t read from parent!&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;            exit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;child receive: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;%c\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, buf[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        close&lt;&#x2F;span&gt;&lt;span&gt;(p[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;: received ping&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; getpid&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(p[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;], chimsg,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;){&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;            fprintf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;Can&amp;#39;t write to parent!&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        close&lt;&#x2F;span&gt;&lt;span&gt;(p[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        exit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;write&lt;&#x2F;span&gt;&lt;span&gt;(p[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;], parmsg,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;){&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;            fprintf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;Can&amp;#39;t write to child!&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;            exit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        close&lt;&#x2F;span&gt;&lt;span&gt;(p[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;read&lt;&#x2F;span&gt;&lt;span&gt;(p[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;], buf,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;){&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;            fprintf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt; &amp;quot;Can&amp;#39;t read from child!&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;            exit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;parent receive: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;%c\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, buf[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        close&lt;&#x2F;span&gt;&lt;span&gt;(p[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;]);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        printf&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;%d&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;: received pong&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; getpid&lt;&#x2F;span&gt;&lt;span&gt;());&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;        exit&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;输出是这样的：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D3C6AA; background-color: #2D353B;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ pingpong&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;parent receive: a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3: received pong&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ pingpong&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;parent receive: a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;5: received pong&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ pingpong&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;parent receive: a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;7: received pong&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ pingpong&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;parent receive: a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;9: received pong&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ pingpong&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;parent receive: a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;11: received pong&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ pingpong&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;parent receive: a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;13: received pong&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ pingpong&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;child receive: a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;16: received ping&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;parent receive: b&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;15: received pong&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ QEMU: Terminated&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;可以看到最后还是正常运行了一次，其余都是错误输出，为什么会这样呢？关键在 pipe 上。&lt;&#x2F;p&gt;
&lt;p&gt;在 xv6 中通过系统调用 &lt;code&gt;pipe(int p[])&lt;&#x2F;code&gt; 可以创建一个匿名管道，然后将对应管道读端的文件描述符放入 &lt;code&gt;p[0]&lt;&#x2F;code&gt;，对应管道写端的文件描述符放入 &lt;code&gt;p[1]&lt;&#x2F;code&gt;。&lt;code&gt;p[0]&lt;&#x2F;code&gt; 是具有只读属性的文件描述符，&lt;code&gt;p[1]&lt;&#x2F;code&gt; 是具有只写属性的文件描述符。&lt;&#x2F;p&gt;
&lt;p&gt;匿名管道底下对应的文件没有文件名，因此只能被有亲缘的进程打开。实际情形如下图所示&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;..&#x2F;..&#x2F;images&#x2F;legacy&#x2F;2023&#x2F;pipe.svg&quot; loading=&quot;lazy&quot; &#x2F;&gt; 子进程与父进程之间通过匿名管道通信&lt;&#x2F;p&gt;
&lt;p&gt;为什么子进程不需要等待父进程的写入先完成？&lt;br &#x2F;&gt;
答案是，在管道上的 &lt;code&gt;read&lt;&#x2F;code&gt; 是阻塞的。在没有数据可读时，在管道上的 &lt;code&gt;read&lt;&#x2F;code&gt; 会一直阻塞，直到要么有新的数据被写入，或者管道的所有写端都被关闭。在后者的情况下，&lt;code&gt;read&lt;&#x2F;code&gt; 会返回 0。也正因为这个特性，所有不需要写入数据的子进程，都应该主动关闭掉管道的写端。&lt;&#x2F;p&gt;
&lt;p&gt;在我的程序中出现了这样的输出：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D3C6AA; background-color: #2D353B;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;parent receive: a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3: received pong&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;一个可能是：&lt;code&gt;else&lt;&#x2F;code&gt; 分支也就是父进程的 &lt;code&gt;write&lt;&#x2F;code&gt; 被同在 &lt;code&gt;else&lt;&#x2F;code&gt; 分支的 &lt;code&gt;read&lt;&#x2F;code&gt;（也就是它自己的）消耗掉了，所以 &lt;code&gt;parent receive&lt;&#x2F;code&gt; 才是 &lt;code&gt;a&lt;&#x2F;code&gt; 而不是 &lt;code&gt;b&lt;&#x2F;code&gt;。&lt;br &#x2F;&gt;
&lt;code&gt;write&lt;&#x2F;code&gt; 操作是在 &lt;code&gt;read&lt;&#x2F;code&gt; 操作之前完成的，因此在 &lt;code&gt;read&lt;&#x2F;code&gt; 操作之前，数据已经被写入管道中，且管道中的数据已经准备好被读取。因此，可以保证在 &lt;code&gt;read&lt;&#x2F;code&gt; 操作中能够读取到 &lt;code&gt;write&lt;&#x2F;code&gt; 操作写入的数据。&lt;br &#x2F;&gt;
正常的程序，父进程写入管道的数据应该被子进程消耗掉才对。如果不加 &lt;code&gt;wait(0)&lt;&#x2F;code&gt;：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;运气好，就像最后一次输出，非常凑巧，顺序恰好和把 &lt;code&gt;wait(0)&lt;&#x2F;code&gt; 放在父进程 &lt;code&gt;write&lt;&#x2F;code&gt; 之后那里的顺序一致：在父进程 &lt;code&gt;write&lt;&#x2F;code&gt; 之后等待子进程退出，这样能够保证父进程的 &lt;code&gt;write&lt;&#x2F;code&gt; 一定是由子进程的 &lt;code&gt;read&lt;&#x2F;code&gt; 消耗掉的，同时子进程 &lt;code&gt;write&lt;&#x2F;code&gt; 一个字节后直接执行结束，父进程就可以 &lt;code&gt;read&lt;&#x2F;code&gt; 到值了；&lt;&#x2F;li&gt;
&lt;li&gt;运气不好，遇到先运行父进程一直到 &lt;code&gt;wait&lt;&#x2F;code&gt; 调用而没来得及运行子进程的情况，就会出现这样的问题：子进程的 &lt;code&gt;read&lt;&#x2F;code&gt; 会一直阻塞，因为父进程的 &lt;code&gt;write&lt;&#x2F;code&gt; 被它自己的 &lt;code&gt;read&lt;&#x2F;code&gt; 给消耗掉了，此时没有谁来再给管道写入值了，再加上子进程还要给父进程 &lt;code&gt;write&lt;&#x2F;code&gt; 一个字节，所以它还不能在开头直接 &lt;code&gt;close(p[1]);&lt;&#x2F;code&gt;，&lt;code&gt;read&lt;&#x2F;code&gt; 返回的第二个条件也不满足，所以子进程的 &lt;code&gt;read&lt;&#x2F;code&gt; 会一直阻塞。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;问题解决。看似很小的问题，其实也有一点原子的味道，如果给 pipe 上锁，是不是就不会出现这个问题了？值得思考。&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="zh-CN">
        <title>从 Happened-before 说起（2）</title>
        <published>2023-04-03T00:00:00+00:00</published>
        <updated>2023-04-03T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://whx828.com/posts/happened-before-2/"/>
        <id>https://whx828.com/posts/happened-before-2/</id>
        
        <content type="html" xml:base="https://whx828.com/posts/happened-before-2/">&lt;p&gt;书接上文，继续讨论那个让人疑惑的问题。&lt;br &#x2F;&gt;
为了方便讨论，我把代码挪过来：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D3C6AA; background-color: #2D353B;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;static&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; X&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; AtomicI32&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; AtomicI32&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;static&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; AtomicI32&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; AtomicI32&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; a&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;    X&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;store&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Relaxed&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #859289;font-style: italic;&quot;&gt;    &#x2F;&#x2F; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;    Y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;store&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;20&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Relaxed&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #859289;font-style: italic;&quot;&gt;    &#x2F;&#x2F; 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; b&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;load&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;Relaxed&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #859289;font-style: italic;&quot;&gt; &#x2F;&#x2F; 3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; X&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;load&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;Relaxed&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #859289;font-style: italic;&quot;&gt; &#x2F;&#x2F; 4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;} {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;y&lt;&#x2F;span&gt;&lt;span&gt;}&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;More interestingly, the output can also be 0 20, even though there is no possible globally consistent order of the four operations that would result in this outcome. When 3 is executed, there is no happens-before relationship with 2, which means it could load either 0 or 20. When 4 is executed, there is no happens-before relationship with 1, which means it could load either 0 or 10. Given this, the output 0 20 is a valid outcome.&lt;br &#x2F;&gt;
更有趣的是，输出也可以是 0 20，即使没有可能导致此结果的四个操作的全局一致顺序。当 3 执行时，与 2 没有 happens-before 关系，也就是说它可以加载 0 或 20。当 4 执行时，与 1 没有 happens-before 关系，这意味着它可以加载 0 或 10。鉴于此，输出 0 20 是一个有效的结果。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;想要彻底搞明白，还得从概念的细节下手：&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;…the basic happens-before rule is that everything that happens within the same thread happens in order. In this case: 1 happens-before 2, and 3 happens-before 4. Since we use relaxed memory ordering, there are no other happens-before relationships in our example.&lt;br &#x2F;&gt;
……基本的 happens-before 规则是同一线程内发生的所有事情都按顺序发生。在这种情况下：1 happens-before 2，3 happens-before 4。由于我们使用 &lt;code&gt;Relaxed&lt;&#x2F;code&gt; 内存排序，因此在我们的示例中没有其他 happens-before 关系。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;那到底什么是 happened-before？这里是维基百科给的定义：&lt;&#x2F;p&gt;
&lt;p&gt;In &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; title=&quot;Computer science&quot; href=&quot;https:&#x2F;&#x2F;www.wikiwand.com&#x2F;en&#x2F;Computer_science&quot;&gt;computer science&lt;&#x2F;a&gt;, the &lt;strong&gt;happened-before&lt;&#x2F;strong&gt; &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; title=&quot;Binary relation&quot; href=&quot;https:&#x2F;&#x2F;www.wikiwand.com&#x2F;en&#x2F;Binary_relation&quot;&gt;relation&lt;&#x2F;a&gt; (denoted: →) is a relation between the result of two events, such that if one event should happen before another event, the result must reflect that, even if those events are in reality executed out of order (usually to optimize program flow). This involves &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; title=&quot;Partially ordered set&quot; href=&quot;https:&#x2F;&#x2F;www.wikiwand.com&#x2F;en&#x2F;Partially_ordered_set&quot;&gt;ordering&lt;&#x2F;a&gt; events based on the potential &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; title=&quot;Causal relationships&quot; href=&quot;https:&#x2F;&#x2F;www.wikiwand.com&#x2F;en&#x2F;Causal_relationships&quot;&gt;causal relationship&lt;&#x2F;a&gt; of pairs of events in a concurrent system, especially &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; title=&quot;Asynchronous communication&quot; href=&quot;https:&#x2F;&#x2F;www.wikiwand.com&#x2F;en&#x2F;Asynchronous_communication&quot;&gt;asynchronous&lt;&#x2F;a&gt; &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; title=&quot;Distributed systems&quot; href=&quot;https:&#x2F;&#x2F;www.wikiwand.com&#x2F;en&#x2F;Distributed_systems&quot;&gt;distributed systems&lt;&#x2F;a&gt;. It was formulated by &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; title=&quot;Leslie Lamport&quot; href=&quot;https:&#x2F;&#x2F;www.wikiwand.com&#x2F;en&#x2F;Leslie_Lamport&quot;&gt;Leslie Lamport&lt;&#x2F;a&gt;.&lt;br &#x2F;&gt;
在计算机科学中，happened-before 关系（表示为：→）是两个事件的结果之间的关系，这样如果一个事件应该在另一个事件之前发生，那么即使这些事件在现实中发生，结果也必须反映出来乱序执行（通常是为了优化程序流程）。这涉及根据并发系统中事件对的潜在因果关系对事件进行排序，尤其是异步分布式系统。它是由 Leslie Lamport 制定的。&lt;&#x2F;p&gt;
&lt;p&gt;The happened-before relation is formally defined as the least &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; title=&quot;Strict partial order&quot; href=&quot;https:&#x2F;&#x2F;www.wikiwand.com&#x2F;en&#x2F;Strict_partial_order&quot;&gt;strict partial order&lt;&#x2F;a&gt; on events such that:&lt;br &#x2F;&gt;
happened-before 关系的正式定义为──事件最不严格的偏序，使得：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;If events a and b occur on the same process, a → b if the occurrence of event a preceded the occurrence of event b.&lt;br &#x2F;&gt;
如果事件 a 和 b 在同一进程上，则 a → b。事件 a 的发生先于事件 b 的发生。&lt;&#x2F;li&gt;
&lt;li&gt;If event a is the sending of a message and event b is the reception of the message sent in event a, a → b.&lt;br &#x2F;&gt;
如果事件 a 是消息的发送者，事件 b 是 a 发送的消息的接收者，则 a → b。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If two events happen in different isolated processes (that do not exchange messages directly or indirectly via third-party processes), then the two processes are said to be concurrent, that is neither a → b nor b → a is true.&lt;br &#x2F;&gt;
如果两个事件发生在不同的隔离进程中（不直接或通过第三方进程间接交换消息），则称这两个进程是并发的，a → b 和 b → a 都不成立。&lt;&#x2F;p&gt;
&lt;p&gt;If there are other causal relationships between events in a given system, such as between the creation of a process and its first event, these relationships are also added to the definition. For example, in some programming languages such as Java, C, C++ or Rust, a &lt;strong&gt;happens-before&lt;&#x2F;strong&gt; edge exists if memory written to by statement A is visible to statement B, that is, if statement A completes its write before statement B starts its read.&lt;br &#x2F;&gt;
如果给定系统中的事件之间存在其他因果关系，例如进程的创建与此进程第一个事件之间的因果关系，这些关系也会添加到定义中。例如，在某些编程语言中，如 Java、C、C++ 或 Rust，如果语句 A 写入的内存对语句 B 可见，即如果语句 A 在语句 B 开始读取之前完成了写入，则存在 happens-before 关系。&lt;&#x2F;p&gt;
&lt;p&gt;The processes that make up a distributed system have no knowledge of the happened-before relation unless they use a &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; title=&quot;Logical clock&quot; href=&quot;https:&#x2F;&#x2F;www.wikiwand.com&#x2F;en&#x2F;Logical_clock&quot;&gt;logical clock&lt;&#x2F;a&gt;, like a &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; title=&quot;Lamport clock&quot; href=&quot;https:&#x2F;&#x2F;www.wikiwand.com&#x2F;en&#x2F;Lamport_clock&quot;&gt;Lamport clock&lt;&#x2F;a&gt; or a &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; title=&quot;Vector clock&quot; href=&quot;https:&#x2F;&#x2F;www.wikiwand.com&#x2F;en&#x2F;Vector_clock&quot;&gt;vector clock&lt;&#x2F;a&gt;. This allows one to design algorithms for &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; title=&quot;Mutual exclusion&quot; href=&quot;https:&#x2F;&#x2F;www.wikiwand.com&#x2F;en&#x2F;Mutual_exclusion&quot;&gt;mutual exclusion&lt;&#x2F;a&gt;, and tasks like debugging or optimising distributed systems.&lt;br &#x2F;&gt;
构成分布式系统的进程之间没有 happened-before 关系，除非它们使用逻辑时钟，如 Lamport 时钟或矢量时钟。这允许人们设计互斥算法，以及调试或优化分布式系统等任务。&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;维基百科的定义更加明确：happened-before 表征的是一个事件应该在另一个事件之前发生。在这个例子中，我们只能肯定的是：操作 1 happened-before 操作 2，操作 3 happened-before 操作 4，其他什么都无法肯定，即使你看到了程序输出 &lt;code&gt;0 20&lt;&#x2F;code&gt; 也不意味着操作 4 在操作 1 之前发生或者操作 2 在操作 3 之前发生，换句话说，正是因为你使用的是 &lt;code&gt;Relaxed&lt;&#x2F;code&gt; 内存排序，Rust 也就放弃提供跨线程的操作顺序的保证了，而我觉得无法理解是因为我之前认为 &lt;code&gt;0 20&lt;&#x2F;code&gt; 根本就无法发生，但真的不会吗？来看看 GPT-4 的回答：&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;在多线程环境中，使用 &lt;code&gt;Relaxed&lt;&#x2F;code&gt; 内存排序的原子操作不会产生跨线程的 happened-before 关系。这意味着，当线程执行操作 3 时，我们不能确定操作 2 是否已经发生。同样地，当线程执行操作 4 时，我们也不能确定操作 1 是否已经发生。&lt;&#x2F;p&gt;
&lt;p&gt;以下是可能导致输出 0 20 的一种情况：&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;线程 a 执行操作 1，将 X 设置为 10。&lt;&#x2F;li&gt;
&lt;li&gt;线程 b 执行操作 3，加载 Y 的值。此时，线程 a 尚未执行操作 2，因此 Y 的值仍然是 0。所以，操作 3 加载的值是 0。&lt;&#x2F;li&gt;
&lt;li&gt;线程 a 执行操作 2，将 Y 设置为 20。&lt;&#x2F;li&gt;
&lt;li&gt;线程 b 执行操作 4，加载 X 的值。此时，线程 a 已经执行了操作 1，但由于没有跨线程的 happens-before 关系，线程 b 仍然可以看到 X 的旧值 0。因此，操作 4 加载的值是 0。&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;这就是为什么输出可能是 0 20。在这种情况下，线程 b 观察到的操作顺序实际上是：操作 3、操作 4、操作 1、操作 2。这个例子说明了在使用 &lt;code&gt;Relaxed&lt;&#x2F;code&gt; 内存排序时，不同线程之间的操作顺序是不确定的，可能导致一些看似违反直觉的结果。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;我对这个答案不是很满意，它并未说服我，所以我接着追问：&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;为什么没有跨线程的 happened-before 关系，线程 b 就可以看到 X 的旧值 0 呢？（这也的确是我最核心的疑问）&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;当没有跨线程的 happened-before 关系时，线程 b 可以看到 X 的旧值 0，是因为内存顺序、编译器优化和处理器行为可能导致数据在不同线程之间的可见性有延迟。在我们的例子中，由于使用了 &lt;code&gt;Relaxed&lt;&#x2F;code&gt; 内存排序，编译器和处理器对操作的优化和重排更加自由。这可能导致线程 a 对 X 的写入操作（操作 1）在线程 b 观察到之前存在一定的延迟。以下是一些可能导致这种现象的因素：&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;编译器优化：编译器可能会对代码进行优化，以提高执行效率。在 &lt;code&gt;Relaxed&lt;&#x2F;code&gt; 内存排序下，编译器可以自由地重新排序操作，只要它们在单个线程中的顺序保持不变。这种优化可能导致线程 b 在观察到线程 a 对 X 的写入操作之前存在延迟。&lt;&#x2F;li&gt;
&lt;li&gt;处理器缓存：现代处理器通常具有多级缓存，用于加速内存访问。当一个线程对内存位置进行写操作时，这个改动可能首先出现在处理器的缓存中，而不是立即写回到主存。在没有强制 happened-before 关系的情况下，其他线程可能在一段时间内仍然看到旧的值。&lt;&#x2F;li&gt;
&lt;li&gt;处理器指令重排：为了提高执行效率，处理器可能会对指令进行重排。这意味着实际执行的指令顺序可能与代码中的顺序不同。在 &lt;code&gt;Relaxed&lt;&#x2F;code&gt; 内存排序下，指令重排可能导致线程 b 在观察到线程 a 对 X 的写入操作之前存在延迟。&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;因此，在没有跨线程的 happened-before 关系的情况下，线程 b 可能看到 X 的旧值 0，是由于编译器优化、处理器缓存和处理器指令重排等因素导致的内存访问延迟。这些因素使得线程之间的操作顺序和数据可见性变得不确定。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;GPT-4 提供了几种可能会发生的场景，成功说服了我，因为真的有可能发生。同时我也对内存排序是如何做到的有了新的理解，这并不完全是 Rust 语言本身能决定的事情，你要考虑延迟、缓存、编译器，甚至还需要硬件、处理器的配合，那么这其中的自由度和复杂度就不是常人能全部考虑到的。&lt;&#x2F;p&gt;
&lt;p&gt;行文至此，再次感觉到编程的复杂，看起来简单的内存排序竟会在背后包含如此复杂的内容，不得不感叹计算机是一个整体，到了一定复杂度以后很难完全抽象出单一元素来完备地解答问题。如此发展下去，恐怕到最后也只有机器能解答机器了吧。&lt;&#x2F;p&gt;
&lt;p&gt;另外 AI 的确不失为一种很棒的学习工具，GPT-4 并不是一次性就给出了上述回答，它前几次的回答有错误，考虑到避免误导，我就没有把错误的对话也放上来，有的时候答案其实并不重要，如果能正确地发问，其实有些时候问题也就解决了。&lt;br &#x2F;&gt;
目前的 GPT 模型其实效果已经相当好了，但依然存在一本正经地胡说行为，因此如果想用它来学习，你最好有能分辨答案是否正确的能力，这又有些悖论了，我如果有这个能力，往往就没那么需要再问了。&lt;&#x2F;p&gt;
&lt;p&gt;从维基百科中可以得知 happened-before 是由 Leslie Lamport 这位分布式大牛提出的，happened-before 是为了一个更大的问题所做的铺垫，这个问题就是分布式系统中的时间。分布式系统中相当多的概念和算法都需要依靠 happened-before 这个偏序关系，说它是构成分布式世界的基石一点也不为过，详细的展开则要去读《Time, Clocks, and the Ordering of Events in a Distributed System》这篇论文才能知道了。&lt;&#x2F;p&gt;
&lt;p&gt;其实 happened-before 还有许多部分可以展开，不过鄙人才疏学浅，目前只掌握了这些，或许以后还会写点自己的心得体会吧，敬请期待。&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="zh-CN">
        <title>从 Happened-before 说起（1）</title>
        <published>2023-03-22T00:00:00+00:00</published>
        <updated>2023-03-22T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://whx828.com/posts/happened-before-1/"/>
        <id>https://whx828.com/posts/happened-before-1/</id>
        
        <content type="html" xml:base="https://whx828.com/posts/happened-before-1/">&lt;blockquote&gt;
&lt;p&gt;本文大部分是背景介绍，本来想一气呵成，但发现要讲的东西有点多，遂分成了两篇来写。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;m-ou.se&#x2F;&quot;&gt;Mara Bos&lt;&#x2F;a&gt; 关于并发主题的新书 &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;marabos.nl&#x2F;atomics&#x2F;&quot;&gt;Rust Atomics and Locks&lt;&#x2F;a&gt; 最近可以免费在线阅读了，这位 Rust Library team 的 Leader 自不必多说，对 Rust 的理解（贡献）非是常人可比，而这次 Mara 博士这次的慷慨更是让手头常年拮据学生党（鄙人）直呼老铁 666！&lt;del&gt;耶，是官方的白嫖！&lt;&#x2F;del&gt;&lt;&#x2F;p&gt;
&lt;p&gt;玩笑差不多了，说正事。&lt;br &#x2F;&gt;
尽管鄙人的英语是中国人水平，但为了学点 Rust，困难可以克服（感谢谷歌翻译+DeepL+ChatGPT），这本书不长，但想要读透，真正领会作者的思想，要花好多功夫。在一众翻译软件的帮助下，我简单阅读了这本书的前几章内容，其中第一个令我印象深刻的内容当属第 3 章中提到的也是我们今天的主题：Happened-before 关系。&lt;&#x2F;p&gt;
&lt;p&gt;要讨论 Happened-before 关系，说来话长，让我们保持耐心，先从简单的计算机历史说起。&lt;br &#x2F;&gt;
最初的计算机工作非常简单，只要把一些简单繁琐的计算任务搞定即可，在真空管和穿孔打卡的时代，程序员是把程序写到纸上，你没看错，是纸，然后在纸上穿孔，如此反复操作，直到穿成厚厚的一摞，再把这一摞交给计算机，计算机计算结果打印出来，然后程序员拿到打印结果。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;这就是最开始的 IO。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;用今天的眼光看那时的程序员也太不容易了，纸上编程确实有助于学习编码和思考代码逻辑，但如果真要把干活的程序写在纸上再去穿孔才能执行，这种繁琐、浪费是现在的程序员所无法想象的（谁愿意天天穿孔），你可能会问：如果我就运行自己的程序行不行，答案是不行！在当时计算机的资源是相当昂贵的，没有那么多机器让你一个人玩，就像买东西太贵选择拼单一样，你写程序也要和人拼计算机，所谓批处理就是这么一回事，名字起得挺高深，实际上背后一把辛酸泪。&lt;&#x2F;p&gt;
&lt;p&gt;这样的 IO 用脚趾头想都能想到肯定会和 CPU 的速度存在巨大差异，CPU 的计算时间非常少而等待 IO 结束的时间却很多。所以为了 &lt;del&gt;让 CPU 更累&lt;&#x2F;del&gt; 更合理地利用 CPU 计算资源，我们就得想个办法，看能不能「偷」点时间出来。后来不知道哪位天使大哥&#x2F;大姐想到了一个鬼点子：我们可以把内存划分为多个部分（日子宽裕了，内存也比以前大了，可以让更多程序用了），不同的程序可以使用各自的内存部分互不干涉，这些单独的程序就是所谓的进程。然后我们给 CPU 再加上一个超能力：跨进程切换执行。这样就有戏法可以玩了：当某个进程进行磁盘 IO 的时候，CPU 就可以切换到另外一个进程执行（闲着也是闲着，不如干点别的活），这样就 &lt;del&gt;让 CPU 更累&lt;&#x2F;del&gt; 偷出了本来可以摸鱼（等待 IO）的时间来干活（运行其他进程），我们的目的达到了！（能力越大，责任就越大嘛~）&lt;&#x2F;p&gt;
&lt;p&gt;怎么给 CPU 加上跨进程切换执行的超能力呢？请看三板斧：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;CPU 时间片：现在我们有很多进程，所以对于每个进程如何执行，需要有个规定──每一次切换进程后，CPU 只会工作一段时间，然后又切换到另外一个进程，再执行一段时间。我们把 CPU 切换进程的这个时间段叫做“时间片”。&lt;&#x2F;li&gt;
&lt;li&gt;程序计数器：CPU 经过一圈切换后还会切换回最开始的进程继续执行（对每个进程都是如此），所以它需要知道进程已经执行到了哪一步才好接着执行，程序计数器应运而生，它会记住进程执行到的位置。有了这个就可以继续执行了。&lt;&#x2F;li&gt;
&lt;li&gt;栈指针：程序计数器解决了记忆程序（代码）执行到的位置，但是每个进程还持有操作系统分配给它的内存资源，这玩意对每个进程是独立的，因此也需要记录，所以我们用栈指针来记录操作系统给它的内存资源地址。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;这三板斧下去，CPU 再也不好摸鱼了，比起以前，那效率是高多了，但是人类对于极致的追求是无止境的，大家慢慢发现切换进程这个操作本身居然挺费时间，如果每个进程都有很多 IO，那么 CPU 的时间都被切换进程浪费掉了，然后还什么都没做，这不是又让 CPU 闲着了吗？不行，必须要解决！&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;这只是一个缺点，相关的缺点还有很多，不一一列举了。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;进程切换成本这么高，一部分的原因是进程太「重」了，每切换一次上面的三板斧都得顾及到，那么让它变得小一点不就好了吗？这就是线程：我们让一个进程创建很多个线程，然后让线程来做以前进程的工作，现在 CPU 会在线程而不是进程之间来回切换，由于线程更小，时间片也分得更小，以至于多个线程之间切换执行成本也小了，同时 CPU 等待 IO 的几率也更加小了。一举多得。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;线程版本的三板斧：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;程序计数器，表示当前线程执行指令的位置。&lt;&#x2F;li&gt;
&lt;li&gt;保存变量的寄存器。&lt;&#x2F;li&gt;
&lt;li&gt;栈。每个线程的栈记录了函数调用的记录，并反映了当前线程的执行点。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;技术领域有一句名言：没有银弹。意思是不管什么问题，没有万能解决方案。多线程也不是没缺点，对程序员来说最直观的感受就是：多线程编程更难。为什么？因为在多线程编程的场景下，你会经常遇到「多个线程同时读取和修改同一个变量」的问题，而在 Rust 中，我们认为“这通常会导致未定义的行为（UB）”。&lt;&#x2F;p&gt;
&lt;p&gt;为什么“多个线程同时读取和修改同一个变量”会是个问题？这不是效率更高了吗？请看下面的伪代码：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D3C6AA; background-color: #2D353B;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;data_race() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  global x = 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  thread1 = thread {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    for i in 0..100 {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      x += 1;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  thread2 = thread {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    for i in 0..100 {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      x += 1;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  };&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  t1 = thread1.spawn();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  t2 = thread2.spawn();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  t1.join();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  t2.join();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  return x;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;之所以写伪代码是因为用 Rust 想写个有问题的程序着实不容易。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;伪代码说明（虽然我希望这是不言自明的）：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;global x = 0&lt;&#x2F;code&gt; 表示 &lt;code&gt;x&lt;&#x2F;code&gt; 是个全局变量，每个线程都能看到并修改它的值&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;thread1 =  thread { for i in 0..100 { x += 1; } };&lt;&#x2F;code&gt; 表示 &lt;code&gt;thread1&lt;&#x2F;code&gt; 对 &lt;code&gt;x&lt;&#x2F;code&gt; 进行 100 次加 1 操作，这是 &lt;code&gt;thread1&lt;&#x2F;code&gt; 的定义&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;t1 = thread1.spawn();&lt;&#x2F;code&gt; 则是启动 &lt;code&gt;thread1&lt;&#x2F;code&gt;，&lt;code&gt;thread1&lt;&#x2F;code&gt; 自此开始执行&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;thread1.join();&lt;&#x2F;code&gt; 表示当前线程（主线程）将一直等待 &lt;code&gt;thread1&lt;&#x2F;code&gt; 执行结束&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;thread2&lt;&#x2F;code&gt; 上述一切同理&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;请猜想下，这段程序执行到 &lt;code&gt;return x;&lt;&#x2F;code&gt; 时，&lt;code&gt;x&lt;&#x2F;code&gt; 的值会是多少？&lt;&#x2F;p&gt;
&lt;p&gt;答案是：只有天知道，理论上在 100-200 之间的任何整数值都有可能。&lt;&#x2F;p&gt;
&lt;p&gt;你可能会问：&lt;code&gt;x&lt;&#x2F;code&gt; 不是 &lt;code&gt;200&lt;&#x2F;code&gt; 吗？&lt;br &#x2F;&gt;
&lt;code&gt;x&lt;&#x2F;code&gt; 不一定会是 &lt;code&gt;200&lt;&#x2F;code&gt;，这就是多线程编程的吊诡之处，很反直觉。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;更反直觉的还在后面。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;试想下面的过程：&lt;br &#x2F;&gt;
（1）CPU 时间片先分给 &lt;code&gt;thread1&lt;&#x2F;code&gt; 执行，假设代表 &lt;code&gt;x&lt;&#x2F;code&gt; 这个变量的寄存器在 &lt;code&gt;thread1&lt;&#x2F;code&gt; 中执行累加到了 50，此时恰巧时间片用完了，而存放在寄存器中的值 50 还没来及写入实际的物理内存。&lt;br &#x2F;&gt;
（2）因为时间片用完了，CPU 现在分配给 &lt;code&gt;thread2&lt;&#x2F;code&gt;，由于 &lt;code&gt;thread1&lt;&#x2F;code&gt; 算出来的值并没有写回内存，所以实际上此时 &lt;code&gt;thread2&lt;&#x2F;code&gt; 还是从 &lt;code&gt;x = 0&lt;&#x2F;code&gt; 开始进行加 1 操作，这次我们假设分给它的时间片够进行 60 次加 1 操作，之后 &lt;code&gt;thread2&lt;&#x2F;code&gt; 将得到的 &lt;code&gt;x = 60&lt;&#x2F;code&gt; 写入实际的物理内存。&lt;br &#x2F;&gt;
（3）时间片再度分配给 &lt;code&gt;thread1&lt;&#x2F;code&gt;，&lt;code&gt;thread1&lt;&#x2F;code&gt; 开始执行它在上一个时间片结束时没有执行完的工作，将 &lt;code&gt;x = 50&lt;&#x2F;code&gt; 写入实际的物理内存，计算机严格按照代码执行指令，但此时问题出现：&lt;code&gt;thread1&lt;&#x2F;code&gt; 计算并写入的 &lt;code&gt;x = 50&lt;&#x2F;code&gt; 会把 &lt;code&gt;thread2&lt;&#x2F;code&gt; 计算并写入的 &lt;code&gt;x = 60&lt;&#x2F;code&gt; 覆盖掉。而每次执行程序，上述情况的发生总不会完全一致，比如时间片的大小就不是能完全确定的，相当于每次都有微调，这就是多次执行相同的代码得到的结果却完全不一致的原因。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;其实真实的过程比这复杂得多，这里进行了简化以方便讨论概念。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;如何解决这样的问题？先来看问题出在哪里。我们可以发现上面程序过程中的关键点是：每个线程的 &lt;strong&gt;计算 &lt;code&gt;x&lt;&#x2F;code&gt; 的值&lt;&#x2F;strong&gt; 和 &lt;strong&gt;把算好的值存入物理内存&lt;&#x2F;strong&gt; 这两个操作之间是 &lt;strong&gt;不连续的&lt;&#x2F;strong&gt;，这样就给了其他线程进来搞破坏的可趁之机。&lt;br &#x2F;&gt;
如果在单个线程中，计算值和把算好的值存入内存这两个操作连续进行是很自然的，自然到你根本不会意识到它们还可以不连续，这是你编程时的默认心智模型，如果这一条都不成立大家也就不用编码了。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;其实这里面还有指令重排的事，别以为你「看到」的就是「真相」。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;但是在多线程环境中，这就成为了问题，为了灵活和性能，多线程编程的自由度更高。如果多线程编程要强行规定线程间的执行顺序、线程内的指令执行顺序，那样还有意义吗？还不如继续优化多进程。&lt;&#x2F;p&gt;
&lt;p&gt;好，我们现在遇到了一个“既要…还要…”的问题：我们既要留住多线程的灵活，又要让它在某些时候不那么灵活，有没有两全法呢？有，原子操作！&lt;&#x2F;p&gt;
&lt;p&gt;原子操作是什么呢？我认为最通俗易懂的说法是：要么不做，要么全做。不过我的总结不够规范，咱们还是来看专业人士（Mara Bos 博士）是怎么表述这个概念的：&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The word atomic comes from the Greek word ἄτομος, meaning indivisible, something that cannot be cut into smaller pieces. In computer science, it is used to describe an operation that is indivisible: it is either fully completed, or it didn’t happen yet.&lt;br &#x2F;&gt;
原子这个词来自希腊语 ἄτομος，意思是不可分割的，不能被切割成更小的部分。在计算机科学中，它被用来描述一个不可分割的操作：它要么完全完成，要么还没有发生。&lt;br &#x2F;&gt;
However, atomic operations do allow for different threads to safely read and modify the same variable. Since such an operation is indivisible, it either happens completely before or completely after another operation, avoiding undefined behavior.&lt;br &#x2F;&gt;
原子操作允许不同的线程安全地读取和修改同一个变量。由于原子操作是不可分割的，它要么完全发生在另一个操作之前，要么完全发生在另一个操作之后，这样就避免了 UB。&lt;&#x2F;p&gt;
&lt;p&gt;Atomic operations are the main building block for anything involving multiple threads. All the other concurrency primitives, such as mutexes and condition variables, are implemented using atomic operations.&lt;br &#x2F;&gt;
原子操作是涉及多线程的任何事物的主要构建块。所有其他并发原语，例如互斥量和条件变量，都是使用原子操作实现的。&lt;br &#x2F;&gt;
In Rust, atomic operations are available as methods on the standard atomic types that live in &lt;code&gt;std::sync::atomic&lt;&#x2F;code&gt;. They all have names starting with &lt;code&gt;Atomic&lt;&#x2F;code&gt;, such as &lt;code&gt;AtomicI32&lt;&#x2F;code&gt; or &lt;code&gt;AtomicUsize&lt;&#x2F;code&gt;. Which ones are available depends on the hardware architecture and sometimes operating system, but almost all platforms provide at least all atomic types up to the size of a pointer.&lt;br &#x2F;&gt;
在 Rust 中，原子操作可以作为存在于 &lt;code&gt;std::sync::atomic&lt;&#x2F;code&gt; 中的标准原子类型的方法。它们的名称都以 &lt;code&gt;Atomic&lt;&#x2F;code&gt; 开头，例如 &lt;code&gt;AtomicI32&lt;&#x2F;code&gt; 或 &lt;code&gt;AtomicUsize&lt;&#x2F;code&gt;。哪些可用取决于硬件架构，有时取决于操作系统，但几乎所有平台都至少提供所有原子类型，最大为指针大小。&lt;br &#x2F;&gt;
Unlike most types, they allow modification through a shared reference (e.g., &lt;code&gt;&amp;amp;AtomicU8&lt;&#x2F;code&gt;). This is possible thanks to interior mutability, as discussed in “Interior Mutability” in Chapter 1.&lt;br &#x2F;&gt;
与大多数类型不同，它们允许通过共享引用进行修改（例如 &lt;code&gt;&amp;amp;AtomicU8&lt;&#x2F;code&gt;）。这要归功于内部可变性，正如第 1 章“内部可变性”中所讨论的那样。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;我们可以看到“原子操作是不可分割的”，放在我们的例子中这也就意味着我们可以通过原子操作，让线程的 &lt;strong&gt;计算 &lt;code&gt;x&lt;&#x2F;code&gt; 的值&lt;&#x2F;strong&gt; 和 &lt;strong&gt;把算好的值存入物理内存&lt;&#x2F;strong&gt; 之间是 &lt;strong&gt;不可分割的&lt;&#x2F;strong&gt;，那么也就不会出现前文中所述的错误，&lt;code&gt;x&lt;&#x2F;code&gt; 就会是 &lt;code&gt;200&lt;&#x2F;code&gt;。&lt;&#x2F;p&gt;
&lt;p&gt;Rust 是一门标榜“安全”的语言，既然多线程编程中会有“不安全”的场景出现，那么 Rust 肯定要考虑如何解决，不过相比 The book 中其他主题的 Rust 安全特色（所有权、借用检查等），我读到 Rust Atomics and Locks 后面只觉得在多线程编程方面，Rust 还是很明显地抄了不少别人（C++）的东西，例如下面 Mara Bos 博士话锋一转，开始讨论起了另一个概念：&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;But, before we can dive into the different atomic operations, we briefly need to touch upon a concept called memory ordering:&lt;br &#x2F;&gt;
但是，在我们深入研究不同的原子操作之前，我们需要简单地谈谈一个叫做内存排序的概念：&lt;br &#x2F;&gt;
Every atomic operation takes an argument of type &lt;code&gt;std::sync::atomic::Ordering&lt;&#x2F;code&gt;, which determines what guarantees we get about the relative ordering of operations. The simplest variant with the fewest guarantees is &lt;code&gt;Relaxed&lt;&#x2F;code&gt;. &lt;code&gt;Relaxed&lt;&#x2F;code&gt; still guarantees consistency on a single atomic variable, but does not promise anything about the relative order of operations between different variables.&lt;br &#x2F;&gt;
每个原子操作都有一个类型为 &lt;code&gt;std::sync::atomic::Ordering&lt;&#x2F;code&gt; 的参数，它决定了我们对操作的相对顺序有什么「保证」。而「保证」最少的、最简单的变体是 &lt;code&gt;Relaxed&lt;&#x2F;code&gt;。&lt;code&gt;Relaxed&lt;&#x2F;code&gt; 仍然保证单个原子变量的一致性，但不保证不同变量之间的相对操作顺序。&lt;br &#x2F;&gt;
What this means is that two threads might see operations on different variables happen in a different order. For example, if one thread writes to one variable first and then to a second variable very quickly afterwards, another thread might see that happen in the opposite order.&lt;br &#x2F;&gt;
这意味着两个线程可能会看到对不同变量的操作以不同的顺序发生。例如，如果一个线程首先写入一个变量，然后很快写入第二个变量，则另一个线程可能会看到以相反顺序发生的情况。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;我之前说有更反直觉的东西，这不现在看到了？为什么第二个线程可能看到以相反顺序发生的情况？&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Processors and compilers perform all sorts of tricks to make your programs run as fast as possible. A processor might determine that two particular consecutive instructions in your program will not affect each other, and execute them out of order, if that is faster, for example. While one instruction is briefly blocked on fetching some data from main memory, several of the following instructions might be executed and finished before the first instruction finishes, as long as that wouldn’t change the behavior of your program. Similarly, a compiler might decide to reorder or rewrite parts of your program if it has reason to believe it might result in faster execution. But, again, only if that wouldn’t change the behavior of your program.&lt;br &#x2F;&gt;
处理器和编译器执行各种技巧以使您的程序运行得尽可能快。处理器可能会确定您程序中的两个特定的连续指令不会相互影响，并乱序执行它们（例如，如果这样更快的话）。虽然一条指令在从主存中获取一些数据时被短暂阻塞，但在第一条指令完成之前，可能会执行并完成以下几条指令，只要这不会改变程序的行为。同样，如果编译器有理由相信它可能会导致更快的执行，它可能会决定重新排序或重写程序的某些部分。但是，同样，前提是这不会改变您的程序的行为。&lt;&#x2F;p&gt;
&lt;p&gt;Let’s take a look at the following function as an example:&lt;br &#x2F;&gt;
让我们以下面的函数为例：&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D3C6AA; background-color: #2D353B;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; f&lt;&#x2F;span&gt;&lt;span&gt;(a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;: &amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;, b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;: &amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;    *&lt;&#x2F;span&gt;&lt;span&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;    *&lt;&#x2F;span&gt;&lt;span&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;    *&lt;&#x2F;span&gt;&lt;span&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Here, the compiler will most certainly understand that the order of these operations does not matter, since nothing happens between these three addition operations that depends on the value of &lt;code&gt;*a&lt;&#x2F;code&gt; or &lt;code&gt;*b&lt;&#x2F;code&gt;. (Assuming overflow checking is disabled.) Because of that, it might reorder the second and third operations, and then merge the first two into a single addition:&lt;br &#x2F;&gt;
在这里，编译器肯定会理解这些操作的顺序无关紧要，因为这三个取决于 &lt;code&gt;*a&lt;&#x2F;code&gt; 或 &lt;code&gt;*b&lt;&#x2F;code&gt; 的值的加法操作之间没有任何关联。（假设溢出检查被禁用）因此，它可能会重新排序第二个和第三个操作，然后将前两个合并为一个加法：&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D3C6AA; background-color: #2D353B;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; f&lt;&#x2F;span&gt;&lt;span&gt;(a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;: &amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;, b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;: &amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;    *&lt;&#x2F;span&gt;&lt;span&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;    *&lt;&#x2F;span&gt;&lt;span&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Later, while executing this function of the optimized compiled program, a processor might for a variety of reasons end up executing the second addition before the first addition, possibly because &lt;code&gt;*b&lt;&#x2F;code&gt; was available in a cache, while &lt;code&gt;*a&lt;&#x2F;code&gt; had to be fetched from the main memory.&lt;br &#x2F;&gt;
稍后，在执行优化编译程序的这个函数时，处理器可能由于各种原因在第一次加法之前结束执行第二次加法，这可能是因为 &lt;code&gt;*b&lt;&#x2F;code&gt; 在缓存中可用，而 &lt;code&gt;*a&lt;&#x2F;code&gt; 必须从主存提取。&lt;br &#x2F;&gt;
Regardless of these optimizations, the result stays the same: &lt;code&gt;*a&lt;&#x2F;code&gt; is incremented by two and &lt;code&gt;*b&lt;&#x2F;code&gt; is incremented by one. The order in which they were incremented is entirely invisible to the rest of your program.&lt;br &#x2F;&gt;
不管这些优化如何，结果都保持不变：&lt;code&gt;*a&lt;&#x2F;code&gt; 增加 2，&lt;code&gt;*b&lt;&#x2F;code&gt; 增加 1。它们递增的顺序对于程序的其余部分是完全不可见的。&lt;&#x2F;p&gt;
&lt;p&gt;The logic for verifying that a specific reordering or other optimization won’t affect the behavior of your program does not take other threads into account. In our example above, that’s perfectly fine, as the unique references (&amp;amp;mut i32) guarantee that nothing else can possibly access the values, making other threads irrelevant. The only situation where this is a problem is when mutating data that’s shared between threads. Or, in other words, when working with atomics. This is why we have to explicitly tell the compiler and processor what they can and can’t do with our atomic operations, since their usual logic ignores interactions between threads and might allow for optimizations that do change the result of your program.&lt;br &#x2F;&gt;
验证特定重新排序或其他优化不会影响程序行为的逻辑不会考虑其他线程。在我们上面的示例中，这完全没问题，因为独占引用 (&lt;code&gt;&amp;amp;mut i32&lt;&#x2F;code&gt;) 保证没有其他任何东西可以访问这些值，从而使其他线程无关紧要。唯一会出现问题的情况是在改变线程之间共享的数据时。或者，换句话说，在使用原子时。这就是为什么我们必须明确地告诉编译器和处理器它们可以用我们的原子操作做什么和不能做什么，因为它们通常的逻辑会忽略线程之间的交互，并且可能允许进行确实会改变程序结果的优化。&lt;br &#x2F;&gt;
The interesting question is how we tell them. If we wanted to precisely spell out exactly what is and isn’t acceptable, concurrent programming might become exceedingly verbose and error prone, and maybe even architecture-specific:&lt;br &#x2F;&gt;
有趣的问题是我们如何告诉他们。如果我们想准确地说明什么是可接受的，什么是不可接受的，并发编程可能会变得非常冗长和容易出错，甚至可能是特定于体系结构的：&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D3C6AA; background-color: #2D353B;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;let x = a.fetch_add(1,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Dear compiler and processor,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Feel free to reorder this with operations on b,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    but if there&amp;#39;s another thread concurrently executing f,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    please don&amp;#39;t reorder this with operations on c!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Also, processor, don&amp;#39;t forget to flush your store buffer!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    If b is zero, though, it doesn&amp;#39;t matter.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    In that case, feel free to do whatever is fastest.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Thanks~ &amp;lt;3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Instead, we can only pick from a small set of options, represented by the &lt;code&gt;std::sync::atomic::Ordering&lt;&#x2F;code&gt; enum, which every atomic operation takes as an argument. The set of available options is very limited, but has been carefully picked to fit most use cases well. The orderings are very abstract and do not directly reflect the actual compiler and processor mechanisms involved, such as instruction reordering. This makes it possible for your concurrent code to be architecture-independent and future-proof. It allows for verification without knowing the details of every single current and future processor and compiler version.&lt;br &#x2F;&gt;
相反，我们只能从一小组选项中选择，由 &lt;code&gt;std::sync::atomic::Ordering&lt;&#x2F;code&gt; 枚举表示，每个原子操作都将其作为参数。可用选项集非常有限，但经过精心挑选以适合大多数用例。排序非常抽象，并不直接反映所涉及的实际编译器和处理器机制，例如指令重新排序。这使您的并发代码可以独立于体系结构且面向未来。它允许在不知道每个当前和未来处理器和编译器版本的详细信息的情况下进行验证。&lt;&#x2F;p&gt;
&lt;p&gt;The available orderings in Rust are:&lt;br &#x2F;&gt;
Rust 中可用的排序是：&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Relaxed ordering: Ordering::Relaxed&lt;&#x2F;li&gt;
&lt;li&gt;Release and acquire ordering: Ordering::{Release, Acquire, AcqRel}&lt;&#x2F;li&gt;
&lt;li&gt;Sequentially consistent ordering: Ordering::SeqCst&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In C++, there is also something called consume ordering, which has been purposely omitted from Rust, but is nonetheless interesting to discuss as well.&lt;br &#x2F;&gt;
在 C++ 中，还有一种叫做 consume ordering 的东西，它在 Rust 中被故意省略了，但讨论起来也很有趣。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;在这一大段里我们来捞点干的，大意是编译器会优化代码，导致指令执行顺序和代码表示的顺序不一定一致，而这一点在多线程环境下被放大了。不管是否有指令重排，第一个线程实际上并不关心，因为不会影响它的执行结果，而假如发生了指令重排，使第一个线程真实的执行顺序变得和原来相反，那么第二个线程就看到了相反顺序的发生情况，如果第二个线程的操作对第一个线程的操作顺序有所依赖，这就会出现问题。所以在某些特殊场合，我们需要有能力对代码&#x2F;指令的执行顺序有所限制，如果你不想做上面 Mara 博士举例的“面向协议编程”，内存排序则是你的救星。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The different memory ordering options have a strict formal definition to make sure we know exactly what we’re allowed to assume, and for compiler writers to know exactly what guarantees they need to provide to us. To decouple this from the details of specific processor architectures, memory ordering is defined in terms of an abstract &lt;em&gt;memory model&lt;&#x2F;em&gt;.&lt;br &#x2F;&gt;
不同的内存排序选项有一个严格的正式定义，以确保我们确切地知道我们被允许假设什么，并让编译器编写者确切地知道他们需要为我们提供什么保证。为了将其与特定处理器架构的细节分离，内存排序是根据抽象内存模型定义的。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Rust’s memory model, which is mostly copied from C++, doesn’t match any existing processor architecture, but instead is an abstract model with a strict set of rules that attempt to represent the greatest common denominator of all current and future architectures, while also giving the compiler enough freedom to make useful assumptions while analyzing and optimizing programs.&lt;br &#x2F;&gt;
Rust 的内存模型，主要是从 C++ 复制而来，不匹配任何现有的处理器架构，而是一个具有一组严格规则的抽象模型，试图代表所有当前和未来架构的最大公分母，同时也给出编译器有足够的自由在分析和优化程序时做出有用的假设。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;We’ve already seen a part of the memory model in action in &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;marabos.nl&#x2F;atomics&#x2F;basics.html#borrowing-and-races&quot;&gt;“Borrowing and Data Races” in Chapter 1&lt;&#x2F;a&gt;, where we talked about how data races result in undefined behavior. Rust’s memory model allows for concurrent atomic stores, but considers concurrent non-atomic stores to the same variable to be a data race, resulting in undefined behavior.&lt;br &#x2F;&gt;
我们已经在第 1 章的“借用和数据竞争”中看到了内存模型的一部分，我们在其中讨论了数据竞争如何导致未定义的行为。Rust 的内存模型允许并发&lt;strong&gt;原子存储&lt;&#x2F;strong&gt;，但将对同一变量的并发&lt;strong&gt;非原子存储&lt;&#x2F;strong&gt;视为数据竞争──导致未定义的行为。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;计算机的难题 99% 是靠分层解决的，Rust 的内存模型也不例外，这里借鉴了 C++，或者说是编译器前后端&#x2F;虚拟机的经验，不对某一具体处理器架构而是在这中间又加了一个抽象层，这样就能最大程度地保证灵活，除了多了一层翻译会有一点性能上的权衡以外没啥缺点。&lt;&#x2F;p&gt;
&lt;p&gt;激动，终于要谈到今天的主题──Happened-before 关系了，接着读：&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The memory model defines the order in which operations happen in terms of &lt;em&gt;happens-before relationships&lt;&#x2F;em&gt;. This means that as an abstract model, it doesn’t talk about machine instructions, caches, buffers, timing, instruction reordering, compiler optimizations, and so on, but instead only defines situations where one thing is guaranteed to happen before another thing, and leaves the order of everything else undefined.&lt;br &#x2F;&gt;
内存模型定义了操作发生的顺序，即 happens-before 关系。这意味着，作为一个抽象的模型，它不谈论机器指令、缓存、缓冲区、时间、指令重排、编译器优化等等，只定义了一件事在另一件事之前发生的情况，而对其他事情的顺序没有定义。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;The basic happens-before rule is that everything that happens within the same thread happens in order. If a thread is executing &lt;code&gt;f(); g();&lt;&#x2F;code&gt;, then &lt;code&gt;f()&lt;&#x2F;code&gt; &lt;em&gt;happens-before&lt;&#x2F;em&gt; &lt;code&gt;g()&lt;&#x2F;code&gt;.&lt;br &#x2F;&gt;
基本的 happens-before 规则是同一线程内发生的所有事情都按顺序发生。如果线程正在执行 &lt;code&gt;f(); g();&lt;&#x2F;code&gt;，那么 &lt;code&gt;f()&lt;&#x2F;code&gt; happens-before &lt;code&gt;g()&lt;&#x2F;code&gt;。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;这里我补充一些内容：&lt;&#x2F;p&gt;
&lt;ol start=&quot;0&quot;&gt;
&lt;li&gt;Mara 博士原文是 happens-before，这是编程语言的用法，但我更想讨论的是 happened-before 事件间的关系，故引述原文的地方我不做改动，但在我自己叙述的时候使用后者&lt;&#x2F;li&gt;
&lt;li&gt;当 A 操作 &lt;strong&gt;happened-before&lt;&#x2F;strong&gt; B 操作的时候，操作 A 先于操作 B 执行，且 A 操作的结果对 B 来说可见。每个线程都可以执行不同的任务，但是当它们之间进行一些交互时，例如读写共享内存或发送和接收消息时，必须遵守一些规则。这些规则确保了在一个线程中发生的操作在另一个线程中变得可见之前已经完成。也就是说，在一个线程中发生的操作 happened-before 了在另一个线程中看到该操作&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;happened-before&lt;&#x2F;strong&gt; 包含两种情况：&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;ul&gt;
&lt;li&gt;对于同一线程内的 happened-before，其等同于 sequenced-before（A &lt;em&gt;sequenced-before&lt;&#x2F;em&gt; B → 代表 A 的求值会先完成，之后才进行对 B 的求值）&lt;&#x2F;li&gt;
&lt;li&gt;对于不同线程内的 happened-before，其等同于 inter-thread happened before（A &lt;em&gt;inter-thread happened before&lt;&#x2F;em&gt; B → 如果操作 A happened-before 操作 B，则可以保证线程 1 中的操作 A 的执行对线程 2 中的操作 B 的执行是可见的，也就是说，操作 A 执行后对共享状态所做的修改对线程 2 可见）&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;Between threads, however, happens-before relationships only occur in a few specific cases, such as when spawning and joining a thread, unlocking and locking a mutex, and through atomic operations that use non-relaxed memory ordering. &lt;code&gt;Relaxed&lt;&#x2F;code&gt; memory ordering is the most basic (and most performant) memory ordering that, by itself, never results in any cross-thread happens-before relationships.&lt;br &#x2F;&gt;
然而，在线程之间，happens-before 关系只发生在少数特定情况下，例如 spawn 线程和 join 线程、解锁和锁定互斥锁以及使用非 &lt;code&gt;Relaxed&lt;&#x2F;code&gt; 内存排序的原子操作。&lt;code&gt;Relaxed&lt;&#x2F;code&gt; 内存排序是最基本（也是最高效）的内存排序，它本身不会导致任何跨线程的 happens-before 关系。&lt;&#x2F;p&gt;
&lt;p&gt;To explore what that means, let’s take a look at the following example where we assume &lt;code&gt;a&lt;&#x2F;code&gt; and &lt;code&gt;b&lt;&#x2F;code&gt; are concurrently executed by different threads:&lt;br &#x2F;&gt;
为了探究这意味着什么，让我们看一下下面的示例，其中我们假设 &lt;code&gt;a&lt;&#x2F;code&gt; 和 &lt;code&gt;b&lt;&#x2F;code&gt; 由不同的线程同时执行：&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D3C6AA; background-color: #2D353B;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;static&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; X&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; AtomicI32&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; AtomicI32&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;static&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; AtomicI32&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; AtomicI32&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; a&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;    X&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;store&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Relaxed&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #859289;font-style: italic;&quot;&gt;    &#x2F;&#x2F; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;    Y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;store&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;20&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Relaxed&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #859289;font-style: italic;&quot;&gt;    &#x2F;&#x2F; 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; b&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Y&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;load&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;Relaxed&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #859289;font-style: italic;&quot;&gt; &#x2F;&#x2F; 3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; X&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;load&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;Relaxed&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;span style=&quot;color: #859289;font-style: italic;&quot;&gt; &#x2F;&#x2F; 4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span&gt;(&amp;quot;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span&gt;} {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #DBBC7F;&quot;&gt;y&lt;&#x2F;span&gt;&lt;span&gt;}&amp;quot;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;As mentioned above, the basic happens-before rule is that everything that happens within the same thread happens in order. In this case: 1 happens-before 2, and 3 happens-before 4, as shown in &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;marabos.nl&#x2F;atomics&#x2F;memory-ordering.html#happens-before-diagram-load-store&quot;&gt;Figure 3-1&lt;&#x2F;a&gt;. Since we use relaxed memory ordering, there are no other happens-before relationships in our example.&lt;br &#x2F;&gt;
如上所述，基本的 happens-before 规则是同一线程内发生的所有事情都按顺序发生。在这种情况下：1 happens-before 2，3 happens-before 4，如图 3-1 所示。由于我们使用 &lt;code&gt;Relaxed&lt;&#x2F;code&gt; 内存排序，因此在我们的示例中没有其他 happens-before 关系。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;img src=&quot;https:&#x2F;&#x2F;marabos.nl&#x2F;atomics&#x2F;images&#x2F;raal_0301.png&quot; loading=&quot;lazy&quot; &#x2F;&gt;
&lt;p&gt;Figure 3-1. The happens-before relationships between atomic operations in the example code.&lt;br &#x2F;&gt;
图 3-1 示例代码中原子操作之间的 happens-before 关系。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;If either of &lt;code&gt;a&lt;&#x2F;code&gt; or &lt;code&gt;b&lt;&#x2F;code&gt; completes before the other starts, the output will be &lt;code&gt;0 0&lt;&#x2F;code&gt; or &lt;code&gt;10 20&lt;&#x2F;code&gt;. If &lt;code&gt;a&lt;&#x2F;code&gt; and &lt;code&gt;b&lt;&#x2F;code&gt; run concurrently, it’s easy to see how the output can be &lt;code&gt;10 0&lt;&#x2F;code&gt;. One way this can happen is if the operations run in this order: 3 1 2 4.&lt;br &#x2F;&gt;
如果 &lt;code&gt;a&lt;&#x2F;code&gt; 或 &lt;code&gt;b&lt;&#x2F;code&gt; 中的任何一个在另一个开始之前完成，则输出将为 &lt;code&gt;0 0&lt;&#x2F;code&gt; 或 &lt;code&gt;10 20&lt;&#x2F;code&gt;。如果 &lt;code&gt;a&lt;&#x2F;code&gt; 和 &lt;code&gt;b&lt;&#x2F;code&gt; 同时运行，很容易看出输出是 &lt;code&gt;10 0&lt;&#x2F;code&gt;。发生这种情况的一种方式是操作按以下顺序运行：3 1 2 4。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;More interestingly, the output can also be &lt;code&gt;0 20&lt;&#x2F;code&gt;, even though there is no possible globally consistent order of the four operations that would result in this outcome. When 3 is executed, there is no happens-before relationship with 2, which means it could load either 0 or 20. When 4 is executed, there is no happens-before relationship with 1, which means it could load either 0 or 10. Given this, the output &lt;code&gt;0 20&lt;&#x2F;code&gt; is a valid outcome.&lt;br &#x2F;&gt;
更有趣的是，输出也可以是 &lt;code&gt;0 20&lt;&#x2F;code&gt;，&lt;strong&gt;即使没有可能导致此结果的四个操作的全局一致顺序&lt;&#x2F;strong&gt;。当 3 执行时，与 2 没有 happens-before 关系，也就是说它可以加载 0 或 20。当 4 执行时，与 1 没有 happens-before 关系，这意味着它可以加载 0 或 10。鉴于此，输出 &lt;code&gt;0 20&lt;&#x2F;code&gt; 是一个有效的结果。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;The important and counter-intuitive thing to understand is that operation 3 loading the value 20 does &lt;em&gt;not&lt;&#x2F;em&gt; result in a happens-before relationship with 2, even though that value is the one stored by 2. Our intuitive understanding of the concept of “before” breaks down when things don’t necessarily happen in a globally consistent order, such as when instruction reordering is involved.&lt;br &#x2F;&gt;
需要理解的重要且违反直觉的事情是，操作 3 加载值 20 不会导致与操作 2 为 happens-before 关系，即使该值是由操作 2 存储的。当事情不一定以全局一致顺序发生时，我们对“before”概念的直觉理解就会崩溃，例如当涉及&lt;strong&gt;指令重排&lt;&#x2F;strong&gt;时。&lt;br &#x2F;&gt;
A more practical and intuitive, but less formal, understanding is that from the perspective of the thread executing &lt;code&gt;b&lt;&#x2F;code&gt;, operations 1 and 2 might appear to happen in the opposite order.&lt;br &#x2F;&gt;
一种更实用、更直观但不太正式的理解是，从执行 &lt;code&gt;b&lt;&#x2F;code&gt; 的线程的角度来看，操作 1 和 2 的发生顺序可能相反。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;迷糊了吧，我也迷糊了，我始终无法理解 &lt;code&gt;0 20&lt;&#x2F;code&gt; 是怎么成为一个有效结果的。首先输出 &lt;code&gt;0&lt;&#x2F;code&gt;，这意味着操作 4 在操作 1 之前发生；输出 &lt;code&gt;20&lt;&#x2F;code&gt; 则意味着操作 2 在操作 3 之前发生，而最关键的“基本的 happened-before 规则是同一线程内发生的所有事情都按顺序发生”，那么也就是说操作 3 在操作 4 之前发生，操作 1 在操作 2 之前发生，我是没有想得到是什么样的全局顺序能够满足这些要求，无论怎么想都有矛盾，Mara 博士也说这个例子中并没有能导致该结果的四个操作的全局一致顺序，所以如果还在这个方向思考，肯定是难以得到简单直观解释的。&lt;&#x2F;p&gt;
&lt;p&gt;让我卖个关子（其实已有伏笔），欲知后事如何，且听下回分解。&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="zh-CN">
        <title>AI 来了</title>
        <published>2023-03-17T00:00:00+00:00</published>
        <updated>2023-03-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://whx828.com/posts/ai-laile/"/>
        <id>https://whx828.com/posts/ai-laile/</id>
        
        <content type="html" xml:base="https://whx828.com/posts/ai-laile/">&lt;p&gt;今天晚上有点累，同时闲得无聊，而且最近总被 GPT-4&#x2F;ChatGPT&#x2F;文心一言刷屏，突然也想跟把风玩玩 AI。&lt;&#x2F;p&gt;
&lt;p&gt;上网冲浪找到了这个项目：&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;setzer22&#x2F;llama-rs&quot;&gt;LLaMA-rs&lt;&#x2F;a&gt;，是 &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ggerganov&#x2F;llama.cpp&quot;&gt;llama.cpp&lt;&#x2F;a&gt; 的 Rust 版本，正好 MacBook 也能跑，比较适合我。&lt;br &#x2F;&gt;
我尝试着 clone 了项目，想着看看能不能跑通，权当娱乐。&lt;&#x2F;p&gt;
&lt;p&gt;需要这么几步操作：&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;首先你需要准备 LLaMA 模型，常规操作是到 facebook 那里慢悠悠地填邮件，等人家给你发链接，不过晚吃瓜有晚吃瓜的好处，网友是万能的，现在磁力链接都有了：&lt;br &#x2F;&gt;
&lt;code&gt;magnet:?xt=urn:btih:ZXXDAUWYLRUXXBHUYEMS6Q5CE5WA3LVA&amp;amp;dn=LLaMA&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;简单瞅瞅，这些模型太大，我只是想玩一下，所以选择了最小的 7B&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;模型下载好之后需要按照 &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ggerganov&#x2F;llama.cpp&quot;&gt;llama.cpp&lt;&#x2F;a&gt; 项目的步骤继续：&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;把模型挪到 &lt;code&gt;.&#x2F;models&lt;&#x2F;code&gt; 下&lt;&#x2F;li&gt;
&lt;li&gt;安装必要的依赖：&lt;code&gt;python3 -m pip install torch numpy sentencepiece&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;将 7B 模型转换为 ggml FP16 格式：&lt;code&gt;python3 convert-pth-to-ggml.py models&#x2F;7B&#x2F; 1&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;将模型量化为 4 位：&lt;code&gt;.&#x2F;quantize.sh 7B&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;通过上面一顿操作你就得到了 &lt;code&gt;.&#x2F;models&#x2F;7B&#x2F;ggml-model-q4_0.bin&lt;&#x2F;code&gt; 这个文件&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;友情提示下载的模型就有 10 几个 G，转化好的玩意也有 4G 多，所以你最好在等下载&amp;amp;运行转换命令的时候找点事做，不然会非常无聊（说好的娱乐向呢。。。）&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;接下来 clone &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;setzer22&#x2F;llama-rs&quot;&gt;LLaMA-rs&lt;&#x2F;a&gt; 项目，在 LLaMA-rs 项目的根目录下执行 &lt;code&gt;cargo build --release&lt;&#x2F;code&gt;，构建 Rust 项目（熟悉 Rust 的要注意目前 debug 模式会报错，必须是 release 模式才行）&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;构建完成之后就可以用 &lt;code&gt;cargo run --release -- &amp;lt;ARGS&amp;gt;&lt;&#x2F;code&gt; 命令运行了，人家给的例子是 &lt;code&gt;cargo run --release -- -m &#x2F;data&#x2F;Llama&#x2F;LLaMA&#x2F;7B&#x2F;ggml-model-q4_0.bin -p &quot;Tell me how cool the Rust programming language is:&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;一切顺利你会看到结果，大功告成！我跑出来的东西是这样的：&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;img src=&quot;..&#x2F;..&#x2F;images&#x2F;legacy&#x2F;2023&#x2F;llama-rs-result.png&quot; loading=&quot;lazy&quot; &#x2F;&gt;
&lt;blockquote&gt;
&lt;p&gt;Tell me how cool the Rust programming language is:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;It’s compiled using standard techniques, but it has no runtime library (all classes are inlined into executables). So all kinds of things you wouldn’t normally have to worry about compile-time.&lt;&#x2F;li&gt;
&lt;li&gt;It can create a complete binary application from an XML file that specifies the class hierarchy and relationships - no other code is necessary or allowed!&lt;&#x2F;li&gt;
&lt;li&gt;The programming language looks like Java, but it has none of the overhead – it runs in memory at normal speed on modern hardware (i5+MacBookPro here). I’m really loving this because I can now write C-like&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;告诉我，Rust 编程语言有多酷：&lt;br &#x2F;&gt;
1）它是使用标准技术编译的，但是它没有运行时库（所有类都插入了可执行文件中）。因此，您通常不必担心编译时的各种事情。&lt;br &#x2F;&gt;
2）它可以从 XML 文件中创建一个完整的二进制应用程序，该应用程序指定类层次结构和关系 - 不需要或允许其他代码！&lt;br &#x2F;&gt;
3）编程语言看起来像 Java，但没有开销 - 它以现代硬件的正常速度（i5+MacBookPro）在内存中运行。我真的很喜欢这个，因为我现在可以写类 C 语言&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;AI 还是有点意思的，第一条还像那么回事，Rust 官方的确没有提供运行时，但是这意味着有更多的工作要在编译时去做啊，AI 的逻辑让人哭笑不得；&lt;br &#x2F;&gt;
第二条更加离谱，如果这里说 TOML 文件将是绝杀，可惜换不得；第三条又是说对了一部分，Rust 的确快，但和 Java 并没多少相似之处。&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;再来看基于 Stanford Alpaca 的 &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;antimatter15&#x2F;alpaca.cpp&quot;&gt;alpaca.cpp&lt;&#x2F;a&gt; 项目的神奇操作，步骤和前面的差不多，但是效果更好：&lt;&#x2F;p&gt;
&lt;img src=&quot;..&#x2F;..&#x2F;images&#x2F;legacy&#x2F;2023&#x2F;alpaca-cpp.png&quot; loading=&quot;lazy&quot; &#x2F;&gt;
&lt;blockquote&gt;
&lt;p&gt;Rust has been described as “the most exciting new development in software engineering since C++”. It combines safety and performance, with a focus on correctness that makes it ideal for writing safe code. Rust also offers great tooling support from the community which allows you to write better programs faster than ever before!&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Rust 被描述为“自 C++ 以来软件工程领域最激动人心的新发展”。它结合了安全性和性能，并注重正确性，这使其成为编写安全代码的理想选择。Rust 还提供来自社区的强大工具支持，使您能够比以往更快地编写更好的程序！&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;这个效果就比前者好太多了，基本没有错误！&lt;&#x2F;p&gt;
&lt;p&gt;最恐怖的是，所有的这一切都是在我这台 2016 的老 MacBook 上完成的，没有什么显卡&#x2F;GPU 加持，完全靠 CPU 也能做到这种程度，这样看来 ChatGPT 那种神乎其技的表现也就不足为奇了，所谓图灵测试根本是难不住它们的，依照这个速度发展下去，奇点一定会到来；&lt;br &#x2F;&gt;
这个世界太疯狂，未来会变成什么样子，真是令人期待！&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="zh-CN">
        <title>2022 总结</title>
        <published>2023-01-01T00:00:00+00:00</published>
        <updated>2023-01-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://whx828.com/posts/2022-zongjie/"/>
        <id>https://whx828.com/posts/2022-zongjie/</id>
        
        <content type="html" xml:base="https://whx828.com/posts/2022-zongjie/">&lt;h1 id=&quot;2022-hui-gu-bian-shi&quot;&gt;2022 回顾 &amp;amp; 鞭尸&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;ge-ren-neng-li&quot;&gt;个人能力&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;nian-chu-ji-hua&quot;&gt;年初计划&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;深度阅读 10 本左右的各领域书籍&lt;&#x2F;li&gt;
&lt;li&gt;争取输出自己的内容，读书笔记或者技术博客 5-6 篇&lt;&#x2F;li&gt;
&lt;li&gt;练习英语阅读能力，之后是听和说&lt;&#x2F;li&gt;
&lt;li&gt;锻炼身体，减肥 10 斤&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;zhi-xing-qing-kuang&quot;&gt;执行情况&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;img src=&quot;..&#x2F;..&#x2F;images&#x2F;legacy&#x2F;2023&#x2F;2022%20%E9%98%85%E8%AF%BB%E4%B9%A6%E7%B1%8D.png&quot; loading=&quot;lazy&quot; &#x2F;&gt;2022 阅读书籍&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;读了一共大概 6、7 本书吧，事实上没有太多时间读书&lt;&#x2F;li&gt;
&lt;li&gt;写了 1 篇博客，几乎剃了光头，现在看来 2022 年唯一的正式输出也稚嫩得可笑，毫无水平，留着警醒自己吧，不要什么垃圾都往外输出&lt;&#x2F;li&gt;
&lt;li&gt;保持阅读了英语内容，但没有学习英语，对英语失去了兴趣，我还有什么理由学习英语呢，尤其是在翻译软件异常发达的今天，明天有效果极好的同声传译软件出来我都不奇怪&lt;&#x2F;li&gt;
&lt;li&gt;身体一年不如一年，年末受到新冠的攻击，至今仍未痊愈&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;bian-cheng-neng-li&quot;&gt;编程能力&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;ge-ren-zhan-wang&quot;&gt;个人展望&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;nian-chu-ji-hua-1&quot;&gt;年初计划&lt;&#x2F;h4&gt;
&lt;p&gt;按照 &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;zerotomastery.io&#x2F;blog&#x2F;learn-to-code-for-free&#x2F;&quot;&gt;Learn to code for free, get hired in 5 months, and have fun along the way&lt;&#x2F;a&gt; 的计划学习&lt;br &#x2F;&gt;
追加简单的计算机科学自学计划 2022.2.15&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;成为一个具有职业水平的 Java 后端开发者（全年）&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;blockquote&gt;
&lt;p&gt;这一项估计不行了，计划赶不上变化&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;练习一定的算法题目（全年）&lt;&#x2F;li&gt;
&lt;li&gt;成为一个优秀的 Rust 语言爱好者（后半年）&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h4 id=&quot;zhi-xing-qing-kuang-1&quot;&gt;执行情况&lt;&#x2F;h4&gt;
&lt;p&gt;第一个计划没有执行，我完全低估了前端开发的难度和逻辑，所累积的技术栈对于前端学习的帮助也非常小，学不下去也实属正常；&lt;br &#x2F;&gt;
第二个计划执行了一些，但不多，英语课程学习起来所花费的时间巨大，而收益却未知，我不知道是好还是坏，好在内容足够有趣。&lt;&#x2F;p&gt;
&lt;p&gt;前两项完全没做，没学 Java 也没学算法，甚至连数据结构都没学全；&lt;br &#x2F;&gt;
最后一项估计完成了 3、4 成左右的样子吧，Rust 的难度也不小，只是我还愿意往下学而已。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;xue-xi-lu-jing&quot;&gt;学习路径&lt;&#x2F;h3&gt;
&lt;p&gt;预计到 2023 年年初具备职业开发者的素质，争取走技术移民&#x2F;独立开发者的路子。&lt;&#x2F;p&gt;
&lt;h4 id=&quot;zhi-xing-qing-kuang-2&quot;&gt;执行情况&lt;&#x2F;h4&gt;
&lt;p&gt;很遗憾，还未达成职业水平，而且在上班前也不会达到吧，去年的我想得太美了，完全没意识到学一年编程就达到职业水平是凡人不可能完成的任务。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;jie-duan-ji-hua&quot;&gt;阶段计划&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;yue-du-ji-hua&quot;&gt;阅读计划&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;nian-chu-ji-hua-2&quot;&gt;年初计划&lt;&#x2F;h4&gt;
&lt;ol&gt;
&lt;li&gt;读完《计算机系统要素》&lt;&#x2F;li&gt;
&lt;li&gt;读完《CSAPP》&lt;&#x2F;li&gt;
&lt;li&gt;读完《操作系统导论》&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h4 id=&quot;zhi-xing-qing-kuang-3&quot;&gt;执行情况&lt;&#x2F;h4&gt;
&lt;p&gt;第一本读了一半，这本书其实也就值得读一半；&lt;br &#x2F;&gt;
走马观花地读完了第二本，实验和课后题完全没碰；&lt;br &#x2F;&gt;
最后一本读了三分之一。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;gong-zuo-ji-hua&quot;&gt;工作计划&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;nian-chu-ji-hua-3&quot;&gt;年初计划&lt;&#x2F;h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;del&gt;完成 WH 交代的任务&lt;&#x2F;del&gt;，顺利毕业&lt;&#x2F;li&gt;
&lt;li&gt;&lt;del&gt;上手区块链、JavaScript 项目&lt;&#x2F;del&gt;&lt;&#x2F;li&gt;
&lt;li&gt;每月输出内容取材于每周的周记，周记又源于日记&lt;&#x2F;li&gt;
&lt;li&gt;学习英语，认真读英语文章，保证质量&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h4 id=&quot;zhi-xing-qing-kuang-4&quot;&gt;执行情况&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;img src=&quot;..&#x2F;..&#x2F;images&#x2F;legacy&#x2F;2023&#x2F;2022%20%E5%91%A8%E6%8A%A5.png&quot; loading=&quot;lazy&quot; &#x2F;&gt;2022 周报&lt;&#x2F;p&gt;
&lt;p&gt;2022.4.16──2022.6.22 这段时间因学校封校，老师进不来，日子变得轻松的缘故下写了点 &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;whx828.notion.site&#x2F;3e61b415aabe410d8b3f37844dfb5e68?v=f23ac96cfb3a43558649ccb8382c2279&quot;&gt;周报&lt;&#x2F;a&gt;，还有一篇 &lt;a href=&quot;&#x2F;posts&#x2F;rust-tanxian&#x2F;&quot;&gt;Rust 博客&lt;&#x2F;a&gt;；&lt;br &#x2F;&gt;
除此之外 2022 年什么都没输出，在年末也失去了耐心，没能完成很好的内容输出。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;jian-dan-de-ji-suan-ji-ke-xue-zi-xue-ji-hua&quot;&gt;简单的计算机科学自学计划&lt;&#x2F;h3&gt;
&lt;h4 id=&quot;nian-chu-ji-hua-4&quot;&gt;年初计划&lt;&#x2F;h4&gt;
&lt;p&gt;5-8 重点：&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Composing programs&lt;br &#x2F;&gt;
Coursera Programming Languages(ML, Racket, Ruby)&lt;&#x2F;li&gt;
&lt;li&gt;The Missing Semester of Your CS Education&lt;br &#x2F;&gt;
讲 Shell，Git，tmux 等等&lt;&#x2F;li&gt;
&lt;li&gt;Coursera Data Structures and Algorithms Specialization(UCSD)&lt;br &#x2F;&gt;
算法：贪心算法，分治算法，动态规划&lt;br &#x2F;&gt;
数据结构：动态数组，哈希表，二叉树&lt;&#x2F;li&gt;
&lt;li&gt;CSAPP, CMU: Intro to Computer Systems&lt;br &#x2F;&gt;
数据在计算机中存储，汇编，程序优化，内存分级，控制流&lt;&#x2F;li&gt;
&lt;li&gt;MIT 6.S081 OS&lt;br &#x2F;&gt;
系统调用，Page Table，Exception，多线程，进程等&lt;&#x2F;li&gt;
&lt;li&gt;MIT 6.824 分布式系统&lt;br &#x2F;&gt;
实现 RAFT 协议，使用 RAFT 协议搭建 KV Server，实现动态切片&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h4 id=&quot;zhi-xing-qing-kuang-5&quot;&gt;执行情况&lt;&#x2F;h4&gt;
&lt;p&gt;走马观花地看了 1，发现没什么意思，2 的东西挺好，把边角料讲好也是本事；还有大致过了一遍 5 的视频字幕，对 OS 有了点概念，除此之外没看什么课程。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;yuan-ze&quot;&gt;原则&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;strong&gt;坚持一个目标不动摇&lt;&#x2F;strong&gt;，不要换来换去，别被别人影响，锻炼自己心态，什么时候天都塌不下来&lt;br &#x2F;&gt;
对于研究生期间遇到的项目，需要什么就学什么，不再进行项目相关扩展学习，专注于自己的学习计划&lt;br &#x2F;&gt;
三思而行，抛弃不该有的心理包袱，扩展网络上的人际交往&lt;&#x2F;p&gt;
&lt;h4 id=&quot;zhi-xing-qing-kuang-6&quot;&gt;执行情况&lt;&#x2F;h4&gt;
&lt;p&gt;完全没有做到，一塌糊涂，心态随着「躺平」的深渊越来越近，不想关心一切；&lt;br &#x2F;&gt;
研究生期间的项目估计到此为止了，对我而言只剩下毕业论文；&lt;br &#x2F;&gt;
不仅没有扩展网络人际，甚至还断掉了两个现实中的关系，不过我只后悔为什么没有早点断，那样还能体面一点，和谐一点。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;yan-jiu-sheng-gong-zuo-2022-2&quot;&gt;研究生工作 2022.2-&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;del&gt;建立一个无人工厂：&lt;&#x2F;del&gt;&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;建立 RFID、机器人、生产线组成的系统&lt;&#x2F;li&gt;
&lt;li&gt;基于 Rethink 机器人控制，把仿真控制程序下到实体机器人上，实现机器人操作&lt;&#x2F;li&gt;
&lt;li&gt;构建局域网，搭建 RFID 天线、其代码识别功能，机器人抓去工件（具有代码）&lt;&#x2F;li&gt;
&lt;li&gt;远程操控，通过手机操控该系统&lt;&#x2F;li&gt;
&lt;li&gt;建立与实体系统对应的元宇宙系统&lt;&#x2F;li&gt;
&lt;li&gt;元宇宙系统与实体系统实现链接、互动&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h4 id=&quot;zhi-xing-qing-kuang-7&quot;&gt;执行情况&lt;&#x2F;h4&gt;
&lt;p&gt;花了半年的时间才最终意识到我的研究生教育是个骗局，所有的一切除了毕业证书全都和我无关，我不应该花哪怕一秒钟在这些东西上面，因为完全都是浪费。当我知道这些的时候已经很晚了，可以说浪费了大半年的时间。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;zi-xue-ke-cheng-geng-xin-2022-3-11&quot;&gt;自学课程更新 2022.3.11-&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;cs61a.org&quot;&gt;CS 61A: Structure and Interpretation of Computer Programs&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;sp18.datastructur.es&#x2F;&quot;&gt;CS 61B: Data Structures&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;http:&#x2F;&#x2F;web.mit.edu&#x2F;6.031&#x2F;www&#x2F;sp21&#x2F;&quot;&gt;6.031: Software Construction&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h4 id=&quot;zhi-xing-qing-kuang-8&quot;&gt;执行情况&lt;&#x2F;h4&gt;
&lt;p&gt;只看了 CS61B，还没看完。现在让我学的话我也只会学 CS61B，贪多嚼不烂。&lt;&#x2F;p&gt;
&lt;h1 id=&quot;zong-jie&quot;&gt;总结&lt;&#x2F;h1&gt;
&lt;h2 id=&quot;bi-ji-qing-kuang&quot;&gt;笔记情况&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;img src=&quot;..&#x2F;..&#x2F;images&#x2F;legacy&#x2F;2023&#x2F;2022%20%E6%80%BB%E7%BB%93.png&quot; loading=&quot;lazy&quot; &#x2F;&gt;2022 总结&lt;&#x2F;p&gt;
&lt;p&gt;看得出我还是记了不少笔记的，可惜没啥时间消化它们。2023 继续坚持。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;xiang-mu-ji-hua&quot;&gt;项目计划&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;markdown-ge-shi-hua&quot;&gt;Markdown 格式化&lt;&#x2F;h3&gt;
&lt;p&gt;为啥想做这个东西，每次整理笔记的时候格式总是一团糟，网上找到的实现也不符合我的需求，干脆自己写一个吧。&lt;&#x2F;p&gt;
&lt;h3 id=&quot;crane-yu-yan&quot;&gt;Crane 语言&lt;&#x2F;h3&gt;
&lt;p&gt;读完 《Crafting Interpreter》总有种自己也写个语言的冲动，暂定名为 Crane，希望在 2023 年完成这个项目。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;sui-sui-nian-fa-lao-sao&quot;&gt;碎碎念 &amp;amp; 发牢骚&lt;&#x2F;h2&gt;
&lt;p&gt;计划别搞太满，因为是没办法全部执行的。所以 2023 年我就不做什么计划了，把 2022 年没能搞定的任务接着往下完成。 接下来就随心所欲吧，因为不知道意外什么时候到来，人生要及时行乐。2022 年我失去了很多，但并未得到什么，我发现逼自己也没什么用，再怎么调低自己的期望也无法掩盖世道越来越艰难的事实。躺平不是自嘲，而是无奈的选择。&lt;br &#x2F;&gt;
写这篇总结之前我看了点别人的 2022 总结，怎么说呢，现在还在互联网上能表达自己生活的人，别管他们把自己的日子说得多么艰难，实际上还是对操蛋的生活有一定还手之力的家伙；而真正「弯路里没路的人」是「死得悄无声息」的，他倒下，然后死去，一点浪花都不会有，就像我的牢骚一样。&lt;br &#x2F;&gt;
这一年，好像大家心里累得连愤怒的力气都没有了，我是这样的，以前我心里还有点血气，现在我很少提得起兴致。「天道残缺匹夫补，只为苍生不为主。」匹夫何在？苍生何在？&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;主又何在？&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;我感到我离人很远。什么是爱具体的人？当我离开网络离人越近，当这个人越具体，我反而会越反感，越难以接受，我离「爱」这个动词越来越远，我好像并不知道「爱」是什么。&lt;br &#x2F;&gt;
我的耐心也在减少，我懒得再去装作礼貌，我讨厌他们，同时也不放过自己。&lt;&#x2F;p&gt;
&lt;p&gt;过去的一年岂是一篇小文就能总结？大概就这样吧。人生如果真的是缓慢受锤的过程的话，我希望 2023 锤得慢一点。&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="zh-CN">
        <title>记一次 Rust 探险</title>
        <published>2022-04-17T00:00:00+00:00</published>
        <updated>2022-04-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://whx828.com/posts/rust-tanxian/"/>
        <id>https://whx828.com/posts/rust-tanxian/</id>
        
        <content type="html" xml:base="https://whx828.com/posts/rust-tanxian/">&lt;h2 id=&quot;wen-ti-de-qi-shi&quot;&gt;问题的起始&lt;&#x2F;h2&gt;
&lt;p&gt;最近在看《The Book》，第 17 章的 17.3 节里面有这样一个细节：&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;……&lt;&#x2F;p&gt;
&lt;p&gt;请求审核博文来改变其状态&lt;&#x2F;p&gt;
&lt;p&gt;接下来需要增加请求审核博文的功能，这应当将其状态由 &lt;code&gt;Draft&lt;&#x2F;code&gt; 改为 &lt;code&gt;PendingReview&lt;&#x2F;code&gt;。示例 17-15 展示了这段代码：&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D3C6AA; background-color: #2D353B;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Post&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    state&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;dyn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; State&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    content&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Post&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #859289;font-style: italic;&quot;&gt;   &#x2F;&#x2F; --snip--&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;    pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; new&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Post&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;        Post&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            state&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;Box&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;Draft&lt;&#x2F;span&gt;&lt;span&gt; {})),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            content&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;    pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; add_text&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;&amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;, text&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;content&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;push_str&lt;&#x2F;span&gt;&lt;span&gt;(text);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;    pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; content&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; -&amp;gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;    pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; request_review&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;&amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(s)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;state&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;take&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;            self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;state &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;request_review&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;trait&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; State&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; request_review&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;dyn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; State&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Draft&lt;&#x2F;span&gt;&lt;span&gt; {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; State&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt; for&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Draft&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; request_review&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;dyn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; State&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;        Box&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;new&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;PendingReview&lt;&#x2F;span&gt;&lt;span&gt; {})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; PendingReview&lt;&#x2F;span&gt;&lt;span&gt; {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; State&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt; for&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; PendingReview&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; request_review&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;dyn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; State&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;        self&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;blockquote&gt;
&lt;p&gt;……&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;我们需要将 &lt;code&gt;state&lt;&#x2F;code&gt; 临时设置为 &lt;code&gt;None&lt;&#x2F;code&gt; 来获取 &lt;code&gt;state&lt;&#x2F;code&gt; 值，即老状态的所有权，而不是使用 &lt;code&gt;self.state = self.state.request_review();&lt;&#x2F;code&gt; 这样的代码直接更新状态值。这确保了当 &lt;code&gt;Post&lt;&#x2F;code&gt; 被转换为新状态后不能再使用老 &lt;code&gt;state&lt;&#x2F;code&gt; 值。&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;……&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;这里让我非常困惑，我认为并不是这个原因，因此找了不少解释，以下是总结。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;box-de-xing-zhi&quot;&gt;Box 的性质&lt;&#x2F;h2&gt;
&lt;p&gt;首先来看可变性。&lt;br &#x2F;&gt;
在 Rust 中，一个变量是否可变，取决于是否用 &lt;code&gt;mut&lt;&#x2F;code&gt; 修饰变量绑定。&lt;&#x2F;p&gt;
&lt;p&gt;如果我们用 &lt;code&gt;let var : T&lt;&#x2F;code&gt; 声明，那么 &lt;code&gt;var&lt;&#x2F;code&gt; 是不可变的；而且 &lt;code&gt;var&lt;&#x2F;code&gt; 内部所有的成员也都是不可变的；&lt;br &#x2F;&gt;
如果我们用 &lt;code&gt;let mut var : T&lt;&#x2F;code&gt; 声明，那么 &lt;code&gt;var&lt;&#x2F;code&gt; 是可变的，相应的它的内部所有成员也都是可变的。&lt;br &#x2F;&gt;
这样的话，如果有个结构体引用 &lt;code&gt;&amp;amp;SomeStruct&lt;&#x2F;code&gt;，则 &lt;code&gt;SomeStruct&lt;&#x2F;code&gt; 的所有字段都是不可变的。&lt;br &#x2F;&gt;
但在实际开发中，确实存在需要结构体中的某个字段可变的情况。针对这种情况，Rust 的标准库中有个 &lt;code&gt;std::cell&lt;&#x2F;code&gt; 模块，通过共享的可变容器允许以受控的方式进行可变性操作。&lt;&#x2F;p&gt;
&lt;p&gt;在 &lt;code&gt;std::cell&lt;&#x2F;code&gt; 模块中的 &lt;code&gt;Cell&lt;&#x2F;code&gt; 和 &lt;code&gt;RefCell&lt;&#x2F;code&gt; 是实现内部可变性的&lt;strong&gt;容器&lt;&#x2F;strong&gt;，在保持容器不被 &lt;code&gt;drop&lt;&#x2F;code&gt; 的情况下可以修改其中的值；而 &lt;code&gt;Box&lt;&#x2F;code&gt; 虽然一直都被拿来和前两个一起讨论，但 &lt;code&gt;Box&lt;&#x2F;code&gt; 并没在 &lt;code&gt;std::cell&lt;&#x2F;code&gt; 模块中，它对可变性其实没啥限定。&lt;br &#x2F;&gt;
&lt;code&gt;Box&lt;&#x2F;code&gt; 是一个&lt;strong&gt;指针&lt;&#x2F;strong&gt;，有所有权和生命周期，指向堆上的某个位置，和普通的指针不同的是，它&lt;strong&gt;独占&lt;&#x2F;strong&gt;了对数据的所有权；&lt;br &#x2F;&gt;
&lt;code&gt;Cell&lt;&#x2F;code&gt; &lt;strong&gt;不是&lt;&#x2F;strong&gt;一个指针，&lt;code&gt;Cell&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; 只是把数据 T 包装一下，告诉你它有“内部可变性”，数据还是那些数据。&lt;&#x2F;p&gt;
&lt;p&gt;其次来看所有权规则。&lt;br &#x2F;&gt;
&lt;code&gt;Box&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; 不是 &lt;code&gt;Copy&lt;&#x2F;code&gt; 类型，因为 &lt;code&gt;Box&lt;&#x2F;code&gt; 拥有分配在堆上的缓冲区，非 &lt;code&gt;Copy&lt;&#x2F;code&gt; 类型如果采用逐位复制，那么会使编译器无法分辨哪个值需要对&lt;strong&gt;被引用的原始资源&lt;&#x2F;strong&gt;负责。&lt;&#x2F;p&gt;
&lt;p&gt;性质已经搞清，接下来我们来看具体问题。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wei-shen-me-zhi-jie-fu-zhi-bu-xing&quot;&gt;为什么直接赋值不行&lt;&#x2F;h2&gt;
&lt;p&gt;我在 stackoverflow 上找到一个有关的问答，回答者把它换成了直接版本：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D3C6AA; background-color: #2D353B;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Post&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    state&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;dyn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; State&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    content&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;trait&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; State&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; request_review&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;dyn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; State&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Post&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #859289;font-style: italic;&quot;&gt;    &#x2F;&#x2F; ... &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;    pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; request_review&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;&amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;        self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;state &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;state&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;request_review&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #859289;font-style: italic;&quot;&gt;    &#x2F;&#x2F; ... &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;编译器报错：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D3C6AA; background-color: #2D353B;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;self.state = self.state.request_review();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;             ^^^^^^ move occurs because `self.state` has type `std::boxed::Box&amp;lt;dyn State&amp;gt;`, which does not implement the `Copy` trait&amp;#39;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;原回答：&lt;br &#x2F;&gt;
This is because calling &lt;code&gt;State::request_review&lt;&#x2F;code&gt; will move &lt;code&gt;Box&amp;lt;self&amp;gt;&lt;&#x2F;code&gt;, which is allocated on heap, and Rust doesn’t allow you to just move values away from heap unless you implement &lt;code&gt;Copy&lt;&#x2F;code&gt;, otherwise what’s left there? The book uses &lt;code&gt;Option::take()&lt;&#x2F;code&gt; to move ownership out and leave &lt;code&gt;None&lt;&#x2F;code&gt; on the place.&lt;&#x2F;p&gt;
&lt;p&gt;翻译如下：&lt;br &#x2F;&gt;
这是因为调用 &lt;code&gt;State::request_review&lt;&#x2F;code&gt; 将 &lt;code&gt;move&lt;&#x2F;code&gt; 分配在堆上的 &lt;code&gt;Box&amp;lt;self&amp;gt;&lt;&#x2F;code&gt;，而 Rust 不允许你将值从堆中 &lt;code&gt;move&lt;&#x2F;code&gt;，除非你实现 &lt;code&gt;Copy&lt;&#x2F;code&gt;，否则原值还剩下什么呢？The book 里面使用 &lt;code&gt;Option::take()&lt;&#x2F;code&gt; 将所有权移出，并为原值保留了 &lt;code&gt;None&lt;&#x2F;code&gt; 。&lt;&#x2F;p&gt;
&lt;p&gt;其实已经讲得很清楚了，但我还要问一句：&lt;code&gt;move&lt;&#x2F;code&gt; 发生在哪里？&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D3C6AA; background-color: #2D353B;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;self.state = self.state.request_review();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;这一句中的 &lt;code&gt;self.state.request_review();&lt;&#x2F;code&gt; 使得结构体 &lt;code&gt;Post&lt;&#x2F;code&gt; 的 &lt;code&gt;state&lt;&#x2F;code&gt; 字段被 &lt;code&gt;request_review()&lt;&#x2F;code&gt; 方法赋了新值，并取得了 &lt;code&gt;state&lt;&#x2F;code&gt; 的所有权，此时 &lt;code&gt;self.state&lt;&#x2F;code&gt; 的所有权转移进了 &lt;code&gt;request_review()&lt;&#x2F;code&gt; 方法内，&lt;code&gt;self.state&lt;&#x2F;code&gt; 变成未初始化状态，而 Rust 编译器禁止使用未经初始化的变量，因为这会产生未定义行为。&lt;br &#x2F;&gt;
因此编译器报错，还指出了我们没有为 &lt;code&gt;std::boxed::Box&amp;lt;dyn State&amp;gt;&lt;&#x2F;code&gt; 实现 &lt;code&gt;Copy&lt;&#x2F;code&gt; trait，如果实现了这个 trait，&lt;code&gt;self.state&lt;&#x2F;code&gt; 在 &lt;code&gt;self.state.request_review()&lt;&#x2F;code&gt; 之后依然能保持初始化状态，也就可以完成 &lt;code&gt;self.state =&lt;&#x2F;code&gt; 这部分的赋值了。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2023-2-16-zhui-jia&quot;&gt;2023.2.16 追加&lt;&#x2F;h2&gt;
&lt;p&gt;再读《The Book》，想到自己还写过这么一篇文章，回来看的时候发现有个地方没说透：&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Rust 不允许你将值从堆中 &lt;code&gt;move&lt;&#x2F;code&gt;，除非你实现 &lt;code&gt;Copy&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;这句话什么意思？还是要看&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?version=stable&amp;amp;mode=debug&amp;amp;edition=2021&amp;amp;gist=dcc068cc77c38b8a929b9177a11500ec&quot;&gt;报错信息&lt;&#x2F;a&gt;：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D3C6AA; background-color: #2D353B;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;   Compiling&lt;&#x2F;span&gt;&lt;span&gt; playground v0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;playground)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;error[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;E0507&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; cannot&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt; move&lt;&#x2F;span&gt;&lt;span&gt; out of `&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;state` which is behind a mutable reference&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;  --&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; src&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;lib&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;rs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;22&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;         self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;state &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;state&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;request_review&lt;&#x2F;span&gt;&lt;span&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;   |                      ^^^^^^^^^^ ----------------&lt;&#x2F;span&gt;&lt;span&gt; `&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;state` moved due to this method call&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;   |                      |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;   |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;                      move&lt;&#x2F;span&gt;&lt;span&gt; occurs because `&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;state` has&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; type&lt;&#x2F;span&gt;&lt;span&gt; `&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;dyn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; State&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;`, which does not implement the `&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;Copy&lt;&#x2F;span&gt;&lt;span&gt;` &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;trait&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;note&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; this function takes ownership of the receiver `&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span&gt;`, which moves `&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;state`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;  --&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; src&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;lib&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;rs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;7&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;23&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;   |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;7&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;     fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; request_review&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;dyn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; State&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;   |                       ^^^^&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt;For&lt;&#x2F;span&gt;&lt;span&gt; more information about this error,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt; try&lt;&#x2F;span&gt;&lt;span&gt; `rustc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; --&lt;&#x2F;span&gt;&lt;span&gt;explain&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; E0507&lt;&#x2F;span&gt;&lt;span&gt;`&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;error&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; could not compile `playground` due to previous error&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;我们的操作会 &lt;code&gt;cannot move out of *self.state* which is behind a mutable reference&lt;&#x2F;code&gt;，也就是说会在可变引用时 &lt;code&gt;move&lt;&#x2F;code&gt; 变量（转移所有权）。&lt;br &#x2F;&gt;
看一下函数签名： &lt;code&gt;fn request_review(&amp;amp;mut self)&lt;&#x2F;code&gt;，果然使用的是 &lt;code&gt;Post&lt;&#x2F;code&gt; 的可变引用（也就是 &lt;code&gt;&amp;amp;mut self&lt;&#x2F;code&gt;），然后在 &lt;code&gt;self.state.request_review()&lt;&#x2F;code&gt; 这一步时 &lt;code&gt;move&lt;&#x2F;code&gt; 了 &lt;code&gt;self.state&lt;&#x2F;code&gt;，如果 &lt;code&gt;self.state&lt;&#x2F;code&gt; 没有实现 &lt;code&gt;Copy&lt;&#x2F;code&gt; 这个 trait，那么根据 Rust 规则，使用可变引用时是不能 &lt;code&gt;move&lt;&#x2F;code&gt; 的，一旦 &lt;code&gt;move&lt;&#x2F;code&gt; 了，对象的内存地址改变了，那引用还有效吗？&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;从借用规则角度看，可变引用是「独占引用」，也即在存在可变引用的时候是不能其他引用的，如果把值看成一种「可变引用」，那么很明显发生了冲突，之前的可变引用很可能就失效了。&lt;&#x2F;li&gt;
&lt;li&gt;从所有权角度看，可以把可变引用看成持有一段时间的所有权的值的特殊状态，这段时间内原值是不拥有所有权的，所以原值也没有能力去 &lt;code&gt;move&lt;&#x2F;code&gt;。&lt;&#x2F;li&gt;
&lt;li&gt;实现了 &lt;code&gt;Copy&lt;&#x2F;code&gt; trait 意味着不会真的转移所有权，而是会原封不动地复制一份出去，不会对原值有影响，因此引用就还会是有效状态。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;说了这么多，让我看看书里的操作是什么：&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #D3C6AA; background-color: #2D353B;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Post&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #859289;font-style: italic;&quot;&gt;    &#x2F;&#x2F; --snip--&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;    pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt; request_review&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;&amp;amp;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E67E80;&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(s)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;state&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;take&lt;&#x2F;span&gt;&lt;span&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D699B6;&quot;&gt;            self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;state &lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #7FBBB3;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt;(s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #E69875;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A7C080;&quot;&gt;request_review&lt;&#x2F;span&gt;&lt;span&gt;())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;人家的 &lt;code&gt;state&lt;&#x2F;code&gt; 用 &lt;code&gt;Option&lt;&#x2F;code&gt; 给包住了，而且取值和赋值是分开写的，没有写在一行里，从 &lt;code&gt;take&lt;&#x2F;code&gt; 的签名：&lt;code&gt;pub fn take(&amp;amp;mut self) -&amp;gt; Option&amp;lt;T&amp;gt;&lt;&#x2F;code&gt; 中看出 &lt;code&gt;take&lt;&#x2F;code&gt; 用的是可变借用而不是 &lt;code&gt;self&lt;&#x2F;code&gt;，也就没有 &lt;code&gt;move&lt;&#x2F;code&gt; 了，同时生命周期推断也能发挥作用，当然就规避掉了这些问题。&lt;&#x2F;p&gt;
&lt;p&gt;问题解决！感谢这些在网上无私分享知识的人们！&lt;&#x2F;p&gt;
&lt;h2 id=&quot;can-kao-yue-du&quot;&gt;参考阅读&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;57193489&#x2F;why-do-we-need-to-call-take-for-optiont-variable&quot;&gt;why do we need to call take() for Option&amp;lt;T&amp;gt; variable&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;rustwiki.org&#x2F;zh-CN&#x2F;rust-by-example&#x2F;scope&#x2F;move.html&quot;&gt;所有权和移动&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;rustwiki.org&#x2F;zh-CN&#x2F;rust-by-example&#x2F;variable_bindings&#x2F;declare.html&quot;&gt;变量先声明&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.archgrid.xyz&#x2F;2022&#x2F;03&#x2F;rust-ownership&#x2F;&quot;&gt;聊聊 Rust 中的所有权机制&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;ipotato.me&#x2F;article&#x2F;57&quot;&gt;Rust 中几个智能指针的异同与使用场景&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;rustcc.cn&#x2F;article?id=37d1cb4f-5cc9-4adc-b41a-dbe4914bf4b5&quot;&gt;【Rust 每周一知】如何理解 Rust 中的可变与不可变？&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
</content>
        
    </entry>
    <entry xml:lang="zh-CN">
        <title>杭州游记</title>
        <published>2021-07-03T00:00:00+00:00</published>
        <updated>2021-07-03T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://whx828.com/posts/hangzhou-youji/"/>
        <id>https://whx828.com/posts/hangzhou-youji/</id>
        
        <content type="html" xml:base="https://whx828.com/posts/hangzhou-youji/">&lt;p&gt;我毕业了，为了出来散心，选择到杭州旅游。&lt;&#x2F;p&gt;
&lt;p&gt;为什么来杭州呢？也没有什么特别的理由，首先我想来一座南方的城市，感受一下和北方的不同；其次去哪里无所谓，重要的是独自旅行的过程，虽然也是一种无奈；另外杭州的名气比较响亮：“上有天堂，下有苏杭”，浙江也是社会主义共同富裕的先行示范区，我想看看是怎么个先行示范的样子。&lt;&#x2F;p&gt;
&lt;p&gt;一直到旅程结束我在家里写这一篇博客的时候，都很难讲杭州是一座怎样的城市，限于各种原因我只能走马观花：杭州看起来年轻十足，年轻小伙子姑娘很多；杭州又十分忙碌，晚上10点的地铁依然是人挤人；杭州也有闲散舒适，这里的老头一样喜欢饭后打牌；杭州同时繁华，这里城市建设一流，消费主义盛行，花花世界迷人眼，各种商场随处可见，仿佛就是要人们“消费、消费、消费”，可能是浙江人有钱不在乎这些，也可能是我在景区待久了的原因。但景区也有景区的好处，比如杭州的垃圾箱和公共厕所很多，这一点确实很方便旅客。总之，经过几天的旅行我还是难以看懂这里，但已经知道这里和我从前待过的任何一处都很不一样。&lt;&#x2F;p&gt;
&lt;p&gt;杭州大妈也很热情，得知我是从辽宁来的时候纷纷表示：“哦呦，好远”，“你北方人不习惯吧”，“杭州菜偏甜”等等，另一种热情是景区的大妈，她们热心的方式是请你“喝茶”，来之前我查了一下杨梅岭骗局，对此早有戒心。&lt;&#x2F;p&gt;
&lt;p&gt;这次旅行中也遇到了很多有意思的人：青旅的舍友王祚彦先生，一位执意寻找”西湖老公“的江苏台湾冒险家，他的旅行经历相当丰富，也给我很多见闻和思考；永福寺的哈尔滨老奶奶，年轻时在北京教书，退休之后在各地旅游，是一位非常坚定的”考研党“；还有很多热情的杭州人，他们是这个闷热城市里的习习凉风，吹散我很多疲惫，在此诚心谢谢他们，使我的旅行不仅仅是旅行。&lt;&#x2F;p&gt;
&lt;p&gt;用双脚丈量土地这个说法听起来很浪漫，实际上的感受更多是一个字：累。在路上和日常的生活感受完全不一样，我也开始理解为什么有很多人迷恋这种在路上的感觉，不仅仅是娱乐和享受，而是追求一种未知的改变，这种感觉可以赋予人一种生活的激情，焕发出新的活力。&lt;&#x2F;p&gt;
&lt;p&gt;短短四五天，毕业旅行走到尾声，我挥一挥衣袖，带走了很多照片，也算不虚此行，说罢杭州好，我还是思念辽东的凉爽。&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;注&lt;&#x2F;strong&gt;：本文最开始写在 Notion 上，由于照片太多，没有把照片上传到 GitHub，所以想看照片的，请移步我的 &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;whx828.notion.site&#x2F;7990fe0b7f2944908d84f6d1f2f05ba1&quot;&gt;Notion&lt;&#x2F;a&gt; 站点。&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="zh-CN">
        <title>把自己作为方法</title>
        <published>2021-06-05T00:00:00+00:00</published>
        <updated>2021-06-05T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://whx828.com/posts/ba-ziji-zuowei-fangfa/"/>
        <id>https://whx828.com/posts/ba-ziji-zuowei-fangfa/</id>
        
        <content type="html" xml:base="https://whx828.com/posts/ba-ziji-zuowei-fangfa/">&lt;p&gt;其实是读书笔记。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bei-da-qing-nian-de-jiao-lu&quot;&gt;北大青年的焦虑&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;我妈妈回了一封信，我的印象比较深，她说她年轻的时候什么都学苏联，现在什么都学西方，这是一个问题。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;所以中国的情况变化了吗？这是一个问题。我们究竟是谁？要干什么？&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;我感觉他们对这个社会在今天发生什么也没有兴趣。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;可能确实如此，互联网的信息密集令人迷失，即使什么都不做也会有“算法”给你找乐子，虽然那不一定算是乐子。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;他们对这些事情不感兴趣。不感兴趣，又写这方面的文章，就很空洞，里面没有什么实在的观察。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;有些“学人”只是为了表面的享受，学术并没有走进他们的生活。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;大二以后，我比较重视数学和英语，觉得这是比较实在的东西，也去学经济学的课，剩下的时间就是做“浙江村”调查，以及搞社团&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;项飙在他大二的时候觉得数学和英语是比较实在的，联系到他求学的年代是90年代初期，这么一算，30年过去了，我倒没在大二产生这样的想法，而是大一就认识到了。&lt;&#x2F;p&gt;
&lt;p&gt;但这也没能如何，毕竟人家上的是北大。不过跨越这么多年，大学生所产生的想法依然有一定程度的重叠，这是很奇妙的。&lt;&#x2F;p&gt;
&lt;p&gt;项飙还提到做调查和搞社团，放到今天来看这就是做比赛和玩社团的翻版，项飙做的调查使他的起步很高，但也许并不是出于功利想法，今天可就不一样了。&lt;&#x2F;p&gt;
&lt;p&gt;今天的比赛之类没有那么学术，甚至也不是为了娱乐，而是规则扭曲下的产物，核心在于利益竞争；至于社团，年轻人甚至不屑于跟现实世界里身边的人沟通，当然他们到了互联网上，到了游戏里又是一副样子了，可想而知社团的情况，一潭死水而已。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;青年很重要，不在于我们去回想自己的青年时光，而是用今天青年的眼光去拷问我们，让他们来“审判”我们，这样才能有更真的东西，我们才有机会来反思自己。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;每一代青年都是特定时代的产物，其中也会有怪胎。&lt;&#x2F;p&gt;
&lt;p&gt;不过每代人都觉得自己的时代是最乏味的，其实没有什么可拷问。年轻人不关心这些。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;这种学生下海赚钱的事其实在1991年就有了，但在1992年一下子爆发出来，市场经济被认为是正统。各种文化现象也重新出来，比如新一轮“国学热”。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;这一段令我印象深刻的是项飙居然可以如此清晰地记住像“1991年”这样的时间节点，今天的中国我很难对某件事有清晰而具体的隔断，一般是以段时间来划分。&lt;&#x2F;p&gt;
&lt;p&gt;另一方面赚钱的事其实早就有了，罗马不是一天建成的，社会风气也不是一天就变坏的。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;资源是什么意思呢？就是在私有化市场经济之后，原来我们生存所需要的物质，现在转化成了潜在的资源，是可以升值的。你一定要占据，要有明确的产权。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;这一段相当精辟。 非常准确传神地带有一种社会风向转变的角度的叙事，有一种醒悟感：原来不能卖的现在可以卖了，世界的规则变了。大多数人们并不知道的是，某种残酷就要到来。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;同时我们对腐败官员的揭露，却把大量篇幅放在男女关系上，而对这个人究竟怎么贪污、制度设计哪里有问题、贪污造成的具体后果又讲的很虚幻？&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;很本质也很准确，不过这是讲不了的问题，项飙这样说很明显透出一种学者的稚气，其实虚幻已经给你答案了不是吗。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;yan-jiu-zhe-jiang-cun&quot;&gt;研究“浙江村”&lt;&#x2F;h2&gt;
&lt;p&gt;很有意思的一点是之前认为“浙江村”在温州，原来是在北京。这样项飙上大学的时候去做研究就说的通了，毕竟那个年代不太可能长期两地来回跑。&lt;&#x2F;p&gt;
&lt;p&gt;由此看来，一个人的故乡很重要，例如项飙早期最重要的调查其实都没逃出他的“温州”，不过这也很合理，谁也不是石头缝里蹦出来的。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;冲动是每个人都有的，关键不在于你有没有冲动，而在于你是不是让冲动推着你走。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;我几乎从未让冲动推着走过，也许这就是我目前还是一事无成的原因。&lt;&#x2F;p&gt;
&lt;p&gt;项飙的“浙江村”调查，在他的叙述来看，完全是一副高材生的典型成功案例，站在高台上做一些不那么容易的事，只要做出水准之上的东西就足以收获很多。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;因为我们大量的信息和思考方式是一定要通过文字表达出来的，积累确实很重要。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;文字 → 表达，这是很多人都提到过的概念，我也认为文字传递信息，高效而方便。虽然不像游戏、视频那样给人很高的刺激，但是性价比很好。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;这是我长期以来的一个弱点，还在挣扎当中。我必须要追赶，但也不能够放弃自己的特点，把自己搞成那样的人。怎么弄现在没有结论，还在继续追赶，我们二十年以后可以再讨论这个问题。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;人人皆有弱点，即使像项飙这样的大学者也不例外。&lt;&#x2F;p&gt;
&lt;p&gt;我认为得到一些就会失去一些，如果我的偏好对我而言我足够喜欢，那么我会接受拥有他而失去的代价。&lt;&#x2F;p&gt;
&lt;p&gt;直接有直接的好，含蓄有含蓄的美。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;理论不在于新不新、深不深、更不在于正确不正确，而是能不能形成沟通性。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;这恰恰是最难的一点，和谁去沟通？&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;艺术上的热情还是比较自然的，爱画画的人总是爱画画，但其他工作，比如研究性的、公益性的，会牵扯到很多很繁琐的细节，确实要有一种持续的热情。不能完全靠自发，而是需要通过教育。艺术真正的魅力是产生一种视觉效果，让对方去思考、反思，有思考的引带力。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;为了生活而又高于生活。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;如果赚钱糊口不是主要的目的了，你的生活意义是什么，你怎么和社会形成关系？&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;到这一步我至少5-10年，所以不用急着回答。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bian-yuan-yu-zhong-xin&quot;&gt;边缘与中心&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;真正的英雄不是改变世界，而是改变自己生活的每一天。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;醍醐灌顶。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;边缘的人要进入中心的欲望特别强，这当然会让人发挥很大的能动性，但造成各种扭曲。而且一旦进入中心之后，很多人变质腐败，因为他们从来没有把自己是谁想清楚，存在就是为了进入中心，把生他养他的土地、和周边人的关系都放弃了，变成没有原则的人。人生活中的原则不是靠抽象理念来维持的，都是靠具体的社会关系，这个当然是儒家的思想，但它确实有它的道理。如果跟周边的人、生活的世界关系不清楚，就会变成机会主义者，其他人都成了利用工具。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;基本把人的割裂讲明白了，所以把自己想明白就是在救别人。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;中国历史上的强大中心，很大度上是靠把这个中心内化，每个地方都觉得自己是个小中心，所以都会比较从容。然后把它在象征意义上给拢起来，所以既有大一统，但是又不会削尖脑袋往上爬，觉得自己的生活一无是处。其实中心对很多边缘地方是不管的，地方有很强的自主性，是那种柔性的、开放的关系。今天“地方”的文化意义真的是被抽空了， 搞一些地方博物馆、旅游，都不能够进入人心，所以处理好“边缘”和“中心”的关系是很重要的。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;角度很奇妙，同时很合理地解答了我心中长久以来的困惑，讲明白了地方和中央的关系：你当大哥，我做小弟，但咱也是个土皇帝，犹如各玩各的、貌合神离的所谓“夫妻”那般暧昧。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;大一统并不意味着一个刚性结构，但现在环境已经变了，今天我们是一个很强大的国家，确实需要强大的中心，因为有资源再分配的问题，比如上海和西藏的关系，要有互相帮助的精神。所以我强调文化和社会的自主性，但是在经济上，市场要统一，资源上，通过行政力量来二次分配，还有军队税收，这些都不能放松。第二个变化就是全球化。自洽不能是封闭起来的自洽，而是每个地方都是一个小的中心，是汇集的地方，一个穴位，贯通全身，要用这样的方式去思考。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;这个回答很有中国味道。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;那时中国对世界的影响，我觉得比今天要大。今天我们究竟摸索出了一条清晰的道路，或者是提供了一个很大的理想吗？今天的情况又不一样，今天的中国走向世界，主要不是靠输出理念，而是靠做贸易。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;输出革命和做生意可不一样。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;但更可能的是，要等一批人积累起来以后，才会对这个世界有普遍性的启发。中国是在这样一个全球化的环境下崛起，靠中国的独特性去讲世界的普遍性问题，这个蛮牵强，还不如把自己具体的问题讲清楚。把这一角讲清楚，其实就是全世界的话语。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;ge-ren-wei-ji&quot;&gt;个人危机&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;如果我不在当地泡，就是在说空话，唯一的干货来自人民群众。 观点属于人民，把观点整理出来，这个就是我们的工作。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;这两句话的左派气质已经藏不住了。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;不要怕边缘，或者知识不够，把自己的不够、天真真实地体现出来，就会很可爱，不要装腔作势。只有知道了你的真实性之后，才可以信任你。当然东方文化在政治上是相反的，这些东西都要被屏蔽，领导人不是个人，他是权力的化身，这就是不太一样的理解。到了牛津，我很感谢他们给我这么一个工作，使得我能想这些问题。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;真实是强大的力量，当然恐惧也是。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;“距离感”是分析上、方法上的概念，它和切入性是一种辩证关系。距离感不是指对问题的关心程度、对事实的熟悉程度，这些不能有距离感，越近越好，要把自己融进去。但在分析的时候，要有登上山丘看到平原的心态，才会比较客观、灵活、全面。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;分寸感能令双方感觉从容不迫。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;shen-me-shi-pi-pan&quot;&gt;什么是批判&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;学术也是这样，不能靠直觉去判断，一定要去证明它，要去展示结论是怎么达到的。往往越是明显的结论，越难去证明，但是一旦证明了以后，会是很大的贡献。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;返璞归真，最难是真。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;li-jie-de-xue-wen&quot;&gt;理解的学问&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;有人甚至断言理解是不可能的。您怎么看？&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;理解是很自然的，不难，重要的是怎样不去拒绝理解。&lt;&#x2F;li&gt;
&lt;li&gt;要真的懂你，聊一聊是不够的，因为我不知道你从哪里来的这些感觉， 所以一定要知道你的世界。从了解开始，才能真正地理解。&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;重要的是怎样不去拒绝理解这句话说出了关键，也许自己应该放下那不该有的傲慢，真诚地对待人类。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;要把他的言和行都看作是他的行动。只有通过这样理解，我们才知道我们应该怎么面对这些社会病态：不能把人一棍子打死，要考虑如何沟通，否则对罪犯就只有放纵和消灭两种态度了，没有教育改造一说了。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;世界当然不是非黑即白的，可是&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fang-tan-zhi-qian&quot;&gt;访谈之前&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;社会科学告诉你，其实没有什么很强的规律，都在于自己怎么样去理解这个世界，怎么样主动地采取行动。可能会有大的图景，但没有所谓的规律，因为一旦发现规律，那么一切到此为止，就不需要再去做工作了。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;这是一种反直觉式的思考，甚至可以说不太理性，很唯心，和工科思维很不一样。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;社会科学首先是关于你的，然后才是关于社会的。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;其实任何一门科学都差不多吧，先从自身角度出发，然后扩展到很宏大的层面。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;在中国，很多事情能不能撑下来，关键在于有没有这口气，如果你有这种小型的团结，有时候像牛皮糖一样，这个事情也就拖过去了，能做下去。不要期望有一个人帮你挡，有困难大家一起面对。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;这个就和PHT想要抱团的想法不谋而合，这么看来即便在异国，他的思维也没有脱离中国太多。&lt;&#x2F;p&gt;
&lt;p&gt;而我有更加现在中国的看法，像张一鸣最近把字节交给和自己一起创业的南开的梁汝波，这就是普罗大众能接触到的这种小型团结的体现之一。&lt;&#x2F;p&gt;
&lt;p&gt;因此给我的启示之一是：对每个人来说，小团体是必然要出现的，你可以游离在大团体中，但必然要有自己的小团体，要有一处互相支撑的地方。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;niu-jin-ji-yi&quot;&gt;牛津记忆&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;这种一对一的辅导最大的好处是什么？他们说最大的好处就是躲不过，懂就是懂，不懂就是不懂&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;条件所限，我只能自己给自己一对一辅导了。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;社会生活里有很多问题都是老问题&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;因此很大一部分的经验还没有失效，关键在于你要分清楚哪些问题是老问题。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;表面上是政府在办牛津，事实上是牛津在办政府。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;这话说的，牛气！不过清北也差不多了？当然，不要忽视东方霍格沃兹。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;其实大学的作用就是提供了一个安全的环境，让你做思想上的各种探索。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;说的有一半贴切，一半理想化。比如我到想起来要关注思想的时候人多半已经不在大学里了。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;高水平的大锅饭比较好，没有竞争压力了，大家最独特的才华才会体现出来。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;可是只有当社会的水平达到一定程度才能这么玩儿，中国的体量，绝不可能做到如此宽松的地步，无论哪个阶层永远都有相当数量的人想改命，也就不能吃上大锅饭。小国寡民不适合中国。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;你自己有多聪明、能写多少书，这个很重要吗？关键是你能培养出什么人。那些真正厉害的人，带学生，一辈子写两三篇文章，就能改变人类历史。考申请课题搞出来的东西，到底有多大的价值，确实存疑&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;那问题是：不是人人都能有这样的水平，但是却提供了大量的岗位，总不能为了宁缺毋滥不招人了吧，饭还是要吃的。&lt;&#x2F;p&gt;
&lt;p&gt;那么我们要做到：如果天才来了，别去挡他的路。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ju-chi-gan-yu-zhi-jie-xing&quot;&gt;距离感与直接性&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;主体性不是说“我很厉害”、“我很特殊”，完全不是这个意思：而是说我作为一个人在这个世界上，我和世界是什么关系，我看到了什么，哪怕我的看法不对，但是应该把自己怎么想的搞清楚。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;先从问题出发，把自己想明白，项飙很强调想清楚自己，在认识世界之前，先要有自我。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;这跟你的物质利益到底有什么关系？要把这个问题讲清楚，你的行为才有意义。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;同时也讲实际，先不管情感上如何，能不能在硬件上先达到？这是一个可以去反推的手段。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;一定要有从内到外的冲击力，有情绪的积累。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;这是后期要做的事情，之前主动摒弃情感，现在把它再拿回来，做一个总结与积累，是一个过程的收尾。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fei-xu-gou-xie-zuo&quot;&gt;非虚构写作&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;你要把自己是什么想清楚。“认命”是说从历史、结构的角度，想清楚自己是什么。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;这个对“认命”的解释令人耳目一新，回到之前论述的主题 → 想清楚自己是什么。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;xue-shu-bu-shi-tian-zhi&quot;&gt;学术不是天职&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;“跨语言的自我”，翻译成为一种思想方法，朋友之间的交流也可以是一个方法，很重要的功能是逼着你去想这个about。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;两种文化的交锋，语言代表了背后的文化，是一种投影。使用双语就是在让自己在两种思考方式之间进行转化，可能产生很独特的、很好的、经过两种文化检验过的、真正了不起的东西。&lt;&#x2F;p&gt;
&lt;p&gt;但也可能四不像。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;min-zu-yu-min-cui&quot;&gt;民族与民粹&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;清楚现实状况的人，文章是不可能写得那么正式的，因为事情非常复杂，搞出一二三四五六，只是贴标签，其实是不完全清楚。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;这个是我从未想到的，但可以解释一些现象。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;作为过渡，我就去了新加坡国立大学，在亚洲研究所做博后。新加坡国立大学对我生活的影响非常大，我在那里碰见了我的爱人，她也在亚洲研究所。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;所以说，你不知惊喜在哪里冒出来，不要放弃学习！&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;新加坡最让我觉得可圈可点的地方，还不是像杜赞奇和安东尼-瑞德这样的一批人，而是他们背后一群兢兢业业的人。你可能从来没听过他们，他们往往都是女性，也许没有很大的想法，看起来没有什么天才的创造力，就是埋头苦干，有非常专业的精神，建立团队，有宽容的态度，做事情比较无私。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;新加坡的这样的一群人决定了所在群体的下限，他们也许上限没有多高，但是下限绝对不低。这是很重要的隐形实力。&lt;&#x2F;p&gt;
&lt;p&gt;联想到之前和某人关于对亚洲某发达国家的讨论，也许在那里有很多这样的人，无关男女。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;夸夸其谈相当可怕，好像一种灵感让自己感动起来，但是飘过去了就什么都没有。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;传神，无奈。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;xin-jia-po-qi-meng&quot;&gt;新加坡启蒙&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;她让我理解到电影、诗歌、艺术、民谣其实和学术一样，都是人类自我表达的方式。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;很多事情首先都是从认识自我开始，然后慢慢就有了表达欲。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;因为从小到大，学习是天职，从来不问为什么学习，没有想过学术和寓言其实是一回事，跟唱歌是一回事。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;我的启蒙从大学开始。我为什么学习，学习是什么这两个问题我已经有答案了。&lt;&#x2F;p&gt;
&lt;p&gt;首先回答第二个问题，学习是生活的必须，如果想要把自己的想法落实，学习是必要手段；其次，生活里基本所有的元素都可以通过学习重构，触发改变，这其中当然就包含了进步，这样也就回答了第一个问题，我想做到想做的事，因此要学习。&lt;&#x2F;p&gt;
&lt;p&gt;我现在认为学习是改变的一部分，同时也是改变的开端。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;kua-guo-xing-de-zi-qia-de-xiao-shi-jie&quot;&gt;跨国性的自洽的小世界&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;这个小群体越是具备异质性、多样性，它的抵制的能力就越强，就会更加有机。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;这个对会议很有参考意义，我们应该一上来就去选择非常不一样的人，尽管会带来很多挑战。对于学习或者工作，这样的关系应该尚能维持。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;对于学者来讲，小世界首先是一个被构造的过程，其次是不断骚动的过程。你构造它，它逼着你，刺激你去反思自己，批评自己，不断冲破原来的理解。它越是活跃，越是骚动，给你的安全感越强，因为你的生存就是你的思考，如果不断觉得自己在思考，就很明确地感觉到自己在生存，不用为生存害怕，因为思想活着。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;构造是在满足表达欲，这个构造的过程会产生很多奇妙的反应，会改变你，持续不断。&lt;&#x2F;p&gt;
&lt;p&gt;项飙说生存就是思考，那么只要还在思考，我们就永生。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;真正的全球性只存在于无数的地方性之中。贝多芬是全世界的，但他首先是欧洲的，不是非洲的，不是拉美的。为什么欧洲的音乐家比非洲的音乐家更“全球”？这是个问题。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;前半句是在说万事皆有顺序，先小而大；后半句的观点其实很容易解释，欧洲有钱有技术，因此有人，非洲只有才华，冒不出头。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;da-xue-ying-gai-xun-zhao-li-wai&quot;&gt;大学应该寻找例外&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;每个时代大学的功能都不一样。我们进入了一个物质相对充裕、城市教育水平相对高的时期，所以“人的生产”变得越来越重要。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;所以这是不是在说：从前的人没那么重要？&lt;&#x2F;p&gt;
&lt;p&gt;尽管真相不中听，现在的人，也没那么重要。大学确实应该认识到时代的召唤，进而改革，可是改革就要流血，不是每个人都愿意流血，你还不知道你的改革会让谁去流血。&lt;&#x2F;p&gt;
&lt;p&gt;因此先驱令人敬仰，不光是因为他们敢自己流血，而且也是因为他们做好了让大家都去流血的心理准备。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;大学不是去树立范例，而是要去寻找例外。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;这么看，现在的大学热衷于造神，离项飙的想法还远着，几近背道而驰。&lt;&#x2F;p&gt;
&lt;p&gt;大学不去寻找例外，我们自己去找，自己的、别人的、亲人朋友的、陌生人的，通通来者不拒。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;但是恢复高考把此前的官僚和城市知识分子一下子拢进来，其实是一个政党和当时社会主义体制下的精英的重新联盟。大学当然是搞精英主义，你看现在回忆恢复高考的人，很多都是干部子弟，从农村回到城市，不仅恢复了原来比较优越的地位，而且用这种途径在文化、道德上使自己的优越正当化、合法化。现在我们的大学是主流中的主流，大学也以此为豪。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;ge-ren-wen-ti-jing-yan-hua&quot;&gt;个人问题经验化&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;“打通”是什么意思，这个词我们已经说过很多遍了，打通就是回到实践，因为实践是最盘根、最通的！怎么样回到实践？从哪里回到实践？就是要从这些书本上学到的概念、范畴、理论、教条、框架离开，新的基础就是实践。但实践是那么流动、那么无情，怎么把握？个人经历就是开始把握的起点。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;在实践中总结自己的经验，反推回之前学的东西 → 解构、重构。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;xin-yan-jiu&quot;&gt;新研究&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;要真正通向上帝，必须通过自己的语境和语言，那是通向上帝唯一的思想途径。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;母语是根源，包容一切。人无法脱离根源，连上帝也不能免俗。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;现在我们共同的超越性的理想没有了，下面又没有空间，大家每天糊里糊涂。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;解放全人类的激情褪去之后，犹如理想破灭，那可不就是行尸走肉吗？原来是难得糊涂安慰自己，现在是醉生梦死麻痹自己。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;整个法律就写成让你时刻准备着离婚，有点这个意思。比方说两人结婚二十年，女方工资水平比较低，但对家庭付出大量的时间、精力的投入，到离婚时这些都不算，只算你名下登记的资产。《司法解释三》通过的背后的一个原因是说很多女性傍大款结婚，结婚后很快离婚，要拿一半财产，所以法律要保护大款。很明显，对比来看，就能看到法律对谁的声音更敏感。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;因此对于一些国家出台的政策，你要认真想一想到底和你有没有关系，不过大家也不是傻子，有很多人都很清醒。&lt;&#x2F;p&gt;
&lt;p&gt;某些话有人能听懂其中隐含的意思，可能是因为那些话是专门说给那些人听的。与你无关，你自然很难听懂，不要自作多情。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;但后来到现在，基本上就是城市里面受过高等教育的人在讨论，哪怕在社交媒体上，也很少听到工人的声音。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;这带来两个问题：&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;社交媒体是否本身就具有门槛，将一些人置之门外？&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;工人也是人，也会有表达欲的需要，既然他们不在社交媒体上满足表达欲，那么是在哪里？&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;回答：&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;也许是，因为时代的受教育文化因素等影响，不过在可见的未来十几年，会有大量工人涌进互联网。&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;以我父辈为例，表达欲是在和朋友的现实交流中完成的，例如酒局，其实承担很大一部分的社交功能，即便看起来很没意思，但那是大家共同选择的游戏方式，想玩就得入局。&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;gong-tong-li-xiang&quot;&gt;共同理想&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;不是从理念上改变自己、重新树立理想，而是知道自己已经背叛了理想，现在要通过一切手段来自保，不允许任何人说话，所以现在的情况是比较复杂的。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;其实很可悲，但问题是，你的可悲不要来烦扰到我。可惜这种可悲更多意义上是一种奢侈品，绝非人人皆有，拥有它的人可以轻易影响别人的生活，这也是复杂的来源。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;现在世界的问题这么多，中国当然要努力走出不一样的路，但现在主流的心态，不是说要走不一样的路，而是取而代之，要当老大，很多基本的想法和美国非常类似，我觉得这和共同理想的丧失都有关系。中国在什么时候最令世界钦佩？那就是上世纪五六十年代。从万隆会议开始，到第三世界理论的提出，中国在国际上的影响非常大，引起了很多国际上的争论。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;这当然是理想破灭的后果之一，既然选择了不一样的路那就是必然，要了解过去，但不能沉湎。如果真的想重现当年的辉煌，那就重新走当年的老路，反之，洗洗睡吧。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;要证明自己其实就是没有自己，意思是说，要通过已经预设的原则和标准、别人的逻辑和流程来证明自己的存在，其实是取悦别人，把自己搞没有了。自我证明是很危险的。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;但在今天，想要活着，挣钱，就要时时刻刻证明自己，哪怕要牺牲自己。每个人都在这个罗网里没有解脱。也许在生产资料高度发达的、具有高度人类责任感的社会才能真正有尊严地活着吧。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;xiang-shen-zuo-wei-fang-fa&quot;&gt;乡绅作为方法&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;如果人民代表制度不能被有效激活，那么现在的政治环境里面，似乎没有什么真正的沟通渠道。– 吴琦&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;谁说一流的知识分子对时局不清楚？他们明明清楚得很，还是不能小瞧任何人，收起对他们不切实际的想象，把自己作为方法，重新看待世界。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fang-tan-zhi-qian-1&quot;&gt;访谈之前&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;现在年轻人说，不用下结论，也不用从高大上的原则出发，就是讲自己的经验，经验比较琐碎，乱七八糟没有关系，只要是真的就有意义。这是一份从容和自信，这是相对新的， 跟年轻人的教育水平、城市化的生活方式都有关系。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;吃饱了之后会去想一想的人正在越来越多地浮现出来，毕竟思考也是一种活动。&lt;&#x2F;p&gt;
&lt;p&gt;思考之后，会有一些不一样的东西进来，包括自尊。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ren-de-zai-sheng-chan&quot;&gt;人的再生产&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;“人的再生产”跟“人的生产”不一样，“人的生产”是说人怎么样被培养成一个生产的要素， 而“人的再生产”就是人怎么样再生产自己，自己成为目标。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;让人成为真正的人，去做只有人才能胜任的事，让人类给人类自己存在的意义。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;再去看资本主义本身的变化，现在谁是赚钱的大户，平台可能是第一，第二就是跟“人的再生产”有关系的教育、医疗、娱乐等各种服务，接下来可能是采掘和农业，所谓第一产业。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;在人的再生产之前还有项目，说明我们还没有完全解放自己，不过我看情况已经很有转机，也许下一个阶段真的不远了。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;这也促使我思考如今“人的再生产”的问题，这其实是一个很重要的政治问题，看起来最不政治，但政治就在这里出现。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;在一定高度上看，政治无处不在。&lt;&#x2F;p&gt;
&lt;p&gt;今天的政治是否有了新的含义？不得而知。但可以肯定的是会有一些变化，围绕人的斗争形式上丰富起来几乎是一个必然结果，这也就导致了一些看起来不政治的问题实际上就是政治问题。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;政府鼓励的不是真正回国定居工作，而一般是短期回国甚至不回国服务，从回国服务变成为国服务，这是一个很大的转变。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;这里可以看出政府的格局，见过世面之后，“物以稀为贵”的“稀”会经过提纯，变得纯粹了起来；某些事上不再讲面子，而是要里子，底气足了之后做一些符合自己状态的事，这是政府的进步。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;jie-ceng-liu-dong-de-bei-lun&quot;&gt;阶层流动的悖论&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;一个是到目前为止基本上大部分人还是往上流动，因为经济总量还是在扩张。第二个特征，中国的社会分化是一种全民参与式、以市场为基准的社会竞争。第三个特征，纵向分化又跟横向的流动紧密联系在一起。社交媒体分层又造成更大的分割、破碎化，很难形成动员，在思想表达上很同质。但像中国的这么大规模，人人都不认命，这可能不是经常出现的现象。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;原来有人往上流动是因为经济总量还在扩张才能办到，不是有人穷有人富的动态过程，而是有人如果富，很大可能会一直富下去。那么如果经济总量不再扩张，悲观看就不会再有新人富起来了。&lt;&#x2F;p&gt;
&lt;p&gt;仔细一想好像真的是这个道理，发达国家的阶级流动远远小于中国，只是他们的平民阶层相对优渥的生活掩盖了这些现象。天下的乌鸦很快就要一般黑了。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;现在我们好像被绑架了，一定要更高更快更强，正是因为不太愿意进行激烈的再分配，已经获得的人还要获得更多，同时又要把下面的人也提上去，这个确实很难，今后可能还是要慢慢走向再分配的思路。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;项飙认为今后可能要慢慢走向相对温和的再分配，我认为这将会是一个长期博弈过程，里面充满了变数，如果真有人人发财的路子，美国早就去做了。&lt;&#x2F;p&gt;
&lt;p&gt;再分配是历史发展的主旋律，小到劫富济贫，大到社会变化，都是这种主旋律的集中体现。联系到现在既去政治化又加强政治化的特点，我认为事情可能会走向最危险的境地，会发生相当剧烈的变革，然而变革之后又会是什么样子？天知道。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;xun-zhao-xin-de-hua-yu&quot;&gt;寻找新的话语&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;放在上世纪90年代或者2000年初， 那时还有关于左与右的讨论， 两边对于中国社会的描述以及背后的原因，都有具体的指向，比如左翼认为是资本主义这个大的系统出现问题，右翼说是权力本身的腐朽和话语的滞后。但现在一个很大的问题是，首先这个对立慢慢在消失，其次可能也因为对立的消失，公共话语本身也消失了，没有回应大家实际的感受，所以有一种普遍的不知所措。一方面感受到自己的生活出现了具体的变化，也包括进步，但另一方面又觉得不足够，不知道怎么理解，也不知道对抗什么，索性不想那么多，生活还能照样过，也蛮舒服。 – 吴琦&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;这也是我看到的困惑，当吃饱了饭，矛盾没那么尖化的时候，似乎每个人都无所适从了，集体迷失方向感，再没有一个强人出来给大家指明方向，抑或者是人人都想得很明白，但又没有推广性，难以有沟通全员的共识存在。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;在今天，生活方式跟资本、国家权力同等重要。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;还是上述观点的延伸，饱暖思淫欲。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;文化这个概念可能会引起误解，一讲文化大家就觉得是文学、艺术，其实它就是指生活方式、日常经历、生活意义，包括抖音这些，六七十年代的文化研究，和在此之前的法兰克福学派给了我们很好的例子。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;原来我们觉得“粗俗”的东西实际上就是生活的一部分，然而经过一定程度的教育我们好像把“生活”本身视作一种“罪恶”，其实是不够了解自己。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;比方说我会倾向于去讲去政治化或者非政治化，比如物流型权力、基础设施权力，这些都是讲公共事务变得越来越被技术化地处理，人民内部矛盾用人民币解决，不管有理没理，就是给钱，对错不重要了，这就是我说的去政治化的意思。香港也是一样，商人治港，别问原则，老老实实做生意，其他的都无所谓，但是这个不可能长治久安。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;这样“简化”问题，其实是在逃避、偷懒，是在放弃对本质、对解释、对理解的追求。&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;反思的意思是，你要阻止自己，要把自己停住，不要线性地往前冲，想一想为什么今天要这么做，不能用别的方式。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;这个讲的不好。反思应该是一种隐藏起来的本能，如果没有反思，人类不可能存活下来，面对这样一个没有天敌，只能内部竞争的环境，我们应该做的是找回自己的反思本能。&lt;&#x2F;p&gt;
&lt;h2 id=&quot;zuo-wei-zhong-jie-de-ren-lei-xue&quot;&gt;作为中介的人类学&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;一个好的范例超过很多理论。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;zai-tan-xiang-shen&quot;&gt;再谈乡绅&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;要成为一系列的叙述，一个强大的自觉，讲出来之后，能让你觉得站在这个世界上有根基，如果外面来的东西你觉得不懂，你就有勇气说不懂，说不喜欢。所谓知识就是对世界上发生了什么事有根有据的了解，从这里开始，去观察，去沉淀，慢慢沉淀出底气。&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;相当于有了自己的“根”，一个坐标系里的参考点，从此有了空间。&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;一本书最大的用处是给人改变，其次是给人思考，这本《把自己作为方法》二者皆有。里面最令人印象深刻的一句是：“不要拒绝理解”。这是我想法的盲区，也许在以后，我会再次翻看这本书，相信可以给我与此刻不一样的感受。&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
