<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

 <title></title>
 <link href="https://icing.fun/atom.xml" rel="self"/>
 <link href="https://icing.fun/"/>
 <updated>2026-03-10T03:37:34+00:00</updated>
 <id>https://icing.fun</id>
 <author>
   <name>IcingTomato</name>
   <email>blog@icing.fun</email>
 </author>

 
 <entry>
   <title>【Linux】Fedora 上手配置</title>
   <link href="https://icing.fun/posts/fedora_setup_tutorial.html"/>
   <updated>2026-03-02T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/fedora_setup_tutorial</id>
   <content type="html">&lt;p&gt;公司给了个 ThinkBook 14, 原装是 Windows 11, 可能是用的人多了，系统糊成狗屎一样，难用的要死，用户名还是之前人的名字，感觉很诡异。正好因为要用 Ubuntu 的系统盘，索性装个 Fedora 吧。&lt;/p&gt;

&lt;p&gt;下载不用多说什么了，直接上官网，下载最新的 Fedora Workstation 版本的 ISO 镜像就行了。下载完成后，使用 Rufus 或者 balenaEtcher 之类的软件将 ISO 镜像写入到一个 USB 闪存盘中，制作成可启动的安装盘。（只可惜我用的 Ventoy）&lt;/p&gt;

&lt;p&gt;我下载的 Fedora Cinnamon Desktop Spins，这个用的多，以前就用 Arch Linux 的时候也用过，感觉还不错。安装过程和其他 Linux 发行版差不多，选择语言、键盘布局、磁盘分区等，按照提示一步步操作就行了。&lt;/p&gt;

&lt;p&gt;注意一点是，用户目录保持英文的问题。我是安装的时候选英文，后面再进系统换回中文的，这样用户目录就不会变成中文了。因为如果用户目录是中文的，很多软件可能会因为路径问题而出错。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2026/03/02/1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;安装完成后看看系统配置：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2026/03/02/2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;现在就可以马克擦车了：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dnf makecache
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;为什么不运行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo dnf update&lt;/code&gt; 呢？因为 Fedora 的更新可能会比较大，尤其是第一次更新，可能会下载很多包，耗时较长。运行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo dnf makecache&lt;/code&gt; 可以先更新软件包缓存，这样在后续安装软件时会更快。（其实就是以前用 Arch 的时候滚动更新滚怕了，前一天在公司把电脑合上，第二天上班的时候进不去系统报 Kernel Panic……）&lt;/p&gt;

&lt;p&gt;下面就是安装输入法了，这个我走了弯路。原本想用 ibus-rime 的，结果安装之后发现 ibus 在 Electron 应用里有问题，输入法无法正常使用。后来换成了 fcitx5-rime，安装之后就没有问题了。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dnf &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;fcitx5-rime
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后配合使用东风破（Plum）安装雾凇拼音：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 请先安装 git 和 bash，并加入环境变量&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# 请确保和 github.com 的连接稳定&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~
git clone https://github.com/rime/plum.git plum
&lt;span class=&quot;c&quot;&gt;# 卸载 plum 只需要删除 ~/plum 文件夹即可&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;接着：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/plum
&lt;span class=&quot;nv&quot;&gt;rime_frontend&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;fcitx5-rime bash rime-install iDvel/rime-ice:others/recipes/full
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;再次重新部署 Rime，使用 Ctrl + ~ 键，来选择雾凇拼音。&lt;/p&gt;

&lt;p&gt;插入一个小插曲：我想直接用 fcitx5 的，然后把 ibus 卸载。结果卸载 ibus 的时候用了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo dnf remove ibus*&lt;/code&gt;，我是万万没想到现在都在往 Wayland 方向发展，我还以为还在用 X11,卸载的时候没看直接 y 了，整个桌面都没了。只能说我被 Arch 鞭打太多次了已经习惯了， 直接 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo dnf install @cinnamon-desktop-environment&lt;/code&gt; 重新安装 Cinnamon 桌面环境，重启之后 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo systemctl enable lightdm.service &amp;amp;&amp;amp; sudo systemctl start lightdm.service&lt;/code&gt; 就好了。&lt;/p&gt;

&lt;p&gt;然后就是安装 WPS，切忌切忌安装外版的 WPS，国内的广告满天飞（你是把雷军他妈的骨灰盒打包放进去了吗？），直接上国外的版本，安装包里没有广告，安装完成后就没有了。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;wget https://wdl1.pcfg.cache.wpscdn.com/wpsdl/wpsoffice/download/linux/11723/wps-office-11.1.0.11723.XA-1.x86_64.rpm

&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;rpm &lt;span class=&quot;nt&quot;&gt;-ivh&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--nodigest&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--nosignature&lt;/span&gt; ./wps-office-11.1.0.11723.XA-1.x86_64.rpm
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;别问为什么 RPM 安装要带那么多参数，问就是傻X WPS 程序员写得烂，安装包里没有签名和摘要，所以必须加上 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--nodigest --nosignature&lt;/code&gt; 参数才能安装成功。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2026/03/02/3.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;还有就是老生常谈的 WPS 缺字体的问题了。参考&lt;a href=&quot;https://github.com/dv-anomaly/ttf-wps-fonts&quot;&gt;dv-anomaly/ttf-wps-fonts&lt;/a&gt;这个项目或者&lt;a href=&quot;https://github.com/xChen16/wps-fonts&quot;&gt;xChen16/wps-fonts&lt;/a&gt;或者&lt;a href=&quot;https://gitee.com/owlman/wps_fonts&quot;&gt;owlman/wps_fonts&lt;/a&gt;就行。&lt;/p&gt;

&lt;p&gt;但是主界面还是有方框，解决方案如下：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dnf &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;rpm &lt;span class=&quot;nt&quot;&gt;-E&lt;/span&gt; %fedora&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;.noarch.rpm https://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;rpm &lt;span class=&quot;nt&quot;&gt;-E&lt;/span&gt; %fedora&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;.noarch.rpm
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dnf makecache
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dnf &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;google-noto-sans-cjk-vf-fonts
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dnf &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;wqy-microhei-fonts
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dnf &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;wqy-zenhei-fonts
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dnf &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;langpacks-zh_CN
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dnf &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;google-noto-sans-cjk-fonts google-noto-serif-cjk-fonts wqy-zenhei-fonts wqy-microhei-fonts
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dnf remove libreoffice-core
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;不记得是哪个了，反正一套连招下来显示正常了。&lt;/p&gt;

&lt;p&gt;然后就是喜闻乐见的 Typora 安装了。Typora 官方没给 RPM 包，只有 DEB 包，所以我找了个 GitHub 项目来搞定这个安装：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dnf &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;pandoc
git clone https://github.com/RPM-Outpost/typora.git
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;typora/
&lt;span class=&quot;nb&quot;&gt;chmod&lt;/span&gt; +x create-package.sh
./create-package.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;好像就这么些了。&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>【博客搭建】Jekyll 语法高亮配置</title>
   <link href="https://icing.fun/posts/jekyll_syntax_highlight.html"/>
   <updated>2026-01-23T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/jekyll_syntax_highlight</id>
   <content type="html">&lt;p&gt;一个月前看 X 上有人分享了一个很简约的网站，&lt;a href=&quot;https://usgraphics.com/&quot;&gt;U.S. Graphics Company&lt;/a&gt;，想着自己需要一个简约的主题，于是顺手扒了他们网页研究一下做个 Jekyll 主题出来。前前后后一个月的时间，把主题做出来了。但总感觉差强人意：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;代码高亮很难受！&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;代码高亮要做层叠样式，很烦。还好 Jekyll 中默认的语法高亮是 Rouge。&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;markdown&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;kramdown&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;kramdown&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;GFM&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;hard_wrap&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;na&quot;&gt;syntax_highlighter&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;rouge&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;搂了一下文档，发现这个可以直接生成层叠样式文件！&lt;/p&gt;

&lt;p&gt;首先得确保安装了 Rouge：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gem &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;rouge
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;安装完成后，可以看看自带的样式有哪些：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rougify &lt;span class=&quot;nb&quot;&gt;help &lt;/span&gt;style
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;会告诉你有如下样式：&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;PS&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Z:\tomato\Codes\Web\Blog&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rougify&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;help&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;usage:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rougify&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;theme&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Print&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;CSS&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;styles&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;the&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;given&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;theme.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Extra&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;are&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;passed&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;the&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;theme.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;To&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;select&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;light/dark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;the&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;theme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;.light&apos;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;or&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;.dark&apos;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;the&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;theme-name&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;respectively.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Theme&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;defaults&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;thankful_eyes.&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;options:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--scope&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;       &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;highlight&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;scope&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;by&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--tex&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;         &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;as&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;TeX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--tex-prefix&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;default:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;RG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prefix&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;TeX&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;implies&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--tex&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;specified&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;available&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;themes:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;base16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;base16.dark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;base16.light&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;base16.monokai&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;base16.monokai.dark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;base16.monokai.light&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;base16.solarized&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;base16.solarized.dark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;base16.solarized.light&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;colorful&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;github&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;github.dark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;github.light&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;gruvbox&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;gruvbox.dark&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;gruvbox.light&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;igorpro&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;magritte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;molokai&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;monokai&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;monokai.sublime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pastie&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;thankful_eyes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tulip&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;那么有聪明的小伙伴要问了，番茄哥，它那么多样式，到底哪个适合呢？&lt;/p&gt;

&lt;p&gt;我推荐个在线预览网站：&lt;a href=&quot;https://spsarolkar.github.io/rouge-theme-preview/&quot;&gt;Rouge Theme Preview Page&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;看上哪个样式，就直接生成对应的层叠样式文件：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;rougify style base16.solarized &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; assets/css/syntax-base16-solarized.css
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;比如我就生成了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;base16.solarized&lt;/code&gt; 这个样式的层叠样式文件。&lt;/p&gt;

&lt;p&gt;然后就该把生成的层叠样式文件引入到网页中了，在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_includes/head.html&lt;/code&gt; 里加一行：&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;link&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;stylesheet&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/assets/css/syntax-base16-solarized.css&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;当然，你要是不想生成，可以直接去那个在线预览网站对应的 &lt;a href=&quot;https://github.com/spsarolkar/rouge-theme-preview/tree/gh-pages/css&quot;&gt;GitHub 仓库&lt;/a&gt;里下载对应的层叠样式文件。&lt;/p&gt;

&lt;p&gt;看看效果吧！&lt;/p&gt;

&lt;h5 id=&quot;java&quot;&gt;Java&lt;/h5&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;total&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;	&lt;span class=&quot;n&quot;&gt;total&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;total&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;scala&quot;&gt;Scala&lt;/h5&gt;

&lt;div class=&quot;language-scala highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;findNums&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Iterable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;, &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// a for comprehension using two generators&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;until&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
         &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&amp;lt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;until&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
         &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;isPrime&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;c&quot;&gt;C++&lt;/h5&gt;
&lt;div class=&quot;language-c++ highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;    
    &lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Size of char: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; byte&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Size of int: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; bytes&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Size of float: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; bytes&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Size of double: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;double&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; bytes&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;endl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h5 id=&quot;python&quot;&gt;Python&lt;/h5&gt;
&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# line comment
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LinkedList&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;next&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>【Linux】Inline assembly for x86 in Linux</title>
   <link href="https://icing.fun/posts/linux_inline_assembly.html"/>
   <updated>2026-01-10T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/linux_inline_assembly</id>
   <content type="html">&lt;p&gt;If you’re a Linux kernel developer, you probably find yourself coding highly architecture-dependent functions or optimizing a code path pretty often. And you probably do this by inserting assembly language instructions into the middle of C statements (a method otherwise known as inline assembly). Let’s take a look at the specific usage of inline assembly in Linux. (We’ll limit our discussion to the IA32 assembly.)&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#1&quot;&gt;GNU assembler syntax in brief&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#2&quot;&gt;Inline assembly&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#3&quot;&gt;Examples of common inline assembly usage&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#4&quot;&gt;Use of specific register constraints&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#5&quot;&gt;Using matching constraints&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#6&quot;&gt;Use of memory operand constraint&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#7&quot;&gt;Using clobbered registers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#8&quot;&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#9&quot;&gt;Resources&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;gnu-assembler-syntax-in-brief&quot;&gt;&lt;span id=&quot;1&quot;&gt;GNU assembler syntax in brief&lt;/span&gt;&lt;/h1&gt;

&lt;p&gt;Let’s first look at the basic assembler syntax used in Linux. GCC, the GNU C Compiler for Linux, uses AT&amp;amp;T assembly syntax. Some of the basic rules of this syntax are listed below. (The list is by no means complete; I’ve included only those rules pertinent to inline assembly.)&lt;/p&gt;

&lt;h2 id=&quot;register-naming&quot;&gt;Register naming&lt;/h2&gt;

&lt;p&gt;Register names are prefixed by %. That is, if eax has to be used, it should be used as %eax.&lt;/p&gt;

&lt;h2 id=&quot;source-and-destination-ordering&quot;&gt;Source and destination ordering&lt;/h2&gt;

&lt;p&gt;In any instruction, source comes first and destination follows. This differs from Intel syntax, where source comes after destination.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    mov %eax, %ebx, transfers the contents of eax to ebx.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;size-of-operand&quot;&gt;Size of operand&lt;/h2&gt;

&lt;p&gt;The instructions are suffixed by b, w, or l, depending on whether the operand is a byte, word, or long. This is not mandatory; GCC tries provide the appropriate suffix by reading the operands. But specifying the suffixes manually improves the code readability and eliminates the possibility of the compilers guessing incorrectly.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    movb %al, %bl -- Byte move
	movw %ax, %bx -- Word move
	movl %eax, %ebx -- Longword move
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;immediate-operand&quot;&gt;Immediate operand&lt;/h2&gt;

&lt;p&gt;An immediate operand is specified by using $.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    movl $0xffff, %eax -- will move the value of 0xffff into eax register.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;indirect-memory-reference&quot;&gt;Indirect memory reference&lt;/h2&gt;

&lt;p&gt;Any indirect references to memory are done by using ( ).&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; movb (%esi), %al -- will transfer the byte in the memory 
                     pointed by esi into al  register
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;inline-assembly&quot;&gt;&lt;span id=&quot;2&quot;&gt;Inline assembly&lt;/span&gt;&lt;/h1&gt;

&lt;p&gt;GCC provides the special construct “asm” for inline assembly, which has the following format:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;	&lt;span class=&quot;n&quot;&gt;asm&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assembler&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;template&lt;/span&gt;
	    &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;operands&lt;/span&gt;			 	&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;optional&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	    &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operands&lt;/span&gt;			 	&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;optional&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	    &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clobbered&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;registers&lt;/span&gt; 	  	&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;optional&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	    &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;	
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In this example, the assembler template consists of assembly instructions. The input operands are the C expressions that serve as input operands to the instructions. The output operands are the C expressions on which the output of the assembly instructions will be performed.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;n&quot;&gt;asm&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;movl %%cr3, %0&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;=r&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cr3val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  a	    %eax
  b 	%ebx
  c 	%ecx
  d 	%edx
  S	    %esi
  D	    %edi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;memory-operand-constraintm&quot;&gt;Memory operand constraint(m)&lt;/h2&gt;

&lt;p&gt;When the operands are in the memory, any operations performed on them will occur directly in the memory location, as opposed to register constraints, which first store the value in a register to be modified and then write it back to the memory location. But register constraints are usually used only when they are absolutely necessary for an instruction or they significantly speed up the process. Memory constraints can be used most efficiently in cases where a C variable needs to be updated inside “asm” and you really don’t want to use a register to hold its value. For example, the value of idtr is stored in the memory location loc:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;     &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;sidt %0&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;m&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;matchingdigit-constraints&quot;&gt;Matching(Digit) constraints&lt;/h2&gt;

&lt;p&gt;In some cases, a single variable may serve as both the input and the output operand. Such cases may be specified in “asm” by using matching constraints.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;n&quot;&gt;asm&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;incl %0&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;=a&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In our example for matching constraints, the register %eax is used as both the input and the output variable. var input is read to %eax and updated %eax is stored in var again after increment. “0” here specifies the same constraint as the 0th output variable. That is, it specifies that the output instance of var should be stored in %eax only. This constraint can be used:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;In cases where input is read from a variable or the variable is modified and modification is written back to the same variable&lt;/li&gt;
  &lt;li&gt;In cases where separate instances of input and output operands are not necessary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The most important effect of using matching restraints is that they lead to the efficient use of available registers.&lt;/p&gt;

&lt;h1 id=&quot;examples-of-common-inline-assembly-usage&quot;&gt;&lt;span id=&quot;3&quot;&gt;Examples of common inline assembly usage&lt;/span&gt;&lt;/h1&gt;

&lt;p&gt;The following examples illustrate usage through different operand constraints. There are too many constraints to give examples for each one, but these are the most frequently used constraint types.&lt;/p&gt;

&lt;h2 id=&quot;asm-and-the-register-constraint-r&quot;&gt;“asm” and the register constraint “r”&lt;/h2&gt;

&lt;p&gt;Let’s first take a look at “asm” with the register constraint ‘r’. Our example shows how GCC allocates registers, and how it updates the value of output variables.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	
	&lt;span class=&quot;n&quot;&gt;asm&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;movl %1, %%eax;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;	     &quot;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;movl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;		:&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;(y)	/* y is output operand */&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;		:&quot;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;(x)		/* x is input operand */&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;		:&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;);	/* %eax is clobbered register */&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In this example, the value of x is copied to y inside “asm”. x and y are passed to “asm” by being stored in registers. The assembly code generated for this example looks like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    main:
        pushl %ebp
        movl %esp,%ebp
        subl $8,%esp
        movl $10,-4(%ebp)	 
        movl -4(%ebp),%edx	/* x=10 is stored in %edx */
#APP	/* asm starts here */	
        movl %edx, %eax		/* x is moved to %eax */
        movl %eax, %edx		/* y is allocated in edx and updated */

#NO_APP	/* asm ends here */
        movl %edx,-8(%ebp)	/* value of y in stack is updated with 
				   the value in %edx */ 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;GCC is free here to allocate any register when the “r” constraint is used. In our example it chose %edx for storing x. After reading the value of x in %edx, it allocated the same register for y.&lt;/p&gt;

&lt;p&gt;Since y is specified in the output operand section, the updated value in %edx is stored in -8(%ebp), the location of y on stack. If y were specified in the input section, the value of y on stack would not be updated, even though it does get updated in the temporary register storage of y(%edx).&lt;/p&gt;

&lt;p&gt;And since %eax is specified in the clobbered list, GCC doesn’t use it anywhere else to store data.&lt;/p&gt;

&lt;p&gt;Both input x and output y were allocated in the same %edx register, assuming that inputs are consumed before outputs are produced. Note that if you have a lot of instructions, this may not be the case. To make sure that input and output are allocated in different registers, we can specify the &amp;amp; constraint modifier. Here is our example with the constraint modifier added.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	
	&lt;span class=&quot;n&quot;&gt;asm&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;movl %1, %%eax;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;	     &quot;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;movl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;		:&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;(y)	/* y is output operand, note the	&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;				   &amp;amp; constraint modifier. */&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;		:&quot;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;(x)		/* x is input operand */&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;		:&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;);	/* %eax is clobbered register */&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And here is the assembly code generated for this example, from which it is evident that x and y have been stored in different registers across “asm”.&lt;/p&gt;

&lt;h1 id=&quot;use-of-specific-register-constraints&quot;&gt;&lt;span id=&quot;4&quot;&gt;Use of specific register constraints&lt;/span&gt;&lt;/h1&gt;

&lt;p&gt;Now let’s take a look at how to specify individual registers as constraints for the operands. In the following example, the cpuid instruction takes the input in the %eax register and gives output in four registers: %eax, %ebx, %ecx, %edx. The input to cpuid (the variable “op”) is passed to “asm” in the eax register, as cpuid expects it to. The a, b, c, and d constraints are used in the output to collect the values in the four registers, respectively.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;n&quot;&gt;asm&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;cpuid&quot;&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;=a&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
                  &lt;span class=&quot;s&quot;&gt;&quot;=b&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_ebx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
                  &lt;span class=&quot;s&quot;&gt;&quot;=c&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_ecx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
                  &lt;span class=&quot;s&quot;&gt;&quot;=d&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_edx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;a&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;op&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And below you can see the generated assembly code for this (assuming the _eax, _ebx, etc…. variables are stored on stack):&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    movl -20(%ebp),%eax	/* store &apos;op&apos; in %eax -- input */
#APP
        cpuid
#NO_APP
        movl %eax,-4(%ebp)	/* store %eax in _eax -- output */
        movl %ebx,-8(%ebp)	/* store other registers in
        movl %ecx,-12(%ebp)	   respective output variables */  
        movl %edx,-16(%ebp)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The strcpy function can be implemented using the “S” and “D” constraints in the following manner:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;n&quot;&gt;asm&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;cld&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;	      rep&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;	      movsb&quot;&lt;/span&gt;
	      &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* no input */&lt;/span&gt;
	      &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;S&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;D&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dst&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;c&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The source pointer src is put into %esi by using the “S” constraint, and the destination pointer dst is put into %edi using the “D” constraint. The count value is put into %ecx as it is needed by rep prefix.&lt;/p&gt;

&lt;p&gt;And here you can see another constraint that uses the two registers %eax and %edx to combine two 32-bit values and generate a 64-bit value:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#define rdtscll(val) \
     __asm__ __volatile__ (&quot;rdtsc&quot; : &quot;=A&quot; (val))
&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;The&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;generated&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assembly&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;looks&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;like&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;has&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memory&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;space&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;

&lt;span class=&quot;cp&quot;&gt;#APP
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;rdtsc&lt;/span&gt;
&lt;span class=&quot;cp&quot;&gt;#NO_APP
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;movl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ebp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* As a result of A constraint 
        movl %edx,-4(%ebp)	   %eax and %edx serve as outputs */&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;Note&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;here&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;that&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;values&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;edx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:%&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eax&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;serve&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bit&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;using-matching-constraints&quot;&gt;&lt;span id=&quot;5&quot;&gt;Using matching constraints&lt;/span&gt;&lt;/h1&gt;

&lt;p&gt;Here you can see the code for the system call, with four parameters:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
{ \
long __res; \
__asm__ volatile (&quot;int $0x80&quot; \
        : &quot;=a&quot; (__res) \
        : &quot;0&quot; (__NR_##name),&quot;b&quot; ((long)(arg1)),&quot;c&quot; ((long)(arg2)), \
          &quot;d&quot; ((long)(arg3)),&quot;S&quot; ((long)(arg4))); \
__syscall_return(type,__res); \
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In the above example, four arguments to the system call are put into %ebx, %ecx, %edx, and %esi by using the constraints b, c, d, and S. Note that the “=a” constraint is used in the output so that the return value of the system call, which is in %eax, is put into the variable &lt;em&gt;_res. By using the matching constraint “0” as the first operand constraint in the input section, the syscall number __NR&lt;/em&gt;##name is put into %eax and serves as the input to the system call. Thus %eax serves here as both input and output register. No separate registers are used for this purpose. Note also that the input (syscall number) is consumed (used) before the output (the return value of syscall) is produced.&lt;/p&gt;

&lt;h1 id=&quot;use-of-memory-operand-constraint&quot;&gt;&lt;span id=&quot;6&quot;&gt;Use of memory operand constraint&lt;/span&gt;&lt;/h1&gt;

&lt;p&gt;Consider the following atomic decrement operation:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    &lt;span class=&quot;n&quot;&gt;__asm__&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__volatile__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                &lt;span class=&quot;s&quot;&gt;&quot;lock; decl %0&quot;&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;=m&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;counter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;m&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;counter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The generated assembly for this would look something like this:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;    #APP
	lock
	decl -24(%ebp) /* counter is modified on its memory location */
#NO_APP.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You might think of using the register constraint here for the counter. If you do, the value of the counter must first be copied on to a register, decremented, and then updated to its memory. But then you lose the whole purpose of locking and atomicity, which clearly shows the necessity of using the memory constraint.&lt;/p&gt;

&lt;h1 id=&quot;using-clobbered-registers&quot;&gt;&lt;span id=&quot;7&quot;&gt;Using clobbered registers&lt;/span&gt;&lt;/h1&gt;

&lt;p&gt;Consider an elementary implementation of memory copy.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;	&lt;span class=&quot;n&quot;&gt;asm&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;movl $count, %%ecx;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;	      up: lodsl;	&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;	      stosl;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;	      loop up;&quot;&lt;/span&gt;
		&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; 			&lt;span class=&quot;cm&quot;&gt;/* no output */&lt;/span&gt;
		&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;S&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;D&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dst&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* input */&lt;/span&gt;
		&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%ecx&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;%eax&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;	&lt;span class=&quot;cm&quot;&gt;/* clobbered list */&lt;/span&gt;	
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;While lodsl modifies %eax, the lodsl and stosl instructions use it implicitly. And the %ecx register explicitly loads the count. But GCC won’t know this unless we inform it, which is exactly what we do by including %eax and %ecx in the clobbered register set. Unless this is done, GCC assumes that %eax and %ecx are free, and it may decide to use them for storing other data. Note here that %esi and %edi are used by “asm”, and are not in the clobbered list. This is because it has been declared that “asm” will use them in the input operand list. The bottom line here is that if a register is used inside “asm” (implicitly or explicitly), and it is not present in either the input or output operand list, you must list it as a clobbered register.&lt;/p&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;&lt;span id=&quot;8&quot;&gt;Conclusion&lt;/span&gt;&lt;/h1&gt;

&lt;p&gt;On the whole, inline assembly is huge and provides a lot of features that we did not even touch on here. But with a basic grasp of the material in this article, you should be able to start coding inline assembly on your own.&lt;/p&gt;

&lt;h1 id=&quot;resources&quot;&gt;&lt;span id=&quot;9&quot;&gt;Resources&lt;/span&gt;&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;Refer to the &lt;a href=&quot;https://gcc.gnu.org/onlinedocs/gcc-2.95.3/gcc.html&quot;&gt;Using and Porting the GNU Compiler Collection (GCC)&lt;/a&gt; manual.&lt;/li&gt;
  &lt;li&gt;Refer to the &lt;a href=&quot;https://web.archive.org/web/20030219153403/http://www.gnu.org/manual/gas-2.9.1/html_mono/as.html&quot;&gt;GNU Assembler (GAS)&lt;/a&gt; manual.&lt;/li&gt;
  &lt;li&gt;Check out &lt;a href=&quot;https://www.delorie.com/djgpp/doc/brennan/brennan_att_inline_djgpp.html&quot;&gt;Brennan’s Guide to Inline Assembly&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>【Linux】Linux 汇编语言开发指南</title>
   <link href="https://icing.fun/posts/linux_assembly_dev.html"/>
   <updated>2026-01-01T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/linux_assembly_dev</id>
   <content type="html">&lt;p&gt;汇编语言的优点是速度快，可以直接对硬件进行操作，这对诸如图形处理等关键应用是非常重要的。Linux 是一个用 C 语言开发的操作系统，这使得很多程序员开始忘记在 Linux 中还可以直接使用汇编这一底层语言来优化程序的性能。本文为那些在Linux 平台上编写汇编代码的程序员提供指南，介绍 Linux 汇编语言的语法格式和开发工具，并辅以具体的例子讲述如何开发实用的Linux 汇编程序。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#1&quot;&gt;简介&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#2&quot;&gt;Linux 汇编语法格式&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#3&quot;&gt;Hello World!&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#4&quot;&gt;Linux 汇编工具&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#5&quot;&gt;系统调用&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#6&quot;&gt;命令行参数&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#7&quot;&gt;GCC 内联汇编&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#8&quot;&gt;小结&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#9&quot;&gt;参考资料&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;简介&quot;&gt;&lt;span id=&quot;1&quot;&gt;简介&lt;/span&gt;&lt;/h1&gt;

&lt;p&gt;作为最基本的编程语言之一，汇编语言虽然应用的范围不算很广，但重要性却勿庸置疑，因为它能够完成许多其它语言所无法完成的功能。就拿 Linux 内核来讲，虽然绝大部分代码是用 C 语言编写的，但仍然不可避免地在某些关键地方使用了汇编代码，其中主要是在 Linux 的启动部分。由于这部分代码与硬件的关系非常密切，即使是 C 语言也会有些力不从心，而汇编语言则能够很好扬长避短，最大限度地发挥硬件的性能。&lt;/p&gt;

&lt;p&gt;大多数情况下 Linux 程序员不需要使用汇编语言，因为即便是硬件驱动这样的底层程序在 Linux 操作系统中也可以用完全用 C 语言来实现，再加上 GCC 这一优秀的编译器目前已经能够对最终生成的代码进行很好的优化，的确有足够的理由让我们可以暂时将汇编语言抛在一边了。但实现情况是 Linux 程序员有时还是需要使用汇编，或者不得不使用汇编，理由很简单：精简、高效和 libc 无关性。假设要移植 Linux 到某一特定的嵌入式硬件环境下，首先必然面临如何减少系统大小、提高执行效率等问题，此时或许只有汇编语言能帮上忙了。&lt;/p&gt;

&lt;p&gt;汇编语言直接同计算机的底层软件甚至硬件进行交互，它具有如下一些优点：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;能够直接访问与硬件相关的存储器或 I/O 端口；&lt;/li&gt;
  &lt;li&gt;能够不受编译器的限制，对生成的二进制代码进行完全的控制；&lt;/li&gt;
  &lt;li&gt;能够对关键代码进行更准确的控制，避免因线程共同访问或者硬件设备共享引起的死锁；&lt;/li&gt;
  &lt;li&gt;能够根据特定的应用对代码做最佳的优化，提高运行速度；&lt;/li&gt;
  &lt;li&gt;能够最大限度地发挥硬件的功能。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;同时还应该认识到，汇编语言是一种层次非常低的语言，它仅仅高于直接手工编写二进制的机器指令码，因此不可避免地存在一些缺点：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;编写的代码非常难懂，不好维护；&lt;/li&gt;
  &lt;li&gt;很容易产生 bug，难于调试；&lt;/li&gt;
  &lt;li&gt;只能针对特定的体系结构和处理器进行优化；&lt;/li&gt;
  &lt;li&gt;开发效率很低，时间长且单调。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Linux 下用汇编语言编写的代码具有两种不同的形式。第一种是完全的汇编代码，指的是整个程序全部用汇编语言编写。尽管是完全的汇编代码，Linux 平台下的汇编工具也吸收了 C 语言的长处，使得程序员可以使用 #include、#ifdef 等预处理指令，并能够通过宏定义来简化代码。第二种是内嵌的汇编代码，指的是可以嵌入到C语言程序中的汇编代码片段。虽然 ANSI 的 C 语言标准中没有关于内嵌汇编代码的相应规定，但各种实际使用的 C 编译器都做了这方面的扩充，这其中当然就包括 Linux 平台下的 GCC。&lt;/p&gt;

&lt;h1 id=&quot;linux-汇编语法格式&quot;&gt;&lt;span id=&quot;2&quot;&gt;Linux 汇编语法格式&lt;/span&gt;&lt;/h1&gt;

&lt;p&gt;绝大多数 Linux 程序员以前只接触过DOS/Windows 下的汇编语言，这些汇编代码都是 Intel 风格的。但在 Unix 和 Linux 系统中，更多采用的还是 AT&amp;amp;T 格式，两者在语法格式上有着很大的不同：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;在 AT&amp;amp;T 汇编格式中，寄存器名要加上 ‘%’ 作为前缀；而在 Intel 汇编格式中，寄存器名不需要加前缀。例如：&lt;/p&gt;

    &lt;table&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th&gt;AT&amp;amp;T 格式&lt;/th&gt;
          &lt;th&gt;Intel 格式&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;pushl  %eax&lt;/td&gt;
          &lt;td&gt;push eax&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;在 AT&amp;amp;T 汇编格式中，用 ‘$’ 前缀表示一个立即操作数；而在 Intel 汇编格式中，立即数的表示不用带任何前缀。例如：&lt;/p&gt;

    &lt;table&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th&gt;AT&amp;amp;T 格式&lt;/th&gt;
          &lt;th&gt;Intel 格式&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;pushl $1&lt;/td&gt;
          &lt;td&gt;push 1&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;AT&amp;amp;T 和 Intel 格式中的源操作数和目标操作数的位置正好相反。在 Intel 汇编格式中，目标操作数在源操作数的左边；而在 AT&amp;amp;T 汇编格式中，目标操作数在源操作数的右边。例如：&lt;/p&gt;

    &lt;table&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th&gt;AT&amp;amp;T 格式&lt;/th&gt;
          &lt;th&gt;Intel 格式&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;addl $1, %eax&lt;/td&gt;
          &lt;td&gt;add eax, 1&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;在 AT&amp;amp;T 汇编格式中，操作数的字长由操作符的最后一个字母决定，后缀’b’、’w’、’l’分别表示操作数为字节（byte，8 比特）、字（word，16 比特）和长字（long，32比特）；而在 Intel 汇编格式中，操作数的字长是用 “byte ptr” 和 “word ptr” 等前缀来表示的。例如：&lt;/p&gt;

    &lt;table&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th&gt;AT&amp;amp;T 格式&lt;/th&gt;
          &lt;th&gt;Intel 格式&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;movb val, %al&lt;/td&gt;
          &lt;td&gt;mov al, byte ptr val&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;在 AT&amp;amp;T 汇编格式中，绝对转移和调用指令（jump/call）的操作数前要加上’*‘作为前缀，而在 Intel 格式中则不需要。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;远程转移指令和远程子调用指令的操作码，在 AT&amp;amp;T 汇编格式中为 “ljump” 和 “lcall”，而在 Intel 汇编格式中则为 “jmp far” 和 “call far”，即：&lt;/p&gt;

    &lt;table&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th&gt;AT&amp;amp;T 格式&lt;/th&gt;
          &lt;th&gt;Intel 格式&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;ljump $section, $offset&lt;/td&gt;
          &lt;td&gt;jmp far section:offset8&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;lcall $section, $offset&lt;/td&gt;
          &lt;td&gt;call far section:offset&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;

    &lt;p&gt;与之相应的远程返回指令则为：&lt;/p&gt;

    &lt;table&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th&gt;AT&amp;amp;T 格式&lt;/th&gt;
          &lt;th&gt;Intel 格式&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;lret $stack_adjust&lt;/td&gt;
          &lt;td&gt;ret far stack_adjust&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;在 AT&amp;amp;T 汇编格式中，内存操作数的寻址方式是&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;section:disp(base, index, scale)&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;而在 Intel 汇编格式中，内存操作数的寻址方式为：&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;section:[base + index*scale + disp]&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;由于 Linux 工作在保护模式下，用的是 32 位线性地址，所以在计算地址时不用考虑段基址和偏移量，而是采用如下的地址计算方法：&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;disp + base + index * scale&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;下面是一些内存操作数的例子：&lt;/p&gt;

    &lt;table&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th&gt;AT&amp;amp;T 格式&lt;/th&gt;
          &lt;th&gt;Intel 格式&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;movl -4(%ebp), %eax&lt;/td&gt;
          &lt;td&gt;mov eax, [ebp - 4]&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;movl array(, %eax, 4), %eax&lt;/td&gt;
          &lt;td&gt;mov eax, [eax*4 + array]&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;movw array(%ebx, %eax, 4), %cx&lt;/td&gt;
          &lt;td&gt;mov cx, [ebx + eax*4 + array]&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;movb $4, %fs:(%eax)&lt;/td&gt;
          &lt;td&gt;mov fs:eax, 4&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;hello-world&quot;&gt;&lt;span id=&quot;3&quot;&gt;Hello World!&lt;/span&gt;&lt;/h1&gt;

&lt;p&gt;真不知道打破这个传统会带来什么样的后果，但既然所有程序设计语言的第一个例子都是在屏幕上打印一个字符串 “Hello World!”，那我们也以这种方式来开始介绍 Linux 下的汇编语言程序设计。&lt;/p&gt;

&lt;p&gt;在 Linux 操作系统中，你有很多办法可以实现在屏幕上显示一个字符串，但最简洁的方式是使用 Linux 内核提供的系统调用。使用这种方法最大的好处是可以直接和操作系统的内核进行通讯，不需要链接诸如 libc 这样的函数库，也不需要使用 ELF 解释器，因而代码尺寸小且执行速度快。&lt;/p&gt;

&lt;p&gt;Linux 是一个运行在保护模式下的 32 位操作系统，采用 flat memory 模式，目前最常用到的是 ELF 格式的二进制代码。一个 ELF 格式的可执行程序通常划分为如下几个部分：.text、.data 和 .bss，其中 .text 是只读的代码区，.data 是可读可写的数据区，而 .bss 则是可读可写且没有初始化的数据区。代码区和数据区在 ELF 中统称为 section，根据实际需要你可以使用其它标准的 section，也可以添加自定义 section，但一个 ELF 可执行程序至少应该有一个 .text 部分。下面给出我们的第一个汇编程序，用的是 AT&amp;amp;T 汇编语言格式：&lt;/p&gt;

&lt;p&gt;例1. AT&amp;amp;T 格式&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#hello.s 
.data                    # 数据段声明
        msg : .string &quot;Hello, world!\\n&quot; # 要输出的字符串
        len = . - msg                   # 字串长度
.text                    # 代码段声明
.global _start           # 指定入口函数
        
_start:                  # 在屏幕上显示一个字符串
        movl $len, %edx  # 参数三：字符串长度
        movl $msg, %ecx  # 参数二：要显示的字符串
        movl $1, %ebx    # 参数一：文件描述符(stdout) 
        movl $4, %eax    # 系统调用号(sys_write) 
        int  $0x80       # 调用内核功能
        
                         # 退出程序
        movl $0,%ebx     # 参数一：退出代码
        movl $1,%eax     # 系统调用号(sys_exit) 
        int  $0x80       # 调用内核功能
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;初次接触到 AT&amp;amp;T 格式的汇编代码时，很多程序员都认为太晦涩难懂了，没有关系，在 Linux 平台上你同样可以使用 Intel 格式来编写汇编程序：&lt;/p&gt;

&lt;p&gt;例2. Intel 格式&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;; hello.asm 
section .data            ; 数据段声明
        msg db &quot;Hello, world!&quot;, 0xA     ; 要输出的字符串
        len equ $ - msg                 ; 字串长度
section .text            ; 代码段声明
global _start            ; 指定入口函数
_start:                  ; 在屏幕上显示一个字符串
        mov edx, len     ; 参数三：字符串长度
        mov ecx, msg     ; 参数二：要显示的字符串
        mov ebx, 1       ; 参数一：文件描述符(stdout) 
        mov eax, 4       ; 系统调用号(sys_write) 
        int 0x80         ; 调用内核功能
                         ; 退出程序
        mov ebx, 0       ; 参数一：退出代码
        mov eax, 1       ; 系统调用号(sys_exit) 
        int 0x80         ; 调用内核功能
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;上面两个汇编程序采用的语法虽然完全不同，但功能却都是调用 Linux 内核提供的 sys_write 来显示一个字符串，然后再调用 sys_exit 退出程序。在 Linux 内核源文件 include/asm-i386/unistd.h 中，可以找到所有系统调用的定义。&lt;/p&gt;

&lt;h1 id=&quot;linux-汇编工具&quot;&gt;&lt;span id=&quot;4&quot;&gt;Linux 汇编工具&lt;/span&gt;&lt;/h1&gt;

&lt;p&gt;Linux 平台下的汇编工具虽然种类很多，但同 DOS/Windows 一样，最基本的仍然是汇编器、链接器和调试器。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;汇编器&lt;/p&gt;

    &lt;p&gt;汇编器（assembler）的作用是将用汇编语言编写的源程序转换成二进制形式的目标代码。Linux 平台的标准汇编器是 GAS，它是 GCC 所依赖的后台汇编工具，通常包含在 binutils 软件包中。GAS 使用标准的 AT&amp;amp;T 汇编语法，可以用来汇编用 AT&amp;amp;T 格式编写的程序&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;as -o hello.o hello.s&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;Linux 平台上另一个经常用到的汇编器是 NASM，它提供了很好的宏指令功能，并能够支持相当多的目标代码格式，包括 bin、a.out、coff、elf、rdf 等。NASM 采用的是人工编写的语法分析器，因而执行速度要比 GAS 快很多，更重要的是它使用的是 Intel 汇编语法，可以用来编译用 Intel 语法格式编写的汇编程序：&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nasm -f elf hello.asm&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;链接器&lt;/p&gt;

    &lt;p&gt;由汇编器产生的目标代码是不能直接在计算机上运行的，它必须经过链接器的处理才能生成可执行代码。链接器通常用来将多个目标代码连接成一个可执行代码，这样可以先将整个程序分成几个模块来单独开发，然后才将它们组合(链接)成一个应用程序。 Linux 使用 ld 作为标准的链接程序，它同样也包含在 binutils 软件包中。汇编程序在成功通过 GAS 或 NASM 的编译并生成目标代码后，就可以使用 ld 将其链接成可执行程序了：&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ld -s -o hello hello.o&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;调试器&lt;/p&gt;

    &lt;p&gt;有人说程序不是编出来而是调出来的，足见调试在软件开发中的重要作用，在用汇编语言编写程序时尤其如此。Linux 下调试汇编代码既可以用 GDB、DDD 这类通用的调试器，也可以使用专门用来调试汇编代码的 ALD(Assembly Language Debugger)。&lt;/p&gt;

    &lt;p&gt;从调试的角度来看，使用 GAS 的好处是可以在生成的目标代码中包含符号表(symbol table)，这样就可以使用 GDB 和 DDD 来进行源码级的调试了。要在生成的可执行程序中包含符号表，可以采用下面的方式进行编译和链接：&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;as --gstabs -o hello.o hello.s&lt;/code&gt;
 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ld -o hello hello.o&lt;/code&gt;&lt;/p&gt;

    &lt;p&gt;执行 as 命令时带上参数 –gstabs 可以告诉汇编器在生成的目标代码中加上符号表，同时需要注意的是，在用 ld 命令进行链接时不要加上 -s 参数，否则目标代码中的符号表在链接时将被删去。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;在 GDB 和 DDD 中调试汇编代码和调试 C 语言代码是一样的，你可以通过设置断点来中断程序的运行，查看变量和寄存器的当前值，并可以对代码进行单步跟踪。下图是在 DDD 中调试汇编代码时的情景：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2026/01/01/registers.png&quot; alt=&quot;用 DDD 调试汇编程序 &quot; /&gt;&lt;/p&gt;

&lt;p&gt;汇编程序员通常面对的都是一些比较苛刻的软硬件环境，短小精悍的ALD可能更能符合实际的需要，因此下面主要介绍一下如何用ALD来调试汇编程序。首先在命令行方式下执行ald命令来启动调试器，该命令的参数是将要被调试的可执行程序：&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;ald hello
Assembly Language Debugger 0.1.3
Copyright &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;C&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; 2000-2002 Patrick Alken
hello: ELF Intel 80386 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;32 bit&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;, LSB, Executable, Version 1 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;current&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
Loading debugging symbols...&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;15 symbols loaded&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
ald&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;当 ALD 的提示符出现之后，用 disassemble 命令对代码段进行反汇编：&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ald&amp;gt; disassemble &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; .text
Disassembling section .text &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;0x08048074 - 0x08048096&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
08048074  BA0F000000                 mov edx, 0xf
08048079  B998900408                 mov ecx, 0x8049098
0804807E  BB01000000                 mov ebx, 0x1
08048083  B804000000                 mov eax, 0x4
08048088  CD80                       int 0x80
0804808A  BB00000000                 mov ebx, 0x0
0804808F  B801000000                 mov eax, 0x1
08048094  CD80                       int 0x80
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;上述输出信息的第一列是指令对应的地址码，利用它可以设置在程序执行时的断点：&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ald&amp;gt; &lt;span class=&quot;nb&quot;&gt;break &lt;/span&gt;0x08048088
Breakpoint 1 &lt;span class=&quot;nb&quot;&gt;set &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;0x08048088
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;断点设置好后，使用 run 命令开始执行程序。ALD 在遇到断点时将自动暂停程序的运行，同时会显示所有寄存器的当前值：&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ald&amp;gt; run
Starting program: hello
Breakpoint 1 encountered at 0x08048088
eax &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0x00000004 ebx &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0x00000001 ecx &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0x08049098 edx &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0x0000000F
esp &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0xBFFFF6C0 ebp &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0x00000000 esi &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0x00000000 edi &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0x00000000
ds  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0x0000002B es  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0x0000002B fs  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0x00000000 gs  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0x00000000
ss  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0x0000002B cs  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0x00000023 eip &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0x08048088 eflags &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0x00000246
Flags: PF ZF IF
08048088  CD80                       int 0x80
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如果需要对汇编代码进行单步调试，可以使用 next 命令：&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ald&amp;gt; next
Hello, world!
eax &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0x0000000F ebx &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0x00000000 ecx &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0x08049098 edx &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0x0000000F
esp &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0xBFFFF6C0 ebp &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0x00000000 esi &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0x00000000 edi &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0x00000000
ds  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0x0000002B es  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0x0000002B fs  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0x00000000 gs  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0x00000000
ss  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0x0000002B cs  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0x00000023 eip &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0x0804808F eflags &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; 0x00000346
Flags: PF ZF TF IF
0804808F  B801000000                 mov eax, 0x1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;若想获得 ALD 支持的所有调试命令的详细列表，可以使用 help 命令：&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ald&amp;gt; &lt;span class=&quot;nb&quot;&gt;help
&lt;/span&gt;Commands may be abbreviated.
If a blank &lt;span class=&quot;nb&quot;&gt;command &lt;/span&gt;is entered, the last &lt;span class=&quot;nb&quot;&gt;command &lt;/span&gt;is repeated.
Type &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;help&lt;/span&gt; &amp;lt;&lt;span class=&quot;nb&quot;&gt;command&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos; for more specific information on &amp;lt;command&amp;gt;.
General commands
attach         clear          continue       detach         disassemble
enter          examine        file           help           load
next           quit           register       run            set
step           unload         window         write
Breakpoint related commands
break          delete         disable        enable         ignore
lbreak         tbreak
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;系统调用&quot;&gt;&lt;span id=&quot;5&quot;&gt;系统调用&lt;/span&gt;&lt;/h1&gt;

&lt;p&gt;即便是最简单的汇编程序，也难免要用到诸如输入、输出以及退出等操作，而要进行这些操作则需要调用操作系统所提供的服务，也就是系统调用。除非你的程序只完成加减乘除等数学运算，否则将很难避免使用系统调用，事实上除了系统调用不同之外，各种操作系统的汇编编程往往都是很类似的。&lt;/p&gt;

&lt;p&gt;在 Linux 平台下有两种方式来使用系统调用：利用封装后的 C 库（libc）或者通过汇编直接调用。其中通过汇编语言来直接调用系统调用，是最高效地使用 Linux 内核服务的方法，因为最终生成的程序不需要与任何库进行链接，而是直接和内核通信。&lt;/p&gt;

&lt;p&gt;和 DOS 一样，Linux 下的系统调用也是通过中断（int 0x80）来实现的。在执行 int 80 指令时，寄存器 eax 中存放的是系统调用的功能号，而传给系统调用的参数则必须按顺序放到寄存器 ebx，ecx，edx，esi，edi 中，当系统调用完成之后，返回值可以在寄存器 eax 中获得。&lt;/p&gt;

&lt;p&gt;所有的系统调用功能号都可以在文件 /usr/include/bits/syscall.h 中找到，为了便于使用，它们是用 SYS_&lt;name&gt; 这样的宏来定义的，如 SYS_write、SYS_exit 等。例如，经常用到的 write 函数是如下定义的：&lt;/name&gt;&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;ssize_t&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;size_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;该函数的功能最终是通过 SYS_write 这一系统调用来实现的。根据上面的约定，参数 fb、buf 和 count 分别存在寄存器 ebx、ecx 和 edx 中，而系统调用号 SYS_write 则放在寄存器 eax 中，当 int 0x80 指令执行完毕后，返回值可以从寄存器 eax 中获得。&lt;/p&gt;

&lt;p&gt;或许你已经发现，在进行系统调用时至多只有 5 个寄存器能够用来保存参数，难道所有系统调用的参数个数都不超过 5 吗？当然不是，例如 mmap 函数就有 6 个参数，这些参数最后都需要传递给系统调用 SYS_mmap：&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;  &lt;span class=&quot;nf&quot;&gt;mmap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;size_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prot&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;off_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;当一个系统调用所需的参数个数大于 5 时，执行int 0x80 指令时仍需将系统调用功能号保存在寄存器 eax 中，所不同的只是全部参数应该依次放在一块连续的内存区域里，同时在寄存器 ebx 中保存指向该内存区域的指针。系统调用完成之后，返回值仍将保存在寄存器 eax 中。&lt;/p&gt;

&lt;p&gt;由于只是需要一块连续的内存区域来保存系统调用的参数，因此完全可以像普通的函数调用一样使用栈(stack)来传递系统调用所需的参数。但要注意一点，Linux 采用的是 C 语言的调用模式，这就意味着所有参数必须以相反的顺序进栈，即最后一个参数先入栈，而第一个参数则最后入栈。如果采用栈来传递系统调用所需的参数，在执行int 0x80 指令时还应该将栈指针的当前值复制到寄存器 ebx中。&lt;/p&gt;

&lt;h1 id=&quot;命令行参数&quot;&gt;&lt;span id=&quot;6&quot;&gt;命令行参数&lt;/span&gt;&lt;/h1&gt;

&lt;p&gt;在 Linux 操作系统中，当一个可执行程序通过命令行启动时，其所需的参数将被保存到栈中：首先是 argc，然后是指向各个命令行参数的指针数组 argv，最后是指向环境变量的指针数据 envp。在编写汇编语言程序时，很多时候需要对这些参数进行处理，下面的代码示范了如何在汇编代码中进行命令行参数的处理：&lt;/p&gt;

&lt;p&gt;例3. 处理命令行参数&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# args.s
.text
.globl _start
        
_start:
        popl	%ecx		# argc
vnext:
        popl	%ecx		# argv
        test 	%ecx, %ecx      # 空指针表明结束
        jz	exit
        movl	%ecx, %ebx
        xorl	%edx, %edx
strlen:
        movb	(%ebx), %al
        inc	%edx
        inc	%ebx
        test	%al, %al
        jnz	strlen
        movb	$10, -1(%ebx)
        movl	$4, %eax        # 系统调用号(sys_write) 
        movl	$1, %ebx        # 文件描述符(stdout) 
        int	$0x80
        jmp	vnext
exit:
        movl	$1,%eax         # 系统调用号(sys_exit) 
        xorl	%ebx, %ebx      # 退出代码
        int 	$0x80
		
        ret
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;span id=&quot;7&quot;&gt;GCC 内联汇编&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;用汇编编写的程序虽然运行速度快，但开发速度非常慢，效率也很低。如果只是想对关键代码段进行优化，或许更好的办法是将汇编指令嵌入到 C 语言程序中，从而充分利用高级语言和汇编语言各自的特点。但一般来讲，在 C 代码中嵌入汇编语句要比”纯粹”的汇编语言代码复杂得多，因为需要解决如何分配寄存器，以及如何与C代码中的变量相结合等问题。&lt;/p&gt;

&lt;p&gt;GCC 提供了很好的内联汇编支持，最基本的格式是：&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;__asm__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;asm statements&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;例如：&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;__asm__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;nop&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如果需要同时执行多条汇编语句，则应该用”\n\t”将各个语句分隔开，例如：&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;__asm__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;pushl %%eax &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;t&quot;&lt;/span&gt;
         &lt;span class=&quot;s&quot;&gt;&quot;movl $0, %%eax &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;t&quot;&lt;/span&gt;
         &lt;span class=&quot;s&quot;&gt;&quot;popl %eax&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;通常嵌入到 C 代码中的汇编语句很难做到与其它部分没有任何关系，因此更多时候需要用到完整的内联汇编格式：&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;__asm__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;asm statements&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;outputs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inputs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;registers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;modified&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;插入到 C 代码中的汇编语句是以”:”分隔的四个部分，其中第一部分就是汇编代码本身，通常称为指令部，其格式和在汇编语言中使用的格式基本相同。指令部分是必须的，而其它部分则可以根据实际情况而省略。&lt;/p&gt;

&lt;p&gt;在将汇编语句嵌入到C代码中时，操作数如何与C代码中的变量相结合是个很大的问题。GCC采用如下方法来解决这个问题：程序员提供具体的指令，而对寄存器的使用则只需给出”样板”和约束条件就可以了，具体如何将寄存器与变量结合起来完全由GCC和GAS来负责。&lt;/p&gt;

&lt;p&gt;在GCC内联汇编语句的指令部中，加上前缀’%’的数字(如%0，%1)表示的就是需要使用寄存器的”样板”操作数。指令部中使用了几个样板操作数，就表明有几个变量需要与寄存器相结合，这样GCC和GAS在编译和汇编时会根据后面给定的约束条件进行恰当的处理。由于样板操作数也使用’%’作为前缀，因此在涉及到具体的寄存器时，寄存器名前面应该加上两个’%’，以免产生混淆。&lt;/p&gt;

&lt;p&gt;紧跟在指令部后面的是输出部，是规定输出变量如何与样板操作数进行结合的条件，每个条件称为一个”约束”，必要时可以包含多个约束，相互之间用逗号分隔开就可以了。每个输出约束都以’=’号开始，然后紧跟一个对操作数类型进行说明的字后，最后是如何与变量相结合的约束。凡是与输出部中说明的操作数相结合的寄存器或操作数本身，在执行完嵌入的汇编代码后均不保留执行之前的内容，这是GCC在调度寄存器时所使用的依据。&lt;/p&gt;

&lt;p&gt;输出部后面是输入部，输入约束的格式和输出约束相似，但不带’=’号。如果一个输入约束要求使用寄存器，则GCC在预处理时就会为之分配一个寄存器，并插入必要的指令将操作数装入该寄存器。与输入部中说明的操作数结合的寄存器或操作数本身，在执行完嵌入的汇编代码后也不保留执行之前的内容。&lt;/p&gt;

&lt;p&gt;有时在进行某些操作时，除了要用到进行数据输入和输出的寄存器外，还要使用多个寄存器来保存中间计算结果，这样就难免会破坏原有寄存器的内容。在GCC内联汇编格式中的最后一个部分中，可以对将产生副作用的寄存器进行说明，以便GCC能够采用相应的措施。&lt;/p&gt;

&lt;p&gt;下面是一个内联汇编的简单例子：&lt;/p&gt;

&lt;p&gt;例4. 内联汇编&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cm&quot;&gt;/* inline.c */&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;__asm__&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__volatile__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;movl %1, %%eax;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;r&quot;&lt;/span&gt;
                         &lt;span class=&quot;s&quot;&gt;&quot;movl %%eax, %0;&quot;&lt;/span&gt;
                         &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;=r&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;      &lt;span class=&quot;cm&quot;&gt;/* 输出 */&lt;/span&gt;    
                         &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;r&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;       &lt;span class=&quot;cm&quot;&gt;/* 输入 */&lt;/span&gt;
                         &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%eax&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;     &lt;span class=&quot;cm&quot;&gt;/* 不受影响的寄存器 */&lt;/span&gt;
    
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Result: %d, %d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;n&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;上面的程序完成将变量a的值赋予变量b，有几点需要说明：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;变量b是输出操作数，通过%0来引用，而变量a是输入操作数，通过%1来引用。&lt;/li&gt;
  &lt;li&gt;输入操作数和输出操作数都使用r进行约束，表示将变量a和变量b存储在寄存器中。输入约束和输出约束的不同点在于输出约束多一个约束修饰符’=’。&lt;/li&gt;
  &lt;li&gt;在内联汇编语句中使用寄存器eax时，寄存器名前应该加两个’%’，即%%eax。内联汇编中使用%0、%1等来标识变量，任何只带一个’%’的标识符都看成是操作数，而不是寄存器。&lt;/li&gt;
  &lt;li&gt;内联汇编语句的最后一个部分告诉GCC它将改变寄存器eax中的值，GCC在处理时不应使用该寄存器来存储任何其它的值。&lt;/li&gt;
  &lt;li&gt;由于变量b被指定成输出操作数，当内联汇编语句执行完毕后，它所保存的值将被更新。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;在内联汇编中用到的操作数从输出部的第一个约束开始编号，序号从0开始，每个约束记数一次，指令部要引用这些操作数时，只需在序号前加上’%’作为前缀就可以了。需要注意的是，内联汇编语句的指令部在引用一个操作数时总是将其作为32位的长字使用，但实际情况可能需要的是字或字节，因此应该在约束中指明正确的限定符：&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;“m”、”v”、”o”&lt;/td&gt;
      &lt;td&gt;内存单元&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;“r”&lt;/td&gt;
      &lt;td&gt;任何寄存器&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;“q”&lt;/td&gt;
      &lt;td&gt;寄存器eax、ebx、ecx、edx之一&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;“i”、”h”&lt;/td&gt;
      &lt;td&gt;直接操作数&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;“E”和”F”&lt;/td&gt;
      &lt;td&gt;浮点数&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;“g”&lt;/td&gt;
      &lt;td&gt;任意&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;“a”、”b”、”c”、”d”&lt;/td&gt;
      &lt;td&gt;分别表示寄存器eax、ebx、ecx和edx&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;“S”和”D”&lt;/td&gt;
      &lt;td&gt;寄存器esi、edi&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;“I”&lt;/td&gt;
      &lt;td&gt;常数（0至31）&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h1 id=&quot;小结&quot;&gt;&lt;span id=&quot;8&quot;&gt;小结&lt;/span&gt;&lt;/h1&gt;

&lt;p&gt;Linux操作系统是用C语言编写的，汇编只在必要的时候才被人们想到，但它却是减少代码尺寸和优化代码性能的一种非常重要的手段，特别是在与硬件直接交互的时候，汇编可以说是最佳的选择。Linux提供了非常优秀的工具来支持汇编程序的开发，使用GCC的内联汇编能够充分地发挥C语言和汇编语言各自的优点。&lt;/p&gt;

&lt;h1 id=&quot;参考资料&quot;&gt;&lt;span id=&quot;9&quot;&gt;参考资料&lt;/span&gt;&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;在网站 &lt;a href=&quot;https://asm.sourceforge.net/&quot;&gt;linuxassembly.org&lt;/a&gt; 上可以找到大量的Linux汇编资源。&lt;/li&gt;
  &lt;li&gt;软件包binutils提供了as和ld等实用工具，其相关信息可以在网站 &lt;a href=&quot;https://www.sourceware.org/binutils/&quot;&gt;sources.redhat.com/binutils/&lt;/a&gt; 上找到。&lt;/li&gt;
  &lt;li&gt;NASM是Intel格式的汇编器，其相关信息可以在网站 &lt;a href=&quot;https://www.nasm.us/&quot;&gt;nasm.sourceforge.net&lt;/a&gt; 上找到。&lt;/li&gt;
  &lt;li&gt;ALD是一个短小精悍的汇编调试器，其相关信息可以在网站 &lt;a href=&quot;http://ald.sourceforge.net/&quot;&gt;dunx1.irt.drexel.edu/~psa22/ald.html&lt;/a&gt; 上找到。&lt;/li&gt;
  &lt;li&gt;intel2gas是一个能够将Intel汇编格式转换成AT&amp;amp;T汇编格式的小工具，其相关信息可以在网站 &lt;a href=&quot;https://web.archive.org/web/20071106131526/http://www.niksula.hut.fi/~mtiihone/intel2gas/&quot;&gt;www.niksula.cs.hut.fi/~mtiihone/intel2gas/&lt;/a&gt; 上找到。&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>【搞机小子】Airpi AP3000M 5G CPE 使用体验 </title>
   <link href="https://icing.fun/posts/airpi_ap3000m.html"/>
   <updated>2025-10-01T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/airpi_ap3000m</id>
   <content type="html">&lt;p&gt;书接上回，我在淘宝买了个&lt;a href=&quot;https://www.waveshare.net/wiki/RM530N-GL&quot;&gt;RM530N-GL&lt;/a&gt;模块，配合 微雪 USB 3.2 Gen1 5G DONGLE 来给笔电上 5G。&lt;/p&gt;

&lt;p&gt;不过，USB 设备总觉得有点别扭，尤其是我这种经常出差的人，插拔总觉得不方便。&lt;/p&gt;

&lt;center&gt;
    &lt;img src=&quot;../img/post/2025/10/01/1.jpg&quot; alt=&quot;Order&quot; title=&quot;Order&quot; width=&quot;50%&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;很久之前在淘宝上看到一款手搓的 5G CPE，叫 Airpi AP3000M，用的 MT7981  芯片，AX3000 的 Wi-Fi，1GB RAM + 16GB ROM，不带 5G 模块才 439。&lt;/p&gt;

&lt;center&gt;
    &lt;img src=&quot;../img/post/2025/10/01/1.png&quot; alt=&quot;Order&quot; title=&quot;Order&quot; width=&quot;50%&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;样子还硬派的，于是果断下单。&lt;/p&gt;

&lt;center&gt;
    &lt;img src=&quot;../img/post/2025/10/01/2.png&quot; alt=&quot;Order&quot; title=&quot;Order&quot; width=&quot;50%&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;拿到手之后是散件，需要自己动手装。（没拍装机过程，可以找店家要安装视频，本人比较头铁，自己安的）&lt;/p&gt;

&lt;p&gt;装好之后，插上电源，等 1 分钟左右，等到侧面的红色指示灯常亮之后，就可以用手机或者电脑连接 Wi-Fi 了。&lt;/p&gt;

&lt;center&gt;
    &lt;img src=&quot;../img/post/2025/10/01/3.png&quot; alt=&quot;Order&quot; title=&quot;Order&quot; width=&quot;50%&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;（按理说是没有密码的，我这个是时候截图的时候被我设置了密码）&lt;/p&gt;

&lt;p&gt;或者者直接用网线连接 CPE 的 LAN 口。（LAN口是离电源口最远的那个）&lt;/p&gt;

&lt;p&gt;打开浏览器，输入 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.88.1&lt;/code&gt;，就可以进入管理界面了。&lt;/p&gt;

&lt;center&gt;
    &lt;img src=&quot;../img/post/2025/10/01/4.png&quot; alt=&quot;Order&quot; title=&quot;Order&quot; width=&quot;50%&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;默认用户名是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root&lt;/code&gt;，密码是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;admin&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;进入管理界面之后，找到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;移动网络&lt;/code&gt; -&amp;gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;其他设定&lt;/code&gt;，找到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;USB 设备信息 /lsusb&lt;/code&gt;，可以看到识别出来的 5G 模块：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Bus 002 Device 002: ID 2c7c:0801 Quectel RM530N-GL&lt;/code&gt;&lt;/p&gt;

&lt;center&gt;
    &lt;img src=&quot;../img/post/2025/10/01/5.png&quot; alt=&quot;Order&quot; title=&quot;Order&quot; width=&quot;50%&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;然后找到 找到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;移动网络&lt;/code&gt; -&amp;gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;串口调试&lt;/code&gt;，选择模组的 AT 口，发送以下命令：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ATE1 # 设置回显
AT+QCFG=&quot;usbnet&quot;,3 # 设置为 RNDIS 模式
AT+CFUN=1,1 # 重启模组
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;（别问我为什么不用 MBIM 模式，我也不知道，反正 RNDIS 模式能用就行）&lt;/p&gt;

&lt;p&gt;然后可以进入 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;网络选项&lt;/code&gt; -&amp;gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;接口配置&lt;/code&gt;，添加一个新的移动网络接口，名字可以叫 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WWAN&lt;/code&gt;，选择 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eth2&lt;/code&gt; 作为接口。协议选择 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DHCP客户端&lt;/code&gt;。（eth0 是 LAN 口，eth1 是 WAN 口，eth2 是 5G 模块）&lt;/p&gt;

&lt;center&gt;
    &lt;img src=&quot;../img/post/2025/10/01/6.png&quot; alt=&quot;Order&quot; title=&quot;Order&quot; width=&quot;50%&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;也可以添加IPv6的DHCP客户端。&lt;/p&gt;

&lt;center&gt;
    &lt;img src=&quot;../img/post/2025/10/01/7.png&quot; alt=&quot;Order&quot; title=&quot;Order&quot; width=&quot;50%&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;就可以上网了。&lt;/p&gt;

&lt;p&gt;也可以&lt;a href=&quot;https://github.com/vernesong/OpenClash&quot;&gt;养小猫咪&lt;/a&gt;：&lt;/p&gt;

&lt;center&gt;
    &lt;img src=&quot;../img/post/2025/10/01/8.png&quot; alt=&quot;Order&quot; title=&quot;Order&quot; width=&quot;20%&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;最后用&lt;a href=&quot;https://test.ustc.edu.cn/&quot;&gt;中科大测速&lt;/a&gt;：&lt;/p&gt;

&lt;center&gt;
    &lt;img src=&quot;../img/post/2025/10/01/9.png&quot; alt=&quot;Order&quot; title=&quot;Order&quot; width=&quot;50%&quot; /&gt;
&lt;/center&gt;
</content>
 </entry>
 
 <entry>
   <title>【赛博丁真】让你的笔电也加入 5G </title>
   <link href="https://icing.fun/posts/laptop_cellular.html"/>
   <updated>2025-09-04T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/laptop_cellular</id>
   <content type="html">&lt;s&gt;都说 2019 年是 5G 商用元年，但我一直都有点困惑，4G 已经够快了，5G 到底有什么用呢？&lt;/s&gt;

&lt;p&gt;手机和 Pad 上都有 5G，但是笔电制造商很不热衷于在笔电主板上加一个 WWAN 接口或者是直接集成，就连高通处理器的笔电很多也没有集成。&lt;/p&gt;

&lt;p&gt;为了探究这个问题，我在 2023 年让我爸斥巨资买了个 Surface Pro 9 5G 版，来体验一下 5G 的快感。&lt;/p&gt;

&lt;center&gt;
    &lt;img src=&quot;../img/post/2023/11/29/order.jpg&quot; alt=&quot;Order&quot; title=&quot;Order&quot; width=&quot;50%&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;随后在进入联想工作后，又弄了一台 ThinkPad X1 Carbon Gen 9，原装是 LTE 模块，上淘宝搜一下轻轻松松就搞到一个高通 X55 的 5G 模块，换上装 Fedora（过程还是比较麻烦的，下一期补上这个）。&lt;/p&gt;

&lt;p&gt;先说结论，如果说模块支持修改 IMEI 的话，买个天际通流量卡，基本上就可以做到随时随地在线，办公追剧两不误。&lt;/p&gt;

&lt;p&gt;讲真，天际通的流量卡真的很香，2000G 流量才 99 元（我直接包年，599），5G 网络覆盖也还不错。&lt;/p&gt;

&lt;p&gt;其实能改 IMEI 的模块也不多，ThinkPad 的模块需要魔改才能暴露串口，使用 AT 指令来修改 IMEI，Surface Pro 9 的模块貌似用的广和通的，也是屏蔽了部分 COM 口。&lt;/p&gt;

&lt;p&gt;所以，我直接在淘宝的微雪旗舰店买了个 &lt;a href=&quot;https://www.waveshare.net/wiki/USB_3.2_Gen1_5G_DONGLE&quot;&gt;USB 3.2 Gen1 5G DONGLE&lt;/a&gt;，再配上 Sub-6 GHz 和 毫米波 模块 &lt;a href=&quot;https://www.waveshare.net/wiki/RM530N-GL&quot;&gt;RM530N-GL&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;把黑盒的 USB 线接到笔电上，再在电脑上安装驱动：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.waveshare.net/w/upload/f/f5/Quectel_Windows_USB_DriverQ_NDIS_V2.4.6.zip&quot;&gt;RM520N-GL Windows NDIS驱动&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.waveshare.net/w/upload/9/94/Quectel_Windows_USB_Driver%28Q%29_MBIM_V1.3.1.zip&quot;&gt;RM520N-GL Windows MBIM驱动&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;center&gt;
    &lt;img src=&quot;../img/post/2025/09/04/Capture.PNG&quot; alt=&quot;Devices Manager&quot; title=&quot;Devices Manager&quot; width=&quot;50%&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;看到这样就成。然后下载 &lt;a href=&quot;https://www.waveshare.net/w/upload/c/ca/QCOM_V1.6.zip&quot;&gt;QCOM&lt;/a&gt;，用作为修改 IMEI 的工具。&lt;/p&gt;

&lt;p&gt;在设备管理器中，我们能看到三个 COM 口，记下 AT 指令口的 COM 号，比如我的是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Quectel USB AT Port (COM11)&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;打开 QCOM，选择对应的 COM 口，波特率 115200，然后点击 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Open Port&lt;/code&gt;；&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Operation&lt;/code&gt; 下勾选 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RTS&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Send with Enter&lt;/code&gt;：&lt;/p&gt;

&lt;center&gt;
    &lt;img src=&quot;../img/post/2025/09/04/Capture1.PNG&quot; alt=&quot;QCOM setup&quot; title=&quot;QCOM setup&quot; width=&quot;50%&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;输入 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ATE1&lt;/code&gt;，回车，打开回显，看到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OK&lt;/code&gt; 说明串口通信正常。&lt;/p&gt;

&lt;p&gt;输入 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AT+CGSN&lt;/code&gt;，回车，看到返回的结果是当前的 IMEI 号。&lt;/p&gt;

&lt;p&gt;移远模组的文档里面没写修改 IMEI 的 AT 指令，网上也有愣头青跑去移远论坛下问，结果人家说不支持修改 IMEI。微雪的文档也说不支持，乐。&lt;/p&gt;

&lt;p&gt;国内版可能用不了，但是全球版应该会遵循3GPP TS 27.007 和 TS 27.005 标准，这两个标准规定了常见的蜂窝网络AT命令集（如拨号、短信、网络注册、信号质量查询等）。&lt;/p&gt;

&lt;p&gt;放心大胆使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AT+EGMR=1,7,&quot;你的华为随身WiFi的IMEI号&quot;&lt;/code&gt; 来修改 IMEI 吧。最后可以用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AT+CGSN&lt;/code&gt; 来查询修改后的 IMEI 号。&lt;/p&gt;

&lt;p&gt;修改完 IMEI 之后，拔掉黑盒，插上 SIM 卡，就可以联网了。&lt;/p&gt;

&lt;center&gt;
    &lt;img src=&quot;../img/post/2025/09/04/IMG_4009.jpeg&quot; alt=&quot;BlackBox&quot; title=&quot;BlackBox&quot; width=&quot;50%&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;如果要使用 MBIM 模式的话，使用以下 AT 指令：&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;AT+QCFG&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;usbnet&quot;&lt;/span&gt;,2
AT+CFUN&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1,1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;想换回 NDIS 模式的话，使用以下 AT 指令：&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;AT+QCFG&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;usbnet&quot;&lt;/span&gt;,1
AT+QNETDEVCTL&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;2,3,1
AT+CFUN&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1,1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;center&gt;
    &lt;img src=&quot;../img/post/2025/09/04/Capture2.PNG&quot; alt=&quot;BlackBox&quot; title=&quot;BlackBox&quot; width=&quot;50%&quot; /&gt;
&lt;/center&gt;

&lt;s&gt;不觉得这很酷吗？作为一名理工男我觉得这太酷了，很符合我对未来生活的想象，科技并带着趣味。&lt;/s&gt;

&lt;p&gt;突然想起来，我刚上大学的时候，在常州认识了常州创客中心的创始人，当时他就跟我说过一句话：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;何同学很厉害。他做的 5G 视频你看了没有，我觉得那就是创客。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;哦。啧。唉。&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>【玩转树莓派】VSCode 远程登录树莓派并免密登录</title>
   <link href="https://icing.fun/posts/vscode_headless_login_rpi.html"/>
   <updated>2025-07-20T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/vscode_headless_login_rpi</id>
   <content type="html">&lt;h2 id=&quot;安装-vscode-及-remote-ssh-插件&quot;&gt;安装 VSCode 及 Remote SSH 插件&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;安装 &lt;a href=&quot;https://code.visualstudio.com/&quot;&gt;Visual Studio Code&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;安装插件：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Remote - SSH&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;生成-ssh-密钥对如果没有的话&quot;&gt;生成 SSH 密钥对（如果没有的话）&lt;/h2&gt;

&lt;p&gt;打开 PowerShell 或 CMD：&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;ssh-keygen&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;默认会保存在：&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;C:\Users\&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;你的用户名&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;\.ssh\id_rsa&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;（私钥）&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;C:\Users\&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;你的用户名&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;\.ssh\id_rsa.pub&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;（公钥）&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;直接按回车即可，不设密码。&lt;/p&gt;

&lt;h2 id=&quot;登录树莓派并上传公钥&quot;&gt;登录树莓派并上传公钥&lt;/h2&gt;

&lt;p&gt;先用普通方式连接一次：&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;ssh&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pi&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;raspberrypi.local&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# 或 ssh pi@192.168.x.x&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后在树莓派上执行：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; ~/.ssh
&lt;span class=&quot;nb&quot;&gt;chmod &lt;/span&gt;700 ~/.ssh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后用如下命令将 Windows 上的公钥复制进去（在 Windows 端执行）：&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kr&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;nn&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;USERPROFILE&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;\.ssh\id_rsa.pub&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ssh&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pi&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;raspberrypi.local&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;cat &amp;gt;&amp;gt; ~/.ssh/authorized_keys&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;再设置好权限（树莓派端）：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;chmod &lt;/span&gt;600 ~/.ssh/authorized_keys
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;编辑-ssh-配置文件windows&quot;&gt;编辑 SSH 配置文件（Windows）&lt;/h2&gt;

&lt;p&gt;打开：&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;C:\Users\&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;你的用户名&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;\.ssh\config&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;（没有就创建）&lt;/p&gt;

&lt;p&gt;添加如下内容：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Host rpi
    HostName 192.168.x.x     # 树莓派的 IP
    User pi
    IdentityFile ~/.ssh/id_rsa
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>【阅板无数】使用 OpenOCD 对 Raspberry Pi CM5 进行调试</title>
   <link href="https://icing.fun/posts/raspberry-pi-cm5.html"/>
   <updated>2025-07-17T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/raspberry-pi-cm5</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;../img/post/2025/07/17/cm5.webp&quot; alt=&quot;cm5&quot; width=&quot;50%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;2024年11月27日，在距第一款商用 Raspberry Pi Model B（于 2012 年 2 月 29 日推出）发布整整12年之后，Raspberry Pi 基金会发布了 Raspberry Pi Compute Module 5（CM5）。这款产品的发布标志着 Raspberry Pi 进入了一个新的阶段，特别是在工业和嵌入式应用领域。&lt;/p&gt;

&lt;p&gt;Raspberry Pi CM5 是一款基于 Raspberry Pi 4 的计算模块，采用了更小的尺寸和更高的集成度，旨在满足工业和嵌入式应用的需求。它配备了强大的处理器、丰富的接口和扩展能力，使其成为各种应用场景的理想选择。&lt;/p&gt;

&lt;h2 id=&quot;测试点位&quot;&gt;测试点位&lt;/h2&gt;

&lt;p&gt;废话不多说，直接进入正题，以往的 Raspberry Pi 系列产品都可以通过 JTAG 进行调试，但 CM5 的 JTAG 接口并不直接暴露出来。同时我们需要使用 OpenOCD 来对其进行调试。&lt;/p&gt;

&lt;p&gt;根据官方提供的&lt;a href=&quot;https://datasheets.raspberrypi.com/cm5/cm5-datasheet.pdf&quot;&gt;数据手册&lt;/a&gt;，我们可以看到 CM5 的 JTAG 接口位于 Wi-Fi 模块背面的测试点位，具体位置参见文档第37页。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2025/07/17/doc.png&quot; alt=&quot;cm5&quot; width=&quot;50%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;具体焊接点位如下，橙色线和黄色线是对应原版树莓派 Debug Probe 的线的颜色：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2025/07/17/pin.png&quot; alt=&quot;cm5&quot; width=&quot;50%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2025/07/17/the-probe.png&quot; alt=&quot;cm5&quot; width=&quot;50%&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Orange
  TX/&lt;strong&gt;SCLK&lt;/strong&gt; (Output from Probe)&lt;/li&gt;
  &lt;li&gt;Black
  GND&lt;/li&gt;
  &lt;li&gt;Yellow
  RX/&lt;strong&gt;SWD&lt;/strong&gt; (Input to Probe or I/O)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;具体参见&lt;a href=&quot;https://www.raspberrypi.com/documentation/microcontrollers/debug-probe.html#the-debug-probe&quot;&gt;官方文档&lt;/a&gt;。&lt;/p&gt;

&lt;h2 id=&quot;树莓派配置&quot;&gt;树莓派配置&lt;/h2&gt;

&lt;p&gt;在树莓派镜像里面找到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/boot/firmware/config.txt&lt;/code&gt; 文件，添加以下内容：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;all]
&lt;span class=&quot;nv&quot;&gt;enable_uart&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
&lt;span class=&quot;nv&quot;&gt;dtoverlay&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;uart0
&lt;span class=&quot;nv&quot;&gt;dtoverlay&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;disable-bt
&lt;span class=&quot;nv&quot;&gt;uart_2ndstage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
&lt;span class=&quot;nv&quot;&gt;enable_jtag_gpio&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1

&lt;span class=&quot;nv&quot;&gt;dtparam&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;fan_temp0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;35000
&lt;span class=&quot;nv&quot;&gt;dtparam&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;fan_temp0_hyst&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;5000
&lt;span class=&quot;nv&quot;&gt;dtparam&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;fan_temp0_speed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;175
&lt;span class=&quot;nv&quot;&gt;dtparam&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;uart0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;on
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/boot/firmware/cmdline.txt&lt;/code&gt; 文件中修改成以下内容：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;earlycon&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;pl011,0x107d001000,115200n8 &lt;span class=&quot;nv&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;tty1 &lt;span class=&quot;nv&quot;&gt;console&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;ttyAMA0,115200 &lt;span class=&quot;nv&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PARTUUID&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;5f127066-02 &lt;span class=&quot;nv&quot;&gt;rootfstype&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;ext4 fsck.repair&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;yes &lt;/span&gt;rootwait quiet splash plymouth.ignore-serial-consoles cfg80211.ieee80211_regdom&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;CN
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/boot/firmware/config.txt&lt;/code&gt; 文件中的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;enable_jtag_gpio=1&lt;/code&gt; 是启用 JTAG GPIO 的关键配置。&lt;/p&gt;

  &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/boot/firmware/cmdline.txt&lt;/code&gt; 文件中的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;console=ttyAMA0,115200&lt;/code&gt; 原本应该是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;console=serial0,115200n8&lt;/code&gt;，但由于树莓派 CM5 的 Serial0 默认绑定那两个焊上的测试点，我们需要把串口转到 GPIO 14 和 15 上，因此需要将其修改为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;console=ttyAMA0,115200&lt;/code&gt;。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;本人自制了一个带 3V3 的调试器，使用了树莓派官方的 Debug Probe，焊接了 3V3、GND、SWD 和 SCLK 四个引脚。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2025/07/17/debug-probe.png&quot; alt=&quot;debug-probe&quot; width=&quot;50%&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;openocd-配置&quot;&gt;OpenOCD 配置&lt;/h2&gt;

&lt;p&gt;在电脑上安装 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AArch64 GNU/Linux target (aarch64-none-linux-gnu)&lt;/code&gt;，可以在&lt;a href=&quot;https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads&quot;&gt;此处&lt;/a&gt;下载。如果需要裸机编程，还需要安装 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AArch64 bare-metal target (aarch64-none-elf)&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;Windows版的 OpenOCD 可以在&lt;a href=&quot;https://gnutoolchains.com/arm-eabi/openocd/&quot;&gt;此处&lt;/a&gt;下载。&lt;/p&gt;

&lt;p&gt;Linux 用户可以自己编译，也可以使用包管理器安装 OpenOCD。&lt;/p&gt;

&lt;p&gt;安装好后可以打开终端，输入以下命令来检查 OpenOCD 是否安装成功：&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;path_to_openocd&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;\openocd.exe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--version&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后检查 AArch64 GNU/Linux target (aarch64-none-linux-gnu)：&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;C:\Program Files (x86)\Arm GNU Toolchain aarch64-none-linux-gnu\14.3 rel1\bin&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;\aarch64-none-linux-gnu-gdb.exe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--version&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;接下来创建一个 OpenOCD 配置文件 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rpi5.cfg&lt;/code&gt;，内容如下：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# SPDX-License-Identifier: GPL-2.0-or-later

# The Broadcom BCM2712 used in Raspberry Pi 5
# No documentation was found on Broadcom website

# Partial information is available in Raspberry Pi website:
# https://www.raspberrypi.com/documentation/computers/processors.html#bcm2712

# v1.0 initial revision - trejan on forums.raspberrypi.com

if { [info exists CHIPNAME] } {
        set  _CHIPNAME $CHIPNAME
} else {
        set  _CHIPNAME bcm2712
}

if { [info exists CHIPCORES] } {
        set _cores $CHIPCORES
} else {
        set _cores 4
}

if { [info exists USE_SMP] } {
        set _USE_SMP $USE_SMP
} else {
        set _USE_SMP 0
}

if { [info exists DAP_TAPID] } {
        set _DAP_TAPID $DAP_TAPID
} else {
        set _DAP_TAPID 0x4ba00477
}

transport select swd

swd newdap $_CHIPNAME cpu -expected-id $_DAP_TAPID -irlen 4
adapter speed 4000

dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu

# MEM-AP for direct access
target create $_CHIPNAME.ap mem_ap -dap $_CHIPNAME.dap -ap-num 0

# these addresses are obtained from the ROM table via &apos;dap info 0&apos; command
set _DBGBASE {0x80010000 0x80110000 0x80210000 0x80310000}
set _CTIBASE {0x80020000 0x80120000 0x80220000 0x80320000}

set _smp_command &quot;target smp&quot;

for { set _core 0 } { $_core &amp;lt; $_cores } { incr _core } {
        set _CTINAME $_CHIPNAME.cti$_core
        set _TARGETNAME $_CHIPNAME.cpu$_core

        cti create $_CTINAME -dap $_CHIPNAME.dap -ap-num 0 -baseaddr [lindex $_CTIBASE $_core]
        target create $_TARGETNAME aarch64 -dap $_CHIPNAME.dap -ap-num 0 -dbgbase [lindex $_DBGBASE $_core] -cti $_CTINAME

        set _smp_command &quot;$_smp_command $_TARGETNAME&quot;
}

if {$_USE_SMP} {
        eval $_smp_command
}

# default target is cpu0
targets $_CHIPNAME.cpu0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;或者使用以下内容：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# bcm2712.cfg
# SPDX-License-Identifier: GPL-2.0-or-later
# OpenOCD target config file
# This file is based on target/bcm2711.cfg
# I have checked that it works with Open On-Chip Debugger 0.12.0 
# using the Raspberry Pi Debug-Probe interface

transport select swd
adapter speed 1000

if { [info exists CHIPNAME] } {
    set  _CHIPNAME $CHIPNAME
} else {
    set  _CHIPNAME bcm2712
}

if { [info exists CHIPCORES] } {
    set _cores $CHIPCORES
} else {
    set _cores 4
}

if { [info exists USE_SMP] } {
    set _USE_SMP $USE_SMP
} else {
    set _USE_SMP 0
}

if { [info exists DAP_TAPID] } {
    set _DAP_TAPID $DAP_TAPID
} else {
    set _DAP_TAPID 0x2ba00477
}

# swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_DAP_TAPID
swd newdap $_CHIPNAME cpu -expected-id $_DAP_TAPID
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu

# MEM-AP for direct access
target create $_CHIPNAME.ap mem_ap -dap $_CHIPNAME.dap -ap-num 0

# these addresses are obtained from the ROM table via &apos;dap info 0&apos; command
set _DBGBASE {0x80010000 0x80110000 0x80210000 0x80310000}
set _CTIBASE {0x80020000 0x80120000 0x80220000 0x80320000}

set _smp_command &quot;target smp&quot;

for { set _core 0 } { $_core &amp;lt; $_cores } { incr _core } {
    set _CTINAME $_CHIPNAME.cti$_core
    set _TARGETNAME $_CHIPNAME.cpu$_core

    cti create $_CTINAME -dap $_CHIPNAME.dap -ap-num 0 -baseaddr [lindex $_CTIBASE $_core]
    target create $_TARGETNAME aarch64 -dap $_CHIPNAME.dap -ap-num 0 -dbgbase [lindex $_DBGBASE $_core] -cti $_CTINAME

    set _smp_command &quot;$_smp_command $_TARGETNAME&quot;
}

if {$_USE_SMP} {
    eval $_smp_command
}

# default target is cpu0
targets $_CHIPNAME.cpu0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后新建一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmsis-dap.cfg&lt;/code&gt; 文件，内容如下：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# SPDX-License-Identifier: GPL-2.0-or-later

#
# ARM CMSIS-DAP compliant adapter
#
# http://www.keil.com/support/man/docs/dapdebug/
#

adapter driver cmsis-dap

# Optionally specify the serial number of CMSIS-DAP usb device.
# adapter serial 02200201E6661E601B98E3B9
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;启动-openocd-开始调试&quot;&gt;启动 OpenOCD 开始调试&lt;/h2&gt;

&lt;p&gt;在终端中运行以下命令来启动 OpenOCD：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &amp;lt;path_to_openocd&amp;gt;
.&lt;span class=&quot;se&quot;&gt;\o&lt;/span&gt;penocd.exe &lt;span class=&quot;nt&quot;&gt;--file&lt;/span&gt; cmsis-dap.cfg &lt;span class=&quot;nt&quot;&gt;--file&lt;/span&gt; rpi5.cfg
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如果一切正常，你应该会看到类似以下的输出：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Open On-Chip Debugger 0.12.0 (2025-07-10) [https://github.com/sysprogs/openocd]
Licensed under GNU GPL v2
libusb1 d52e355daa09f17ce64819122cb067b8a2ee0d4b
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : Using CMSIS-DAPv2 interface with VID:PID=0x2e8a:0x000c, serial=0DA4770B2DB8B6AA
Info : CMSIS-DAP: SWD supported
Info : CMSIS-DAP: Atomic commands supported
Info : CMSIS-DAP: Test domain timer supported
Info : CMSIS-DAP: FW Version = 2.0.0
Info : CMSIS-DAP: Interface Initialised (SWD)
Info : SWCLK/TCK = 0 SWDIO/TMS = 0 TDI = 0 TDO = 0 nTRST = 0 nRESET = 0
Info : CMSIS-DAP: Interface ready
Info : clock speed 4000 kHz
Info : SWD DPIDR 0x2ba01477
Info : [bcm2712.ap] Examination succeed
Info : bcm2712.cpu0: hardware has 6 breakpoints, 4 watchpoints
Info : [bcm2712.cpu0] external reset detected
Info : [bcm2712.cpu0] Examination succeed    
Info : bcm2712.cpu1: hardware has 6 breakpoints, 4 watchpoints
Info : [bcm2712.cpu1] external reset detected
Info : [bcm2712.cpu1] Examination succeed
Info : bcm2712.cpu2: hardware has 6 breakpoints, 4 watchpoints
Info : [bcm2712.cpu2] external reset detected
Info : [bcm2712.cpu2] Examination succeed
Info : bcm2712.cpu3: hardware has 6 breakpoints, 4 watchpoints
Info : [bcm2712.cpu3] external reset detected
Info : [bcm2712.cpu3] Examination succeed
Info : [bcm2712.ap] gdb port disabled
Info : [bcm2712.cpu0] starting gdb server on 3333
Info : Listening on port 3333 for gdb connections
Info : [bcm2712.cpu1] starting gdb server on 3334
Info : Listening on port 3334 for gdb connections
Info : [bcm2712.cpu2] starting gdb server on 3335
Info : Listening on port 3335 for gdb connections
Info : [bcm2712.cpu3] starting gdb server on 3336
Info : Listening on port 3336 for gdb connections
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;使用-gdb-连接-openocd&quot;&gt;使用 GDB 连接 OpenOCD&lt;/h2&gt;

&lt;p&gt;在终端中打开 GDB，使用以下命令连接到 OpenOCD：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &amp;lt;path_to_aarch64_gnu_toolchain&amp;gt;
.&lt;span class=&quot;se&quot;&gt;\a&lt;/span&gt;arch64-none-linux-gnu-gdb.exe
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后在 GDB 中输入以下命令：&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-gdb&quot;&gt;target remote :3333
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;将会看到类似以下的输出：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Remote debugging using :3333
warning: No executable has been specified and target does not support
determining executable automatically.  Try using the &quot;file&quot; command. 
0xffffd06fcf183b48 in ?? ()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这表示你已经成功连接到 OpenOCD，并且可以开始调试 Raspberry Pi CM5。&lt;/p&gt;

&lt;p&gt;更多调试命令可以参考 OpenOCD 和 GDB 的&lt;a href=&quot;https://openocd.org/doc/html/General-Commands.html&quot;&gt;文档&lt;/a&gt;和&lt;a href=&quot;https://sourceware.org/gdb/current/onlinedocs/gdb/&quot;&gt;手册&lt;/a&gt;。&lt;/p&gt;

&lt;h2 id=&quot;参考资料&quot;&gt;参考资料&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://developer.arm.com/documentation/ka006096/latest/&quot;&gt;How to Connect and Debug a Raspberry Pi 5 Bare Metal - ARM Developer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>【阅板无数】（Intel x86 IoT系列）Intel Quark D2000 复活记</title>
   <link href="https://icing.fun/posts/intel_quark_d2000.html"/>
   <updated>2025-06-01T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/intel_quark_d2000</id>
   <content type="html">&lt;p&gt;&lt;img src=&quot;../img/post/2025/06/01/intel-quark-microcontroller-dev-kit-d2000-development-kit-with-intel-quark-d2000-microcontroller.png&quot; alt=&quot;d2000&quot; width=&quot;50%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;书接上回&lt;a href=&quot;https://icing.fun/2024/01/20/intel_genuino_101/&quot;&gt;【阅板无数】（Intel x86 IoT系列）Intel Arduino/Genuino 101 简单测评&lt;/a&gt;，我们讲到在2015年1月的时候，Intel “积极”拥抱开源硬件，推出了基于 Quark SoC 的 Arduino/Genuino 101 开发板。（其实英特尔在2013年就在英特尔论坛上推出了 Quark 系列的 32 位 x86 架构微控制器，很可惜在2019年1月英特尔宣布停止Quark系列产品的生产。）&lt;/p&gt;

&lt;h2 id=&quot;前言&quot;&gt;前言&lt;/h2&gt;

&lt;p&gt;站在后人的角度看待英特尔在 IoT 领域的尝试，英特尔的确是有点“心有余而力不足”，倒也不至于全产品线沦落到“出师未捷身先死”的地步。其第一款产品是单核心 32 纳米 &lt;a href=&quot;https://www.intel.com/content/www/us/en/products/sku/79084/intel-quark-soc-x1000-16k-cache-400-mhz/specifications.html&quot;&gt;X1000&lt;/a&gt; SoC，应用在 Intel Galileo 开发板上。Intel Galileo 是基于 Intel x86 架构的 Arduino 认证开发板系列中的第一款，专为创客和教育社区而设计。&lt;/p&gt;

&lt;p&gt;单凭这第一款产品可以看出来英特尔是想要积极拥抱开源硬件吗？如拥，用过这玩意儿的都知道，这个还要单独供电，核心非常烫手。（关于这款板子后续会有文章介绍，今天我们着重介绍 Quark D2000。）&lt;/p&gt;

&lt;p&gt;这款代号为“薄荷峡谷（Mint Valley）”的 Intel Quark D2000 SoC 是英特尔在2015年Q3季度推出的产品，应用在 Intel Quark Microcontroller D2000 开发板上。它是英特尔在 IoT 领域的又一次尝试，旨在提供一个低功耗、低成本的解决方案，适用于物联网设备和嵌入式应用。&lt;/p&gt;

&lt;p&gt;同时，Quark 系列也补全了英特尔在嵌入式微控制器领域的产品线。商用的 Xeon，消费级的 Core/Pentium/Celeron 系列，移动端的 Atom 系列，嵌入式的 Quark 系列。自此，英特尔补完了在微电子领域的产品线。&lt;s&gt;EE补完计划&lt;/s&gt;&lt;/p&gt;

&lt;h2 id=&quot;规格&quot;&gt;规格&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;产品名称&lt;/th&gt;
      &lt;th&gt;Intel Quark D2000 Series&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;代号&lt;/td&gt;
      &lt;td&gt;Mint Valley&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;32 位 i586&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;32 MHz&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;L1 Cache&lt;/td&gt;
      &lt;td&gt;0 KB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;GPIO&lt;/td&gt;
      &lt;td&gt;SPI, I2C, GPIO, SPI, Comparators, ADC, PWM, DMA&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;UART&lt;/td&gt;
      &lt;td&gt;2 个 UART&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;封装&lt;/td&gt;
      &lt;td&gt;LQFN40&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;描述&lt;/td&gt;
      &lt;td&gt;32位，单核单线程，Pentium ISA 兼容微控制器&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;详细规格可以参考&lt;a href=&quot;https://www.intel.com/content/www/us/en/products/sku/91947/intel-quark-microcontroller-d2000/specifications.html&quot;&gt;此处&lt;/a&gt;&lt;a href=&quot;#jump1&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;有意思的是，虽然写的是 Pentium ISA 兼容微控制器，但是它不支持 SIMD 或 x87 浮点。（玩过 8087 的都知道，8087 是 Intel 的第一个浮点协处理器。这玩意儿运行起来十分烫手，估计是因为功耗原因没加入 x87 浮点指令集。）&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2025/06/01/IntelQuarkD2000-Fig1.webp&quot; alt=&quot;d2000 fig&quot; width=&quot;50%&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;结语&quot;&gt;结语&lt;/h2&gt;

&lt;p&gt;不过这款产品还是非常能打的，站在软件开发的角度来看，英特尔其实是想把在 CPU 端的开发经验带到嵌入式领域。毕竟到了2015年，英特尔在 CPU 领域已经有了几十年的积累，x86 架构的微控制器可以让开发者更容易地使用现有的 x86 工具链和软件库，从而降低了开发门槛。&lt;/p&gt;

&lt;p&gt;但是这样也有缺点，英特尔历史包袱太重，放不下庞大的PC/商用市场，或者说英特尔只是想在 Maker 社区和开源硬件社区赚一波快钱。这款产品从发布到生命周期结束，英特尔都没有好好对待。首先就是开发平台就只能使用 Intel System Studio for Microcontrollers，完全看不出英特尔拥抱开源硬件的诚意（特别是 Arduino 授权，用 Arduino Uno 的 Pinout 但是不支持 Arduino IDE）。&lt;/p&gt;

&lt;p&gt;反观 Nordic 和 Espressif 的产品，Nordic 的 nRF 系列和 Espressif 的 ESP 系列都提供了丰富的开源支持和社区资源，尤其是 Arduino，开发者可以轻松上手（Arduino 确实是为打破壁垒做出巨大贡献，让很多非电子专业的人们可以快速开发自己想要的东西）。而英特尔的 Quark D2000 开发板在这方面就显得将这些需求置若罔闻。&lt;/p&gt;

&lt;p&gt;很重要的一点就是拥抱开源社区其实是在培养用户粘性，就好比 Espressif 的 ESP 系列产品，提供了丰富的开源支持和社区资源，尤其是 Arduino 生态系统。开发者可以轻松上手，快速开发出各种物联网应用。如果需要开发更复杂的应用，还可以使用 ESP-IDF（Espressif IoT Development Framework）进行更底层的开发。&lt;/p&gt;

&lt;p&gt;也可能是因为时任英特尔 CEO 的布莱恩·科再奇（Brian Krzanich） &lt;s&gt;对下属十分热情&lt;/s&gt; 对开源硬件的热情不够，导致英特尔在这方面的投入和支持力度不足。也可能是他在任期间，因为其战略决定，导致英特尔在研发10纳米制程芯片的进度上相比台积电及三星都要缓慢，导致市场占有率被竞争对手超微所蚕食。&lt;a href=&quot;#jump2&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Verge 还提到，英特尔虽然以 PC 和服务器而闻名，但其业务已被智能手机和云颠覆，而该公司似乎对人工智能和自动驾驶汽车的兴起毫无察觉。英特尔承诺推出智能耳机、英特尔驱动的智能手表、智能眼镜、英特尔电视服务、搭载英特尔芯片的无人机和自动驾驶汽车，但英特尔大约 85% 的收入仍然来自其服务器和 PC 工作。近年来，英特尔曾多次试图在 CES 上通过华丽的主题演讲重新定位自己，但这些努力没有说服力，也缺乏重点。&lt;/p&gt;

&lt;p&gt;站在开源硬件的角度，英特尔同样不受待见。Arduino 社区从未接受 Curie，随着 Linux 驱动的 Raspberry Pi 越来越主导低端黑客板卡领域，Arduino 兼容性变得不再是必备功能。对于英特尔试图通过其 Curie 吸引的豪华智能手表供应商来说，这当然没有多大意义。&lt;/p&gt;

&lt;p&gt;x86 社区也没有太多考虑 Quark。由于 Quark 最初仅宣布与 Pentium ISA 兼容，因此它的进展最初放缓了。当 Intel 添加 x86 兼容性时，为时已晚&lt;a href=&quot;#jump3&quot;&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;时任 LinkedIn 半导体销售和营销小组的主持人 Bill Giovino&lt;a href=&quot;#jump4&quot;&gt;&lt;sup&gt;4&lt;/sup&gt;&lt;/a&gt; 评价 Intel Quark D2000 的文章中提到：&lt;em&gt;如今，似乎每家半导体公司都有用于物联网 （IoT） 的微控制器解决方案。我们看到了来自通常内核供应商的低功耗、高性能和高集成度微控制器的规格。但是，当英特尔宣布将重新进入微控制器业务，推出用于物联网的 32 位 x86 MCU 时，就像雷神拿起锤子再次参加比赛一样。&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;注：英特尔最早的产品是3101 SRAM，英特尔第一款微控制器是基于哈佛架构的 Intel 8048/MCS-48（1976年），其衍生版本就有著名的 8051，也就是51单片机。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;只可惜，在死神面前，雷神的锤子不堪一击，甚至连锤子都被捏的粉碎。&lt;/p&gt;

&lt;h2 id=&quot;复活雷神的锤子&quot;&gt;&lt;s&gt;复活雷神的锤子&lt;/s&gt;&lt;/h2&gt;

&lt;p&gt;上面提到了，这款产品没有适配 Arduino IDE，所以我们需要使用 Intel System Studio for Microcontrollers 来编译和烧录程序。&lt;/p&gt;

&lt;p&gt;可笑的是，英特尔在2019年1月宣布停止Quark系列产品的生产和支持，这意味着 Intel System Studio for Microcontrollers 也不再更新了。甚至 Intel System Studio for Microcontrollers 的下载链接都失效了。英特尔只保留了 Quark D2000 的数据手册、规格说明书和一些指南。&lt;/p&gt;

&lt;p&gt;Quark D2000 Dev Platform的一些官方和三方链接我贴在此处：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.intel.com/content/www/us/en/developer/articles/guide/intel-quark-microcontroller-developer-kit-d2000-getting-started-for-windows.html&quot;&gt;Intel® Quark™ Microcontroller Developer Kit D2000 – Getting Started for Windows* - Intel&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.intel.com/content/www/us/en/developer/articles/technical/d2000-button-and-led.html#_Toc453769087&quot;&gt;Add a Button and LED to Your Intel® Quark™ Microcontroller Developer Kit D2000 - Intel&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.intel.cn/content/www/cn/zh/developer/articles/technical/the-qmsi-pin-name-and-pin-map-of-intel-quark-microcontroller-d2000-crb.html&quot;&gt;The QMSI Pin Name and Pin Map of Intel® Quark™ Microcontroller D2000 CRB - Intel&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.instructables.com/Blink-LED-Test-on-Intel-Quark-D2000-Development-Bo/&quot;&gt;Blink LED Test on Intel Quark D2000 Development Board - Autodesk Instructables&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://web.archive.org/web/20170521234453/http://makerpro.cc/2017/05/the-introduction-of-quark-d2000/&quot;&gt;【X86 MCU】安裝Quark D2000開發環境 作者：何信昱 - MakerPro&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.sharetechnote.com/html/Intel_Quark_SoftwareInstallation.html&quot;&gt;Embedded System - Intel Quark - ShareTechnote&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.allaboutcircuits.com/projects/the-quark-d2000-development-board-moving-beyond-hello-world/&quot;&gt;The Quark D2000 Development Board: Moving Beyond “Hello World” - All About Circuits&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;上面难得有点用的应该也就是第 3 个链接了。防止英特尔下架，我贴在我这里：&lt;/p&gt;

&lt;h4 id=&quot;pin-map&quot;&gt;Pin Map&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2025/06/01/d2000-pinmap-681526.png&quot; alt=&quot;pinmap&quot; width=&quot;50%&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;pin-name&quot;&gt;Pin Name&lt;/h4&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cm&quot;&gt;/**
    * External Pad pin identifiers
   **/&lt;/span&gt; 

    &lt;span class=&quot;n&quot;&gt;QM_PIN_ID_0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;cm&quot;&gt;/**&amp;lt; Pin id 0. */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QM_PIN_ID_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;cm&quot;&gt;/**&amp;lt; Pin id 1. */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QM_PIN_ID_2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;cm&quot;&gt;/**&amp;lt; Pin id 2. */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QM_PIN_ID_3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;cm&quot;&gt;/**&amp;lt; Pin id 3. */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QM_PIN_ID_4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;cm&quot;&gt;/**&amp;lt; Pin id 4. */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QM_PIN_ID_5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;cm&quot;&gt;/**&amp;lt; Pin id 5. */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QM_PIN_ID_6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;cm&quot;&gt;/**&amp;lt; Pin id 6. */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QM_PIN_ID_7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;cm&quot;&gt;/**&amp;lt; Pin id 7. */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QM_PIN_ID_8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;cm&quot;&gt;/**&amp;lt; Pin id 8. */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QM_PIN_ID_9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;cm&quot;&gt;/**&amp;lt; Pin id 9. */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QM_PIN_ID_10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/**&amp;lt; Pin id 10. */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QM_PIN_ID_11&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/**&amp;lt; Pin id 11. */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QM_PIN_ID_12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/**&amp;lt; Pin id 12. */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QM_PIN_ID_13&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/**&amp;lt; Pin id 13. */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QM_PIN_ID_14&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/**&amp;lt; Pin id 14. */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QM_PIN_ID_15&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/**&amp;lt; Pin id 15. */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QM_PIN_ID_16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/**&amp;lt; Pin id 16. */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QM_PIN_ID_17&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/**&amp;lt; Pin id 17. */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QM_PIN_ID_18&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/**&amp;lt; Pin id 18. */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QM_PIN_ID_19&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/**&amp;lt; Pin id 19. */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QM_PIN_ID_20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/**&amp;lt; Pin id 20. */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QM_PIN_ID_21&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/**&amp;lt; Pin id 21. */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QM_PIN_ID_22&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/**&amp;lt; Pin id 22. */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QM_PIN_ID_23&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/**&amp;lt; Pin id 23. */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QM_PIN_ID_24&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/**&amp;lt; Pin id 24. */&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/**
 * Pin function type. (Mode 0 ~ Mode 3)
 */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QM_PMUX_FN_0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* Mode 0 */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QM_PMUX_FN_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* Mode 1 */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QM_PMUX_FN_2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* Mode 2 */&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;QM_PMUX_FN_3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* Mode 3 */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;example&quot;&gt;Example&lt;/h4&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cm&quot;&gt;/* Mux out STDOUT_UART tx/rx pins and enable input for rx. */&lt;/span&gt;
   &lt;span class=&quot;err&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;qm_pmux_select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QM_PIN_ID_12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QM_PMUX_FN_2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;  &lt;/span&gt; &lt;span class=&quot;err&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;qm_pmux_select&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QM_PIN_ID_13&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QM_PMUX_FN_2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;  &lt;/span&gt; &lt;span class=&quot;err&quot;&gt;  &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;qm_pmux_input_en&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QM_PIN_ID_13&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2025/06/01/quark-d2000-crb-schematics_page-0006.jpg&quot; alt=&quot;pinmap&quot; width=&quot;50%&quot; /&gt;
&lt;img src=&quot;../img/post/2025/06/01/quark-d2000-crb-schematics_page-0007.jpg&quot; alt=&quot;pinmap&quot; width=&quot;50%&quot; /&gt;
&lt;img src=&quot;../img/post/2025/06/01/quark-d2000-crb-schematics_page-0008.jpg&quot; alt=&quot;pinmap&quot; width=&quot;50%&quot; /&gt;
&lt;img src=&quot;../img/post/2025/06/01/quark-d2000-crb-schematics_page-0009.jpg&quot; alt=&quot;pinmap&quot; width=&quot;50%&quot; /&gt;
&lt;img src=&quot;../img/post/2025/06/01/quark-d2000-crb-schematics_page-0010.jpg&quot; alt=&quot;pinmap&quot; width=&quot;50%&quot; /&gt;
&lt;img src=&quot;../img/post/2025/06/01/quark-d2000-crb-schematics_page-0011.jpg&quot; alt=&quot;pinmap&quot; width=&quot;50%&quot; /&gt;
&lt;img src=&quot;../img/post/2025/06/01/quark-d2000-crb-schematics_page-0012.jpg&quot; alt=&quot;pinmap&quot; width=&quot;50%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;那么你现在可能有疑问：IDE 都没有了，还有编译环境吗？有的，兄弟，有的。我们自己手动编译 IAMCU i586 的工具链。&lt;/p&gt;

&lt;h3 id=&quot;手动编译-iamcu-i586-的工具链&quot;&gt;手动编译 IAMCU i586 的工具链&lt;/h3&gt;

&lt;p&gt;英特尔十分难得地提供了 &lt;a href=&quot;https://github.com/quark-mcu&quot;&gt;The Intel Quark MCUs Software Stack&lt;/a&gt;。在 QMSI（Quark Microcontroller Software Interface）中，英特尔提供了一个名为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qmsi&lt;/code&gt; 的目录，其中包含了 Quark D2000 和 SE C1000 的驱动和库。具体参照&lt;a href=&quot;https://github.com/quark-mcu/qmsi/tree/d311fd6d16d8385c67b9e5a3310ed6f4f098b023&quot;&gt;此链接&lt;/a&gt;。在自述文件中提到：&lt;/p&gt;

&lt;p&gt;&lt;em&gt;您必须首先设置 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IAMCU_TOOLCHAIN_DIR&lt;/code&gt; 环境变量。 假设工具链被解压为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$HOME/issm_2016/&lt;/code&gt; 并且 您可以在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$HOME/issm_2016/tools/compiler/gcc-ia/5.2.1/bin&lt;/code&gt; 中找到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i586-intel-elfiamcu-gcc&lt;/code&gt; ……&lt;/em&gt;&lt;/p&gt;

&lt;s&gt;这不禁让人兴奋起来&lt;/s&gt;
&lt;p&gt;敢情英特尔还是定制了一个 i586 的交叉编译工具链。理得佢咁多，先搞一个试试。&lt;/p&gt;

&lt;h4 id=&quot;环境&quot;&gt;环境&lt;/h4&gt;

&lt;p&gt;我用的是 &lt;a href=&quot;https://releases.ubuntu.com/18.04/ubuntu-18.04.6-live-server-amd64.iso&quot;&gt;Ubuntu Server 18.04.6 LTS&lt;/a&gt;，安装了以下依赖：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt update
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;build-essential git cmake gcc-multilib g++-multilib python3-pip
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这环境属实是东雪莲它妈给东雪莲开门——罕见到家了。&lt;/p&gt;

&lt;p&gt;接着需要获取 QMSI，这是 Intel 官方早期为 Quark D2000 提供的裸机驱动层，包含 GPIO、UART、RTC、I2C 等外设支持：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone https://github.com/quark-mcu/qmsi.git
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;qmsi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;接着是编译和安装交叉编译工具链。Intel 官方推荐的工具链是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i586-intel-elfiamcu-gcc&lt;/code&gt;，不过因为你完全不可能下到原始安装包，所以我们需要手动编译。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;TARGET&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;i586-elf
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PREFIX&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/opt/cross

&lt;span class=&quot;c&quot;&gt;# 下载 Binutils 和 GCC 源码&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; ~/quark-toolchain &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/quark-toolchain
wget https://ftp.gnu.org/gnu/binutils/binutils-2.36.tar.gz
wget https://ftp.gnu.org/gnu/gcc/gcc-10.2.0/gcc-10.2.0.tar.gz

&lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-xvf&lt;/span&gt; binutils-2.36.tar.gz
&lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-xvf&lt;/span&gt; gcc-10.2.0.tar.gz
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;gcc-10.2.0
./contrib/download_prerequisites
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ..

&lt;span class=&quot;c&quot;&gt;# 构建 binutils&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;mkdir &lt;/span&gt;build-binutils &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;build-binutils
../binutils-2.36/configure &lt;span class=&quot;nt&quot;&gt;--target&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$TARGET&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--prefix&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PREFIX&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--disable-nls&lt;/span&gt;
make &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;nproc&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;make &lt;span class=&quot;nb&quot;&gt;install
cd&lt;/span&gt; ..

&lt;span class=&quot;c&quot;&gt;# 构建 gcc（只要 C）&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;mkdir &lt;/span&gt;build-gcc &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;build-gcc
../gcc-10.2.0/configure &lt;span class=&quot;nt&quot;&gt;--target&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$TARGET&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--prefix&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PREFIX&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--disable-nls&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--enable-languages&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;c &lt;span class=&quot;nt&quot;&gt;--without-headers&lt;/span&gt;
make all-gcc &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;nproc&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
make all-target-libgcc &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;nproc&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;make install-gcc
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;make install-target-libgcc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;添加交叉编译工具链到 PATH：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/opt/cross/bin:&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;检查是否安装成功：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;i586-elf-gcc &lt;span class=&quot;nt&quot;&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;现在环境才搭一半，工具链是“裸机”版本（newlib 或 newlib-nano 未安装或未连接），无法找到标准 C 头文件，如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stdio.h&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stdlib.h&lt;/code&gt; 等。我们需要安装 newlib。&lt;/p&gt;

&lt;p&gt;首先下载 newlib 源码：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone https://sourceware.org/git/newlib-cygwin.git
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;newlib-cygwin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;构建并安装 newlib：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;mkdir &lt;/span&gt;build &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;build
../configure &lt;span class=&quot;nt&quot;&gt;--target&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;i586-elf &lt;span class=&quot;nt&quot;&gt;--prefix&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/opt/cross
make all &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;nproc&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
make &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# 如果安装失败，请尝试&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo env&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;PATH=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; make &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;接着就是魔改 QMSI 的文件。定位到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qmsi&lt;/code&gt; 根目录下的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;base.mk&lt;/code&gt; ，修改以下内容：&lt;/p&gt;

&lt;div class=&quot;language-makefile highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;### Tools
#PREFIX ?= arc-elf32
#TOOLCHAIN_DIR=$(ARCMCU_TOOLCHAIN_DIR)
#else
#PREFIX ?= i586-intel-elfiamcu
#TOOLCHAIN_DIR=$(IAMCU_TOOLCHAIN_DIR)
#endif
&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;TOOLCHAIN_DIR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dir&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;$(&lt;/span&gt;CROSS_COMPILE&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;PREFIX&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;$(&lt;/span&gt;notdir &lt;span class=&quot;p&quot;&gt;$(&lt;/span&gt;CROSS_COMPILE&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;CFLAGS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-Wno-error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;implicit-fallthrough

&lt;span class=&quot;err&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;.&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;ifeq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;($(TARGET), sensor)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;CFLAGS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-DQM_SENSOR&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;CFLAGS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-ffreestanding&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;CFLAGS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-mARCv2EM&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-mav2em&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-mno-sdata&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;LDFLAGS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-nostartfiles&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;LDLIBS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-lc&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-lgcc&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#LDLIBS += -lc -lnosys -lsoftfp -lgcc
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LDLIBS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-lc&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-lgcc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;最后是编译，我们尝试编译一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blinky&lt;/code&gt;：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;unset &lt;/span&gt;IAMCU_TOOLCHAIN_DIR
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~/qmsi/examples/blinky
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;CROSS_COMPILE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/opt/cross/bin/i586-elf
make &lt;span class=&quot;nv&quot;&gt;TARGET&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;x86 &lt;span class=&quot;nv&quot;&gt;SOC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;quark_d2000 &lt;span class=&quot;nv&quot;&gt;V&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;编译成功后会在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;release/quark_d2000/x86/bin/blinky.bin&lt;/code&gt;。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;注意：如果编译时候遇到编译器抛出 switch-case 函数错误 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;error: this statement may fall through [-Werror=implicit-fallthrough=]&lt;/code&gt; 的时候，请定位到报错行下方添加 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__attribute__((fallthrough));&lt;/code&gt;。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4 id=&quot;烧录&quot;&gt;烧录&lt;/h4&gt;

&lt;p&gt;非常幸运的是，这个板子自带 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FTDI FT232HL&lt;/code&gt; USB 转串口芯片，所以我们可以直接使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OpenOCD&lt;/code&gt; 来烧录。&lt;/p&gt;

&lt;p&gt;首先，如果你用的是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Windows&lt;/code&gt; 系统，需要下载 &lt;a href=&quot;https://zadig.akeo.ie/&quot;&gt;Zadig&lt;/a&gt; 工具，将 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FT232HL&lt;/code&gt; 的驱动安装为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WinUSB&lt;/code&gt;。如果你用的是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Linux&lt;/code&gt; 系统，通常不需要额外安装驱动。&lt;/p&gt;

&lt;p&gt;我们需要下载英特尔提供的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OpenOCD&lt;/code&gt; 副本。点击&lt;a href=&quot;https://github.com/intel/OpenOCD/releases/tag/0.9-0.1&quot;&gt;此处&lt;/a&gt;下载对应操作系统的版本。解压后，进入 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scripts&lt;/code&gt; 目录。&lt;/p&gt;

&lt;p&gt;接着从 &lt;a href=&quot;https://github.com/intel/OpenOCD&quot;&gt;Intel/OpenOCD&lt;/a&gt; 仓库中，定位到 &lt;a href=&quot;https://github.com/intel/OpenOCD/tree/master/tcl/board&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tcl/board/&lt;/code&gt;&lt;/a&gt; 目录，找到 &lt;a href=&quot;https://github.com/intel/OpenOCD/blob/master/tcl/board/quark_d2000.cfg&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;quark_d2000.cfg&lt;/code&gt;&lt;/a&gt; 和 &lt;a href=&quot;https://github.com/intel/OpenOCD/blob/master/tcl/board/quark_d2000_onboard.cfg&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;quark_d2000_onboard.cfg&lt;/code&gt;&lt;/a&gt; 两个文件，下载到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$Intel_OpenOCD/scripts/board/&lt;/code&gt; 目录下。然后定位到 &lt;a href=&quot;https://github.com/intel/OpenOCD/tree/master/tcl/target&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tcl/target/&lt;/code&gt;&lt;/a&gt; 目录，找到 &lt;a href=&quot;https://github.com/intel/OpenOCD/blob/master/tcl/target/quark_d2000.cfg&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;quark_d2000.cfg&lt;/code&gt;&lt;/a&gt; 文件，下载到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$Intel_OpenOCD/scripts/target/&lt;/code&gt; 目录下。&lt;/p&gt;

&lt;p&gt;现在我们通过命令行/终端进入到 OpenOCD 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bin&lt;/code&gt; 目录下。&lt;/p&gt;

&lt;p&gt;我们还需要下载 Quark D2000 的 Bootloader。点击&lt;a href=&quot;https://github.com/quark-mcu/qm-bootloader/releases/tag/v1.3.0&quot;&gt;此处&lt;/a&gt;下载 1.3.0 版本的 Bootloader。&lt;/p&gt;

&lt;p&gt;因为我准备在 Windows 上刷板子，所以还需要使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scp&lt;/code&gt; 命令将 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blinky.bin&lt;/code&gt; 复制到 OpenOCD 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bin&lt;/code&gt; 目录下。&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;scp.exe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tomato&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;192.168.56.108:/home/tomato/qmsi/examples/blink/release/quark_d2000/x86/bin/blinky.bin&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;/blinky.bin&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;我们现在就可以通过 OpenOCD 来烧录了。&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;\openocd.exe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;\scripts\board\quark_d2000_onboard.cfg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;flash_rom quark_d2000_rom.bin 0&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;\openocd.exe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;\scripts\board\quark_d2000_onboard.cfg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;flash_rom blinky.bin 0x00180000&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如果是 Linux 系统，可以参考&lt;a href=&quot;https://www.mouser.com/pdfdocs/system-studio-getting-started-guide.pdf&quot;&gt;此处&lt;/a&gt;第24页，命令类似：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;./openocd &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; ../scripts/board/quark_d2000_onboard.cfg &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;init&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;flash_rom quark_d2000_rom.bin&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;shutdown&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在看到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;All done&lt;/code&gt;的时候按下复位键，蓝色的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;USR&lt;/code&gt; LED 会每隔 0.25s 闪烁一下，表示烧录成功。&lt;/p&gt;

&lt;p&gt;或者是配合 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gdb&lt;/code&gt; 调试。先在 OpenOCD 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bin&lt;/code&gt; 目录下执行：&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;\openocd.exe&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;\scripts\board\quark_d2000_onboard.cfg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;就会显示如下信息：&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;Open&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;On-Chip&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Debugger&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;0.8.0-dev-ga422c7e&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2016&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-05-23-16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;57&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Licensed&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;under&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;GNU&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;GPL&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;For&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bug&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;reports&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;http://openocd.sourceforge.net/doc/doxygen/bugs.html&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Info&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;only&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;one&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;transport&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;option&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;autoselect&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;jtag&apos;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;adapter&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;speed:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;kHz&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;trst_only&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;separate&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;trst_push_pull&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;adapter&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;speed:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;kHz&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;trst_only&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;separate&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;trst_push_pull&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Info&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;clock&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;speed&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;kHz&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Info&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;JTAG&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tap:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;quark_d2000.cltap&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tap/device&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;found:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;0x0e786013&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mfg:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;0x009&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;part:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;0xe786&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ver:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;0x0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Enabling&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lmt&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;core&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tap&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Info&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;JTAG&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tap:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;quark_d2000.lmt&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;接着打开另一个终端，执行：&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;gbd&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如果在 Windows 上运行前提是你得安装好 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MSYS2&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;然后在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gdb&lt;/code&gt; 中输入：&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gdb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;remote&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;3333&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;接着输入以下命令来烧录程序：&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gdb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;monitor&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;reset&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;halt&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gdb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;monitor&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;load_image&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;blinky.bin&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;0x00180000&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gdb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;monitor&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;reset&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2025/06/01/quark_d2000.gif&quot; alt=&quot;d2000&quot; width=&quot;50%&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;配置-zephyr-rtos&quot;&gt;配置 Zephyr RTOS&lt;/h3&gt;

&lt;p&gt;(2025-06-02 更新)&lt;/p&gt;

&lt;p&gt;Zephyr RTOS 是一个开源的实时操作系统，支持多种硬件平台，包括 Intel Quark D2000。我们可以使用 Zephyr 来开发更复杂的应用。&lt;/p&gt;

&lt;p&gt;但是我们不能用最新的 Zephyr 版本，因为 Quark D2000 的支持在 Zephyr 2.0 之后被移除。我们需要使用 Zephyr 1.14.0 版本 和 SDK 0.10.0 版本。&lt;/p&gt;

&lt;h4 id=&quot;环境准备&quot;&gt;环境准备&lt;/h4&gt;

&lt;p&gt;回到 Ubuntu Server 18.04.6 LTS 环境，安装 Zephyr 所需的依赖：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get update
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--no-install-recommends&lt;/span&gt; git cmake ninja-build gperf &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  ccache dfu-util device-tree-compiler wget &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  python3-pip python3-setuptools python3-wheel xz-utils file make gcc &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
  gcc-multilib
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Zephyr 需要CMake 版本 3.13.1 或更高版本。但是 Ubuntu 18.04 默认的 CMake 版本是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3.10.2&lt;/code&gt;，我们需要手动安装最新版本的 CMake：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt purge cmake
python3 &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; pip &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--upgrade&lt;/span&gt; pip
python3 &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;scikit-build&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;0.14.0
python3 &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;cmake
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;安装完之后可能会遇到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARNING: The scripts cmake, cpack and ctest are installed in &apos;/home/tomato/.local/bin&apos; which is not on PATH.&lt;/code&gt; 的警告。我们需要将其添加到 PATH 中：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$HOME&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/.local/bin:&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;export PATH=&quot;$HOME/.local/bin:$PATH&quot;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
&lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;最后我们需要安装 安装 Zephyr 软件开发工具包 （SDK）：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.10.0/zephyr-sdk-0.10.0-setup.run
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &amp;lt;sdk download directory&amp;gt;
sh zephyr-sdk-0.10.0-setup.run
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;导出 Zephyr SDK 的环境变量，默认位置在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/opt/zephyr-sdk/&lt;/code&gt;：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ZEPHYR_TOOLCHAIN_VARIANT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;zephyr
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ZEPHYR_SDK_INSTALL_DIR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&amp;lt;sdk installation directory&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;下载-zephyr-源码&quot;&gt;下载 Zephyr 源码&lt;/h4&gt;

&lt;p&gt;使用 Bootstrap West 工具来下载 Zephyr 源码：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;python3 &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; pip &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;west
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;我们需要指定 Zephyr 的版本为 1.14.0：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;west init zephyrproject &lt;span class=&quot;nt&quot;&gt;--mr&lt;/span&gt; v1.14.0
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;zephyrproject
west update
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;安装-python-依赖项&quot;&gt;安装 Python 依赖项&lt;/h4&gt;

&lt;p&gt;Zephyr 需要一些 Python 依赖项，我们可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pip&lt;/code&gt; 来安装：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;python3 &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; pip &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; zephyr/scripts/requirements.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如果你在安装过程中遇到依赖项问题，可以把 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zephyr/scripts/requirements.txt&lt;/code&gt; 中 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hub==2.0&lt;/code&gt; 改成 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hub==2.0.9&lt;/code&gt;。&lt;/p&gt;

&lt;h4 id=&quot;构建应用程序&quot;&gt;构建应用程序&lt;/h4&gt;

&lt;p&gt;导航到主项目目录：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;zephyrproject/zephyr
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;设置环境：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;source &lt;/span&gt;zephyr-env.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;构建 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;blinky&lt;/code&gt; 示例应用程序：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;samples/basic/blinky
west build &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt; quark_d2000_crb &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;构建完成后会在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build/zephyr/zephyr.bin&lt;/code&gt; 生成二进制文件。烧录方式和上面类似。烧录成功后按下复位键，蓝色的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;USR&lt;/code&gt; LED 会每隔 1s 闪烁一下，表示烧录成功。&lt;/p&gt;

&lt;p&gt;可以参照&lt;a href=&quot;https://docs.zephyrproject.org/1.14.0/getting_started/index.html#&quot;&gt;Zephyr 1.14.0 官方文档&lt;/a&gt;来了解更多关于 Zephyr 的信息。&lt;/p&gt;

&lt;h2 id=&quot;完成&quot;&gt;完成&lt;/h2&gt;

&lt;p&gt;至此，我们在失去官方工具链的情况下成功复活了这个板子。&lt;/p&gt;

&lt;h2 id=&quot;补记-2026-01-22-更新&quot;&gt;补记 （2026-01-22 更新）&lt;/h2&gt;

&lt;p&gt;回顾一个我经常浏览的网站&lt;a href=&quot;https://steward-fu.github.io/website/mcu.htm#d2000&quot;&gt;司徒的教學網站 - MCU - Intel Quark D2000&lt;/a&gt;，发现了司徒大佬早在2024年就发布了一个 Intel Quark D2000 的&lt;a href=&quot;https://github.com/steward-fu/website/releases/tag/d2000&quot;&gt;开发包&lt;/a&gt;，里面包含了编译所需工具。可以直接下载使用，省去了我们手动编译工具链的麻烦。&lt;/p&gt;

&lt;h2 id=&quot;引用&quot;&gt;引用&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;span id=&quot;jump1&quot;&gt;&lt;a href=&quot;https://www.intel.com/content/www/us/en/products/sku/91947/intel-quark-microcontroller-d2000/specifications.html&quot;&gt;Intel® Quark™ Microcontroller D2000 - Intel&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
  &lt;li&gt;&lt;span id=&quot;jump2&quot;&gt;&lt;a href=&quot;https://web.archive.org/web/20201205135803/https://www.theverge.com/2018/6/22/17492184/intel-future-ceo-brian-krzanich-resignation-2018&quot;&gt;Warren, Tom. Intel now faces a fight for its future. The Verge. 2018-06-22 [2020-11-26]. （原始内容存档于2020-12-05） &lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
  &lt;li&gt;&lt;span id=&quot;jump3&quot;&gt;&lt;a href=&quot;https://linuxgizmos.com/who-killed-the-quark/&quot;&gt;Who killed the Quark? by Eric Brown - LinuxGizmos.com&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
  &lt;li&gt;&lt;span id=&quot;jump4&quot;&gt;&lt;a href=&quot;https://www.mouser.com/applications/Intel-Quark-Internet-of-Things-MCU/&quot;&gt;The Intel Quark®™ Microcontroller: Why an x86 MCU is The Right Stuff for The Internet of Things, By Bill Giovino - Mouser Electornics&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>【Linux 从入门到重修C语言】系统调用的一种奇技淫巧</title>
   <link href="https://icing.fun/posts/system_call.html"/>
   <updated>2025-05-20T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/system_call</id>
   <content type="html">&lt;p&gt;今天&lt;s&gt;手欠&lt;/s&gt;手滑在赋权的时候把 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chmod&lt;/code&gt; 的权限改成了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;000&lt;/code&gt;，就在想怎么解决。&lt;/p&gt;

&lt;p&gt;突然灵光乍现，没有 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chmod&lt;/code&gt; 程序不是还有 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chmod()&lt;/code&gt; 系统调用么，直接写个 C 代码改一下就完事了：&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;sys/stat.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;chmod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;/usr/bin/chmod&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0755&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;编译后直接执行就可以了。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gcc ./mian.c &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; ./a.out
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;参考&lt;a href=&quot;https://man7.org/linux/man-pages/man2/chmod.2.html&quot;&gt;此处&lt;/a&gt;。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;NAME
       chmod, fchmod, fchmodat - change permissions of a file
LIBRARY
       Standard C library (libc, -lc)
SYNOPSIS
       #include &amp;lt;sys/stat.h&amp;gt;

       int chmod(const char *pathname, mode_t mode);
       int fchmod(int fd, mode_t mode);

       #include &amp;lt;fcntl.h&amp;gt;           /* Definition of AT_* constants */
       #include &amp;lt;sys/stat.h&amp;gt;

       int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;那有大聪明问了，如果 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc&lt;/code&gt; 也 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;000&lt;/code&gt; 了怎么办？&lt;/p&gt;

&lt;p&gt;那直接用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cc1 + as + ld&lt;/code&gt; 组合就可以了。系统中仍然保留有 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cc1&lt;/code&gt;（GCC 的前端编译器）、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;as&lt;/code&gt;（汇编器）和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ld&lt;/code&gt;（链接器），仍可以手动完成编译流程。&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc&lt;/code&gt; 在编译过程中（比如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcc shit.c -o shit&lt;/code&gt;）实际上隐式做了如下几步：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;预处理（cpp）：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shit.c&lt;/code&gt; -&amp;gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shit.i&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;编译（cc1）：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shit.i&lt;/code&gt; -&amp;gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shit.s&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;汇编（as）：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shit.s&lt;/code&gt; -&amp;gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shit.o&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;链接（ld）：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shit.o&lt;/code&gt; -&amp;gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shit&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;当然，嫌麻烦 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clang&lt;/code&gt; 也可以。&lt;/p&gt;

&lt;p&gt;看样子想学好 Linux，得先学明白C。&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>【玩转树莓派】制作一个口袋服务器 2</title>
   <link href="https://icing.fun/posts/pocket_server_2.html"/>
   <updated>2025-05-19T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/pocket_server_2</id>
   <content type="html">&lt;p&gt;书接上回，笔者用树莓派 Zero 2 W 制作了一个口袋服务器。用起来总觉得不得劲。&lt;/p&gt;

&lt;p&gt;口袋做到了，服务器还是差很远。&lt;/p&gt;

&lt;p&gt;树莓派的系统用来玩玩还行，真正可靠性还是差点意思，有些功能还是跟服务器系统差一些。&lt;/p&gt;

&lt;p&gt;所以我想到了 &lt;a href=&quot;https://cdimage.ubuntu.com/releases/20.04/release/&quot;&gt;Ubuntu Server&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;选择&lt;a href=&quot;https://cdimage.ubuntu.com/releases/20.04/release/ubuntu-20.04.5-preinstalled-server-armhf+raspi.img.xz&quot;&gt;Preinstalled server image&lt;/a&gt;。看在口袋服务器的份上，还是选择 Hard-Float 版本的。&lt;/p&gt;

&lt;p&gt;按照常规方式烧录到TF卡上，插入树莓派，接上电源，连接串口工具，打开 PuTTY，设置波特率为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;115200&lt;/code&gt;，数据位 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;8&lt;/code&gt;，停止位 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt;，无奇偶校验。然后插入TF卡，接上电源，就可以看到树莓派的启动信息了。&lt;/p&gt;

&lt;p&gt;登录信息和树莓派OS不太一样，参考&lt;a href=&quot;https://wiki.ubuntu.com/ARM/RaspberryPi#First_boot_.28Username.2FPassword.29&quot;&gt;此处&lt;/a&gt;。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The login username is “&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ubuntu&lt;/code&gt;”, password is “&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ubuntu&lt;/code&gt;”. &lt;strong&gt;You will be asked to change the password on first login.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;连接-wi-fi&quot;&gt;连接 Wi-Fi&lt;/h2&gt;

&lt;p&gt;依旧是轻车熟路，先连个Wi-Fi。&lt;/p&gt;

&lt;p&gt;Ubuntu Server 20.04 之后的版本连接 Wi-Fi 的方式略显诡异。&lt;/p&gt;

&lt;p&gt;打开：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;nano /etc/netplan/50-cloud-init.yaml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在文件中添加以下内容：&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;network&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;ethernets&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;eth0&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;dhcp4&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;optional&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;usb0&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;dhcp4&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;no&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;addresses&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;192.168.100.2/24&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;
    &lt;span class=&quot;na&quot;&gt;wifis&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;na&quot;&gt;wlan0&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;optional&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;dhcp4&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
            &lt;span class=&quot;na&quot;&gt;access-points&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;你家Wi-Fi名称&quot;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt;
                    &lt;span class=&quot;na&quot;&gt;hidden&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
                    &lt;span class=&quot;na&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;你家Wi-Fi密码&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;保存后，执行以下命令：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;netplan apply
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;换源&quot;&gt;换源&lt;/h2&gt;

&lt;p&gt;连上Wi-Fi 之后，换源。参考&lt;a href=&quot;https://mirrors.ustc.edu.cn/help/ubuntu-ports.html&quot;&gt;此处&lt;/a&gt;。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s@//ports.ubuntu.com/\? @//ports.ubuntu.com/ubuntu-ports @g&apos;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s@//ports.ubuntu.com@//mirrors.ustc.edu.cn@g&apos;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
            /etc/apt/sources.list
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;更新软件包列表并安装-ifupdown-和-dnsmasq&quot;&gt;更新软件包列表并安装 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ifupdown&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dnsmasq&lt;/code&gt;&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt update
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt; ifupdown dnsmasq
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;配置-usb-网络&quot;&gt;配置 USB 网络&lt;/h2&gt;

&lt;p&gt;首先得让 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dnsmasq&lt;/code&gt; 监听 USB 网络接口，把原来的服务关掉。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl stop systemd-resolved
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl disable systemd-resolved
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后设置接口：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;nano /etc/network/interfaces
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后添加以下内容：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;auto lo
iface lo inet loopback

auto usb0
allow-hotplug usb0
iface usb0 inet static
        address 192.168.100.2
        netmask 255.255.255.0

allow-hotplug wlan0
iface wlan0 inet dhcp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;接下来配置 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/dnsmasq.conf&lt;/code&gt; 文件，添加以下内容：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;interface&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;usb0
dhcp-range&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;192.168.100.10,192.168.100.100,24h
dhcp-option&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;3,192.168.100.2
dhcp-option&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;6,223.5.5.5
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;新建 systemd 服务文件等待 usb0 后再启动 dnsmasq&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;nano /etc/systemd/system/dnsmasq-usb0.service
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;添加以下内容：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;Unit]
&lt;span class=&quot;nv&quot;&gt;Description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;Delayed start of dnsmasq after usb0 is up
&lt;span class=&quot;nv&quot;&gt;After&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;network-online.target
&lt;span class=&quot;nv&quot;&gt;Wants&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;network-online.target

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;Service]
&lt;span class=&quot;nv&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;simple
&lt;span class=&quot;nv&quot;&gt;ExecStartPre&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/bin/bash &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;while ! ip link show usb0 | grep -q &quot;state UP&quot;; do sleep 1; done&apos;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;ExecStart&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/sbin/dnsmasq &lt;span class=&quot;nt&quot;&gt;-k&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--conf-file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/etc/dnsmasq.conf
&lt;span class=&quot;nv&quot;&gt;Restart&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;always

&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;Install]
&lt;span class=&quot;nv&quot;&gt;WantedBy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;multi-user.target
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;保存后，执行以下命令：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl daemon-reload
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl disable dnsmasq
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl &lt;span class=&quot;nb&quot;&gt;enable&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--now&lt;/span&gt; dnsmasq-usb0.service
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;设置-swap&quot;&gt;设置 Swap&lt;/h2&gt;

&lt;p&gt;老样子，内存不够，硬盘来凑。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;fallocate &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; 512M /swapfile
&lt;span class=&quot;nb&quot;&gt;sudo chmod &lt;/span&gt;600 /swapfile
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;mkswap /swapfile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;设置开机自动挂载：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;nano /etc/fstab
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;添加以下内容：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;/swapfile none swap sw 0 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;可以直接用命令开启 swap：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;swapon /swapfile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;当然，也可以重启树莓派。&lt;/p&gt;

&lt;h2 id=&quot;结语&quot;&gt;结语&lt;/h2&gt;

&lt;p&gt;基本上每次等能连接差不多要1~2分钟，正好在猩八课插上电脑再去拿个咖啡回来就能干活了。&lt;/p&gt;

&lt;h2 id=&quot;番外&quot;&gt;番外&lt;/h2&gt;

&lt;p&gt;可以通过删除一些不需要的 Ubuntu 服务器实例来清理 软件包和禁用服务。这样可以节省一些磁盘空间并释放内存。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt purge &lt;span class=&quot;nt&quot;&gt;--auto-remove&lt;/span&gt; snapd squashfs-tools friendly-recovery apport at
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;删除无人值守升级&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt purge &lt;span class=&quot;nt&quot;&gt;--auto-remove&lt;/span&gt; unattended-upgrades
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl disable apt-daily-upgrade.timer
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl mask apt-daily-upgrade.service
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl disable apt-daily.timer
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl mask apt-daily.service
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这将删除 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unattended-upgrades&lt;/code&gt; 软件包和负责自动更新的关联服务软件包。&lt;/p&gt;

&lt;p&gt;但是有些环境不能这样，可以配置 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unattended-upgrades&lt;/code&gt; 以仅安装安全性更新。&lt;/p&gt;

&lt;p&gt;通过注释 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unattended-upgrades&lt;/code&gt; 的 apt 配置中的其他源来仅启用安全更新：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;nano /etc/apt/apt.conf.d/50unattended-upgrades
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;移除 Plymouth，我开机也不看那些花花绿绿的屏幕，直接铲了：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt purge &lt;span class=&quot;nt&quot;&gt;--auto-remove&lt;/span&gt; plymouth
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这个过程会非常长，可能需要 10 分钟或更长时间才能完成。（因为涉及到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;update-initramfs&lt;/code&gt;）&lt;/p&gt;

&lt;p&gt;删除完之后还需要修改 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/boot/firmware/cmdline.txt&lt;/code&gt; 文件，删除以下内容：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;quiet splash
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后重启树莓派。&lt;/p&gt;

&lt;h2 id=&quot;ip-转发&quot;&gt;IP 转发&lt;/h2&gt;

&lt;p&gt;晚上敲代码的时候突发奇想，这个能不能让来自 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;usb0&lt;/code&gt; 的流量转发到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wlan0&lt;/code&gt; 上呢？&lt;/p&gt;

&lt;p&gt;可以的，兄弟，可以的。&lt;/p&gt;

&lt;p&gt;首先通过编辑 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/sysctl.conf&lt;/code&gt; 文件来启用 IP 转发：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;nano /etc/sysctl.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在文件中找到以下行（找不到没关系，直接追加）：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#net.ipv4.ip_forward=1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;取消注释并将其更改为：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;net.ipv4.ip_forward&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;保存后，执行以下命令：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;sysctl &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;或者立即生效：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;sysctl &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt; net.ipv4.ip_forward&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;接下来，使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iptables&lt;/code&gt; 来设置 NAT 转发：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 让 usb0 的流量通过 wlan0 出口转发&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; nat &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; POSTROUTING &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; wlan0 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; MASQUERADE

&lt;span class=&quot;c&quot;&gt;# 允许 usb0 转发出去&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; FORWARD &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; usb0 &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; wlan0 &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;iptables &lt;span class=&quot;nt&quot;&gt;-A&lt;/span&gt; FORWARD &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; wlan0 &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; usb0 &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; state &lt;span class=&quot;nt&quot;&gt;--state&lt;/span&gt; ESTABLISHED,RELATED &lt;span class=&quot;nt&quot;&gt;-j&lt;/span&gt; ACCEPT
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;最后，保存 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iptables&lt;/code&gt; 规则，防止重启后规则丢失：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;iptables-persistent
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;netfilter-persistent save
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;整体流程如下：&lt;/p&gt;

&lt;div class=&quot;language-css highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;电脑&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--usb0--&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;树莓派&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;192&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;168&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--wlan0--&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;Wi-Fi&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;路由器&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--Internet&lt;/span&gt;
            &lt;span class=&quot;err&quot;&gt;↕&lt;/span&gt;
         &lt;span class=&quot;nt&quot;&gt;dnsmasq&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;发&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;IP&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;（192&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;168&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;.x&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;）&lt;/span&gt;
         &lt;span class=&quot;nt&quot;&gt;iptables&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;转发&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;（邪魅一笑）这样不就能在树莓派上面部署，咳咳，嗯。&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>【玩转树莓派】制作一个口袋服务器</title>
   <link href="https://icing.fun/posts/pocket_server.html"/>
   <updated>2025-05-17T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/pocket_server</id>
   <content type="html">&lt;p&gt;手头上有个闲置的树莓派 Zero 2 W，想着能不能把它做成一个口袋服务器，随时随地都能用。于是就有了这篇文章。&lt;/p&gt;

&lt;p&gt;树莓派 Zero 2 W 是一款小巧的单板计算机，搭载了四核 ARM Cortex-A53 处理器，内存为 512MB。它的体积小巧，功耗低，非常适合用作轻量级的服务器。&lt;/p&gt;

&lt;p&gt;同时支持 Wi-Fi 和蓝牙，可以方便地连接到网络。树莓派 Zero 2 W 的价格也非常亲民，适合 DIY 爱好者和学生使用。&lt;/p&gt;

&lt;p&gt;树莓派的操作系统是基于 Debian 的 Raspberry Pi OS，支持多种编程语言和开发工具，非常适合用来学习和实验。&lt;/p&gt;

&lt;p&gt;那么树莓派的优点讲完了，缺点也很明显：PWR接口和USB接口是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Micro USB&lt;/code&gt;，所以需要一个转换头。HDMI接口是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Mini HDMI&lt;/code&gt;，又要一个转换头。&lt;/p&gt;

&lt;p&gt;看了一下&lt;a href=&quot;https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#test-pad-locations&quot;&gt;官方文档&lt;/a&gt;，发现他们预留了测试点位，里面有一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;5V&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GND&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;USB_DP&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;USB_DM&lt;/code&gt; 的测试点位，直接焊接上去就可以了。这样就可以用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;USB&lt;/code&gt; 供电了。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2025/05/17/zero2-pad-diagram.png&quot; alt=&quot;pin&quot; width=&quot;50%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;如果嫌自己焊的太捞了，可以直接去搜树莓派USB转接器，这种产品多的很。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2025/05/17/pi-zero-usb-adapter-3.jpg&quot; alt=&quot;pin&quot; width=&quot;50%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;买到手装好之后就该开始配置了。&lt;/p&gt;

&lt;h2 id=&quot;烧录镜像&quot;&gt;烧录镜像&lt;/h2&gt;

&lt;p&gt;最新的树莓派64位 Lite 镜像（笔者截稿时是2025年5月13日发行的），使用会有些问题，所以我翻了一下仓库，建议下载这个镜像&lt;a href=&quot;https://downloads.raspberrypi.com/raspios_lite_arm64/images/raspios_lite_arm64-2022-01-28/2022-01-28-raspios-bullseye-arm64-lite.zip&quot;&gt;raspios_lite_arm64-2022-01-28&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;解压后直接烧录到TF卡上，然后需要修改 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/boot/config.txt&lt;/code&gt; 文件，添加以下内容：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;enable_uart&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;因为我们手边没有HDMI线，没办法接屏幕，所以需要通过配置串口来访问树莓派，这种叫法叫做 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;headless&lt;/code&gt; 模式。（很奇怪，中文翻译成 &lt;strong&gt;无头&lt;/strong&gt; 模式，实际上就是不需要任何外设来启动树莓派&lt;s&gt;开什么玩笑不是还是需要串口工具么&lt;/s&gt;）&lt;/p&gt;

&lt;p&gt;接下来我们需要从&lt;s&gt;烤箱&lt;/s&gt;里面拿出来一个串口工具，连接到树莓派的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UART&lt;/code&gt; 接口上。树莓派 Zero 2 W 的 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UART&lt;/code&gt; 接口在下面的图中可以看到（Pin1的焊盘是方形的）：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2025/05/17/GPIO-Pinout-Diagram-2.png&quot; alt=&quot;pin&quot; width=&quot;50%&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;uart-连接&quot;&gt;UART 连接&lt;/h2&gt;

&lt;p&gt;连接好之后，打开 PuTTY，设置波特率为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;115200&lt;/code&gt;，数据位 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;8&lt;/code&gt;，停止位 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt;，无奇偶校验。然后插入TF卡，接上电源，就可以看到树莓派的启动信息了。&lt;/p&gt;

&lt;p&gt;以下信息可以参阅&lt;a href=&quot;https://learn.adafruit.com/turning-your-raspberry-pi-zero-into-a-usb-gadget/ethernet-gadget&quot;&gt;Turning your Raspberry Pi Zero into a USB Gadget - Adafruit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;用户名 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pi&lt;/code&gt;，密码 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;raspberry&lt;/code&gt;。登录后可以看到树莓派的命令行界面。&lt;/p&gt;

&lt;p&gt;接着编辑config.txt &amp;amp; cmdline.txt&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;nano /boot/config.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在文件末尾添加以下内容：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;dtoverlay&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;dwc2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后编辑 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmdline.txt&lt;/code&gt; 文件：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;nano /boot/cmdline.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rootwait&lt;/code&gt; 后添加一个空格，然后键入 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;modules-load=dwc2,g_ether&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;保存并退出。&lt;/p&gt;

&lt;p&gt;然后就是熟门熟路地进入 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;raspi-config&lt;/code&gt;，设置一下 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSH&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Wi-Fi&lt;/code&gt; 的配置。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;树莓派 Zero 2 W 的 Wi-Fi 是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2.4GHz&lt;/code&gt; 的，不能连接 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;5GHz&lt;/code&gt; 的 Wi-Fi。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;配置usb网络&quot;&gt;配置USB网络&lt;/h2&gt;

&lt;p&gt;如果使用的是 Mac 或 Linux，则很可能已经安装了 Bonjour。在 Windows 上，需要安装 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iTunes&lt;/code&gt; 以添加 Bonjour 支持，以便它知道如何处理 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.local&lt;/code&gt; 名称。&lt;/p&gt;

&lt;p&gt;关闭树莓派，把USB口插到电脑上，等待树莓派启动，电脑会有设备插入的提示音。&lt;/p&gt;

&lt;p&gt;但是可怜的 Windows 会自动识别成串口设备，这时候我们 去下载&lt;a href=&quot;https://www.catalog.update.microsoft.com/Search.aspx?q=usb%5Cvid_0525%26pid_a4a2&quot;&gt;USB Ethernet/RNDIS Gadget&lt;/a&gt;的驱动，手动安装上，就能正常识别了。&lt;/p&gt;

&lt;p&gt;接下来需要配置固定IP，方便我们使用。&lt;/p&gt;

&lt;p&gt;在树莓派上执行以下命令：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;nano /etc/network/interfaces
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在文件中添加以下内容：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;allow-hotplug usb0
iface usb0 inet static
        address 192.168.100.2
        netmask 255.255.255.0
        network 192.168.100.0
        broadcast 192.168.100.255
        gateway 192.168.100.1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;保存并退出。这将为 Raspberry Pi 提供 IP 地址 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.100.2&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;然后重启网络接口&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;ifdown usb0
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;ifup usb0
ifconfig usb0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;接着回到自己的电脑，因为我是牛马的ThinkPad用户，我安装了Windows，所以我需要打开网络和共享中心，然后单击更改适配器设置。找到 RNDIS 适配器并将其重命名为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pizero&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;接着右键单击它，选择属性，然后选择 Internet 协议版本 4 (TCP/IPv4)，然后单击属性。选择使用下面的 IP 地址，并输入 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;192.168.100.1&lt;/code&gt; 作为计算机的 IP 地址和网关，子网掩码为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;255.255.255.0&lt;/code&gt; 与树莓派的相同。（网关后来被擦除了，Adafruit的作者认为Windows是自动使用IP地址，但是我认为是电脑与树莓派之间是二层设备，二层之间不需要网关）&lt;/p&gt;

&lt;h2 id=&quot;共享电脑网络&quot;&gt;共享电脑网络&lt;/h2&gt;

&lt;p&gt;打开网络和共享中心，然后单击我已经连接的网络（比如我现在连接的是Wi-Fi）去更改适配器设置。右键单击 Wi-Fi 适配器，选择属性，然后选择共享选项卡。选中允许其他网络用户通过此计算机的 Internet 连接来连接的复选框，并从下拉列表中选择 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pizero&lt;/code&gt; 适配器。然后单击确定。&lt;/p&gt;

&lt;p&gt;使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo reboot&lt;/code&gt; 重新启动树莓派，然后使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh pi@raspberrypi.local&lt;/code&gt; 通过 SSH 将其重新连接到它。可以尝试 ping 百度。&lt;/p&gt;

&lt;h2 id=&quot;ip寻址&quot;&gt;IP寻址&lt;/h2&gt;

&lt;p&gt;在我们烧录的这个版本的 Raspbian 上，所有网卡的 IP 寻址都是通过名为 dhcpcd 的程序在树莓派上完成的。但是我们现在不需要 dhcpcd，所以我们需要禁用它。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl disable dhcpcd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;blockquote&gt;
  &lt;p&gt;注意：禁用前请使用串口工具登录树莓派。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;然后设置接口：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;nano /etc/network/interfaces
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后添加以下内容：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;auto lo
iface lo inet loopback

auto usb0
allow-hotplug usb0
iface usb0 inet static
        address 192.168.100.2
        netmask 255.255.255.0
        &lt;span class=&quot;c&quot;&gt;#network 192.168.100.0&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;#broadcast 192.168.100.255&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;#gateway 192.168.100.1&lt;/span&gt;

allow-hotplug wlan0
iface wlan0 inet dhcp
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;接下来修改 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/wpa_supplicant/wpa_supplicant.conf&lt;/code&gt; 文件，添加以下内容：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;network&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;={&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;scan_ssid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1
    &lt;span class=&quot;nv&quot;&gt;ssid&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;我家的Wi-Fi&quot;&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;psk&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;我家的Wi-Fi密码&quot;&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;key_mgmt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;WPA-PSK
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;scan_ssid=1&lt;/code&gt; 是因为我家的 Wi-Fi 是隐藏的，所以需要添加这个选项。&lt;/p&gt;

&lt;p&gt;接着，我们需要安装 dnsmasq，它允许我们使用 DHCP 为连接到 Pi 上的 USB 端口的 PC 或 Mac 分配 IP 地址。如果树莓派默认的源下载速度太慢，可以参考&lt;a href=&quot;https://mirrors.ustc.edu.cn/help/debian.html&quot;&gt;USTC&lt;/a&gt;。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s/deb.debian.org/mirrors.ustc.edu.cn/g&apos;&lt;/span&gt; /etc/apt/sources.list
&lt;span class=&quot;nb&quot;&gt;sudo sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s|security.debian.org/\? |security.debian.org/debian-security |g&apos;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s|security.debian.org|mirrors.ustc.edu.cn|g&apos;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s|deb.debian.org/debian-security|mirrors.ustc.edu.cn/debian-security|g&apos;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
            /etc/apt/sources.list
&lt;span class=&quot;nb&quot;&gt;sudo sed&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-i&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;s|raspbian.raspberrypi.org|mirrors.ustc.edu.cn/raspbian|g&apos;&lt;/span&gt; /etc/apt/sources.list
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt update
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;安装 dnsmasq：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-y&lt;/span&gt; dnsmasq
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后编辑 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/dnsmasq.conf&lt;/code&gt; 文件，添加以下内容：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;dhcp-range&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;192.168.100.1,192.168.100.254,24h
dhcp-option&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;3
dhcp-option&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;6
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;DHCP 范围需要与我们分配给 usb0 接口的接口 IP 地址匹配，此选项将分配 192.168.100.2 和 .254 之间的地址，租期为 24 小时。这应该绰绰有余。如果由于某种原因需要更改 IP 范围，请确保将 usb0 的配置与这些项目匹配。我们还使用了 DHCP 选项 3 和 6 - 它们在配置文件中进行了注释，但它们阻止 dnsmaq 通告默认路由或 DNS - 在本教程中，我们不需要树莓派作为 DNS 服务器或路由器。&lt;/p&gt;

&lt;p&gt;最后重启树莓派。就可以使用 SSH 连接我们的树莓派了：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ssh &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt; pi 192.168.100.2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;添加-swap-分区&quot;&gt;添加 swap 分区&lt;/h2&gt;

&lt;p&gt;树莓派的内存只有 512MB，运行一些程序会很吃力，所以我们需要添加一个 swap 分区。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;nano /etc/fstab
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;看到文件末尾有以下内容：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# a swapfile is not a swap partition, no line here&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#   use  dphys-swapfile swap[on|off]  for that&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;我就知道了，树莓派的 swap 分区是使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dphys-swapfile&lt;/code&gt; 来管理的。我们可以直接使用它来创建一个 swap 分区。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;nano /etc/dphys-swapfile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;修改以下内容：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;CONF_SWAPSIZE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;512
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;重启 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dphys-swapfile&lt;/code&gt; 服务：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl restart dphys-swapfile
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;查看 swap 分区：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;free &lt;span class=&quot;nt&quot;&gt;-h&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;可以看到 swap 分区已经添加成功了。&lt;/p&gt;

&lt;h2 id=&quot;降低功耗&quot;&gt;降低功耗&lt;/h2&gt;

&lt;p&gt;有些电脑 USB 可能带不动，所以我们需要降低以下功耗。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;nano /boot/config.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在文件末尾添加以下内容：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;dtparam&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;act_led_trigger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;actpwr
&lt;span class=&quot;nv&quot;&gt;gpu_mem&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;16
&lt;span class=&quot;nv&quot;&gt;arm_freq&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;700
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;其中 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dtparam=act_led_trigger=actpwr&lt;/code&gt; 是让树莓派的电源指示灯变成硬盘活动指示灯。&lt;/p&gt;

&lt;p&gt;然后修改 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/boot/cmdline.txt&lt;/code&gt; 文件，在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;console=tty1&lt;/code&gt; 后面加上 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;maxcpus=2&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;重启，这将限制树莓派的 CPU 核心数为 2 个。&lt;/p&gt;

&lt;h2 id=&quot;定时清除-buffcache&quot;&gt;定时清除 buff/cache&lt;/h2&gt;

&lt;p&gt;参见&lt;a href=&quot;https://icing.fun/2025/05/12/server_maintain/#title3&quot;&gt;【服务器维护】时隔425天的一次维护记录 - 冰冰番茄的归档&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;也可以将清理脚本 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clear_cache&lt;/code&gt; 放在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/local/bin&lt;/code&gt; 目录下，确保权限 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+x&lt;/code&gt;，然后添加到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/cron.d&lt;/code&gt; 中：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;nano /etc/cron.d/clear_cache
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/cron.d/clear_cache&lt;/code&gt; 中添加以下内容：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;/10 &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; root /usr/local/bin/clear_cache
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;连接家里的-nas&quot;&gt;连接家里的 NAS&lt;/h2&gt;

&lt;p&gt;可以参考&lt;a href=&quot;https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/7/html/storage_administration_guide/mounting_an_smb_share#unix_extensions_support&quot;&gt;此处&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;先安装必要组件：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;cifs-utils
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后直接挂载：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mount &lt;span class=&quot;nt&quot;&gt;-t&lt;/span&gt; cifs &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;vers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1.0,username&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;user_name //server_name/share_name /mnt/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如果需要密码，可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-o password=your_password&lt;/code&gt; 选项。&lt;/p&gt;

&lt;p&gt;卸载：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;umount /mnt/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>【服务器维护】时隔425天的一次维护记录</title>
   <link href="https://icing.fun/posts/server_maintain.html"/>
   <updated>2025-05-12T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/server_maintain</id>
   <content type="html">&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#title1&quot;&gt;删除阿里云助手Agent&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#title2&quot;&gt;阻止脚本小子偷偷撞我SSH密码&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#title3&quot;&gt;定时清扫一下 buff/cache&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;删除阿里云助手agent&quot;&gt;&lt;span id=&quot;title1&quot;&gt;删除阿里云助手Agent&lt;/span&gt;&lt;/h2&gt;

&lt;p&gt;今天正好在玩树莓派的时候，心血来潮登录自己&lt;s&gt;部落格&lt;/s&gt;博客的服务器看看。&lt;/p&gt;

&lt;p&gt;熟练地 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;htop&lt;/code&gt; 一下，结果……&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2025/05/12/1.png&quot; alt=&quot;htop&quot; width=&quot;50%&quot; /&gt;
&lt;em&gt;惊不惊喜？意不意外？&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/local/share/assist-daemon/assist_daemon&lt;/code&gt; 很扎眼，我就知道是阿里云干的事情。&lt;/p&gt;

&lt;p&gt;首先说结论：参阅&lt;a href=&quot;https://help.aliyun.com/zh/ecs/user-guide/start-stop-or-uninstall-the-cloud-assistant-agent#4f295d821anjm&quot;&gt;卸载云助手Agent&lt;/a&gt;的文档，跟着删就行。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 停止云助手守护进程&lt;/span&gt;
/usr/local/share/assist-daemon/assist_daemon &lt;span class=&quot;nt&quot;&gt;--stop&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 卸载云助手守护进程&lt;/span&gt;
/usr/local/share/assist-daemon/assist_daemon &lt;span class=&quot;nt&quot;&gt;--delete&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 删除云助手守护进程目录&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-rf&lt;/span&gt; /usr/local/share/assist-daemon

&lt;span class=&quot;c&quot;&gt;# 卸载云助手Agent&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;dpkg &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; aliyun-assist &lt;span class=&quot;c&quot;&gt;# Debian/Ubuntu&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;rpm &lt;span class=&quot;nt&quot;&gt;-qa&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;aliyun_assist | xargs &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;rpm &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# CentOS/RHEL&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 删除云助手Agent目录&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-rf&lt;/span&gt; /usr/local/share/aliyun-assist
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;阻止脚本小子偷偷撞我ssh密码&quot;&gt;&lt;span id=&quot;title2&quot;&gt;阻止脚本小子偷偷撞我SSH密码&lt;/span&gt;&lt;/h2&gt;

&lt;p&gt;跟前年hvv一样，阿里不知道从哪里找来一些野鸡选手，当时我的博客用的是&lt;s&gt;硬屎&lt;/s&gt;极简风，用Jekyll生成的类似Apache/Nginx默认页面，具体看&lt;a href=&quot;https://web.archive.org/web/20231003163648/http://icing.fun/&quot;&gt;这&lt;/a&gt;。发短信告诉我80端口开了，都看到里面的文件了，很危险，需要我注意。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2025/05/12/2.png&quot; alt=&quot;?&quot; width=&quot;50%&quot; /&gt;
&lt;em&gt;我请问呢？&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;现在看来，他们很喜欢扫 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh&lt;/code&gt; 端口。&lt;s&gt;抓不到漏洞急了吧？随便写一下就能输出报告？我那个时候高位端口都是开着的咋不扫一下？看ssh日志时候才发现有个IP是镇江的江苏科技大学的一直在扫我服务器，光扫5000以下的，有点难绷了兄弟。&lt;/s&gt;&lt;/p&gt;

&lt;p&gt;使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cat /var/log/auth.log |grep Failed&lt;/code&gt; 这个命令（文件可能是auth.log或者是auth.log.数字，可以进目录看看）看了一下登录失败的记录。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2025/05/12/3.png&quot; alt=&quot;ssh&quot; width=&quot;50%&quot; /&gt;
&lt;em&gt;ssh登录失败的记录&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;蔚为壮观……&lt;/p&gt;

&lt;p&gt;可以看看这个&lt;a href=&quot;https://icingtomato.github.io/Anti-SSH-Attack/&quot;&gt;Treemap&lt;/a&gt;，可以清晰看到IP地址和源地址以及攻击手段。&lt;/p&gt;

&lt;p&gt;自己搓了个脚本，提取 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/var/log/auth.log&lt;/code&gt; 登录失败的IP地址，添加到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/hosts.deny&lt;/code&gt; 里面。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 脚本功能：从/var/log/auth.log和/var/log/auth.log.N提取SSH失败登录的IP地址并添加到/etc/hosts.deny&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 检查是否有root权限&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-ne&lt;/span&gt; 0 &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
    &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Need root!&quot;&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;exit &lt;/span&gt;1
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 查找所有匹配的日志文件&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;log_files&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=(&lt;/span&gt;/var/log/auth.log /var/log/auth.log.&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 检查是否找到至少一个有效的日志文件&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;valid_files&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0
&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;log_file &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;log_files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[@]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
    if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$log_file&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
        &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;valid_files&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;$((&lt;/span&gt;valid_files+1&lt;span class=&quot;k&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fi
done

if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$valid_files&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-eq&lt;/span&gt; 0 &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
    &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Cannot find any auth.log files&quot;&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;exit &lt;/span&gt;1
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 计数器&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;added&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0
&lt;span class=&quot;nv&quot;&gt;skipped&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0

&lt;span class=&quot;c&quot;&gt;# 处理每个找到的日志文件&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for &lt;/span&gt;log_file &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;log_files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[@]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
    &lt;span class=&quot;c&quot;&gt;# 跳过不存在的文件&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$log_file&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
        continue
    fi

    &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Processing &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$log_file&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;...&quot;&lt;/span&gt;
    
    &lt;span class=&quot;c&quot;&gt;# 查找包含&quot;port&quot;但不包含正常连接行为的记录，提取IP地址&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;port&quot;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$log_file&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-E&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;(Accepted password|Received disconnect|Disconnected from user)&quot;&lt;/span&gt; | &lt;span class=&quot;k&quot;&gt;while &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; line&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# 使用正则表达式提取from/by与port之间的IP地址&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$line&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;~ &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;from|by&lt;span class=&quot;o&quot;&gt;)[[&lt;/span&gt;:space:]]+&lt;span class=&quot;o&quot;&gt;([&lt;/span&gt;0-9]+&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;0-9]+&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;0-9]+&lt;span class=&quot;se&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;0-9]+&lt;span class=&quot;o&quot;&gt;)[[&lt;/span&gt;:space:]]+port &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
            &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ip&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;BASH_REMATCH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[2]&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
            
            &lt;span class=&quot;c&quot;&gt;# 检查是否已经在hosts.deny文件中&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;grep&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-q&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;sshd: &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ip&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; /etc/hosts.deny&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
                &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Pass &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ip&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; (exist)&quot;&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;((&lt;/span&gt;skipped++&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
                &lt;span class=&quot;c&quot;&gt;# 将IP地址追加到hosts.deny&lt;/span&gt;
                &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;sshd: &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ip&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; /etc/hosts.deny
                &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Block &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$ip&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;((&lt;/span&gt;added++&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;fi
        fi
    done
done

&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Done! Add: &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$added&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;, Exist: &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$skipped&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;再加上定时任务，&lt;a href=&quot;https://crontab.guru/every-1-minute&quot;&gt;每分钟执行一次&lt;/a&gt;。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; /root/anti_attack.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2025/05/12/4.png&quot; alt=&quot;block_ip&quot; width=&quot;50%&quot; /&gt;
&lt;em&gt;尝试运行，不错，确实在自动运行&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;自己尝试拿手机热点登录一下，获取一个IP地址，看看能不能被封。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2025/05/12/5.png&quot; alt=&quot;block_ip&quot; width=&quot;50%&quot; /&gt;
&lt;em&gt;可以清晰看到第一次登录成功，加了deny之后封IP成功，ssh登录失败了&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;定时清扫一下-buffcache&quot;&gt;&lt;span id=&quot;title3&quot;&gt;定时清扫一下 buff/cache&lt;/span&gt;&lt;/h2&gt;

&lt;p&gt;有时候服务器运行久了，内存会被占满，导致服务器变得很卡。可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;free -h&lt;/code&gt; 命令查看一下内存的使用情况。&lt;/p&gt;

&lt;p&gt;可以看到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;buff/cache&lt;/code&gt; 占用的内存很大。一般可以用以下命令清理一下：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Writing to this will cause the kernel to drop clean caches, as well as&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# reclaimable slab objects like dentries and inodes.  Once dropped, their&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# memory becomes free.&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# To free pagecache:&lt;/span&gt;
	&lt;span class=&quot;nb&quot;&gt;echo &lt;/span&gt;1 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /proc/sys/vm/drop_caches
&lt;span class=&quot;c&quot;&gt;# To free reclaimable slab objects (includes dentries and inodes):&lt;/span&gt;
	&lt;span class=&quot;nb&quot;&gt;echo &lt;/span&gt;2 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /proc/sys/vm/drop_caches
&lt;span class=&quot;c&quot;&gt;# To free slab objects and pagecache:&lt;/span&gt;
	&lt;span class=&quot;nb&quot;&gt;echo &lt;/span&gt;3 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /proc/sys/vm/drop_caches
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;来源：&lt;a href=&quot;https://www.kernel.org/doc/Documentation/sysctl/vm.txt&quot;&gt;Documentation for /proc/sys/vm/*&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;但是有时候运行的时候会报错 Permission denied，可以用如下命令：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;sh &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;echo 3 &amp;gt; /proc/sys/vm/drop_caches&apos;&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Or&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;echo &lt;/span&gt;3 | &lt;span class=&quot;nb&quot;&gt;sudo tee&lt;/span&gt; /proc/sys/vm/drop_caches
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;再使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;free -h&lt;/code&gt; 命令查看一下内存的使用情况，buff/cache已经清理掉了。&lt;/p&gt;

&lt;p&gt;其实可以在 /etc/cron.daily 目录下，创建一个脚本 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/cron.daily/clear_cache.sh&lt;/code&gt;，内容如下：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/sh&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;sync
echo &lt;/span&gt;3 &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /proc/sys/vm/drop_caches
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后给这个脚本加上可执行权限： &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chmod +x /etc/cron.daily/clear_cache.sh&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;这样就可以每天定时清理缓存了。不过这个脚本会清理掉所有的缓存，包括文件系统缓存和页面缓存，所以在使用时要谨慎。&lt;/p&gt;

&lt;h2 id=&quot;转移到-cloudflare&quot;&gt;转移到 Cloudflare&lt;/h2&gt;

&lt;p&gt;2020年7月27日 19:20:00&lt;/p&gt;

&lt;p&gt;我在阿里云上创建了这台1C512M的小水管。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2025/05/12/6.png&quot; alt=&quot;ECS&quot; width=&quot;50%&quot; /&gt;
&lt;em&gt;阿里云ECS&lt;/em&gt;
&lt;img src=&quot;../img/post/2025/05/12/7.png&quot; alt=&quot;ECS&quot; width=&quot;50%&quot; /&gt;
&lt;em&gt;创建时间&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;于2025年5月16日 12:00:00，转移到 Cloudflare。&lt;/p&gt;

&lt;p&gt;别了，阿里云尼亚。&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>【Git】Git 取消文件跟踪</title>
   <link href="https://icing.fun/posts/git_rm.html"/>
   <updated>2025-05-02T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/git_rm</id>
   <content type="html">&lt;p&gt;前两天在写小程序的时候，没注意把 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.vscode&lt;/code&gt; 文件夹给上传上去了。就在想怎么把它删掉。&lt;/p&gt;

&lt;h2 id=&quot;明确目标&quot;&gt;明确目标&lt;/h2&gt;

&lt;p&gt;首先，我们要知道，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.vscode&lt;/code&gt; 是存放 VS Code 的配置文件的。里面有我们的配置文件，像是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;settings.json&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;launch.json&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tasks.json&lt;/code&gt; 等等。这些删除之后，VS Code 每次都会自动生成新的配置文件。&lt;/p&gt;

&lt;p&gt;所以我们要保证的是，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.vscode&lt;/code&gt; 文件夹在本地是存在的，但是在远程仓库中是不存在的。&lt;/p&gt;

&lt;p&gt;当我尝试使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitignore&lt;/code&gt; 的时候，发现 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitignore&lt;/code&gt; 文件并没有生效。
因为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitignore&lt;/code&gt; 只会忽略那些没有被 Git 跟踪的文件。也就是说，如果你已经将 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.vscode&lt;/code&gt; 文件夹添加到 Git 中，那么即使你在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitignore&lt;/code&gt; 中添加了它，它也不会被忽略。&lt;/p&gt;

&lt;p&gt;在实际操作之前，我们先来理解下 Git 工作区、暂存区和版本库概念：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;工作区：就是你在电脑里能看到的目录。&lt;/li&gt;
  &lt;li&gt;暂存区：英文叫 stage 或 index。一般存放在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.git&lt;/code&gt; 目录下的 index 文件（.git/index）中，所以我们把暂存区有时也叫作索引（index）。&lt;/li&gt;
  &lt;li&gt;版本库：工作区有一个隐藏目录 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.git&lt;/code&gt;，这个不算工作区，而是 Git 的版本库。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;工作区暂存区和版本库之间的关系&quot;&gt;工作区、暂存区和版本库之间的关系&lt;/h2&gt;

&lt;h3 id=&quot;工作区---暂存区&quot;&gt;工作区 -&amp;gt; 暂存区&lt;/h3&gt;

&lt;p&gt;使用 git add 命令将工作区中的修改添加到暂存区。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git add &amp;lt;filename&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;暂存区---版本库&quot;&gt;暂存区 -&amp;gt; 版本库&lt;/h3&gt;

&lt;p&gt;使用 git commit 命令将暂存区中的修改提交到版本库。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git commit &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Commit message&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;版本库---远程仓库&quot;&gt;版本库 -&amp;gt; 远程仓库&lt;/h3&gt;

&lt;p&gt;使用 git push 命令将本地版本库的提交推送到远程仓库。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git push origin &amp;lt;branch-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;远程仓库---本地版本库&quot;&gt;远程仓库 -&amp;gt; 本地版本库&lt;/h3&gt;

&lt;p&gt;使用 git pull 或 git fetch 命令从远程仓库获取更新。&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git pull origin &amp;lt;branch-name&amp;gt;
&lt;span class=&quot;c&quot;&gt;# 或者&lt;/span&gt;
git fetch origin &amp;lt;branch-name&amp;gt;
git merge origin/&amp;lt;branch-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;git-rm-操作步骤&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git rm&lt;/code&gt; 操作步骤&lt;/h2&gt;

&lt;p&gt;git rm 命令用于删除文件。&lt;/p&gt;

&lt;p&gt;如果只是简单地从工作目录中手工删除文件，运行 git status 时就会在 Changes not staged for commit 的提示。&lt;/p&gt;

&lt;p&gt;git rm 删除文件有以下几种形式：&lt;/p&gt;

&lt;h3 id=&quot;将文件从暂存区和工作区中删除&quot;&gt;将文件从暂存区和工作区中删除：&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git &lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &amp;lt;file&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;强行从暂存区和工作区中删除修改后的文件&quot;&gt;强行从暂存区和工作区中删除修改后的文件：&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git &lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; &amp;lt;file&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;如果删除之前修改过并且已经放到暂存区域的话，则必须要用强制删除选项 -f。&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;从暂存区中删除但是保留工作区文件&quot;&gt;从暂存区中删除，但是保留工作区文件：&lt;/h3&gt;

&lt;p&gt;如果想把文件从暂存区域移除，但仍然希望保留在当前工作目录中，换句话说，仅是从跟踪清单中删除，使用 –cached 选项即可：&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git &lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--cached&lt;/span&gt; &amp;lt;file&amp;gt;
&lt;span class=&quot;c&quot;&gt;# 删除目录需要带递归选项 -r&lt;/span&gt;
git &lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--cached&lt;/span&gt; &amp;lt;&lt;span class=&quot;nb&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>【Calc】CASIO Graph Light Lycée 法版 中文翻译</title>
   <link href="https://icing.fun/posts/casio_graph_light_calc_trans.html"/>
   <updated>2025-04-17T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/casio_graph_light_calc_trans</id>
   <content type="html">&lt;h2 id=&quot;主菜单&quot;&gt;主菜单&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Calcul  计算&lt;/li&gt;
  &lt;li&gt;Stats  统计&lt;/li&gt;
  &lt;li&gt;Probabilité  概率&lt;/li&gt;
  &lt;li&gt;Tableur  表格&lt;/li&gt;
  &lt;li&gt;Graphe  图形&lt;/li&gt;
  &lt;li&gt;Tabl fonct  函数表&lt;/li&gt;
  &lt;li&gt;Équation  方程&lt;/li&gt;
  &lt;li&gt;Complexe  复数&lt;/li&gt;
  &lt;li&gt;Vecteurs  向量&lt;/li&gt;
  &lt;li&gt;Prod. crolx  叉积&lt;/li&gt;
  &lt;li&gt;Math Box  数学盒&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;config--配置&quot;&gt;Config  配置&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Paramètre calcul  计算参数
    &lt;ul&gt;
      &lt;li&gt;Saisie/Résultat  输入/结果
        &lt;ul&gt;
          &lt;li&gt;Smaths/Rmaths  自然显示/包含分数显示&lt;/li&gt;
          &lt;li&gt;Smaths/Rdéc 自然显示/转换成科学计数法或小数显示&lt;/li&gt;
          &lt;li&gt;Sligne/Rligne  线性显示/科学计数法或分数显示&lt;/li&gt;
          &lt;li&gt;Sligne/Rdéc  线性显示/转换成科学计数法显示&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Unité d’angle  角度单位
        &lt;ul&gt;
          &lt;li&gt;Degré  度&lt;/li&gt;
          &lt;li&gt;Radian  弧度&lt;/li&gt;
          &lt;li&gt;Grade  渐度&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Arrondi  取整
        &lt;ul&gt;
          &lt;li&gt;Fix  保留位数&lt;/li&gt;
          &lt;li&gt;Sci  科学计数法 有效数字&lt;/li&gt;
          &lt;li&gt;Norm  1: 科学计数法; 2: 小数&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Forme complexe  复数形式
        &lt;ul&gt;
          &lt;li&gt;a+bi  a+bi&lt;/li&gt;
          &lt;li&gt;r∠θ  r∠θ&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Sépart chiffers 数字分隔符
        &lt;ul&gt;
          &lt;li&gt;Séparat Lecture?  读数分隔符
            &lt;ul&gt;
              &lt;li&gt;Activé  启用&lt;/li&gt;
              &lt;li&gt;Désactivé  禁用&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Puissance de 10  10的幂
        &lt;ul&gt;
          &lt;li&gt;×10□  ×10□&lt;/li&gt;
          &lt;li&gt;×10  ×10&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Paramètre systèm  系统参数
    &lt;ul&gt;
      &lt;li&gt;Contraste 对比度
        &lt;ul&gt;
          &lt;li&gt;Clair  明亮&lt;/li&gt;
          &lt;li&gt;Sombre  暗色&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Extinct auto  自动灭屏
        &lt;ul&gt;
          &lt;li&gt;10 min  10分钟&lt;/li&gt;
          &lt;li&gt;60 min  60分钟&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Pol multiligne 多行显示
        &lt;ul&gt;
          &lt;li&gt;Police normale  正常字体&lt;/li&gt;
          &lt;li&gt;Petite police  小字体&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;QR Code  二维码
        &lt;ul&gt;
          &lt;li&gt;Version 3  版本3&lt;/li&gt;
          &lt;li&gt;Version 11  版本11&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Réinitialiser  重置
    &lt;ul&gt;
      &lt;li&gt;Config &amp;amp; données  配置和数据
        &lt;ul&gt;
          &lt;li&gt;Réinitialis OK? Config &amp;amp; données  重置确定?
            &lt;ul&gt;
              &lt;li&gt;Oui  是&lt;/li&gt;
              &lt;li&gt;Annuler  取消&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Mém variables  内存变量
        &lt;ul&gt;
          &lt;li&gt;Réinitialis OK? Mém variables  重置确定?
            &lt;ul&gt;
              &lt;li&gt;Oui  是&lt;/li&gt;
              &lt;li&gt;Annuler  取消&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Tout  全部
        &lt;ul&gt;
          &lt;li&gt;Réinitialis OK? Tout  重置确定?
            &lt;ul&gt;
              &lt;li&gt;Oui  是&lt;/li&gt;
              &lt;li&gt;Annuler  取消&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Mode d’emploi  使用说明&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;calcul-计算&quot;&gt;Calcul 计算&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Outils  工具&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Annuler  取消&lt;/li&gt;
  &lt;li&gt;Simplifier  简化
    &lt;ul&gt;
      &lt;li&gt;Automatique  自动&lt;/li&gt;
      &lt;li&gt;Manuel  手动&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Vérification  检查&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Catalog  目录&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Analyse fonction  解析函数
    &lt;ul&gt;
      &lt;li&gt;Nb dérivé(d/dx) 导数&lt;/li&gt;
      &lt;li&gt;Intégrale  积分&lt;/li&gt;
      &lt;li&gt;Somme  求和&lt;/li&gt;
      &lt;li&gt;Reste  余数&lt;/li&gt;
      &lt;li&gt;Simplification  简化&lt;/li&gt;
      &lt;li&gt;Logarithme base a  对数&lt;/li&gt;
      &lt;li&gt;Logarithme(log)  对数&lt;/li&gt;
      &lt;li&gt;Logarithme(ln)  自然对数&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Probabilité  概率
    &lt;ul&gt;
      &lt;li&gt;%&lt;/li&gt;
      &lt;li&gt;Factorielle  阶乘&lt;/li&gt;
      &lt;li&gt;Permutation  排列&lt;/li&gt;
      &lt;li&gt;Combinaison  组合&lt;/li&gt;
      &lt;li&gt;Nombre aléatoire  随机数&lt;/li&gt;
      &lt;li&gt;Entier aléatoire  随机整数&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Calcul numérique  数值计算
    &lt;ul&gt;
      &lt;li&gt;PGCD  最大公约数&lt;/li&gt;
      &lt;li&gt;PPCM  最小公倍数&lt;/li&gt;
      &lt;li&gt;Valeur absolue  绝对值&lt;/li&gt;
      &lt;li&gt;Tronc. à l’unité  截断到整数&lt;/li&gt;
      &lt;li&gt;Arrondi  到整数&lt;/li&gt;
      &lt;li&gt;Partie entière  整数部分&lt;/li&gt;
      &lt;li&gt;Arrondi(,)  四舍五入&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Angl/Coord/Sexag  角度/坐标/六十进制
    &lt;ul&gt;
      &lt;li&gt;Degrés  度&lt;/li&gt;
      &lt;li&gt;Radians  弧度&lt;/li&gt;
      &lt;li&gt;Gradians  渐度&lt;/li&gt;
      &lt;li&gt;Cartésien. à pol.  笛卡尔坐标系&lt;/li&gt;
      &lt;li&gt;Pol. à cartésien.  极坐标系&lt;/li&gt;
      &lt;li&gt;Degrés min sec  度分秒&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Trigonmétrique  三角函数
    &lt;ul&gt;
      &lt;li&gt;sin  正弦&lt;/li&gt;
      &lt;li&gt;cos  余弦&lt;/li&gt;
      &lt;li&gt;tan  正切&lt;/li&gt;
      &lt;li&gt;sin⁻¹  反正弦&lt;/li&gt;
      &lt;li&gt;cos⁻¹  反余弦&lt;/li&gt;
      &lt;li&gt;tan⁻¹  反正切&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Conversion unité  单位转换
    &lt;ul&gt;
      &lt;li&gt;Vitesse  速度
        &lt;ul&gt;
          &lt;li&gt;km/h→m/s  km/h→m/s&lt;/li&gt;
          &lt;li&gt;m/s→km/h  m/s→km/h&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Température  温度
        &lt;ul&gt;
          &lt;li&gt;Celsius→Fahrenheit  摄氏→华氏&lt;/li&gt;
          &lt;li&gt;Fahrenheit→Celsius  华氏→摄氏&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Autre  其他
    &lt;ul&gt;
      &lt;li&gt;Rép  重复&lt;/li&gt;
      &lt;li&gt;Pré-Rép  预设重复&lt;/li&gt;
      &lt;li&gt;pi  圆周率&lt;/li&gt;
      &lt;li&gt;e  自然对数底&lt;/li&gt;
      &lt;li&gt;e^  自然对数底的幂&lt;/li&gt;
      &lt;li&gt;√  平方根&lt;/li&gt;
      &lt;li&gt;𝒙√  𝒙次方根&lt;/li&gt;
      &lt;li&gt;^-1  反函数&lt;/li&gt;
      &lt;li&gt;^2  平方&lt;/li&gt;
      &lt;li&gt;^()  幂&lt;/li&gt;
      &lt;li&gt;-  负号&lt;/li&gt;
      &lt;li&gt;,  小数点&lt;/li&gt;
      &lt;li&gt;()  括号&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;stats--统计&quot;&gt;Stats  统计&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;1 variable  一个变量&lt;/li&gt;
  &lt;li&gt;2 variables  两个变量&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;probabilités--概率&quot;&gt;Probabilités  概率&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Binomiale P(X=)  二项分布 P(X=)
    &lt;ul&gt;
      &lt;li&gt;Liste de valeurs  值列表&lt;/li&gt;
      &lt;li&gt;Valeur unique  单值&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Poisson P(X≥)  泊松分布 P(X≥)
    &lt;ul&gt;
      &lt;li&gt;Liste de valeurs  值列表&lt;/li&gt;
      &lt;li&gt;Valeur unique  单值&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Binomiale P(X≤)  二项分布 P(X≤)&lt;/li&gt;
  &lt;li&gt;Densité Normale  正态分布密度&lt;/li&gt;
  &lt;li&gt;Normale P(≤X≤)  正态分布 P(≤X≤)&lt;/li&gt;
  &lt;li&gt;Inverse normale  正态分布反函数&lt;/li&gt;
  &lt;li&gt;Poisson P(X=)  泊松分布 P(X=)
    &lt;ul&gt;
      &lt;li&gt;Liste de valeurs  值列表&lt;/li&gt;
      &lt;li&gt;Valeur unique  单值&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Poisson P(X≤)  泊松分布 P(X≤)
    &lt;ul&gt;
      &lt;li&gt;Liste de valeurs  值列表&lt;/li&gt;
      &lt;li&gt;Valeur unique  单值&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;tableur--表格&quot;&gt;Tableur  表格&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Outils  工具&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Remplir formule  填充公式
    &lt;ul&gt;
      &lt;li&gt;Formul=  公式&lt;/li&gt;
      &lt;li&gt;Plage  范围&lt;/li&gt;
      &lt;li&gt;Confirmer  确认&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Remplir valeur  填充值
    &lt;ul&gt;
      &lt;li&gt;Valeur  值&lt;/li&gt;
      &lt;li&gt;Plage  范围&lt;/li&gt;
      &lt;li&gt;Confirmer  确认&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Modifier cell  修改单元格&lt;/li&gt;
  &lt;li&gt;Espace libre  空间
    &lt;ul&gt;
      &lt;li&gt;2380 octets libre  2380字节可用&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Couper &amp;amp; Coller  剪切和粘贴&lt;/li&gt;
  &lt;li&gt;Copier &amp;amp; Coller  复制和粘贴&lt;/li&gt;
  &lt;li&gt;Tout supprimer  删除所有内容&lt;/li&gt;
  &lt;li&gt;Recalculer  重新计算&lt;/li&gt;
  &lt;li&gt;Calcul auto  自动计算
    &lt;ul&gt;
      &lt;li&gt;Activé  启用&lt;/li&gt;
      &lt;li&gt;Désactivé  禁用&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Afficher cell  显示单元格
    &lt;ul&gt;
      &lt;li&gt;Formule  公式&lt;/li&gt;
      &lt;li&gt;Valeur  值&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;graphe--图形&quot;&gt;Graphe  图形&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;f(x)  函数图像
    &lt;ul&gt;
      &lt;li&gt;Modifier  修改&lt;/li&gt;
      &lt;li&gt;Afficher/Masquer  显示/隐藏
        &lt;ul&gt;
          &lt;li&gt;Afficher  显示&lt;/li&gt;
          &lt;li&gt;Masquer  隐藏&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Type de ligne  线条类型&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;g(x)  函数图像&lt;/li&gt;
  &lt;li&gt;Tracer  绘制
    &lt;ul&gt;
      &lt;li&gt;Fenêtre graphique  图形窗口
        &lt;ul&gt;
          &lt;li&gt;Pré-enregistrées  预设
            &lt;ul&gt;
              &lt;li&gt;Orthonormé  正交标准&lt;/li&gt;
              &lt;li&gt;Trigonométrique  三角函数&lt;/li&gt;
              &lt;li&gt;Standard(-10;10) 标准(-10;10)&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;𝒙min  𝒙最小值&lt;/li&gt;
          &lt;li&gt;max  最大值&lt;/li&gt;
          &lt;li&gt;grad.  刻度&lt;/li&gt;
          &lt;li&gt;𝒚min  𝒚最小值&lt;/li&gt;
          &lt;li&gt;max  最大值&lt;/li&gt;
          &lt;li&gt;grad.  刻度&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Résolution graph  图形分辨率
        &lt;ul&gt;
          &lt;li&gt;Racines  根&lt;/li&gt;
          &lt;li&gt;Maximum local  局部最大值&lt;/li&gt;
          &lt;li&gt;Minimum local  局部最小值&lt;/li&gt;
          &lt;li&gt;Intersection  交点&lt;/li&gt;
          &lt;li&gt;Ordonnée origine  原点纵坐标&lt;/li&gt;
          &lt;li&gt;𝒚(image)  𝒚(因变量)&lt;/li&gt;
          &lt;li&gt;𝒙(antécédent)  𝒙(自变量)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Parcourir courbe  遍历曲线&lt;/li&gt;
      &lt;li&gt;Zoom  缩放
        &lt;ul&gt;
          &lt;li&gt;Zoom automatique  自动缩放&lt;/li&gt;
          &lt;li&gt;Zoom avant  向前缩放&lt;/li&gt;
          &lt;li&gt;Zoom arrière  向后缩放&lt;/li&gt;
          &lt;li&gt;Facteur de zoom  缩放因子
            &lt;ul&gt;
              &lt;li&gt;2×  2×&lt;/li&gt;
              &lt;li&gt;3×  3×&lt;/li&gt;
              &lt;li&gt;10×  10×&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Placer un point  放置一个点&lt;/li&gt;
      &lt;li&gt;Tracer tangente  绘制切线&lt;/li&gt;
      &lt;li&gt;Nb dérivé  导数个数
        &lt;ul&gt;
          &lt;li&gt;Activé  启用&lt;/li&gt;
          &lt;li&gt;Désactivé  禁用&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Affich. Fonction  函数显示
        &lt;ul&gt;
          &lt;li&gt;Activé  启用&lt;/li&gt;
          &lt;li&gt;Désactivé  禁用&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Arrière-plan  背景
        &lt;ul&gt;
          &lt;li&gt;Label  标签
            &lt;ul&gt;
              &lt;li&gt;Activé  启用&lt;/li&gt;
              &lt;li&gt;Désactivé  禁用&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;Grille  网格
            &lt;ul&gt;
              &lt;li&gt;Activé  启用&lt;/li&gt;
              &lt;li&gt;Désactivé  禁用&lt;/li&gt;
              &lt;li&gt;Ligne  线&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;Axes  轴
            &lt;ul&gt;
              &lt;li&gt;Activé  启用&lt;/li&gt;
              &lt;li&gt;Désactivé  禁用&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Outils  工具&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Fenêtre graphique  图形窗口
    &lt;ul&gt;
      &lt;li&gt;Pré-enregistrées  预设
        &lt;ul&gt;
          &lt;li&gt;Orthonormé  正交标准&lt;/li&gt;
          &lt;li&gt;Trigonométrique  三角函数&lt;/li&gt;
          &lt;li&gt;Standard(-10;10) 标准(-10;10)&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;𝒙min  𝒙最小值&lt;/li&gt;
      &lt;li&gt;max  最大值&lt;/li&gt;
      &lt;li&gt;grad.  刻度&lt;/li&gt;
      &lt;li&gt;point  点&lt;/li&gt;
      &lt;li&gt;𝒚min  𝒚最小值&lt;/li&gt;
      &lt;li&gt;max  最大值&lt;/li&gt;
      &lt;li&gt;grad.  刻度&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Nb dérivé  导数个数
    &lt;ul&gt;
      &lt;li&gt;Activé  启用&lt;/li&gt;
      &lt;li&gt;Désactivé  禁用&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Affich. Fonction  函数显示
    &lt;ul&gt;
      &lt;li&gt;Activé  启用&lt;/li&gt;
      &lt;li&gt;Désactivé  禁用&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Arrière-plan  背景
    &lt;ul&gt;
      &lt;li&gt;Label  标签
        &lt;ul&gt;
          &lt;li&gt;Activé  启用&lt;/li&gt;
          &lt;li&gt;Désactivé  禁用&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Grille  网格
        &lt;ul&gt;
          &lt;li&gt;Activé  启用&lt;/li&gt;
          &lt;li&gt;Désactivé  禁用&lt;/li&gt;
          &lt;li&gt;Ligne  线&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Axes  轴
        &lt;ul&gt;
          &lt;li&gt;Activé  启用&lt;/li&gt;
          &lt;li&gt;Désactivé  禁用&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;tabl-fonct--函数表&quot;&gt;Tabl fonct  函数表&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;f(x)/g(x): Vide  函数表: 空&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Outils  工具&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Plage du tableau  表格范围&lt;/li&gt;
  &lt;li&gt;Défin f(x)/g(x)  定义f(x)/g(x)
    &lt;ul&gt;
      &lt;li&gt;Défin f(x)&lt;/li&gt;
      &lt;li&gt;Défin g(x)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Type de tableau  表格类型
    &lt;ul&gt;
      &lt;li&gt;f(x)/g(x)  函数表&lt;/li&gt;
      &lt;li&gt;f(x)  函数表&lt;/li&gt;
      &lt;li&gt;g(x)  函数表&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Éditer  编辑
    &lt;ul&gt;
      &lt;li&gt;Insérer ligne  插入行&lt;/li&gt;
      &lt;li&gt;Tout supprimer  删除所有内容&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Recalculer  重新计算&lt;/li&gt;
  &lt;li&gt;Vérification  检查&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;équation--方程&quot;&gt;Équation  方程&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Syst équations  方程组
    &lt;ul&gt;
      &lt;li&gt;2 inconnues  2个未知数&lt;/li&gt;
      &lt;li&gt;3 inconnues  3个未知数&lt;/li&gt;
      &lt;li&gt;4 inconnues  4个未知数&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Polynomiale  多项式
    &lt;ul&gt;
      &lt;li&gt;a(x²)+bx+c  a(x²)+bx+c&lt;/li&gt;
      &lt;li&gt;a(x³)+bx²+cx+d  a(x³)+bx²+cx+d&lt;/li&gt;
      &lt;li&gt;a(x⁴)+bx³+cx²+dx+e  a(x⁴)+bx³+cx²+dx+e&lt;/li&gt;
    &lt;/ul&gt;

    &lt;p&gt;&lt;em&gt;Outils  工具&lt;/em&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;Racine complexe  复根
        &lt;ul&gt;
          &lt;li&gt;Activé  启用&lt;/li&gt;
          &lt;li&gt;Désactivé  禁用&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Vérification  检查&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Solveur  求解
    &lt;ul&gt;
      &lt;li&gt;Saisir l’équation  输入方程&lt;/li&gt;
    &lt;/ul&gt;

    &lt;p&gt;&lt;em&gt;Outils  工具&lt;/em&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;Annuler  取消&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;complexe--复数&quot;&gt;Complexe  复数&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Outils  工具&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Annuler  取消&lt;/li&gt;
  &lt;li&gt;Vérification  检查&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;vecteurs--向量&quot;&gt;Vecteurs  向量&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;[OUTILS] pour définir un vecteur  [工具] 定义向量&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Outils  工具&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;VctA: Vide  向量A: 空&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;prod-crolx-叉积&quot;&gt;Prod. crolx 叉积&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;A/B=X/D  向量A/B=X/D&lt;/li&gt;
  &lt;li&gt;A/B=C/X  向量A/B=C/X&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;math-box--数学盒&quot;&gt;Math Box  数学盒&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Lancer de dés  掷骰子
    &lt;ul&gt;
      &lt;li&gt;Dés  骰子
        &lt;ul&gt;
          &lt;li&gt;1 dé  1个骰子&lt;/li&gt;
          &lt;li&gt;2 dés  2个骰子&lt;/li&gt;
          &lt;li&gt;3 dés  3个骰子&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Essais  尝试
        &lt;ul&gt;
          &lt;li&gt;:5  5次&lt;/li&gt;
          &lt;li&gt;Confirmer  确认&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Même résult  相同结果
        &lt;ul&gt;
          &lt;li&gt;Non  同结果&lt;/li&gt;
          &lt;li&gt;#1  #1&lt;/li&gt;
          &lt;li&gt;#2  #2&lt;/li&gt;
          &lt;li&gt;#3  #3&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Exécuter  执行&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Pile ou face  正反面
    &lt;ul&gt;
      &lt;li&gt;Pièces  硬币
        &lt;ul&gt;
          &lt;li&gt;1 pièce  1个硬币&lt;/li&gt;
          &lt;li&gt;2 pièces  2个硬币&lt;/li&gt;
          &lt;li&gt;3 pièces  3个硬币&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Essais  尝试
        &lt;ul&gt;
          &lt;li&gt;:5  5次&lt;/li&gt;
          &lt;li&gt;Confirmer  确认&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Même résult  相同结果
        &lt;ul&gt;
          &lt;li&gt;Non  同结果&lt;/li&gt;
          &lt;li&gt;#1  #1&lt;/li&gt;
          &lt;li&gt;#2  #2&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Exécuter  执行&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Droite grad.  不等式区间
    &lt;ul&gt;
      &lt;li&gt;A:  区间A
        &lt;ul&gt;
          &lt;li&gt;𝒙＜𝒂&lt;/li&gt;
          &lt;li&gt;𝒙≤𝒂&lt;/li&gt;
          &lt;li&gt;𝒙=𝒂&lt;/li&gt;
          &lt;li&gt;𝒙＞𝒂&lt;/li&gt;
          &lt;li&gt;𝒙≥𝒂&lt;/li&gt;
          &lt;li&gt;𝒂＜𝒙＜𝒃&lt;/li&gt;
          &lt;li&gt;𝒂≤𝒙＜𝒃&lt;/li&gt;
          &lt;li&gt;𝒂＜𝒙≤𝒃&lt;/li&gt;
          &lt;li&gt;𝒂≤𝒙≤𝒃&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;B:  区间B&lt;/li&gt;
      &lt;li&gt;C:  区间C&lt;/li&gt;
      &lt;li&gt;Exécuter  执行&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Cercle  圆
    &lt;ul&gt;
      &lt;li&gt;Type: CercleTrigo  三角函数圆
        &lt;ul&gt;
          &lt;li&gt;CercleTrigo  三角函数圆&lt;/li&gt;
          &lt;li&gt;Demi-cercle  半圆&lt;/li&gt;
          &lt;li&gt;Horloge  时钟&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;θ1: θ1&lt;/li&gt;
      &lt;li&gt;θ2: θ2&lt;/li&gt;
      &lt;li&gt;Exécuter  执行&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;
</content>
 </entry>
 
 <entry>
   <title>【老物新用】Mojo V3 FPGA 在 Ubuntu 上的开发环境搭建</title>
   <link href="https://icing.fun/posts/mojo_fpga_setup.html"/>
   <updated>2025-03-10T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/mojo_fpga_setup</id>
   <content type="html">&lt;p&gt;今天翻出一个12年前老物件（虽说是12年前，其实是两三年前买的），是一款 FPGA 开发板，还记得自己当时因为修这个开发板,使用烙铁风枪的水平突飞猛进。
这款板子还是比较坑的，DC接口居然只能接5V，当时公司里面只有9-12V的适配器，插上去就一股电子元器件的清香。拿万用表打了一下，好家伙直接一带一路，烧掉一个稳压（AMS1117）、两个LED、一个SPI Flash、一个FPGA芯片（XC6SLX9）。很感谢当时在M5的同事，帮我找到了这么多坏的元器件，不然我还以为只是一个稳压坏了。&lt;/p&gt;

&lt;p&gt;这老物件，生产它的公司 &lt;a href=&quot;https://twitter.com/embeddedmicro&quot;&gt;Embedded Micro&lt;/a&gt;已经无了（貌似是转生成&lt;a href=&quot;https://alchitry.com/&quot;&gt;Alchitry&lt;/a&gt;了，有机会把板子买过来试试），官网也无了，这些资料也只能在&lt;a href=&quot;https://archive.org/&quot;&gt;Internet Archive&lt;/a&gt;上找到，还是很感谢这个网站的存在，已经捐了10刀作为感谢，希望这个网站能继续运营下去。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2025/03/10/1.png&quot; alt=&quot;捐赠照片&quot; /&gt;&lt;/p&gt;

&lt;p&gt;对我来说，FPGA（现场可编程逻辑门阵列）一直是电气工程设计中排行老二的领域（老大是制造芯片，那个我还远远做不到），在高中的时候就开始接触，直到大学的时候第一次去Seeed Studio实习，跟同事们聊起FPGA时，我们一致认为FPGA是一个很有意思的领域，但是门槛太高，学习成本太高：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;—— “我搞过FPGA” &lt;br /&gt;
—— “歪日，牛的，兄弟” &lt;br /&gt;
—— “这碉板子贵的一批” &lt;br /&gt;
—— “多少钱” &lt;br /&gt;
—— “便宜的都得好几百” &lt;br /&gt;
—— “……我还是琢磨公司的XIAO吧”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;这玩意儿不是简单地修改代码就能运行起来的，不仅仅是“玩”，FPGA 使用自己的语言（通常是 Verilog 或 VHDL）进行编程，使用基于同步硬件的技术，并使用极其复杂的软件开发。&lt;/p&gt;

&lt;h2 id=&quot;mojo-v3-fpga-开发板概况&quot;&gt;Mojo V3 FPGA 开发板概况&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;1 个 Xilinx Spartan6 FPGA&lt;/li&gt;
  &lt;li&gt;8 个可编程的 LED&lt;/li&gt;
  &lt;li&gt;84 个 I/O 引脚。&lt;/li&gt;
  &lt;li&gt;1 个 Atmel AVR 32U4 MCU。&lt;/li&gt;
  &lt;li&gt;1 个 flash memory chip 用于存储 FPGA 配置数据&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;XC6SLX9 FPGA 是开发板的核心，它的内部有：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;9,152 个逻辑块&lt;/li&gt;
  &lt;li&gt;16 个 DSP 切片&lt;/li&gt;
  &lt;li&gt;576 KB RAM&lt;/li&gt;
  &lt;li&gt;102 个 I/O 引脚&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;我估摸着这应该是世界上第一个把FPGA和MCU结合在一起的开发板，之后的都是什么ARM+FPGA、ESP32+FPGA的设计，也都是参照这个设计的，让MCU可以把比特流文件从SPI Flash中烧录到FPGA里面，就不需要额外的 JTAG 线了。（赛灵思一个原厂JTAG实在是贵的不行，就相当于买一个FPGA一样，仿制的也贵的离谱）&lt;/p&gt;

&lt;p&gt;我也想借着闲赋在家的时候，整理整理这个FPGA的基础使用方法。板子的环境搭建我就放在【老物新用】这个栏目里面，具体的知识我再另外开设一个栏目。&lt;/p&gt;

&lt;h2 id=&quot;xilinx-ise-webpack-安装&quot;&gt;Xilinx ISE WebPACK 安装&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://www.xilinx.com/support/download/index.html/content/xilinx/en/downloadNav/vivado-design-tools/archive-ise.html&quot;&gt;AMD FPGA ISE Archive&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;这个软件是 Xilinx 早期的 FPGA 开发软件 ISE，现在已经不再维护了。也是神奇，之前接触FPGA还是赛灵思，转眼就被按摩店收购了。收购赛灵思之后感觉按摩店都起飞了，估计是用了不少赛灵思的IP核。&lt;/p&gt;

&lt;p&gt;进入到这个网页，找到14.7（14.7的Win10版本就是VirtualBox虚拟机），ISE Design Suite - 14.7  Full Product Installation，Full Installer for Linux (TAR/GZIP - 6.09 GB) MD5 SUM Value : e8065b2ffb411bb74ae32efa475f9817，点击该选项，跳转到AMD登录界面，登录完成后即可下载。&lt;/p&gt;

&lt;p&gt;下载完成后，解压到一个目录，然后进入到该目录，执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./xsetup&lt;/code&gt;，然后一路下一步，到选择产品的时候需要选择ISE WebPACK即可，等待安装完成。&lt;/p&gt;

&lt;p&gt;注意需要添加License，这个License可以在Xilinx官网申请，也可以在网上找到，我这里就&lt;s&gt;不&lt;/s&gt;&lt;a href=&quot;../img/post/2025/03/10/vivadolicense.zip&quot;&gt;提供&lt;/a&gt;了。&lt;/p&gt;

&lt;s&gt;
安装完之后，需要添加环境变量，打开 `/etc/environment` 文件，添加如下内容：
&lt;/s&gt;
&lt;s&gt;
```shell
# Xilinx ISE WebPACK
. /opt/Xilinx/14.7/ISE_DS/settings64.sh &amp;gt;/dev/null 2&amp;gt;&amp;amp;1
```
&lt;/s&gt;
&lt;s&gt;
其中 `. /opt/Xilinx/14.7/ISE_DS/settings64.sh` 是官方给的，安装完之后会提示你运行这个命令，这个命令会设置一些环境变量，然后就可以在终端中使用 `ise` 命令打开软件了。我就是图方便加到 `.bashrc` 里面的。但是每次开终端都会有运行结果显示，所以我加了 `&amp;gt;/dev/null 2&amp;gt;&amp;amp;1`。
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;i&gt;
至于为什么不加到 `/etc/environment` 和 `.bashrc` 文件里面，是因为加了之后不知道为啥会影响到其他软件的运行，导致其他软件无法正常运行
&lt;/i&gt;&lt;/p&gt;
&lt;/s&gt;

&lt;p&gt;建议是使用shell脚本启动环境：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# /opt/start_ise.sh&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Xilinx ISE WebPACK&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; /opt/Xilinx/14.7/ISE_DS/settings64.sh &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;/dev/null 2&amp;gt;&amp;amp;1
ise &amp;amp; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;/dev/null 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后给这个脚本添加执行权限：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo chmod&lt;/span&gt; +x /opt/start_ise.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;mojo-loader-和-mojo-ide-安装&quot;&gt;Mojo Loader 和 Mojo IDE 安装&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/IcingTomato/MojoFPGA&quot;&gt;IcingTomato/MojoFPGA - GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;这个是我以前下载的 Mojo Loader 和 Mojo IDE 的程序，上传到了 GitHub 上留作备份。这两个程序一个是用来烧录 FPGA 的，另一个是用来编写代码的。&lt;/p&gt;

&lt;p&gt;将 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mojo-ide-B1.3.6-linux64.tgz&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mojo-loader-1.3.0-linux64.tgz&lt;/code&gt; 下载到本地，解压到一个目录，然后进入到该目录，执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./mojo-ide&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./mojo-loader&lt;/code&gt; 即可。&lt;/p&gt;

&lt;p&gt;要注意的是，Mojo IDE 需要JDK8，如果没有安装的话，可以使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo apt install openjdk-8-jdk&lt;/code&gt; 安装。&lt;/p&gt;

&lt;p&gt;我这边为了方便，把这两个程序解压到了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/opt/&lt;/code&gt; 目录下，然后创建软链接：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo chmod&lt;/span&gt; +x /opt/mojo-ide-B1.3.6-linux64/mojo-ide
&lt;span class=&quot;nb&quot;&gt;sudo chmod&lt;/span&gt; +x /opt/mojo-loader-1.3.0-linux64/mojo-loader
&lt;span class=&quot;nb&quot;&gt;sudo ln&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; /opt/mojo-ide-B1.3.6-linux64/mojo-ide /usr/bin/mojo-ide
&lt;span class=&quot;nb&quot;&gt;sudo ln&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; /opt/mojo-loader-1.3.0-linux64/mojo-loader /usr/bin/mojo-loader
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这样就可以在终端中使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mojo-ide&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mojo-loader&lt;/code&gt; 命令了。&lt;/p&gt;

&lt;h2 id=&quot;mojo-loader-使用&quot;&gt;Mojo Loader 使用&lt;/h2&gt;

&lt;p&gt;打开终端，输入 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mojo-loader&lt;/code&gt;，然后选择你的 FPGA 开发板，然后选择你的比特流文件，然后点击 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Erase&lt;/code&gt;，等待擦除完成后即可点击 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Load&lt;/code&gt; 将bin文件加载到Flash。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2025/03/10/2.png&quot; alt=&quot;Mojo Loader&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;mojo-ide-使用&quot;&gt;Mojo IDE 使用&lt;/h2&gt;

&lt;p&gt;建议是使用shell脚本启动环境：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# /opt/start_mojo_ide.sh&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Xilinx ISE WebPACK&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; /opt/Xilinx/14.7/ISE_DS/settings64.sh &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;/dev/null 2&amp;gt;&amp;amp;1
mojo_ide &amp;amp; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;/dev/null 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后给这个脚本添加执行权限：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo chmod&lt;/span&gt; +x /opt/start_mojo_ide.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2025/03/10/3.png&quot; alt=&quot;Mojo IDE&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;补充记录&quot;&gt;补充记录&lt;/h2&gt;

&lt;p&gt;针对 ISE 和 Mojo IDE/Loader 在开始菜单的显示问题，我在后续使用的时候琢磨出来了，找到一个相对比较好的解决方案：&lt;/p&gt;

&lt;h3 id=&quot;ise-配置&quot;&gt;ISE 配置&lt;/h3&gt;

&lt;p&gt;先安装完 ISE WebPACK，打开终端，输入：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /usr/share/applications/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后创建一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ise.desktop&lt;/code&gt; 文件：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;vim ise.desktop
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后输入以下内容：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;Desktop Entry] 
&lt;span class=&quot;nv&quot;&gt;Version&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1.0 
&lt;span class=&quot;nv&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;ISE 
&lt;span class=&quot;nv&quot;&gt;Exec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;bash &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;unset LANG &amp;amp;&amp;amp; unset QT_PLUGIN_PATH &amp;amp;&amp;amp; source /opt/Xilinx/14.7/ISE_DS/settings64.sh &amp;amp;&amp;amp; ise&quot;&lt;/span&gt; 
&lt;span class=&quot;nv&quot;&gt;Icon&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/opt/Xilinx/14.7/ISE_DS/ISE/data/images/pn-ise.png
&lt;span class=&quot;nv&quot;&gt;Terminal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;false 
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;Application
&lt;span class=&quot;nv&quot;&gt;Categories&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;Development&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;保存退出。&lt;/p&gt;

&lt;h3 id=&quot;mojo-ide-配置&quot;&gt;Mojo IDE 配置&lt;/h3&gt;

&lt;p&gt;同样的，打开终端，输入：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /opt/MojoFPGA/mojo-ide-B1.3.6/
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;vim mojo-ide.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后输入以下内容：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# Xilinx ISE WebPACK&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; /opt/Xilinx/14.7/ISE_DS/settings64.sh &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;/dev/null 2&amp;gt;&amp;amp;1
&lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; /opt/MojoFPGA/mojo-ide-B1.3.6/mojo-ide &amp;amp; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;/dev/null 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;保存退出。&lt;/p&gt;

&lt;p&gt;然后给这个脚本添加执行权限：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo chmod&lt;/span&gt; +x /opt/MojoFPGA/mojo-ide-B1.3.6/mojo-ide.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后添加软链接：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo ln&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; /opt/MojoFPGA/mojo-ide-B1.3.6/mojo-ide.sh /usr/sbin/mojo-ide
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;再回到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/share/applications/&lt;/code&gt; 目录，创建一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mojo-ide.desktop&lt;/code&gt; 文件：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;vim mojo-ide.desktop
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后输入以下内容：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;Desktop Entry] 
&lt;span class=&quot;nv&quot;&gt;Version&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1.0 
&lt;span class=&quot;nv&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;Mojo IDE 
&lt;span class=&quot;nv&quot;&gt;Exec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/sbin/mojo-ide
&lt;span class=&quot;nv&quot;&gt;Icon&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/opt/MojoFPGA/mojo-ide-B1.3.6/icon.png
&lt;span class=&quot;nv&quot;&gt;Terminal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;false
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;Application
&lt;span class=&quot;nv&quot;&gt;Categories&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;Development&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;保存退出。&lt;/p&gt;

&lt;p&gt;这样就可以在开始菜单中找到 ISE 和 Mojo IDE 了。&lt;/p&gt;

&lt;h3 id=&quot;mojo-loader-配置&quot;&gt;Mojo Loader 配置&lt;/h3&gt;

&lt;p&gt;先创建软链接：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo ln&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; /opt/MojoFPGA/mojo-loader-1.3.0/mojo-loader /usr/sbin/mojo-loader
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;同样的，打开终端，输入：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /usr/share/applications/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后创建一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mojo-loader.desktop&lt;/code&gt; 文件：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;Desktop Entry] 
&lt;span class=&quot;nv&quot;&gt;Version&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;1.0 
&lt;span class=&quot;nv&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;Mojo Loader 
&lt;span class=&quot;nv&quot;&gt;Exec&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/usr/sbin/mojo-loader
&lt;span class=&quot;nv&quot;&gt;Icon&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/opt/MojoFPGA/mojo-loader-1.3.0/icon.png
&lt;span class=&quot;nv&quot;&gt;Terminal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;false
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;Application
&lt;span class=&quot;nv&quot;&gt;Categories&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;Development&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;保存退出。&lt;/p&gt;

&lt;p&gt;这样就可以在开始菜单中找到 Mojo Loader 了。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2025/03/10/4.png&quot; alt=&quot;Desktop Shortcut&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>【家庭网络改造】QNAP NAS计划任务自动删除米家摄像头三个月前的视频文件</title>
   <link href="https://icing.fun/posts/qnap_nas_xiaomi_cam.html"/>
   <updated>2024-11-27T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/qnap_nas_xiaomi_cam</id>
   <content type="html">&lt;p&gt;去年8月29日在京东下单了一个QNAP威联通的TS-216，替换掉我家原来自己用树莓派3B+（Ubuntu Server + Samba）搭建的NAS。装了两个东芝P300 2TB的硬盘，开始组的RAID 1。后来发现家里面四五个摄像头每天的数据量大得很，没几天就把硬盘写满了。后面想想RAID 1不实在，家里没啥重要数据，今年回家的时候就格盘换成RAID 0了。但是米家摄像头数据还是很大，没几个月3.6TB就快写满了。&lt;/p&gt;

&lt;p&gt;于是在米家APP中找到了视频存储时长设置选项，改成3个月：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2024/11/27/1.jpg&quot; alt=&quot;米家APP中视频存储时长设置选项&quot; /&gt;&lt;/p&gt;

&lt;p&gt;改了之后NAS上面数据一点没动，应该是不会删除NAS上面的视频数据，所以就想着让NAS怎么自动删除米家摄像头三个月前的视频文件。&lt;/p&gt;

&lt;p&gt;(以下所有操作需提前在NAS中开启SSH服务)&lt;/p&gt;

&lt;p&gt;首先想到的是用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;crontab&lt;/code&gt;，但是QNAP的Linux系统是基于BusyBox的，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;crontab -e&lt;/code&gt; 这种命令有，但是不会运行成功，即便是加上 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo&lt;/code&gt; ，也不能保存计划任务。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2024/11/27/2.png&quot; alt=&quot;crontab -e&quot; /&gt;&lt;/p&gt;

&lt;p&gt;所以只能使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vi&lt;/code&gt; 命令编辑计划任务文件，文件路径是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/config/crontab&lt;/code&gt; ，在文件末尾加上：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;0 &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /share/MiCam/xiaomi_camera_videos &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; bash auto_del.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2024/11/27/3.png&quot; alt=&quot;vi /etc/config/crontab&quot; /&gt;&lt;/p&gt;

&lt;p&gt;这个命令的意思是每小时执行一次 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;auto_del.sh&lt;/code&gt; 脚本，脚本内容如下：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Set the base directory where random directories are located&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;base_directory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;./&quot;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Calculate the date threshold for deletion (3 months ago)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;date_threshold&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;date&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--date&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;-3 months&apos;&lt;/span&gt; +&lt;span class=&quot;s1&quot;&gt;&apos;%Y%m%d00&apos;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Before &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$date_threshold&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; will be deleted!&quot;&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# Find all random directories and process them&lt;/span&gt;
find &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$base_directory&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-maxdepth&lt;/span&gt; 1 &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; d &lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;[0-9a-f]*&apos;&lt;/span&gt; | &lt;span class=&quot;k&quot;&gt;while &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;# Change directory to the random directory&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$dir&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;continue&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;# Skip if directory change fails&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Entry &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$dir&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.&quot;&lt;/span&gt;

  &lt;span class=&quot;c&quot;&gt;# Find and delete directories older than the threshold&lt;/span&gt;
  find &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-maxdepth&lt;/span&gt; 1 &lt;span class=&quot;nt&quot;&gt;-type&lt;/span&gt; d &lt;span class=&quot;nt&quot;&gt;-name&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;??????????&apos;&lt;/span&gt; | &lt;span class=&quot;k&quot;&gt;while &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; subdir&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do
    if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;basename&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$subdir&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-lt&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$date_threshold&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;then
      &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Deleting directory: &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$subdir&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
      &lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-rf&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$subdir&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;  &lt;span class=&quot;c&quot;&gt;# Remove the directory recursively&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;fi
  done&lt;/span&gt;

  &lt;span class=&quot;c&quot;&gt;# Change back to the base directory&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ..
&lt;span class=&quot;k&quot;&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;手动运行结果如下：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2024/11/27/4.png&quot; alt=&quot;Run script&quot; /&gt;&lt;/p&gt;

&lt;p&gt;因为米家摄像头会在设置的文件夹下创建 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xiaomi_camera_videos&lt;/code&gt; 文件夹，然后在这个文件夹下以设备序列号（？）创建的很像乱码的文件夹，每个乱码文件夹下面又以&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;年月日时&lt;/code&gt;为名的文件夹，所以这个脚本的作用是删除 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xiaomi_camera_videos/??????????&lt;/code&gt; 文件夹下三个月前的视频文件夹。所以脚本必须放在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/目标文件夹/xiaomi_camera_videos&lt;/code&gt;下：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2024/11/27/5.png&quot; alt=&quot;Script destination&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>【网络基础】什么是NAT？</title>
   <link href="https://icing.fun/posts/type_of_nat.html"/>
   <updated>2024-11-22T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/type_of_nat</id>
   <content type="html">&lt;p&gt;NAT是一种地址转换技术，它可以将IP数据报文头中的IP地址转换为另一个IP地址，并通过转换端口号达到地址重用的目的。NAT作为一种缓解IPv4公网地址枯竭的过渡技术，由于实现简单，得到了广泛应用。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#title1&quot;&gt;&lt;strong&gt;1&lt;/strong&gt;　NAT解决了什么问题？　&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#title2&quot;&gt;&lt;strong&gt;2&lt;/strong&gt;　NAT的类型　&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#title3&quot;&gt;&lt;strong&gt;3&lt;/strong&gt;　NAT是如何工作的？　&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#title4&quot;&gt;&lt;strong&gt;4&lt;/strong&gt;　如何使用NAT？&lt;/a&gt;　&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;nat解决了什么问题&quot;&gt;&lt;span id=&quot;title1&quot;&gt;NAT解决了什么问题？&lt;/span&gt;&lt;/h2&gt;

&lt;p&gt;随着网络应用的增多，IPv4地址枯竭的问题越来越严重。尽管IPv6可以从根本上解决IPv4地址空间不足问题，但目前众多网络设备和网络应用大多是基于IPv4的，因此在IPv6广泛应用之前，使用一些过渡技术（如CIDR、私网地址等）是解决这个问题的主要方式，NAT就是这众多过渡技术中的一种。&lt;/p&gt;

&lt;p&gt;当私网用户访问公网的报文到达网关设备后，如果网关设备上部署了NAT功能，设备会将收到的IP数据报文头中的IP地址转换为另一个IP地址，端口号转换为另一个端口号之后转发给公网。在这个过程中，设备可以用同一个公网地址来转换多个私网用户发过来的报文，并通过端口号来区分不同的私网用户，从而达到地址复用的目的。&lt;/p&gt;

&lt;p&gt;早期的NAT是指Basic NAT，Basic NAT在技术上实现比较简单，只支持地址转换，不支持端口转换。因此，Basic NAT只能解决私网主机访问公网问题，无法解决IPv4地址短缺问题。后期的NAT主要是指网络地址端口转换NAPT（Network Address Port Translation），NAPT既支持地址转换也支持端口转换，允许多台私网主机共享一个公网IP地址访问公网，因此NAPT才可以真正改善IP地址短缺问题。&lt;/p&gt;

&lt;h2 id=&quot;nat的类型&quot;&gt;&lt;span id=&quot;title2&quot;&gt;NAT的类型&lt;/span&gt;&lt;/h2&gt;

&lt;p&gt;根据NAT转换是对报文中的源地址进行转换还是对目的地址进行转换，NAT可以分为源NAT、目的NAT和双向NAT，下面我们分别介绍这三种NAT类型。&lt;/p&gt;

&lt;h3 id=&quot;snat源nat&quot;&gt;SNAT（源NAT）&lt;/h3&gt;

&lt;p&gt;源NAT在NAT转换时，仅对报文中的源地址进行转换，主要应用于私网用户访问公网的场景。当私网用户主机访问Internet时，私网用户主机发送的报文到达NAT设备后，设备通过源NAT技术将报文中的私网IPv4地址转换成公网IPv4地址，从而使私网用户可以正常访问Internet。&lt;/p&gt;

&lt;p&gt;根据转换时是否同时转换源端口号，源NAT可以细分为如下几种类型，详见下图。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2024/11/22/1.png&quot; alt=&quot;源NAT分类&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;dnat目的nat&quot;&gt;DNAT（目的NAT）&lt;/h3&gt;

&lt;p&gt;目的NAT在NAT转换时，仅对报文中的目的地址和目的端口号进行转换，主要应用于公网用户访问私网服务的场景。当公网用户主机发送的报文到达NAT设备后，设备通过目的NAT技术将报文中的公网IPv4地址转换成私网IPv4地址，从而使公网用户可以使用公网地址访问私网服务。&lt;/p&gt;

&lt;p&gt;根据转换前后的地址是否存在一种固定的映射关系，目的NAT可以细分为如下几种类型，详见下图。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2024/11/22/2.png&quot; alt=&quot;目的NAT分类&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;双向nat&quot;&gt;双向NAT&lt;/h3&gt;

&lt;p&gt;双向NAT指的是在转换过程中同时转换报文的源信息和目的信息。双向NAT不是一个单独的功能，而是源NAT和目的NAT的组合。双向NAT是针对同一条流，在其经过设备时同时转换报文的源地址和目的地址。双向NAT主要应用在同时有外网用户访问内部服务器和私网用户访问内部服务器的场景。&lt;/p&gt;

&lt;h3 id=&quot;stun中定义的nat类型&quot;&gt;STUN中定义的NAT类型&lt;/h3&gt;

&lt;p&gt;在STUN标准中，根据私网IP地址和端口到NAT出口的公网IP地址和端口的映射方式，把NAT分为如下四种类型，详见下图。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2024/11/22/3.png&quot; alt=&quot;STUN中定义的NAT类型&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Full Cone NAT（完全锥型NAT）&lt;/p&gt;

    &lt;p&gt;所有从同一个私网IP地址和端口（IP1:Port1）发送过来的请求都会被映射成同一个公网IP地址和端口（IP:Port）。并且，任何外部主机通过向映射的公网IP地址和端口发送报文，都可以实现和内部主机进行通信。&lt;/p&gt;

    &lt;p&gt;这是一种比较宽松的策略，只要建立了私网IP地址和端口与公网IP地址和端口的映射关系，所有的Internet上的主机都可以访问该NAT之后的主机。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Restricted Cone NAT（限制锥型NAT）&lt;/p&gt;

    &lt;p&gt;所有从同一个私网IP地址和端口（IP1:Port1）发送过来的请求都会被映射成同一个公网IP和端口号（IP:Port）。与完全锥型NAT不同的是，当且仅当内部主机之前已经向公网主机发送过报文，此时公网主机才能向私网主机发送报文。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Port Restricted Cone NAT（端口限制锥型NAT）&lt;/p&gt;

    &lt;p&gt;与限制锥型NAT很相似，只不过它包括端口号。也就是说，一台公网主机（IP2:Port2）想给私网主机发送报文，必须是这台私网主机先前已经给这个IP地址和端口发送过报文。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Symmetric NAT（对称NAT）&lt;/p&gt;

    &lt;p&gt;所有从同一个私网IP地址和端口发送到一个特定的目的IP地址和端口的请求，都会被映射到同一个IP地址和端口。如果同一台主机使用相同的源地址和端口号发送报文，但是发往不同的目的地，NAT将会使用不同的映射。此外，只有收到数据的公网主机才可以反过来向私网主机发送报文。&lt;/p&gt;

    &lt;p&gt;这和端口限制锥型NAT不同，端口限制锥型NAT是所有请求映射到相同的公网IP地址和端口，而对称NAT是不同的请求有不同的映射。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;nat是如何工作的&quot;&gt;&lt;span id=&quot;title3&quot;&gt;NAT是如何工作的？&lt;/span&gt;&lt;/h2&gt;

&lt;p&gt;根据前面的分类，我们分别从源NAT和目的NAT中各选一种NAT为代表，介绍其工作原理。其他类型的NAT虽然在转换时，转换的内容有细微差别，但是工作原理都相似，不再重复介绍。此外，双向NAT是源NAT和目的NAT的组合，双向NAT的工作原理也不再重复介绍。&lt;/p&gt;

&lt;h3 id=&quot;napt工作原理&quot;&gt;NAPT工作原理&lt;/h3&gt;

&lt;p&gt;NAPT在进行地址转换的同时还进行端口转换，可以实现多个私网用户共同使用一个公网IP地址上网。NAPT根据端口来区分不同用户，真正做到了地址复用。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2024/11/22/4.png&quot; alt=&quot;NAPT工作原理示意图&quot; /&gt;&lt;/p&gt;

&lt;p&gt;当Host访问Web Server时，设备的处理过程如下：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;设备收到Host发送的报文后查找NAT策略，发现需要对报文进行地址转换。&lt;/li&gt;
  &lt;li&gt;设备根据源IP Hash算法从NAT地址池中选择一个公网IP地址，替换报文的源IP地址，同时使用新的端口号替换报文的源端口号，并建立会话表，然后将报文发送至Internet。&lt;/li&gt;
  &lt;li&gt;设备收到Web Server响应Host的报文后，通过查找会话表匹配到步骤2中建立的表项，将报文的目的地址替换为Host的IP地址，将报文的目的端口号替换为原始的端口号，然后将报文发送至Intranet。&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;nat-server工作原理&quot;&gt;NAT Server工作原理&lt;/h3&gt;
&lt;p&gt;使用NAT Server时，需要先在设备上配置公网地址和私网地址的固定映射关系。配置完成后，设备将会生成Server-Map表项，存放公网地址和私网地址的映射关系。该表项将一直存在除非NAT Server的配置被删除。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2024/11/22/5.png&quot; alt=&quot;NAT Server工作原理示意图&quot; /&gt;&lt;/p&gt;

&lt;p&gt;内部Server的私网IPv4地址为192.168.1.2/24，对外的公网IPv4地址为1.1.1.10，端口号都为80，它们之间的映射关系在设备上已提前配置好。当Host访问Server时，设备的处理过程如下：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;设备收到Internet上用户访问1.1.1.10的报文的首包后，查找并匹配到Server-Map表项，将报文的目的IP地址转换为192.168.1.2。&lt;/li&gt;
  &lt;li&gt;设备建立会话表，然后将报文发送至Intranet。&lt;/li&gt;
  &lt;li&gt;设备收到Server响应Host的报文后，通过查找会话表匹配到步骤2中建立的表项，将报文的源地址替换为1.1.1.10，然后将报文发送至Internet。&lt;/li&gt;
  &lt;li&gt;后续Host继续发送给Server的报文，设备都会直接根据会话表项的记录对其进行转换，而不会再去查找Server-map表项。&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;如何使用nat&quot;&gt;&lt;span id=&quot;title4&quot;&gt;如何使用NAT？&lt;/span&gt;&lt;/h2&gt;

&lt;p&gt;前面已经介绍了，不同的NAT类型适用于不同的应用场景。下面介绍几种典型的NAT应用，帮助用户使用NAT。&lt;/p&gt;

&lt;h3 id=&quot;私网用户通过napt访问internet&quot;&gt;私网用户通过NAPT访问Internet&lt;/h3&gt;

&lt;p&gt;在许多小区、学校和企业的私网规划中，由于公网地址资源有限，通常给私网用户分配私网IPv4地址。此时，可以配置源NAT来实现私网用户访问Internet。用户可以根据自己拥有的公网IPv4地址的个数，选择使用NAPT或者Easy IP。&lt;/p&gt;

&lt;p&gt;当用户拥有的公网IP地址个数较多时，配置了NAT设备出接口的IP地址和其他应用之后，还有可用的空闲公网IP地址时，可以选择NAPT。NAPT使用地址池内的IPv4地址作为私网主机转换后的公网IPv4地址。如下图所示，在设备上配置NAPT，实现私网主机访问Internet功能。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2024/11/22/6.png&quot; alt=&quot;私网用户通过NAPT访问Internet&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;私网用户通过easy-ip访问internet&quot;&gt;私网用户通过Easy IP访问Internet&lt;/h3&gt;

&lt;p&gt;当用户拥有的公网IPv4地址个数较少时，配置了NAT设备出接口的IPv4地址和其他应用之后，没有可用的空闲公网IPv4地址时，可以选择Easy IP。Easy IP使用出接口的IPv4地址作为私网主机转换后的公网IPv4地址。如下图所示，在设备上配置Easy IP，实现私网主机访问Internet功能。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2024/11/22/7.png&quot; alt=&quot;私网用户通过Easy IP访问Internet&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;公网用户通过nat-server访问私网服务器&quot;&gt;公网用户通过NAT Server访问私网服务器&lt;/h3&gt;

&lt;p&gt;在某些场合，私网中有一些服务器需要向公网用户提供服务，比如私网中部署的一些Web服务器、FTP服务器等，NAT支持这样的应用，此时可以配置NAT Server来实现公网用户访问私网服务器。如下图所示，在设备上配置NAT Server，固定“公网IP地址＋端口号”与“私网IP地址＋端口号”间的映射关系，实现公网主机通过该映射关系访问私网服务器功能。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2024/11/22/8.png&quot; alt=&quot;公网用户通过NAT Server访问私网服务器&quot; /&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>【WSFC 学习笔记】如何理解 Windows Server 故障转移群集 的 Quorum</title>
   <link href="https://icing.fun/posts/wsfc_quorum.html"/>
   <updated>2024-04-20T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/wsfc_quorum</id>
   <content type="html">&lt;h1 id=&quot;前言&quot;&gt;前言&lt;/h1&gt;

&lt;p&gt;最近一个月一直在学高可用的东西，其中 WSFC 是其中一个重要的组成部分。在学习 WSFC 的过程中，我发现了一个很重要的概念：Quorum，这个概念网上一找全是照着微软官方文档写的 &lt;a href=&quot;https://learn.microsoft.com/en-us/windows-server/failover-clustering/manage-cluster-quorum#quorum-configuration-options&quot;&gt;仲裁配置选项&lt;/a&gt;。问有什么模型的时候头头是道，什么节点多数无见证啊、仅磁盘见证啊什么的，一问啥是仲裁（Quorum）和见证（Witness）的时候傻眼了。所以我决定写一篇文章来总结一下我对 Quorum 的理解。&lt;/p&gt;

&lt;h1 id=&quot;仲裁quorum是什么&quot;&gt;仲裁（Quorum）是什么&lt;/h1&gt;

&lt;p&gt;仲裁（Quorum）是 WSFC 中的一个重要概念，它是用来保证群集中的节点之间能够达成一致的一个机制。在 WSFC 中，仲裁是通过仲裁资源来实现的，这个资源可以是磁盘、文件共享、或者是其他的仲裁资源。在 WSFC 中，仲裁资源的作用是用来保证群集中的节点之间能够达成一致，从而保证群集的正常运行。&lt;/p&gt;

&lt;p&gt;依我看，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Quorum&lt;/code&gt; 其实应该翻译成 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;有效参与仲裁的设备（数）&lt;/code&gt;，因为 Quorum 本来就翻译成 &lt;a href=&quot;https://dictionary.cambridge.org/dictionary/english/quorum&quot;&gt;法定人数/出席会议最小人数&lt;/a&gt;，不应该直接叫 仲裁。&lt;/p&gt;

&lt;p&gt;现在涉及到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;仲裁&lt;/code&gt; 这个法律概念，所以我们可以引入法律属于去解释。在法律中，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;仲裁&lt;/code&gt; 是指一种解决纠纷的方式，当纠纷发生时，双方可以通过仲裁的方式来解决纠纷。在法律仲裁中，仲裁员是一个独立的第三方，他们会根据法律和事实来做出裁决。但在 WSFC 中，仲裁员（节点/服务器/虚拟机）既是当事人（所有节点），又参与仲裁庭，它们会根据法律和事实（仲裁模型）来做出裁决，是用来保证群集中的节点之间能够达成一致的。&lt;/p&gt;

&lt;p&gt;节点多数，无见证：由节点组织“合议制仲裁庭”，当事人（所有参与群集的节点/服务器）约定由奇数名仲裁员（节点）组成仲裁庭（偶数节点就使其中一个节点下线），其中一名为首席仲裁员（主节点/服务器）；如果是双节点就采取“独任制仲裁庭”，只推举一名仲裁员（一个节点做主服务器，另外一个下线）。&lt;/p&gt;

&lt;p&gt;磁盘、文件共享见证：见证人是证人之外知道案件情况的当事人（所以磁盘、文件共享见证需要对所有节点可见，在注册表中节点文件是Cluster，见证文件是0.Cluster，可以证明见证确实是“当事人”）。见证人不参与仲裁庭，但是可以提供证据（见证文件）。&lt;/p&gt;

&lt;p&gt;总结来说：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;节点多数，无见证：
    &lt;ul&gt;
      &lt;li&gt;合议庭：集群的所有活动节点。&lt;/li&gt;
      &lt;li&gt;仲裁庭成员：每个节点都可以投票决定集群状态，若节点总数为偶数，可能需要让一个节点下线以避免平票。&lt;/li&gt;
      &lt;li&gt;首席仲裁员（主节点）：在实际的WSFC中，通常没有固定的“首席仲裁员”或主节点，所有节点理论上是平等的，但在实践中，某些节点可能因为资源位置或网络优势暂时承担更多责任。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;双节点集群的“独任制”：
    &lt;ul&gt;
      &lt;li&gt;这种情况下，通常需要额外的见证（磁盘或文件共享见证），因为单纯的两个节点在一个节点失效时无法决定集群状态。如果不使用见证，确实可能会推举一个节点为主导，另一个则在主节点活跃时处于待命状态。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;磁盘、文件共享见证：
    &lt;ul&gt;
      &lt;li&gt;见证人：在这种情况下，见证（文件共享或磁盘）充当了“知情人”，它存储关于集群配置的关键信息，确保在节点间的意见不一致时提供“证据”来帮助做出决策。见证的存在特别在节点数为偶数时非常关键，以避免平票问题。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;但是大多数人对法律仲裁制度不了解，而且法律仲裁制度和 WSFC 中的仲裁机制有很大的不同，所以我觉得这个比喻不太合适。&lt;/p&gt;

&lt;p&gt;所以我决定引入日常生活，比如双节点集群就像情侣之间决定晚餐吃什么，引入磁盘见证相当于三口之家中孩子的存在，这样比喻起来更加贴近生活，也更容易理解。&lt;/p&gt;

&lt;p&gt;原文如下：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Mode&lt;/th&gt;
      &lt;th&gt;Description&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Node majority (no witness) &lt;br /&gt; &lt;b&gt;节点多数&lt;/b&gt;&lt;/td&gt;
      &lt;td&gt;Only nodes have votes. No quorum witness is configured. The cluster quorum is the majority of voting nodes in the active cluster membership.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Node majority with witness (disk or file share) &lt;br /&gt; &lt;b&gt;节点多数+见证&lt;/b&gt;&lt;/td&gt;
      &lt;td&gt;Nodes have votes. In addition, a quorum witness has a vote. The cluster quorum is the majority of voting nodes in the active cluster membership plus a witness vote. A quorum witness can be a designated disk witness or a designated file share witness.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;No majority (disk witness only) &lt;br /&gt; &lt;b&gt;仅磁盘见证&lt;/b&gt;&lt;/td&gt;
      &lt;td&gt;No nodes have votes. Only a disk witness has a vote. &lt;br /&gt; The cluster quorum is determined by the state of the disk witness. Generally, this mode is not recommended, and it should not be selected because it creates a single point of failure for the cluster.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&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;br /&gt; &lt;b&gt;节点多数&lt;/b&gt;&lt;/td&gt;
      &lt;td&gt;【双节点】男生让渡（即其中一节点下线，有一票投票权但动态见证干预其不投票），让女生（主节点/服务器/虚拟机 Owner Node）来选择点什么外卖或者出去吃什么餐馆。&lt;s&gt;你就负责买单就行。&lt;/s&gt; &lt;br /&gt; 【三节点及以上】女生带闺蜜来了，女生和闺蜜手拉手胳膊挽胳膊掌握晚餐选择主动权（即具有集群的控制权，在一个三节点集群中，通常需要至少两个节点在线并相互通信，以维持集群的正常操作）。象征性问你一下想吃什么。&lt;s&gt;所以你还是负责买单的小丑。&lt;/s&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;核心家庭（三口之家）或扩展家庭（爸妈或者和爷爷奶奶外公外婆一起为节点，孩子为见证）&lt;br /&gt; &lt;b&gt;节点多数+见证&lt;/b&gt;&lt;/td&gt;
      &lt;td&gt;&lt;s&gt;爸妈想吃啥就做啥，你的意见仅供参考&lt;/s&gt; &lt;br /&gt; 因为爷爷奶奶外公外婆说孩子想吃这个那个，所以爸妈做饭就做了大家都爱吃的东西。（换句话说见证也参与，而不仅仅是节点多数）&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;你过生日那天 &lt;br /&gt; &lt;b&gt;仅磁盘见证&lt;/b&gt;&lt;/td&gt;
      &lt;td&gt;&lt;s&gt;“妈，我生日想吃开封菜。” “不行，油炸食品不健康。”&lt;/s&gt; （别看上面的见证是你，但是这一条就不是你了）&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2024/04/20/1.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2024/04/20/2.png&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;总结&quot;&gt;总结&lt;/h1&gt;

&lt;p&gt;给我写乐了。宿舍停水了，舍友用我的博客洗完了澡。&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>【阅板无数】（Intel x86 IoT系列）Intel Arduino/Genuino 101 简单测评</title>
   <link href="https://icing.fun/posts/intel_genuino_101.html"/>
   <updated>2024-01-20T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/intel_genuino_101</id>
   <content type="html">&lt;p&gt;&lt;em&gt;注：下文中 Intel Arduino/Genuino 101 简称为 Arduino 101&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2024/01/20/1.jpg&quot; /&gt;
&lt;em&gt;Arduino 101&lt;/em&gt;&lt;/p&gt;

&lt;h1 id=&quot;arduinogenuino-101-的由来&quot;&gt;Arduino/Genuino 101 的由来&lt;/h1&gt;

&lt;p&gt;2015年10月16日&lt;a href=&quot;#jump1&quot;&gt;&lt;sup&gt;1&lt;/sup&gt;&lt;/a&gt;，距离世界上第一台商用可编程计算器 Olivetti Programma 101&lt;a href=&quot;#jump2&quot;&gt;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt; 问世过去了整整50年。为了致敬这个伟大的项目，英特尔和 Massimo Banzi&lt;a href=&quot;#jump3&quot;&gt;&lt;sup&gt;3&lt;/sup&gt;&lt;/a&gt;（Arduino项目的联合创始人）在 Maker Faire 宣布推出一款新的开发板，名为Arduino/Genuino 101 —— 一款专为教育用途、创客世界和首次接触编程的人设计的开发板。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2024/01/20/2.jpg&quot; /&gt;
&lt;em&gt;Olivetti Programma 101&lt;/em&gt;&lt;/p&gt;

&lt;h1 id=&quot;arduinogenuino-101-的硬件和软件&quot;&gt;Arduino/Genuino 101 的硬件和软件&lt;/h1&gt;

&lt;p&gt;Arduino 101是一款学习和开发板，以入门级价格提供英特尔® Curie™ 模块的性能和低功耗以及 Arduino 的简单性。它保留了与 UNO 相同的强大外形和外设列表，并增加了板载低功耗蓝牙®（Bluetooth Low Energy，BLE，Nordic 的 nRF512822）功能和 6 轴加速度计/陀螺仪（Bosch 的 BMI160）。&lt;/p&gt;

&lt;p&gt;Arduino 101 使用的 Curie™ 模块属于异构双核，包含两个微型内核，一个 x86 （Quark SE，SE 即 Second Edition） 和一个 32 位 ARC 架构内核，时钟频率均为 32MHz。英特尔工具链可在两个内核上以最佳方式编译 Arduino 草图，以完成要求最苛刻的任务。英特尔开发的实时操作系统 （Zephyr） 和框架是开源的。其中，ARC架构是一种32位的RISC处理器架构，由 Synopsys（新思科技）开发。&lt;/p&gt;

&lt;p&gt;101 带有 14 个数字输入/输出引脚（其中 4 个可用作 PWM 输出）、6 个模拟输入、一个用于串行通信和草图上传的 USB 连接器、一个电源插孔、一个带 SPI 信号的 ICSP 接头和 I2C 专用引脚。电路板工作电压和 I/O 为 3.3V，但所有引脚均具有 5V 过压保护。&lt;/p&gt;

&lt;p&gt;相较于标准 Arduino Uno， Arduino 101 采用的异构双核的 Curie™ 模块比 8位的 Atmel 328p 微控制器更强大，存储空间也更大（Intel 官方的 Curie 规格是 384KB Flash 与 80KB SRAM ，但相关报导写 196KB Flash 与 24KB RAM，Arduino 官网写 384KB Flash 与 80KB SRAM，但 SRAM 部分注明只有 24KB 可供应用程序 Sketch 使用。因此，推估之所以写 196KB Flash，应该也是系统占据一部分，真正可供运用的是 196KB。除此之外电路板上似乎又增设2MB Flash 可供 Curie 使用）&lt;/p&gt;

&lt;p&gt;在2016年4月21日，英特尔发布 Arduino 101 固件源代码。包含用于 101 上 Curie 处理器的完整 BSP（板级支持包）。它允许您编译和修改核心操作系统和固件，以管理更新和引导加载程序。固件在 Curie 模块内的 x86 芯片上运行，并使用 &lt;em&gt;回调&lt;/em&gt; 与 ARC 内核（运行 Arduino 程序）进行通信。x86 内核负责处理低功耗蓝牙® （BLE） 和 USB 通信，从而减轻 ARC 内核的负担。&lt;a href=&quot;#jump4&quot;&gt;&lt;sup&gt;4&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;技术规格5&quot;&gt;技术规格&lt;a href=&quot;#jump5&quot;&gt;&lt;sup&gt;5&lt;/sup&gt;&lt;/a&gt;&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Microcontroller&lt;/th&gt;
      &lt;th&gt;Intel Curie&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;Operating Voltage&lt;/td&gt;
      &lt;td&gt;3.3V (5V tolerant I/O)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Input Voltage (recommended)&lt;/td&gt;
      &lt;td&gt;7-12V&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Input Voltage (limit)&lt;/td&gt;
      &lt;td&gt;7-17V&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Digital I/O Pins&lt;/td&gt;
      &lt;td&gt;14 (of which 4 provide PWM output)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;PWM Digital I/O Pins&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Analog Input Pins&lt;/td&gt;
      &lt;td&gt;6&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;DC Current per I/O Pin&lt;/td&gt;
      &lt;td&gt;20 mA&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Flash Memory&lt;/td&gt;
      &lt;td&gt;196 kB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;SRAM&lt;/td&gt;
      &lt;td&gt;24 kB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Clock Speed&lt;/td&gt;
      &lt;td&gt;32MHz&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;LED_BUILTIN&lt;/td&gt;
      &lt;td&gt;13&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Features&lt;/td&gt;
      &lt;td&gt;Bluetooth® Low Energy, 6-axis accelerometer/gyro&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Length&lt;/td&gt;
      &lt;td&gt;68.6 mm&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Width&lt;/td&gt;
      &lt;td&gt;53.4 mm&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Weight&lt;/td&gt;
      &lt;td&gt;34 gr.&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h1 id=&quot;arduino-代码实现&quot;&gt;Arduino 代码实现&lt;/h1&gt;

&lt;h2 id=&quot;blink&quot;&gt;Blink&lt;/h2&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;Arduino.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9600&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;delay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// wait for serial port to connect. Needed for native USB port only&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;pinMode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LED_BUILTIN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OUTPUT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;loop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;digitalWrite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LED_BUILTIN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HIGH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;LED ON!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;delay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;digitalWrite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LED_BUILTIN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LOW&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;LED OFF!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;delay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;读取板载-imu&quot;&gt;读取板载 IMU&lt;/h2&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;Arduino.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&quot;CurieIMU.h&quot;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9600&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;delay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Start the acceleromter&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;CurieIMU&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// Set the accelerometer range to 2G&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;CurieIMU&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setAccelerometerRange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;loop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// read accelerometer:&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CurieIMU&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;readAccelerometer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;X_AXIS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CurieIMU&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;readAccelerometer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Y_AXIS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;z&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CurieIMU&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;readAccelerometer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Z_AXIS&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;x: &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot; y: &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot; z: &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;读取板载-rtc&quot;&gt;读取板载 RTC&lt;/h1&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;Arduino.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;CurieTime.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9600&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;delay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;setTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;23&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2024&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;loop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//create a character array of 16 characters for the time&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;clockTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//use sprintf to create a time string of the hour, minte and seconds&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sprintf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clockTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;%2d:%2d:%2d&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hour&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;minute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;second&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;//create a character array of 15 characters for the date&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dateTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//use sprintf to create a date string from month, day and year&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sprintf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dateTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;%2d/%2d/%4d&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;month&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;day&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;//print the time and date to the serial monitor&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clockTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dateTime&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;delay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;使用板载-ble-控制-led&quot;&gt;使用板载 BLE 控制 LED&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;需要配合Nordic nRF Connect使用，可以在 Google Play Store 或 App Store 下载&lt;/em&gt;&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;Arduino.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;CurieBLE.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;
&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;BLEService&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ledService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;19B10000-E8F2-537E-4F6C-D104768A1214&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// BLE LED Service&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// BLE LED Switch Characteristic - custom 128-bit UUID, read and writable by central&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;BLEUnsignedCharCharacteristic&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;switchCharacteristic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;19B10001-E8F2-537E-4F6C-D104768A1214&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BLERead&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BLEWrite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ledPin&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// pin to use for the LED&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9600&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// set LED pin to output mode&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;pinMode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ledPin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OUTPUT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// begin initialization&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;BLE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// set advertised local name and service UUID:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;BLE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setLocalName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Arduino 101&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;BLE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setAdvertisedService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ledService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// add the characteristic to the service&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ledService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addCharacteristic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;switchCharacteristic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// add service&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;BLE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ledService&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// set the initial value for the characeristic:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;switchCharacteristic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// start advertising&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;BLE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;advertise&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;BLE LED Peripheral&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;loop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// listen for BLE peripherals to connect:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;BLEDevice&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;central&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BLE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;central&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// if a central is connected to peripheral:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;central&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Connected to central: &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// print the central&apos;s MAC address:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;central&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// while the central is still connected to peripheral:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;central&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;connected&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; 
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// if the remote device wrote to the characteristic,&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// use the value to control the LED:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;switchCharacteristic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;written&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; 
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;switchCharacteristic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt; 
                &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;// any value other than 0&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;LED on&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;digitalWrite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ledPin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HIGH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;         &lt;span class=&quot;c1&quot;&gt;// will turn the LED on&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; 
                &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; 
                &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;                              &lt;span class=&quot;c1&quot;&gt;// a 0 value&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;LED off&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;digitalWrite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ledPin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LOW&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;// will turn the LED off&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// when the central disconnects, print it out:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Disconnected from central: &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Serial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;central&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2024/01/20/3.gif&quot; width=&quot;50%&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;后记&quot;&gt;后记&lt;/h1&gt;

&lt;p&gt;Arduino 101 于 2016年 Q1 季度发布。仅仅过去一年有余，在英特尔宣布 Galileo，Edison 和 Joule 模块停产一个月后，也草草停产 Curie 模块（07/17/2017）&lt;a href=&quot;#jump6&quot;&gt;&lt;sup&gt;6&lt;/sup&gt;&lt;/a&gt;，只能说是非常可惜，英特尔宏图壮志准备在 IoT 领域大展拳脚，但是却因为种种原因，最终只能黯然收场。也导致诸多使用 Curie 模块的企业被迫更换产品线，比如&lt;a href=&quot;https://www.cnx-software.com/2017/03/29/100-xiaomi-90-minutes-ultra-smart-running-shoes-are-equipped-with-intel-curie-module/&quot;&gt;小米智能跑鞋&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2024/01/20/Intel-Curie-Arduino-101-Discontinued.webp&quot; /&gt;
&lt;em&gt;图片源自&lt;a href=&quot;https://www.cnx-software.com/2017/07/26/intel-curie-module-arduino-101-boards-are-being-discontinued-too/&quot;&gt;Intel Curie Module, Arduino 101 Board Are Being Discontinued (Too) - CNX Software&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;《Arduino程序设计基础》 的作者 陈吕洲 先生对 Arduino 101 抱有极高的评价：Genuino 101是一个极具特色的Arduino开发板，它基于Intel Curie模组，不仅有着和Arduino UNO一样特性和外设，还集成了低功耗蓝牙（BLE）和六轴姿态传感器（IMU）功能，借助intel Curie模组上模式匹配引擎，甚至可以进行机器学习操作。因此使用Genuino 101，可以完成一些传统单片机或者Arduino难以胜任的工作，制作更为惊艳的作品。为此他本人还专门为 Arduino 101 著书 —— 《Arduino 101 开发入门》&lt;a href=&quot;#jump7&quot;&gt;&lt;sup&gt;7&lt;/sup&gt;&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;不过 Arduino 101 也有三点比标准 Arduino Uno 差&lt;a href=&quot;#jump8&quot;&gt;&lt;sup&gt;8&lt;/sup&gt;&lt;/a&gt;：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;只有4组 PWM 脉宽调变输出，Uno 有6组；&lt;/li&gt;
  &lt;li&gt;没有任何的 EEPROM 存储，Uno 至少还有1KB可以使用；&lt;/li&gt;
  &lt;li&gt;单一 I/O 的电流驱动能力最高仅4mA，Uno 可到20mA。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;所以 Curie 只是引脚排列与 Arduino 相仿，不能完全保证原有设计电路或者 Arduino Shield可完全相容（兼容）沿用、续用。&lt;/p&gt;

&lt;p&gt;如果再与 MediaTek 的 LinkIt ONE 小比一下，LinkIt One也有效能更佳的处理器核心与更多容量的存储，且依然提供EEPROM 可用，但 PWM 方面则只有2组。当然，LinkIt ONE 强在无线通讯（日后会测评一下），如 GPRS、Wi-Fi、GPS等，Curie 略强在惯性感测。&lt;/p&gt;

&lt;p&gt;英特尔似乎在 IoT 领域并没有取得太大的成就，但是英特尔的 x86 芯片却是世界上最流行的 CPU 架构，这也是英特尔的核心竞争力，所以英特尔在 IoT 领域的失败并不会影响到英特尔的核心业务，但是英特尔的 IoT 产品却是非常有趣的，比如 Edison、Galileo、Curie、Arduino 101 等等，这些产品都是英特尔的 IoT 产品，但是英特尔并没有将这些产品做成一个系列，而是分散在各个不同的系列中，这也是英特尔在 IoT 领域失败的一个原因。&lt;/p&gt;

&lt;p&gt;笔者手上的 Genuino 101 是 2021年在 SeeedStudio 任职时，从 FAE 仓库里找到的，当时已经停产了，但是还是有一些库存，所以就拿了一块回来，但是一直没有时间去折腾，直到最近才拿出来玩一玩，但是发现 Arduino 101 的资料实在是太少了，所以就写了这篇文章，谨此纪念一家伟大的公司一个伟大的产品。&lt;/p&gt;

&lt;h1 id=&quot;引用&quot;&gt;引用&lt;/h1&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;span id=&quot;jump1&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_Arduino_boards_and_compatible_systems#cite_note-Arduino_101-6&quot;&gt;List of Arduino boards and compatible systems - Wikipedia&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
  &lt;li&gt;&lt;span id=&quot;jump2&quot;&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Programma_101&quot;&gt;Programma 101 - Wikipedia&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
  &lt;li&gt;&lt;span id=&quot;jump3&quot;&gt;&lt;a href=&quot;https://massimobanzi.com/about/&quot;&gt;Massimo Banzi - massimobanzi.com&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
  &lt;li&gt;&lt;span id=&quot;jump4&quot;&gt;&lt;a href=&quot;https://blog.arduino.cc/2016/04/21/intel-releases-the-arduino-101-firmware-source-code/&quot;&gt;Intel releases the Arduino 101 firmware source code - Arduino&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
  &lt;li&gt;&lt;span id=&quot;jump5&quot;&gt;&lt;a href=&quot;https://www.arduino.cc/en/Main/ArduinoBoard101&quot;&gt;Arduino 101 - Arduino&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
  &lt;li&gt;&lt;span id=&quot;jump6&quot;&gt;&lt;a href=&quot;https://ark.intel.com/content/www/cn/zh/ark/products/92347/arduino-101.html&quot;&gt;Arduino 101 - Intel&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
  &lt;li&gt;&lt;span id=&quot;jump7&quot;&gt;&lt;a href=&quot;https://clz.me/101-book/&quot;&gt;《Arduino 101 开发入门》 - XX到此一游&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
  &lt;li&gt;&lt;span id=&quot;jump8&quot;&gt;&lt;a href=&quot;https://makerpro.cc/2015/10/arduino-101-review/&quot;&gt;Arduino 101擁抱Intel Curie核心 優缺點比一比 - 陸向陽 MakerPro&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
</content>
 </entry>
 
 <entry>
   <title>【安卓搞机记】通过 adb 侧载低版本 SDK 的安卓应用</title>
   <link href="https://icing.fun/posts/adb_install_bypass.html"/>
   <updated>2024-01-16T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/adb_install_bypass</id>
   <content type="html">&lt;p&gt;前些日子翻出来自己高中写的安卓应用，安装上去看看，但是发现小米的 HyperOS 装不上去，一直报错：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;安装失败 (-29) 
失败原因
安装包与系统不兼容&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;我第一反应应该是因为应用的目标 SDK 版本（19）太低了，先用 &lt;a href=&quot;https://appcloner.app/&quot;&gt;App Cloner&lt;/a&gt; 改改参数，改到 SDK26 看看。&lt;/p&gt;

&lt;p&gt;还是不行，打开是能打开但是白屏。&lt;/p&gt;

&lt;p&gt;最后看看用 adb 侧载算了：&lt;/p&gt;

&lt;h2 id=&quot;安全性&quot;&gt;&lt;a href=&quot;https://developer.android.google.cn/about/versions/14/behavior-changes-all?hl=zh-cn#security&quot;&gt;安全性&lt;/a&gt;&lt;/h2&gt;

&lt;h3 id=&quot;最低可安装的目标-api-级别&quot;&gt;最低可安装的目标 API 级别&lt;/h3&gt;

&lt;p&gt;从 Android 14 开始，targetSdkVersion 低于 23 的应用无法安装。要求应用满足这些最低目标 API 级别要求有助于提高用户的安全性和隐私性。&lt;/p&gt;

&lt;p&gt;恶意软件通常会以较旧的 API 级别为目标平台，以绕过在较新版本 Android 中引入的安全和隐私保护机制。例如，有些恶意软件应用使用 targetSdkVersion 22，以避免受到 Android 6.0 Marshmallow（API 级别 23）在 2015 年引入的运行时权限模型的约束。这项 Android 14 变更使恶意软件更难以规避安全和隐私权方面的改进限制。尝试安装以较低 API 级别为目标平台的应用将导致安装失败，并且 Logcat 中会显示以下消息：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;INSTALL_FAILED_DEPRECATED_SDK_VERSION: App package must target at least SDK version 23, but found 7
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;在升级到 Android 14 的设备上，targetSdkVersion 低于 23 的所有应用都将继续保持安装状态。&lt;/p&gt;

&lt;p&gt;如果您需要测试以旧版 API 级别为目标平台的应用，请使用以下 ADB 命令：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;adb &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--bypass-low-target-sdk-block&lt;/span&gt; FILENAME.apk
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>【Git】Git 推送的配置</title>
   <link href="https://icing.fun/posts/git_push_setup.html"/>
   <updated>2023-12-22T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/git_push_setup</id>
   <content type="html">&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#title1&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Git&lt;/code&gt; 初次设定&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#title2&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Git&lt;/code&gt; 代理设置&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#title3&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Git&lt;/code&gt; 回滚操作&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#title4&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git push&lt;/code&gt; 到两个地址的仓库&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#title5&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Git&lt;/code&gt; 不公开邮箱账户&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#title6&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Git&lt;/code&gt; 取消文件跟踪&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#title7&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Git&lt;/code&gt; 记住密码&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;git-初次设定&quot;&gt;&lt;span id=&quot;title1&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Git&lt;/code&gt; 初次设定&lt;/span&gt;&lt;/h2&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config &lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt; user.name &lt;span class=&quot;s2&quot;&gt;&quot;IcingTomato&quot;&lt;/span&gt;
git config &lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt; user.email &lt;span class=&quot;s2&quot;&gt;&quot;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;参阅&lt;a href=&quot;https://git-scm.com/book/zh-tw/v2/%E9%96%8B%E5%A7%8B-%E5%88%9D%E6%AC%A1%E8%A8%AD%E5%AE%9A-Git&quot;&gt;1.6 開始 - 初次設定 Git&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;git-代理设置&quot;&gt;&lt;span id=&quot;title2&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Git&lt;/code&gt; 代理设置&lt;/span&gt;&lt;/h2&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config &lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt; http.proxy http://proxyUsername:proxyPassword@proxy.server.com:port
git config &lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt; https.proxy http://proxyUsername:proxyPassword@proxy.server.com:port
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;git-回滚操作&quot;&gt;&lt;span id=&quot;title3&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Git&lt;/code&gt; 回滚操作&lt;/span&gt;&lt;/h2&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git reset &lt;span class=&quot;nt&quot;&gt;--hard&lt;/span&gt; HEAD^ &lt;span class=&quot;c&quot;&gt;# 回退到上个版本。&lt;/span&gt;
git reset &lt;span class=&quot;nt&quot;&gt;--hard&lt;/span&gt; HEAD^ &amp;lt;filename&amp;gt; &lt;span class=&quot;c&quot;&gt;# 回退指定文件到上个版本。&lt;/span&gt;
git reset &lt;span class=&quot;nt&quot;&gt;--hard&lt;/span&gt; HEAD^^ &lt;span class=&quot;c&quot;&gt;# 回退到上上个版本。&lt;/span&gt;
git reset &lt;span class=&quot;nt&quot;&gt;--hard&lt;/span&gt; HEAD~n &lt;span class=&quot;c&quot;&gt;# 回退到前n次提交之前，若n=3，则可以回退到3次提交之前。&lt;/span&gt;
git reset &lt;span class=&quot;nt&quot;&gt;--hard&lt;/span&gt; &amp;lt;commit_sha&amp;gt; &lt;span class=&quot;c&quot;&gt;# 回滚到指定commit的SHA码，一般使用这种方式。&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--hard&lt;/code&gt; 参数撤销工作区中所有未提交的修改内容，将暂存区与工作区都回到上一次版本，并删除之前的所有信息提交。
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--soft&lt;/code&gt; 参数撤销工作区中所有未提交的修改内容，将暂存区与工作区都回到上一次版本，但保留之前的所有信息提交。&lt;/p&gt;

&lt;p&gt;回滚完之后就可以&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git push &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; origin &amp;lt;branch_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;git-push-到两个地址的仓库&quot;&gt;&lt;span id=&quot;title4&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git push&lt;/code&gt; 到两个地址的仓库&lt;/span&gt;&lt;/h2&gt;

&lt;p&gt;好比我这个博客仓库，在国内因为某些不可抗力，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;github&lt;/code&gt; 无法访问，所以我在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gitee&lt;/code&gt; 上也有一个仓库，这样就可以在国内访问了。但是我每次都要推送两次，很麻烦。或者要登陆 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gitee&lt;/code&gt; 的仓库，然后按一下同步按钮，也很麻烦。&lt;/p&gt;

&lt;p&gt;所以我就想，能不能只推送一次，然后两个仓库都更新呢？&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 原始推送地址 https://github.com/IcingTomato/icing.fun.git&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# 添加第二个推送地址&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;git&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;remote&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;set-url&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--add&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;origin&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;https://gitee.com/IcingTomato/icing.fun.git&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# 查看推送/拉取地址&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;git&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;remote&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# origin  https://github.com/IcingTomato/icing.fun.git (fetch)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# origin  https://github.com/IcingTomato/icing.fun.git (push)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# origin  https://gitee.com/IcingTomato/icing.fun.git (push)&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# 推送&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;git&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;git-不公开邮箱账户&quot;&gt;&lt;span id=&quot;title5&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Git&lt;/code&gt; 不公开邮箱账户&lt;/span&gt;&lt;/h2&gt;

&lt;p&gt;之前貌似更新了什么，好像是将保密你的邮箱地址，并在执行基于 Web WebIDE 的 Git 操作中，使用 xxxx@user.noreply.xxx.com 作为你的邮箱地址。如果你希望命令行 Git 操作使用你的私人邮箱地址，你必须在 Git 中设置你的邮箱地址。&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 我经常用 GitHub 的邮箱，全局就设置成这个了&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;git&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;user.email&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;xxxx@users.noreply.github.com&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# cd 到 icing.fun 仓库目录下&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;git&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;user.email&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;xxxx@users.noreply.github.com&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;git&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;user.email&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;xxxx@users.noreply.gitee.com&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;git-取消文件跟踪&quot;&gt;&lt;span id=&quot;title6&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Git&lt;/code&gt; 取消文件跟踪&lt;/span&gt;&lt;/h2&gt;

&lt;p&gt;参见&lt;a href=&quot;http://icing.fun/2025/05/02/git_rm/&quot;&gt;【Git】Git 取消文件跟踪&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;git-记住密码&quot;&gt;&lt;span id=&quot;title7&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Git&lt;/code&gt; 记住密码&lt;/span&gt;&lt;/h2&gt;

&lt;p&gt;在使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git push&lt;/code&gt; 时，可能会遇到需要输入用户名和密码的情况。为了避免每次都输入，可以使用以下命令来记住密码：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config &lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt; credential.helper store
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这将会在本地存储你的 Git 凭据，之后在推送时就不需要再次输入用户名和密码了。
如果你希望在每次推送时都输入密码，可以使用以下命令：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config &lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt; credential.helper cache
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这将会在内存中缓存你的凭据，默认缓存时间为 15 分钟。
如果你希望更改缓存时间，可以使用以下命令：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git config &lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt; credential.helper &lt;span class=&quot;s1&quot;&gt;&apos;cache --timeout=3600&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这将会将缓存时间设置为 1 小时（3600 秒）。&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>【Git】GitHub 的三种 Pull Request</title>
   <link href="https://icing.fun/posts/github_pull_request.html"/>
   <updated>2023-12-13T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/github_pull_request</id>
   <content type="html">&lt;p&gt;在 GitHub 上处理 Pull Requests（PRs）时，有三种主要的合并策略：创建合并提交（Merge Commit）、挤压合并（Squash and Merge）、变基合并（Rebase and Merge）。下面简要解释每种策略的特点及其区别：&lt;/p&gt;

&lt;h3 id=&quot;1-创建合并提交merge-commit&quot;&gt;1. 创建合并提交（Merge Commit）&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;操作&lt;/strong&gt;：当你选择创建合并提交时，GitHub 会创建一个新的合并提交来将 PR 的更改合并到基分支（如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;main&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;master&lt;/code&gt;）。这个合并提交会包含一个特殊的提交信息，通常包括一个指向 PR 的引用。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;结果&lt;/strong&gt;：在基分支的提交历史中，PR 的所有提交都将被保留，并附加一个额外的合并提交。这保持了完整的历史记录和PR的独立性。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;适用场景&lt;/strong&gt;：当你想保留对 PR 的每一次单独提交的完整历史时。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;2-挤压合并squash-and-merge&quot;&gt;2. 挤压合并（Squash and Merge）&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;操作&lt;/strong&gt;：挤压合并会将 PR 中的所有提交合并成一个单独的提交，然后将这个提交合并到基分支。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;结果&lt;/strong&gt;：基分支的提交历史更简洁，因为它只包含一个代表整个 PR 的提交。但这意味着PR中原始提交的细节被压缩。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;适用场景&lt;/strong&gt;：适用于PR包含许多小的、渐进的更改，但你想在基分支上保持一份干净、未混杂的历史记录。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;3-变基合并rebase-and-merge&quot;&gt;3. 变基合并（Rebase and Merge）&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;操作&lt;/strong&gt;：变基合并首先会将 PR 的提交历史变基到目标分支的最新提交上，然后将这些提交直接加入到基分支，而不创建额外的合并提交。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;结果&lt;/strong&gt;：这在基分支上产生一条线性的提交历史，但不会保留 PR 作为独立实体的信息。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;适用场景&lt;/strong&gt;：当你希望保持线性历史且避免合并提交时。这通常适用于较小的、清晰的更改。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;总结&quot;&gt;总结&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;创建合并提交&lt;/strong&gt;保留了所有的提交历史和PR的独立性，增加了一个额外的合并提交。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;挤压合并&lt;/strong&gt;将PR的所有提交压缩成一个单独的提交，使历史更干净。&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;变基合并&lt;/strong&gt;保持了线性的提交历史，但不会创建合并提交。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;选择哪种策略取决于你的项目团队如何希望管理其版本控制历史的清晰度和连贯性。&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>【阅板无数】RaspberryPi 启动流程探究</title>
   <link href="https://icing.fun/posts/raspberrypi_boot.html"/>
   <updated>2023-12-09T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/raspberrypi_boot</id>
   <content type="html">&lt;p&gt;树莓派学习第一步，探究树莓派的启动流程。&lt;/p&gt;

&lt;h1 id=&quot;树莓派的启动流程&quot;&gt;树莓派的启动流程&lt;/h1&gt;

&lt;p&gt;相较于一般/通常的 ARM SoC 来说，树莓派1/2/3/Zero的启动流程有些不同，这里简单的记录一下。&lt;/p&gt;

&lt;h2 id=&quot;树莓派123zero的启动流程&quot;&gt;树莓派1/2/3/Zero的启动流程&lt;/h2&gt;

&lt;p&gt;在开机时，CPU是离线的，由GPU上的一个小型RISC核心负责启动SoC，因此大部分启动组件实际上是在GPU代码上运行，而不是CPU上。&lt;/p&gt;

&lt;p&gt;启动顺序如下：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;第一阶段引导程序：用于挂载SD卡上的FAT32启动分区，以便可以访问第二阶段引导程序。它在制造树莓派时已经烧录到SoC本身，并且用户无法重新编程。&lt;/li&gt;
  &lt;li&gt;第二阶段引导程序（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bootcode.bin&lt;/code&gt;）：用于从SD卡检索GPU固件，加载固件，然后启动GPU。&lt;/li&gt;
  &lt;li&gt;GPU固件（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;start.elf&lt;/code&gt;）：一经加载，允许GPU启动CPU。另一个文件&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fixup.dat&lt;/code&gt;用于配置GPU和CPU之间的SDRAM分区。此时，CPU从&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;复位&lt;/code&gt;模式释放并转移到CPU上执行。&lt;/li&gt;
  &lt;li&gt;用户代码（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;User Code&lt;/code&gt;）：这可以是任何数量的二进制文件之一。默认情况下，它是Linux内核（通常命名为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;kernel.img&lt;/code&gt;），但它也可以是另一个引导程序（例如&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;U-Boot&lt;/code&gt;）或一个简单的应用程序。
&lt;em&gt;在2012年10月19日之前，曾经还有第三阶段引导程序（loader.bin），现已废除。&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;下面是原文&lt;a href=&quot;https://elinux.org/RPi_Software&quot;&gt;elinux.org/RPi_Software&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;At power-up, the CPU is offline, and a small RISC core on the GPU is responsible for booting the SoC, therefore most of the boot components are actually run on the GPU code, not the CPU.&lt;/p&gt;

  &lt;p&gt;The boot order and components are as follows:&lt;/p&gt;

  &lt;ul&gt;
    &lt;li&gt;First stage bootloader - This is used to mount the FAT32 boot partition on the SD card so that the second stage bootloader can be accessed. It is programmed into the SoC itself during manufacture of the RPi and cannot be reprogrammed by a user.&lt;/li&gt;
    &lt;li&gt;Second stage bootloader (bootcode.bin) - This is used to retrieve the GPU firmware from the SD card, program the firmware, then start the GPU.&lt;/li&gt;
    &lt;li&gt;GPU firmware (start.elf) - Once loaded, this allows the GPU to start up the CPU. An additional file, fixup.dat, is used to configure the SDRAM partition between the GPU and the CPU. At this point, the CPU is release from reset and execution is transferred over.&lt;/li&gt;
    &lt;li&gt;User code - This can be one of any number of binaries. By default, it is the Linux kernel (usually named kernel.img), but it can also be another bootloader (e.g. U-Boot), or a bare-bones application.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;p&gt;&lt;em&gt;Prior to 19th October 2012, there was previously also a third stage bootloader (loader.bin) but this is no longer required.&lt;a href=&quot;https://github.com/raspberrypi/firmware/commit/c57ea9dd367f12bf4fb41b7b86806a2dc6281176&quot;&gt;[1]&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;树莓派4bbcm2711的启动流程&quot;&gt;树莓派4B（BCM2711）的启动流程&lt;/h2&gt;

&lt;p&gt;树莓派4B（BCM2711）因为某些硬件升级导致启动流程复杂了不是一丁半点&lt;a href=&quot;https://hackaday.io/page/6372-raspberry-pi-4-boot-sequence&quot;&gt;[2]&lt;/a&gt;。&lt;/p&gt;

&lt;p&gt;当树莓派4开机时，引导过程涉及BCM2711 VideoCore VI 处理器单元（VPU）的操作。以下是引导过程的步骤概述：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;VPU核心0的初始化：&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;开机时，BCM2711芯片的VPU核心0开始运行。&lt;/li&gt;
      &lt;li&gt;程序计数器设置为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x60000000&lt;/code&gt;，映射到片上启动ROM。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;VPU频率和启动ROM：&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;最初，VPU的频率设置为振荡器频率，树莓派4上为54.0 MHz。&lt;/li&gt;
      &lt;li&gt;这个低频率足以完成初始引导任务。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;读取OTP寄存器：&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;启动ROM读取某些一次性可编程（OTP）寄存器（17/18, 66, 和 67）。&lt;/li&gt;
      &lt;li&gt;这些寄存器与树莓派3相比有不同的含义。更多信息可以在&lt;a href=&quot;https://github.com/raspberrypi/firmware/issues/1169&quot;&gt;这个GitHub问题&lt;/a&gt;中找到。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;引导指示引脚：&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;如果配置了“引导指示引脚”，则它会被激活几毫秒。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;USB设备模式恢复：&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;如果配置了USB设备模式强制引导引脚且激活，某些步骤会被跳过。&lt;/li&gt;
      &lt;li&gt;这是一种从USB启动恢复的机制。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;SD卡引导：&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;如果SD卡引导引脚处于激活状态或未配置，启动ROM尝试从SD卡的第一个FAT分区加载&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;recovery.bin&lt;/code&gt;。&lt;/li&gt;
      &lt;li&gt;这种机制有助于在EEPROM损坏时恢复板子。更多细节可以在&lt;a href=&quot;https://www.raspberrypi.org/documentation/hardware/raspberrypi/booteeprom.md&quot;&gt;树莓派硬件文档&lt;/a&gt;中找到。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;从EEPROM加载固件：&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;BootROM尝试从EEPROM芯片加载固件，通常是通过SPI0在GPIO 40–43接口的Winbond W25X40芯片。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;USB设备模式：&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;如果前面的步骤失败，芯片进入通过Type-C连接器的USB设备模式。&lt;/li&gt;
      &lt;li&gt;它等待从USB主机获取恢复映像，需要在主机上更新usbboot。更多信息可以在&lt;a href=&quot;https://github.com/raspberrypi/firmware/pull/1169&quot;&gt;这个拉取请求&lt;/a&gt;中找到。&lt;/li&gt;
      &lt;li&gt;在这种模式下，VPU的频率提升到100 MHz。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;固件映像签名：&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;需要在固件映像中附加一个20字节的签名，这是使用存储在OTP中的通用密钥的映像的HMAC-SHA1散列。&lt;/li&gt;
      &lt;li&gt;这个密钥无法通过树莓派提供的固件的API访问。&lt;/li&gt;
      &lt;li&gt;这种机制最初在树莓派3上是可选的，现在则是强制性的，尽管它并不提供安全保护，因为存在一个通用的recovery.bin映像。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;这个引导过程突出显示了确保树莓派4能够成功引导并从潜在的固件问题中恢复的各种机制。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;When the Raspberry Pi 4 is powered on, the BCM2711 VPU core 0 gets started. The program counter is set to 0x60000000. This address maps to the on-chip boot ROM. Note that the VPU frequency is set to the oscillator (54.0 MHz on RPi4), so it’s not very fast, but it does not do a lot of things either:&lt;/p&gt;

  &lt;p&gt;Read boot-related OTP registers (17/18, 66 and 67). Note that these registers have a different meaning than on Raspberry Pi 3. More information can be found &lt;a href=&quot;https://github.com/raspberrypi/firmware/issues/1169&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

  &lt;p&gt;If a “boot indication pin” is configured, it is activated for some milliseconds.&lt;/p&gt;

  &lt;p&gt;If USB device-mode recovery force boot pin is configured and active, steps 4 and 5 are skipped.&lt;/p&gt;

  &lt;p&gt;If SD card boot pin is either active or not configured, the boot ROM tries to load recovery.bin from the first FAT partition. This provides a mechanism to unbrick your board if the EEPROM gets corrupted. More details can be found &lt;a href=&quot;https://www.raspberrypi.org/documentation/hardware/raspberrypi/booteeprom.md&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

  &lt;p&gt;Next, the boot ROM tries to load firmware from the EEPROM chip. This is a standard Winbond W25X40 chip, access through SPI0 on GPIO 40–43.&lt;/p&gt;

  &lt;p&gt;If everything else fails, the chip enters USB device mode (on the Type-C connector) and waits to get the recovery image from the USB host. You need an updated usbboot on the host to use this method. See also this pull request.&lt;/p&gt;

  &lt;p&gt;The VPU frequency is increased to 100 MHz for the USB device mode.&lt;/p&gt;

  &lt;p&gt;Note that a 20-byte signature must be appended to the firmware image. It is an HMAC-SHA1 hash of the image using a universal key that is also stored in the OTP, but not accessible using the Foundation firmware APIs. A similar mechanism was available as an optional feature on Raspberry Pi3. I originally assumed that the key is unique for each Raspberry Pi, but since there is one universal recovery.bin image that works for all, there must be only one key. Given that it provides no security, I’m not sure why this hash is now mandatory.&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>【博客搭建】Jekyll Learning</title>
   <link href="https://icing.fun/posts/jekyll_learning.html"/>
   <updated>2023-12-06T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/jekyll_learning</id>
   <content type="html">&lt;p&gt;Jekyll/Liquid 博客学习记录（连载）&lt;/p&gt;

&lt;h1 id=&quot;jekyll博客配置教程&quot;&gt;Jekyll博客配置教程&lt;/h1&gt;

&lt;p&gt;我是LNMP派，因为我不会用Apache配置。&lt;/p&gt;

&lt;p&gt;然而静态博客没必要MySQL, MariaDB, PHP。所以我们只安装Jekyll所有必需的依赖项。&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;ruby-full build-essential zlib1g-dev nginx
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;gcc g++ make
curl &lt;span class=&quot;nt&quot;&gt;-sL&lt;/span&gt; https://dl.yarnpkg.com/debian/pubkey.gpg | &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-key add -
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;deb https://dl.yarnpkg.com/debian/ stable main&quot;&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;sudo tee&lt;/span&gt; /etc/apt/sources.list.d/yarn.list
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get update &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;yarn
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然而Ubuntu 16.04太老了，ruby的版本不支持Jekyll 4。所以我们要手动安装Ruby 3.0.0。&lt;/p&gt;

&lt;p&gt;第一步是为Ruby安装一些依赖项。一步一步运行。&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;curl
curl &lt;span class=&quot;nt&quot;&gt;-sL&lt;/span&gt; https://deb.nodesource.com/setup_12.x | &lt;span class=&quot;nb&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-E&lt;/span&gt; bash -
curl &lt;span class=&quot;nt&quot;&gt;-sS&lt;/span&gt; https://dl.yarnpkg.com/debian/pubkey.gpg | &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-key add -
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;deb https://dl.yarnpkg.com/debian/ stable main&quot;&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;sudo tee&lt;/span&gt; /etc/apt/sources.list.d/yarn.list
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get update
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;git-core zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev software-properties-common libffi-dev nodejs yarn
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;接下来，我们将使用以下三种方法之一安装Ruby。每个都有自己的好处，如今大多数人都喜欢使用rbenv，但是如果您熟悉rvm，也可以按照这些步骤进行操作。我也提供了从源代码安装的说明，但是一般而言，您需要选择rbenv或rvm。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;方法一：使用rbenv安装。首先安装rbenv，然后安装ruby-build：&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd
&lt;/span&gt;git clone https://github.com/rbenv/rbenv.git ~/.rbenv
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;export PATH=&quot;$HOME/.rbenv/bin:$PATH&quot;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;eval &quot;$(rbenv init -)&quot;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
&lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$SHELL&lt;/span&gt;

git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;export PATH=&quot;$HOME/.rbenv/plugins/ruby-build/bin:$PATH&quot;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
&lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$SHELL&lt;/span&gt;

rbenv &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;3.0.0
rbenv global 3.0.0
ruby &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;方法二：RVM安装&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;libgdbm-dev libncurses5-dev automake libtool bison libffi-dev
gpg &lt;span class=&quot;nt&quot;&gt;--keyserver&lt;/span&gt; hkp://keys.gnupg.net &lt;span class=&quot;nt&quot;&gt;--recv-keys&lt;/span&gt; 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
curl &lt;span class=&quot;nt&quot;&gt;-sSL&lt;/span&gt; https://get.rvm.io | bash &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; stable
&lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; ~/.rvm/scripts/rvm
rvm &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;3.0.0
rvm use 3.0.0 &lt;span class=&quot;nt&quot;&gt;--default&lt;/span&gt;
ruby &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;方法三：Ruby源码安装&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd
&lt;/span&gt;wget http://ftp.ruby-lang.org/pub/ruby/3.0/ruby-3.0.0.tar.gz
&lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-xzvf&lt;/span&gt; ruby-3.0.0.tar.gz
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;ruby-3.0.0/
./configure
make
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;make &lt;span class=&quot;nb&quot;&gt;install
&lt;/span&gt;ruby &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Ruby服务器在国外，我的博客服务器在国内，所以换个Ruby源&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gem &lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; https://rubygems.org/
gem &lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--add&lt;/span&gt; https://gems.ruby-china.com/
gem &lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;最后一步是安装Bundler&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gem &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;bundler jekyll github-pages jekyll-paginate webrick
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;安装完之后就可以将博客从&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GitHub&lt;/code&gt;或&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Gitee&lt;/code&gt;上&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git clone&lt;/code&gt;下来了。&lt;/p&gt;

&lt;p&gt;接着完成对&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx&lt;/code&gt;的配置&lt;/p&gt;

&lt;p&gt;安装&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;nginx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后定位到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx&lt;/code&gt;的配置文件：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;vim /etc/nginx/sites-enabled/default
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;配置文件在下面：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pi@ubuntu:~cat /etc/nginx/sites-enabled/default 
server &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;c&quot;&gt;# 监听80端口，我嫌麻烦就懒得加SSL了&lt;/span&gt;
	listen 80 default_server&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	listen &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;::]:80 default_server&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;# 网页在本地的根目录&lt;/span&gt;
	root /var/www/html&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;# 显示的主页&lt;/span&gt;
	index index.html&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;# 你的域名&lt;/span&gt;
	server_name domain.yours&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;# 404，403配置文件&lt;/span&gt;
  &lt;span class=&quot;c&quot;&gt;# 主要目的是当出现404或403时直接回显200&lt;/span&gt;
	error_page 404 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;200 /404.html&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# 404&lt;/span&gt;
        location /404.html &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
                root /var/www/html/&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                internal&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;        
        &lt;span class=&quot;c&quot;&gt;# 403&lt;/span&gt;
        error_page 403 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;200 /offline.html&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;# 404&lt;/span&gt;
        location /offline.html &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
                root /var/www/html/&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                internal&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;        
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;保存好之后重启&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl restart nginx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;jekyll博客维护教程&quot;&gt;Jekyll博客维护教程&lt;/h1&gt;

&lt;p&gt;博客的维护教程修改自 &lt;a href=&quot;https://github.com/Huxpro/huxpro.github.io&quot;&gt;Hux&lt;/a&gt; 和 &lt;a href=&quot;https://github.com/qiubaiying/qiubaiying.github.io&quot;&gt;BY_Blog&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;环境&quot;&gt;环境&lt;/h2&gt;

&lt;p&gt;如果你安装了 &lt;a href=&quot;http://jekyllcn.com/&quot;&gt;Jekyll&lt;/a&gt;，那你只需要在命令行输入&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jekyll serve&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jekyll s&lt;/code&gt;就能在本地浏览器中输入&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http://127.0.0.1:4000/&lt;/code&gt;预览主题，对主题的修改也能实时展示（需要强刷浏览器，Ctrl+F5）。&lt;/p&gt;

&lt;h2 id=&quot;开始&quot;&gt;开始&lt;/h2&gt;

&lt;p&gt;你可以通用修改 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_config.yml&lt;/code&gt;文件来轻松的开始搭建自己的博客:&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Site settings&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;啥玩意儿啊这&lt;/span&gt;                 &lt;span class=&quot;c1&quot;&gt;# 你的博客网站标题&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;SEOTitle&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;啥玩意儿 | What&apos;s this&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# SEO 标题&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Hey&quot;&lt;/span&gt;                 &lt;span class=&quot;c1&quot;&gt;# 随便说点，描述一下&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# SNS settings      &lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;github_username&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;# 你的github账号&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Build settings&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# paginate: 100              # 一页你准备放几篇文章&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Jekyll官方网站还有很多的参数可以调，比如设置文章的链接形式…网址在这里：&lt;a href=&quot;http://jekyllrb.com/&quot;&gt;Jekyll - Official Site&lt;/a&gt; 中文版的在这里：&lt;a href=&quot;http://jekyllcn.com/&quot;&gt;Jekyll中文&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;撰写博文&quot;&gt;撰写博文&lt;/h2&gt;

&lt;p&gt;要发表的文章一般以 &lt;strong&gt;Markdown&lt;/strong&gt; 的格式放在这里&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_posts/&lt;/code&gt;，你只要看看这篇模板里的文章你就立刻明白该如何设置。&lt;/p&gt;

&lt;p&gt;yaml 头文件长这样:&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;     &lt;span class=&quot;s&quot;&gt;post&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;      &lt;span class=&quot;s&quot;&gt;硕人其颀 衣锦褧衣&lt;/span&gt; 
&lt;span class=&quot;na&quot;&gt;subtitle&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;   &lt;span class=&quot;s&quot;&gt;Quark核心板的GPIO推算过程&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;       &lt;span class=&quot;s&quot;&gt;2021-02-01&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;     &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;header-img&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;img/2021/02/01/01/title.jpg&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;catalog&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;tags&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Quark&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;GPIO&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Linux&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Project-Quantum&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Nano Pi&lt;/span&gt;
&lt;span class=&quot;nn&quot;&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;侧边栏&quot;&gt;侧边栏&lt;/h2&gt;

&lt;p&gt;看右边&lt;/p&gt;

&lt;p&gt;设置是在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_config.yml&lt;/code&gt;文件里面的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Sidebar settings&lt;/code&gt;那块。&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Sidebar settings&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;sidebar&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;#添加侧边栏&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;sidebar-about-description&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;简单的描述一下你自己&quot;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;sidebar-avatar&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/img/avatar-by.jpg&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;#你的大头贴，请使用绝对地址.注意：名字区分大小写！后缀名也是&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;侧边栏是响应式布局的，当屏幕尺寸小于992px的时候，侧边栏就会移动到底部。具体请见&lt;a href=&quot;http://v3.bootcss.com/css/&quot;&gt;bootstrap栅格系统&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;mini-about-me&quot;&gt;Mini About Me&lt;/h2&gt;

&lt;p&gt;Mini-About-Me 这个模块将在你的头像下面，展示你所有的社交账号。这个也是响应式布局，当屏幕变小时候，会将其移动到页面底部，只不过会稍微有点小变化，具体请看代码。&lt;/p&gt;

&lt;h2 id=&quot;featured-tags&quot;&gt;Featured Tags&lt;/h2&gt;

&lt;p&gt;看到这个网站 &lt;a href=&quot;http://medium.com&quot;&gt;Medium&lt;/a&gt; 的推荐标签非常的炫酷，所以我将他加了进来。
这个模块现在是独立的，可以呈现在所有页面，包括主页和发表的每一篇文章标题的头上。&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Featured Tags&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;featured-tags&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;  
&lt;span class=&quot;na&quot;&gt;featured-condition-size&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;     &lt;span class=&quot;c1&quot;&gt;# A tag will be featured if the size of it is more than this condition value&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;唯一需要注意的是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;featured-condition-size&lt;/code&gt;: 如果一个标签的 SIZE，也就是使用该标签的文章数大于上面设定的条件值，这个标签就会在首页上被推荐。&lt;/p&gt;

&lt;p&gt;内部有一个条件模板 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;｛% if tag[1].size &amp;gt; ｛｛ site.featured-condition-size｝｝ %｝&lt;/code&gt; 是用来做筛选过滤的.&lt;/p&gt;

&lt;h2 id=&quot;social-media-account&quot;&gt;Social-media Account&lt;/h2&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# SNS settings&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;RSS&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;bilibili_username&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;s&quot;&gt;bilibili_uid&lt;/span&gt; 
&lt;span class=&quot;na&quot;&gt;zhihu_username&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;     &lt;span class=&quot;s&quot;&gt;username&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;facebook_username&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;  &lt;span class=&quot;s&quot;&gt;username&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;github_username&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;    &lt;span class=&quot;s&quot;&gt;username&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;weibo_username&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;     &lt;span class=&quot;s&quot;&gt;username&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;friends&quot;&gt;Friends&lt;/h2&gt;

&lt;p&gt;友链部分。这会在全部页面显示。&lt;/p&gt;

&lt;p&gt;设置是在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_config.yml&lt;/code&gt;文件里面的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Friends&lt;/code&gt;那块，自己加吧。&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Friends&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;friends&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;huohuo&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;http://null.fun/&quot;&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;},&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Apple&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;https://apple.com/&quot;&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;keynote-layout&quot;&gt;Keynote Layout&lt;/h2&gt;

&lt;p&gt;HTML5幻灯片的排版：&lt;/p&gt;

&lt;p&gt;这部分是用于占用html格式的幻灯片的，一般用到的是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Reveal.js&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Impress.js&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Slides&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Prezi&lt;/code&gt; 等等.我认为一个现代化的博客怎么能少了放html幻灯的功能呢~&lt;/p&gt;

&lt;p&gt;其主要原理是添加一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iframe&lt;/code&gt;，在里面加入外部链接。你可以直接写到头文件里面去，详情请见下面的yaml头文件的写法。&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;     &lt;span class=&quot;s&quot;&gt;keynote&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;iframe&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;     &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;http://huangxuan.me/js-module-7day/&quot;&lt;/span&gt;
&lt;span class=&quot;nn&quot;&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;iframe在不同的设备中，将会自动的调整大小。保留内边距是为了让手机用户可以向下滑动，以及添加更多的内容。&lt;/p&gt;

&lt;h2 id=&quot;comment&quot;&gt;Comment&lt;/h2&gt;

&lt;p&gt;博客不仅支持 &lt;a href=&quot;http://disqus.com&quot;&gt;Disqus&lt;/a&gt; 评论系统,还加入了 &lt;a href=&quot;https://gitalk.github.io/&quot;&gt;Gitalk&lt;/a&gt; 评论系统，&lt;a href=&quot;https://guides.github.com/features/mastering-markdown/&quot;&gt;支持 Markdwon 语法&lt;/a&gt;，cool~&lt;/p&gt;

&lt;h3 id=&quot;disqus&quot;&gt;Disqus&lt;/h3&gt;

&lt;p&gt;优点：国际比较流行，界面也很大气、简洁，如果有人评论，还能实时通知，直接回复通知的邮件就行了；&lt;/p&gt;

&lt;p&gt;缺点：评论必须要去注册一个disqus账号，分享一般只有Facebook和Twitter，另外在墙内加载速度略慢了一点。想要知道长啥样，可以看以前的版本点&lt;a href=&quot;http://brucezhaor.github.io/about.html&quot;&gt;这里&lt;/a&gt; 最下面就可以看到。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Note：有很多人反映 Disqus 插件加载不出来，可能墙又架高了，有条件的话翻个墙就好了~&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;使用：&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;首先&lt;/strong&gt;，你需要去注册一个Disqus帐号。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;其次&lt;/strong&gt;，你只需要在下面的 yaml 头文件中设置一下就可以了。&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# 评论系统&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Disqus（https://disqus.com/）&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;disqus_username&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;gitalk&quot;&gt;Gitalk&lt;/h3&gt;

&lt;p&gt;优点：界面干净简洁，利用 Github issue API 做的评论插件，使用 Github 帐号进行登录和评论，最喜欢的支持 Markdown 语法，对于程序员来说真是太 cool 了。&lt;/p&gt;

&lt;p&gt;缺点：配置比较繁琐，每篇文章的评论都需要初始化。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;使用：&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;参考我的这篇文章：&lt;a href=&quot;http://panzhifei.fun/2020/08/18/%E5%B1%A1%E9%A1%BE%E5%B0%94%E4%BB%86%E4%B8%8D%E8%BE%93%E5%B0%94%E8%BD%BD/&quot;&gt;《屡顾尔仆 不输尔载-Jekyll博客迁移计划：Gitalk 插件与 Google Analytics 的配置》&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;analytics&quot;&gt;Analytics&lt;/h2&gt;

&lt;p&gt;网站分析，现在支持百度统计和Google Analytics。需要去官方网站注册一下，然后将返回的code贴在下面：&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Baidu Analytics&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;ba_track_id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; 
&lt;span class=&quot;c1&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Google Analytics&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;ga_track_id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;UA-&apos;&lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;# 你用Google账号去注册一个就会给你一个这样的id&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;ga_domain&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;                    &lt;span class=&quot;c1&quot;&gt;# 默认的是 auto, 这里我是自定义了的域名，你如果没有自己的域名，需要改成auto。&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;customization&quot;&gt;Customization&lt;/h2&gt;

&lt;p&gt;如果你喜欢折腾，你可以去自定义这个模板的 Code。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;如果你可以理解 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_include/&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_layouts/&lt;/code&gt;文件夹下的代码（这里是整个界面布局的地方），你就可以使用 Jekyll 使用的模版引擎 &lt;a href=&quot;https://github.com/Shopify/liquid/wiki&quot;&gt;Liquid&lt;/a&gt;的语法直接修改/添加代码，来进行更有创意的自定义界面啦！&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;header-image&quot;&gt;Header Image&lt;/h2&gt;

&lt;p&gt;博客每页的标题底图是可以自己选的，看看几篇示例post你就知道如何设置了。&lt;/p&gt;

&lt;p&gt;标题底图的选取完全是看个人的审美了。每一篇文章可以有不同的底图，你想放什么就放什么，最后宽度要够，大小不要太大，否则加载慢啊。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;上传的图片最好先压缩，这里推荐 imageOptim 图片压缩软件，让你的博客起飞。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;但是需要注意的是本模板的标题是&lt;strong&gt;白色&lt;/strong&gt;的，所以背景色要设置为&lt;strong&gt;灰色&lt;/strong&gt;或者&lt;strong&gt;黑色&lt;/strong&gt;，总之深色系就对了。当然你还可以自定义修改字体颜色，总之，用github pages就是可以完全的个性定制自己的博客。&lt;/p&gt;

&lt;h2 id=&quot;seo-title&quot;&gt;SEO Title&lt;/h2&gt;

&lt;p&gt;我的博客标题是 &lt;strong&gt;呐啥&lt;/strong&gt; ，但是我想要在搜索的时候显示 &lt;strong&gt;哦豁&lt;/strong&gt; ，这个就需要 SEO Title 来定义了。&lt;/p&gt;

&lt;p&gt;其实这个 SEO Title 就是定义了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;标题&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&lt;/code&gt; 这个里面的东西和多说分享的标题，可以自行修改的。&lt;/p&gt;

&lt;h2 id=&quot;增加阅读时间和字数统计&quot;&gt;增加阅读时间和字数统计&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;注意：以下代码中出现的全角花括号要改成半角花括号。不要问我为什么，问就是这个影响我全局代码编译。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Displaying a post’s word count is rather common when creating a blog, but usually those techniques rely on JavaScript to work. The script reads the post’s text, counts the words and displays the result accordingly. That was the way I did things on this blog first as well, but then I set out to find a better way.&lt;/p&gt;

&lt;h3 id=&quot;showing-the-word-count&quot;&gt;Showing the word count&lt;/h3&gt;

&lt;p&gt;Luckily Jekyll provides a handy liquid filter called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;number_of_words&lt;/code&gt;. So displaying the actual word count is as simple as that:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s&quot;&gt;｛｛ page.content | number_of_words ｝｝&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;While this works just nicely it’s not very solid. You might want to hide word counts on shorter posts, for example as they’re of little value in such posts. This is a little more complex as you can not directly use Liquid filters in a conditional block.&lt;/p&gt;

&lt;h3 id=&quot;variables-in-liquid&quot;&gt;Variables in Liquid&lt;/h3&gt;

&lt;p&gt;In Liquid there are two ways to create variables. You can &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;｛% assign %｝&lt;/code&gt; a variable and you can &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;｛% capture %｝&lt;/code&gt; a variable. The difference might not be obvious, but it’s simple once you get it.&lt;/p&gt;

&lt;p&gt;Assigning a value to a variable means that you take any kind of data (e.g. a string, a number, a boolean) and Liquid knows that you want to access that exact data when you refer to this variable. An assigned variable is fixed, that means you can not use the value returned from other Liquid tags.&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s&quot;&gt;｛% assign awesome = &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; %｝&lt;/span&gt;

&lt;span class=&quot;s&quot;&gt;｛% if awesome %｝&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;&amp;lt;p&amp;gt;Yay, awesome!&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;｛% endif %｝&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But what if you want to store a Liquid tags’s return value in a variable? That’s exactly what the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;｛% capture %｝&lt;/code&gt; block is for. Unlike assigned variables, captured variables can only hold strings — which will cause us some trouble later on. This is simply because Liquid tags return strings by default.&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s&quot;&gt;｛% capture value %｝&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;｛｛ page.title | upcase ｝｝ from ｛｛ page.date | date&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;%b&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;%d,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;%y&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;｝｝&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;｛% endcapture %｝&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As you can see in the above example, you can capture any number of strings into a variable, be it strings returned from a Liquid tag or fixed strings.&lt;/p&gt;

&lt;h3 id=&quot;making-the-word-count-conditional&quot;&gt;Making the word count conditional&lt;/h3&gt;

&lt;p&gt;Now that you know about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;｛% assign %｝&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;｛% capture %｝&lt;/code&gt; we can move on to store our word count in a variable. The question remains, do we assign the variable or do we capture it?&lt;/p&gt;

&lt;p&gt;It should be clear by now that we’ll have to capture the value as it’s returned from a Liquid tag. That gives us something like this:&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s&quot;&gt;｛% capture words %｝&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;｛｛ page.content | number_of_words ｝｝&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;｛% endcapture %｝&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Let’s say we considered posts that are shorter than 250 words not worthy of getting the word count. A good example for this would be ‘link list’-style post that consist of mostly a quote from the original article and a comment spanning a sentence or two. Ideally, this would be taken care of using a simple conditional block.&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s&quot;&gt;｛% if words &amp;gt; 250 %｝&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;｛｛ words ｝｝&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;｛% endif %｝&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But you’ll soon see that this won’t work as intended as Jekyll will throw you this error an error saying you’ve attempted to compare a string (the words) with a number (250), which is entirely true, and also, sadly, entirely not possible. There is, however, a simple workaround.&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s&quot;&gt;｛% capture words %｝&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;｛｛  page.content | number_of_words | minus&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;250 ｝｝&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;｛% endcapture %｝&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;｛% unless words contains &quot;-&quot; %｝&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;｛｛  words | plus&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;250 ｝｝&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;｛% endunless %｝&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can use Liquid filters to substract your minimum number from the word count to see if it falls below 0. If it does it will contain a ‘-‘ at the beginning, which means the post is too short and won’t get the word number displayed. If our variable doesn’t contain a ‘-‘ we can simply add our minimum number back to the word count and display it. Quite simple, right?&lt;/p&gt;

&lt;h3 id=&quot;customising-the-output&quot;&gt;Customising the output&lt;/h3&gt;

&lt;p&gt;Now that we finally have our word number along with the conditional to hide it from short posts we can move on to make the output a bit nicer. You do this using Liquid filters like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;append&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;prepend&lt;/code&gt;. For a complete list of available filters you can check Shopify’s &lt;a href=&quot;https://github.com/Shopify/liquid/wiki/Liquid-for-Designers#standard-filters&quot;&gt;Liquid for Designers guide&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;｛｛  words | plus: 250 | append&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;words&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;｝｝&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The above snippet results in something like ‘There are 250 words in this post’. You can go crazy with filters, they offer lots of possibilities.&lt;/p&gt;

&lt;h3 id=&quot;calculating-the-reading-time&quot;&gt;Calculating the reading time&lt;/h3&gt;

&lt;p&gt;You might have noticed that I display an estimated reading time on this blog instead of just a word count. Personally, I just think this is a more useful guideline. Doing this is as easy as putting the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;divided_by&lt;/code&gt; filter into our final word count construct. The number to divide by is arbitrary, but 180 is the avarage number of words a person reads per minute.&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;｛｛  words | plus: 250 | divided_by: 180 | append&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;minutes&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;read&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;｝｝&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;summing-it-up&quot;&gt;Summing it up&lt;/h3&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s&quot;&gt;｛% capture words %｝&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;｛｛  page.content | number_of_words | minus&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;250 ｝｝&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;｛% endcapture %｝&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;｛% unless words contains &quot;-&quot; %｝&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;｛｛  words | plus&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;: 250 | append&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;words&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;｝｝&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;｛% endunless %｝&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s&quot;&gt;｛% capture words %｝&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;｛｛  page.content | number_of_words | minus&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;250 ｝｝&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;｛% endcapture %｝&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;｛% unless words contains &quot;-&quot; %｝&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;｛｛  words | plus&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;: 250 | divided_by: 180 | append&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;minute&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;read&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;｝｝&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;｛% endunless %｝&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;这是我用的参数&quot;&gt;这是我用的参数&lt;/h3&gt;

&lt;p&gt;在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/_include&lt;/code&gt;下新建&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;read_time.html&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;word_count.html&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s&quot;&gt;&amp;lt;!-- Add Read Time and word count, by chiya 2021.02.06--&amp;gt;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;｛% capture words %｝&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;｛｛  content | number_of_words | minus&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;0 ｝｝&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;｛% endcapture %｝&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;｛% unless words contains &apos;-&apos; %｝&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;｛｛  words | plus: 200 | divided_by: 100 | append&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;minute(s)&apos;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;｝｝&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;｛% endunless %｝&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s&quot;&gt;&amp;lt;!-- Add Read Time and word count, chiya 2021.02.06--&amp;gt;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;｛% capture words %｝&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;｛｛  page.content | number_of_words | minus&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;10 ｝｝&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;｛% endcapture %｝&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;｛% unless words contains &quot;-&quot; %｝&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;｛｛  words | plus&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;: 10 | append&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;words&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;｝｝&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;｛% endunless %｝&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后编辑&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;./_layouts/post.html&lt;/code&gt;，大概在43行处。&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s&quot;&gt;&amp;lt;header class=&quot;intro-header&quot; &amp;gt;&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&amp;lt;div class=&quot;header-mask&quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&amp;lt;div class=&quot;container&quot;&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;lt;div class=&quot;row&quot;&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&amp;lt;div class=&quot;col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1&quot;&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;s&quot;&gt;&amp;lt;div class=&quot;post-heading&quot;&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;s&quot;&gt;&amp;lt;div class=&quot;tags&quot;&amp;gt;&lt;/span&gt;
                        &lt;span class=&quot;s&quot;&gt;｛% for tag in page.tags %｝&lt;/span&gt;
                        &lt;span class=&quot;s&quot;&gt;&amp;lt;a class=&quot;tag&quot; href=&quot;｛｛  site.baseurl ｝｝/tags/#｛｛  tag ｝｝&quot; title=&quot;｛｛  tag ｝｝&quot;&amp;gt;｛｛  tag ｝｝&amp;lt;/a&amp;gt;&lt;/span&gt;
                        &lt;span class=&quot;s&quot;&gt;｛% endfor %｝&lt;/span&gt;
                    &lt;span class=&quot;s&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;s&quot;&gt;&amp;lt;h1&amp;gt;｛｛  page.title ｝｝&amp;lt;/h1&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;s&quot;&gt;｛% comment %｝&lt;/span&gt;
                        &lt;span class=&quot;s&quot;&gt;always create a h2 for keeping the margin , Hux&lt;/span&gt;
                    &lt;span class=&quot;s&quot;&gt;｛% endcomment %｝&lt;/span&gt;
                    &lt;span class=&quot;s&quot;&gt;｛% comment %｝ if page.subtitle ｛% endcomment %｝&lt;/span&gt;
                    &lt;span class=&quot;s&quot;&gt;&amp;lt;h2 class=&quot;subheading&quot;&amp;gt;｛｛  page.subtitle ｝｝&amp;lt;/h2&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;s&quot;&gt;｛% comment %｝ endif ｛% endcomment %｝&lt;/span&gt;
                    &lt;span class=&quot;s&quot;&gt;&amp;lt;!-- Add Read Time and word count, by chiya 2021.02.06--&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;s&quot;&gt;&amp;lt;p class=&quot;meta&quot;&amp;gt;&lt;/span&gt;
                        &lt;span class=&quot;s&quot;&gt;&amp;lt;span&amp;gt;Posted by ｛% if page.author %｝｛｛  page.author ｝｝｛% else %｝｛｛  site.title ｝｝｛% endif %｝ on ｛｛  page.date | date&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;%B&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;%-d,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;%Y&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;｝｝&amp;lt;/span&amp;gt;&lt;/span&gt;
                        &lt;span class=&quot;s&quot;&gt;&amp;lt;span&amp;gt;- ｛% include word_count.html %｝, ｛% include read_time.html %｝ to read&amp;lt;/span&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;s&quot;&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;s&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;s&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;最终使用&quot;&gt;最终使用&lt;/h1&gt;

&lt;p&gt;如果配置好nginx和Jekyll的话&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;文件夹
git clone 仓库地址
git pull origin master
jekyll build &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; /var/www/html/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;现在我单独写了个脚本用于自动拉取编译以及发布：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /var/www/html/
&lt;span class=&quot;nb&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-rf&lt;/span&gt; /var/www/html/blog/
&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; /root/icing.fun
git pull origin master
jekyll build &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; /root/icing.fun &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; /var/www/html/blog/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;chmod&lt;/span&gt; +x deploy.sh
rvm cron setup
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;crontab &lt;span class=&quot;nt&quot;&gt;-e&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;# 编辑&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*&lt;/span&gt; /bin/bash /root/push_blog.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;每分钟就能拉取一次编译发布。&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>【新品开箱】Make Windows Great Again</title>
   <link href="https://icing.fun/posts/make_windows_great_again.html"/>
   <updated>2023-11-29T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/make_windows_great_again</id>
   <content type="html">&lt;h2 id=&quot;补记&quot;&gt;补记&lt;/h2&gt;

&lt;p&gt;电源计划 卓越性能，启动！&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;powercfg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-duplicatescheme&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;e9a42b02-d5df-448d-aa00-03f14749eb61&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;显示成功。但在电源计划里依然没有显示卓越性能。&lt;/p&gt;

&lt;p&gt;此时需要修改注册表的CSEnabled值，但CSEnabled不见了(之前有的)，所以应该在管理员模式下的 cmdlet 敲&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;reg&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;HKLM\System\CurrentControlSet\Control\Power&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;/v&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;PlatformAoAcOverride&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;/t&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;REG_DWORD&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;/d&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;问了一下 Premier 事业部的同事，他们说目前据了解20H2取消了csenable更改来设置高性能，需要指令调用。&lt;/p&gt;

&lt;p&gt;====================================&lt;/p&gt;

&lt;p&gt;如何优雅地使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Windows&lt;/code&gt; 作为开发环境。&lt;/p&gt;

&lt;h2 id=&quot;如何使用-wsl-在-windows-上优雅地安装-linux&quot;&gt;如何使用 WSL 在 Windows 上优雅地安装 Linux&lt;/h2&gt;

&lt;h3 id=&quot;检视你电脑的版本&quot;&gt;检视你电脑的版本&lt;/h3&gt;

&lt;p&gt;必须是运行 Windows 10 版本 2004 及更高版本（内部版本 19041 及更高版本）或 Windows 11 的电脑才能优雅。其他的版本可以参阅&lt;a href=&quot;https://learn.microsoft.com/zh-cn/windows/wsl/install-manual&quot;&gt;手动安装页&lt;/a&gt;，但是不优雅。&lt;/p&gt;

&lt;h3 id=&quot;安装-wsl-优雅的命令&quot;&gt;安装 WSL 优雅的命令&lt;/h3&gt;

&lt;p&gt;现在，可以使用单个命令安装运行 WSL 所需的一切内容。 在管理员模式下打开 PowerShell 或 Windows 命令提示符，方法是右键单击并选择“以管理员身份运行”，输入 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wsl --install&lt;/code&gt; 命令，然后重启计算机。&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;wsl&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--install&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;此命令将启用运行 WSL 并安装 Linux 的 Ubuntu 发行版所需的功能。 （可以更改此默认发行版）。&lt;/p&gt;

&lt;p&gt;如果你运行的是旧版，或只是不想使用 install 命令并希望获得分步指引，请参阅旧版 WSL 手动安装步骤。&lt;/p&gt;

&lt;p&gt;首次启动新安装的 Linux 发行版时，将打开一个控制台窗口，要求你等待将文件解压缩并存储到计算机上。 未来的所有启动时间应不到一秒。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;上述命令仅在完全未安装 WSL 时才有效，如果运行 wsl –install 并查看 WSL 帮助文本，请尝试运行 wsl –list –online 以查看可用发行版列表并运行 wsl –install -d &lt;DistroName&gt; 以安装发行版。 若要卸载 WSL，请参阅&lt;a href=&quot;https://learn.microsoft.com/zh-cn/windows/wsl/troubleshooting#uninstall-legacy-version-of-wsl&quot;&gt;卸载旧版 WSL&lt;/a&gt; 或&lt;a href=&quot;https://learn.microsoft.com/zh-cn/windows/wsl/basic-commands#unregister-or-uninstall-a-linux-distribution&quot;&gt;注销或卸载 Linux 发行版&lt;/a&gt;。&lt;/DistroName&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;更改默认安装的-linux-发行版&quot;&gt;更改默认安装的 Linux 发行版&lt;/h3&gt;

&lt;p&gt;默认情况下，安装的 Linux 分发版为 Ubuntu。 可以使用 -d 标志进行更改。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;若要更改安装的发行版，请输入：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wsl --install -d &amp;lt;Distribution Name&amp;gt;&lt;/code&gt;。 将 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;Distribution Name&amp;gt;&lt;/code&gt; 替换为要安装的发行版的名称。&lt;/li&gt;
  &lt;li&gt;若要查看可通过在线商店下载的可用 Linux 发行版列表，请输入：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wsl --list --online&lt;/code&gt; 或 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wsl -l -o&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;若要在初始安装后安装其他 Linux 发行版，还可使用命令：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wsl --install -d &amp;lt;Distribution Name&amp;gt;&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;如果要通过 Linux/Bash 命令行（而不是通过 PowerShell 或命令提示符）安装其他发行版，必须在命令中使用 .exe：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wsl.exe --install -d &amp;lt;Distribution Name&amp;gt;&lt;/code&gt; 或若要列出可用发行版，则使用：&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wsl.exe -l -o&lt;/code&gt;。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;s&gt;Ubuntu 不够你用是吧？&lt;/s&gt;

&lt;h3 id=&quot;将版本从-wsl-1-升级到-wsl-2&quot;&gt;将版本从 WSL 1 升级到 WSL 2&lt;/h3&gt;

&lt;p&gt;使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wsl --install&lt;/code&gt; 命令安装的新 Linux 安装将默认设置为 WSL 2。&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wsl --set-version&lt;/code&gt; 命令可用于从 WSL 2 降级到 WSL 1，或将以前安装的 Linux 发行版从 WSL 1 更新到 WSL 2。&lt;/p&gt;

&lt;p&gt;要查看 Linux 发行版是设置为 WSL 1 还是 WSL 2，请使用命令 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wsl -l -v&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;要更改版本，请使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wsl --set-version &amp;lt;distro name&amp;gt; 2&lt;/code&gt; 命令将 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;distro name&amp;gt;&lt;/code&gt; 替换为要更新的 Linux 发行版的名称。 例如，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wsl --set-version Ubuntu-20.04 2&lt;/code&gt; 会将 Ubuntu 20.04 发行版设置为使用 WSL 2。&lt;/p&gt;

&lt;p&gt;如果在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wsl --install&lt;/code&gt; 命令可用之前手动安装了 WSL，则可能还需要启用 WSL 2 所使用的虚拟机可选组件并安装内核包（如果尚未这样做）。&lt;/p&gt;

&lt;h3 id=&quot;wsl-子系统访问宿主机的-proxy&quot;&gt;WSL 子系统访问宿主机的 Proxy&lt;/h3&gt;

&lt;p&gt;在 WSL 里面新建一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setProxy.sh&lt;/code&gt; , 然后把这个复制进去：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#!/bin/bash&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;hostip&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cat&lt;/span&gt; /etc/resolv.conf | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;nameserver | &lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;{ print $2 }&apos;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;wslip&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;hostname&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-I&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;awk&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;{print $1}&apos;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;7890

&lt;span class=&quot;nv&quot;&gt;PROXY_HTTP&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;http://&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hostip&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

set_proxy&lt;span class=&quot;o&quot;&gt;(){&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;http_proxy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PROXY_HTTP&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;HTTP_PROXY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PROXY_HTTP&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

    &lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;https_proxy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PROXY_HTTP&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;HTTPS_PROXY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PROXY_HTTP&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

    git config &lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt; http.proxy &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PROXY_HTTP&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
    git config &lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt; https.proxy &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PROXY_HTTP&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;

    &lt;span class=&quot;c&quot;&gt;# 设置APT代理&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Acquire::http::Proxy &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PROXY_HTTP&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;;&quot;&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;sudo tee&lt;/span&gt; /etc/apt/apt.conf.d/95proxies &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /dev/null
    &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Acquire::https::Proxy &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PROXY_HTTP&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;;&quot;&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;sudo tee&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-a&lt;/span&gt; /etc/apt/apt.conf.d/95proxies &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; /dev/null
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

unset_proxy&lt;span class=&quot;o&quot;&gt;(){&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;unset &lt;/span&gt;http_proxy
    &lt;span class=&quot;nb&quot;&gt;unset &lt;/span&gt;HTTP_PROXY

    &lt;span class=&quot;nb&quot;&gt;unset &lt;/span&gt;https_proxy
    &lt;span class=&quot;nb&quot;&gt;unset &lt;/span&gt;HTTPS_PROXY

    git config &lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--unset&lt;/span&gt; http.proxy
    git config &lt;span class=&quot;nt&quot;&gt;--global&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--unset&lt;/span&gt; https.proxy

    &lt;span class=&quot;c&quot;&gt;# 移除APT代理设置&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;sudo rm&lt;/span&gt; /etc/apt/apt.conf.d/95proxies
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

test_setting&lt;span class=&quot;o&quot;&gt;(){&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Host ip:&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;hostip&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;WSL ip:&quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;wslip&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Current proxy:&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$https_proxy&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;set&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;then
    &lt;/span&gt;set_proxy

&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;unset&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;then
    &lt;/span&gt;unset_proxy

&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;test&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;then
    &lt;/span&gt;test_setting
&lt;span class=&quot;k&quot;&gt;else
    &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Unsupported arguments.&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;理论上是所有系统都可以这样做&lt;/p&gt;

&lt;p&gt;然后 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chmod +x setProxy.sh&lt;/code&gt; , 最后要设置的时候就 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;source ./setProxy.sh set&lt;/code&gt; 就行了。&lt;/p&gt;

&lt;h3 id=&quot;powershell-美化&quot;&gt;PowerShell 美化&lt;/h3&gt;

&lt;h4 id=&quot;scoop包管理器&quot;&gt;Scoop包管理器：&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;https://scoop.sh/&quot;&gt;Scoop&lt;/a&gt; 是 Windows 的命令行安装程序。使用 Scoop，可以为终端安装程序和插件。&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;Set-ExecutionPolicy&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;RemoteSigned&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Scope&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;CurrentUser&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;irm&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;get.scoop.sh&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iex&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scoop&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;搜索软件&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scoop&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;安装软件&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scoop&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;查看软件详细信息&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scoop&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;查看已安装软件&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scoop&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;uninstall&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;卸载软件，&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;删除配置文件。&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scoop&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;更新&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;scoop&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;本体和软件列表&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scoop&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;更新指定软件&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scoop&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;update&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;更新所有已安装的软件&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scoop&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;checkup&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;检查&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;scoop&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;的问题并给出解决问题的建议&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scoop&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;help&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;查看命令列表&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scoop&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;help&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;查看命令帮助说明&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;gsudo提权&quot;&gt;gsudo（提权）&lt;/h4&gt;

&lt;p&gt;&lt;a href=&quot;https://gerardog.github.io/gsudo/&quot;&gt;gsudo&lt;/a&gt; 是 sudo 在 Windows 的等价物，具有与原始 Unix/Linux sudo 相似的用户体验。允许在当前控制台窗口或新控制台窗口中以提升的权限运行命令，或提升当前 shell。&lt;/p&gt;

&lt;p&gt;只需 gsudo 将（或sudo别名）添加到您的命令中，它就会以提升的方式运行。&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;###GSUDO&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;#安装：&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scoop&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;gsudo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;#导入配置文件内$PROFILE：&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# 添加以下这行&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Import-Module&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Get-Command&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;gsudoModule.psd1&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Source&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# 或者运行这行命令:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Get-Command&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;gsudoModule.psd1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Write-Output&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;`n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;Import-Module &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;`&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Source&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;`&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Add-Content&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$PROFILE&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;#在PowerShell中执行notepad $PROFILE，打开文件。&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;#在其中添加：&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Set-alias&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;su&apos;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;gsudo&apos;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Set-alias&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;sudo&apos;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;gsudo&apos;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;$PROFILE&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;使配置生效&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# gsudo如果用户选择启用缓存，则可以提升多次，仅显示一个 UAC 弹出窗口。&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# 凭据缓存&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;使用&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;手动启动&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;停止缓存会话&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;gsudo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cache&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;off&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;。&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;使用&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;停止所有缓存会话&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gsudo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-k&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;。&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;可用的缓存模式：&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Disabled:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;每次提权都会显示一个&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;UAC&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;弹出窗口。&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Explicit:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;（默认）每次提权都会显示一个&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;UAC&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;弹出窗口，除非缓存会话以&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;gsudo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;cache&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Auto:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;类似于&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;unix-sudo&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;。第一个提权显示&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;UAC&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;弹出窗口并自动启动缓存会话。&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;使用更改缓存模式&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gsudo&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;CacheMode&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Disabled&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Explicit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Auto&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;git-和-posh-git&quot;&gt;Git 和 posh-git&lt;/h4&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;###SCOOP安装GIT&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scoop&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bucket&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scoop&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;git&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;#验证GIT安装：&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;git&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--version&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;#模块安装posh-git&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Install-Module&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;posh-git&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Scope&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;AllUser&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Force&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;#notepad $PROFILE打开配置档案,添加以下：&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Import-Module&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;posh-git&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;#配置完成后，运行.$PROFILE,使得修改生效&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# 克隆任何 GitHub 存储库，以测试在输入常用 git 命令时 posh-git的反映：&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;git&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;clone&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;https://github.com/dahlbyk/posh-git&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;posh-git&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;psreadline-语法定制&quot;&gt;PSReadline 语法定制&lt;/h4&gt;

&lt;p&gt;PSReadLine 是微软创建的一个模块，用于自定义 PowerShell 中的命令行编辑环境。它提供了大量的定制，可以改变命令行编辑器以多种方式呈现数据的方式。&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 安装&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Install-Module&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;PSReadLine&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# 配置文件：&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Import-Module&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;PSReadLine&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;fzf&quot;&gt;fzf&lt;/h4&gt;

&lt;p&gt;fzf 是一个用于命令行的模糊文件查找器。&lt;/p&gt;

&lt;p&gt;这将为当前文件夹层次结构中的文件启用搜索机制，或者能够查看您之前使用的先前命令。&lt;/p&gt;

&lt;p&gt;要使用 PSFzf，您必须先安装 fzf。&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# 首先，需要通过SCOOP安装&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scoop&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fzf&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# 第二步，安装模块：&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Install-Module&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;PSFzf&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# 配置文件：&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Import-Module&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;PSFzf&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Set-PsFzfOption&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-PSReadLineChordProvider&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;‘&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Ctrl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;’&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-PSReadLineChordReverseHistory&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;‘&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Ctrl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;’&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;###&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;#Ctrl+f您可以在当前文件夹和子文件夹中搜索文件。&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;#您可以通过Ctrl+r列表查看使用过的命令的历史记录。&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;z&quot;&gt;z&lt;/h4&gt;

&lt;p&gt;z 可让您根据&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cd&lt;/code&gt;命令历史记录在 PowerShell 中快速浏览文件系统。&lt;/p&gt;

&lt;p&gt;z 也是经常使用的模块之一，它有助于快速导航到常用目录，&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;Install-Module&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;neovim&quot;&gt;Neovim&lt;/h4&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;scoop&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;neovim&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;powershell-升级&quot;&gt;Powershell 升级&lt;/h4&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;iex&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&amp;amp; { &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;irm&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;https://aka.ms/install-powershell.ps1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; } -UseMSI&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;git-一键推送&quot;&gt;Git 一键推送&lt;/h3&gt;

&lt;p&gt;新建一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git_push.ps1&lt;/code&gt;：&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# PowerShell Script to Perform Git Operations with User-Inputted Path&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Prompt for the path to the Git repository&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$repoPath&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Read-Host&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Prompt&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Enter the path to your git repository&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Change to the specified directory&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$repoPath&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Update git&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;git&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pull&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Add all changes to staging&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;git&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;--all&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Prompt for a commit message&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$commitMessage&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Read-Host&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-Prompt&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Enter your commit message&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Commit the changes&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;git&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;commit&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$commitMessage&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Push the changes to the remote repository&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;git&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;

&lt;/span&gt;&lt;span class=&quot;c&quot;&gt;# Back to the origin folder&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cd&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;倒叙之前因后果&quot;&gt;倒叙之前因后果&lt;/h2&gt;

&lt;p&gt;11月月初俺爹斥巨资给我换了个笔记本电脑&lt;/p&gt;

&lt;center&gt;
    &lt;img src=&quot;../img/post/2023/11/29/order.jpg&quot; alt=&quot;Order&quot; title=&quot;Order&quot; width=&quot;50%&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;可能有人要“素质三连”了&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Surface Pro 9 不是有酷睿版吗？SQ3 版不是很垃圾吗？有这个钱为什么不买苹果？&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;首先就是全功能 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Type-C&lt;/code&gt; 接口，两个接口可以提供视频，音频，数据传输，更重要的是可以充电。这不比原装的那个方便？带个小米67W就可以搞定手机和电脑的充电了。酷睿版就八行，只能拿那个笨笨的充电器充电。&lt;/p&gt;

&lt;center&gt;
    &lt;img src=&quot;../img/post/2023/11/29/type-c.png&quot; alt=&quot;Type-C&quot; title=&quot;Type-C&quot; width=&quot;50%&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;5G 网络说实在真的很香，之前在学校办的移动的号，大流量卡，装这个上面，基本上是全天在线，很舒服。&lt;/p&gt;

&lt;p&gt;之前去上海面试的时候，在高铁上就可以用电脑来办公，还能追追剧。&lt;/p&gt;

&lt;p&gt;随身WiFi稍微麻烦了点，比如我现在也在用华为的。&lt;/p&gt;

&lt;center&gt;
    &lt;img src=&quot;../img/post/2023/11/29/5g.png&quot; alt=&quot;5G&quot; title=&quot;5G&quot; width=&quot;50%&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;再来就是这个屏幕了，这个屏幕香不香我不知道，主要是能触屏，MacBook那么多年也不能触屏。（估计有人就要骂我，说苹果触控板好用，我只能说，我不喜欢，我喜欢触屏）&lt;/p&gt;

&lt;center&gt;
    &lt;img src=&quot;../img/post/2023/11/29/touch.png&quot; alt=&quot;Touch&quot; title=&quot;Touch&quot; width=&quot;50%&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;说它是个大号平板也不为过，我现在就是拿着它在写这篇文章，很舒服。安卓平板根本打不过，如果说我要用安卓应用，Windows还有安卓子系统。&lt;/p&gt;

&lt;center&gt;
    &lt;img src=&quot;../img/post/2023/11/29/android.png&quot; alt=&quot;Android&quot; title=&quot;Android&quot; width=&quot;50%&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;8cx Gen 3 跑分啥的对我来说确实不重要，抛开实际体验的跑分都是耍流氓。&lt;/p&gt;

&lt;p&gt;实际体验下来没啥用不了的应用，转译慢就慢我还能摸摸鱼。Python脚本可以跑，我用的是 Anaconda 的环境，没啥问题。IDE用的 VSCode，有原生 ARM64 版本，也没啥问题。VS也能用，还能编译x64/x86的程序，也没啥问题。&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>【阅板无数】LinkIt Smart 7688/Duo 考古</title>
   <link href="https://icing.fun/posts/linkit_smart_7688.html"/>
   <updated>2023-11-28T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/linkit_smart_7688</id>
   <content type="html">&lt;p&gt;【阅板无数】LinkIt™ Smart 7688/Duo 使用手册&lt;/p&gt;

&lt;p&gt;MT7688 是一个由联发科技（MediaTek）开发的高性能无线SoC（System on Chip）。它主要用于驱动智能家居和物联网（IoT）设备。MT7688 芯片支持 802.11n Wi-Fi 标准，能够提供高速的无线连接。此外，它通常包括多种接口和功能，比如 USB、GPIO、以太网接口，以及内存和存储接口，这使得它能够灵活地应用于各种设备和应用场景中。&lt;/p&gt;

&lt;h2 id=&quot;参考网站&quot;&gt;参考网站&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://steward-fu.github.io/website/mcu/mt7688/build_openwrt.htm&quot;&gt;(MIPS 24KEc) MT7688 (LinkIt Smart 7688) Build OpenWRT - 司徒的教學網站&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://docs.labs.mediatek.com/resource/linkit-smart-7688/en&quot;&gt;LinkIt Smart 7688/Duo - Mediatek&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://wiki.seeedstudio.com/LinkIt_Smart_7688/&quot;&gt;LinkIt Smart 7688/Duo - SeeedStudio Wiki&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;讲真，Seeed 做的东西都是好东西，但是就是不好好维护&lt;/p&gt;

&lt;h2 id=&quot;编译-openwrt&quot;&gt;编译 OpenWRT&lt;/h2&gt;

&lt;p&gt;截至博客发布日期，我按照网上的教程编译来编译去都用不了，服了&lt;/p&gt;

&lt;p&gt;最后通过 Internet Archive 找到了原始镜像和硬件电路图&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/IcingTomato/embedded_linux_dev/tree/master/MIPS/MT7688_series/LinkIt_Smart_7688(Duo)&quot;&gt;IcingTomato/embedded_linux_dev - GitHub&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# MD5 Check&lt;/span&gt;
51107d057bda7ac71baeac3277e6e3d1  Hardware_Schematics.zip
4e40f19c968e45aaa2cc9d36c3095f03  LinkIt_Smart_7688_Firmware_upgrade.zip
2438f95e0466a454d491c8029e509d6e  Manual.zip
1fb86b892294d3082d8a05d450108c76  MediaTek_LinkIt_Smart_7688_bootloader_v0.8.2.zip
40717f554a8f455df62b238274db1fe4  MediaTek_LinkIt_Smart_7688_firmware_v0.9.2.zip
9e8a7237d8f0c55add7e685a12cf7d12  swapsd.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;其中 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swapsd.sh&lt;/code&gt; 用于将系统从内置闪存切换到外置 SD 卡，并添加 swap 分区&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>【嵌入式实践】Amazon Alexa on M5Core2</title>
   <link href="https://icing.fun/posts/alexa_on_m5core2.html"/>
   <updated>2022-08-15T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/alexa_on_m5core2</id>
   <content type="html">&lt;p&gt;如何用 ESP32 制作一个语音助手&lt;/p&gt;

&lt;p&gt;Amazon Alexa for M5Stack M5Core2(ESP32)&lt;/p&gt;

&lt;h2 id=&quot;0-briefing-of-alexa&quot;&gt;0. Briefing of Alexa&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Amazon Alexa&lt;/strong&gt;, also known simply as &lt;strong&gt;Alexa&lt;/strong&gt;, is a virtual assistant technology largely based on a Polish speech synthesiser named Ivona, bought by Amazon in 2013. It was first used in the Amazon Echo smart speaker and the Echo Dot, Echo Studio and Amazon Tap speakers developed by Amazon Lab126. It is capable of voice interaction, music playback, making to-do lists, setting alarms, streaming podcasts, playing audiobooks, and providing weather, traffic, sports, and other real-time information, such as news. Alexa can also control several smart devices using itself as a home automation system. Users are able to extend the Alexa capabilities by installing “skills” (additional functionality developed by third-party vendors, in other settings more commonly called apps) such as weather programs and audio features. It uses automatic speech recognition, natural language processing, and other forms of weak AI to perform these tasks.&lt;/p&gt;

&lt;p&gt;Most devices with Alexa allow users to activate the device using a wake-word (such as Alexa or Amazon); other devices (such as the Amazon mobile app on iOS or Android and Amazon Dash Wand) require the user to click a button to activate Alexa’s listening mode, although, some phones also allow a user to say a command, such as “Alexa” or “Alexa wake”.&lt;/p&gt;

&lt;h2 id=&quot;1-introduction&quot;&gt;1. Introduction&lt;/h2&gt;

&lt;p&gt;Source Code is &lt;a href=&quot;https://github.com/IcingTomato/AlexaM5Core2&quot;&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;center&gt;
    &lt;img src=&quot;../img/post/2022/08/15/amazon-alexa-logo-300x93.png&quot; alt=&quot;Alexa Logo&quot; title=&quot;Alexa Logo&quot; width=&quot;50%&quot; /&gt;
&lt;/center&gt;

&lt;p&gt;&lt;a href=&quot;https://developer.amazon.com/en-US/alexa&quot;&gt;Amazon Alexa&lt;/a&gt; on &lt;a href=&quot;https://docs.m5stack.com/en/core/core2&quot;&gt;M5Core2&lt;/a&gt; and &lt;a href=&quot;https://docs.m5stack.com/en/core/core2_for_aws&quot;&gt;M5Core2 for AWS&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can use M5Core2Alexa like using a real Amazon Echo (sometimes, not always). You can ask M5Alexa questions like “Alexa, what time is sunrise?” or ask her into Japanese 「アレクサ、今何時ですか？」, or maybe you can control your lights and fans (I don’t have any Alexa-supported IoT devices).&lt;/p&gt;

&lt;h2 id=&quot;2-development-setup&quot;&gt;2. Development Setup&lt;/h2&gt;

&lt;p&gt;This sections talks about setting up your development host, fetching the git repositories, and instructions for build and flash.&lt;/p&gt;

&lt;h3 id=&quot;21-host-setup&quot;&gt;2.1 Host Setup&lt;/h3&gt;

&lt;p&gt;You should install drivers and support packages for your development host. Windows, Linux and Mac OS-X, are supported development hosts. Please see Get Started for the host setup instructions.&lt;/p&gt;

&lt;h3 id=&quot;22-getting-the-repositories&quot;&gt;2.2 Getting the Repositories&lt;/h3&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone &lt;span class=&quot;nt&quot;&gt;--recursive&lt;/span&gt; https://github.com/espressif/esp-idf.git

&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;esp-idf&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; git checkout release/v4.2&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; git submodule init&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; git submodule update &lt;span class=&quot;nt&quot;&gt;--init&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--recursive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

./install.sh

&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ..

git clone https://github.com/IcingTomato/AlexaM5Core2.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;23-building-the-firmware&quot;&gt;2.3 Building the Firmware&lt;/h3&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;AlexaM5Core2/examples/amazon_alexa/ 

&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ESPPORT&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/dev/ttyUSB0 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;or /dev/ttycu.SLAB_USBtoUART macOS or COMxx on MinGW&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;IDF_PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/path/to/esp-idf

&lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$IDF_PATH&lt;/span&gt;/export.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Set audio_board path for M5Core2 and AWS_EDUKIT_PATH:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;AUDIO_BOARD_PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/path/to/AlexaM5Core2/components/audio_hal/audio_board/audio_board_m5_core2_aws
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;AWS_EDUKIT_PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;/path/to/AlexaM5Core2/components/core2forAWS
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Menuconfig is avaliable, also you can change some components:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;idf.py menuconfig
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;3-configuration-steps&quot;&gt;3. Configuration Steps&lt;/h2&gt;

&lt;p&gt;Here are the steps to configure the M5Core2:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;On first boot-up, the M5Core2 is in configuration mode. This is indicated by Orange LED pattern. Please ensure that the LED pattern is seen as described above, before you proceed.&lt;/li&gt;
  &lt;li&gt;Launch the phone app.&lt;/li&gt;
  &lt;li&gt;Select the option &lt;em&gt;Add New Device&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;center&gt;
    &lt;img src=&quot;../img/post/2022/08/15/esp_alexa_app_home.png&quot; alt=&quot;App Home&quot; title=&quot;App Home&quot; width=&quot;50%&quot; /&gt;
&lt;/center&gt;

&lt;ul&gt;
  &lt;li&gt;A list of devices that are in configuration mode is displayed. Note that the devices are discoverable over BLE (Bluetooth Low Energy). Please ensure that the phone app has the appropriate permissions to access Bluetooth (on Android the &lt;em&gt;Location&lt;/em&gt; permission is also required for enabling Bluetooth).&lt;/li&gt;
&lt;/ul&gt;

&lt;center&gt;
    &lt;img src=&quot;../img/post/2022/08/15/esp_alexa_app_discover_devices.png&quot; alt=&quot;App Discover Devices&quot; title=&quot;App Discover Devices&quot; width=&quot;50%&quot; /&gt;
&lt;/center&gt;

&lt;ul&gt;
  &lt;li&gt;Now you can sign-in to your Amazon Alexa account. If you have Amazon Shopping app installed on the same phone, app will automatically sign-in with the account the shopping app is signed in to. Otherwise it will open a login page on the phone’s default browser. (It is recommended to install the Amazon Shopping app on your phone to avoid any other browser related errors.)&lt;/li&gt;
&lt;/ul&gt;

&lt;center&gt;
    &lt;img src=&quot;../img/post/2022/08/15/esp_alexa_app_sign_in.png&quot; alt=&quot;App Sign-in&quot; title=&quot;App Sign-in&quot; width=&quot;50%&quot; /&gt;
&lt;/center&gt;

&lt;ul&gt;
  &lt;li&gt;You can now select the Wi-Fi network that the M5Core2 should connect with, and enter the credentials for this Wi-Fi network.&lt;/li&gt;
&lt;/ul&gt;

&lt;center&gt;
    &lt;img src=&quot;../img/post/2022/08/15/esp_alexa_app_wifi_scan_list.png&quot; alt=&quot;App Scna List&quot; title=&quot;App Scan List&quot; width=&quot;50%&quot; /&gt;
    &lt;img src=&quot;../img/post/2022/08/15/esp_alexa_app_wifi_password.png&quot; alt=&quot;App Wi-Fi Password&quot; title=&quot;App Wi-Fi Password&quot; width=&quot;50%&quot; /&gt;
&lt;/center&gt;

&lt;ul&gt;
  &lt;li&gt;On successful Wi-Fi connection, you will see a list of few of the voice queries that you can try with the M5Core2.&lt;/li&gt;
&lt;/ul&gt;

&lt;center&gt;
    &lt;img src=&quot;../img/post/2022/08/15/esp_alexa_app_things_to_try.png&quot; alt=&quot;App Things To Try&quot; title=&quot;App Things To Try&quot; width=&quot;50%&quot; /&gt;
&lt;/center&gt;

&lt;ul&gt;
  &lt;li&gt;You are now fully setup. You can now say “Alexa” followed by the query you wish to ask.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;4-troubleshooting&quot;&gt;4. Troubleshooting&lt;/h2&gt;

&lt;h3 id=&quot;41-music-and-radio-playback-audible-or-podcast-are-not-supported-on-this-device&quot;&gt;4.1 Music and radio playback (Audible or Podcast) are not supported on this device.&lt;/h3&gt;

&lt;p&gt;According to Espressif Official, music and radio playback  (Audible or Podcast) services are not supported on Non-Amazon-Official products. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Unfortunately, Amazon music functionality needs whitelisted product. Only the commercial products are whitelisted by Amazon. Let us know if you are going to commercialise it.&lt;/code&gt;&lt;/p&gt;

&lt;h3 id=&quot;42-alarm-dismiss-doesnt-take-effect&quot;&gt;4.2 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alarm Dismiss&lt;/code&gt; doesn’t take effect.&lt;/h3&gt;

&lt;p&gt;When the alarm on, you cannot say “Alexa, stop alarm” to dismiss the alarm. I dno’t know why… So, if you want to stop the alarm, you can touch the middle “button” on M5Core2. The middle “button” can also wake up Alexa.&lt;/p&gt;

</content>
 </entry>
 
 <entry>
   <title>【运维实践】什么是LVM？</title>
   <link href="https://icing.fun/posts/what_is_lvm.html"/>
   <updated>2021-08-30T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/what_is_lvm</id>
   <content type="html">&lt;p&gt;深入浅出讲述 Linux 上的 LVM (Logical Volume Manager 逻辑卷管理)&lt;/p&gt;

&lt;p&gt;想象一个情况，我在网上买了个新电脑，自带 Windows 10 操作系统。512GiB 的硬盘我不想分区直接用，过了三个月：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/08/30/1.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;它快满了，我就添置一块硬盘当仓库盘。但是有些文件太大我还要花时间移动到新的仓库盘上……&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/08/30/2.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;虽然现在传输速度很快，但是还要花时间查找能移动和不能移动的文件确实麻烦。所以现在隆重介绍 LVM 逻辑卷管理。&lt;/p&gt;

&lt;p&gt;逻辑卷管理的重点在于 &lt;strong&gt;可以弹性调整 FlieSystem 的容量&lt;/strong&gt; 而不是 &lt;strong&gt;注重文件传输效率和数据安全&lt;/strong&gt; 上面。追求读写效率或者数据保护的可以使用 RAID 。&lt;/p&gt;

&lt;p&gt;LVM 可以整合成多个物理硬盘在一起，让这些分区看起来像在一块大硬盘上。而且在将来还可以新增或者移除物理硬盘到 LVM 中。&lt;/p&gt;

&lt;h2 id=&quot;什么是-lvm--pv-pe-vg-lv-的含义&quot;&gt;什么是 LVM : PV, PE, VG, LV 的含义&lt;/h2&gt;

&lt;p&gt;LVM 全名 Logical Volume Manager ，大陆中文译作 逻辑卷管理。台湾中文翻译成 邏輯捲軸管理員。在这里我觉得用『捲軸』来解释更方便，引用一下鸟哥的解释：&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;之所以稱為『捲軸』可能是因為可以將 filesystem 像捲軸一樣伸長或縮短之故吧！
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;LVM 的做法是将几个实体的 Partitions分区 (或者 Disks硬盘) 通过软件转换成 LVM 最底层的 “块” (PV) ，然后将这些 “块” 组合成一块庞大的 “硬盘” (VG)，接着将这块巨大的 “硬盘” 分割成一个个可以格式化的 “小硬盘” (LV)，最终就能挂载使用了。但是为什么这样可以对 FileSystem 进行扩容和缩小呢？其实和一个叫 PE 的东西有关。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/08/30/3.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;physical-volume-pv-物理卷&quot;&gt;Physical Volume, PV, 物理卷&lt;/h3&gt;

&lt;p&gt;物理卷的理解其实很简单，可以近似看作是我们买来的实体的硬盘。但实际上&lt;strong&gt;物理卷(PV)&lt;/strong&gt; 需要调整 &lt;strong&gt;硬盘(Disks)/分区(Partitions)&lt;/strong&gt; 的 &lt;strong&gt;系统识别码(systemID)&lt;/strong&gt; 为 &lt;em&gt;8e&lt;/em&gt;( LVM 的识别码)，然后再经过 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pvcreate&lt;/code&gt; 的指令将它转换成 LVM 最底层的 &lt;strong&gt;物理卷(PV)&lt;/strong&gt; ，之后才能将这些 PV 加以使用。调整 systemID 的方法有三种：&lt;strong&gt;gdisk,  fdisk 和 parted&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;&lt;em&gt;注：gdisk是仅为GPT分区使用，fdisk是仅为MBR分区使用，如果用错的的话主引导记录会被清空，切记切记&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;volume-group-vg-卷组&quot;&gt;Volume Group, VG, 卷组&lt;/h3&gt;

&lt;p&gt;顾名思义 卷组 就是很多个物理卷的凑成的一个组。就好比小学的时候会分小组，小组里面的每个同学就是物理卷，几个同学组成的一个组就是卷组。同理 VG 就是 LVM 将许多个 PV 整合成的东西。那么 VG 最大可以达到多少呢？这个和 PE物理块 和 LVM 的版本有关。在以前，32位的 Linux 操作系统上的 LVM(lvm1) 一个 LV 最大只能支持65534个 PE，假设使用 Linux 的默认设置(一个 PE 大小为4MiB)，那么一个 LV 的最大容量也就只有 4M*65534/(1024M/G)=256GiB。不过在64位的操作系统上 LV 几乎不存在大小限制。(主要还是和寻址有关系)&lt;/p&gt;

&lt;h3 id=&quot;physical-extent-pe-物理块&quot;&gt;Physical Extent, PE, 物理块&lt;/h3&gt;

&lt;p&gt;LVM 预设的 PE 大小是 &lt;strong&gt;4MiB&lt;/strong&gt;。它是整个 LVM 的最小存储区块，换句话说就是我们写入的每个文件都是往 PE 里面填充的。简单来说 PE 很像在机械硬盘上划分的磁道。所以调整 PE 大小会影响到 LVM 的最大容量的。但是在 CentOS/Red Hat 6 之后的操作系统普遍采用 lvm2 技术，以及64位 CPU 的出现，因此这个限制不复存在。&lt;/p&gt;

&lt;h3 id=&quot;logical-volume-lv-逻辑卷&quot;&gt;Logical Volume, LV, 逻辑卷&lt;/h3&gt;

&lt;p&gt;最终 一大块 VG 会像切蛋糕一样分成一个个 LV ，这些被切出来的 LV 就是能&lt;s&gt;吃的&lt;/s&gt;格式化使用的东西了。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/08/30/4.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;那么问题来了：LV 可以随意划分大小吗？答案是不可以。因为 PE 是 LVM 中最小的存储单位，所以 LV 的大小和 PV 的块数相关。在 Linux 系统中，为了方便我们使用 LVM 管理磁盘，LV 通常被命名为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/vg_name/lv_name&lt;/code&gt; 的样子。&lt;/p&gt;

&lt;p&gt;此外，前文中提及到 LVM 可以弹性变更 FileSystem 的容量，实际上是通过 “交换PE” 来进行扩容和缩小的操作，将原本逻辑卷LV中的物理块PE移出以缩小容量，将空闲的物理块PE移入现有逻辑卷LV以扩容。如下图：&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/08/30/5.gif&quot; alt=&quot;PE与VG&quot; /&gt;&lt;/p&gt;

&lt;p&gt;VG 内的 PE 会分给虚线部分的 LV ，如果未来这个 VG 要扩充的话，加上其他的 PV 即可。最重要的是如果 LV 要扩充的话，也可以通过加入 VG 内没有使用到的 PE 来扩充的。&lt;/p&gt;

&lt;h3 id=&quot;logical-extent-le-逻辑块&quot;&gt;Logical Extent, LE, 逻辑块&lt;/h3&gt;

&lt;p&gt;逻辑卷LV中可以分配的最小存储单元，在同一卷组VG中LE的大小和PE是相同的，并且一一相对。&lt;/p&gt;

&lt;h2 id=&quot;lvm-工具&quot;&gt;LVM 工具&lt;/h2&gt;

&lt;h3 id=&quot;fdisk-gdisk-和-parted&quot;&gt;fdisk, gdisk 和 parted&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;fdisk&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[student@node2 ~]## fdisk /dev/sda
欢迎使用 fdisk (util-linux 2.23.2)。

更改将停留在内存中，直到您决定将更改写入磁盘。
使用写入命令前请三思。

命令(输入 m 获取帮助)：          &amp;lt;==这里可以输入指令，可以按 m 来查看所有指令
命令(输入 m 获取帮助)：m
命令操作
   a   toggle a bootable flag
   b   edit bsd disklabel
   c   toggle the dos compatibility flag
   d   delete a partition                           #删除一个分区
   g   create a new empty GPT partition table
   G   create an IRIX (SGI) partition table
   l   list known partition types
   m   print this menu
   n   add a new partition                          #增加一个新分区
   o   create a new empty DOS partition table
   p   print the partition table                    #打印分区表
   q   quit without saving changes                  #不储存直接离开
   s   create a new empty Sun disklabel
   t   change a partition&apos;s system id
   u   change display/entry units
   v   verify the partition table
   w   write table to disk and exit                 #写入分区表并离开
   x   extra functionality (experts only)

命令(输入 m 获取帮助)：

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;gdisk&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[student@node2 ~]# gdisk /dev/vda  &amp;lt;==仔細看，不要加上數字喔！
GPT fdisk (gdisk) version 0.8.6

Partition table scan:
  MBR: protective
  BSD: not present
  APM: not present
  GPT: present

Found valid GPT with protective MBR; using GPT.  &amp;lt;==找到了 GPT 的分割表！

Command (? for help):           &amp;lt;==这里可以输入指令，可以按 ? 来查看所有指令
Command (? for help): ?
b       back up GPT data to a file
c       change a partition&apos;s name
d       delete a partition                            #删除一个分区
i       show detailed information on a partition
l       list known partition types
n       add a new partition                           #增加一个新分区
o       create a new empty GUID partition table (GPT)
p       print the partition table                     #打印分区表 
q       quit without saving changes                   #不储存直接离开
r       recovery and transformation options (experts only)
s       sort partitions
t       change a partition&apos;s type code
v       verify disk
w       write table to disk and exit                  #写入分区表并离开
x       extra functionality (experts only)
?       print this menu
Command (? for help):  
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;parted&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[student@node2 ~]# parted /dev/sda
GNU Parted 3.1
使用 /dev/sda
Welcome to GNU Parted! Type &apos;help&apos; to view a list of commands.
(parted) help                                                             
  align-check TYPE N                        check partition N for TYPE(min|opt) alignment
  help [COMMAND]                           print general help, or help on COMMAND
  mklabel,mktable LABEL-TYPE               create a new disklabel (partition table)
  mkpart PART-TYPE [FS-TYPE] START END     make a partition
  name NUMBER NAME                         name partition NUMBER as NAME
  print [devices|free|list,all|NUMBER]     display the partition table, available devices, free space, all found partitions, or a particular partition
  quit                                     exit program
  rescue START END                         rescue a lost partition near START and END
  
  resizepart NUMBER END                    resize partition NUMBER
  rm NUMBER                                delete partition NUMBER
  select DEVICE                            choose the device to edit
  disk_set FLAG STATE                      change the FLAG on selected device
  disk_toggle [FLAG]                       toggle the state of FLAG on selected device
  set NUMBER FLAG STATE                    change the FLAG on partition NUMBER
  toggle [NUMBER [FLAG]]                   toggle the state of FLAG on partition NUMBER
  unit UNIT                                set the default unit to UNIT
  version                                  display the version number and copyright information of GNU Parted
(parted)  
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;pv-阶段&quot;&gt;PV 阶段&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;pvcreate ：将实体partition 建立成为 PV ；&lt;/li&gt;
  &lt;li&gt;pvscan ：搜寻目前系统里面任何具有 PV 的磁盘；&lt;/li&gt;
  &lt;li&gt;pvdisplay ：显示出目前系统上面的 PV 状态；&lt;/li&gt;
  &lt;li&gt;pvremove ：将 PV 属性移除，让该partition 不具有PV 属性。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;vg-阶段&quot;&gt;VG 阶段&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;vgcreate ：就是主要建立 VG 的指令；&lt;/li&gt;
  &lt;li&gt;vgscan ：搜寻系统上面是否有 VG 存在；&lt;/li&gt;
  &lt;li&gt;vgdisplay ：显示目前系统上面的 VG 状态；&lt;/li&gt;
  &lt;li&gt;vgextend ：在 VG 内增加额外的 PV ；&lt;/li&gt;
  &lt;li&gt;vgreduce ：在 VG 内移除 PV ；&lt;/li&gt;
  &lt;li&gt;vgchange ：设定 VG 是否启动(active)；&lt;/li&gt;
  &lt;li&gt;vgremove ：删除一个 VG 。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;lv-阶段&quot;&gt;LV 阶段&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;lvcreate ：建立 LV ；&lt;/li&gt;
  &lt;li&gt;lvscan ：查询系统上面的 LV ；&lt;/li&gt;
  &lt;li&gt;lvdisplay ：显示系统上面的 LV 状态；&lt;/li&gt;
  &lt;li&gt;lvextend ：在 LV 里面增加容量；&lt;/li&gt;
  &lt;li&gt;lvreduce ：在 LV 里面减少容量；&lt;/li&gt;
  &lt;li&gt;lvremove ：删除一个 LV ；&lt;/li&gt;
  &lt;li&gt;lvresize ：对 LV 进行容量大小的调整。&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;lvm-实操流程&quot;&gt;LVM 实操流程&lt;/h2&gt;

&lt;p&gt;在这里我们就用 RHel 8 RH134 的题目来演练一下如何调整逻辑卷大小以及创建逻辑卷。&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;十六、调整逻辑卷大小
1）预先创建 2GiB 的分区/dev/vdb1，并用于创建卷组 testvg
2）创建大小为 200MiB 的逻辑卷/dev/testvg/vo，格式化为 xfs 文件系统，并挂载在/mnt/vo 上
3）将逻辑卷/dev/testvg/vo 及其文件系统大小调整到 300MiB，确保文件系统内容保持不变。


[student@node2 ~]# fdisk /dev/vdb
Welcome to fdisk (util-linux 2.32.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0xae75bf0a.
Command (m for help): n
Partition type
p primary (0 primary, 0 extended, 4 free)
e extended (container for logical partitions)
Select (default p):
Using default response p.
Partition number (1-4, default 1):
First sector (2048-10485759, default 2048):
Last sector, +sectors or +size{K,M,G,T,P} (2048-10485759,default 10485759): +2G
Created a new partition 1 of type &apos;Linux&apos; and of size 2 GiB.
Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
[student@node2 ~]# pvcreate /dev/vdb1
[student@node2 ~]# vgcreate testvg /dev/vdb1
[student@node2 ~]# lvcreate -L 200M -n vo testvg
[student@node2 ~]# mkfs.xfs /dev/testvg/vo
[student@node2 ~]# mkdir /mnt/vo
[student@node2 ~]# vim /etc/fstab
/dev/testvg/vo /mnt/vo xfs defaults 0 0
[student@node2 ~]# mount -a
[student@node2 ~]# df -hT /dev/testvg/vo # 查看文件系统的类型
和大小
Filesystem Type Size Used Avail Use% Mounted on
/dev/mapper/testvg-vo xfs 195M 12M 183M 6% /mnt/vo
[student@node2 ~]# lvextend -L 300M /dev/testvg/vo
[student@node2 ~]# lvs
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync
Convert
vo testvg -wi-ao---- 300.00m
# 扩展文件系统，ext 类型的文件系统用 resize2fs /dev/testvg/vo，后面接的是逻辑卷的路径。
[student@node2 ~]# xfs_growfs /mnt/vo # 后面接的是挂载点的路径
[student@node2 ~]# df -hT /dev/testvg/vo
Filesystem Type Size Used Avail Use% Mounted on
/dev/mapper/testvg-vo xfs 295M 13M 283M 5% /mnt/vo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;十八、创建逻辑卷
根据以下要求，创建新的逻辑卷：
1）逻辑卷的名字为 mylv，属于 myvg 卷组，大小为 50 个 pe
2）卷组 myvg 中的逻辑卷的 pe 大小应当为 16MiB
3）使用 vfat 文件系统将逻辑卷 mylv 格式化
4）此逻辑卷应当在系统启动时自动挂载到/mnt/mydata 目录下

[student@node2 ~]# fdisk /dev/vdb
Welcome to fdisk (util-linux 2.32.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Command (m for help): n
Partition type
p primary (2 primary, 0 extended, 2 free)
e extended (container for logical partitions)
Select (default p):
Using default response p.
Partition number (3,4, default 3):
First sector (5244928-10485759, default 5244928):
Last sector, +sectors or +size{K,M,G,T,P} (5244928-10485759,default 10485759):
+1G
Created a new partition 3 of type &apos;Linux&apos; and of size 1 GiB.
Command (m for help): w
The partition table has been altered.
Syncing disks.
[student@node2 ~]# pvcreate /dev/vdb3
[student@node2 ~]# vgcreate -s 16M myvg /dev/vdb3
[student@node2 ~]# lvcreate -l 50 -n mylv myvg
[student@node2 ~]# mkfs.vfat /dev/myvg/mylv
[student@node2 ~]# mkdir /mnt/mydata
[student@node2 ~]# vim /etc/fstab
/dev/myvg/mylv /mnt/mydata vfat defaults 0 0
[student@node2 ~]# mount -a
[student@node2 ~]# df -h /mnt/mydata/
Filesystem Size Used Avail Use% Mounted on
/dev/myvg/mylv 799M 4.0K 799M 1% /mnt/mydata
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>【运维实践】HTTP状态码</title>
   <link href="https://icing.fun/posts/http_status_code.html"/>
   <updated>2021-04-16T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/http_status_code</id>
   <content type="html">&lt;p&gt;当浏览者访问一个网页时，浏览者的浏览器会向网页所在服务器发出请求。当浏览器接收并显示网页前，此网页所在的服务器会返回一个包含HTTP状态码的信息头（server header）用以响应浏览器的请求。&lt;/p&gt;

&lt;p&gt;HTTP状态码的英文为HTTP Status Code。&lt;/p&gt;
&lt;p&gt;下面是常见的HTTP状态码：&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;200 - 请求成功&lt;/li&gt;
	&lt;li&gt;301 - 资源（网页等）被永久转移到其它URL&lt;/li&gt;
	&lt;li&gt;404 - 请求的资源（网页等）不存在&lt;/li&gt;
	&lt;li&gt;500 - 内部服务器错误&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;HTTP状态码分类&lt;/h2&gt;

&lt;p&gt;HTTP状态码由三个十进制数字组成，第一个十进制数字定义了状态码的类型，后两个数字没有分类的作用。HTTP状态码共分为5种类型：&lt;/p&gt;
&lt;table class=&quot;reference&quot;&gt;&lt;caption&gt;HTTP状态码分类&lt;/caption&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;分类&lt;/th&gt;
&lt;th&gt;分类描述&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1**&lt;/td&gt;
&lt;td&gt;信息，服务器收到请求，需要请求者继续执行操作&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2**&lt;/td&gt;
&lt;td&gt;成功，操作被成功接收并处理&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3**&lt;/td&gt;
&lt;td&gt;重定向，需要进一步的操作以完成请求&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4**&lt;/td&gt;
&lt;td&gt;客户端错误，请求包含语法错误或无法完成请求&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5**&lt;/td&gt;
&lt;td&gt;服务器错误，服务器在处理请求的过程中发生了错误&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;HTTP状态码列表:&lt;/p&gt;
&lt;table class=&quot;reference&quot;&gt;&lt;caption&gt;HTTP状态码列表&lt;/caption&gt;
&lt;tbody&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;tr&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;Continue&lt;/td&gt;
&lt;td&gt;继续。客户端应继续其请求&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;101&lt;/td&gt;
&lt;td&gt;Switching Protocols&lt;/td&gt;
&lt;td&gt;切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议，例如，切换到HTTP的新版本协议&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan=&quot;3&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;200&lt;/td&gt;
&lt;td&gt;OK&lt;/td&gt;
&lt;td&gt;请求成功。一般用于GET与POST请求&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;201&lt;/td&gt;
&lt;td&gt;Created&lt;/td&gt;
&lt;td&gt;已创建。成功请求并创建了新的资源&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;202&lt;/td&gt;
&lt;td&gt;Accepted&lt;/td&gt;
&lt;td&gt;已接受。已经接受请求，但未处理完成&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;203&lt;/td&gt;
&lt;td&gt;Non-Authoritative Information&lt;/td&gt;
&lt;td&gt;非授权信息。请求成功。但返回的meta信息不在原始的服务器，而是一个副本&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;204&lt;/td&gt;
&lt;td&gt;No Content&lt;/td&gt;
&lt;td&gt;无内容。服务器成功处理，但未返回内容。在未更新网页的情况下，可确保浏览器继续显示当前文档&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;205&lt;/td&gt;
&lt;td&gt;Reset Content&lt;/td&gt;
&lt;td&gt;重置内容。服务器处理成功，用户终端（例如：浏览器）应重置文档视图。可通过此返回码清除浏览器的表单域&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;206&lt;/td&gt;
&lt;td&gt;Partial Content&lt;/td&gt;
&lt;td&gt;部分内容。服务器成功处理了部分GET请求&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan=&quot;3&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;300&lt;/td&gt;
&lt;td&gt;Multiple Choices&lt;/td&gt;
&lt;td&gt;多种选择。请求的资源可包括多个位置，相应可返回一个资源特征与地址的列表用于用户终端（例如：浏览器）选择&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;301&lt;/td&gt;
&lt;td&gt;Moved Permanently&lt;/td&gt;
&lt;td&gt;永久移动。请求的资源已被永久的移动到新URI，返回信息会包括新的URI，浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;302&lt;/td&gt;
&lt;td&gt;Found&lt;/td&gt;
&lt;td&gt;临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;303&lt;/td&gt;
&lt;td&gt;See Other&lt;/td&gt;
&lt;td&gt;查看其它地址。与301类似。使用GET和POST请求查看&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;304&lt;/td&gt;
&lt;td&gt;Not Modified&lt;/td&gt;
&lt;td&gt;未修改。所请求的资源未修改，服务器返回此状态码时，不会返回任何资源。客户端通常会缓存访问过的资源，通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;305&lt;/td&gt;
&lt;td&gt;Use Proxy&lt;/td&gt;
&lt;td&gt;使用代理。所请求的资源必须通过代理访问&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;306&lt;/td&gt;
&lt;td&gt;Unused&lt;/td&gt;
&lt;td&gt;已经被废弃的HTTP状态码&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;307&lt;/td&gt;
&lt;td&gt;Temporary Redirect&lt;/td&gt;
&lt;td&gt;临时重定向。与302类似。使用GET请求重定向&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan=&quot;3&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;400&lt;/td&gt;
&lt;td&gt;Bad Request&lt;/td&gt;
&lt;td&gt;客户端请求的语法错误，服务器无法理解&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;401&lt;/td&gt;
&lt;td&gt;Unauthorized&lt;/td&gt;
&lt;td&gt;请求要求用户的身份认证&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;402&lt;/td&gt;
&lt;td&gt;Payment Required&lt;/td&gt;
&lt;td&gt;保留，将来使用&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;403&lt;/td&gt;
&lt;td&gt;Forbidden&lt;/td&gt;
&lt;td&gt;服务器理解请求客户端的请求，但是拒绝执行此请求&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;404&lt;/td&gt;
&lt;td&gt;Not Found&lt;/td&gt;
&lt;td&gt;服务器无法根据客户端的请求找到资源（网页）。通过此代码，网站设计人员可设置&quot;您所请求的资源无法找到&quot;的个性页面&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;405&lt;/td&gt;
&lt;td&gt;Method Not Allowed&lt;/td&gt;
&lt;td&gt;客户端请求中的方法被禁止&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;406&lt;/td&gt;
&lt;td&gt;Not Acceptable&lt;/td&gt;
&lt;td&gt;服务器无法根据客户端请求的内容特性完成请求&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;407&lt;/td&gt;
&lt;td&gt;Proxy Authentication Required&lt;/td&gt;
&lt;td&gt;请求要求代理的身份认证，与401类似，但请求者应当使用代理进行授权&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;408&lt;/td&gt;
&lt;td&gt;Request Time-out&lt;/td&gt;
&lt;td&gt;服务器等待客户端发送的请求时间过长，超时&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;409&lt;/td&gt;
&lt;td&gt;Conflict&lt;/td&gt;
&lt;td&gt;服务器完成客户端的 PUT 请求时可能返回此代码，服务器处理请求时发生了冲突&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;410&lt;/td&gt;
&lt;td&gt;Gone&lt;/td&gt;
&lt;td&gt;客户端请求的资源已经不存在。410不同于404，如果资源以前有现在被永久删除了可使用410代码，网站设计人员可通过301代码指定资源的新位置&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;411&lt;/td&gt;
&lt;td&gt;Length Required&lt;/td&gt;
&lt;td&gt;服务器无法处理客户端发送的不带Content-Length的请求信息&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;412&lt;/td&gt;
&lt;td&gt;Precondition Failed&lt;/td&gt;
&lt;td&gt;客户端请求信息的先决条件错误&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;413&lt;/td&gt;
&lt;td&gt;Request Entity Too Large&lt;/td&gt;
&lt;td&gt;由于请求的实体过大，服务器无法处理，因此拒绝请求。为防止客户端的连续请求，服务器可能会关闭连接。如果只是服务器暂时无法处理，则会包含一个Retry-After的响应信息&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;414&lt;/td&gt;
&lt;td&gt;Request-URI Too Large&lt;/td&gt;
&lt;td&gt;请求的URI过长（URI通常为网址），服务器无法处理&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;415&lt;/td&gt;
&lt;td&gt;Unsupported Media Type&lt;/td&gt;
&lt;td&gt;服务器无法处理请求附带的媒体格式&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;416&lt;/td&gt;
&lt;td&gt;Requested range not satisfiable&lt;/td&gt;
&lt;td&gt;客户端请求的范围无效&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;417&lt;/td&gt;
&lt;td&gt;Expectation Failed&lt;/td&gt;
&lt;td&gt;服务器无法满足Expect的请求头信息&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan=&quot;3&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;500&lt;/td&gt;
&lt;td&gt;Internal Server Error&lt;/td&gt;
&lt;td&gt;服务器内部错误，无法完成请求&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;501&lt;/td&gt;
&lt;td&gt;Not Implemented&lt;/td&gt;
&lt;td&gt;服务器不支持请求的功能，无法完成请求&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;502&lt;/td&gt;
&lt;td&gt;Bad Gateway&lt;/td&gt;
&lt;td&gt;作为网关或者代理工作的服务器尝试执行请求时，从远程服务器接收到了一个无效的响应&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;503&lt;/td&gt;
&lt;td&gt;Service Unavailable&lt;/td&gt;
&lt;td&gt;由于超载或系统维护，服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;504&lt;/td&gt;
&lt;td&gt;Gateway Time-out&lt;/td&gt;
&lt;td&gt;充当网关或代理的服务器，未及时从远端服务器获取请求&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;505&lt;/td&gt;
&lt;td&gt;HTTP Version not supported&lt;/td&gt;
&lt;td&gt;服务器不支持请求的HTTP协议的版本，无法完成处理&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
</content>
 </entry>
 
 <entry>
   <title>【Blog Build】Plan of Jekyll Blog - Episode 2: Ruby-3, Jekyll-4, Git, Ubuntu and Nginx</title>
   <link href="https://icing.fun/posts/jekyll_blog_tutorial_02.html"/>
   <updated>2021-02-19T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/jekyll_blog_tutorial_02</id>
   <content type="html">&lt;p&gt;This tutorial you will learn how to configure Jekyll-4 on Ubuntu 16.04/18.04.&lt;/p&gt;

&lt;h1 id=&quot;catalogue&quot;&gt;Catalogue&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#1&quot;&gt;Jekyll-4 Installation Ubuntu 16.04&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#2&quot;&gt;Nginx Setup&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#3&quot;&gt;GitHub Local Repository Setup&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#4&quot;&gt;Git roll back to some commit&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#5&quot;&gt;Jekyll Maintaining Tutorial&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#6&quot;&gt;Jekyll Code Block for Liquid-Like&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#7&quot;&gt;Finally…&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#8&quot;&gt;My Second Jekyll Blog&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#9&quot;&gt;Git Dual Repository Setup&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is the blog repository: &lt;a href=&quot;https://github.com/IcingTomato/blog.old&quot;&gt;blog.old&lt;/a&gt;/&lt;a href=&quot;https://github.com/IcingTomato/blog.old3&quot;&gt;blog.old3&lt;/a&gt;&lt;/p&gt;

&lt;h1 id=&quot;jekyll-4-installation-ubuntu-1604&quot;&gt;&lt;span id=&quot;1&quot;&gt;Jekyll-4 Installation Ubuntu 16.04&lt;/span&gt;&lt;/h1&gt;

&lt;p&gt;First, we should install Ruby3.0.0 for Ubuntu 16.04/18.04:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;ruby-full build-essential zlib1g-dev nginx
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;gcc g++ make
curl &lt;span class=&quot;nt&quot;&gt;-sL&lt;/span&gt; https://dl.yarnpkg.com/debian/pubkey.gpg | &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-key add -
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;deb https://dl.yarnpkg.com/debian/ stable main&quot;&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;sudo tee&lt;/span&gt; /etc/apt/sources.list.d/yarn.list
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get update &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;yarn
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;curl
curl &lt;span class=&quot;nt&quot;&gt;-sL&lt;/span&gt; https://deb.nodesource.com/setup_12.x | &lt;span class=&quot;nb&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-E&lt;/span&gt; bash -
curl &lt;span class=&quot;nt&quot;&gt;-sS&lt;/span&gt; https://dl.yarnpkg.com/debian/pubkey.gpg | &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-key add -
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;deb https://dl.yarnpkg.com/debian/ stable main&quot;&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;sudo tee&lt;/span&gt; /etc/apt/sources.list.d/yarn.list

&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get update
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;git-core zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev software-properties-common libffi-dev nodejs yarn
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then, we can use &lt;strong&gt;one of these methods&lt;/strong&gt; to install Ruby-3:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rbenv&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; ~
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;export PATH=&quot;$HOME/.rbenv/bin:$PATH&quot;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;eval &quot;$(rbenv init -)&quot;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
&lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$SHELL&lt;/span&gt;

git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;export PATH=&quot;$HOME/.rbenv/plugins/ruby-build/bin:$PATH&quot;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
&lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$SHELL&lt;/span&gt;

rbenv &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;3.0.0
rbenv global 3.0.0
ruby &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RVM&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;libgdbm-dev libncurses5-dev automake libtool bison libffi-dev
gpg &lt;span class=&quot;nt&quot;&gt;--keyserver&lt;/span&gt; hkp://keys.gnupg.net &lt;span class=&quot;nt&quot;&gt;--recv-keys&lt;/span&gt; 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
curl &lt;span class=&quot;nt&quot;&gt;-sSL&lt;/span&gt; https://get.rvm.io | bash &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; stable
&lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; ~/.rvm/scripts/rvm
rvm &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;3.0.0
rvm use 3.0.0 &lt;span class=&quot;nt&quot;&gt;--default&lt;/span&gt;
ruby &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ol&gt;
  &lt;li&gt;Ruby Source Codes Installation&lt;/li&gt;
&lt;/ol&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd
&lt;/span&gt;wget http://ftp.ruby-lang.org/pub/ruby/3.0/ruby-3.0.0.tar.gz
&lt;span class=&quot;nb&quot;&gt;tar&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-xzvf&lt;/span&gt; ruby-3.0.0.tar.gz
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;ruby-3.0.0/
./configure
make
&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;make &lt;span class=&quot;nb&quot;&gt;install
&lt;/span&gt;ruby &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Caution: &lt;/strong&gt;In some area, it’s difficult to visit RubyGems, so you might be change a Ruby Source.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gem &lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt; https://rubygems.org/
gem &lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--add&lt;/span&gt; https://gems.ruby-china.com/
gem &lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Finally, install &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Bundler&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gem &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;bundler jekyll github-pages jekyll-paginate webrick
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After installation, you can clone your repository from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GitHub&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GitLab&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone https://github.com/IcingTomato/blog.old.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;nginx-setup&quot;&gt;&lt;span id=&quot;2&quot;&gt;Nginx Setup&lt;/span&gt;&lt;/h1&gt;

&lt;p&gt;Well, you can also use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Apache&lt;/code&gt; which use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo apt-get install apache2&lt;/code&gt; on Debian/Ubuntu or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo yum install httpd&lt;/code&gt; on CentOS/RHEL/Fedora.&lt;/p&gt;

&lt;p&gt;First, install Nginx:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get isntall nginx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then, configure nginx profile:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@blog:~# &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;nano /etc/nginx/sites-enabled/default

server &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        listen 80 default_server&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        listen &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;::]:80 default_server&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;c&quot;&gt;# SSL configuration&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;#&lt;/span&gt;
        listen 443 ssl default_server&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        listen &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;::]:443 ssl default_server&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;c&quot;&gt;# Disable SSL, because when it enabled, it blocked 80.&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;#ssl on;&lt;/span&gt;
        ssl_certificate path/to/your_key.pem&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        ssl_certificate_key path/to/your_key.key&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        ssl_session_timeout 5m&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        ssl_prefer_server_ciphers on&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        root /var/www/html&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;c&quot;&gt;# Add index.php to the list if you are using PHP&lt;/span&gt;
        index index.html&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        server_name your.domain&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        location / &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;c&quot;&gt;# First attempt to serve request as file, then&lt;/span&gt;
                &lt;span class=&quot;c&quot;&gt;# as directory, then fall back to displaying a 404.&lt;/span&gt;
                try_files &lt;span class=&quot;nv&quot;&gt;$uri&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$uri&lt;/span&gt;/ &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;404&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;


        &lt;span class=&quot;c&quot;&gt;# Rewrited the 404 page to 200&lt;/span&gt;
        error_page 404 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;200 /404.html&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        location /404.html &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
                root /var/www/html/&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                internal&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;        

        &lt;span class=&quot;c&quot;&gt;# Rewrited the 403 page to 200&lt;/span&gt;
        error_page 403 &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;200 /403.html&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

        location /403.html &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
                root /var/www/html/&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                internal&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl+O&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl+X&lt;/code&gt; to save and exit.&lt;/p&gt;

&lt;p&gt;Finally, restart &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx.service&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl restart nginx

&lt;span class=&quot;c&quot;&gt;# On AWS, you must use systemctl to start, stop, enable, disable, restart a service.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;github-local-repository-setup&quot;&gt;&lt;span id=&quot;3&quot;&gt;GitHub Local Repository Setup&lt;/span&gt;&lt;/h1&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git init
git add README.md
git commit &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;first commit&quot;&lt;/span&gt;
git branch &lt;span class=&quot;nt&quot;&gt;-M&lt;/span&gt; master
git remote add origin repo_address
git push &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; origin master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;git-roll-back-to-some-commit&quot;&gt;&lt;span id=&quot;4&quot;&gt;Git roll back to some commit&lt;/span&gt;&lt;/h1&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git reset &lt;span class=&quot;nt&quot;&gt;--hard&lt;/span&gt; 某个commit &lt;span class=&quot;nb&quot;&gt;id
&lt;/span&gt;git push &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-u&lt;/span&gt; origin master
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;jekyll-maintaining-tutorial&quot;&gt;&lt;span id=&quot;5&quot;&gt;Jekyll Maintaining Tutorial&lt;/span&gt;&lt;/h1&gt;

&lt;p&gt;You can make a quick start for surfing the Jekyll blog:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone &lt;span class=&quot;nt&quot;&gt;-b&lt;/span&gt; blank https://github.com/IcingTomato/blog.old.git
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;blog.old
jekyll serve &lt;span class=&quot;c&quot;&gt;# jekyll s&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;# =&amp;gt; Now browse to http://localhost:4000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/02/19/quick_start.jpg&quot; alt=&quot;quick_start&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;setup-_configyml&quot;&gt;Setup &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_config.yml&lt;/code&gt;&lt;/h2&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Site settings&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Your Blog&lt;/span&gt;                        &lt;span class=&quot;c1&quot;&gt;# Your blog title&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;SEOTitle&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Jekyll | Ruby&lt;/span&gt;                 &lt;span class=&quot;c1&quot;&gt;# SEO title&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Hello&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;from&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Seattle&quot;&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;	&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# Your blog description&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# SNS settings      &lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;github_username&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;John Doe&lt;/span&gt;               &lt;span class=&quot;c1&quot;&gt;# GitHub account&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;RSS&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;                               &lt;span class=&quot;c1&quot;&gt;# RSS On&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;weibo_username&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;                         &lt;span class=&quot;c1&quot;&gt;# Weibo  &lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;zhihu_username&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;                         &lt;span class=&quot;c1&quot;&gt;# Zhihu&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;facebook_username&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;                      &lt;span class=&quot;c1&quot;&gt;# Facebook&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;bilibili_username&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;                      &lt;span class=&quot;c1&quot;&gt;# Bilibili  &lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;twitter_username&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;                       &lt;span class=&quot;c1&quot;&gt;# Twitter&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Build settings&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;paginate&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;100&lt;/span&gt;                          &lt;span class=&quot;c1&quot;&gt;# Contents in a page&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can visit &lt;a href=&quot;https://jekyllrb.com/docs/&quot;&gt;Jekyll-Docs&lt;/a&gt;/&lt;a href=&quot;http://jekyllcn.com/docs/home/&quot;&gt;Jekyll中文网-文档&lt;/a&gt; for more support.&lt;/p&gt;

&lt;h3 id=&quot;sidebar&quot;&gt;Sidebar&lt;/h3&gt;

&lt;p&gt;On PCs, tablet devices or ultra-wide scale screen there is a sidebar to display your personal profile.&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Sidebar settings&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;sidebar&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;                                           &lt;span class=&quot;c1&quot;&gt;# Add Sidebar&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;sidebar-about-description&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;describe&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;yourself&quot;&lt;/span&gt;          &lt;span class=&quot;c1&quot;&gt;# Description&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;sidebar-avatar&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;/img/avatar.jpg&lt;/span&gt;                         &lt;span class=&quot;c1&quot;&gt;# Your Avatar&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Sidebar&lt;/strong&gt; is a Responsive Layout*, when the display size is below 992px, the sidebar will move to the page bottom. You can visit &lt;a href=&quot;https://getbootstrap.com/docs/3.4/css/&quot;&gt;Bootstrap3 for global CSS settings&lt;/a&gt;/&lt;a href=&quot;https://v3.bootcss.com/css/&quot;&gt;Bootstrap 设置全局 CSS 样式&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;mini-about-me&quot;&gt;Mini About Me&lt;/h3&gt;

&lt;p&gt;This module is under your avatar. It will display all your social media account. It is also a Responsive Layout. When the screen size become small, it will move to the bottom of the page. But there is a litte change when it move to the bottom.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/02/19/mini_about_me.jpg&quot; alt=&quot;mini_about_me&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/02/19/mini_about_me_bottom.jpg&quot; alt=&quot;mini_about_me_bottom&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;featured-tags&quot;&gt;Featured Tags&lt;/h3&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Featured Tags&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;featured-tags&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;  
&lt;span class=&quot;na&quot;&gt;featured-condition-size&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;15&lt;/span&gt;     
&lt;span class=&quot;c1&quot;&gt;# A tag will be featured if the size of it is more than this condition value&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;featured-condition-size&lt;/code&gt; means if the tags’ count over 15(or the number you set), it will display on home page.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/02/19/tags.jpg&quot; alt=&quot;tags&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;friends&quot;&gt;Friends&lt;/h3&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Friends&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;friends&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;[&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;John&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Doe&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;http://john.doe/&quot;&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;},{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;村財　師内&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;https://sonzai.shinai/&quot;&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;},{&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;鵜祖田　陽&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nv&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;https://usoda.you/&quot;&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;pi&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;comment&quot;&gt;Comment&lt;/h3&gt;

&lt;p&gt;This Jekyll Blog supports both &lt;a href=&quot;http://disqus.com/&quot;&gt;Disqus&lt;/a&gt; and &lt;a href=&quot;https://gitalk.github.io/&quot;&gt;Gitalk&lt;/a&gt;, it also supports Markdown Grammar.&lt;/p&gt;

&lt;h4 id=&quot;disqus&quot;&gt;Disqus&lt;/h4&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Disqus（https://disqus.com/）&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;disqus_username&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;gitalk&quot;&gt;Gitalk&lt;/h4&gt;

&lt;p&gt;First, we should create a new repository for saving our comments:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/02/19/gitalk_repo_create.jpg&quot; alt=&quot;gitalk_repo_create&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/02/19/gitalk_repo_setup.jpg&quot; alt=&quot;gitalk_repo_setup&quot; /&gt;&lt;/p&gt;

&lt;p&gt;And then open &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Issues&lt;/code&gt; option:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/02/19/open_issues.jpg&quot; alt=&quot;open_issues&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Besides, register a new OAuth application:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/02/19/oauth_setup.jpg&quot; alt=&quot;oauth_setup&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/02/19/oauth_id.jpg&quot; alt=&quot;oauth_id&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;google-analytics&quot;&gt;Google Analytics&lt;/h3&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Google Analytics&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;ga_track_id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;UA-&apos;&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;ga_domain&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;         &lt;span class=&quot;c1&quot;&gt;# Default as &apos;auto&apos;, you can use your domain&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/02/19/google_analytics.jpg&quot; alt=&quot;google_analytics&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;write-your-first-blog&quot;&gt;Write your first blog&lt;/h2&gt;

&lt;p&gt;We must put the article, which named as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;YYYY-MM-DD-your_first_article.markdown&lt;/code&gt;, in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_post&lt;/code&gt; folder. And you can change parameter in the front of the article:&lt;/p&gt;

&lt;div class=&quot;language-yml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;     &lt;span class=&quot;s&quot;&gt;post&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;      &lt;span class=&quot;s&quot;&gt;Your First Blog&lt;/span&gt; 
&lt;span class=&quot;na&quot;&gt;subtitle&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;   &lt;span class=&quot;s&quot;&gt;Jekyll is Хорошо&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;date&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;       &lt;span class=&quot;s&quot;&gt;1900-01-01&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;     &lt;span class=&quot;s&quot;&gt;John Doe&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;header-img&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;img/title.jpg&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;catalog&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;tags&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Jekyll&lt;/span&gt;
&lt;span class=&quot;nn&quot;&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;jekyll-code-block-for-liquid-like&quot;&gt;&lt;span id=&quot;6&quot;&gt;Jekyll Code Block for Liquid-Like&lt;/span&gt;&lt;/h1&gt;

&lt;p&gt;In Jekyll, some Ruby code block can’t generate perfectly.&lt;/p&gt;

&lt;p&gt;So, we can use &lt;a href=&quot;https://shopify.github.io/liquid/tags/template/&quot;&gt;raw tag&lt;/a&gt; to avoid execute liquid or liquid-like code block:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{% raw %}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You can use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;{% highlight ruby %}{% endhighlight %}&lt;/code&gt; for code highlight.&lt;/p&gt;

&lt;h1 id=&quot;finally&quot;&gt;&lt;span id=&quot;7&quot;&gt;Finally…&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h1&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;your.folder
git clone repo.address
git pull origin master
jekyll build &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; /var/www/html/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;my-second-jekyll-blog&quot;&gt;&lt;span id=&quot;8&quot;&gt;My Second Jekyll Blog&lt;/span&gt;&lt;/h1&gt;

&lt;p&gt;Here is the blog repository: &lt;a href=&quot;https://github.com/IcingTomato/blog.old2&quot;&gt;blog.old2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can use these command line for configuring the blog:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &amp;lt;the folder&amp;gt;
git clone https://github.com/IcingTomato/blog.old2.git
bundle add webrick rake
bundle &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--path&lt;/span&gt; vendor/cache
git pull origin master
bundle &lt;span class=&quot;nb&quot;&gt;exec &lt;/span&gt;jekyll build &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; /var/www/html/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;First, you need to install some Dependence like &lt;strong&gt;webrick&lt;/strong&gt; &lt;strong&gt;rake&lt;/strong&gt; &lt;strong&gt;jekyll&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And then, in my case, I had a PATH problem.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Bundler::GemNotFound: Could not find rake-10.3.2 in any of the sources
~/.rvm/gems/ruby-2.0.0-p451/gems/bundler-1.6.2/lib/bundler/spec_set.rb:92:in `block in materialize&apos;
~/.rvm/gems/ruby-2.0.0-p451/gems/bundler-1.6.2/lib/bundler/spec_set.rb:85:in `map!&apos;
~/.rvm/gems/ruby-2.0.0-p451/gems/bundler-1.6.2/lib/bundler/spec_set.rb:85:in `materialize&apos;
~/.rvm/gems/ruby-2.0.0-p451/gems/bundler-1.6.2/lib/bundler/definition.rb:133:in `specs&apos;
~/.rvm/gems/ruby-2.0.0-p451/gems/bundler-1.6.2/lib/bundler/definition.rb:178:in `specs_for&apos;
Show 28 more lines
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I used &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gem install rake&lt;/code&gt; but it was no use fixing the matter.&lt;/p&gt;

&lt;p&gt;SO, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bundle install --path vendor/cache&lt;/code&gt; can help you fix the problem.&lt;/p&gt;

&lt;p&gt;This command line generally fixes it as that is the more common problem. Basically, my bundler path configuration is messed up. See their &lt;a href=&quot;https://bundler.io/v1.11/man/bundle-config.1.html&quot;&gt;documentation&lt;/a&gt; (first paragraph) for where to find those configurations and change them manually if needed.&lt;/p&gt;

&lt;h1 id=&quot;git-dual-repository-setup&quot;&gt;&lt;span id=&quot;9&quot;&gt;Git Dual Repository Setup&lt;/span&gt;&lt;/h1&gt;

&lt;p&gt;Everytime I finish my blog, I have to push to two different platform: &lt;a href=&quot;https://github.com/&quot;&gt;GitHub&lt;/a&gt; and &lt;a href=&quot;https://gitee.com/&quot;&gt;Gitee&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://gitee.com/&quot;&gt;Gitee&lt;/a&gt; is a collaboration platform for software development &amp;amp; code hosting in China Mainland.&lt;/p&gt;

&lt;p&gt;Because I use Ali ECS Area Hangzhou, it’s hard to visit GitHub, so I have to use Gitee.&lt;/p&gt;

&lt;p&gt;So&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;your-repository-path&apos;&lt;/span&gt;
git remote add gitee &lt;span class=&quot;s1&quot;&gt;&apos;your-gitee-repository-address&apos;&lt;/span&gt;
git push gitee master    &lt;span class=&quot;c&quot;&gt;# Push to &apos;gitee&apos;&lt;/span&gt;
git push origin master   &lt;span class=&quot;c&quot;&gt;# Push to &apos;github&apos; &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can also change &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;your-repository/.git/config&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[core]
	repositoryformatversion = 0
	filemode = true
	bare = false
	logallrefupdates = true
[remote &quot;origin&quot;]
	url = &apos;your-github-repository-address&apos;
	fetch = +refs/heads/*:refs/remotes/origin/*
[branch &quot;master&quot;]
	remote = origin
	merge = refs/heads/master
[remote &quot;gitee&quot;]
	url = &apos;your-gitee-repository-address&apos;
	fetch = +refs/heads/*:refs/remotes/gitee/*
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

</content>
 </entry>
 
 <entry>
   <title>【运维实践】网络基础知识</title>
   <link href="https://icing.fun/posts/network_basic.html"/>
   <updated>2021-01-30T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/network_basic</id>
   <content type="html">&lt;p&gt;The foundations of networking: switches, routers, and wireless access points. Switches, routers, and wireless access points are the essential networking basics. Through them, devices connected to your network can communicate with one another and with other networks, like the Internet.&lt;/p&gt;

&lt;h1 id=&quot;传输介质简介&quot;&gt;传输介质简介&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;可以让设备通过网卡连接互联网的介质，如同轴电缆、双绞线和光纤等。不同的传输介质具有不同的特性，这些特性直接影响到通信的诸多方面，如线路编码方式、传输速度和传输距离等。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;常见的网络传输介质&quot;&gt;常见的网络传输介质&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;同轴电缆（Coaxial Cable）&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/coaxial_cable.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;同轴电缆是一种早期使用的传输介质，同轴电缆的标准分为两种，10BASE2和10BASE5。这两种标准都支持10Mbps的传输速率，最长传输距离分别为185米和500米。一般情况下，10Base2同轴电缆使用BNC接头，10Base5同轴电缆使用N型接头。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;10BASE5和10BASE2是早期的两种以太网标准，它们均采用同轴电缆作为传输介质。10BASE5和10BASE2所使用的同轴电缆的直径分别为9.5mm和5mm，所以前者又称为粗缆，后者又称为细缆。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;现在，10Mbps的传输速率早已不能满足目前企业网络需求，因此同轴电缆在目前企业网络中很少应用。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;双绞线（Twisted Pair）&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/twisted_pair.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;与同轴电缆相比双绞线（Twisted Pair）具有更低的制造和部署成本，因此在企业网络中被广泛应用。双绞线可分为屏蔽双绞线(Shielded Twisted Pair，STP)和非屏蔽双绞线(Unshielded Twisted Pair，UTP)。屏蔽双绞线在双绞线与外层绝缘封套之间有一个金属屏蔽层，可以屏蔽电磁干扰。双绞线有很多种类型，不同类型的双绞线所支持的传输速率一般也不相同。例如，3类双绞线支持10Mbps传输速率；5类双绞线支持100Mbps传输速率；超5类双绞线及更高级别的双绞线支持千兆以太网传输。双绞线使用RJ-45接头连接网络设备。为保证终端能够正确收发数据，RJ-45接头中的针脚必须按照一定的线序排列&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;光纤（Optical Fiber）&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/optical_fiber.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;双绞线和同轴电缆传输数据时使用的是电信号，而光纤传输数据时使用的是光信号。光纤支持的传输速率包括10Mbps，100Mbps，1Gbps，10Gbps，甚至更高。根据光纤传输光信号模式的不同，光纤又可分为单模光纤和多模光纤。单模光纤只能传输一种模式的光，不存在模间色散，因此适用于长距离高速传输。多模光纤允许不同模式的光在一根光纤上传输，由于模间色散较大而导致信号脉冲展宽严重，因此多模光纤主要用于局域网中的短距离传输。光纤连接器种类很多，常用的连接器包括ST，FC，SC，LC连接器。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;串口电缆（Serial Port Cable）&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/serialportcable.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;网络通信中常常会用到各种各样的串口电缆。常用的串口电缆标准为RS-232，同时也是推荐的标准。但是RS-232的传输速率有限，传输距离仅为6米。其他的串口电缆标准可以支持更长的传输距离，例如RS-422和RS-485的传输距离可达1200米。RS-422和RS-485串口电缆通常使用V.35接头，这种接头在上世纪80年代已经淘汰，但是现在仍在帧中继、ATM等传统网络上使用。V.24是RS-232标准的欧洲版。RS-232本身没有定义接头标准，常用的接头类型为DB-9和DB-25。现在，RS-232已逐渐被FireWire、USB等新标准取代，新产品和新设备已普遍使用USB标准。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;什么是网络&quot;&gt;什么是「网络」&lt;/h3&gt;

&lt;blockquote&gt;
  &lt;p&gt;网络是由若干节点和连接这些节点的链路构成，表示诸多对象及其相互联系。网络是信息传输、接收、共享的虚拟平台，通过它把各个点、面、体的信息联系到一起，从而实现这些资源的共享。网络是人类发展史来最重要的发明，提高了科技和人类社会的发展。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;网络设备有什么&quot;&gt;网络设备有什么&lt;/h3&gt;

&lt;p&gt;电脑、手机、iPad、凡是能联网的设备、提供服务的设备、路由器、交换机、防火墙、无线设备……&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;网卡是上网必备的工具&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;简单网络&quot;&gt;简单网络&lt;/h3&gt;

&lt;p&gt;两个终端，用一条能承载数据传输的物理介质（也称为传输介质）连接起来，就组成了一个最简单的网络。&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/simplenetwork.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;网络划分为&quot;&gt;网络划分为&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;有线网络&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;无线网络&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;双绞线的线序&quot;&gt;双绞线的线序&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;T-568A&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;白绿 绿 白橙 蓝 白蓝 橙 白棕 棕
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;T-568B&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;白橙 橙 白绿 蓝 白蓝 绿 白棕 棕
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;根据网线两端的线序可分为&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;直通线：两端线序是一样的&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;交叉线：两端线序是相反的&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;冲突域collision-domain&quot;&gt;冲突域（Collision Domain）&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/CollisionDomain.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;共享式网络中可能会出现信号冲突现象。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;如图是一个10BASE5以太网，每个主机都是用同一根同轴电缆来与其它主机进行通信，因此，这里的同轴电缆又被称为共享介质，相应的网络被称为共享介质网络，或简称为共享式网络。共享式网络中，不同的主机同时发送数据时，就会产生信号冲突的问题，解决这一问题的方法一般是采用载波侦听多路访问/冲突检测技术（Carrier Sense Multiple Access/Collision Detection）。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;CSMA/CD的基本工作过程如下：&lt;/p&gt;
  &lt;blockquote&gt;
    &lt;p&gt;终端设备不停地检测共享线路的状态。如果线路空闲，则可以发送数据；如果线路不空闲，则等待一段时间后继续检测（延时时间由退避算法决定）。&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;blockquote&gt;
    &lt;p&gt;如果有另外一个设备同时发送数据，两个设备发送的数据会产生冲突。&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;blockquote&gt;
    &lt;p&gt;终端设备检测到冲突之后，会马上停止发送自己的数据，并发送特殊阻塞信息，以强化冲突信号，使线路上其他站点能够尽早检测到冲突。&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;blockquote&gt;
    &lt;p&gt;终端设备检测到冲突后，等待一段时间之后再进行数据发送（延时时间由退避算法决定）。&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;blockquote&gt;
    &lt;p&gt;CSMA/CD的工作原理可简单总结为：先听后发，边发边听，冲突停发，随机延迟后重发。&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;双工模式duplex&quot;&gt;双工模式（Duplex）&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/Duplex.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;两种双工模式都支持双向数据传输。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;半双工：在半双工模式（half-duplex mode）下，通信双方都能发送和接收数据，但不能同时进行。当一台设备发送时，另一台只能接收，反之亦然。对讲机是半双工的典型例子。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;全双工：在全双工模式（full-duplex mode）下，通信双方都能同时接收和发送数据。电话网络是典型的全双工例子。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;以太网上的通信模式包括半双工和全双工两种：&lt;/p&gt;
  &lt;blockquote&gt;
    &lt;p&gt;半双工模式下，共享物理介质的通信双方必须采用CSMA/CD机制来避免冲突。例如，10BASE5以太网的通信模式就必须是半双工模式。
全双工模式下，通信双方可以同时实现双向通信，这种模式不会产生冲突，因此不需要使用CSMA/CD机制。例如，10BASE-T以太网的通信模式就可以是全双工模式。
同一物理链路上相连的两台设备的双工模式必须保持一致。&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;以太网帧结构&quot;&gt;以太网帧结构&lt;/h1&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/networkframe.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;网络中传输数据时需要定义并遵循一些标准，以太网是根据IEEE 802.3标准来管理和控制数据帧的。&lt;/p&gt;

&lt;h2 id=&quot;网络通信协议&quot;&gt;网络通信协议&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/protocol.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;不同的协议栈用于定义和管理不同网络的数据转发规则。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;20世纪60年代以来，计算机网络得到了飞速发展。各大厂商和标准组织为了在数据通信网络领域占据主导地位，纷纷推出了各自的网络架构体系和标准，如IBM公司的SNA协议，Novell公司的IPX/SPX协议，以及广泛流行的OSI参考模型和TCP/IP协议。同时，各大厂商根据这些协议生产出了不同的硬件和软件。标准组织和厂商的共同努力促进了网络技术的快速发展和网络设备种类的迅速增长。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;网络通信中，“协议”和“标准”这两个词汇常常可以混用。同时，协议或标准本身又常常具有层次的特点。一般地，关注于逻辑数据关系的协议通常被称为上层协议，而关注于物理数据流的协议通常被称为底层协议。IEEE 802就是一套用来管理物理数据流在局域网中传输的标准，包括在局域网中传输物理数据的802.3以太网标准。除以太外，还有一些用来管理物理数据流在广域网中传输的标准，如PPP（Point-to-Point Protocol），高级数据链路控制HDLC（High-Level Data Link Control）。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;分层模型-osi&quot;&gt;分层模型-OSI&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/osi.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;国际标准化组织ISO于1984年提出了OSI RM（Open System Interconnection Reference Model，开放系统互连参考模型）。OSI参考模型很快成为了计算机网络通信的基础模型。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;OSI参考模型具有以下优点：简化了相关的网络操作；提供了不同厂商之间的兼容性；促进了标准化工作；结构上进行了分层；易于学习和操作。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;OSI参考模型各个层次的基本功能如下：&lt;/p&gt;
  &lt;blockquote&gt;
    &lt;p&gt;物理层：在设备之间传输比特流，规定了电平、速度和电缆针脚。&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;blockquote&gt;
    &lt;p&gt;数据链路层：将比特组合成字节，再将字节组合成帧，使用链路层地址（以太网使用MAC地址）来访问介质，并进行差错检测。&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;blockquote&gt;
    &lt;p&gt;网络层：提供逻辑地址，供路由器确定路径。&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;blockquote&gt;
    &lt;p&gt;传输层：提供面向连接或非面向连接的数据传递以及进行重传前的差错检测。&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;blockquote&gt;
    &lt;p&gt;会话层：负责建立、管理和终止表示层实体之间的通信会话。该层的通信由不同设备中的应用程序之间的服务请求和响应组成。&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;blockquote&gt;
    &lt;p&gt;表示层：提供各种用于应用层数据的编码和转换功能，确保一个系统的应用层发送的数据能被另一个系统的应用层识别。&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;blockquote&gt;
    &lt;p&gt;应用层：OSI参考模型中最靠近用户的一层，为应用程序提供网络服务。&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;分层模型-tcpip&quot;&gt;分层模型-TCP/IP&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/tcpip.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;TCP/IP模型同样采用了分层结构，层与层相对独立但是相互之间也具备非常密切的协作关系。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;TCP/IP模型将网络分为四层。TCP/IP模型不关注底层物理介质，主要关注终端之间的逻辑数据流转发。TCP/IP模型的核心是网络层和传输层，网络层解决网络之间的逻辑转发问题，传输层保证源端到目的端之间的可靠传输。最上层的应用层通过各种协议向终端用户提供业务应用。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;数据封装&quot;&gt;数据封装&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/package.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;应用数据需要经过TCP/IP每一层处理之后才能通过网络传输到目的端，每一层上都使用该层的协议数据单元PDU（Protocol Data Unit）彼此交换信息。不同层的PDU中包含有不同的信息，因此PDU在不同层被赋予了不同的名称。如上层数据在传输层添加TCP报头后得到的PDU被称为Segment（数据段）；数据段被传递给网络层，网络层添加IP报头得到的PDU被称为Packet（数据包）；数据包被传递到数据链路层，封装数据链路层报头得到的PDU被称为Frame（数据帧）；最后，帧被转换为比特，通过网络介质传输。这种协议栈逐层向下传递数据，并添加报头和报尾的过程称为封装。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;终端之间的通信&quot;&gt;终端之间的通信&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/communication.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;数据链路层控制数据帧在物理链路上传输。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;数据包在以太网物理介质上传播之前必须封装头部和尾部信息，封装后的数据包称为数据帧，数据帧中封装的信息决定了数据如何传输。以太网上传输的数据帧有两种格式，选择哪种格式由TCP/IP协议簇中的网络层决定。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;帧格式&quot;&gt;帧格式&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/frame.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;以太网上使用两种标准帧格式。第一种是上世纪80年代初提出的DIX v2格式，即Ethernet II帧格式。Ethernet II后来被IEEE 802标准接纳，并写进了IEEE 802.3x-1997的3.2.6节。第二种是1983年提出的IEEE 802.3格式。这两种格式的主要区别在于Ethernet II格式中包含一个Type字段，标识以太帧处理完成之后将被发送到哪个上层协议进行处理，IEEE 802.3格式中，同样的位置是长度字段。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;不同的Type字段值可以用来区别这两种帧的类型，当Type字段值小于等于1500（或者十六进制的0x05DC）时，帧使用的是IEEE 802.3格式。当Type字段值大于等于1536 （或者十六进制的0x0600）时，帧使用的是Ethernet II格式。以太网中大多数的数据帧使用的是Ethernet II格式。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;以太帧中还包括源和目的MAC地址，分别代表发送者的MAC和接收者的MAC，此外还有帧校验序列字段，用于检验传输过程中帧的完整性。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;ethernet_ii帧格式&quot;&gt;Ethernet_II帧格式&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/ethernetii.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Ethernet_II 帧类型值大于等于1536 (0x0600)，以太网数据帧的长度在64-1518字节之间。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ethernet_II的帧中各字段说明如下：&lt;/p&gt;
  &lt;blockquote&gt;
    &lt;p&gt;DMAC（Destination MAC）是目的MAC地址。DMAC字段长度为6个字节，标识帧的接收者。&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;blockquote&gt;
    &lt;p&gt;SMAC（Source MAC）是源MAC地址。SMAC字段长度为6个字节，标识帧的发送者。&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;blockquote&gt;
    &lt;p&gt;类型字段（Type）用于标识数据字段中包含的高层协议，该字段长度为2个字节。类型字段取值为0x0800的帧代表IP协议帧；类型字段取值为0x0806的帧代表ARP协议帧。&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;blockquote&gt;
    &lt;p&gt;数据字段（Data）是网络层数据，最小长度必须为46字节以保证帧长至少为64字节，数据字段的最大长度为1500字节
。
循环冗余校验字段（FCS）提供了一种错误检测机制。该字段长度为4个字节。&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;ieee8023帧格式&quot;&gt;IEEE802.3帧格式&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/ieee8023.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;IEEE802.3帧长度字段值小于等于1500 (0x05DC)。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;IEEE802.3帧格式类似于Ethernet_II帧，只是Ethernet_II帧的Type域被802.3帧的Length域取代，并且占用了Data字段的8个字节作为LLC和SNAP字段。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Length字段定义了Data字段包含的字节数。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;逻辑链路控制LLC（Logical Link Control）由目的服务访问点DSAP（Destination Service Access Point）、源服务访问点SSAP（Source Service Access Point）和Control字段组成。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;SNAP（Sub-network Access Protocol）由机构代码（Org Code）和类型（Type）字段组成。Org Code三个字节都为0。Type字段的含义与Ethernet_II帧中的Type字段相同。IEEE802.3帧根据DSAP和SSAP字段的取值又可分为以下几类：&lt;/p&gt;
  &lt;blockquote&gt;
    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  1）当DSAP和SSAP都取特定值0xff时，802.3帧就变成了Netware-ETHERNET帧，用来承载NetWare类型的数据。
  2）当DSAP和SSAP都取特定值0xaa时，802.3帧就变成了ETHERNET_SNAP帧。ETHERNET_SNAP帧可以用于传输多种协议。
  3）DSAP和SSAP其他的取值均为纯IEEE802.3帧。
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;数据帧传输&quot;&gt;数据帧传输&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/frametrans.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;数据链路层基于MAC地址进行帧的传输。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;以太网在二层链路上通过MAC地址来唯一标识网络设备，并且实现局域网上网络设备之间的通信。MAC地址也叫物理地址，大多数网卡厂商把MAC地址烧入了网卡的ROM中。发送端使用接收端的MAC地址作为目的地址。以太帧封装完成后会通过物理层转换成比特流在物理介质上传输。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;以太网的mac地址&quot;&gt;以太网的MAC地址&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/mac.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;MAC地址由两部分组成，分别是供应商代码和序列号。其中前24位代表该供应商代码，由IEEE管理和分配。剩下的24位序列号由厂商自己分配。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;如同每一个人都有一个名字一样，每一台网络设备都用物理地址来标识自己，这个地址就是MAC地址。网络设备的MAC地址是全球唯一的。MAC地址长度为48比特，通常用十六进制表示。MAC地址包含两部分：前24比特是组织唯一标识符（OUI，Organizationally Unique Identifier），由IEEE统一分配给设备制造商。例如，华为的网络产品的MAC地址前24比特是0x00e0fc。后24位序列号是厂商分配给每个产品的唯一数值，由各个厂商自行分配（这里所说的产品可以是网卡或者其他需要MAC地址的设备）。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;单播unicast&quot;&gt;单播（Unicast）&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/unicast.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;局域网上的帧可以通过三种方式发送。第一种是单播，指从单一的源端发送到单一的目的端。每个主机接口由一个MAC地址唯一标识，MAC地址的OUI中，第一字节第8个比特表示地址类型。对于主机MAC地址，这个比特固定为0，表示目的MAC地址为此MAC地址的帧都是发送到某个唯一的目的端。在冲突域中，所有主机都能收到源主机发送的单播帧，但是其他主机发现目的地址与本地MAC地址不一致后会丢弃收到的帧，只有真正的目的主机才会接收并处理收到的帧。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;广播broadcast&quot;&gt;广播（Broadcast）&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/broadcast.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;第二种发送方式是广播，表示帧从单一的源发送到共享以太网上的所有主机。广播帧的目的MAC地址为十六进制的FF:FF:FF:FF:FF:FF，所有收到该广播帧的主机都要接收并处理这个帧。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;广播方式会产生大量流量，导致带宽利用率降低，进而影响整个网络的性能。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;当需要网络中的所有主机都能接收到相同的信息并进行处理的情况下，通常会使用广播方式。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;组播multicast&quot;&gt;组播（Multicast）&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/multicast.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;第三种发送方式为组播，组播比广播更加高效。组播转发可以理解为选择性的广播，主机侦听特定组播地址，接收并处理目的MAC地址为该组播MAC地址的帧。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;组播MAC地址和单播MAC地址是通过第一字节中的第8个比特区分的。组播MAC地址的第8个比特为1，而单播MAC地址的第8个比特为0。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;当需要网络上的一组主机（而不是全部主机）接收相同信息，并且其他主机不受影响的情况下通常会使用组播方式。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;数据帧的发送和接收&quot;&gt;数据帧的发送和接收&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/frametxrx.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;当主机接收到的数据帧所包含的目的MAC地址是自己时，会把以太网封装剥掉后送往上层协议。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;帧从主机的物理接口发送出来后，通过传输介质传输到目的端。共享网络中，这个帧可能到达多个主机。主机检查帧头中的目的MAC地址，如果目的MAC地址不是本机MAC地址，也不是本机侦听的组播或广播MAC地址，则主机会丢弃收到的帧。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;如果目的MAC地址是本机MAC地址，则接收该帧，检查帧校验序列（FCS）字段，并与本机计算的值对比来确定帧在传输过程中是否保持了完整性。如果帧的FCS值与本机计算的值不同，主机会认为帧已被破坏，并会丢弃该帧。如果该帧通过了FCS校验，则主机会根据帧头部中的Type字段来确定将帧发送给上层哪个协议处理。本例中，Type字段的值为0x0800，表明该帧需要发送到IP协议上处理。在发送给IP协议之前，帧的头部和尾部会被剥掉。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;ip编址&quot;&gt;IP编址&lt;/h1&gt;

&lt;h2 id=&quot;上层协议地址&quot;&gt;上层协议地址&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/ipprotocol.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;以太网帧中的Type字段值为0x0800，表示该帧的网络层协议为IP协议。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;在剥掉帧的头部和尾部之前，网络设备需要根据帧头中Type字段确定下一步将帧发送到哪个上层协议进行处理。本例中的帧头部Type字段表示该帧需要上送到IP协议进行处理。以下将介绍帧的头部和尾部被剥掉后，IP协议将如何处理帧中的数据。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;ip报文头部&quot;&gt;IP报文头部&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/ipheader.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;IP报文头部信息用于指导网络设备对报文进行路由和分片。同一个网段内的数据转发通过链路层即可实现，而跨网段的数据转发需要使用网络设备的路由功能。分片是指数据包超过一定长度时，需要被划分成不同的片段使其能够在网络中传输。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;IP报文头部长度为20到60字节，报文头中的信息可以用来指导网络设备如何将报文从源设备发送到目的设备。其中，版本字段表示当前支持的IP协议版本，当前的版本号为4。DS字段早期用来表示业务类型，现在用于支持QoS中的差分服务模型，实现网络流量优化。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;源和目的IP地址是分配给主机的逻辑地址，用于在网络层标识报文的发送方和接收方。根据源和目的IP地址可以判断目的端是否与发送端位于同一网段，如果二者不在同一网段，则需要采用路由机制进行跨网段转发。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;ip编址-1&quot;&gt;IP编址&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/ipaddress.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;IP地址分为网络部分和主机部分。&lt;/p&gt;

&lt;p&gt;IP地址由32个二进制位组成，通常用点分十进制形式表示。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;IPv4地址为32比特的二进制数，通常用点分十进制表示。IP地址用来标识网络中的设备，具有IP地址的设备可以在同一网段内或跨网段通信。IP地址包括两部分，第一部分是网络号，表示IP地址所属的网段，第二部分是主机号，用来唯一标识本网段上的某台网络设备。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/ipaddress2.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;每个网段上都有两个特殊地址不能分配给主机或网络设备。第一个是该网段的网络地址，该IP地址的主机位为全0，表示一个网段。第二个地址是该网段中的广播地址，目的地址为广播地址的报文会被该网段中的所有网络设备接收。广播地址的主机位为全1。除网络地址和广播地址以外的其他IP地址都可以作为网络设备的IP地址。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;二进制十进制和十六进制&quot;&gt;二进制、十进制和十六进制&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/dox.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;在IP网络中，二进制和十六进制是常用的编码方式。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;网络中的数据可以采用二进制、十进制或十六进制来表示，了解这些进制对理解IP网络基础知识很有必要。每种进制使用不同的基值表示每一位的数值。二进制每一位只有0和1两个值，基值为2，二进制数的每一位都可以用2的x次幂来表示，x表示二进制数的位数。十六进制的每一位可以有16个数值，范围为0-F（即0-9和A-F），A对应十进制的10，F对应十进制的15（二进制的1111）。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/dox2.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;IP地址以字节为单位分为四段，每字节包含8个比特，可以表示0到255，共256个数值。从二进制到十进制转换表中可以看到每一位二进制数所代表的十进制数。上面的表格举例说明了8位二进制数转换为十进制数和十六进制数的情况。从表格中也可以看到全0和全1所对应的十进制数和十六进制数。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;二进制和十进制转换&quot;&gt;二进制和十进制转换&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/dox3.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;32位的IP地址分为4个字节，每个字节有256个取值。因此，理论上IPv4可以有4,294,967,296个IP地址，但实际上只有其中一部分地址可以分配给网络设备使用。本例中，IP地址的前三个字节表示网络号，最后一个字节表示该网络上网络设备可用的地址范围。将二进制格式的IP地址转换为十进制格式时，需要把二进制中每一位1所代表的值加在一起，得出IP地址的十进制值。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;ip地址分类&quot;&gt;IP地址分类&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/ipaddress3.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;IPv4地址被划分为A、B、C、D、E五类，每类地址的网络号包含不同的字节数。A类，B类和C类地址为可分配IP地址，每类地址支持的网络数和主机数不同。比如，A类地址可支持126个网络，每个网络支持224 （16,777,216 )个主机地址，另外每个网段中的网络地址和广播地址不能分配给主机。C类地址支持200多万个网络，每个网络支持256个主机地址，其中254个地址可以分配给主机使用。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;D类地址为组播地址。主机收到以D类地址为目的地址的报文后，且该主机是该组播组成员，就会接收并处理该报文。各类IP地址可以通过第一个字节中的比特位进行区分。如A类地址第一字节的最高位固定为0，B类地址第一字节的高两位固定为10，C类地址第一字节的高三位固定为110，D类地址第一字节的高四位固定为1110，E类地址第一字节的高四位固定为1111。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;ip地址类型&quot;&gt;IP地址类型&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;私有地址范围&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;10.0.0.0~10.255.255.255&lt;/li&gt;
    &lt;li&gt;172.16.0.0~172.31.255.255&lt;/li&gt;
    &lt;li&gt;192.168.0.0~192.168.255.255&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;特殊地址&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;127.0.0.0~127.255.255.255&lt;/li&gt;
    &lt;li&gt;0.0.0.0&lt;/li&gt;
    &lt;li&gt;255.255.255.255&lt;/li&gt;
  &lt;/ul&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;IPv4中的部分IP地址被保留用作特殊用途。为节省IPv4地址，A、B、C类地址段中都预留了特定范围的地址作为私网地址。现在，世界上所有终端系统和网络设备需要的IP地址总数已经超过了32位IPv4地址所能支持的最大地址数4,294,967,296。为主机分配私网地址节省了公网地址，可以用来缓解IP地址短缺的问题。企业网络中普遍使用私网地址，不同企业网络中的私网地址可以重叠。默认情况下，网络中的主机无法使用私网地址与公网通信；当需要与公网通信时，私网地址必须转换成公网地址。还有其他一些特殊IP地址，如127.0.0.0网段中的地址为环回地址，用于诊断网络是否正常。IPv4中的第一个地址0.0.0.0表示任何网络，这个地址的作用将在路由原理中详细介绍。IPv4中的最后一个地址255.255.255.255是0.0.0.0网络中的广播地址。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;网络通信&quot;&gt;网络通信&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/networkcommunication.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;源主机必须要知道目的主机的IP地址后才能将数据发送到目的地。源主机向其他目的主机发送报文之前，需要检查目的IP地址和源IP地址是否属于同一个网段。如果是，则报文将被下发到底层协议进行以太网封装处理。如果目的地址和源地址属于不同网段，则主机需要获取下一跳路由器的IP地址，然后将报文下发到底层协议处理。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;子网掩码mask&quot;&gt;子网掩码（Mask）&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/mask.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;子网掩码用于区分网络部分和主机部分。子网掩码与IP地址的表示方法相同。每个IP地址和子网掩码一起可以用来唯一的标识一个网段中的某台网络设备。子网掩码中的1表示网络位，0表示主机位。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;默认子网掩码&quot;&gt;默认子网掩码&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/default_mask.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;每类IP地址有一个缺省子网掩码。A类地址的缺省子网掩码为8位，即第一个字节表示网络位，其他三个字节表示主机位。B类地址的缺省子网掩码为16位，因此B类地址支持更多的网络，但是主机数也相应减少。C类地址的缺省子网掩码为24位，支持的网络最多，同时也限制了单个网络中主机的数量。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;地址规划&quot;&gt;地址规划&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/address.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;通过子网掩码可以判断主机所属的网段、网段上的广播地址以及网段上支持的主机数。图中这个例子，主机地址为192.168.1.7，子网掩码为24位（C类IP地址的缺省掩码），从中我们可以判断该主机位于192.168.1.0/24网段。将IP地址中的主机位全部置为1，并转换为十进制数，即可得到该网段的广播地址192.168.1.255。网段中支持的主机数为2n，n为主机位的个数。本例中n=8，28=256，减去本网段的网络地址和广播地址，可知该网段支持254个有效主机地址。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;有类ip编址的缺陷&quot;&gt;有类IP编址的缺陷&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/ipwaste.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;在设计网络时使用有类IP地址会造成地址的浪费。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;如果企业网络中希望通过规划多个网段来隔离物理网络上的主机，使用缺省子网掩码就会存在一定的局限性。网络中划分多个网段后，每个网段中的实际主机数量可能很有限，导致很多地址未被使用。如图所示的场景下，如果使用缺省子网掩码的编址方案，则地址使用率很低。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;变长子网掩码&quot;&gt;变长子网掩码&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/VLSM.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;采用可变长子网掩码可解决上述问题。缺省子网掩码可以进一步划分，成为变长子网掩码（VLSM）。通过改变子网掩码，可以将网络划分为多个子网。本例中的地址为C类地址，缺省子网掩码为24位。现借用一个主机位作为网络位，借用的主机位变成子网位。一个子网位有两个取值0和1，因此可划分两个子网。该比特位设置为0，则子网号为0，该比特位设置为1，则子网号为128。将剩余的主机位都设置为0，即可得到划分后的子网地址；将剩余的主机位都设置为1，即可得到子网的广播地址。每个子网中支持的主机数为27-2（减去子网地址和广播地址），即126个主机地址。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;网关gateway&quot;&gt;网关（Gateway）&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/gateway.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;网关用来转发来自不同网段之间的数据包。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;报文转发过程中，首先需要确定转发路径以及通往目的网段的接口，然后将报文封装在以太帧中通过指定的物理接口转发出去。如果目的主机与源主机不在同一网段，报文需要先转发到网关，然后通过网关将报文转发到目的网段。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;网关是指接收并处理本地网段主机发送的报文并转发到目的网段的设备。为实现此功能，网关必须知道目的网段的IP地址。网关设备上连接本地网段的接口地址即为该网段的网关地址。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;ip包分片&quot;&gt;IP包分片&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/ippackage.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;网络中转发的IP报文的长度可以不同，但如果报文长度超过了数据链路所支持的最大长度，则报文就需要分割成若干个较小的片段才能够在链路上传输。将报文分割成多个片段的过程叫做分片。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;接收端根据分片报文中的标识符（Identification），标志（Flags)，及片偏移（Fragment Offset）字段对分片报文进行重组。标识符用于识别属于同一个数据包的分片，以区别于同一主机或其他主机发送的其它数据包分片，保证分片被正确的重新组合。标志字段用于判断是否已经收到最后一个分片。最后一个分片的标志字段设置为0，其他分片的标志字段设置为1，目的端在收到标志字段为0的分片后，开始重组报文。片偏移字段表示每个分片在原始报文中的位置。第一个分片的片偏移为0，第二个分片的片偏移表示紧跟第一个分片后的第一个比特的位置。比如，如果首片报文包含1259比特，那么第二分片报文的片偏移字段值就应该为1260。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;生存时间&quot;&gt;生存时间&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/livetime.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;报文在网段间转发时，如果网络设备上的路由规划不合理，就可能会出现环路，导致报文在网络中无限循环，无法到达目的端。环路发生后，所有发往这个目的地的报文都会被循环转发，随着这种报文逐渐增多，网络将会发生拥塞。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;为避免环路导致的网络拥塞，IP报文头中包含一个生存时间TTL（Time To Live）字段。报文每经过一台三层设备，TTL值减1。初始TTL值由源端设备设置。当报文中的TTL降为0时，报文会被丢弃。同时，丢弃报文的设备会根据报文头中的源IP地址向源端发送ICMP错误消息。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;协议号&quot;&gt;协议号&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/protocolnum.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;目的端的网络层在接收并处理报文以后，需要决定下一步对报文该做如何处理。IP报文头中的协议字段标识了将会继续处理报文的协议。与以太帧头中的Type字段类似，协议字段也是一个十六进制数。该字段可以标识网络层协议，如ICMP（Internet Control Message Protocol，因特网控制报文协议），也可以标识上层协议，如TCP（Transmission Control Protocol，传输控制协议，对应值0x06）、UDP（User Datagram Protocol，用户数据包协议，对应值0x11）。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;常用端口列举&quot;&gt;常用端口列举&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;端口：0
    &lt;blockquote&gt;
      &lt;p&gt;服务：Reserved&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：通常用于分析操作系统。这一方法能够工作是因为在一些系统中“0”是无效端 口，当你试图使用通常的闭合端口连接它时将产生不同的结果。一种典型的扫描，使用 IP地址为0.0.0.0，设置ACK位并在以太网层广播。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：1
    &lt;blockquote&gt;
      &lt;p&gt;服务：tcpmux&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：这显示有人在寻找SGI Irix机器。Irix是实现tcpmux的主要提供者，默认情况下 tcpmux在这种系统中被打开。Irix机器在发布是含有几个默认的无密码的帐户，如： IP、GUEST UUCP、NUUCP、DEMOS 、TUTOR、DIAG、OUTOFBOX等。许多管理员在安装后忘 记删除这些帐户。因此HACKER在INTERNET上搜索tcpmux并利用这些帐户。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：7
    &lt;blockquote&gt;
      &lt;p&gt;服务：Echo&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：能看到许多人搜索Fraggle放大器时，发送到X.X.X.0和X.X.X.255的信息。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：19
    &lt;blockquote&gt;
      &lt;p&gt;服务：Character Generator&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：这是一种仅仅发送字符的服务。UDP版本将会在收到UDP包后回应含有垃圾字符的 包。TCP连接时会发送含有垃圾字符的数据流直到连接关闭。HACKER利用IP欺骗可以发 动DoS攻击。伪造两个chargen服务器之间的UDP包。同样Fraggle DoS攻击向目标地址的 这个端口广播一个带有伪造受害者IP的数据包，受害者为了回应这些数据而过载。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：20、21
    &lt;blockquote&gt;
      &lt;p&gt;服务：FTP&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：FTP服务器所开放的端口，20用于数据传输，21用于控制。最常见的攻击者用于寻找打开 anonymous的FTP服务器的方法。这些服务器带有可读写的目录。木马Doly Trojan、 Fore、Invisible FTP、WebEx、WinCrash和Blade Runner所开放的端口。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：22
    &lt;blockquote&gt;
      &lt;p&gt;服务：Ssh&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：PcAnywhere建立的TCP和这一端口的连接可能是为了寻找ssh。这一服务有许多弱 点，如果配置成特定的模式，许多使用RSAREF库的版本就会有不少的漏洞存在。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：23
    &lt;blockquote&gt;
      &lt;p&gt;服务：Telnet&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：远程登录，入侵者在搜索远程登录UNIX的服务。大多数情况下扫描这一端口是为 了找到机器运行的操作系统。还有使用其他技术，入侵者也会找到密码。木马Tiny Telnet Server就开放这个端口。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：25
    &lt;blockquote&gt;
      &lt;p&gt;服务：SMTP&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：SMTP服务器所开放的端口，用于发送邮件。入侵者寻找SMTP服务器是为了传递他 们的SPAM。入侵者的帐户被关闭，他们需要连接到高带宽的E-MAIL服务器上，将简单的 信息传递到不同的地址。木马Antigen、Email Password Sender、Haebu Coceda、 Shtrilitz Stealth、WinPC、WinSpy都开放这个端口。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：31
    &lt;blockquote&gt;
      &lt;p&gt;服务：MSG Authentication&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：木马Master Paradise、Hackers Paradise开放此端口。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：42
    &lt;blockquote&gt;
      &lt;p&gt;服务：WINS Replication&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：WINS复制&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：53
    &lt;blockquote&gt;
      &lt;p&gt;服务：Domain Name Server（DNS）&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：DNS服务器所开放的端口，入侵者可能是试图进行区域传递（TCP），欺骗DNS （UDP）或隐藏其他的通信。因此防火墙常常过滤或记录此端口。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：67
    &lt;blockquote&gt;
      &lt;p&gt;服务：Bootstrap Protocol Server&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：通过DSL和Cable modem的防火墙常会看见大量发送到广播地址255.255.255.255 的数据。这些机器在向DHCP服务器请求一个地址。HACKER常进入它们，分配一个地址把 自己作为局部路由器而发起大量中间人（man-in-middle）攻击。客户端向68端口广播 请求配置，服务器向67端口广播回应请求。这种回应使用广播是因为客户端还不知道可 以发送的IP地址。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：69
    &lt;blockquote&gt;
      &lt;p&gt;服务：Trival File Transfer&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：许多服务器与bootp一起提供这项服务，便于从系统下载启动代码。但是它们常常由于错误配置而使入侵者能从系统中窃取任何 文件。它们也可用于系统写入文件。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：79
    &lt;blockquote&gt;
      &lt;p&gt;服务：Finger Server&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：入侵者用于获得用户信息，查询操作系统，探测已知的缓冲区溢出错误，回应从自己机器到其他机器Finger扫描。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：80
    &lt;blockquote&gt;
      &lt;p&gt;服务：HTTP&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：用于网页浏览。木马Executor开放此端口。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：99
    &lt;blockquote&gt;
      &lt;p&gt;服务：Metagram Relay&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：后门程序ncx99开放此端口。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：102
    &lt;blockquote&gt;
      &lt;p&gt;服务：Message transfer agent(MTA)-X.400 over TCP/IP&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：消息传输代理。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：109
    &lt;blockquote&gt;
      &lt;p&gt;服务：Post Office Protocol -Version3&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：POP3服务器开放此端口，用于接收邮件，客户端访问服务器端的邮件服务。POP3服务有许多公认的弱点。关于用户名和密码交 换缓冲区溢出的弱点至少有20个，这意味着入侵者可以在真正登陆前进入系统。成功登陆后还有其他缓冲区溢出错误。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：110
    &lt;blockquote&gt;
      &lt;p&gt;服务：SUN公司的RPC服务所有端口&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：常见RPC服务有rpc.mountd、NFS、rpc.statd、rpc.csmd、rpc.ttybd、amd等&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：113
    &lt;blockquote&gt;
      &lt;p&gt;服务：Authentication Service&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：这是一个许多计算机上运行的协议，用于鉴别TCP连接的用户。使用标准的这种服务可以获得许多计算机的信息。但是它可作为许多服务的记录器，尤其是FTP、POP、IMAP、SMTP和IRC等服务。通常如果有许多客户通过防火墙访问这些服务，将会看到许多这个端口的连接请求。记住，如果阻断这个端口客户端会感觉到在防火墙另一边与E-MAIL服务器的缓慢连接。许多防火墙支持TCP连接的阻断过程中发回RST。这将会停止缓慢的连接。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：119
    &lt;blockquote&gt;
      &lt;p&gt;服务：Network News Transfer Protocol&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：NEWS新闻组传输协议，承载USENET通信。这个端口的连接通常是人们在寻找USENET服务器。多数ISP限制，只有他们的客户才能访问他们的新闻组服务器。打开新闻组服务器将允许发/读任何人的帖子，访问被限制的新闻组服务器，匿名发帖或发送SPAM。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：135
    &lt;blockquote&gt;
      &lt;p&gt;服务：Location Service&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：Microsoft在这个端口运行DCE RPC end-point mapper为它的DCOM服务。这与UNIX 111端口的功能很相似。使用DCOM和RPC的服务利用计算机上的end-point mapper注册它们的位置。远端客户连接到计算机时，它们查找end-point mapper找到服务的位置。HACKER扫描计算机的这个端口是为了找到这个计算机上运行Exchange Server吗？ 什么版本？还有&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：110
    &lt;blockquote&gt;
      &lt;p&gt;服务：pop3&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：POP3(Post Office Protocol 3)服务器开放此端口，用于接收邮件，客户端访问服务器端的邮件服务。POP3服务有许多公认的弱点。关于用户名和密码交换缓冲区溢出的弱点至少有20个，这意味着入侵者可以在真正登陆前进入系统。成功登陆后还有其他缓冲区溢出错误。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：137、138、139
    &lt;blockquote&gt;
      &lt;p&gt;服务：NETBIOS Name Service&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：其中137、138是UDP端口，当通过网上邻居传输文件时用这个端口。而139端口：通过这个端口进入的连接试图获得NetBIOS/SMB服务。这个协议被用于windows文件和打印机共享和SAMBA。还有WINS Regisrtation也用它。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：143
    &lt;blockquote&gt;
      &lt;p&gt;服务：Interim Mail Access Protocol v2&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：和POP3的安全问题一样，许多IMAP服务器存在有缓冲区溢出漏洞。记住：一种LINUX蠕虫（admv0rm）会通过这个端口繁殖，因此许多这个端口的扫描来自不知情的已经被感染的用户。当REDHAT在他们的LINUX发布版本中默认允许IMAP后，这些漏洞变的很流行。这一端口还被用于IMAP2，但并不流行。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：161
    &lt;blockquote&gt;
      &lt;p&gt;服务：SNMP
说明：SNMP允许远程管理设备。所有配置和运行信息的储存在数据库中，通过SNMP可获得这些信息。许多管理员的错误配置将被暴露在Internet。Cackers将试图使用默认的密码public、private访问系统。他们可能会试验所有可能的组合。SNMP包可能会被错误的指向用户的网络。&lt;/p&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：389
    &lt;blockquote&gt;
      &lt;p&gt;服务：LDAP、ILS&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：轻型目录访问协议和NetMeeting Internet Locator Server共用这一端口。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：443
    &lt;blockquote&gt;
      &lt;p&gt;服务：Https&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：网页浏览端口，能提供加密和通过安全端口传输的另一种HTTP。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：993
    &lt;blockquote&gt;
      &lt;p&gt;服务：IMAP&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：SSL（Secure Sockets layer）&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：1080
    &lt;blockquote&gt;
      &lt;p&gt;服务：SOCKS代理协议服务器&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：SOCKS代理协议服务器&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：1433
    &lt;blockquote&gt;
      &lt;p&gt;服务：SQL&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：Microsoft的SQL服务开放的端口。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：1503
    &lt;blockquote&gt;
      &lt;p&gt;服务：NetMeeting T.120&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：NetMeeting T.120&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：1521
    &lt;blockquote&gt;
      &lt;p&gt;服务：Oracle 数据库&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：Oracle 数据库&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：1720
    &lt;blockquote&gt;
      &lt;p&gt;服务：NetMeeting&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：NetMeeting H.233 call Setup。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：1731
    &lt;blockquote&gt;
      &lt;p&gt;服务：NetMeeting Audio Call Control&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：NetMeeting音频调用控制。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：3306
    &lt;blockquote&gt;
      &lt;p&gt;服务：MySQL 数据库&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：MySQL 数据库&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：3389
    &lt;blockquote&gt;
      &lt;p&gt;服务：超级终端&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：WINDOWS 2000终端开放此端口。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：4000
    &lt;blockquote&gt;
      &lt;p&gt;服务：QQ客户端&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：腾讯QQ客户端开放此端口。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：5631
    &lt;blockquote&gt;
      &lt;p&gt;服务：pcAnywere&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：有时会看到很多这个端口的扫描，这依赖于用户所在的位置。当用户打开pcAnywere时，它会自动扫描局域网C类网以寻找可能的代理（这里的代理是指agent而不是proxy）。入侵者也会寻找开放这种服务的计算机。，所以应该查看这种扫描的源地址。一些搜寻pcAnywere的扫描包常含端口22的UDP数据包。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：6970
    &lt;blockquote&gt;
      &lt;p&gt;服务：RealAudio&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：RealAudio客户将从服务器的6970-7170的UDP端口接收音频数据流。这是由TCP-7070端口外向控制连接设置的。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：7323
    &lt;blockquote&gt;
      &lt;p&gt;服务：&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：Sygate服务器端。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：8000
    &lt;blockquote&gt;
      &lt;p&gt;服务：OICQ&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：腾讯QQ服务器端开放此端口。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：8010
    &lt;blockquote&gt;
      &lt;p&gt;服务：Wingate&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：Wingate代理开放此端口。&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
  &lt;li&gt;端口：8080
    &lt;blockquote&gt;
      &lt;p&gt;服务：代理端口&lt;/p&gt;
      &lt;blockquote&gt;
        &lt;p&gt;说明：WWW代理开放此端口&lt;/p&gt;
      &lt;/blockquote&gt;
    &lt;/blockquote&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;传输层协议&quot;&gt;传输层协议&lt;/h1&gt;

&lt;p&gt;传输层定义了主机应用程序之间端到端的连通性。传输层中最为常见的两个协议分别是传输控制协议TCP（Transmission Control Protocol）和用户数据包协议UDP（User Datagram Protocol）。&lt;/p&gt;

&lt;h2 id=&quot;tcp&quot;&gt;TCP&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/tcp.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;TCP是一种面向连接的传输层协议，可提供可靠的传输服务。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;TCP位于TCP/IP模型的传输层，它是一种面向连接的端到端协议。TCP作为传输控制协议，可以为主机提供可靠的数据传输。在本例中，两台主机在通信之前，需要TCP在它们之间建立可靠的传输通道。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;tcp端口号&quot;&gt;TCP端口号&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/tcpport.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;端口号用来区分不同的网络服务。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;TCP允许一个主机同时运行多个应用进程。每台主机可以拥有多个应用端口，每对端口号、源和目标IP地址的组合唯一地标识了一个会话。端口分为知名端口和动态端口。有些网络服务会使用固定的端口，这类端口称为知名端口，端口号范围为0-1023。如FTP、HTTP、Telnet、SNMP服务均使用知名端口。动态端口号范围从1024到65535，这些端口号一般不固定分配给某个服务，也就是说许多服务都可以使用这些端口。只要运行的程序向系统提出访问网络的申请，那么系统就可以从这些端口号中分配一个供该程序使用。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;tcp头部&quot;&gt;TCP头部&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/tcpheader.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;TCP通常使用IP作为网络层协议，这时TCP数据段被封装在IP数据包内。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;TCP数据段由TCP Header（头部）和TCP Data（数据）组成。TCP最多可以有60个字节的头部，如果没有Options字段，正常的长度是20字节。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;TCP Header是由如上图标识的一些字段组成，这里列出几个常用字段。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;16位源端口号：源主机的应用程序使用的端口号。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;16位目的端口号：目的主机的应用程序使用的端口号。每个TCP头部都包含源和目的端的端口号，这两个值加上IP头部中的源IP地址和目的IP地址可以唯一确定一个TCP连接。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;32位序列号：用于标识从发送端发出的不同的TCP数据段的序号。数据段在网络中传输时，它们的顺序可能会发生变化；接收端依据此序列号，便可按照正确的顺序重组数据。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;32位确认序列号：用于标识接收端确认收到的数据段。确认序列号为成功收到的数据序列号加1。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;4位头部长度：表示头部占32bit字的数目，它能表达的TCP头部最大长度为60字节。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;16位窗口大小：表示接收端期望通过单次确认而收到的数据的大小。由于该字段为16位，所以窗口大小的最大值为65535字节，该机制通常用来进行流量控制。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;16位校验和：校验整个TCP报文段，包括TCP头部和TCP数据。该值由发送端计算和记录并由接收端进行验证。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;tcp建立连接的过程&quot;&gt;TCP建立连接的过程&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/tcpconnect.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;TCP通过三次握手建立可靠连接。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;TCP是一种可靠的，面向连接的全双工传输层协议。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;TCP连接的建立是一个三次握手的过程。如图所示：&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;主机A（通常也称为客户端）发送一个标识了SYN的数据段，表示期望与服务器A建立连接，此数据段的序列号（seq）为a。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;服务器A回复标识了SYN+ACK的数据段，此数据段的序列号（seq）为b，确认序列号为主机A的序列号加1（a+1），以此作为对主机A的SYN报文的确认。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;主机A发送一个标识了ACK的数据段，此数据段的序列号（seq）为a+1，确认序列号为服务器A的序列号加1（b+1），以此作为对服务器A的SYN报文的确认。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;tcp传输过程&quot;&gt;TCP传输过程&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/tcptrans.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;TCP的可靠传输还体现在TCP使用了确认技术来确保目的设备收到了从源设备发来的数据，并且是准确无误的。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;确认技术的工作原理如下：&lt;/p&gt;
  &lt;blockquote&gt;
    &lt;p&gt;目的设备接收到源设备发送的数据段时，会向源端发送确认报文，源设备收到确认报文后，继续发送数据段，如此重复。&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;blockquote&gt;
    &lt;p&gt;如图所示，主机A向服务器A发送TCP数据段，为描述方便假定每个数据段的长度都是500个字节。当服务器A成功收到序列号是M+1499的字节以及之前的所有字节时，会以序列号M+1499+1=M+1500进行确认。另外，由于数据段N+3传输失败，所以服务器A未能收到序列号为M+1500的字节，因此服务器A还会再次以序列号M+1500进行确认。&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;tcp流量控制&quot;&gt;TCP流量控制&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/tcpstream.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;TCP滑动窗口技术通过动态改变窗口大小来实现对端到端设备之间的数据传输进行流量控制。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;如图所示，主机A和服务器A之间通过滑动窗口来实现流量控制。为方便理解，此例中只考虑主机A发送数据给服务器A时，服务器A通过滑动窗口进行流量控制。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;主机A向服务器发送4个长度为1024字节的数据段，其中主机的窗口大小为4096个字节。服务器A收到第3个数据段后，缓存区满，第4个数据段被丢弃。服务器以ACK 3073响应，窗口大小调整为3072，表明服务器的缓冲区只能处理3072个字节的数据段。于是主机A改变其发送速率，发送窗口大小为3072的数据段。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;tcp关闭连接&quot;&gt;TCP关闭连接&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/tcpoff.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;主机在关闭连接之前，要确认收到来自对方的ACK。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;TCP支持全双工模式传输数据，这意味着同一时刻两个方向都可以进行数据的传输。在传输数据之前，TCP通过三次握手建立的实际上是两个方向的连接，因此在传输完毕后，两个方向的连接必须都关闭。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;TCP连接的建立是一个三次握手的过程，而TCP连接的终止则要经过四次握手。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;如图所示：&lt;/p&gt;
  &lt;blockquote&gt;
    &lt;p&gt;主机A想终止连接，于是发送一个标识了FIN，ACK的数据段，序列号为a，确认序列号为b。&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;blockquote&gt;
    &lt;p&gt;服务器A回应一个标识了ACK的数据段，序列号为b，确认序号为a+1，作为对主机A的FIN报文的确认。&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;blockquote&gt;
    &lt;p&gt;服务器A想终止连接，于是向主机A发送一个标识了FIN，ACK的数据段，序列号为b，确认序列号为a+1。&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;blockquote&gt;
    &lt;p&gt;主机A回应一个标识了ACK的数据段，序列号为a+1，确认序号为b+1，作为对服务器A的FIN报文的确认。&lt;/p&gt;
  &lt;/blockquote&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;以上四次交互便完成了两个方向连接的关闭。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;udp&quot;&gt;UDP&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/udp.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;UDP是一种面向无连接的传输层协议，传输可靠性没有保证。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;当应用程序对传输的可靠性要求不高，但是对传输速度和延迟要求较高时，可以用UDP协议来替代TCP协议在传输层控制数据的转发。UDP将数据从源端发送到目的端时，无需事先建立连接。UDP采用了简单、易操作的机制在应用程序间传输数据，没有使用TCP中的确认技术或滑动窗口机制，因此UDP不能保证数据传输的可靠性，也无法避免接收到重复数据的情况。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;udp头部&quot;&gt;UDP头部&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/udpheader.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;UDP头部仅占8字节，传输数据时没有确认机制。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;UDP报文分为UDP报文头和UDP数据区域两部分。报头由源端口、目的端口、报文长度以及校验和组成。UDP适合于实时数据传输，如语音和视频通信。相比于TCP，UDP的传输效率更高、开销更小，但是无法保障数据传输的可靠性。UDP头部的标识如下：&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;16位源端口号：源主机的应用程序使用的端口号。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;16位目的端口号：目的主机的应用程序使用的端口号。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;16位UDP长度：是指UDP头部和UDP数据的字节长度。因为UDP头部长度为8字节，所以该字段的最小值为8。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;16位UDP校验和：该字段提供了与TCP校验字段同样的功能；该字段是可选的。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;udp传输过程&quot;&gt;UDP传输过程&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/udptrans.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;使用UDP传输数据时，由应用程序根据需要提供报文到达确认、排序、流量控制等功能。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;主机A发送数据包时，这些数据包是以有序的方式发送到网络中的，每个数据包独立地在网络中被发送，所以不同的数据包可能会通过不同的网络路径到达主机B。这样的情况下，先发送的数据包不一定先到达主机B。因为UDP数据包没有序号，主机B将无法通过UDP协议将数据包按照原来的顺序重新组合，所以此时需要应用程序提供报文的到达确认、排序和流量控制等功能。通常情况下，UDP采用实时传输机制和时间戳来传输语音和视频数据。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/udptrans2.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;UDP不提供重传机制，占用资源小，处理效率高。&lt;/p&gt;

&lt;p&gt;一些时延敏感的流量，如语音、视频等，通常使用UDP作为传输层协议。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;UDP适合传输对时延敏感的流量，如语音和视频。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;在使用TCP协议传输数据时，如果一个数据段丢失或者接收端对某个数据段没有确认，发送端会重新发送该数据段。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;TCP重新发送数据会带来传输延迟和重复数据，降低了用户的体验。对于时延敏感的应用，少量的数据丢失一般可以被忽略，这时使用UDP传输将能够提升用户的体验。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;数据转发过程&quot;&gt;数据转发过程&lt;/h1&gt;

&lt;p&gt;TCP/IP协议簇和底层协议配合，保证了数据能够实现端到端的传输。数据传输过程是一个非常复杂的过程，例如数据在转发的过程中会进行一系列的封装和解封装。对于网络工程师来说，只有深入地理解了数据在各种不同设备上的转发过程，才能够对网络进行正确的分析和检测。&lt;/p&gt;

&lt;h2 id=&quot;数据转发过程概述&quot;&gt;数据转发过程概述&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/datatrans.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;数据包在相同网段内或不同网段之间转发所依据的原理基本一致。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;数据可以在同一网络内或者不同网络间传输，数据转发过程也分为本地转发和远程转发，但两者的数据转发原理是基本一样的，都是遵循TCP/IP协议簇。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;本示例中，主机A需要访问服务器A的Web服务，并且假定两者之间已经建立了TCP连接。接下来会以此示例来讲解数据在不同网络间的传输过程。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;tcp封装&quot;&gt;TCP封装&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/tcppack.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;当主机建立了到达目的地的TCP连接后，便开始对应用层数据进行封装。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;主机A会对待发送的应用数据首先执行加密和压缩等相关操作，之后进行传输层封装。Web应用是基于传输层的TCP协议传输数据的。主机A使用TCP进行报文封装时，必须填充源端口和目的端口字段，初始序列号和确认序列号字段，标识位，窗口字段以及校验和字段。此例中数据段的源端口号为主机A随机选择的1027号端口，目的端口号为服务器A的TCP知名端口80。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;ip封装&quot;&gt;IP封装&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/ippack.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;主机A完成传输层封装后，一般会进行网络层数据封装，在使用IP进行封装时，需要明确IP报文的源和目的地址。如果IP报文的大小大于网络的最大传输单元（MTU），则该报文有可能在传输过程中被分片。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;生存时间（TTL）字段用来减少网络环路造成的影响。ARG3系列路由器产生的数据包，默认TTL值为255。路由器转发一个数据包时，该值会被减1，如果路由器发现该值被减为0，就会丢弃该数据包。这样，即使网络中存在环路，数据包也不会在网络上一直被转发。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;协议字段标识了传输层所使用的协议。本例中，传输层使用的是TCP协议，所以该字段的填充值为0X06。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;查找路由&quot;&gt;查找路由&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/findroute.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;主机A必须要拥有到达目的地的路由。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;每个主机都会独自维护各自的路由表项。主机A在发送数据前需要先检查是否能够到达目的端，这个过程是通过查找路由来完成的。在此示例中，主机A拥有一条到达“任何网络”（在IP编址部分已经简要介绍过）的路由，它发往其他网络的数据都会通过IP地址为10.1.1.1的接口转发到下一跳，即网关10.1.1.254。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;arp&quot;&gt;ARP&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/arp.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;通过ARP缓存表找到下一跳的MAC地址。&lt;/p&gt;

&lt;p&gt;如果表项里没有下一跳的MAC地址，主机A会发送ARP请求。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;接下来，由于数据包要被封装成数据帧，所以主机A需要获取下一跳的MAC地址，也就是网关的MAC地址。主机首先会查询ARP缓存表。本例中，主机A的ARP缓存表中存在网关MAC地址的表项。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;如果没有查找到网关的MAC地址表项，主机A会通过发送ARP请求来获取网关的MAC地址。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;以太网封装&quot;&gt;以太网封装&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/ethpack.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;主机A在链路层封装数据帧时，会遵循IEEE 802.3或Ethernet_II标准，Ethernet_II帧头中的类型字段填充为0x0800，以表示网络层使用的是IP协议。源MAC地址为主机A的MAC地址，目的MAC地址为网关路由器E0/0接口的MAC地址。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;数据帧转发过程&quot;&gt;数据帧转发过程&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/frametranspath.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;主机工作在半双工状态下，所以会使用CSMA/CD来检测链路是否空闲。&lt;/p&gt;

&lt;p&gt;前导码用于使接收者进入同步状态，定界符用于指示帧的开始。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;主机A工作在半双工状态下，所以会使用CSMA/CD来检测链路是否空闲。如果链路空闲，主机A会将一个前导码（Preamble）和一个帧首定界符（SFD）附加到帧头然后进行传输。前导码的作用是使接收设备进行同步并做好接收数据帧的准备。前导码是包括了7个字节的二进制“1”、“0”交替的代码，即1010…10共56位。帧首定界符是长度为1个字节的10101011二进制序列，它的作用是使接收端对帧的第一位进行定位。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/frametranspath2.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;同一个冲突域里的设备都会接收到主机A发送的数据帧。&lt;/p&gt;

&lt;p&gt;只有网关（RTA）会处理该数据帧，并继续转发。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;本例中，主机A发送数据帧到共享以太网，此网络中的所有网络设备都会收到该帧。设备收到帧之后，首先会进行FCS校验。如果FCS校验未能通过，则帧被立即丢弃。对于通过了FCS校验的帧，设备会检查帧中的目的MAC地址。如果帧中的目的MAC地址与自己的MAC地址不同，设备将丢弃帧，如果相同，则会继续处理。处理过程中，帧头帧尾会被剥去（也就是解封装），剩下的数据报文会被根据帧头中的类型字段的值来送到网络层中的对应协议模块去处理。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;数据包转发过程&quot;&gt;数据包转发过程&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/packtrans.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;网关检查是否具有到达目的网络的路由条目。&lt;/p&gt;

&lt;p&gt;如果存在转发路径，则为数据包添加一个新的二层帧头和帧尾，并继续转发。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;RTA收到此数据报文后，网络层会对该报文进行处理。RTA首先根据IP头部信息中的校验和字段，检查IP数据报文头部的完整性，然后根据目的IP地址查看路由表，确定是否能够将数据包转发到目的端。RTA还必须对TTL的值进行处理。另外，报文大小不能超过MTU值。如果报文大小超过MTU值，则报文将被分片。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;网络层处理完成后，报文将被送到数据链路层重新进行封装，成为一个新的数据帧，该帧的头部会封装新的源MAC地址和目的MAC地址。如果当前网络设备不知道下一跳的MAC地址，将会使用ARP来获得。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;数据帧解封装&quot;&gt;数据帧解封装&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/frameunpack.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;RTB以服务器A的MAC地址作为目的MAC继续转发。&lt;/p&gt;

&lt;p&gt;服务器A接收到该数据帧后，发现目的MAC为自己的MAC，于是会继续处理该数据帧。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;该示例中，服务器A处于一个共享以太网中，两台服务器都会收到RTB发送的数据帧。该帧的目的MAC地址与服务器B的接口MAC地址不匹配，所以会被服务器B丢弃。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;服务器A成功收到该帧，并通过FCS校验。服务器A将利用帧中的类型字段来识别在网络层处理该数据的协议。该示例中，服务器A会将解封装后的此数据交给网络层的IP协议来进行处理。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;数据包解封装&quot;&gt;数据包解封装&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/packunpack.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;服务器A检查数据包的目的IP地址，发现目的IP与自己的IP地址相同。&lt;/p&gt;

&lt;p&gt;服务器A剥掉数据包的IP头部后，会送往上层协议TCP继续进行处理。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;服务器A通过IP协议来处理该报文，首先会通过校验和字段来验证报文头的完整性，然后检查IP报文头中的目的IP地址是否与自己当前的IP地址匹配。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;如果在源与目的之间的数据传输期间数据发生了报文分片，则报文会被目的端重新组合。标识字段用于标识属于同一数据源的分片报文，偏移量表示该分片在原分组中的相对位置。标志字段目前只有两位有意义，标志字段最低位为1，表示后面还有分片，为0表示这已经是最后一个数据片；中间一位为1表示不能分片，为0表示允许分片。所有的分片报文必须被目的端全部接收到后才会进行重新组合。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;协议字段表示此数据包携带的上层数据是哪种协议的数据。需要注意的是，下一个报头并非总是传输层报头。例如，ICMP报文也是使用IP协议封装，协议字段值为0x01。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;数据段解封装&quot;&gt;数据段解封装&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2021/01/30/dataunpack.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;服务器A检查TCP头部的目的端口，然后将数据段发送给应用层的HTTP协议进行处理。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;当IP报文头被处理完并剥离后，数据段会被发送到传输层进行处理。在此示例中，传输层协议使用的是TCP，且发送端和接收端已经通过三次握手建立了连接。传输层收到该数据段后，TCP协议会查看并处理该数据段头部信息，其中目的端口号为80，用于表示处理该数据的应用层协议为HTTP协议。TCP处理完头部信息后会将此数据段头部进行剥离，然后将剩下的应用数据发送到HTTP协议进行处理。&lt;/p&gt;
&lt;/blockquote&gt;
</content>
 </entry>
 
 <entry>
   <title>【Blog Build】Plan of Jekyll Blog - Episode 1: Jekyll-3 on Ubuntu and Nginx</title>
   <link href="https://icing.fun/posts/jekyll_blog_tutorial_01.html"/>
   <updated>2020-05-04T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/jekyll_blog_tutorial_01</id>
   <content type="html">&lt;p&gt;This tutorial you will learn how to configure Jekyll-3 on Ubuntu 16.04 and Nginx.&lt;/p&gt;

&lt;h1 id=&quot;jekyll-on-ubuntu&quot;&gt;Jekyll On Ubuntu&lt;/h1&gt;

&lt;p&gt;The release of the Ubuntu is &lt;a href=&quot;https://ubuntu.com/16-04&quot;&gt;Ubuntu 16.04 LTS (Xenial Xerus)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can follow this link &lt;a href=&quot;https://jekyllrb.com/docs/installation/ubuntu/&quot;&gt;Jekyll on Ubuntu&lt;/a&gt; to configure Jekyll.&lt;/p&gt;

&lt;p&gt;Before we install Jekyll, we need to install Ruby and other dependencies:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;ruby-full build-essential zlib1g-dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Caution: &lt;/strong&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo apt-get install ruby-full&lt;/code&gt; command on Ubuntu 16.04 even 18.04 can only install Ruby2.5, it might take some unsuspected problem.&lt;/p&gt;

&lt;p&gt;Avoid installing RubyGems packages (called gems) as the root user. (Well, AliCloud only provides &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root&lt;/code&gt; account and I am lazy about adding a new user account. So I think it doesn’t matter to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root&lt;/code&gt; account.) Instead, set up a gem installation directory for your user account. The following commands will add environment variables to your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.bashrc&lt;/code&gt; file to configure the gem installation path:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;# Install Ruby Gems to ~/gems&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;export GEM_HOME=&quot;$HOME/gems&quot;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
&lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&apos;export PATH=&quot;$HOME/gems/bin:$PATH&quot;&apos;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.bashrc
&lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Finally, install Jekyll and Bundler:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gem &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;jekyll bundler
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can make a quick start for surfing the Jekyll blog:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;jekyll new my-awesome-site
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;my-awesome-site
bundle &lt;span class=&quot;nb&quot;&gt;exec &lt;/span&gt;jekyll serve
&lt;span class=&quot;c&quot;&gt;# =&amp;gt; Now browse to http://localhost:4000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Or, clone the repository from GitHub and build Jekyll blog:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone https://github.com/IcingTomato/blog.old.git
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;blog.old
jekyll serve
&lt;span class=&quot;c&quot;&gt;# =&amp;gt; Now browse to http://localhost:4000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;liquid-warning&quot;&gt;Liquid warning&lt;/h1&gt;

&lt;p&gt;If you follow the step, congratulation, you cannot see any blog in your website.&lt;/p&gt;

&lt;p&gt;Just like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2020/05/04/unsuspected_error.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Well, because Ruby2.5 made its Bundler incompatible with Jekyll-4.0, so we have to uninstall Jekyll-4.0 and install the previous versions.&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;gem uninstall jekyll
gem &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;jekyll &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; 3.1.3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;jekyll-serve&quot;&gt;Jekyll Serve&lt;/h1&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jekyll serve&lt;/code&gt; will publish your site on localhost:4000. But you can change the port:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;jekyll serve &lt;span class=&quot;nt&quot;&gt;--port&lt;/span&gt; 4001
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;But you can’t visit it on public network. So you can:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;jekyll serve &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--host&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;0.0.0.0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After doing these jobs, we can’t visit our website ethier.&lt;/p&gt;

&lt;h1 id=&quot;nginx-configuration&quot;&gt;Nginx Configuration&lt;/h1&gt;

&lt;p&gt;Because Jekyll uses port 4000, so we will make a Nginx “proxy” from port 4000 to port 80.&lt;/p&gt;

&lt;p&gt;First, install Nginx:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;apt-get &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;nginx
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then, use your favourite text editor to edit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/nginx/conf.d/jekyll.conf&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@blog:~# &lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;nano /etc/nginx/conf.d/jekyll.conf

server &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    listen 80&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    server_name your.domain&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    location / &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        proxy_pass http://localhost:4000&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img src=&quot;../img/post/2020/05/04/your_domain.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Finally, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl+O&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl+X&lt;/code&gt; to save and exit, then restart &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nginx.service&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;systemctl restart nginx
jekyll serve &lt;span class=&quot;nt&quot;&gt;--detach&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
</content>
 </entry>
 
 <entry>
   <title>【安卓搞机记】Google Pixel XL 折腾记</title>
   <link href="https://icing.fun/posts/google_pixel_hacking.html"/>
   <updated>2018-01-22T00:00:00+00:00</updated>
   <id>https://icing.fun/posts/google_pixel_hacking</id>
   <content type="html">&lt;p&gt;我在18年的时候，攒了好久的一笔钱，买了 Pixel XL，换掉了可怜的 iPhone5s，然后就开始了我的折腾之路。&lt;/p&gt;

&lt;h1 id=&quot;前言&quot;&gt;前言&lt;/h1&gt;

&lt;p&gt;手机摔个稀碎，没法拍图了&lt;/p&gt;

&lt;h1 id=&quot;pixelpixel-xl-v版解锁教程&quot;&gt;Pixel/Pixel XL V版解锁教程&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;退出谷歌账号，取消屏幕密码，删除指纹&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;把设备恢复出厂设置&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;跳过设置向导所有东西，不要连接wifi&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;进入开发者选项开启USB调试，并授权电脑访问&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;电脑使用adb命令&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;adb shell pm uninstall &lt;span class=&quot;nt&quot;&gt;--user&lt;/span&gt; 0 com.android.phone 
adb reboot
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;比较关键的一步，国内很多人卡在这里，主要是要让手机可以访问谷歌并且消除wifi上的X号，我的方法是先使用adb命令（或者科学上网法）&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;adb shell settings put global captive_portal_https_url https://www.google.cn/generate_204 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后开关飞行模式，再开启外网，再连接wifi，就可以消除信号x了&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;设置锁屏密码为图形，再通过桌面的google程序登录谷歌账号&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;这时候再回去开发者选项就会看到OEM解锁可以开了&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;打开OEM解锁重启进入BootLoader&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;电源+音量+ 或&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;adb reboot bootloader
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;使用adb命令&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;fastboot oem unlock
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;或&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;fastboot flashing unlock
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;然后手机会进入一个界面，音量键选择YES（将会清除所有数据）&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;清除完了之后手机会跳回到BootLoader界面，可以看到底下已经是UNLOCK状态了&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;然后重启手机，再进入开发者选项，就会看到OEM解锁那里已经是解锁状态了&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;如何进入bootloader界面&quot;&gt;如何进入Bootloader界面？&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;方法一：手机关机，等待3秒钟，按住音量下1秒，不要松开，然后按住电源键，等待手机振动，手机进入bootloader界面。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;方法二：手机关机，等待3秒钟，按住音量下1秒，链接电源线，等待手机振动，手机进入bootloader界面。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;方法三：手机开机状态下，打开usb调试，在cmd窗口中手动输入&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;adb reboot bootloader
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;线刷包刷机教程&quot;&gt;线刷包刷机教程&lt;/h1&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;在&lt;a href=&quot;https://developers.google.cn/android/images&quot;&gt;谷歌Pixel镜像&lt;/a&gt;下载对应的线刷包&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;然后把所有的文件放到同一个文件夹内&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;手机进入Bootloader界面，链接电脑&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;这时候可以确认驱动是不是安装好了，打开设备管理器&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;双击刚才那个文件夹下的 flash-all.bat，开始刷机（刷机会清除所有数据哦）&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;刷机过程中手机会重启多次，请静静等待结束&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;为什么要解锁-bootloader&quot;&gt;为什么要解锁 Bootloader？&lt;/h1&gt;

&lt;p&gt;解锁 Bootloader 是打开玩机之门的钥匙。只有在 Bootloader 解锁的前提下，我们接下来的步骤才得以顺利进行：安装 TWRP、获取 Root 权限……最后，通过一些需要 Root 权限的特殊手段，打开位置历史记录功能，获得近乎完整的 Android 体验。&lt;/p&gt;

&lt;p&gt;让我们直奔正题吧：&lt;/p&gt;

&lt;p&gt;（注意：解锁 Bootloader 重置设备数据，请注意备份）&lt;/p&gt;

&lt;p&gt;首先，我们需要安装必（ni）备（dong）的工具并成功接入互联网。&lt;/p&gt;

&lt;p&gt;前往「设置-关于手机-版本号」，猛击版本号 7 次开启「开发者选项」。&lt;/p&gt;

&lt;p&gt;在开发者选项中开启「OEM 解锁」。若该选项显示为灰色，请检查你的网络连接是否正（ke）常（xue）USB 调试。&lt;/p&gt;

&lt;p&gt;在 Pixel 设备中，开启 OEM 解锁需要连网&lt;/p&gt;

&lt;p&gt;通过数据线将手机连接至电脑，以管理员身份运行命令提示符（CMD），输入 adb shell 并回车。&lt;/p&gt;

&lt;p&gt;此时，手机端会弹出 USB 调试申请，点击「允许」。&lt;/p&gt;

&lt;p&gt;回到命令提示符窗口，键入&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;adb reboot bootloader 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;并回车，手机会立即重启至 Bootloader 模式。&lt;/p&gt;

&lt;p&gt;在 Bootloader 解锁界面中，使用音量键 +/- 来控制光标，选择「Yes」并按下电源键来进行 Bootloader 解锁。&lt;/p&gt;

&lt;p&gt;稍等片刻之后，你的设备会自动重启，开机时屏幕下方出现一把打开的小锁，那 Bootloader 就解锁成功啦。&lt;/p&gt;

&lt;h1 id=&quot;刷入第三方-recovery--twrp&quot;&gt;刷入第三方 Recovery —— TWRP&lt;/h1&gt;

&lt;p&gt;如果说 Bootloader 是玩机大门上的那把锁，那么 TWRP 就是你打开玩机之门后的领路人。&lt;/p&gt;

&lt;p&gt;所以在解锁 Bootloader 之后，紧接着要做的事情就是刷入第三方 Recovery —— TWRP。由于 Pixel 与 Nexus 的系统分区方式不同，刷入 TWRP 的方式也略为复杂一些：&lt;/p&gt;

&lt;p&gt;首先，前往 TWRP 官网下载最新版 TWRP 压缩包（.zip）和临时 TWRP 镜像文件（.img）。&lt;/p&gt;

&lt;p&gt;将 .img 文件留在电脑上，同时将 .zip 文件拷贝至内置储存。&lt;/p&gt;

&lt;p&gt;重启手机至 Fastboot 模式（参考上面的方法或关机后长按「电源」和「音量 -」），在电脑以管理员身份运行命令提示符。&lt;/p&gt;

&lt;p&gt;在命令提示符窗口中输入 cd 你的 .img 文件路径 来进行定向（比如我的 .img 文件放在 E:\Android 下，那就键入 cd E:\Android 并回车），然后输入&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;fastboot boot xxx.img //xxx 为具体的文件名
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;此时手机会重启至临时 TWRP。&lt;/p&gt;

&lt;p&gt;在临时 TWRP 中，选择「Install」，找到我们事先放在内置储存中的压缩包文件，点击刷入。&lt;/p&gt;

&lt;p&gt;至此，我们就已经用第三方 TWRP 替换了系统自带的 Recovery，接下来的 Root 操作也得以进行：&lt;/p&gt;

&lt;p&gt;前往 SuperSU 官网下载最新版 SuperSU 压缩包。&lt;/p&gt;

&lt;p&gt;将压缩包拷贝至手机内置储存。&lt;/p&gt;

&lt;p&gt;重启手机至 TWRP（关机后长按「电源」和「音量+」），找到 SuperSU 压缩包并刷入。&lt;/p&gt;

&lt;p&gt;完成后重启手机，首次启动过程会自动中断并再次自动重启，不用担心。开机后，手机便已获得 Root 权限，SuperSU 权限管理应用也已经安装至系统当中。&lt;/p&gt;

&lt;p&gt;做好这些工作之后，我们就可以进一步使用 LocationReportEnabler 等需要 Root 权限的应用来开启位置记录报告功能，最终获得完整的 Android 生态体验了。&lt;/p&gt;

&lt;h1 id=&quot;如何进行系统更新&quot;&gt;如何进行系统更新&lt;/h1&gt;

&lt;p&gt;非 Root 用户很难对系统文件进行修改，但在进行系统更新时则较为轻松，在保证网络条件畅（ke）通（xue）的前提下，只需前往「设置-关于-系统更新」，便可自动检查、下载并升级至最新版本的 Android 操作系统。&lt;/p&gt;

&lt;p&gt;但对 Root 用户而言，手动刷入工厂镜像进行系统更新的方法则更为稳妥。&lt;/p&gt;

&lt;p&gt;首先，我们需要前往 Google 的 Nexus/Pixel 工厂镜像网站找到并下载最新版本的 Android 系统镜像，然后解压。&lt;/p&gt;

&lt;p&gt;完整工厂镜像文件压缩包包含了这些内容&lt;/p&gt;

&lt;p&gt;如果你是拿到手机想要优先进行系统升级的用户，将手机重启至 Fastboot 模式并连接电脑后，直接运行 flash-all.bat 即可全自动升级至最新版本；如果你想保留升级前的系统数据，则需要在运行 flash-all.bat 前对其进行一些处理。&lt;/p&gt;

&lt;p&gt;使用文本文档、Notepad++ 等工具打开 flash-all.bat，找到&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;fastboot &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt; update image-marlin-xxxxxx.zip
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;字段，将其改为&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;fastboot update image-marlin-nof27b.zip //即去掉 &lt;span class=&quot;nt&quot;&gt;-w&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;然后保存，即可利用修改后的 flash-all.bat 文件在保留数据的前提下进行系统更新。&lt;/p&gt;

&lt;p&gt;另外，在运行 flash-all.bat 进行更新的过程中，很有可能会出现报错。报错文本类似于&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;archive does not contain &lt;span class=&quot;s1&quot;&gt;&apos;boot.sig&apos;&lt;/span&gt;
archive does not contain &lt;span class=&quot;s1&quot;&gt;&apos;recovery.sig&apos;&lt;/span&gt;
archive does not contain &lt;span class=&quot;s1&quot;&gt;&apos;system.sig&apos;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;当出现这样的字段时，千万不要终止操作。耐心等待耐心等待耐心等待！只要最后出现&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;finished. total &lt;span class=&quot;nb&quot;&gt;time&lt;/span&gt;: 128.109s 
Press any key to exit...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;即是升级成功，手机也会自动重启进入新系统。&lt;/p&gt;

&lt;p&gt;另外，在这个过程中所出现的错误往往和 platform-tools（包含 ADB、fastboot 等）版本过旧有关。所以遇到其他形式的报错也不用惊慌，前往 Google 官方网站 下载安装最新版本的 platform-tools 后，再次执行以上操作步骤即可。&lt;/p&gt;

&lt;p&gt;Google 从年初开始提供独立的 platform-tools 下载&lt;/p&gt;

&lt;p&gt;与非 root 系统自动更新相比，手动刷入完整版工厂镜像尽管要麻烦不少，但也更加灵活。&lt;/p&gt;

&lt;p&gt;举个例子，我的 Pixel XL 到手时的系统版本是 Android 7.1.1，但安全更新补丁停留在去年 10 月。如果采用非 root 系统自动更新的方法，那我总计需要更新五次才能更新至最新的 3 月安全更新补丁。&lt;/p&gt;

&lt;p&gt;手动 Fastboot 刷入工厂镜像则简单许多，只要我们刷入的是完整版工厂镜像，就可以无视版本跨度，一次性升级至最新版本。&lt;/p&gt;

&lt;h1 id=&quot;原生安卓wifi信号去叹号去叉教程50-android-p&quot;&gt;原生安卓WiFi信号去叹号去叉教程5.0-Android P&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;Captive Portal是安卓5引入的一种检测网络是否正常连接的机制，制作的非常有创意，通过HTTP返回的状态码是否是204来判断是否成功，如果访问得到了200带网页数据，那你就可能处在一个需要登录验证才能上网的环境里，比如说校园网，再比如说一些酒店提供的客户才能免费使用的WiFi（其实是通过DNS劫持实现的），如果连接超时（根本就连接不上）就在WiFi图标和信号图标上加一个标志，安卓5和6是叹号，安卓7改成一个叉了。只不过默认访问的是谷歌自家的验证服务器，然而由于你懂的原因，就算你连接上了网络也连不上这个服务器… 嗯…那其实还是没有连接上网络嘛… 噫….&lt;/p&gt;

  &lt;p&gt;谷歌设计了一个开关来控制是否启用这个特性，同时也提供了一个变量来控制待验证的服务器地址，国内的修改版ROM通常都改成了高通中国的地址，还有一些ROM设计了代码在重启的时候恢复这个设置，不知道是出于什么目的。&lt;/p&gt;

  &lt;p&gt;没更新7.0的时候，一直用小狐狸的叹号杀手，很不错的应用，可惜当时他已经很久不更新了，当时安卓N不能用，后来自己做了个小工具，想了想就干脆上架酷安吧，也能帮助大家，这样有了CaptiveMgr工具，这分明就是个没有名字的名字嘛…根本就是foo, bar一样…好像也没什么好叫的了？现在代码还比较乱，要是哪天有空把这堆代码整理出来就开源了算了，毕竟纯粹体力活。&lt;/p&gt;

  &lt;p&gt;具体的原理不在这里写了，这里主要写如何去掉叹号或者叉标志。&lt;/p&gt;

  &lt;p&gt;如果有root权限直接用我这个工具算了，比较方便，毕竟用命令也就是检测一下系统然后代替执行命令而已嘛。&lt;/p&gt;

  &lt;p&gt;(PS: 如果使用SS/SSR可以通过NAT模式让系统直接连接，其内部是通过iptables实现的)&lt;/p&gt;

  &lt;p&gt;如果没有root权限就得按下面操作了，做好配置以后重启WiFi和数据流量（打开再关闭飞行模式即可）就可以看到效果了。&lt;/p&gt;

  &lt;p&gt;以下需要ADB调试，配置不赘述&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
  &lt;li&gt;5.0 - 6.x教程&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;5和6还不支持HTTPS，直接修改即可&lt;/p&gt;

&lt;p&gt;检测开关相关：&lt;/p&gt;

&lt;p&gt;先处理开关状态，这个变量删除就是默认开启的，删除操作随意执行，反正没影响，删除状态下获取这个变量会返回null。&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;注意：如果关闭，则无法判断当前网络是否需要登录，无法自动弹出登录页面&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;adb shell settings delete global captive_portal_server //删除
adb shell settings put global captive_portal_server 0 //禁用
adb shell settings get global captive_portal_server  //查询状态
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;服务器地址相关：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;adb shell settings delete global captive_portal_server  //删除地址就可以恢复默认的谷歌服务器
adb shell settings put global captive_portal_server captive.v2ex.co  //设置一个可用地址（高通/V2EX都推荐）
adb shell settings get global captive_portal_server  //查询当前地址
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;7.0 - 7.1教程&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;这两个版本相比5和6没有大的更改，只是默认连接服务器的时候使用HTTPS，但是提供了一个开关用以指定是否使用HTTPS&lt;/p&gt;

&lt;p&gt;检测开关相关：同5.0 - 6.x&lt;/p&gt;

&lt;p&gt;HTTPS开关相关：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;adb shell settings delete global captive_portal_use_https  //删除（直接删除则默认使用HTTPS）
adb shell settings put global captive_portal_use_https 0  //禁用HTTPS（写1启用 写0禁用）
adb shell settings get global captive_portal_use_https  //查询HTTPS开关状态
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;服务器地址相关：（如果启用了HTTPS需要先确定地址是否支持HTTPS）同5.0 - 6.x&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;7.1.1教程&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;这个版本把HTTPS和HTTP两个地址分开保存，并通过7.0加入的HTTPS开关来控制使用哪一个地址。&lt;/p&gt;

&lt;p&gt;检测开关相关：同5.0 - 6.x&lt;/p&gt;

&lt;p&gt;HTTPS开关相关：同7.0 - 7.1&lt;/p&gt;

&lt;p&gt;服务器地址相关：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;adb shell settings delete global captive_portal_https_url  //删除（删除默认用HTTPS）
adb shell settings delete global captive_portal_http_url
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;分别修改两个地址&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;adb shell settings put global captive_portal_http_url http://captive.v2ex.co/generate_204
adb shell settings put global captive_portal_https_url https://captive.v2ex.co/generate_204
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;7.1.2教程&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;此版本服务器地址判断逻辑相比7.1.1没有更改，但是检测的开关却变了。&lt;/p&gt;

&lt;p&gt;检测开关：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#删除变量：（删除以后默认启用）&lt;/span&gt;
adb shell settings delete global captive_portal_mode
&lt;span class=&quot;c&quot;&gt;#关闭检测：&lt;/span&gt;
adb shell settings put global captive_portal_mode 0
&lt;span class=&quot;c&quot;&gt;#查看当前状态：&lt;/span&gt;
adb shell settings get global captive_portal_mode
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;服务器地址相关（同7.1.1）：&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#删除（删除默认用HTTPS）&lt;/span&gt;
adb shell settings delete global captive_portal_https_url
adb shell settings delete global captive_portal_http_url  
&lt;span class=&quot;c&quot;&gt;#分别修改两个地址&lt;/span&gt;
adb shell settings put global captive_portal_http_url http://captive.v2ex.co/generate_204
adb shell settings put global captive_portal_https_url https://captive.v2ex.co/generate_204
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;8.0.0和8.1.0和9.0(Android P)同上7.1.2，未做修改&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;隐藏导航栏和状态栏&quot;&gt;隐藏导航栏和状态栏&lt;/h1&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#全屏沉浸：&lt;/span&gt;
adb shell settings put global policy_control immersive.full&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;#沉浸状态栏：&lt;/span&gt;
adb shell settings put global policy_control immersive.status&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;#沉浸导航栏：&lt;/span&gt;
adb shell settings put global policy_control immersive.navigation&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;*&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;#单独控制某一个app不沉浸，比如以下代码设定google实时界面不沉浸，其他程序沉浸：&lt;/span&gt;
adb shell settings put global policy_control immersive.full&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;apps,-com.google.android.googlequicksearchbox

&lt;span class=&quot;c&quot;&gt;#恢复到正常方式：&lt;/span&gt;
adb shell settings put global policy_control null
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;adb-查看android手机中应用的包名和安装位置&quot;&gt;adb 查看android手机中应用的包名和安装位置&lt;/h1&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;#查看是否连接手机&lt;/span&gt;
adb devices

&lt;span class=&quot;c&quot;&gt;#进入指定的device的shell&lt;/span&gt;
adb shell
&lt;span class=&quot;c&quot;&gt;#或者&lt;/span&gt;
adb &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;*********&lt;/span&gt; shell

&lt;span class=&quot;c&quot;&gt;#adb 查看所有安装的包&lt;/span&gt;
adb shell pm list packages

&lt;span class=&quot;c&quot;&gt;#根据某个关键字查找包&lt;/span&gt;
pm list packages | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;tencent

&lt;span class=&quot;c&quot;&gt;#查看包安装位置&lt;/span&gt;
pm list packages &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;#同样可以进行筛选&lt;/span&gt;
pm list packages &lt;span class=&quot;nt&quot;&gt;-f&lt;/span&gt; | &lt;span class=&quot;nb&quot;&gt;grep &lt;/span&gt;tencent

&lt;span class=&quot;c&quot;&gt;#将apk拉到pc中&lt;/span&gt;
adb pull /data/app/com.tencent.tbs-1/base.apk ~/Downloads
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;黑阈&quot;&gt;黑阈&lt;/h1&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;adb &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; shell sh /data/data/me.piebridge.brevent/brevent.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;google-pixel-电信破解&quot;&gt;Google Pixel 电信破解&lt;/h1&gt;

&lt;blockquote&gt;
  &lt;p&gt;仅适用于一代，无需双清，无需QPST，摆脱繁琐的刷机&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;在Android Pie下测试通过，重启后不丢失&lt;/p&gt;

&lt;p&gt;开发者模式中开启 OEM 解锁后，重启手机进入 bootloader 模式，在电脑端运行 fastboot oem unlock&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;注：此过程会清除手机数据，请及时备份。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href=&quot;https://onedrive.live.com/embed?cid=A62E298A214E48C7&amp;amp;resid=A62E298A214E48C7%2125763&amp;amp;authkey=ANct6CYbGcn2HhM&quot;&gt;下载modem.img&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;刷入modem.img&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;fastboot flash modem_a modem.img
fastboot flash modem_b modem.img
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;理论上不支持移动和联通，如更换请重刷官方底包&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;注意（如果有路由器级别kexue可以忽略）&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;p&gt;你需要2018年3月或之前的系统。原因是这样的：
有一个叫frp的分区，它的全称是——Factory Reset Protection。
开机设置读取frp，得知是否首次开机。清除frp，伪装成首次开机。
不幸的是，4月的官方镜像里的开机设置没有这种操作。开机设置才不管frp呢，必须联网。
所以在恢复出厂设置前一定要看看你的安全补丁日期是哪个月的！！如果是4月的需要先刷回3月。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1 id=&quot;2021年2月21日补记&quot;&gt;2021年2月21日补记&lt;/h1&gt;

&lt;p&gt;忘记是哪一次刷机的时候&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pixel&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pixel XL&lt;/code&gt;的包搞混了，在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pixel&lt;/code&gt;上刷了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;XL&lt;/code&gt;的包，结果还能用？就是屏幕的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;最小宽度&lt;/code&gt;（可以在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;设置 -&amp;gt; 系统 -&amp;gt; 开发者选项 -&amp;gt; 绘图&lt;/code&gt; 下面更改）变了好像？&lt;/p&gt;
</content>
 </entry>
 

</feed>
