<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Unix on 方糖猫Blog</title>
    <link>https://ftmao.com/blog/tags/unix/</link>
    <description>AI 视频、AI Agent 与工程实践笔记</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <lastBuildDate>Wed, 01 Nov 2017 11:00:00 +0800</lastBuildDate><atom:link href="https://ftmao.com/blog/tags/unix/index.xml" rel="self" type="application/rss+xml" /><item>
      <title>《深入理解计算机系统》（CSAPP）学习笔记：给新手的硬件、操作系统与网络并发入门</title>
      <link>https://ftmao.com/blog/bookstore/computer-systems-programmer-perspective-notes/</link>
      <pubDate>Wed, 01 Nov 2017 11:00:00 +0800</pubDate>
      <guid>https://ftmao.com/blog/bookstore/computer-systems-programmer-perspective-notes/</guid>
      <description>&lt;h1 id=&#34;深入理解计算机系统csapp学习笔记给新手的硬件操作系统与网络并发入门&#34;&gt;《深入理解计算机系统》（CSAPP）学习笔记：给新手的硬件、操作系统与网络并发入门&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;参考书籍：《深入理解计算机系统》（Computer Systems: A Programmer&amp;rsquo;s Perspective，简称 CSAPP）&lt;br&gt;
目标读者：想学透计算机底层、准备面试、或者写代码总感觉&amp;quot;知其然不知其所以然&amp;quot;的新手。&lt;br&gt;
阅读建议：这篇文章不讲完 700 页书的全部细节，而是帮你建立&lt;strong&gt;主干知识框架&lt;/strong&gt;，并标注容易踩坑的地方。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一为什么要学-csapp&#34;&gt;一、为什么要学 CSAPP？&lt;/h2&gt;
&lt;p&gt;很多新手学编程的路径是：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;语法 → 框架 → 项目 → 面试八股&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;但遇到这些问题时往往卡住：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;为什么 &lt;code&gt;int&lt;/code&gt; 溢出会变成负数？&lt;/li&gt;
&lt;li&gt;为什么同样的代码，有时快有时慢？&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fork()&lt;/code&gt; 之后到底发生了什么？&lt;/li&gt;
&lt;li&gt;为什么多线程程序偶尔结果不对？&lt;/li&gt;
&lt;li&gt;TCP 连接为什么要三次握手、四次挥手？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CSAPP 就是帮你从&amp;quot;会写代码&amp;quot;进化到&amp;quot;理解代码为什么这样跑&amp;quot;。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;二计算机系统全景图&#34;&gt;二、计算机系统全景图&lt;/h2&gt;
&lt;p&gt;先把整体结构印在脑子里：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;graph TD
    A[应用程序] --&amp;gt; B[操作系统]
    B --&amp;gt; C[硬件层]
    C --&amp;gt; D[CPU / 处理器]
    C --&amp;gt; E[内存 / 主存]
    C --&amp;gt; F[磁盘 / SSD]
    C --&amp;gt; G[网络接口 / I/O 设备]
    B --&amp;gt; H[进程管理]
    B --&amp;gt; I[虚拟内存]
    B --&amp;gt; J[文件系统]
    B --&amp;gt; K[网络协议栈]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;核心思想&lt;/strong&gt;：操作系统是应用程序和硬件之间的中间层。它负责：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;让多个程序&amp;quot;同时&amp;quot;运行（进程调度）&lt;/li&gt;
&lt;li&gt;给每个程序独立的内存空间（虚拟内存）&lt;/li&gt;
&lt;li&gt;统一管理文件、网络、输入输出&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;三信息就是位--上下文&#34;&gt;三、信息就是位 + 上下文&lt;/h2&gt;
&lt;p&gt;计算机里所有的信息——数字、文字、图片、声音、代码——最终都是 &lt;strong&gt;0 和 1&lt;/strong&gt;。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    A[人类可理解的数据] --&amp;gt;|编码| B[二进制位流]
    B --&amp;gt;|解释规则| C[整数 / 浮点数 / 字符 / 指令]
    C --&amp;gt;|上下文| D[有意义的信息]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;31-整数溢出新手最常踩的坑&#34;&gt;3.1 整数溢出：新手最常踩的坑&lt;/h3&gt;
&lt;p&gt;在 C/C++ 中，有符号整数溢出是&lt;strong&gt;未定义行为&lt;/strong&gt;（Undefined Behavior）。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; a &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2147483647&lt;/span&gt;;  &lt;span style=&#34;color:#75715e&#34;&gt;// int 最大值
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; b &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; a &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;;       &lt;span style=&#34;color:#75715e&#34;&gt;// 溢出，结果未定义，通常变成 -2147483648
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;避坑技巧&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;做加法前判断是否接近上限。&lt;/li&gt;
&lt;li&gt;涉及大数时用 &lt;code&gt;long long&lt;/code&gt; 或任意精度库。&lt;/li&gt;
&lt;li&gt;无符号整数运算不会溢出，但会发生&lt;strong&gt;回绕&lt;/strong&gt;（wrap around），同样要小心。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;32-浮点数精度问题&#34;&gt;3.2 浮点数精度问题&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;double&lt;/span&gt; a &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0.1&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;double&lt;/span&gt; b &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0.2&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (a &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; b &lt;span style=&#34;color:#f92672&#34;&gt;==&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0.3&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;相等&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#66d9ef&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;不相等！&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;);  &lt;span style=&#34;color:#75715e&#34;&gt;// 大概率进这里
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;原因&lt;/strong&gt;：0.1 在二进制浮点中无法精确表示。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;避坑技巧&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;比较浮点数时用误差范围：&lt;code&gt;fabs(a + b - 0.3) &amp;lt; 1e-9&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;财务计算避免用 &lt;code&gt;float&lt;/code&gt;/&lt;code&gt;double&lt;/code&gt;，考虑定点数或专用库。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;33-大端与小端&#34;&gt;3.3 大端与小端&lt;/h3&gt;
&lt;p&gt;多字节数据在内存里怎么放？&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    A[数据 0x12345678] --&amp;gt; B[大端序&amp;lt;br/&amp;gt;内存: 12 34 56 78]
    A --&amp;gt; C[小端序&amp;lt;br/&amp;gt;内存: 78 56 34 12]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;大端&lt;/strong&gt;：高位字节放低地址（像人类读数字）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;小端&lt;/strong&gt;：低位字节放低地址（x86-64 常用）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;避坑技巧&lt;/strong&gt;：网络传输用&lt;strong&gt;大端序&lt;/strong&gt;（网络字节序），调用 &lt;code&gt;htonl()&lt;/code&gt; / &lt;code&gt;htons()&lt;/code&gt; 转换。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;四程序的机器级表示&#34;&gt;四、程序的机器级表示&lt;/h2&gt;
&lt;h3 id=&#34;41-从源代码到可执行文件&#34;&gt;4.1 从源代码到可执行文件&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    A[源代码 hello.c] --&amp;gt;|预处理器 cpp| B[预处理后的 .i]
    B --&amp;gt;|编译器 cc1| C[汇编代码 .s]
    C --&amp;gt;|汇编器 as| D[目标文件 .o]
    D --&amp;gt;|链接器 ld| E[可执行文件]
    E --&amp;gt;|操作系统加载| F[CPU 执行]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;每一步都可能出问题：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;阶段&lt;/th&gt;
					&lt;th&gt;典型错误&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;预处理&lt;/td&gt;
					&lt;td&gt;宏展开导致奇怪语法&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;编译&lt;/td&gt;
					&lt;td&gt;类型错误、语法错误&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;汇编&lt;/td&gt;
					&lt;td&gt;很少直接出错&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;链接&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;undefined reference&lt;/code&gt;、&lt;code&gt;multiple definition&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;运行&lt;/td&gt;
					&lt;td&gt;段错误、内存泄漏、逻辑错误&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;42-调用栈函数调用的底层&#34;&gt;4.2 调用栈：函数调用的底层&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TB
    subgraph 栈内存[&amp;#34;栈内存（从高地址向低地址增长）&amp;#34;]
        A[调用者栈帧] --&amp;gt; B[返回地址]
        B --&amp;gt; C[被调用者局部变量]
        C --&amp;gt; D[被调用者参数空间]
    end&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;关键概念&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;栈帧（Stack Frame）&lt;/strong&gt;：每次函数调用都会在栈上分配一块空间。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;返回地址&lt;/strong&gt;：函数执行完后要回到哪里。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;缓冲区溢出&lt;/strong&gt;：局部数组写越界，可能覆盖返回地址，导致程序崩溃或被攻击。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;43-缓冲区溢出经典安全漏洞&#34;&gt;4.3 缓冲区溢出：经典安全漏洞&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;vulnerable&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; buf[&lt;span style=&#34;color:#ae81ff&#34;&gt;8&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;gets&lt;/span&gt;(buf);  &lt;span style=&#34;color:#75715e&#34;&gt;// 危险！不检查长度
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;避坑技巧&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;永远不要用 &lt;code&gt;gets()&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;用 &lt;code&gt;fgets()&lt;/code&gt;、&lt;code&gt;snprintf()&lt;/code&gt;、&lt;code&gt;strncpy()&lt;/code&gt; 等带长度限制的函数。&lt;/li&gt;
&lt;li&gt;编译时开启保护：&lt;code&gt;-fstack-protector-strong&lt;/code&gt;、&lt;code&gt;-D_FORTIFY_SOURCE=2&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;五内存层次结构&#34;&gt;五、内存层次结构&lt;/h2&gt;
&lt;h3 id=&#34;51-速度像金字塔&#34;&gt;5.1 速度像金字塔&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TB
    A[寄存器&amp;lt;br/&amp;gt;最快 / 容量最小] --&amp;gt; B[L1 缓存]
    B --&amp;gt; C[L2 缓存]
    C --&amp;gt; D[L3 缓存]
    D --&amp;gt; E[主存 / 内存]
    E --&amp;gt; F[磁盘 / SSD]
    F --&amp;gt; G[网络存储]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;核心规律&lt;/strong&gt;：越靠近 CPU，速度越快，容量越小，价格越贵。&lt;/p&gt;
&lt;h3 id=&#34;52-局部性原理&#34;&gt;5.2 局部性原理&lt;/h3&gt;
&lt;p&gt;程序倾向于重复使用最近用过的数据和指令：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;时间局部性&lt;/strong&gt;：刚访问的数据很可能再次被访问。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;空间局部性&lt;/strong&gt;：访问某个地址后，附近地址很可能被访问。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;优化例子&lt;/strong&gt;：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 缓存不友好：按列访问
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; j &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;; j &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; n; j&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; i &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;; i &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; n; i&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        sum &lt;span style=&#34;color:#f92672&#34;&gt;+=&lt;/span&gt; a[i][j];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 缓存友好：按行访问
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; i &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;; i &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; n; i&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; j &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;; j &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt; n; j&lt;span style=&#34;color:#f92672&#34;&gt;++&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        sum &lt;span style=&#34;color:#f92672&#34;&gt;+=&lt;/span&gt; a[i][j];&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;避坑技巧&lt;/strong&gt;：写循环时注意数据访问顺序，尽量连续访问内存。&lt;/p&gt;
&lt;h3 id=&#34;53-cache-未命中&#34;&gt;5.3 Cache 未命中&lt;/h3&gt;
&lt;p&gt;CPU 先去缓存找数据，没找到再去内存找，这就是 &lt;strong&gt;Cache Miss&lt;/strong&gt;，会带来几十到几百个时钟周期的延迟。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;减少 Cache Miss 的方法&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;数据紧凑排列，减少结构体填充。&lt;/li&gt;
&lt;li&gt;避免伪共享（多线程中不同变量落在同一缓存行）。&lt;/li&gt;
&lt;li&gt;按行遍历二维数组。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;六链接&#34;&gt;六、链接&lt;/h2&gt;
&lt;p&gt;链接器把多个 &lt;code&gt;.o&lt;/code&gt; 文件拼成一个可执行文件。&lt;/p&gt;
&lt;h3 id=&#34;61-静态链接-vs-动态链接&#34;&gt;6.1 静态链接 vs 动态链接&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TB
    A[静态链接] --&amp;gt; B[库代码复制进可执行文件]
    B --&amp;gt; C[优点: 独立运行]
    B --&amp;gt; D[缺点: 体积大 / 更新麻烦]
    
    E[动态链接] --&amp;gt; F[运行时才加载共享库]
    F --&amp;gt; G[优点: 体积小 / 共享内存]
    F --&amp;gt; H[缺点: 依赖环境 .so 文件]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;62-常见链接错误&#34;&gt;6.2 常见链接错误&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;错误&lt;/th&gt;
					&lt;th&gt;原因&lt;/th&gt;
					&lt;th&gt;解决&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;undefined reference to &#39;xxx&#39;&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;函数声明了但没找到定义&lt;/td&gt;
					&lt;td&gt;检查是否漏链接库文件&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;multiple definition of &#39;xxx&#39;&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;全局变量/函数在多个文件定义&lt;/td&gt;
					&lt;td&gt;用 &lt;code&gt;extern&lt;/code&gt; 声明，只在一个 &lt;code&gt;.c&lt;/code&gt; 中定义&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;cannot find -lxxx&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;链接器找不到库&lt;/td&gt;
					&lt;td&gt;用 &lt;code&gt;-L&lt;/code&gt; 指定库路径&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;避坑技巧&lt;/strong&gt;：头文件只放声明，定义放在 &lt;code&gt;.c&lt;/code&gt; 文件里；全局变量尽量用 &lt;code&gt;static&lt;/code&gt; 限制作用域。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;七异常控制流进程与信号&#34;&gt;七、异常控制流：进程与信号&lt;/h2&gt;
&lt;h3 id=&#34;71-进程是什么&#34;&gt;7.1 进程是什么？&lt;/h3&gt;
&lt;p&gt;进程是操作系统&lt;strong&gt;资源分配的基本单位&lt;/strong&gt;。每个进程有自己的：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;地址空间（代码、数据、堆、栈）&lt;/li&gt;
&lt;li&gt;打开的文件描述符&lt;/li&gt;
&lt;li&gt;寄存器状态&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TB
    subgraph 进程地址空间[&amp;#34;进程地址空间&amp;#34;]
        A[内核空间] 
        B[栈]
        C[堆]
        D[数据段]
        E[代码段]
    end
    A --&amp;gt; B --&amp;gt; C --&amp;gt; D --&amp;gt; E&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;72-fork--exec--waitunix-进程三件套&#34;&gt;7.2 fork / exec / wait：Unix 进程三件套&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;sequenceDiagram
    participant P as 父进程
    participant C as 子进程
    participant K as 内核
    P-&amp;gt;&amp;gt;K: fork()
    K--&amp;gt;&amp;gt;P: 返回子进程 PID
    K--&amp;gt;&amp;gt;C: 返回 0
    C-&amp;gt;&amp;gt;K: execve(&amp;#34;/bin/ls&amp;#34;, ...)
    K-&amp;gt;&amp;gt;C: 替换为 ls 程序
    C--&amp;gt;&amp;gt;P: 退出状态
    P-&amp;gt;&amp;gt;K: waitpid()
    K--&amp;gt;&amp;gt;P: 回收子进程&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;关键注意点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;fork()&lt;/code&gt; 后，父进程和子进程&lt;strong&gt;独立运行&lt;/strong&gt;，各自有独立地址空间。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;exec()&lt;/code&gt; 会替换当前进程的代码和数据，PID 不变。&lt;/li&gt;
&lt;li&gt;父进程必须用 &lt;code&gt;wait()&lt;/code&gt;/&lt;code&gt;waitpid()&lt;/code&gt; 回收子进程，否则会产生&lt;strong&gt;僵尸进程&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;73-僵尸进程与孤儿进程&#34;&gt;7.3 僵尸进程与孤儿进程&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;僵尸进程&lt;/strong&gt;：子进程已结束，但父进程没回收，占用进程表资源。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;孤儿进程&lt;/strong&gt;：父进程先结束，子进程被 &lt;code&gt;init&lt;/code&gt; 进程收养。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;避坑技巧&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;父进程捕获 &lt;code&gt;SIGCHLD&lt;/code&gt; 信号，在信号处理函数中调用 &lt;code&gt;waitpid()&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;或者用 &lt;code&gt;signal(SIGCHLD, SIG_IGN)&lt;/code&gt;（在 Linux 上可自动回收）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;74-信号&#34;&gt;7.4 信号&lt;/h3&gt;
&lt;p&gt;信号是 Unix 的异步通知机制：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;信号&lt;/th&gt;
					&lt;th&gt;含义&lt;/th&gt;
					&lt;th&gt;常见场景&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;SIGINT&lt;/td&gt;
					&lt;td&gt;中断（Ctrl+C）&lt;/td&gt;
					&lt;td&gt;终止前台进程&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;SIGSEGV&lt;/td&gt;
					&lt;td&gt;段错误&lt;/td&gt;
					&lt;td&gt;访问非法内存&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;SIGKILL&lt;/td&gt;
					&lt;td&gt;强制终止&lt;/td&gt;
					&lt;td&gt;无法捕获、无法忽略&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;SIGTERM&lt;/td&gt;
					&lt;td&gt;正常终止&lt;/td&gt;
					&lt;td&gt;可以被捕获处理&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;避坑技巧&lt;/strong&gt;：&lt;code&gt;SIGKILL&lt;/code&gt; 和 &lt;code&gt;SIGSTOP&lt;/code&gt; 不能被捕获或忽略，不要试图拦截它们。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;八虚拟内存&#34;&gt;八、虚拟内存&lt;/h2&gt;
&lt;h3 id=&#34;81-为什么需要虚拟内存&#34;&gt;8.1 为什么需要虚拟内存？&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    A[进程A虚拟地址] --&amp;gt;|页表| C[物理内存]
    B[进程B虚拟地址] --&amp;gt;|页表| C
    C --&amp;gt; D[磁盘交换区]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;虚拟内存的好处：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;隔离&lt;/strong&gt;：每个进程以为自己在独占内存，互不干扰。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;简化&lt;/strong&gt;：程序使用连续虚拟地址，实际物理内存可以离散。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;共享&lt;/strong&gt;：不同进程可以映射同一块物理内存（如共享库）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;82-地址翻译页表与-tlb&#34;&gt;8.2 地址翻译：页表与 TLB&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    A[虚拟地址] --&amp;gt; B[页号 + 页内偏移]
    B --&amp;gt; C{TLB 命中?}
    C --&amp;gt;|是| D[直接得到物理地址]
    C --&amp;gt;|否| E[查页表]
    E --&amp;gt; F[得到物理地址]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;页表&lt;/strong&gt;：虚拟页到物理页的映射表。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TLB&lt;/strong&gt;：页表的缓存，加速地址翻译。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;避坑技巧&lt;/strong&gt;：频繁访问大量不连续内存会导致大量 TLB Miss，性能骤降。&lt;/p&gt;
&lt;h3 id=&#34;83-malloc--free-的底层&#34;&gt;8.3 malloc / free 的底层&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;p &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;malloc&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;1024&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;free&lt;/span&gt;(p);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;code&gt;malloc&lt;/code&gt; 不一定每次都向操作系统申请内存，它通常先向 &lt;strong&gt;ptmalloc / jemalloc&lt;/strong&gt; 等内存分配器请求，分配器管理一个堆内存池。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;常见内存问题&lt;/strong&gt;：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;问题&lt;/th&gt;
					&lt;th&gt;表现&lt;/th&gt;
					&lt;th&gt;解决&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;内存泄漏&lt;/td&gt;
					&lt;td&gt;程序运行越久内存越大&lt;/td&gt;
					&lt;td&gt;配对使用 malloc/free，用 Valgrind/ASan 检测&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;重复释放&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;double free&lt;/code&gt; 崩溃&lt;/td&gt;
					&lt;td&gt;free 后将指针置 NULL&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;越界写&lt;/td&gt;
					&lt;td&gt;破坏堆结构，后续 malloc/free 崩溃&lt;/td&gt;
					&lt;td&gt;边界检查，用 ASan&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;使用已释放内存&lt;/td&gt;
					&lt;td&gt;use-after-free&lt;/td&gt;
					&lt;td&gt;释放后置 NULL，或换智能指针&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&#34;九系统级-io&#34;&gt;九、系统级 I/O&lt;/h2&gt;
&lt;h3 id=&#34;91-文件描述符&#34;&gt;9.1 文件描述符&lt;/h3&gt;
&lt;p&gt;Unix 中一切都是文件：普通文件、管道、socket、设备，都用一个整数 &lt;strong&gt;文件描述符（fd）&lt;/strong&gt; 表示。&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; fd &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;open&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;file.txt&amp;#34;&lt;/span&gt;, O_RDONLY);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;read&lt;/span&gt;(fd, buf, &lt;span style=&#34;color:#66d9ef&#34;&gt;sizeof&lt;/span&gt;(buf));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;close&lt;/span&gt;(fd);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;标准文件描述符&lt;/strong&gt;：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;fd&lt;/th&gt;
					&lt;th&gt;含义&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;0&lt;/td&gt;
					&lt;td&gt;标准输入 stdin&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;1&lt;/td&gt;
					&lt;td&gt;标准输出 stdout&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;2&lt;/td&gt;
					&lt;td&gt;标准错误 stderr&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;92-rio-包健壮的-io&#34;&gt;9.2 RIO 包：健壮的 I/O&lt;/h3&gt;
&lt;p&gt;CSAPP 推荐用 RIO（Robust I/O）处理短计数和网络读写：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 读取一行或指定字节数
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;rio_readn&lt;/span&gt;(fd, buf, n);   &lt;span style=&#34;color:#75715e&#34;&gt;// 读到 n 字节或 EOF
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;rio_readlineb&lt;/span&gt;(fd, buf, maxlen);  &lt;span style=&#34;color:#75715e&#34;&gt;// 读一行
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;rio_writen&lt;/span&gt;(fd, buf, n);  &lt;span style=&#34;color:#75715e&#34;&gt;// 写 n 字节
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;避坑技巧&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;read()&lt;/code&gt;/&lt;code&gt;write()&lt;/code&gt; 不保证一次读写完请求的字节数，要处理&lt;strong&gt;短计数&lt;/strong&gt;（short count）。&lt;/li&gt;
&lt;li&gt;网络编程中尤其要注意：TCP 是字节流，没有消息边界。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&#34;十unix-网络编程核心&#34;&gt;十、Unix 网络编程核心&lt;/h2&gt;
&lt;h3 id=&#34;101-客户端--服务器模型&#34;&gt;10.1 客户端 / 服务器模型&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    A[客户端] --&amp;gt;|请求| B[服务器]
    B --&amp;gt;|响应| A&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;102-socket-编程流程&#34;&gt;10.2 Socket 编程流程&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;sequenceDiagram
    participant S as 服务器
    participant C as 客户端
    participant K as 内核
    
    S-&amp;gt;&amp;gt;K: socket()
    S-&amp;gt;&amp;gt;K: bind()
    S-&amp;gt;&amp;gt;K: listen()
    C-&amp;gt;&amp;gt;K: socket()
    C-&amp;gt;&amp;gt;K: connect()
    K--&amp;gt;&amp;gt;S: 连接请求
    S-&amp;gt;&amp;gt;K: accept()
    S-&amp;gt;&amp;gt;K: read/write
    C-&amp;gt;&amp;gt;K: read/write
    S-&amp;gt;&amp;gt;K: close()
    C-&amp;gt;&amp;gt;K: close()&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;103-tcp-三次握手与四次挥手&#34;&gt;10.3 TCP 三次握手与四次挥手&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;sequenceDiagram
    participant C as 客户端
    participant S as 服务器
    C-&amp;gt;&amp;gt;S: SYN
    S-&amp;gt;&amp;gt;C: SYN + ACK
    C-&amp;gt;&amp;gt;S: ACK
    Note over C,S: 连接建立，可以传数据
    C-&amp;gt;&amp;gt;S: FIN
    S-&amp;gt;&amp;gt;C: ACK
    S-&amp;gt;&amp;gt;C: FIN
    C-&amp;gt;&amp;gt;S: ACK
    Note over C,S: 连接关闭&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;为什么是三次握手？&lt;/strong&gt; 防止历史重复连接初始化造成混乱，同时确认双方收发能力正常。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么是四次挥手？&lt;/strong&gt; TCP 是全双工的，双方都要各自关闭发送通道，所以多了一次。&lt;/p&gt;
&lt;h3 id=&#34;104-echo-服务器示例&#34;&gt;10.4 Echo 服务器示例&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;unistd.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#include&lt;/span&gt; &lt;span style=&#34;color:#75715e&#34;&gt;&amp;lt;arpa/inet.h&amp;gt;&lt;/span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define MAXLINE 8192
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;#define PORT 12345
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;echo&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; connfd) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;size_t&lt;/span&gt; n;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;char&lt;/span&gt; buf[MAXLINE];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; ((n &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;read&lt;/span&gt;(connfd, buf, MAXLINE)) &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;write&lt;/span&gt;(connfd, buf, n);  &lt;span style=&#34;color:#75715e&#34;&gt;// 把收到的数据回写
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; listenfd &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;socket&lt;/span&gt;(AF_INET, SOCK_STREAM, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; sockaddr_in serv_addr;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;memset&lt;/span&gt;(&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;serv_addr, &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;sizeof&lt;/span&gt;(serv_addr));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    serv_addr.sin_family &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; AF_INET;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    serv_addr.sin_addr.s_addr &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;htonl&lt;/span&gt;(INADDR_ANY);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    serv_addr.sin_port &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;htons&lt;/span&gt;(PORT);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;bind&lt;/span&gt;(listenfd, (&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; sockaddr &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;)&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;serv_addr, &lt;span style=&#34;color:#66d9ef&#34;&gt;sizeof&lt;/span&gt;(serv_addr));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;listen&lt;/span&gt;(listenfd, &lt;span style=&#34;color:#ae81ff&#34;&gt;1024&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;printf&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Server listening on port %d&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;&lt;/span&gt;, PORT);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;while&lt;/span&gt; (&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; sockaddr_in cli_addr;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;socklen_t&lt;/span&gt; len &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;sizeof&lt;/span&gt;(cli_addr);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; connfd &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;accept&lt;/span&gt;(listenfd, (&lt;span style=&#34;color:#66d9ef&#34;&gt;struct&lt;/span&gt; sockaddr &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt;)&lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;cli_addr, &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt;len);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;echo&lt;/span&gt;(connfd);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;close&lt;/span&gt;(connfd);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：上面的代码是&lt;strong&gt;迭代服务器&lt;/strong&gt;，一次只能处理一个客户端。实际生产环境要用多进程、多线程或 I/O 多路复用。&lt;/p&gt;
&lt;h3 id=&#34;105-网络编程避坑清单&#34;&gt;10.5 网络编程避坑清单&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;坑&lt;/th&gt;
					&lt;th&gt;说明&lt;/th&gt;
					&lt;th&gt;避免方法&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;忘记字节序转换&lt;/td&gt;
					&lt;td&gt;大端小端混用&lt;/td&gt;
					&lt;td&gt;网络传输前用 &lt;code&gt;htonl&lt;/code&gt;/&lt;code&gt;htons&lt;/code&gt;，接收后用 &lt;code&gt;ntohl&lt;/code&gt;/&lt;code&gt;ntohs&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;忽略 &lt;code&gt;read&lt;/code&gt;/&lt;code&gt;write&lt;/code&gt; 返回值&lt;/td&gt;
					&lt;td&gt;可能只读写了一部分&lt;/td&gt;
					&lt;td&gt;循环处理，直到处理完所有字节&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;没有处理 &lt;code&gt;SIGPIPE&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;向已关闭的 socket 写会触发信号&lt;/td&gt;
					&lt;td&gt;忽略 &lt;code&gt;SIGPIPE&lt;/code&gt;，或检查返回值&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;端口复用问题&lt;/td&gt;
					&lt;td&gt;服务器重启时 bind 失败&lt;/td&gt;
					&lt;td&gt;设置 &lt;code&gt;SO_REUSEADDR&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;长连接粘包/拆包&lt;/td&gt;
					&lt;td&gt;TCP 无消息边界&lt;/td&gt;
					&lt;td&gt;设计应用层协议：固定长度、分隔符、长度前缀&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&#34;十一并发编程&#34;&gt;十一、并发编程&lt;/h2&gt;
&lt;h3 id=&#34;111-三种并发模型&#34;&gt;11.1 三种并发模型&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TB
    A[并发模型] --&amp;gt; B[多进程]
    A --&amp;gt; C[多线程]
    A --&amp;gt; D[I/O 多路复用]
    
    B --&amp;gt; B1[进程独立 / 安全]
    B --&amp;gt; B2[切换开销大 / 共享数据麻烦]
    
    C --&amp;gt; C1[共享地址空间 / 切换快]
    C --&amp;gt; C2[需要同步 / 容易出 bug]
    
    D --&amp;gt; D1[单线程处理多个 fd]
    D --&amp;gt; D2[事件驱动 / 编程复杂]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;112-线程同步三件套&#34;&gt;11.2 线程同步三件套&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    A[互斥锁 Mutex] --&amp;gt;|保护临界区| B[保证同一时间只有一个线程访问]
    C[条件变量 Condition Variable] --&amp;gt;|等待某个条件| D[配合 mutex 使用]
    E[信号量 Semaphore] --&amp;gt;|计数器| F[控制同时访问的线程数量]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;113-生产者---消费者模型&#34;&gt;11.3 生产者 - 消费者模型&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    A[生产者线程] --&amp;gt;|写入缓冲区| B[共享缓冲区]
    B --&amp;gt;|读取| C[消费者线程]
    D[Mutex] --&amp;gt;|保护| B
    E[条件变量&amp;lt;br/&amp;gt;not_full] --&amp;gt;|通知| A
    F[条件变量&amp;lt;br/&amp;gt;not_empty] --&amp;gt;|通知| C&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;114-死锁并发程序的噩梦&#34;&gt;11.4 死锁：并发程序的噩梦&lt;/h3&gt;
&lt;p&gt;死锁产生的四个必要条件：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TB
    A[死锁四条件] --&amp;gt; B[互斥]
    A --&amp;gt; C[占有且等待]
    A --&amp;gt; D[不可抢占]
    A --&amp;gt; E[循环等待]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;避免死锁的方法&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;按固定顺序获取锁。&lt;/li&gt;
&lt;li&gt;使用超时机制（try_lock）。&lt;/li&gt;
&lt;li&gt;尽量减少锁的粒度。&lt;/li&gt;
&lt;li&gt;避免在持有锁时调用可能阻塞的函数。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;115-并发编程避坑清单&#34;&gt;11.5 并发编程避坑清单&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;坑&lt;/th&gt;
					&lt;th&gt;说明&lt;/th&gt;
					&lt;th&gt;避免方法&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;数据竞争&lt;/td&gt;
					&lt;td&gt;多个线程同时读写共享数据&lt;/td&gt;
					&lt;td&gt;加锁、原子操作、线程局部存储&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;死锁&lt;/td&gt;
					&lt;td&gt;互相等待对方释放锁&lt;/td&gt;
					&lt;td&gt;统一加锁顺序、超时、死锁检测&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;竞态条件&lt;/td&gt;
					&lt;td&gt;执行顺序影响结果&lt;/td&gt;
					&lt;td&gt;用同步原语保护关键区域&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;伪共享&lt;/td&gt;
					&lt;td&gt;两个变量在同一缓存行被不同 CPU 修改&lt;/td&gt;
					&lt;td&gt;按缓存行对齐变量&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;线程泄露&lt;/td&gt;
					&lt;td&gt;创建线程不 join 或 detach&lt;/td&gt;
					&lt;td&gt;管理好线程生命周期&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&#34;十二典型问题与调试技巧&#34;&gt;十二、典型问题与调试技巧&lt;/h2&gt;
&lt;h3 id=&#34;121-段错误segmentation-fault&#34;&gt;12.1 段错误（Segmentation Fault）&lt;/h3&gt;
&lt;p&gt;常见原因：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;访问 NULL 指针&lt;/li&gt;
&lt;li&gt;数组越界&lt;/li&gt;
&lt;li&gt;使用已释放的内存&lt;/li&gt;
&lt;li&gt;栈溢出&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;调试流程&lt;/strong&gt;：&lt;/p&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart TD
    A[程序崩溃 / 段错误] --&amp;gt; B[用 gdb 启动或 attach]
    B --&amp;gt; C[查看 backtrace]
    C --&amp;gt; D{能否定位?}
    D --&amp;gt;|能| E[修复代码]
    D --&amp;gt;|不能| F[用 ASan / Valgrind 检测]
    F --&amp;gt; G[定位内存错误]
    G --&amp;gt; E&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;h3 id=&#34;122-内存泄漏检测&#34;&gt;12.2 内存泄漏检测&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 用 AddressSanitizer 编译&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gcc -fsanitize&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;address -g program.c -o program
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./program
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 或用 Valgrind&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;valgrind --leak-check&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;full ./program&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h3 id=&#34;123-死锁排查&#34;&gt;12.3 死锁排查&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# Linux 下查看线程堆栈&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pstack &amp;lt;pid&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 或&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;gdb -p &amp;lt;pid&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;info threads
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;thread apply all bt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h3 id=&#34;124-性能分析&#34;&gt;12.4 性能分析&lt;/h3&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# CPU 热点分析&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;perf top -p &amp;lt;pid&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;perf record -g ./program
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;perf report
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;# 火焰图&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;perf script | stackcollapse-perf.pl | flamegraph.pl &amp;gt; flame.svg&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;h3 id=&#34;125-常见面试题速查&#34;&gt;12.5 常见面试题速查&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;问题&lt;/th&gt;
					&lt;th&gt;核心要点&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;进程和线程的区别&lt;/td&gt;
					&lt;td&gt;进程是资源分配单位，线程是调度单位&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;虚拟内存的作用&lt;/td&gt;
					&lt;td&gt;隔离、简化、共享&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;TCP 为什么三次握手&lt;/td&gt;
					&lt;td&gt;防止历史连接、确认双工能力&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;死锁四条件&lt;/td&gt;
					&lt;td&gt;互斥、占有且等待、不可抢占、循环等待&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;局部性原理&lt;/td&gt;
					&lt;td&gt;时间局部性、空间局部性&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;静态链接 vs 动态链接&lt;/td&gt;
					&lt;td&gt;独立运行 vs 共享节省&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&#34;十三学习路线建议&#34;&gt;十三、学习路线建议&lt;/h2&gt;
&lt;div class=&#34;code-block&#34;&gt;
    &lt;button class=&#34;code-copy&#34; type=&#34;button&#34; hidden aria-label=&#34;Copy code to clipboard&#34;&gt;
      &lt;span class=&#34;code-copy-label&#34; aria-hidden=&#34;true&#34;&gt;Copy&lt;/span&gt;
    &lt;/button&gt;
    &lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-mermaid&#34; data-lang=&#34;mermaid&#34;&gt;flowchart LR
    A[C 语言基础] --&amp;gt; B[CSAPP 第 1-3 章&amp;lt;br/&amp;gt;信息表示与汇编]
    B --&amp;gt; C[第 4-6 章&amp;lt;br/&amp;gt;处理器 / 缓存 / 链接]
    C --&amp;gt; D[第 7-9 章&amp;lt;br/&amp;gt;进程 / 信号 / 虚拟内存]
    D --&amp;gt; E[第 10-12 章&amp;lt;br/&amp;gt;I/O / 网络 / 并发]
    E --&amp;gt; F[写一个小 Web 服务器]
    F --&amp;gt; G[看 Linux 内核 / 源码]&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;&lt;p&gt;&lt;strong&gt;配套练习&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;用 C 写一个简单的 shell（支持 fork/exec/pipe）。&lt;/li&gt;
&lt;li&gt;实现一个基于线程池的 HTTP 服务器。&lt;/li&gt;
&lt;li&gt;用 epoll 实现高并发 echo 服务器。&lt;/li&gt;
&lt;li&gt;用 Valgrind 和 ASan 检查自己的项目。&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id=&#34;十四总结&#34;&gt;十四、总结&lt;/h2&gt;
&lt;p&gt;CSAPP 不是一本&amp;quot;看完就忘&amp;quot;的书，它提供的是理解计算机系统的&lt;strong&gt;思维框架&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;数据最终都是位，理解编码才能避免溢出和精度问题。&lt;/li&gt;
&lt;li&gt;程序跑在 CPU 上，理解汇编和栈才能避免安全漏洞。&lt;/li&gt;
&lt;li&gt;内存是分层的，理解缓存和局部性才能写出高性能代码。&lt;/li&gt;
&lt;li&gt;操作系统通过进程、虚拟内存、文件系统管理资源。&lt;/li&gt;
&lt;li&gt;网络编程要理解 TCP 字节流和 socket 生命周期。&lt;/li&gt;
&lt;li&gt;并发编程的核心是同步与避免竞态条件。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;最重要的学习方法是：&lt;strong&gt;边看书边写代码&lt;/strong&gt;。把书中的例子跑起来，改一改，看看会发生什么。只有亲手踩过坑，才能真正理解这些知识。&lt;/p&gt;
&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;这篇文章是笔者学习 CSAPP 和实践中的总结，难免有疏漏。如果有疑问或建议，欢迎留言交流。&lt;/p&gt;
&lt;/blockquote&gt;
</description>
    </item>
    
  </channel>
</rss>
