<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[RSS Feed]]></title><description><![CDATA[wuxiaobai24's blog]]></description><link>https://codeand.fun</link><generator>GatsbyJS</generator><lastBuildDate>Thu, 22 Sep 2022 01:39:18 GMT</lastBuildDate><item><title><![CDATA[2020 年终总结]]></title><description><![CDATA[现在是2021年1月1号的下午，就像每天的早晨、每周的周日、每个月的1号一样，这个时间点是适合做回顾和展望。在对旧事物的记忆消逝之前，回顾一下过去，在新事物到来之前，展望一下未来。 2020 的碎碎念 疫情在家的无聊/有聊时光 2020年的…]]></description><link>https://codeand.fun/posts/2021/01/11/from-2020-to-2021/</link><guid isPermaLink="false">https://codeand.fun/posts/2021/01/11/from-2020-to-2021/</guid><pubDate>Mon, 11 Jan 2021 13:42:33 GMT</pubDate><content:encoded>&lt;p&gt;现在是2021年1月1号的下午，就像每天的早晨、每周的周日、每个月的1号一样，这个时间点是适合做回顾和展望。在对旧事物的记忆消逝之前，回顾一下过去，在新事物到来之前，展望一下未来。&lt;/p&gt;&lt;h2&gt;2020 的碎碎念&lt;/h2&gt;&lt;h3&gt;疫情在家的无聊/有聊时光&lt;/h3&gt;&lt;p&gt;2020年的1月，刚放寒假我就溜回家里去了，本想着说早点回去过年，然后早点回学校干活的。谁知道疫情就这样悄然爆发了。因此2020年的前半年几乎都是在家里渡过的，直到7月末才回到学校。从初中开始，我似乎就没有在家呆过这么长的时间了，即使是高中毕业，也只在家呆了3个月而已。说实话是一种蛮奇怪的感觉，因为从初中住校开始，就再也没有像是在家一样过一些比较慢的生活了。周围人的生活就像车轮一样飞快的滚动起来，各种各样的考试，各种各样的人生节点，似乎一个不小心就要掉队，就要从人生的赛道上跌倒，然后再也回不去。疫情就像是公路上的减速带，突然让人像是越过减速带的车子一样在空中思考，思考着那些在地上不会思考的事情。&lt;/p&gt;&lt;p&gt;由于过年期间在家一直怀着休息一下的心情在过日子，导致在开始上网课后还是一直这样慢悠悠的生活。因为整天无所事事，导致有段时间极度无聊。人在无聊的时候就会疯狂找一些新奇的事情来满足自己，疫情在家也的确做了一些以前想做或者不想做的事情：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;日记：可能是因为在家表达欲有点旺盛，需要一个宣泄口，而我又实在不想在社交网络上记录，所以在2月多开始尝试写日记。虽然现在已经断掉了，但是竟然也记录了256天。在写这篇博客的时候还回顾了一下当时的碎碎念，想想如果当时没有记录下来，可能很多有趣的事情都会被忘记吧，希望2021年多记录一下生活。&lt;/li&gt;&lt;li&gt;读书：二月份的时候开始尝试读一些书来消磨在家的无聊时光，印象中读的第一本书应该是麦家的《人生海海》。一开始还是用微信读书来读书。用手机读的话，可以很方便的在任何地点看，任何时间看，但是对眼睛的确不好，看了一段时间后就有点受不了。加上感觉所谓的碎片化阅读对于读书其实是不太现实的，即使是小说这种偏消遣类型的书籍，都需要一个“进入书籍”的过程。所以后面就入手了一个美版的 Kindle，在网上买了一些实体书，养成了睡觉前看书的习惯。2月到5月基本上是阅读的高峰期，每个月都读了超过10本书。4月初的时候还顺势水了一篇博客（&lt;a href=&quot;https://codeand.fun/posts/2020/04/02/2020-02-03-reading/&quot;&gt;2020 02 &amp;amp; 03 Reading&lt;/a&gt;）。当时还想着按这个趋势，今年说不定可以读100本书呢，哈哈。然而随着期末的临近，读书的数量开始下降，并且在回到学校后，基本上每个月平均也就读5本左右，所有今年算下来是读完了81本书。读的小说比较多，关于技术的书籍也就6本，希望明年可以读多一点技术相关的书籍。&lt;/li&gt;&lt;li&gt;跳绳：在家虽然也能去公路上跑步，但是的确没有在学校的感觉了（晨跑实在不适合我），所以每天的运动就是下午5点左右开始的跳绳。这件事情其实是因为老乾升中考需要考跳绳，所以他每天下午都跑到楼顶去要跳绳（学校要求每天打卡，哎，现在的中学生真心累）。看他跳了几次之后，感觉这是一个在家运动的不错选择，在家人的怂恿下，就开始每天的30分钟到40分钟的跳绳。一开始跳两三个就会被绳子抽头或脚到，后来把绳子放长了才好一点。这个习惯回到学校后就停下来了，一来是感觉在楼上跳绳有点扰民，楼下跳绳有点傻逼；二来是晚上夜跑显然更舒服。（被我从家里面带过来的跳绳一直放在衣柜里没拿出来过）&lt;/li&gt;&lt;li&gt;播客：其实我想不起来我是因为什么接触到播客的了，隐约记得最开始听应该是2019年末的时候，那时听过几期 GGTalk 和几期捕蛇者说。但当时也只是突然想起或者看到感兴趣的话题才会去听。在家这段时间貌似播客也突然进入了一个爆发期的样子，每天都有有趣的播客可以听。当时是每天跳绳的时候都会带上耳机听播客，可能是因为习惯在跳绳时听播客了，所以在回到学校后，基本就没听过了。&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;回到学校后瞬息万变的生活&lt;/h3&gt;&lt;p&gt;说实话，这个学期还是发生了蛮多事情的。&lt;/p&gt;&lt;ol&gt;&lt;li&gt;我大概是在7月下旬的时候回到学校的，由于师兄师姐们都毕业了，老师又不来学校，所以暑假在学校实验室几乎是只有我一个人。同时在舍友的介绍下，还接了一个 C 语言的家教，每天早上去上3个小时的课（虽然钱收少了，但是好像也算是蛮好玩的一次体验吧）。在这种状态下，效率显然不会太高，整天在实验室划水摸鱼。&lt;/li&gt;&lt;li&gt;本来在开学老师是说让我接手廖大哥的论文的，但是在8月底的时候，黄志鸿的论文被退回来大改，所以被拉过去搞他那篇论文了。9月份和10月的前半个月基本都在弄他论文的实验，当然还穿插着烦人的报账。&lt;/li&gt;&lt;li&gt;等到实验基本搞定后，华为那边和学院签了一个项目，老师希望我能参与进去，所以在12月中旬的时候，本应该开始搞毕业论文的我又跑来华为这边打工了（BTW，等到我都已经在华为这边干活了，老师才把论文投出去）。虽说是打工，但是其实干的事情和实验室差不多，只是没像在实验室一样天天睡懒觉了而已，不过好像也不是很累。感觉这边的节奏还是比较快的，明明之前计划好要做半年的事情，现在似乎过年前就要搞定了（我对这件事情是持质疑态度的，现在的工作根本还远远不够嘛，但打工人怎敢质疑boss们的决定呢）。&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;除了上面的事情还有一些其他值得吐槽或者记录的事：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;暑期时花了好几天修复服务器上无法开机的 Linux，后来翻启动日志才发现是我 fstab 文件写的有问题，导致某个盘挂载不上。期间学会了用启动盘和 chroot 来修复坏掉的 Linux 系统。&lt;/li&gt;&lt;li&gt;由于系统编程课程需要一些虚拟机来给学生用，所以在两台 Taishan 服务器上搭建 KVM 来跑多台虚拟机，OpenEuler 的生态的确有点差，很多包都没法直接用 yum 下，而且 manual 也缺了很多东西，好在可以直接拿 CentOS 的包来装。&lt;/li&gt;&lt;li&gt;10月初修复了断电后无法开机的集群。这个当时真的是心态炸裂了，刚好在跑实验就遇上这种事。后来是不断尝试和咨询之前师兄才修复成功的。这个无法开机有很多原因，一来是这个集群开机方式有点奇特，没有接触过的人很难摸索出来；二来是跳板机主板内的电池没电了，所以得把机器拆下来换个电池上去；三是由于断电后跳板机文件系统损坏了，所以 Linux 系统启动不起来，这个只需要进入修复模式，然后用命令修复一下就好了。&lt;/li&gt;&lt;li&gt;用 DeskMini 组了一台黑苹果，入手了一个 4K 屏，换了一个适配 Mac 的蓝牙键盘。加上年初入的Kindle和618时把小米6换成了K30 Pro，今年入手的东西有点多啊。哎，万恶的消费主义啊。&lt;/li&gt;&lt;li&gt;参加了六级，哎，估计又过不了，明年继续努力吧。&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;技术与三分钟热度&lt;/h2&gt;&lt;p&gt;在家的半年，除了只想躺着和娱乐自己的咸鱼时光，当然还穿插着咸鱼后罪恶感爆棚然后下定决心要好好学习的时候啦。由于本人极其擅长三分钟热度，所以有很多东西都是接触一下，然后就弃掉了：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Flutter：日常三分钟热度，稍微接触了一下，然后就弃掉了。为啥弃掉了，没啥原因，就是三分钟热度而已。&lt;/li&gt;&lt;li&gt;6.824：MIT 的分布式计算课程，由于 2020 Spring 的课程有放出视频，所以也看了一波，看了 GFS、MapReduce和 Raft 的前一半论文，完成了第一个实验，然而后面就渐渐忘掉这门课了。。。&lt;/li&gt;&lt;li&gt;Java：在家突然产生了找不到工作的焦虑感，下定决心好好学一学后端的东西。苦思冥想后还是觉得学比较多岗位的 Java。默默买了一本《Java编程思想》后，翻了一半后就放弃了，只想躺尸。冗长的 Java 代码是在是让人受不了啊。&lt;/li&gt;&lt;li&gt;Scala &amp;amp; Spark：因为在6月份左右老师同意让我后面搞分布式计算了，让我接手廖大哥的坑。接手的时候，当然要先学一波 Scala 和 Spark 啦，所以找出了两本评价还不错的书（《Scala 实用指南》和《Spark 权威指南》）看了一下，但是都是翻到一半就放下了。这有挺多原因的，一来是后面接手黄志鸿的论文了，不需要用 Scala 和 Spark；二来是感觉的确不需要对 Scala 和 Spark 掌握太深，而且 Spark 那本书给我的感觉就是，Spark 日常使用只需要用 SQL 写就 OK 了。这也难怪大数据工程师似乎越来越不吃香了，因为一旦平台搭建起来后，后面的使用其实并不需要太多计算机的背景。&lt;/li&gt;&lt;li&gt;SQL &amp;amp; Database：这个东西怎么说呢，我好像每年都会尝试系统的学习一下，但是每次都是很快的放弃了，一直不得要领。哎，这都快成一个执念了。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;虽然大部分尝试学习的技术都没啥进展和成果，很快的就被遗忘了，但是有些东西还是有一定产出的：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;前端：尝试过 Vue 和 React ，学过 Node.js，看过 MDN 的文档和教程，在不同的 Tutorial 中反复横跳，一直不得要领，最后是在开始用 Gastby.js 做博客后感觉有点入门的感觉了，最终还是有点小收获，小成果。后来仔细想过为啥之前一直学不来前端，而用 Gatsby.js 搭建博客却能有一个比较好的进展？一来是前端的东西确实琐碎，想要做出一个东西需要用到其他很多工作或者背景知识，而我又带着一种希望系统学完某个东西的念头去学，所以导致之前一直没啥进展。后来是意识到了它的琐碎的特性，尝试用之前学 Linux 的方式去学（遇到问题再解决，没有问题就忽略，不深究其细节），才有所成果；二来是 Gatsby.js 的确是一个非常适合做（静态）博客的框架，并且文档和 Tutorial 都非常详细。现在回去看看 GitHub 的 Commit，会发现 &lt;a href=&quot;https://github.com/wuxiaobai24/aa-gatsby-blog&quot;&gt;aa-gatsby-blog&lt;/a&gt; 几乎是在一两周内就实现出来的。而且如果一开始不头铁尝试用 Tailwind.css 的话，可能会在更短的时间内搞定。虽然现在的确没法很轻松、很快速的完成一个前端项目，但的确不会再对这个东西有太多的恐惧感了（如果不涉及到 CSS 的话，哈哈哈哈）&lt;/li&gt;&lt;li&gt;LeetCode：这个东西怎么说呢，也有点三分钟热度吧。年初准备整理一下之前刷过的题，但是连一个专题都没完成就结束了。后来想每周都参加周赛，但也才参加了19场而已。不过也不是没有产出。首先是，周赛。虽然大部分时间都是200名开外，属于前三题好说，最后一天打死做不出来的状态，但是的确有次AC了第四题，并拿到了64名（就是第一次打周赛，也是因为这个，后面才会想着打的）。其次是，题解。在整理刷过的题时，发现之前用一种比较 Fancy 的方法 AC 了一道题，所以就把博客的内容转到了 LeetCode 的题解中去了（&lt;a href=&quot;https://leetcode-cn.com/problems/simplify-path/solution/yong-you-xian-zhuang-tai-ji-de-si-xiang-lai-jie-zh/&quot;&gt;用有限状态机的思想来解这道题&lt;/a&gt;），并收获了7个赞和6个收藏。最后，一年下来竟然也 AC 了85道题目，让 AC 过的题目数量达到了330。&lt;/li&gt;&lt;li&gt;Java &amp;amp; Hadoop：是的，你没看错，在上半年被放弃的 Java，在后面的9月份的时候又捡起来了。原因是因为接手的那篇论文是基于 Hadoop 做的，所以用的是 Java。因此在9月份的时候用 Java 实现了几个并行算法，并使用 perf 等东西尝试对现有算法进行了优化，还拿 Hadoop 复现了一个算法。之前一直嫌弃 Java 的我在写的时候竟然觉得“真香”了（主要是 IDEA 太好用了）。当然我也知道自己也就半瓶水，没有 Google 根本没法干活的那种。对 Hadoop 也只是写 Mapper 和 Reducer 而已。&lt;/li&gt;&lt;li&gt;Pytorch：由于12月份要去华为，所以在11末的时候，老师已经不太管我了。由于在那边是做机器学习相关的项目，所以就提前学习了一下 Pytorch（动态图真香），用Pytorch复现了一两篇论文（&lt;a href=&quot;https://github.com/wuxiaobai24/DA-RNN&quot;&gt;DA-RNN&lt;/a&gt;和&lt;a href=&quot;https://github.com/wuxiaobai24/DSANet-pytorch&quot;&gt;DSANet&lt;/a&gt;），后面这个竟然在12月31号的晚上收到了一个 Star，实在是太开心了。&lt;/li&gt;&lt;li&gt;TensorFlow：是的，事情就是那么尴尬，过去那边后他们觉得用 TensorFlow。。。所以就现学现卖的用 TensorFlow 了。嗯，TensorFlow 2 真香。&lt;/li&gt;&lt;li&gt;Blog：（这个也算是技术嘛？）Anyway，今年也写了10篇左右的博客。虽然都挺水的，但是还是希望明年可以写多一点，多记录一下生活，沉淀一下技术。&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;关于 2021&lt;/h2&gt;&lt;p&gt;2021 年可预见会发生的大事就挺多的：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;结束华为的项目：希望这件事情能够顺利吧，也希望可以在这里面水一篇论文出来作为毕业设计。&lt;/li&gt;&lt;li&gt;毕业论文开题：哎，这可能是下学期最让人头疼的事情了。&lt;/li&gt;&lt;li&gt;6月份的六级考试：emmmm，再不过的话就会影响到秋招了。&lt;/li&gt;&lt;li&gt;秋招：虽说还有春招，但是还是希望能在秋招就找到满意的工作。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;我是一个很喜欢做计划的人，但是几乎从来不会按计划做事情，所以未来的事情交给未来的我烦恼吧。&lt;/p&gt;</content:encoded></item><item><title><![CDATA[6.S081 lab2 system calls]]></title><description><![CDATA[6.S081 的第二个实验，system calls，虽然是好久之前做的了，但是一直没把它放到博客里面。今天略无聊，就弄了一下。BTW，第三个实验我到现在都还没开始呢。 system call 在完成实验之前，我们可以先了解一下系统调用的相关的代码。 首先在 user/usys…]]></description><link>https://codeand.fun/posts/2020/12/14/6s081-lab2-system-calls/</link><guid isPermaLink="false">https://codeand.fun/posts/2020/12/14/6s081-lab2-system-calls/</guid><pubDate>Mon, 14 Dec 2020 15:20:55 GMT</pubDate><content:encoded>&lt;blockquote&gt;&lt;p&gt;6.S081 的第二个实验，system calls，虽然是好久之前做的了，但是一直没把它放到博客里面。今天略无聊，就弄了一下。BTW，第三个实验我到现在都还没开始呢。&lt;/p&gt;&lt;/blockquote&gt;&lt;h2&gt;system call&lt;/h2&gt;&lt;p&gt;在完成实验之前，我们可以先了解一下系统调用的相关的代码。&lt;/p&gt;&lt;p&gt;首先在&lt;code class=&quot;language-text&quot;&gt;user/usys.pl&lt;/code&gt;中包含生成系统调用汇编的 Perl 代码，其核心为下面这段代码：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;perl&quot;&gt;&lt;pre class=&quot;language-perl&quot;&gt;&lt;code class=&quot;language-perl&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;sub&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;entry&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;my&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$name&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; shift&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;.global $name\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;${name}:\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot; li a7, SYS_${name}\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot; ecall\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot; ret\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;可以看出来这是一个创建汇编的代码，例如调用&lt;code class=&quot;language-text&quot;&gt;entry(&amp;quot;fork&amp;quot;);&lt;/code&gt;会得到一下汇编：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;fork:
 li a7, SYS_fork
 ecall
 ret&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;从&lt;code class=&quot;language-text&quot;&gt;xv6-book&lt;/code&gt;中，我们可以知道：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;ecall&lt;/code&gt;是&lt;code class=&quot;language-text&quot;&gt;rsic-v&lt;/code&gt;中用来从用户态转到特权态的指令&lt;/li&gt;&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;a7&lt;/code&gt;用来保存要调用的系统调用号。&lt;/li&gt;&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;SYS_fork&lt;/code&gt;在&lt;code class=&quot;language-text&quot;&gt;kernel/syscall.h&lt;/code&gt;中被定义。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;在&lt;code class=&quot;language-text&quot;&gt;ecall&lt;/code&gt;被调用时，RISC-V 的 CPU 会设置一些寄存器（如将&lt;code class=&quot;language-text&quot;&gt;pc&lt;/code&gt;保存在&lt;code class=&quot;language-text&quot;&gt;sepc&lt;/code&gt;），然后将&lt;code class=&quot;language-text&quot;&gt;stvec&lt;/code&gt;保存到&lt;code class=&quot;language-text&quot;&gt;pc&lt;/code&gt;中，这时，&lt;code class=&quot;language-text&quot;&gt;CPU&lt;/code&gt;就会执行&lt;code class=&quot;language-text&quot;&gt;stvec&lt;/code&gt;所指向的代码了，&lt;code class=&quot;language-text&quot;&gt;stvec&lt;/code&gt;在返回用户态时会被设置成&lt;code class=&quot;language-text&quot;&gt;kernel/trampoline.S&lt;/code&gt;中&lt;code class=&quot;language-text&quot;&gt;uservec&lt;/code&gt;（见&lt;code class=&quot;language-text&quot;&gt;kernel/trap.c#L100&lt;/code&gt;）.&lt;/p&gt;&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;uservec&lt;/code&gt;的主要做了以下几件事情：&lt;/p&gt;&lt;ol&gt;&lt;li&gt;交换&lt;code class=&quot;language-text&quot;&gt;a0&lt;/code&gt;和&lt;code class=&quot;language-text&quot;&gt;sscratch&lt;/code&gt;寄存器，而&lt;code class=&quot;language-text&quot;&gt;sscratch&lt;/code&gt;是进程用户空间的&lt;code class=&quot;language-text&quot;&gt;trapframe&lt;/code&gt;的虚拟地址，此时已经将&lt;code class=&quot;language-text&quot;&gt;a0&lt;/code&gt;保存到&lt;code class=&quot;language-text&quot;&gt;sscratch&lt;/code&gt;寄存器中了。&lt;/li&gt;&lt;li&gt;保存寄存器到&lt;code class=&quot;language-text&quot;&gt;trapframe&lt;/code&gt;中（包括&lt;code class=&quot;language-text&quot;&gt;a0&lt;/code&gt;）&lt;/li&gt;&lt;li&gt;从&lt;code class=&quot;language-text&quot;&gt;trapframe&lt;/code&gt;中恢复内核栈、切换页表&lt;/li&gt;&lt;li&gt;跳转到&lt;code class=&quot;language-text&quot;&gt;usertrap&lt;/code&gt;中&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;usertrap&lt;/code&gt;（&lt;code class=&quot;language-text&quot;&gt;kernel/trap.c#32&lt;/code&gt;）主要做了以下几件事：&lt;/p&gt;&lt;ol&gt;&lt;li&gt;检验是否从用户态进入（通过&lt;code class=&quot;language-text&quot;&gt;sstatus&lt;/code&gt;确认）。&lt;/li&gt;&lt;li&gt;设置&lt;code class=&quot;language-text&quot;&gt;stvec&lt;/code&gt;为&lt;code class=&quot;language-text&quot;&gt;kernelvec&lt;/code&gt;，保存用户态&lt;code class=&quot;language-text&quot;&gt;pc&lt;/code&gt;（在调用&lt;code class=&quot;language-text&quot;&gt;ecall&lt;/code&gt;时被保存到了&lt;code class=&quot;language-text&quot;&gt;sepc&lt;/code&gt;中了）。&lt;/li&gt;&lt;li&gt;关中断&lt;/li&gt;&lt;li&gt;执行&lt;code class=&quot;language-text&quot;&gt;syscall&lt;/code&gt;进行系统调用&lt;/li&gt;&lt;li&gt;调用&lt;code class=&quot;language-text&quot;&gt;usertrapret&lt;/code&gt;返回&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;前面的步骤已经将用户态转换成内核态，并将需要保存的信息保存到对应的位置，并将栈和页表等切换成内核所使用的栈和页表了。&lt;/p&gt;&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;syscall&lt;/code&gt;（&lt;code class=&quot;language-text&quot;&gt;kernel/syscall.c#133&lt;/code&gt;）的代码如下：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;syscall&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; num&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;proc&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;p &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;myproc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  num &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; p&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;trapframe&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;a7&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;num &lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; num &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;NELEM&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;syscalls&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; syscalls&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;num&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    p&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;trapframe&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;a0 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; syscalls&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;num&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;quot;%d %s: unknown sys call %d\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            p&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;pid&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; p&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; num&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    p&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;trapframe&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;a0 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;可以看到在&lt;code class=&quot;language-text&quot;&gt;syscall&lt;/code&gt;中，它从&lt;code class=&quot;language-text&quot;&gt;a7&lt;/code&gt;取出&lt;code class=&quot;language-text&quot;&gt;system call number&lt;/code&gt;，并调用了对应的&lt;code class=&quot;language-text&quot;&gt;handler&lt;/code&gt;，然后把返回值保存到用户态的&lt;code class=&quot;language-text&quot;&gt;a0&lt;/code&gt;中。&lt;/p&gt;&lt;p&gt;系统调用返回的过程有点像是刚才的逆过程，&lt;code class=&quot;language-text&quot;&gt;uservec&lt;/code&gt;和&lt;code class=&quot;language-text&quot;&gt;usertrap&lt;/code&gt;分别对应&lt;code class=&quot;language-text&quot;&gt;userret&lt;/code&gt;和&lt;code class=&quot;language-text&quot;&gt;usertrapret&lt;/code&gt;。这里不在赘述。&lt;/p&gt;&lt;p&gt;总结以下，当我们调用&lt;code class=&quot;language-text&quot;&gt;fork()&lt;/code&gt;时会发生的事情。&lt;/p&gt;&lt;ol&gt;&lt;li&gt;通过&lt;code class=&quot;language-text&quot;&gt;usys.pl&lt;/code&gt;生成的汇编&lt;code class=&quot;language-text&quot;&gt;fork()&lt;/code&gt;将参数放到&lt;code class=&quot;language-text&quot;&gt;a7&lt;/code&gt;中，并调用&lt;code class=&quot;language-text&quot;&gt;ecall&lt;/code&gt;&lt;/li&gt;&lt;li&gt;调用&lt;code class=&quot;language-text&quot;&gt;ecall&lt;/code&gt;时，CPU 会执行一些操作（保存用户态&lt;code class=&quot;language-text&quot;&gt;pc&lt;/code&gt;到&lt;code class=&quot;language-text&quot;&gt;sepc&lt;/code&gt;，拷贝&lt;code class=&quot;language-text&quot;&gt;stvec&lt;/code&gt;到&lt;code class=&quot;language-text&quot;&gt;pc&lt;/code&gt;中）&lt;/li&gt;&lt;li&gt;由于&lt;code class=&quot;language-text&quot;&gt;stvec&lt;/code&gt;在用户态时指向&lt;code class=&quot;language-text&quot;&gt;uservec&lt;/code&gt;，所以会执行&lt;code class=&quot;language-text&quot;&gt;uservec&lt;/code&gt;来保存寄存器、切换页表、恢复内核堆栈，并跳转到&lt;code class=&quot;language-text&quot;&gt;usertrap&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;usertrap&lt;/code&gt;会将&lt;code class=&quot;language-text&quot;&gt;stvec&lt;/code&gt;修改成&lt;code class=&quot;language-text&quot;&gt;kernelvec&lt;/code&gt;，关中断调用&lt;code class=&quot;language-text&quot;&gt;syscall&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;syscall&lt;/code&gt;会根据&lt;code class=&quot;language-text&quot;&gt;a7&lt;/code&gt;中保存的&lt;code class=&quot;language-text&quot;&gt;system call number&lt;/code&gt;来调用对应的&lt;code class=&quot;language-text&quot;&gt;handler&lt;/code&gt;，执行完后返回值保存在&lt;code class=&quot;language-text&quot;&gt;a0&lt;/code&gt;中。&lt;/li&gt;&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;usertrap&lt;/code&gt;末尾调用&lt;code class=&quot;language-text&quot;&gt;usertrapret&lt;/code&gt;，而&lt;code class=&quot;language-text&quot;&gt;usertrapret&lt;/code&gt;会跳转到&lt;code class=&quot;language-text&quot;&gt;userret&lt;/code&gt;，这两个过程会逆向&lt;code class=&quot;language-text&quot;&gt;uservec&lt;/code&gt;和&lt;code class=&quot;language-text&quot;&gt;usertrap&lt;/code&gt;的操作。&lt;/li&gt;&lt;/ol&gt;&lt;h2&gt;trace&lt;/h2&gt;&lt;p&gt;由于前面已经分析过调用系统调用的过程了，但是添加一个系统调用还是有所不同的，我们要进行以下步骤：&lt;/p&gt;&lt;ol&gt;&lt;li&gt;在&lt;code class=&quot;language-text&quot;&gt;kernel/syscall.h&lt;/code&gt;中设置系统调用号，如&lt;code class=&quot;language-text&quot;&gt;#define SYS_trace 22&lt;/code&gt;&lt;/li&gt;&lt;li&gt;在&lt;code class=&quot;language-text&quot;&gt;kernel/syscall.c&lt;/code&gt;中的&lt;code class=&quot;language-text&quot;&gt;syscalls&lt;/code&gt;数组中设置对应的 handler 函数，同时需要在该数组的上方加入相关的函数声明，如&lt;code class=&quot;language-text&quot;&gt;extern unit64 sys_trace(void);&lt;/code&gt;&lt;/li&gt;&lt;li&gt;在&lt;code class=&quot;language-text&quot;&gt;kernel/sysproc.c&lt;/code&gt;中实现对应的 handler 函数，如&lt;code class=&quot;language-text&quot;&gt;sys_trace&lt;/code&gt;函数&lt;/li&gt;&lt;li&gt;在&lt;code class=&quot;language-text&quot;&gt;user/user.h&lt;/code&gt;中添加函数声明，如&lt;code class=&quot;language-text&quot;&gt;int trace(int);&lt;/code&gt;&lt;/li&gt;&lt;li&gt;在&lt;code class=&quot;language-text&quot;&gt;user/usys.pl&lt;/code&gt;添加对应的&lt;code class=&quot;language-text&quot;&gt;entry&lt;/code&gt;已生成相应系统调用的汇编，如&lt;code class=&quot;language-text&quot;&gt;entry(&amp;quot;trace&amp;quot;);&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;添加完成后，我们可以就需要实现&lt;code class=&quot;language-text&quot;&gt;kernel/sysproc.c&lt;/code&gt;中&lt;code class=&quot;language-text&quot;&gt;sys_trace&lt;/code&gt;的实现了。&lt;/p&gt;&lt;p&gt;首先，题目要求我们能够通过&lt;code class=&quot;language-text&quot;&gt;trace&lt;/code&gt;系统调用来设置哪些系统调用会被&lt;code class=&quot;language-text&quot;&gt;trace&lt;/code&gt;，而且&lt;code class=&quot;language-text&quot;&gt;trace&lt;/code&gt;的参数也已经提示我们要用&lt;code class=&quot;language-text&quot;&gt;1 &amp;lt;&amp;lt; SYS_*&lt;/code&gt;的方式来设置&lt;code class=&quot;language-text&quot;&gt;mask&lt;/code&gt;了，&lt;code class=&quot;language-text&quot;&gt;mask&lt;/code&gt;应该由&lt;code class=&quot;language-text&quot;&gt;trace&lt;/code&gt;命令来设置。&lt;code class=&quot;language-text&quot;&gt;trace&lt;/code&gt;应该是只时对某个进程有效的，所以这个&lt;code class=&quot;language-text&quot;&gt;mask&lt;/code&gt;应该与进程绑定，所以我们可以在进程&lt;code class=&quot;language-text&quot;&gt;proc&lt;/code&gt;结构体中加入一个新的变量&lt;code class=&quot;language-text&quot;&gt;tracemask&lt;/code&gt;。然后&lt;code class=&quot;language-text&quot;&gt;sys_trace&lt;/code&gt;只需要获取用户态传入的参数，并设置进程的&lt;code class=&quot;language-text&quot;&gt;tracemask&lt;/code&gt;即可。&lt;/p&gt;&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;sys_trace&lt;/code&gt;的实现如下：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;uint64
&lt;span class=&quot;token function&quot;&gt;sys_trace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; mask&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;argint&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;mask&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;myproc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;tracemask &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; mask&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;从上面关于系统调用的分析可以知道，每个系统调用的 handler 都会由&lt;code class=&quot;language-text&quot;&gt;syscall&lt;/code&gt;来调用，所以我们可以在修改这个函数来实现每次系统调用 handler 返回后都输出对应的信息。&lt;code class=&quot;language-text&quot;&gt;pid&lt;/code&gt;和系统调用返回值都可以直接获取到，而系统调用名称则需要自己手动写一个字符串数组来映射。下面是实现代码：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;syscall&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; num&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;proc&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;p &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;myproc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  num &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; p&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;trapframe&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;a7&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;num &lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; num &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;NELEM&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;syscalls&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; syscalls&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;num&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    p&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;trapframe&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;a0 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; syscalls&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;num&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; num  &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; p&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;tracemask&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;quot;%d: syscall %s -&amp;gt; %d\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; p&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;pid&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; syscall_name&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;num&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; p&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;trapframe&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;a0&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;quot;%d %s: unknown sys call %d\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            p&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;pid&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; p&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; num&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    p&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;trapframe&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;a0 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;由于题目要求某个进程被&lt;code class=&quot;language-text&quot;&gt;trace&lt;/code&gt;后，其子进程也要被&lt;code class=&quot;language-text&quot;&gt;trace&lt;/code&gt;，所以我们只需要在&lt;code class=&quot;language-text&quot;&gt;fork&lt;/code&gt;中简单的添加&lt;code class=&quot;language-text&quot;&gt;np-&amp;gt;tracemask = p-&amp;gt;tracemask&lt;/code&gt;即可。&lt;/p&gt;&lt;h2&gt;sysinfo&lt;/h2&gt;&lt;p&gt;这里要增加一个系统调用来实现&lt;code class=&quot;language-text&quot;&gt;sysinfo&lt;/code&gt;，因为前面已经描述过给&lt;code class=&quot;language-text&quot;&gt;xv6&lt;/code&gt;增加系统调用的过程了，这里不在赘述。&lt;/p&gt;&lt;p&gt;因为&lt;code class=&quot;language-text&quot;&gt;sysinfo&lt;/code&gt;需要传入一个&lt;code class=&quot;language-text&quot;&gt;struct sysinfo&lt;/code&gt;的指针，然后通过这个指针返回一个&lt;code class=&quot;language-text&quot;&gt;struct sysinfo&lt;/code&gt;，这个结构体主要包含两个属性：&lt;code class=&quot;language-text&quot;&gt;freemem&lt;/code&gt;和&lt;code class=&quot;language-text&quot;&gt;nproc&lt;/code&gt;，即当前空闲内存和当前状态不为&lt;code class=&quot;language-text&quot;&gt;UNUSED&lt;/code&gt;的&lt;code class=&quot;language-text&quot;&gt;proc&lt;/code&gt;数量。所以这个实验主要要解决三个问题：&lt;/p&gt;&lt;ol&gt;&lt;li&gt;计算当前空闲内存大小&lt;/li&gt;&lt;li&gt;计算当前状态不为&lt;code class=&quot;language-text&quot;&gt;UNUSED&lt;/code&gt;的&lt;code class=&quot;language-text&quot;&gt;proc&lt;/code&gt;数量&lt;/li&gt;&lt;li&gt;将计算得到的值从内核态拷贝到用户态。&lt;/li&gt;&lt;/ol&gt;&lt;h3&gt;freemem&lt;/h3&gt;&lt;p&gt;在&lt;code class=&quot;language-text&quot;&gt;kernel/kalloc.c&lt;/code&gt;代码中可以看到：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;spinlock&lt;/span&gt; lock&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;freelist&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; kmem&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这里有一个全局变量&lt;code class=&quot;language-text&quot;&gt;kmem&lt;/code&gt;，她包含了一个名为&lt;code class=&quot;language-text&quot;&gt;freelist&lt;/code&gt;的链表指针和保护该链表的锁。从其他相关代码可以看出这个&lt;code class=&quot;language-text&quot;&gt;freelist&lt;/code&gt;所代表的链表是空闲页，每一个空闲页的开头都保存着下一个空闲页的位置，由于每一页的大小都是固定的，已知的（由&lt;code class=&quot;language-text&quot;&gt;PGSIZE&lt;/code&gt;确定），所以通过遍历一个&lt;code class=&quot;language-text&quot;&gt;freelist&lt;/code&gt;可以计算出空闲内存大小。这个要主要的是在遍历链表时，需要想获取锁。实现代码如下：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;uint64
&lt;span class=&quot;token function&quot;&gt;kfreemem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    uint64 size &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;run&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;r&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;acquire&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;kmem&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lock&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;r &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; kmem&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;freelist &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; r &lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; r &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; r&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        size &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; PGSIZE&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;release&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;kmem&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;lock&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; size&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3&gt;nproc&lt;/h3&gt;&lt;p&gt;从&lt;code class=&quot;language-text&quot;&gt;kernel/proc.c&lt;/code&gt;可以看出来内核中可用的&lt;code class=&quot;language-text&quot;&gt;struct proc&lt;/code&gt;是由一个数组存储的，我们可以简单的遍历这个数组，然后判断每个元素的状态是否为&lt;code class=&quot;language-text&quot;&gt;UNUSED&lt;/code&gt;，然后计数即可。代码如下：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;uint64
&lt;span class=&quot;token function&quot;&gt;nproc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    uint64 n &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;proc&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;p&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;p &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; proc&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;p &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;proc&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;NPROC&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; p&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;state &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; UNUSED&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            n&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3&gt;copyout&lt;/h3&gt;&lt;p&gt;由于&lt;code class=&quot;language-text&quot;&gt;sys_sysinfo&lt;/code&gt;系统调用读到的地址是用户态的虚拟地址，所以不能在内核直接使用，&lt;code class=&quot;language-text&quot;&gt;copyout&lt;/code&gt;函数来将内存中的数据拷贝到用户态。从实验给出的提示可以看出，可以从参考&lt;code class=&quot;language-text&quot;&gt;sys_fstat&lt;/code&gt;和&lt;code class=&quot;language-text&quot;&gt;filestat&lt;/code&gt;来使用&lt;code class=&quot;language-text&quot;&gt;copyout&lt;/code&gt;。由于&lt;code class=&quot;language-text&quot;&gt;sys_fstat&lt;/code&gt;只涉及到读取参数和调用&lt;code class=&quot;language-text&quot;&gt;filestat&lt;/code&gt;，所以这里只给出&lt;code class=&quot;language-text&quot;&gt;filestat&lt;/code&gt;的代码，它的第二个参数就是用户态的地址。&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Get metadata about file f.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// addr is a user virtual address, pointing to a struct stat.&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;filestat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;f&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; uint64 addr&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;proc&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;p &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;myproc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;stat&lt;/span&gt; st&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;f&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;type &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; FD_INODE &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; f&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;type &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; FD_DEVICE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;ilock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;f&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;ip&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;stati&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;f&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;ip&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;st&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;iunlock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;f&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;ip&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;copyout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;pagetable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; addr&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;st&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;st&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;上面的代码关键在于&lt;code class=&quot;language-text&quot;&gt;copyout(p-&amp;gt;pagetable, add, (char*)&amp;amp;st, sizeof(st))&lt;/code&gt;，这里可以看出&lt;code class=&quot;language-text&quot;&gt;copyout&lt;/code&gt;是通过进程的页表来计算实地址的位置。&lt;/p&gt;&lt;p&gt;因此，我们可以写出&lt;code class=&quot;language-text&quot;&gt;sys_sysinfo&lt;/code&gt;的代码如下：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;uint64
&lt;span class=&quot;token function&quot;&gt;sys_sysinfo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;sysinfo&lt;/span&gt; info&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;proc&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;p &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;myproc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    uint64 pinfo&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;argaddr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;pinfo&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    info&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;freemem &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;kfreemem&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    info&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;nproc &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;nproc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;


    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;copyout&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;pagetable&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pinfo&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;info&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;info&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[6.S081 laba1 util]]></title><description><![CDATA[最近在看 6.S081 的实验，希望这次别半途而废吧。 sleep 简单的解析命令行参数，然后调用 user.h 里面 sleep 函数即可。这道题应该只是让人熟悉一下环境。 记得要修改 Markfile 来编译 sleep 命令。 ./grade-lab-util sleep…]]></description><link>https://codeand.fun/posts/2020/11/20/6s081-lab1-util/</link><guid isPermaLink="false">https://codeand.fun/posts/2020/11/20/6s081-lab1-util/</guid><pubDate>Fri, 20 Nov 2020 21:09:55 GMT</pubDate><content:encoded>&lt;blockquote&gt;&lt;p&gt;最近在看&lt;a href=&quot;https://pdos.csail.mit.edu/6.828/2020/&quot;&gt;6.S081&lt;/a&gt;的实验，希望这次别半途而废吧。&lt;/p&gt;&lt;/blockquote&gt;&lt;h2&gt;sleep&lt;/h2&gt;&lt;p&gt;简单的解析命令行参数，然后调用&lt;code class=&quot;language-text&quot;&gt;user.h&lt;/code&gt;里面&lt;code class=&quot;language-text&quot;&gt;sleep&lt;/code&gt;函数即可。这道题应该只是让人熟悉一下环境。&lt;/p&gt;&lt;ul&gt;&lt;li&gt;记得要修改&lt;code class=&quot;language-text&quot;&gt;Markfile&lt;/code&gt;来编译 sleep 命令。&lt;/li&gt;&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;./grade-lab-util sleep&lt;/code&gt;可以快速的运行测试。&lt;/li&gt;&lt;/ul&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;kernel/types.h&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;kernel/stat.h&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;user/user.h&amp;quot;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; argc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;argc &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;usage: sleep ticks\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; ticks &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;atoi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ticks&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token function&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2&gt;pingpong&lt;/h2&gt;&lt;p&gt;这一题要实现通过&lt;code class=&quot;language-text&quot;&gt;pipe&lt;/code&gt;的进程间通信，虽然只是简单的&lt;code class=&quot;language-text&quot;&gt;pingpong&lt;/code&gt;。但也有需要注意的点：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;因为两个进程需要相互发信息，所以需要两个&lt;code class=&quot;language-text&quot;&gt;pipe&lt;/code&gt;，如果只有一个&lt;code class=&quot;language-text&quot;&gt;pipe&lt;/code&gt;的话，第一个进程向&lt;code class=&quot;language-text&quot;&gt;pipe&lt;/code&gt;写完后，需要读取第二个进程发过来的&lt;code class=&quot;language-text&quot;&gt;pong&lt;/code&gt;，这时就会出现两个进程同时读管道的情况，进而导致&lt;/li&gt;&lt;/ul&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;kernel/types.h&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;kernel/stat.h&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;user/user.h&amp;quot;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; argc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; fds1&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; fds2&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fds1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;make pipe fail.\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fds2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;make pipe fail.\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; byte1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&amp;#x27;1&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; byte2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&amp;#x27;2&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; temp&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; pid &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fork&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pid &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;fork fail\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pid &lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// parent&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fds1&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;byte1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fds2&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;temp&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;temp &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&amp;#x27;2&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;quot;%d: received pong\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getpid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
		&lt;span class=&quot;token function&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// child&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fds1&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;temp&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;temp &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&amp;#x27;1&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;quot;%d: received ping\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getpid&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fds2&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;byte2&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;token function&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2&gt;primes&lt;/h2&gt;&lt;p&gt;这道题是想让我们用&lt;code class=&quot;language-text&quot;&gt;pipe&lt;/code&gt;和&lt;code class=&quot;language-text&quot;&gt;fork&lt;/code&gt;来实现一个&lt;code class=&quot;language-text&quot;&gt;CSP&lt;/code&gt;风格的程序，从给出的&lt;a href=&quot;https://swtch.com/~rsc/thread/&quot;&gt;链接&lt;/a&gt;可以找到要是程序的核心伪代码和图例：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;p = get a number from left neighbor
print p
loop:
    n = get a number from left neighbor
    if (p does not divide n)
        send n to right neighbor&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;img src=&quot;https://imagehosting.wuxiaobai24.fun/blog1605488797128.png&quot; alt=&quot;primes&quot;/&gt;&lt;/p&gt;&lt;p&gt;简单来讲就是，第一个进程先创建一个子进程，并使用管道和子进程通信，然后父进程向管道写入&lt;code class=&quot;language-text&quot;&gt;2&lt;/code&gt;到&lt;code class=&quot;language-text&quot;&gt;35&lt;/code&gt;的数字。子进程执行下面操作：&lt;/p&gt;&lt;ol&gt;&lt;li&gt;从与父进程之间的管道读取数字&lt;/li&gt;&lt;li&gt;如果没读到（&lt;code class=&quot;language-text&quot;&gt;read&lt;/code&gt;返回&lt;code class=&quot;language-text&quot;&gt;0&lt;/code&gt;），则退出&lt;/li&gt;&lt;li&gt;如果读到了，则输出该数字&lt;code class=&quot;language-text&quot;&gt;p&lt;/code&gt;，并创建新的子进程，同时创建与新进程间的管道，子进程跳转到&lt;code class=&quot;language-text&quot;&gt;1&lt;/code&gt;。&lt;/li&gt;&lt;li&gt;从与父进程之间的管道读取数字&lt;code class=&quot;language-text&quot;&gt;n&lt;/code&gt;，并判断&lt;code class=&quot;language-text&quot;&gt;n&lt;/code&gt;是否能够被&lt;code class=&quot;language-text&quot;&gt;p&lt;/code&gt;整除，如果不能则向与子进程的管道中写入该数字。当读不到数字时就退出。&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;上面的流程其实没有提及到管道的关闭和父进程的&lt;code class=&quot;language-text&quot;&gt;wait&lt;/code&gt;操作，但是这些对于程序的正确性是非常重要的，如果没有及时关闭不必要的读端和写端，会导致操作系统文件描述符耗尽，从而创建管道失败。而如果父进程在结束前没有&lt;code class=&quot;language-text&quot;&gt;wait&lt;/code&gt;的话，会导致子进程的输出与&lt;code class=&quot;language-text&quot;&gt;shell&lt;/code&gt;的输出混在一起。&lt;/p&gt;&lt;p&gt;实现代码如下：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;kernel/types.h&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;kernel/stat.h&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;user.h&amp;quot;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; argc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; fds&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; pid&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; readfd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; writefd&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; p&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fds&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;make pipe fail\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    pid &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fork&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pid &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;fork fail\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pid&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// parent&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fds&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// close read&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;35&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fds&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fds&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;token comment&quot;&gt;// child&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fds&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        readfd &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; fds&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        res &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;readfd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;p&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;res &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;readfd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fds&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;make pipe fail&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        pid &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fork&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pid &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;fork fail\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pid&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;// parent&lt;/span&gt;
            writefd &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; fds&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fds&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            
            &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;quot;prime %d\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; p&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;readfd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;%&lt;/span&gt; p&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;token function&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;writefd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;readfd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;writefd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2&gt;find&lt;/h2&gt;&lt;p&gt;这道题要求实现一个简易的&lt;code class=&quot;language-text&quot;&gt;find&lt;/code&gt;命令，虽然看上去听复杂的，但是基本上将&lt;code class=&quot;language-text&quot;&gt;ls&lt;/code&gt;里面的代码修改一下即可搞定。&lt;/p&gt;&lt;p&gt;所以我们可以先分析一下&lt;code class=&quot;language-text&quot;&gt;user/ls.c&lt;/code&gt;的代码，这个程序的核心在于&lt;code class=&quot;language-text&quot;&gt;ls&lt;/code&gt;函数中的实现，所以我们只看这个即可。&lt;/p&gt;&lt;h3&gt;ls 的实现&lt;/h3&gt;&lt;p&gt;首先是用&lt;code class=&quot;language-text&quot;&gt;open&lt;/code&gt;打开给定路径，然后用&lt;code class=&quot;language-text&quot;&gt;fstat&lt;/code&gt;来获取文件的一下属性：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fd &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;ls: cannot open %s\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; path&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fstat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;st&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;ls: cannot stat %s\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; path&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;其中&lt;code class=&quot;language-text&quot;&gt;st&lt;/code&gt;是一个&lt;code class=&quot;language-text&quot;&gt;struct stat&lt;/code&gt;类型的变量，它的定义可以在&lt;code class=&quot;language-text&quot;&gt;kernel/stat.h&lt;/code&gt;中找到：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;T_DIR&lt;/span&gt;     &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;   &lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// Directory&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;T_FILE&lt;/span&gt;    &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;   &lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// File&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;T_DEVICE&lt;/span&gt;  &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;   &lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// Device&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;stat&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; dev&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;     &lt;span class=&quot;token comment&quot;&gt;// File system&amp;#x27;s disk device&lt;/span&gt;
  uint ino&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// Inode number&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;short&lt;/span&gt; type&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// Type of file&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;short&lt;/span&gt; nlink&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Number of links to file&lt;/span&gt;
  uint64 size&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Size of file in bytes&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;从&lt;code class=&quot;language-text&quot;&gt;stat&lt;/code&gt;中我们可以获取到文件类型，通过这个我们就可以来判断当前打开的是目录还是文件了，如果是文件则输出文件信息，如果是目录则解析目录中所包含的文件，并逐个输出文件信息，解析目录的代码如下：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;strlen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; DIRSIZ &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt; buf&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;quot;ls: path too long\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;strcpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buf&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; path&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
p &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; buf&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;strlen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buf&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&amp;#x27;/&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;de&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;de&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;de&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;de&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;inum &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;memmove&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;p&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; de&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DIRSIZ&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  p&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;DIRSIZ&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buf&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;st&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;quot;ls: cannot stat %s\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; buf&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;quot;%s %d %d %d\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fmtname&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buf&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; st&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;type&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; st&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ino&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; st&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;size&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;上面的代码的核心在于通过&lt;code class=&quot;language-text&quot;&gt;while&lt;/code&gt;循环来从目录的文件描述符中读取目录项，目录项的是一个&lt;code class=&quot;language-text&quot;&gt;struct dirent&lt;/code&gt;结构体，可以从&lt;code class=&quot;language-text&quot;&gt;kernel/fs.h&lt;/code&gt;找到相关的定义：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;DIRSIZ&lt;/span&gt; &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token number&quot;&gt;14&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;dirent&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
   ushort inum&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
   &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;DIRSIZ&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;其中&lt;code class=&quot;language-text&quot;&gt;inum&lt;/code&gt;是&lt;code class=&quot;language-text&quot;&gt;inode&lt;/code&gt;编号。&lt;/p&gt;&lt;h3&gt;find 实现&lt;/h3&gt;&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;find&lt;/code&gt;和&lt;code class=&quot;language-text&quot;&gt;ls&lt;/code&gt;的实现基本一致，区别点在于：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;当打开的是文件时，需要与输入&lt;code class=&quot;language-text&quot;&gt;pattern&lt;/code&gt;进行比较，来决定是否输出&lt;/li&gt;&lt;li&gt;当打开的是目录时，需要递归调用&lt;code class=&quot;language-text&quot;&gt;find&lt;/code&gt;函数&lt;/li&gt;&lt;li&gt;由于与&lt;code class=&quot;language-text&quot;&gt;pattern&lt;/code&gt;进行比较是文件名，而不是路径，所以为了简便，find 的三个参数分别为&lt;code class=&quot;language-text&quot;&gt;path&lt;/code&gt;，&lt;code class=&quot;language-text&quot;&gt;filename&lt;/code&gt;，&lt;code class=&quot;language-text&quot;&gt;pattern&lt;/code&gt;。&lt;/li&gt;&lt;/ul&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;kernel/types.h&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;kernel/stat.h&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;user.h&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;kernel/fs.h&amp;quot;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;filename&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;pattern&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; fd&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; buf&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;512&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;p&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;stat&lt;/span&gt; st&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;dirent&lt;/span&gt; de&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fd &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;find: cannot open %s\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; path&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;fstat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;st&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;find: cannot stst %s\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; path&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;st&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;type&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; T_FILE&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;strcmp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;filename&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pattern&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;quot;%s\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; path&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; T_DIR&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;strlen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;path&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; DIRSIZ &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt; buf&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;quot;find: path too long\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;strcpy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buf&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; path&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            p &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; buf &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;strlen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buf&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&amp;#x27;/&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;de&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;de&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;de&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;de&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;inum &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;token keyword&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;strcmp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;de&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;.&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;strcmp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;de&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;..&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;token keyword&quot;&gt;continue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                &lt;span class=&quot;token function&quot;&gt;memmove&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;p&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; de&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; DIRSIZ&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                p&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;DIRSIZ&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;buf&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; de&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pattern&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; 
&lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; argc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;argc &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;usage: find &amp;lt;path&amp;gt; &amp;lt;pattern&amp;gt;\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2&gt;xargs&lt;/h2&gt;&lt;p&gt;在解决这道题前，我们先了解一下&lt;code class=&quot;language-text&quot;&gt;xargs&lt;/code&gt;的使用。&lt;/p&gt;&lt;h3&gt;xargs 基本使用&lt;/h3&gt;&lt;p&gt;我们知道在&lt;code class=&quot;language-text&quot;&gt;shell&lt;/code&gt;中可以使用&lt;code class=&quot;language-text&quot;&gt;|&lt;/code&gt;将两个命令的输出和输入连接在一起，比如说&lt;code class=&quot;language-text&quot;&gt;cat text.txt | more&lt;/code&gt;，这可以让我们将多个简单的程序连接在一起实现复杂的功能。而有时候，我们希望将第一个命令的输出作为第二个命令的命令行参数来调用。比如说我们有一个文件&lt;code class=&quot;language-text&quot;&gt;cmd.txt&lt;/code&gt;包含以下内容：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;echo
ls&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;我们希望用&lt;code class=&quot;language-text&quot;&gt;which&lt;/code&gt;命令来查询&lt;code class=&quot;language-text&quot;&gt;cmd.txt&lt;/code&gt;中每行命令所在的路径。如果我们直接通过&lt;code class=&quot;language-text&quot;&gt;|&lt;/code&gt;来连接&lt;code class=&quot;language-text&quot;&gt;cat cmd.txt&lt;/code&gt;和&lt;code class=&quot;language-text&quot;&gt;which&lt;/code&gt;的话，会没有任何输出，这是因为&lt;code class=&quot;language-text&quot;&gt;which&lt;/code&gt;命令是从命令行参数中读取要查询的命令名，而不是从标准输入中读取。这种时候，我们就可以用&lt;code class=&quot;language-text&quot;&gt;xargs&lt;/code&gt;来将标准输入转化为命令行参数了：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# wuxiaobai24 @ wuxiaobai24-pc in ~/code/6.828/xv6-labs-2020 on git:util x [15:56:08] &lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;cat&lt;/span&gt; cmd.txt
&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# wuxiaobai24 @ wuxiaobai24-pc in ~/code/6.828/xv6-labs-2020 on git:util x [15:56:13] &lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;cat&lt;/span&gt; cmd.txt &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;which&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# wuxiaobai24 @ wuxiaobai24-pc in ~/code/6.828/xv6-labs-2020 on git:util x [15:56:18] C:1&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;cat&lt;/span&gt; cmd.txt &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;xargs&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;which&lt;/span&gt;
/usr/bin/echo
/usr/bin/ls
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;xargs 的使用格式&lt;code class=&quot;language-text&quot;&gt;xargs [options] [command [initial-arguments]]&lt;/code&gt;&lt;/p&gt;&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;echo &amp;quot;world\nos&amp;quot; | xargs echo hello&lt;/code&gt; 会被转化成&lt;code class=&quot;language-text&quot;&gt;echo hello world&lt;/code&gt;和&lt;code class=&quot;language-text&quot;&gt;echo hello os&lt;/code&gt;来执行。&lt;/p&gt;&lt;h3&gt;xargs&lt;/h3&gt;&lt;p&gt;因为题目给出了这里的&lt;code class=&quot;language-text&quot;&gt;xargs&lt;/code&gt;是类似于&lt;code class=&quot;language-text&quot;&gt;xargs -n 1&lt;/code&gt;的执行效果就好了，这其实就降低了难度了，因为它其实限制了&lt;code class=&quot;language-text&quot;&gt;xargs&lt;/code&gt;一次只会传入一个参数，我们逐字符读取输入，然后判断是否为&lt;code class=&quot;language-text&quot;&gt;\n&lt;/code&gt;，如果不是就将该字符暂存，如果是就将这之前保存字符串添加到原本命令行参数的后面，并调用&lt;code class=&quot;language-text&quot;&gt;fork&lt;/code&gt;和&lt;code class=&quot;language-text&quot;&gt;exec&lt;/code&gt;执行即可。&lt;/p&gt;&lt;p&gt;但是其实正常&lt;code class=&quot;language-text&quot;&gt;xargs&lt;/code&gt;好像也没太大问题，即支持一行中有多个参数，只是需要在解析时考虑多一个&lt;code class=&quot;language-text&quot;&gt; &lt;/code&gt;和&lt;code class=&quot;language-text&quot;&gt;\t&lt;/code&gt;即可。&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;kernel/types.h&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;kernel/stat.h&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;kernel/param.h&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;user.h&amp;quot;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; argc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cmdLen&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;cmd&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;MAXARG&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; buf&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;512&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;argc &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;usage: xargs &amp;lt;command&amp;gt;\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    cmdLen &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        cmd&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cmdLen&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    cmd&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cmdLen&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; buf&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;switch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&amp;#x27; &amp;#x27;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&amp;#x27;\t&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
                buf&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&amp;#x27;\0&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                cmd&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;cmdLen&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; buf &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; i&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&amp;#x27;\n&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
                cmd&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;cmdLen&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                buf&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&amp;#x27;\0&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; pid &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;fork&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pid &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;token function&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;xargs: fork fail\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                    &lt;span class=&quot;token function&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pid &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;token comment&quot;&gt;// child&lt;/span&gt;
                    &lt;span class=&quot;token function&quot;&gt;exec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cmd&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; cmd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
                &lt;span class=&quot;token function&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                cmdLen &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; argc &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                cmd&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;cmdLen&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; buf&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
                buf&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2&gt;uptime&lt;/h2&gt;&lt;p&gt;貌似是只需要调用&lt;code class=&quot;language-text&quot;&gt;uptime&lt;/code&gt;的返回值即可？&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;kernel/types.h&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;kernel/stat.h&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;user.h&amp;quot;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; 
&lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; argc&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;argv&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; ticks &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;uptime&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;quot;%d\n&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; ticks&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;exit&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2&gt;grep with regular expressions&lt;/h2&gt;&lt;p&gt;因为给出了提示，在&lt;code class=&quot;language-text&quot;&gt;user/grep.c&lt;/code&gt;里面有关于正则表达式的代码，所以可以直接把那部分代码拷贝过来，然后将&lt;code class=&quot;language-text&quot;&gt;strcmp&lt;/code&gt;修改成对应的&lt;code class=&quot;language-text&quot;&gt;match&lt;/code&gt;即可。&lt;/p&gt;&lt;p&gt;正则表达式&lt;code class=&quot;language-text&quot;&gt;match&lt;/code&gt;代码实现如下：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Regexp matcher from Kernighan &amp;amp; Pike,&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// The Practice of Programming, Chapter 9.&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;matchhere&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;matchstar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;re&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;re&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&amp;#x27;^&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;matchhere&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;re&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// must look at empty string&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;matchhere&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;re&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;text&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&amp;#x27;\0&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// matchhere: search for re at beginning of text&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;matchhere&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;re&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;re&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&amp;#x27;\0&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;re&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&amp;#x27;*&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;matchstar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;re&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; re&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;re&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&amp;#x27;$&amp;#x27;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; re&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&amp;#x27;\0&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;text &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token char&quot;&gt;&amp;#x27;\0&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;text&lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;token char&quot;&gt;&amp;#x27;\0&amp;#x27;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;re&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;token char&quot;&gt;&amp;#x27;.&amp;#x27;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; re&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;matchhere&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;re&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; text&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// matchstar: search for c*re at beginning of text&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;matchstar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; c&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;re&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// a * matches zero or more instances&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;matchhere&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;re&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; text&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;text&lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt;&lt;span class=&quot;token char&quot;&gt;&amp;#x27;\0&amp;#x27;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;text&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt;c &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; c&lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;token char&quot;&gt;&amp;#x27;.&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2&gt;sh&lt;/h2&gt;&lt;h3&gt;not print $ when processing shell command from a file&lt;/h3&gt;&lt;p&gt;一开始挺懵的，要判断&lt;code class=&quot;language-text&quot;&gt;sh&lt;/code&gt;的输入是否从文件中来，后来发现它提供了一个&lt;code class=&quot;language-text&quot;&gt;fstat&lt;/code&gt;的系统调用，函数头为&lt;code class=&quot;language-text&quot;&gt;int fstat(int fd, struct stat*)&lt;/code&gt;，而这里的&lt;code class=&quot;language-text&quot;&gt;struct stat&lt;/code&gt;可以从&lt;code class=&quot;language-text&quot;&gt;kernel/stat.h&lt;/code&gt;中找到：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;T_DIR&lt;/span&gt;     &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;   &lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// Directory&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;T_FILE&lt;/span&gt;    &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;   &lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// File&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token macro property&quot;&gt;&lt;span class=&quot;token directive-hash&quot;&gt;#&lt;/span&gt;&lt;span class=&quot;token directive keyword&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;token macro-name&quot;&gt;T_DEVICE&lt;/span&gt;  &lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;   &lt;/span&gt;&lt;span class=&quot;token comment&quot;&gt;// Device&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;stat&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; dev&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;     &lt;span class=&quot;token comment&quot;&gt;// File system&amp;#x27;s disk device&lt;/span&gt;
  uint ino&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;    &lt;span class=&quot;token comment&quot;&gt;// Inode number&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;short&lt;/span&gt; type&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// Type of file&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;short&lt;/span&gt; nlink&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Number of links to file&lt;/span&gt;
  uint64 size&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// Size of file in bytes&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;通过&lt;code class=&quot;language-text&quot;&gt;fstat&lt;/code&gt;，我们可以判断一个文件描述符是否为设备，而从&lt;code class=&quot;language-text&quot;&gt;user/init.c&lt;/code&gt;中可以看到&lt;code class=&quot;language-text&quot;&gt;sh&lt;/code&gt;的标准输入正式从设备&lt;code class=&quot;language-text&quot;&gt;console&lt;/code&gt;中来的，所以我们在&lt;code class=&quot;language-text&quot;&gt;sh&lt;/code&gt;程序的开始判断一次即可。如果是终端，则每次&lt;code class=&quot;language-text&quot;&gt;getcmd&lt;/code&gt;都输出&lt;code class=&quot;language-text&quot;&gt;$ &lt;/code&gt;，如果不是，则每次都不输出。&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; cmdFromConsole&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// check whether cmd from console&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;getcmd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;buf&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; nbuf&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cmdFromConsole&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;$ &amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;//....&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;//....&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;fstat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;st&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  cmdFromConsole &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;st&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;type &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; T_DEVICE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[ST-MVL: Filling Missing Values in Geo-sensory Time Series Data]]></title><description><![CDATA[这篇文章发表在 IJCAI 2016 上。 解决的问题：如何在 Geo-sensory Time Series 上进行缺失值填充？ 主要的idea：结合 IDW，SES，ICF 和 UCF 四种方法提出一种 Multi-View learning based…]]></description><link>https://codeand.fun/posts/2020/11/09/st-mvl/</link><guid isPermaLink="false">https://codeand.fun/posts/2020/11/09/st-mvl/</guid><pubDate>Mon, 09 Nov 2020 21:09:55 GMT</pubDate><content:encoded>&lt;blockquote&gt;&lt;p&gt;这篇文章发表在 IJCAI 2016 上。&lt;/p&gt;&lt;p&gt;解决的问题：如何在&lt;code class=&quot;language-text&quot;&gt;Geo-sensory Time Series&lt;/code&gt;上进行缺失值填充？&lt;/p&gt;&lt;p&gt;主要的idea：结合 IDW，SES，ICF 和 UCF 四种方法提出一种&lt;code class=&quot;language-text&quot;&gt;Multi-View learning based&lt;/code&gt;的方法来进行缺失值填充。&lt;/p&gt;&lt;/blockquote&gt;&lt;h2&gt;Introduction&lt;/h2&gt;&lt;h3&gt;为什么需要&lt;code class=&quot;language-text&quot;&gt;Filling Missing Values&lt;/code&gt;&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;为了监测环境（如空气质量、天气），大量的传感器被部署在不同的地方，进而产生了大量的&lt;code class=&quot;language-text&quot;&gt;Geo-sensory Time Series&lt;/code&gt;数据。&lt;/li&gt;&lt;li&gt;由于传感器故障和网络传输故障等原因，&lt;code class=&quot;language-text&quot;&gt;Geo-sensory Time Series&lt;/code&gt;数据往往存在大量的缺失：&lt;ul&gt;&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Block missing&lt;/code&gt;包含&lt;ul&gt;&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Spatial block missing&lt;/code&gt;：所有传感器的读数同时缺失。&lt;/li&gt;&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;temporal block missing&lt;/code&gt;：某个传感器的读数在一段时间（时间长度由&lt;span class=&quot;math math-inline&quot;&gt;w&lt;/span&gt;给定)内出现缺失&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;2014/05/01 - 2015/04/30 Beijing
&lt;img src=&quot;https://imagehosting.wuxiaobai24.fun/blogimage-20191109131216066.png&quot; alt=&quot;image-20191109131216066&quot;/&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Challenge&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Readings （仪表读数） can &lt;strong&gt;be absent at arbitrary sensors and timestamps&lt;/strong&gt;.  &lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;同时可能会出现&lt;code class=&quot;language-text&quot;&gt;block missing&lt;/code&gt;（如下图 t2 时刻所有传感器都出现了缺失），这种情况某些方法是无法处理的（比如非负矩阵分解  non-negative matrix factorization NMF)&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://imagehosting.wuxiaobai24.fun/blogimage-20191108124559467.png&quot; alt=&quot;image-20191108124559467&quot;/&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Affected by &lt;strong&gt;multiple complex factors&lt;/strong&gt;, sensor readings change over location and time significantly and non-linearly。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;对于某个传感器的读数来说，相隔比较的远的传感器的读数可能会比相隔比较近的传感器的读数对于当前传感器更加相近，如下图，相比于S3，S1和S2更近，但是S2和S3的AQI变化却更加相似。&lt;/p&gt;&lt;p&gt;  &lt;img src=&quot;https://imagehosting.wuxiaobai24.fun/blogimage-20191108125704233.png&quot; alt=&quot;image-20191108125704233&quot;/&gt;&lt;/p&gt;&lt;p&gt;  &lt;img src=&quot;https://imagehosting.wuxiaobai24.fun/blogimage-20191108125715828.png&quot; alt=&quot;image-20191108125715828&quot;/&gt;&lt;/p&gt;&lt;h3&gt;Contribution&lt;/h3&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;ST-MVL simultaneously considers 1) the &lt;strong&gt;spatial correlation&lt;/strong&gt; between different time series and 2) the &lt;strong&gt;temporal correlation&lt;/strong&gt; between readings at different timestamps in the same series, to generate a more accurate estimate.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;ST-MVL integrates the advantages of &lt;strong&gt;global views&lt;/strong&gt;, i.e. empirical models derived from the data over a long period, and those of &lt;strong&gt;local views&lt;/strong&gt;, i.e. data-driven algorithms that are concerned with recent readings, to achieve better accuracy.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;ST-MVL can &lt;strong&gt;handle the block missing problem&lt;/strong&gt;, combining the four views in a multi-view learning&lt;/p&gt;&lt;p&gt;framework.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;We evaluate our method using Beijing air quality and meteorological data. The results demonstrate the advantages of our method compared with ten baselines.  &lt;/p&gt;&lt;h2&gt;Overview&lt;/h2&gt;&lt;h3&gt;Problem Definition&lt;/h3&gt;&lt;blockquote&gt;&lt;p&gt;由于作者没有显式的提出&lt;code class=&quot;language-text&quot;&gt;Problem Definition&lt;/code&gt;，所以这里只是简单描述一下问题。&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;假设有&lt;code class=&quot;language-text&quot;&gt;m&lt;/code&gt;个传感器（记录的都是同一种数据，如PM2.5），其分别记录了长度为&lt;code class=&quot;language-text&quot;&gt;n&lt;/code&gt;的时间序列，我们可以将其表示成一个矩阵（如下图），第 i 行表示第 i 个传感器的所记录的时间序列，第 j 列表示 j 时刻所有传感器所记录的值，&lt;span class=&quot;math math-inline&quot;&gt;v_{i,j}&lt;/span&gt;表示第 i 个传感器第 j 时刻的读数。下图中&lt;span class=&quot;math math-inline&quot;&gt;v_{2,j}&lt;/span&gt;和&lt;span class=&quot;math math-inline&quot;&gt;v_{1,j+1}&lt;/span&gt;是缺失值，我们的问题就是利用已有的信息来填充缺失值，使其尽量与真实值接近。&lt;strong&gt;注意：这里不同的传感器只是在不同地方而已，它们记录的是同一种数据，例如都是记录PM2.5或都是记录空气湿度。&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://imagehosting.wuxiaobai24.fun/blogimage-20191108130334083.png&quot; alt=&quot;image-20191108130334083&quot;/&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Multi View&lt;/h3&gt;&lt;p&gt;对于相似度计算这个问题，我们可以通过不同的&lt;code class=&quot;language-text&quot;&gt;view&lt;/code&gt;/角度进行分析。&lt;code class=&quot;language-text&quot;&gt;view&lt;/code&gt;可以以下两种方式进行划分：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;利用同一空间维度还是同一时间维度上的信息：&lt;ul&gt;&lt;li&gt;&lt;strong&gt;spatial view&lt;/strong&gt;：利用同一时刻空间上相邻的传感器的值去估计缺失值 &lt;/li&gt;&lt;li&gt;&lt;strong&gt;temporal view&lt;/strong&gt;：利用同一传感器相邻时刻的值去估计缺失值&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;利用全部数据还是部分数据（这里特制是否只使用一段时间内的数据）&lt;ul&gt;&lt;li&gt;&lt;strong&gt;global view&lt;/strong&gt;：考虑所有时刻的数据去估计缺失值&lt;/li&gt;&lt;li&gt;&lt;strong&gt;local view&lt;/strong&gt;：考虑一个时间段内去估计缺失值&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;这一部分可以接合上面那张图来理解。&lt;/p&gt;&lt;h3&gt;Framework&lt;/h3&gt;&lt;blockquote&gt;&lt;p&gt;以下描述不是原文内容，但是将文中所使用的的方法统一到该框架下，有助于理解。&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;对于缺失值填充这个问题来说，我们可以把大部分方法（起码这篇文章所用到四个方法都可以）归结到同一个框架上去。&lt;/p&gt;&lt;p&gt;我们有&lt;span class=&quot;math math-inline&quot;&gt;n&lt;/span&gt;个已知值&lt;span class=&quot;math math-inline&quot;&gt;v_1,v_2,v_3,...,v_n&lt;/span&gt;和一个缺失值&lt;span class=&quot;math math-inline&quot;&gt;u&lt;/span&gt;，我们认为缺失值可以通过已知值的加权求和来进行预估，因此可以通过下面的公式对缺失值&lt;span class=&quot;math math-inline&quot;&gt;u&lt;/span&gt;进行估计：&lt;/p&gt;&lt;div class=&quot;math math-display&quot;&gt;u=\sum_{i=1}^n{w_i*v_i}&lt;/div&gt;&lt;p&gt;那么现在问题的关键就是如何计算权重&lt;span class=&quot;math math-inline&quot;&gt;w_i&lt;/span&gt;了，如果我们能够计算出&lt;span class=&quot;math math-inline&quot;&gt;v_i&lt;/span&gt;和&lt;span class=&quot;math math-inline&quot;&gt;u&lt;/span&gt;之间的相似度&lt;span class=&quot;math math-inline&quot;&gt;sim(v_i, u)&lt;/span&gt;，那么我们就可以通过这样一个公式来计算权重&lt;span class=&quot;math math-inline&quot;&gt;w_i&lt;/span&gt;:&lt;/p&gt;&lt;div class=&quot;math math-display&quot;&gt;w_i = \frac{sim(v_i,u)}{\sum_{i=1}^n sim(v_i,u)}&lt;/div&gt;&lt;p&gt;因此我们可以得到以下公式：&lt;/p&gt;&lt;div class=&quot;math math-display&quot;&gt;u = \frac{ \sum_{i=1}^n sim(v_i,u)*vi}{\sum_{i=1}^n sim(v_i,u)}&lt;/div&gt;&lt;p&gt;那么接下来的问题就是如何去计算&lt;span class=&quot;math math-inline&quot;&gt;v_i&lt;/span&gt;和&lt;span class=&quot;math math-inline&quot;&gt;u&lt;/span&gt;之间的相似度&lt;span class=&quot;math math-inline&quot;&gt;sim(v_i, u)&lt;/span&gt;了。&lt;/p&gt;&lt;h2&gt;ST-MLV&lt;/h2&gt;&lt;p&gt;该文章的主要想法就是结合四个现有的缺失值填充方法，将他们得到的估计值进行综合得到预估值，四个方法分别为:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;IDW&lt;/strong&gt; (Inverse Distance Weighting)&lt;/li&gt;&lt;li&gt;&lt;strong&gt;SES&lt;/strong&gt; (Simple Exponential Smoothing)&lt;/li&gt;&lt;li&gt;&lt;strong&gt;UCF&lt;/strong&gt; (User-based Collaborative filtering)&lt;/li&gt;&lt;li&gt;&lt;strong&gt;ICF&lt;/strong&gt; (Item-based Collaborative filtering)&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;四个方法分别代表不同的&lt;code class=&quot;language-text&quot;&gt;view&lt;/code&gt;（从下图中可以看出看出每种方法所代表的&lt;code class=&quot;language-text&quot;&gt;view&lt;/code&gt;），&lt;strong&gt;&lt;code class=&quot;language-text&quot;&gt;ST-MLV&lt;/code&gt;的主要想法就是先使用四种方法计算出缺失值的估计值，然后对这些估计值进行加权求和（Multi-View Learning)，这里权值通过训练得到。&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://imagehosting.wuxiaobai24.fun/blogimage-20191108160406062.png&quot; alt=&quot;image-20191108160406062&quot;/&gt;&lt;/p&gt;&lt;p&gt;接下来，我们分别介绍这个四种方法以及 Multi-View Learning。因为前面介绍过这四种方法都可以同一到一个框架下，将问题转化成相似度计算问题，因此在后面介绍着四种方法的时候，我们只分析它如何计算相似度。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;为了方便，在下面的讨论中，假定要进行缺失值填充的值为&lt;span class=&quot;math math-inline&quot;&gt;v_{2, j}&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;h3&gt;Global Spatial View - IDW&lt;/h3&gt;&lt;p&gt;IDW的想法是两个传感器在空间上越靠近，那么他们所记录的时间序列应该越相似，因此我们可以使用两个传感器之间距离的倒数来作为他们的相似度，同时，为了控制权值随着距离增加的衰减速度，增加一个恒为正的指数：&lt;/p&gt;&lt;div class=&quot;math math-display&quot;&gt;IDW(v_{i,j}, v_{2,j})=distance(v_{i,j}, v_{2,j})^{-\alpha}&lt;/div&gt;&lt;p&gt;&lt;strong&gt;由于IDW是 Global View ，因此它会利用 &lt;span class=&quot;math math-inline&quot;&gt;t&lt;/span&gt; 时刻的所有传感器（不含缺失值）进行预估（如下图所示，IDW利用的是红框内所有非缺失的值）。&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://imagehosting.wuxiaobai24.fun/blogimage-20191108215839149.png&quot; alt=&quot;image-20191108215839149&quot;/&gt;&lt;/p&gt;&lt;h3&gt;Global Temporal View - SES&lt;/h3&gt;&lt;p&gt;SES的想法是一个传感器/时间序列上，越相近的两个时刻越相似。它借鉴了指数平滑模型&lt;span class=&quot;math math-inline&quot;&gt;\hat{v_{gt}}=\beta v_j + \beta (1-\beta)v_j-1 + \cdots + \beta(1-\beta)^{t_j-1}v_1&lt;/span&gt;，将相似度表示为：&lt;/p&gt;&lt;div class=&quot;math math-display&quot;&gt;SES(v_{2, i}, v_{2,j}) = \beta (1 - \beta)^{|j-i| - 1}&lt;/div&gt;&lt;p&gt;&lt;strong&gt;由于SES是Global View，因此它会利用第 &lt;span class=&quot;math math-inline&quot;&gt;j&lt;/span&gt; 个传感器所有时刻（不含缺失值）的值来进行预估（如下图所示，SES利用的是红框内所有非缺失的值）。&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://imagehosting.wuxiaobai24.fun/blogimage-20191108220309868.png&quot; alt=&quot;image-20191108220309868&quot;/&gt;&lt;/p&gt;&lt;h3&gt;Local View&lt;/h3&gt;&lt;p&gt;在介绍 UCF 和ICF之前，由于他们都是&lt;code class=&quot;language-text&quot;&gt;local view&lt;/code&gt;和&lt;code class=&quot;language-text&quot;&gt;Collaborative filtering&lt;/code&gt;，所以这里先描述一下&lt;code class=&quot;language-text&quot;&gt;local view&lt;/code&gt;和&lt;code class=&quot;language-text&quot;&gt;Collaborative filtering&lt;/code&gt;。&lt;/p&gt;&lt;p&gt;首先，&lt;code class=&quot;language-text&quot;&gt;local view&lt;/code&gt;是计算相似度时只考虑一个时间窗内的数据，时间窗长度由 &lt;span class=&quot;math math-inline&quot;&gt;w&lt;/span&gt; 给定，如果缺失值所在的时刻为&lt;span class=&quot;math math-inline&quot;&gt;t&lt;/span&gt; ，则时间窗为&lt;span class=&quot;math math-inline&quot;&gt;[j- \frac {w-1} {2}, j + \frac {w+1} {2}]&lt;/span&gt;如下图，我们想要预测 &lt;span class=&quot;math math-inline&quot;&gt;v_{2,j}&lt;/span&gt;，而 &lt;span class=&quot;math math-inline&quot;&gt;w=2&lt;/span&gt;，所以我们在计算相似度的时候就只考虑 &lt;span class=&quot;math math-inline&quot;&gt;t-2&lt;/span&gt; 到&lt;span class=&quot;math math-inline&quot;&gt;t+2&lt;/span&gt;的的数据。&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://imagehosting.wuxiaobai24.fun/blogimage-20191108221232886.png&quot; alt=&quot;image-20191108221232886&quot;/&gt;&lt;/p&gt;&lt;h3&gt;Local Spatial View - UCF&lt;/h3&gt;&lt;p&gt;UCF是一种常见的推荐算法，它主要的想法是，相似的用户对于同一个物品的评分是相近的。对于我们这个问题，&lt;strong&gt;一个传感器被当成一个用户&lt;/strong&gt;。两个传感器的相似度的计算公式为：&lt;/p&gt;&lt;div class=&quot;math math-display&quot;&gt;UCF(s_i, s) = 1 / {\sqrt{\frac {\sum_{k= j- \frac {w-1} {2}}^{ j + \frac {w+1} {2}} (v_{i,k}-v_{2,k})} {NT}}}&lt;/div&gt;&lt;p&gt;其中 &lt;span class=&quot;math math-inline&quot;&gt;NT&lt;/span&gt; 为时间窗内，两个传感器同时有读数的时刻数。&lt;/p&gt;&lt;p&gt;因为 UCF 计算的是两个传感器之间的相似度，按照之前提到的 framework，我们可以把这个相似度作为权值对同一时刻所有传感器的读数进行加权求和。&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://imagehosting.wuxiaobai24.fun/blogimage-20191109135949357.png&quot; alt=&quot;image-20191109135949357&quot;/&gt;&lt;/p&gt;&lt;h3&gt;Local Temporal View - ICF&lt;/h3&gt;&lt;p&gt;ICF 也是一种常见的推荐算法，它的主要想法是某个用户对相似的物品会做出相似的评分。对于我们这个问题&lt;strong&gt;，一个时刻被当成一个物品&lt;/strong&gt;。则两个时刻的相似度的计算公式为：&lt;/p&gt;&lt;div class=&quot;math math-display&quot;&gt;sim(t_i, t_2) = 1 / \sqrt {\frac {\sum_{k=i}^m(v_{k,i} - v_{k, 2})} {NS}}&lt;/div&gt;&lt;p&gt;其中 &lt;span class=&quot;math math-inline&quot;&gt;m&lt;/span&gt; 是传感器个数，&lt;span class=&quot;math math-inline&quot;&gt;NS&lt;/span&gt; 是在 &lt;span class=&quot;math math-inline&quot;&gt;t_i&lt;/span&gt; 和 &lt;span class=&quot;math math-inline&quot;&gt;t_j&lt;/span&gt; 同时有读数的传感器的个数。&lt;/p&gt;&lt;p&gt;因为ICF计算的是两个时刻之间的相似度，按照之前提出的 framework，我们可以把这个相似度作为权值对这个传感器在时间窗内值进行加权求和。&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://imagehosting.wuxiaobai24.fun/blogimage-20191109141001345.png&quot; alt=&quot;image-20191109141001345&quot;/&gt;&lt;/p&gt;&lt;h3&gt;Multi-View Learning&lt;/h3&gt;&lt;p&gt;对于缺失值 &lt;span class=&quot;math math-inline&quot;&gt;v_{2, j}&lt;/span&gt;，我们可以使用上面提到的四种方法计算分别得到 &lt;span class=&quot;math math-inline&quot;&gt;\hat {v_{gs}},\hat {v_{gt}},\hat {v_{ls}},\hat {v_{lt}}&lt;/span&gt;，对这四个值进行一次线性回归得到最终的预测值 &lt;span class=&quot;math math-inline&quot;&gt;\hat{v_{2,j}}&lt;/span&gt; :&lt;/p&gt;&lt;div class=&quot;math math-display&quot;&gt;\hat{v_{2,j}} = w_1 * \hat {v_{gs}} + w_2 * \hat {v_{gt}} + w_3 * \hat {v_{ls}} + w_4 * \hat {v_{lt}} + b&lt;/div&gt;&lt;p&gt;其中 &lt;span class=&quot;math math-inline&quot;&gt;w_k&lt;/span&gt; 是分别对每个传感器进行训练得到的。&lt;/p&gt;&lt;p&gt;同时，由于 UCF 和 ICF 不能很好的处理 block missing （因为如果时间窗内所有值都缺失，那么就无法计算出相似度了），所以遇到 block missing 的时候就先用 SES 或 IDW 进行一次填充先。ST-MVL的具体算法如下：&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://imagehosting.wuxiaobai24.fun/blogimage-20191109141800565.png&quot; alt=&quot;image-20191109141800565&quot;/&gt;&lt;/p&gt;&lt;h2&gt;Experiment&lt;/h2&gt;&lt;h3&gt;Dataset&lt;/h3&gt;&lt;p&gt;2014/05/01 - 2015/04/30 北京的空气质量和天气数据。&lt;/p&gt;&lt;h3&gt;Metric&lt;/h3&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Mean Absolute Error (MAE):&lt;/p&gt;&lt;div class=&quot;math math-display&quot;&gt;MAE = \frac {\sum_i{|v_i - \hat{v_i}|}} n&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Mean Relative Error (MRS):&lt;/p&gt;&lt;div class=&quot;math math-display&quot;&gt;MRE = \frac {\sum_i{|v_i - \hat{v_i}|}} {\sum_i v_i}&lt;/div&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;Result&lt;/h3&gt;&lt;p&gt;&lt;img src=&quot;https://imagehosting.wuxiaobai24.fun/blogimage-20191110185118022.png&quot; alt=&quot;image-20191110185118022&quot;/&gt;&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://imagehosting.wuxiaobai24.fun/blogimage-20191109142044280.png&quot; alt=&quot;image-20191109142044280&quot;/&gt;&lt;/p&gt;&lt;h2&gt;Conclusion&lt;/h2&gt;&lt;p&gt;这篇问题主要解决了时空数据上缺失值的问题，当时空数据集存在大量缺失值的问题时，可以考虑引入这篇文章的方法来解决这个问题，算法简洁有效，而且跑起来应该挺快的，算是一个比较好的 baseline。&lt;/p&gt;&lt;h2&gt;Reference&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;https://www.microsoft.com/en-us/research/wp-content/uploads/2016/06/IJCAI-16-fill-missing-values-Yu-Zheng.pdf&quot;&gt;paper pdf&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href=&quot;https://www.microsoft.com/en-us/research/uploads/prod/2016/06/STMVL-Release.zip&quot;&gt;source code and data&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Docker Quick Start]]></title><description><![CDATA[基础概念 Docker 引擎主要的组件构成为： Docker client Docker daemon containerd runc 它们的关系如下： Docker daemon 实现了 Docker 引擎的 API，默认情况下，Docker client 与 Docker…]]></description><link>https://codeand.fun/posts/2020/07/18/docker-quick-start/</link><guid isPermaLink="false">https://codeand.fun/posts/2020/07/18/docker-quick-start/</guid><pubDate>Sat, 18 Jul 2020 17:42:33 GMT</pubDate><content:encoded>&lt;h2&gt;基础概念&lt;/h2&gt;&lt;p&gt;Docker 引擎主要的组件构成为：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Docker client&lt;/li&gt;&lt;li&gt;Docker daemon&lt;/li&gt;&lt;li&gt;containerd&lt;/li&gt;&lt;li&gt;runc&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;它们的关系如下：&lt;/p&gt;&lt;p&gt;Docker daemon 实现了 Docker 引擎的 API，默认情况下，Docker client 与 Docker daemon 之间的通信有本地的 IPC/UNIX socket 完成（&lt;code class=&quot;language-text&quot;&gt;/var/run/docker.sock&lt;/code&gt;）。&lt;/p&gt;&lt;h2&gt;Cheat Sheet&lt;/h2&gt;&lt;h3&gt;Image&lt;/h3&gt;&lt;h4&gt;列出本地镜像&lt;/h4&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; image &lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 列出本地镜像&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; images &lt;span class=&quot;token comment&quot;&gt;# 两条命令等效&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;可以使用&lt;code class=&quot;language-text&quot;&gt;--filter&lt;/code&gt;来过滤&lt;code class=&quot;language-text&quot;&gt;docker image ls&lt;/code&gt;返回的镜像列表：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;dangling：&lt;code class=&quot;language-text&quot;&gt;true/false&lt;/code&gt;，是否为悬虚镜像。&lt;/li&gt;&lt;li&gt;before：&lt;code class=&quot;language-text&quot;&gt;&amp;lt;image name or id&amp;gt;&lt;/code&gt;，返回在其之前被创建的全部镜像&lt;/li&gt;&lt;li&gt;since：&lt;code class=&quot;language-text&quot;&gt;&amp;lt;image name or id&amp;gt;&lt;/code&gt;，返回在其之后被创建的全部镜像&lt;/li&gt;&lt;li&gt;label：标注（label）的名称或值。标注在Dockerfile通过 LABEL 指定，但是&lt;code class=&quot;language-text&quot;&gt;docker image ls&lt;/code&gt;不显示。&lt;/li&gt;&lt;li&gt;reference：用正则表达式对镜像名称和标签过滤&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Example：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; image &lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt; --filter &lt;span class=&quot;token assign-left variable&quot;&gt;dangling&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;true
$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; image &lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt; -f &lt;span class=&quot;token assign-left variable&quot;&gt;before&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;alpine &lt;span class=&quot;token comment&quot;&gt;# -f 是 --filter 的简写&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; image &lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt; -f &lt;span class=&quot;token assign-left variable&quot;&gt;reference&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;quot;*:latest&amp;quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;使用&lt;code class=&quot;language-text&quot;&gt;--format&lt;/code&gt;可以对输出内容镜像格式化输出：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; image &lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt; --format &lt;span class=&quot;token string&quot;&gt;&amp;quot;{{.Size}}&amp;quot;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 只输出 SIZE&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;如果只是想要&lt;code class=&quot;language-text&quot;&gt;IMAGE ID&lt;/code&gt;的话，可以直接用&lt;code class=&quot;language-text&quot;&gt;-q&lt;/code&gt;，这个和删除命令结合可以快速删除所有镜像：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; image &lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt; -q &lt;span class=&quot;token comment&quot;&gt;# 只输出 IMAGE ID&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; image &lt;span class=&quot;token function&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; image &lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt; -q&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 删除所有镜像&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4&gt;拉取镜像&lt;/h4&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; pull ubuntu:latest &lt;span class=&quot;token comment&quot;&gt;# 拉取镜像&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; image pull &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;repository&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt;:&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;tag&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 加上 -a 表示拉取所有标签&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;如果没有指定标签，则默认为 latest&lt;/li&gt;&lt;li&gt;latest 不保证这是仓库中最新的镜像。&lt;/li&gt;&lt;li&gt;从非官方仓库中拉取镜像需要在仓库名称加上 Docker Hub的用户名或组织名，如&lt;code class=&quot;language-text&quot;&gt;docker image pull wuxiaobai24/demo:v2&lt;/code&gt;&lt;/li&gt;&lt;li&gt;如果希望在第三方镜像仓库服务获取镜像，则需要在仓库名称前面加上第三方镜像仓库服务的 DNS 名称，如&lt;code class=&quot;language-text&quot;&gt;docker image pull grc.io/wuxiaobai24/demo:v2&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;我们可以用&lt;code class=&quot;language-text&quot;&gt;docker search&lt;/code&gt;来对 Docker Hug 进行搜索：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; search alpine&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;搜索时可以使用过滤器：&lt;ul&gt;&lt;li&gt;is-official：true/false，是否为官方镜像&lt;/li&gt;&lt;li&gt;is-automated:true/false，是否为自动创建的镜像&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;搜索结果默认返回 25 个结果，可以用&lt;code class=&quot;language-text&quot;&gt;--limit&lt;/code&gt;来指定个数&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;删除镜像&lt;/h4&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; image &lt;span class=&quot;token function&quot;&gt;rm&lt;/span&gt; 0267 &lt;span class=&quot;token comment&quot;&gt;# 通过镜像ID来删除 docker 镜像&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; image &lt;span class=&quot;token function&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; image &lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt; -q&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 删除所有镜像&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; image &lt;span class=&quot;token function&quot;&gt;rm&lt;/span&gt; -f 0267 &lt;span class=&quot;token comment&quot;&gt;# -f mean --force&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;一个&lt;code class=&quot;language-text&quot;&gt;Docker&lt;/code&gt;镜像是由多个镜像层组成的，如果一个在删除某个镜像时，其中某个镜像层还被本地某个镜像引用的话，那么该镜像层不会被删除。&lt;/li&gt;&lt;li&gt;如果某个镜像存在正在运行的容器的话，删除操作不会被允许&lt;/li&gt;&lt;li&gt;可以用&lt;code class=&quot;language-text&quot;&gt;docker image prune&lt;/code&gt;来移除所有悬挂镜像。&lt;ul&gt;&lt;li&gt;&lt;strong&gt;悬虚镜像&lt;/strong&gt;：没有标签的镜像，&lt;code class=&quot;language-text&quot;&gt;&amp;lt;none&amp;gt;:&amp;lt;none&amp;gt;&lt;/code&gt;。通常是因为构建了一个新的镜像并为该镜像打了一个已经存在的标签。这时候旧镜像就会变成悬虚镜像。&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;构造镜像&lt;/h4&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Dockerfile 在当前目录（注意最后面那个`.`）， -t 表示设置镜像&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; image build -t web:latest &lt;span class=&quot;token builtin class-name&quot;&gt;.&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; image tag web:1.0 wuxiaobai24/web:latest &lt;span class=&quot;token comment&quot;&gt;# 给镜像重新打标签&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; image build --squash &lt;span class=&quot;token comment&quot;&gt;# 将多个镜像层合并成一层&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3&gt;Container&lt;/h3&gt;&lt;h4&gt;启动容器&lt;/h4&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; container run &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;image&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;app&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 基础格式&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; container run -it &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;image&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;app&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# -it 表示启动一个交互性程序，并将当前终端连接到容器的Shell终端上&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; container run -d &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;image&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;app&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# -d 表示以后台的方式启动容器&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; container run -d --name &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;container-name&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;image&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;app&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# --name 给容器命名&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; container run -d -p &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;host-port&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt;:&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;container-port&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;image&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# -p 配置端口转发，不指定 &amp;lt;app&amp;gt;的话会运行默认应用&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; container run -it 67fa /bin/bash &lt;span class=&quot;token comment&quot;&gt;# -it 表示以交互模式启动，并attach到tty上&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;在容器中可以用 Ctrl-PQ 来退出容器（同时保持容器继续运行）&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在退出容器后可以用下面的命令来&lt;code class=&quot;language-text&quot;&gt;attach&lt;/code&gt;到已运行的容器：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; container &lt;span class=&quot;token builtin class-name&quot;&gt;exec&lt;/span&gt; -it &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;container name or id&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;bash&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 连接到在运行中的容器&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4&gt;列出镜像&lt;/h4&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; container &lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 查看系统内处于运行状态的容器&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ps&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 同上&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; container &lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt; --all &lt;span class=&quot;token comment&quot;&gt;# 查看系统内所有容器，包已经stop的。&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; container &lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt; -a &lt;span class=&quot;token comment&quot;&gt;# 同上&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; container &lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt; -q &lt;span class=&quot;token comment&quot;&gt;# 显示运行中容器的 id&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4&gt;停止/删除容器&lt;/h4&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;
$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; container stop &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;container name or id&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 停止容器&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; container start &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;container &lt;span class=&quot;token function&quot;&gt;id&lt;/span&gt; or name&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 再次启动该容器&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; container &lt;span class=&quot;token function&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;container name or id&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 删除容器&lt;/span&gt;
$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; container &lt;span class=&quot;token function&quot;&gt;rm&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; container &lt;span class=&quot;token function&quot;&gt;ls&lt;/span&gt; -aq&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt; -f &lt;span class=&quot;token comment&quot;&gt;# 快速删除所有容器&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3&gt;Others&lt;/h3&gt;&lt;h4&gt;查看 Docker 相关信息：&lt;/h4&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; system info&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4&gt;将用户加入到本地 Docker 组中&lt;/h4&gt;&lt;p&gt;这样可以将&lt;code class=&quot;language-text&quot;&gt;sudo docker ...&lt;/code&gt;省略成&lt;code class=&quot;language-text&quot;&gt;docker ...&lt;/code&gt;。&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;usermod&lt;/span&gt; -aG &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;user&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4&gt;查看 Image 信息&lt;/h4&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;docker&lt;/span&gt; image inspect &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;image&lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 显示关于 Image 的信息，可以用来看默认运行的应用&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr/&gt;</content:encoded></item><item><title><![CDATA[用自动机实现一个简易的正则表达式引擎]]></title><description><![CDATA[…]]></description><link>https://codeand.fun/posts/2020/07/08/yong-zi-dong-ji-shi-xian-yi-ge-jian-yi-de-zheng-ze-biao-da-shi-yin-qing/</link><guid isPermaLink="false">https://codeand.fun/posts/2020/07/08/yong-zi-dong-ji-shi-xian-yi-ge-jian-yi-de-zheng-ze-biao-da-shi-yin-qing/</guid><pubDate>Wed, 08 Jul 2020 21:17:30 GMT</pubDate><content:encoded>&lt;h2&gt;起因&lt;/h2&gt;&lt;p&gt;这学期上了一门《计算机软件理论》的课，其实就是本科的《自动机与形式语言》的翻版。由于疫情的缘故，这门课从原来的笔试改成了大作业的形式，其中有一道题目就是让我们将正则表达式转换成自动机，并用自动机来判断输入的文本时候满足正则表达式的描述。写完之后觉得蛮好玩的，就决定写个博客记录一下。&lt;/p&gt;&lt;p&gt;BTW，这里只是实现了一个非常简易的版本。&lt;/p&gt;&lt;h2&gt;理论&lt;/h2&gt;&lt;p&gt;在这门课中证明了正则表达式与自动机的对应关系，可以通过递归构造的方式先将一个正则表达式转换为子表达式，然后构建子表达式对应的子自动机（或者说&lt;span class=&quot;math math-inline&quot;&gt;\epsilon-NFA&lt;/span&gt;)，并通过一定的规则将这些子自动机连接成一个大的自动机。&lt;/p&gt;&lt;p&gt;不妨假设正则表达式中只有&lt;code class=&quot;language-text&quot;&gt;ab&lt;/code&gt;，&lt;code class=&quot;language-text&quot;&gt;a|b&lt;/code&gt;，&lt;code class=&quot;language-text&quot;&gt;a*&lt;/code&gt;三种运算（当然这里支持用括号嵌套）,不妨假设，a 和 b 对应自动机分别为：FA1 和 FA2，那么我们这三种运算所对应的链接方式分别为:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;ab&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;img src=&quot;https://imagehosting.wuxiaobai24.fun/blog%E7%94%A8%E8%87%AA%E5%8A%A8%E6%9C%BA%E5%AE%9E%E7%8E%B0%E4%B8%80%E4%B8%AA%E7%AE%80%E6%98%93%E7%9A%84%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%BC%95%E6%93%8E-20200708220015-2020-07-08&quot; alt=&quot;用自动机实现一个简易的正则表达式引擎-20200708220015-2020-07-08&quot;/&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;a|b&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;img src=&quot;https://imagehosting.wuxiaobai24.fun/blog%E7%94%A8%E8%87%AA%E5%8A%A8%E6%9C%BA%E5%AE%9E%E7%8E%B0%E4%B8%80%E4%B8%AA%E7%AE%80%E6%98%93%E7%9A%84%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%BC%95%E6%93%8E-20200708220206-2020-07-08&quot; alt=&quot;用自动机实现一个简易的正则表达式引擎-20200708220206-2020-07-08&quot;/&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;a*&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;img src=&quot;https://imagehosting.wuxiaobai24.fun/blog%E7%94%A8%E8%87%AA%E5%8A%A8%E6%9C%BA%E5%AE%9E%E7%8E%B0%E4%B8%80%E4%B8%AA%E7%AE%80%E6%98%93%E7%9A%84%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%BC%95%E6%93%8E-20200708220253-2020-07-08&quot; alt=&quot;用自动机实现一个简易的正则表达式引擎-20200708220253-2020-07-08&quot;/&gt;&lt;/p&gt;&lt;p&gt;利用上面的规则，我们就可以将正则表达式转换为一个&lt;span class=&quot;math math-inline&quot;&gt;\epsilon-NFA&lt;/span&gt;，然后当读入输入的时候，我们就默认&lt;span class=&quot;math math-inline&quot;&gt;\epsilon-NFA&lt;/span&gt;对输入进行判断，当然我们也可以先将&lt;span class=&quot;math math-inline&quot;&gt;\epsilon-NFA&lt;/span&gt;转换为&lt;span class=&quot;math math-inline&quot;&gt;DFA&lt;/span&gt;，在对输入进行判断。&lt;/p&gt;&lt;h2&gt;实现&lt;/h2&gt;&lt;p&gt;为了方便，我们先将连接操作&lt;code class=&quot;language-text&quot;&gt;ab&lt;/code&gt;转换为&lt;code class=&quot;language-text&quot;&gt;a-b&lt;/code&gt;：&lt;/p&gt;&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;ab&lt;/code&gt;转换为&lt;code class=&quot;language-text&quot;&gt;a-b&lt;/code&gt;的规则可以通过找规律得到，即当左边的字符不为&lt;code class=&quot;language-text&quot;&gt;(&lt;/code&gt;或&lt;code class=&quot;language-text&quot;&gt;|&lt;/code&gt;，且右边的字符不为&lt;code class=&quot;language-text&quot;&gt;*&lt;/code&gt;、&lt;code class=&quot;language-text&quot;&gt;)&lt;/code&gt;或&lt;code class=&quot;language-text&quot;&gt;|&lt;/code&gt;时，两个字符之间就是连接关系，应该加入&lt;code class=&quot;language-text&quot;&gt;-&lt;/code&gt;符号：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;addConcatOp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; s
    output &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; s&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        L&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; R &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; s&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; s&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; L &lt;span class=&quot;token keyword&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;#x27;(|&amp;#x27;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;and&lt;/span&gt; R &lt;span class=&quot;token keyword&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;#x27;*)|&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            output &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;#x27;-&amp;#x27;&lt;/span&gt;
        output &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; R
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; output&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后将正则表达式从中缀表示转换为后缀表示，这样在后面解析的时候会方便许，中缀转后缀只需要利用一个栈来记录操作即可搞定：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;infix2postfix&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    output &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;#x27;&amp;#x27;&lt;/span&gt;
    st &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; c &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; s&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; c &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;#x27;(|-&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            st&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;append&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;elif&lt;/span&gt; c &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;#x27;)&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;st&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;st&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;#x27;(&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            st&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pop&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            output &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; c
            &lt;span class=&quot;token comment&quot;&gt;# print(st, c)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;st&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;and&lt;/span&gt; st&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;#x27;(&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                output &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; st&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
                st&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pop&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;st&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        output &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; st&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        st&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pop&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; output&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在实现正则表达式之前，我们先定义一下 State 和 NFA 的数据结构，我们在&lt;code class=&quot;language-text&quot;&gt;State&lt;/code&gt;中存储一个&lt;code class=&quot;language-text&quot;&gt;isEnd&lt;/code&gt;的 Flag 来记录是否为接收状态以及一个字典来记录跳转，为了实现空跳转，我们用一个特殊的字符串&lt;code class=&quot;language-text&quot;&gt;Epsilon&lt;/code&gt;来表示&lt;span class=&quot;math math-inline&quot;&gt;\epsilon&lt;/span&gt;：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;Epsilon &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;#x27;Epsilon&amp;#x27;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;State&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; isEnd &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isEnd &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; isEnd
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;next&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;addNext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; token&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; to&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# print(self.next, token, to)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; token &lt;span class=&quot;token keyword&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 
            self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;append&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;to&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;NFA 的数据结构只需要记住一个开始状态和接收状态即可，记住开始状态就可以遍历出整个 NFA，而记住接收状态是为了后面连接 NFA 时方便操作，而之所以只有一个接收状态是因为如果有多个接收状态，可以通过空跳转将其转换成只有一个接收状态。因此其数据结构为：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;NFA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; start&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; end&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;start &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; start
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;end&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; end&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后是就是正则表达式转换为 NFA 的过程，我们逐字符读取已经转成后缀表示的正则表达式：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;如果读到一个字符，我们就构造一个&lt;code class=&quot;language-text&quot;&gt;start -- token --&amp;gt; end&lt;/code&gt;形式的 NFA，并将其压入栈中。&lt;/li&gt;&lt;li&gt;如果读到一个&lt;code class=&quot;language-text&quot;&gt;-&lt;/code&gt;或者&lt;code class=&quot;language-text&quot;&gt;|&lt;/code&gt;，我们就从栈中弹出两个 NFA，并按照上面提到的规则重新构造一个NFA，并将其压入栈中。&lt;/li&gt;&lt;li&gt;如果读到一个&lt;code class=&quot;language-text&quot;&gt;*&lt;/code&gt;，我们就从栈中弹出一个 NFA，并按照上面提到的规则构造一个NFA，并将其压入栈中。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;最后在栈中留下来的 NFA 就是正则表达式对应的 NFA：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;re2nfa&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pattern&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    st &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; c &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; pattern&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; c &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;#x27;|&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;st&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            nfa1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; nfa2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; st&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; st&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            st&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pop&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; st&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pop&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            st&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;append&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;NFA&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;OR&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nfa1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; nfa2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;elif&lt;/span&gt; c &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;#x27;-&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;st&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            nfa1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; nfa2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; st&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; st&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            st&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pop&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; st&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pop&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            st&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;append&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;NFA&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CONCAT&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nfa1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; nfa2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;elif&lt;/span&gt; c &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;#x27;*&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;assert&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;st&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            nfa &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; st&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
            st&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;pop&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            st&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;append&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;NFA&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;CLOSURE&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nfa&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            st&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;append&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;NFA&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;BASIC&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; st&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;其中，构造 NFA 的过程被封装到&lt;code class=&quot;language-text&quot;&gt;NFA&lt;/code&gt;类的静态方法中去了，其实现为：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;NFA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; start&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; end&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;start &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; start
        self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;end&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; end
    
    &lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@staticmethod&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;_initState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; State&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; State&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@staticmethod&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;BASIC&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        start&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; end &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; NFA&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_initState&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        start&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;addNext&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; end&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# S -- token --&amp;gt; E&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; NFA&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;start&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; end&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@staticmethod&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;OR&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nfa1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; nfa2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        start&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; end &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; NFA&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_initState&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        
        start&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;addNext&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Epsilon&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; nfa1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;start&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# S -- e --&amp;gt; NFA1&lt;/span&gt;
        start&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;addNext&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Epsilon&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; nfa2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;start&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# S -- e --&amp;gt; NFA2&lt;/span&gt;
        nfa1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;end&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;addNext&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Epsilon&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; end&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# NFA1 -- e --&amp;gt; E&lt;/span&gt;
        nfa2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;end&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;addNext&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Epsilon&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; end&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;# NFA2 -- e --&amp;gt; E&lt;/span&gt;

        nfa1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;end&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isEnd&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; nfa2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;end&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isEnd &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; NFA&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;start&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; end&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@staticmethod&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CONCAT&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nfa1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; nfa2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        start&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; end &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; NFA&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_initState&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        
        start&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;addNext&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Epsilon&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; nfa1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;start&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# E -- e --&amp;gt; NFA1&lt;/span&gt;
        nfa1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;end&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;addNext&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Epsilon&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; nfa2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;start&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# NFA1 -- e --&amp;gt; NFA2&lt;/span&gt;
        nfa2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;end&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;addNext&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Epsilon&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; end&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# NFA2 -- e --&amp;gt; NFA1&lt;/span&gt;

        nfa1&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;end&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isEnd &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;
        nfa2&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;end&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isEnd &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; NFA&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;start&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; end&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token decorator annotation punctuation&quot;&gt;@staticmethod&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;CLOSURE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nfa&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        start&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; end &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; NFA&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;_initState&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        start&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;addNext&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Epsilon&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;nfa&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;start&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# S -- e --&amp;gt; NFA&lt;/span&gt;
        nfa&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;end&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;addNext&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Epsilon&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;end&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# NFA -- e --&amp;gt; NFA&lt;/span&gt;
        end&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;addNext&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Epsilon&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; start&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# E -- e --&amp;gt; S&lt;/span&gt;

        nfa&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;end&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isEnd &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; NFA&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;start&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; end&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;由于我们的 NFA 是一个 &lt;span class=&quot;math math-inline&quot;&gt;\epsilon-NFA&lt;/span&gt;，所以在使用它时需要大量进行求空闭包的操作，所以我们在实现&lt;code class=&quot;language-text&quot;&gt;match&lt;/code&gt;操作前，我们需要实现求闭包的操作。我们用一个队列来实现空跳转的遍历，然后返回遍历到的状态：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GetEpsilonClosure&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;states&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
		visited &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;states&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		q &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; deque&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;states&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;q&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
				state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; q&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;popleft&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
				&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; item &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Epsilon&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
						&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; item &lt;span class=&quot;token keyword&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; visited&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
								q&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;append&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
								visited&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;add&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;item&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; visited&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后是&lt;code class=&quot;language-text&quot;&gt;match&lt;/code&gt;操作，就是根据读入的字符串来决定如何跳转，遍历完字符串之后再判断一下当前状态是否存在接收状态即可：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;match&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; s&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    states &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;start&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; c &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; s&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# Epsilon -&amp;gt;&lt;/span&gt;
        states &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; NFA&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;GetEpsilonClosure&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;states&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        nextStates &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; state &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; states&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; nextState &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                nextStates&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;add&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nextState&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        states &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; nextStates
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;states&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;break&lt;/span&gt;
    states &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; NFA&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;GetEpsilonClosure&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;states&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; state &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; states&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isEnd&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;上面实现的部分已经可以实现一个支持&lt;code class=&quot;language-text&quot;&gt;a*&lt;/code&gt;,&lt;code class=&quot;language-text&quot;&gt;a|b&lt;/code&gt;,&lt;code class=&quot;language-text&quot;&gt;ab&lt;/code&gt;三种操作的正则表达式了，为了支持更多的特性，我们可以可以通过转换的方式，将其他操作转化为上面三种操作，如&lt;code class=&quot;language-text&quot;&gt;{a,b,c}&lt;/code&gt;可以转换为&lt;code class=&quot;language-text&quot;&gt;(a|b|c)&lt;/code&gt;，&lt;code class=&quot;language-text&quot;&gt;a+&lt;/code&gt;可以转换为&lt;code class=&quot;language-text&quot;&gt;aa*&lt;/code&gt;等。&lt;/p&gt;&lt;p&gt;同时，我们还实现了将 NFA 使用&lt;code class=&quot;language-text&quot;&gt;graphviz&lt;/code&gt;绘制成图片和&lt;span class=&quot;math math-inline&quot;&gt;\epsilon-NFA&lt;/span&gt;到&lt;span class=&quot;math math-inline&quot;&gt;DFA&lt;/span&gt;的转换的功能。&lt;/p&gt;&lt;p&gt;因为使用了&lt;code class=&quot;language-text&quot;&gt;graphviz&lt;/code&gt;库，所以需要先安装对应的包：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;pip &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; graphviz&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;绘制的过程其实就是用广度优先遍历去遍历所有状态，在遍历的时候给这些状态标好序，同时记录所有跳转，然后在用&lt;code class=&quot;language-text&quot;&gt;graphviz&lt;/code&gt;绘制即可：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;toGraph&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; state_prefix&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;#x27;State&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    dot &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; Digraph&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;#x27;nfa&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;quot;png&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    dot&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;attr&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rankdir&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;#x27;LR&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    state2index &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    q &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; deque&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    q&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;append&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;start&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    g &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;q&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; q&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;popleft&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; state &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; state2index&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;continue&lt;/span&gt;
        state2index&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; state_prefix &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state2index&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        index &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; state2index&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        dot&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;node&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; index&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; label&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; shape&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;#x27;doublecircle&amp;#x27;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isEnd &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;#x27;circle&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; token&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; states &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; nextState &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; states&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                g&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;append&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; token&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; nextState&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                q&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;append&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nextState&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;# output&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; start&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; token&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; end &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; g&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        startIndex&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; endIndex &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; state2index&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;start&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; state2index&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;end&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;#x27;{} -- {} --&amp;gt; {}&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;startIndex&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; token&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; endIndex&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        dot&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;edge&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;startIndex&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; endIndex&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; label&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    dot&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;node&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;#x27;start&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; label&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;#x27;S&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; shape&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;quot;plaintext&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    dot&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;edge&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;#x27;start&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; state2index&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;start&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    dot&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;render&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;filename&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;#x27;nfa&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; directory&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;#x27;./&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; state2index&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;因为在实现&lt;span class=&quot;math math-inline&quot;&gt;\epsilon-NFA&lt;/span&gt;到&lt;span class=&quot;math math-inline&quot;&gt;DFA&lt;/span&gt;的转换时需要先知道字母表，所以我们同样用遍历的方式得到字母表，同时构造一个状态到序号的字典，先给 NFA 的状态标序可以帮助我们给后面构造 DFA 时判断两个状态集合是否相同提供便利：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;geneState2Index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; state_prefix&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;#x27;State&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; alphabet_flag &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    state2index &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    alphabet &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    q &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; deque&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    q&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;append&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;start&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;q&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; q&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;popleft&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; state &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; state2index&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;continue&lt;/span&gt;
        state2index&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; state_prefix &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;state2index&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        index &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; state2index&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; token&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; states &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; alphabet_flag&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                alphabet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;append&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;token&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; nextState &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; states&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                q&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;append&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;nextState&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; alphabet_flag&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; state2index&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;alphabet&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; state2index&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;NFA 转 DFA 的基本原理就是 NFA 中一个状态集合对应与 DFA 中的一个状态，所以我们刚才生成的状态到序号的字典来生成 DFA 的序号，其实就是简单拼接字符串，只不过拼接前先做一次排序，我们将其写成一个函数&lt;code class=&quot;language-text&quot;&gt;hashfun&lt;/code&gt;，利用&lt;code class=&quot;language-text&quot;&gt;hashfun&lt;/code&gt;就可以将其 NFA 的状态集合映射成 DFA 的序号。我们通过递归的方式来生成 &lt;code class=&quot;language-text&quot;&gt;DFA&lt;/code&gt;，从 NFA 开始状态为初始的状态集合（当然这里要先求个克林闭包），调用递归函数&lt;code class=&quot;language-text&quot;&gt;GeneNewState&lt;/code&gt;：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;通过&lt;code class=&quot;language-text&quot;&gt;hashfun&lt;/code&gt;来生成 DFA 中的序号，如果这个序号对应的 DFA 状态已经存在了（被记录在一个全局的字典中），我们就直接返回该状态。&lt;/li&gt;&lt;li&gt;如果不存在，我们就生成一个新的 DFA 状态与该序号对应起来，这个状态是否为接收状态通过输入的状态集合中时候存在接收状态来判断；然后遍历字母表中的所有字符来确定输入了这个字符后，当前状态集合会跳转到的状态集合&lt;code class=&quot;language-text&quot;&gt;next_states&lt;/code&gt;（别忘记了求克林闭包），然后对&lt;code class=&quot;language-text&quot;&gt;next_states&lt;/code&gt;递归调用&lt;code class=&quot;language-text&quot;&gt;GeneNewState&lt;/code&gt;，并将返回的状态与当前状态连接起来即可&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;实现代码如下：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;toDFA&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    state2index&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; alphabet &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;geneState2Index&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;#x27;&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; alphabet_flag&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    alphabet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;remove&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;Epsilon&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# print(alphabet)&lt;/span&gt;
    index2state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;hashfunc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;states&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;#x27;#&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;join&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;state2index&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;state&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; state &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; states&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;statesIsEnd&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;states&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; state &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; states&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;isEnd&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;False&lt;/span&gt;
    
    &lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;GeneNewState&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;states&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        index &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; hashfunc&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;states&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; index &lt;span class=&quot;token keyword&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; index2state&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            isEnd &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; statesIsEnd&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;states&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            new_state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; State&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;isEnd&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            index2state&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; new_state
            &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; c &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; alphabet&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                next_states &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; 
                &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; i_state &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; states&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                    next_states &lt;span class=&quot;token operator&quot;&gt;+=&lt;/span&gt; i_state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                next_states &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; NFA&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;GetEpsilonClosure&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;next_states&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                next_index &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; hashfunc&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;next_states&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                next_state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; GeneNewState&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;next_states&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                next_state &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; index2state&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;next_index&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
                new_state&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;addNext&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;c&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; next_state&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; index2state&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;index&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

    states &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; NFA&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;GetEpsilonClosure&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;self&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;start&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    start &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; GeneNewState&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;states&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; NFA&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;start&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[2020 02 & 03 Reading]]></title><description><![CDATA[从2月7号开始，开始每天花一定的时间看书，想要养成读书的习惯，为了激励一下自己，所以在这里记录下 2、3 月份读的书。 2020-02 2月份读了1…]]></description><link>https://codeand.fun/posts/2020/04/02/2020-02-03-reading/</link><guid isPermaLink="false">https://codeand.fun/posts/2020/04/02/2020-02-03-reading/</guid><pubDate>Thu, 02 Apr 2020 21:09:55 GMT</pubDate><content:encoded>&lt;blockquote&gt;&lt;p&gt;从2月7号开始，开始每天花一定的时间看书，想要养成读书的习惯，为了激励一下自己，所以在这里记录下 2、3 月份读的书。&lt;/p&gt;&lt;/blockquote&gt;&lt;h2&gt;2020-02&lt;/h2&gt;&lt;blockquote&gt;&lt;p&gt;2月份读了10本书，大部分书都是在微信上看完的，当时应该有点刻意的让虚构和非虚构的数量相同，所以基本上是一本虚构、一本非虚构的。&lt;/p&gt;&lt;/blockquote&gt;&lt;h3&gt;《人生海海》&lt;/h3&gt;&lt;blockquote&gt;&lt;p&gt;开始时间：2020-02-07&lt;/p&gt;&lt;p&gt;完成时间：2020-02-09&lt;/p&gt;&lt;p&gt;评分：★★★★☆&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;发现了一个本土的好作家——麦家&lt;/p&gt;&lt;h3&gt;《牛奶可乐经济学》&lt;/h3&gt;&lt;blockquote&gt;&lt;p&gt;开始时间：2020-02-11&lt;/p&gt;&lt;p&gt;完成时间：2020-02-17&lt;/p&gt;&lt;p&gt;评分：★★★☆☆&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;一开始看感觉还挺好玩的，但看到3分之一时就觉得有些无趣了，可能因为经济学本来就不是什么太有趣的东西吧。ps：有种看十万个为什么的感觉。&lt;/p&gt;&lt;h3&gt;《白夜行》&lt;/h3&gt;&lt;blockquote&gt;&lt;p&gt;开始时间：2020-02-17&lt;/p&gt;&lt;p&gt;完成时间：2020-02-20&lt;/p&gt;&lt;p&gt;评分：★★★★★&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;东野圭吾的书，果然没让我失望，“枪虾和虾虎鱼的故事”，强烈推荐。&lt;/p&gt;&lt;h3&gt;《精进》&lt;/h3&gt;&lt;blockquote&gt;&lt;p&gt;开始时间：2020-02-17&lt;/p&gt;&lt;p&gt;完成时间：2020-02-19&lt;/p&gt;&lt;p&gt;评分：★★★☆☆&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;知乎式“干货”。第2，3章的一些观点感觉还不错，但后面真的是越看越无趣。&lt;/p&gt;&lt;h3&gt;《娱乐至死》&lt;/h3&gt;&lt;blockquote&gt;&lt;p&gt;开始时间：2020-02-19&lt;/p&gt;&lt;p&gt;完成时间：2020-02-21&lt;/p&gt;&lt;p&gt;评分：★★★★★&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;“人们感到痛苦的不是他们用笑声代替了思考，而是他们不知道自己为什么笑以及为什么不再思考。”&lt;/p&gt;&lt;p&gt;值得多读几遍的书籍。&lt;/p&gt;&lt;h3&gt;《美丽新世界》&lt;/h3&gt;&lt;blockquote&gt;&lt;p&gt;开始时间：2020-02-21&lt;/p&gt;&lt;p&gt;完成时间：2020-02-28&lt;/p&gt;&lt;p&gt;评分：★★★★★&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;看这本书是因为看了《娱乐至死》，hhh，貌似我在高中就看过开头，然而当时并没有看下去。&lt;/p&gt;&lt;h3&gt;《呼吸》&lt;/h3&gt;&lt;blockquote&gt;&lt;p&gt;开始时间：2020-02-21&lt;/p&gt;&lt;p&gt;完成时间：2020-02-23&lt;/p&gt;&lt;p&gt;评分：★★★★☆&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;看起来像是一部作品集，我对这本书的期望值好像有点过高了，有几篇读起来和寓言故事的感觉。恩，像是《一千零一夜》的感觉。&lt;/p&gt;&lt;h3&gt;《练习的心态》&lt;/h3&gt;&lt;blockquote&gt;&lt;p&gt;开始时间：2020-02-23&lt;/p&gt;&lt;p&gt;完成时间：2020-02-26&lt;/p&gt;&lt;p&gt;评分：★★★☆☆  &lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;翻译真的是太烂了吧，有些句子读起来都拗口难懂，书中观点也呈现的不够清晰（也可能是翻译的锅），不过感觉书中有些想法还是不错的，感觉看得下去完全是因为有些观点引起了共鸣。&lt;/p&gt;&lt;h3&gt;《月亮与六便士》&lt;/h3&gt;&lt;blockquote&gt;&lt;p&gt;开始时间：2020-02-29&lt;/p&gt;&lt;p&gt;结束时间：2020-03-01&lt;/p&gt;&lt;p&gt;评分：★★★★☆&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;我看的那个版本似乎特别冷门，感觉之后可以找其他版本来看看。&lt;/p&gt;&lt;h2&gt;2020-03&lt;/h2&gt;&lt;blockquote&gt;&lt;p&gt;这个月读书比较随意，经常同时读好几本书（后来感觉这样不好就改掉了），没想到这样还是读了10本。同时，因为购入了kpw4，所以有一半的书是在 Kindle 上读完的，而且也开始养成了睡前读书的习惯，10点半洗澡，洗完澡就爬到床上去读一个小时的书。感觉这样的生活还是很惬意的，emmm，虽然4月份就不一定有这种好氛围了，哎，美好的假期似乎要结束了。&lt;/p&gt;&lt;/blockquote&gt;&lt;h3&gt;《如何高效学习》&lt;/h3&gt;&lt;blockquote&gt;&lt;p&gt;开始时间：2020-03-02&lt;/p&gt;&lt;p&gt;结束时间：2020-03-04&lt;/p&gt;&lt;p&gt;评分：★★★★☆&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;我应该是第二遍读这本书了，看的时候不断地思考之前自己的做法，发现自己有段时间应该是在践行书中的一些观点的，但是后来似乎就没有有意识地去做这件事了。这也导致了自己有段时间也出现了死读书的情况，比如不思考地抄笔记，记录书中的观点什么的。&lt;/p&gt;&lt;h3&gt;《动物农场》&lt;/h3&gt;&lt;blockquote&gt;&lt;p&gt;开始时间：2020-03-03&lt;/p&gt;&lt;p&gt;结束时间：2020-03-04&lt;/p&gt;&lt;p&gt;评分：★★★★★&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;“目光从猪移到人，再从人移到猪，又重新从猪移到人，要分清哪张脸是猪的，哪张脸是人的，已经不可能了。”&lt;/p&gt;&lt;p&gt;看这本书最开始是因为想读这本书的原版，然而到现在都没开始（捂脸）。&lt;/p&gt;&lt;h3&gt;《掌控习惯》&lt;/h3&gt;&lt;blockquote&gt;&lt;p&gt;开始时间：2020-03-04&lt;/p&gt;&lt;p&gt;结束时间：2020-03-15&lt;/p&gt;&lt;p&gt;评分：★★★★☆&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;虽然看到后半部分就感觉有点无聊了，但是还是讲了许多关于习惯的技巧，比如想，将要养成的习惯挂在已经有的习惯后面等等。&lt;/p&gt;&lt;h3&gt;《孤独小说家》&lt;/h3&gt;&lt;blockquote&gt;&lt;p&gt;开始时间：2020-03-04&lt;/p&gt;&lt;p&gt;结束时间：2020-03-07&lt;/p&gt;&lt;p&gt;评分：★★★★☆&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;有点碎碎念的小说，看的时候感觉很平淡，但是莫名其妙看的进去。BTW，你要是说，这本书是耕平写的，我完全相信。&lt;/p&gt;&lt;h3&gt;《82年生的金智英》&lt;/h3&gt;&lt;blockquote&gt;&lt;p&gt;开始时间：2020-03-08&lt;/p&gt;&lt;p&gt;结束时间：2020-03-09&lt;/p&gt;&lt;p&gt;评分：★★★★☆&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;一本很快就能看完的书，晚上睡前看了一会，然后早上起来看了一会就看完。虽然写的是韩国的事情，但是把地点改成中国也完全不会有违和感。&lt;/p&gt;&lt;h3&gt;《1984》&lt;/h3&gt;&lt;blockquote&gt;&lt;p&gt;开始时间：2020-03-18&lt;/p&gt;&lt;p&gt;结束时间：2020-03-30&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;看完《娱乐至死》就已经决定要看的书了，一开始有点略微无聊，不过看到后面就还好。&lt;/p&gt;&lt;h3&gt;《房思琪的初恋乐园》&lt;/h3&gt;&lt;blockquote&gt;&lt;p&gt;开始时间：2020-03-09&lt;/p&gt;&lt;p&gt;结束时间：2020-03-13&lt;/p&gt;&lt;p&gt;评分：★★★★★&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;这个月让我印象最深刻的书，看这本书的这几天几乎陷进去了，那几天心情有点过于低落。这本书给人一种很奇怪的感觉，一开始看的时候会觉得作者的写作风格很奇怪，读到后半段的时候，会有种既厌恶又难以掩饰喜欢的感觉。&lt;/p&gt;&lt;h3&gt;《微习惯》&lt;/h3&gt;&lt;blockquote&gt;&lt;p&gt;开始时间：2020-03-13&lt;/p&gt;&lt;p&gt;结束时间：2020-03-31&lt;/p&gt;&lt;p&gt;评分：★★★★☆&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;很短的一本书，有种看博客集合的感觉，不过看完后，我也想试试“一个俯卧撑挑战”，hhh。&lt;/p&gt;&lt;h3&gt;《无人生还》&lt;/h3&gt;&lt;blockquote&gt;&lt;p&gt;开始时间：2020-03-20&lt;/p&gt;&lt;p&gt;结束时间：2020-03-21&lt;/p&gt;&lt;p&gt;评分：★★★★☆&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;士兵岛童谣杀人事件，估计是因为之前在其他地方看到过对这本书的模仿，所以看这本书的时候其实挺无感的。&lt;/p&gt;&lt;h3&gt;《禅与摩托车维修艺术》&lt;/h3&gt;&lt;blockquote&gt;&lt;p&gt;开始时间：2020-03-21&lt;/p&gt;&lt;p&gt;结束时间：2020-03-26&lt;/p&gt;&lt;p&gt;评分：★★★★☆&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;游记？哲学书？说实话有点没看懂，书中所说的“良质”是指“Good”吗？？&lt;/p&gt;&lt;h3&gt;总结 &amp;amp; Flag&lt;/h3&gt;&lt;p&gt;2 月份和 3 月份读的书都是和专业无关的，以后可以稍微增加一点专业相关的书籍。&lt;/p&gt;&lt;p&gt;接下来是下个月想读的书：&lt;/p&gt;&lt;ul class=&quot;contains-task-list&quot;&gt;&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; checked=&quot;&quot; disabled=&quot;&quot;/&gt; 别逗了，费曼先生&lt;/li&gt;&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; disabled=&quot;&quot;/&gt; 黑客与画家&lt;/li&gt;&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; disabled=&quot;&quot;/&gt; 肖申克的救赎&lt;/li&gt;&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; disabled=&quot;&quot;/&gt; 非暴力沟通&lt;/li&gt;&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; disabled=&quot;&quot;/&gt; 流浪地球&lt;/li&gt;&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; disabled=&quot;&quot;/&gt; 乌合之众&lt;/li&gt;&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; disabled=&quot;&quot;/&gt; Animal Farm&lt;/li&gt;&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; disabled=&quot;&quot;/&gt; 学习之道&lt;/li&gt;&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; disabled=&quot;&quot;/&gt; 深入浅出 Docker&lt;/li&gt;&lt;li class=&quot;task-list-item&quot;&gt;&lt;input type=&quot;checkbox&quot; disabled=&quot;&quot;/&gt; MySQL 必知必会&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;BTW, 想读 != 一定要读&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Gitea + Drone CI/CD]]></title><description><![CDATA[最近想实践一下 DevOps，所以准备搭建一套代码托管和CI/CD 系统。 技术选型 代码托管 代码托管系统的选择其实并不多： Gitea Gogs GitLab 由于  Gitlab  资源占用过大，所以可以直接去除（毕竟这个系统只有我一个人在用，而且只有一台1核2G…]]></description><link>https://codeand.fun/posts/2020/03/27/gitea-drone-ci-cd/</link><guid isPermaLink="false">https://codeand.fun/posts/2020/03/27/gitea-drone-ci-cd/</guid><pubDate>Fri, 27 Mar 2020 20:38:51 GMT</pubDate><content:encoded>&lt;p&gt;最近想实践一下 DevOps，所以准备搭建一套代码托管和CI/CD 系统。&lt;/p&gt;&lt;h2&gt;技术选型&lt;/h2&gt;&lt;h3&gt;代码托管&lt;/h3&gt;&lt;p&gt;代码托管系统的选择其实并不多：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Gitea&lt;/li&gt;&lt;li&gt;Gogs&lt;/li&gt;&lt;li&gt;GitLab&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;由于 &lt;code class=&quot;language-text&quot;&gt;Gitlab&lt;/code&gt; 资源占用过大，所以可以直接去除（毕竟这个系统只有我一个人在用，而且只有一台1核2G的服务器）。&lt;/p&gt;&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Gitea&lt;/code&gt;是脱胎于&lt;code class=&quot;language-text&quot;&gt;Gogs&lt;/code&gt;的，在&lt;code class=&quot;language-text&quot;&gt;Gogs&lt;/code&gt;上做了较多的扩展，而且迭代的也毕竟快。&lt;code class=&quot;language-text&quot;&gt;Gitea&lt;/code&gt;对现有的代码托管做了&lt;a href=&quot;https://docs.gitea.io/zh-cn/comparison/&quot;&gt;横向对比&lt;/a&gt;,
我们可以看出来&lt;code class=&quot;language-text&quot;&gt;Gitea&lt;/code&gt;几乎是最优选择。&lt;/p&gt;&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Gitea&lt;/code&gt;有一个比较显著的缺点，它没有像&lt;code class=&quot;language-text&quot;&gt;Gitlab&lt;/code&gt;一样内置了&lt;code class=&quot;language-text&quot;&gt;CI/CD&lt;/code&gt;，所以我们必须搭另外一套&lt;code class=&quot;language-text&quot;&gt;CI/CD&lt;/code&gt;系统。&lt;/p&gt;&lt;h3&gt;CI/CD&lt;/h3&gt;&lt;p&gt;对现有的 CI/CD 进行了一下调研:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Jenkins&lt;ul&gt;&lt;li&gt;优点：最为流行，出现坑的容易找到解决方案&lt;/li&gt;&lt;li&gt;缺点：用 Java 编写，过于笨重&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;GitLab CI&lt;ul&gt;&lt;li&gt;优点：据说很好用&lt;/li&gt;&lt;li&gt;缺点：笨重&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Drone&lt;ul&gt;&lt;li&gt;优点：轻量级，支持&lt;code class=&quot;language-text&quot;&gt;Gitea&lt;/code&gt;&lt;/li&gt;&lt;li&gt;缺点：生态不够丰富，文档差&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;在这里我们选择&lt;code class=&quot;language-text&quot;&gt;Drone&lt;/code&gt;作为&lt;code class=&quot;language-text&quot;&gt;CI/CD&lt;/code&gt;，主要原因当然是因为只有它轻量级啊。&lt;/p&gt;&lt;h2&gt;Gitea&lt;/h2&gt;&lt;p&gt;在安装&lt;code class=&quot;language-text&quot;&gt;Gitea&lt;/code&gt;和&lt;code class=&quot;language-text&quot;&gt;Drone&lt;/code&gt;时，我们都选择使用&lt;code class=&quot;language-text&quot;&gt;docker-compose&lt;/code&gt;来管理，因此需要先安装&lt;code class=&quot;language-text&quot;&gt;docker&lt;/code&gt;和&lt;code class=&quot;language-text&quot;&gt;docker-compose&lt;/code&gt;。&lt;/p&gt;&lt;p&gt;创建一个&lt;code class=&quot;language-text&quot;&gt;gitea&lt;/code&gt;文件夹，并在该文件夹下创建&lt;code class=&quot;language-text&quot;&gt;docker-compose.yml&lt;/code&gt;文件：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yml&quot;&gt;&lt;pre class=&quot;language-yml&quot;&gt;&lt;code class=&quot;language-yml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;2&amp;quot;&lt;/span&gt;

&lt;span class=&quot;token key atrule&quot;&gt;networks&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;gitea&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;external&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean important&quot;&gt;false&lt;/span&gt;

&lt;span class=&quot;token key atrule&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; gitea/gitea&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1.11&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; USER_UID=1000
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; USER_GID=1000
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; RUN_MODE=prod
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; SSH_PORT= 3022 &lt;span class=&quot;token comment&quot;&gt;#SSH端口&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; SSH_DOMAIN= &lt;span class=&quot;token comment&quot;&gt;#IP地址或URL&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; DISABLE_REGISTRATION=False &lt;span class=&quot;token comment&quot;&gt;#取消注册&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; always
    &lt;span class=&quot;token key atrule&quot;&gt;networks&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; gitea
    &lt;span class=&quot;token key atrule&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; ./gitea&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;/data
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; /etc/timezone&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;/etc/timezone&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;ro
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; /etc/localtime&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;/etc/localtime&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;ro
    &lt;span class=&quot;token key atrule&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;3000:3000&amp;quot;&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;3022:3022&amp;quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这里面需要注意的是，设置&lt;code class=&quot;language-text&quot;&gt;SSH_PORT&lt;/code&gt;和&lt;code class=&quot;language-text&quot;&gt;SSH_DOMAIN&lt;/code&gt;，这样 gitea 生成的 repo SSH 链接才是能直接使用的形式。&lt;/p&gt;&lt;p&gt;填写完后，直接&lt;code class=&quot;language-text&quot;&gt;docker-compose up -d&lt;/code&gt;开启服务即可，第一次登陆时，会跳出一个安装页面，可以设置所使用的数据库和管理员账号，同时要记得检查一下 SSH 端口和域名是否正确。&lt;/p&gt;&lt;h2&gt;Drone&lt;/h2&gt;&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;Drone&lt;/code&gt;的安装比&lt;code class=&quot;language-text&quot;&gt;Gitea&lt;/code&gt;复杂的多，同时需要先在&lt;code class=&quot;language-text&quot;&gt;Gitea&lt;/code&gt;中创建&lt;code class=&quot;language-text&quot;&gt;OAuth2&lt;/code&gt;应用程序：&lt;/p&gt;&lt;p&gt;打开&lt;code class=&quot;language-text&quot;&gt;Gitea&lt;/code&gt;的页面 -&amp;gt; 个人信息 -&amp;gt; 应用 -&amp;gt; 管理 OAuth2 应用程序&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://imagehosting.wuxiaobai24.fun/blogGitea-Drone-CI-CD-20200327211442-2020-03-27&quot; alt=&quot;Gitea-Drone-CI-CD-20200327211442-2020-03-27&quot;/&gt;&lt;/p&gt;&lt;p&gt;应用名称填什么都无所谓，但是重定向 URL 比较重要，要填 &lt;code class=&quot;language-text&quot;&gt;Drone&lt;/code&gt;服务的地址（虽然现在还没启动），比如说，你的 Drone 的 &lt;code class=&quot;language-text&quot;&gt;ip&lt;/code&gt; 地址为&lt;code class=&quot;language-text&quot;&gt;1.2.3.4&lt;/code&gt;，&lt;code class=&quot;language-text&quot;&gt;Drone&lt;/code&gt;端口的为&lt;code class=&quot;language-text&quot;&gt;8000&lt;/code&gt;，
那么就可以填&lt;code class=&quot;language-text&quot;&gt;http://1.2.3.4:8000&lt;/code&gt;。&lt;/p&gt;&lt;p&gt;创建后会得到一个客户端ID和客户端密钥。这时，&lt;code class=&quot;language-text&quot;&gt;Gitea&lt;/code&gt;的设置就已经完成了。&lt;/p&gt;&lt;p&gt;为了让&lt;code class=&quot;language-text&quot;&gt;Drone Server&lt;/code&gt;和&lt;code class=&quot;language-text&quot;&gt;Drone Runer&lt;/code&gt;能够通过&lt;code class=&quot;language-text&quot;&gt;RPC&lt;/code&gt;连接，我们需要生成&lt;code class=&quot;language-text&quot;&gt;RPC&lt;/code&gt;密钥，可以在 shell 中使用该命令来生成随机数，用该随机数作为 RPC 的密钥&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;$ openssl rand -hex &lt;span class=&quot;token number&quot;&gt;16&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;上面的操作中可以得到：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;客户端 ID&lt;/li&gt;&lt;li&gt;客户端密钥&lt;/li&gt;&lt;li&gt;RPC 密钥&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;创建一个&lt;code class=&quot;language-text&quot;&gt;drone&lt;/code&gt;文件夹并在其中创建一个&lt;code class=&quot;language-text&quot;&gt;docker-compose.yml&lt;/code&gt;文件：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yml&quot;&gt;&lt;pre class=&quot;language-yml&quot;&gt;&lt;code class=&quot;language-yml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot;3.5&amp;quot;&lt;/span&gt;

&lt;span class=&quot;token key atrule&quot;&gt;networks&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;drone&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; drone_network

&lt;span class=&quot;token key atrule&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 
  &lt;span class=&quot;token key atrule&quot;&gt;drone-server&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; drone/drone&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; 8000&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; 443&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;443&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;networks&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; drone
    &lt;span class=&quot;token key atrule&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; ./drone&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;/var/lib/drone
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; /var/run/docker.sock&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;/var/run/docker.sock
    &lt;span class=&quot;token key atrule&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; always
    &lt;span class=&quot;token key atrule&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; DRONE_GITEA_CLIENT_ID= &lt;span class=&quot;token comment&quot;&gt;# Gitea 客户端ID&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; DRONE_GITEA_CLIENT_SECRET= &lt;span class=&quot;token comment&quot;&gt;# Gitea 客户端密钥&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; DRONE_GITEA_SERVER= &lt;span class=&quot;token comment&quot;&gt;# Gitea URL 地址&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; DRONE_GITEA=true
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; DRONE_RPC_SECRET= &lt;span class=&quot;token comment&quot;&gt;# Drone RPC 密钥&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; DRONE_SERVER_HOST= &lt;span class=&quot;token comment&quot;&gt;# Drone URL,可以填域名或 ip:port&lt;/span&gt;
	  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; DRONE_SERVER_PROTO=http &lt;span class=&quot;token comment&quot;&gt;# Drone 所使用的协议 http 或者 https&lt;/span&gt;
	  &lt;span class=&quot;token comment&quot;&gt;# 由于我的 Gitea 的设置是只允许登陆用户访问代码的，所以 Git 需要 Auth&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; DRONE_GIT_ALWAYS_AUTH=true
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; DRONE_GIT_USERNAME= &lt;span class=&quot;token comment&quot;&gt;# Gitea 用户名&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; DRONE_GIT_PASSWORD= &lt;span class=&quot;token comment&quot;&gt;# Gitea 密码&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;drone-agent&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; drone/drone&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;runner&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;docker&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;restart&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; always
    &lt;span class=&quot;token key atrule&quot;&gt;depends_on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; drone&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;server
    &lt;span class=&quot;token key atrule&quot;&gt;networks&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; drone
    &lt;span class=&quot;token key atrule&quot;&gt;volumes&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; /var/run/docker.sock&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;/var/run/docker.sock
    &lt;span class=&quot;token key atrule&quot;&gt;environment&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; DRONE_RPC_SECRET= &lt;span class=&quot;token comment&quot;&gt;# 这里的密钥要和 Server 一样&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; DRONE_RPC_PROTO=http
      &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; DRONE_RPC_HOST= &lt;span class=&quot;token comment&quot;&gt;# 和上面的 DRONE_SERVER_HOST&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;和&lt;code class=&quot;language-text&quot;&gt;Gitea&lt;/code&gt;同理，我们只需要在&lt;code class=&quot;language-text&quot;&gt;docker-compose up -d&lt;/code&gt;即可。&lt;/p&gt;&lt;p&gt;第一次打开 Drone 会先跳到 Gitea 进行验证。由于打开 Drone 会验证 Gitea 是否登陆，所以不用担心 Drone 的页面直接暴露到公网。&lt;/p&gt;&lt;h3&gt;测试 Drone 和 Gitea&lt;/h3&gt;&lt;ol&gt;&lt;li&gt;在 Gitea 中创建一个 repo&lt;/li&gt;&lt;li&gt;在 Drone 激活该 repo&lt;/li&gt;&lt;li&gt;创建公钥并加入到 gitea 中（这一步和 Github 类似）&lt;/li&gt;&lt;li&gt;将 repo clone 到本地&lt;/li&gt;&lt;li&gt;创建一个&lt;code class=&quot;language-text&quot;&gt;.drone.yml&lt;/code&gt;文件：&lt;/li&gt;&lt;li&gt;git commit and push&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;.drone.yml&lt;/code&gt;的样例如下：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yml&quot;&gt;&lt;pre class=&quot;language-yml&quot;&gt;&lt;code class=&quot;language-yml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; pipeline
&lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; docker
&lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; default

&lt;span class=&quot;token key atrule&quot;&gt;steps&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; greeting
  &lt;span class=&quot;token key atrule&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; alpine
  &lt;span class=&quot;token key atrule&quot;&gt;commands&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; echo hello
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; echo world&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;关于&lt;code class=&quot;language-text&quot;&gt;.drone.yml&lt;/code&gt;的信息可以查看&lt;a href=&quot;https://docs.drone.io/&quot;&gt;官方文档&lt;/a&gt;。&lt;/p&gt;&lt;p&gt;之后估计也会写一篇 blog 对 Drone 的使用进行下总结。&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Flutter 官方文档学习记录]]></title><description><![CDATA[编写第一个 Flutter 应用 Get Start 在 Flutter 中，几乎所有都是 widget，包括对齐 (alignment)、填充 (padding) 和布局 (layout)。 一个 widget 的主要工作是提供一个 build…]]></description><link>https://codeand.fun/posts/2020/02/10/flutter-guan-fang-wen-dang-xue-xi-ji-lu/</link><guid isPermaLink="false">https://codeand.fun/posts/2020/02/10/flutter-guan-fang-wen-dang-xue-xi-ji-lu/</guid><pubDate>Mon, 10 Feb 2020 19:39:54 GMT</pubDate><content:encoded>&lt;h2&gt;编写第一个 Flutter 应用&lt;/h2&gt;&lt;blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://flutter.cn/docs/get-started/codelab&quot;&gt;Get Start&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;ul&gt;&lt;li&gt;在 Flutter 中，几乎所有都是 widget，包括对齐 (alignment)、填充 (padding) 和布局 (layout)。&lt;/li&gt;&lt;li&gt;一个 widget 的主要工作是提供一个 build() 方法来描述如何根据其他较低级别的 widgets 来显示自己。&lt;/li&gt;&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;pubspec.yml&lt;/code&gt;文件管理 Flutter 应用的资源（assests），如图片或 package。&lt;/li&gt;&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;flutter pub get&lt;/code&gt;可以按照&lt;code class=&quot;language-text&quot;&gt;pubspec.yml&lt;/code&gt;安装包，BTW，在你一保存该文件时，vscode 会自动帮你执行该命令。&lt;/li&gt;&lt;li&gt;每次 MaterialApp（或者说 组件）需要渲染时，或者在 Flutter inspector 中切换平台时 build 方法都会执行&lt;/li&gt;&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Stateless Widgets&lt;/code&gt;是不可变的，即所有值都是&lt;code class=&quot;language-text&quot;&gt;final&lt;/code&gt;的&lt;/li&gt;&lt;li&gt;Stateful widgets 持有的状态可能在 widget 生命周期中发生变化，实现一个 stateful widget 至少需要两个类： 1）一个 StatefulWidget 类；2）一个 State 类，StatefulWidget 类本身是不变的，但是 State 类在 widget 生命周期中始终存在。&lt;/li&gt;&lt;li&gt;在 Dart 语言中使用下划线前缀标识符，会强制其变成私有。&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Dart 开发语言概览&lt;/h2&gt;&lt;blockquote&gt;&lt;p&gt;&lt;a href=&quot;https://dart.cn/guides/language/language-tour&quot;&gt;https://dart.cn/guides/language/language-tour&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;ul&gt;&lt;li&gt;所有变量引用都是&lt;strong&gt;对象&lt;/strong&gt;，每个对象都是一个&lt;strong&gt;类&lt;/strong&gt;的实例，包括数字，函数和null。所有类都继承与 Object 类。所有变量的初始值都是&lt;code class=&quot;language-text&quot;&gt;null&lt;/code&gt;&lt;/li&gt;&lt;li&gt;Dart 是强类型语言，但是支持类型推断，并且可以用&lt;code class=&quot;language-text&quot;&gt;dynamic&lt;/code&gt;声明不确定的类型。&lt;/li&gt;&lt;li&gt;Dart中用以 &lt;code class=&quot;language-text&quot;&gt;_&lt;/code&gt; 开头的标识符来标识 私有。&lt;/li&gt;&lt;li&gt;建议通过&lt;code class=&quot;language-text&quot;&gt;var&lt;/code&gt;来声明局部变量而非指定其类型，如&lt;code class=&quot;language-text&quot;&gt;var i = 1;&lt;/code&gt;&lt;/li&gt;&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;final&lt;/code&gt;关键词修饰变量表示该变量只能被初始化一次，而&lt;code class=&quot;language-text&quot;&gt;const&lt;/code&gt;关键词修饰变量表示该变量是编译时常量。如果用&lt;code class=&quot;language-text&quot;&gt;const&lt;/code&gt;修改类中的变量，则必须为其加上&lt;code class=&quot;language-text&quot;&gt;static&lt;/code&gt;关键字，即&lt;code class=&quot;language-text&quot;&gt;static const&lt;/code&gt;。&lt;/li&gt;&lt;li&gt;可以将构造函数声明为 const，这种构造函数创建的对象是不可变的。&lt;/li&gt;&lt;li&gt;Dart 内置类型&lt;code class=&quot;language-text&quot;&gt;numbers&lt;/code&gt;,&lt;code class=&quot;language-text&quot;&gt;strings&lt;/code&gt;,&lt;code class=&quot;language-text&quot;&gt;booleans&lt;/code&gt;,&lt;code class=&quot;language-text&quot;&gt;lists&lt;/code&gt;,&lt;code class=&quot;language-text&quot;&gt;sets&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;maps&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;runes&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;symbols&lt;/code&gt;。&lt;/li&gt;&lt;li&gt;&lt;/li&gt;&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Flutter 安装记录]]></title><description><![CDATA[起因 最近想开始写日记了，但是找了一圈发现好像好用又安全的App几乎没有，主要是怕不安全。很多App是不支持导出什么的,而且存在别人的服务器上总感觉不好，要是公司倒闭了，我们的日记岂不是全没有，就算有导出功能，要迁移到另一个App…]]></description><link>https://codeand.fun/posts/2020/02/10/flutter-an-zhuang-ji-lu/</link><guid isPermaLink="false">https://codeand.fun/posts/2020/02/10/flutter-an-zhuang-ji-lu/</guid><pubDate>Mon, 10 Feb 2020 17:42:33 GMT</pubDate><content:encoded>&lt;h2&gt;起因&lt;/h2&gt;&lt;p&gt;最近想开始写日记了，但是找了一圈发现好像好用又安全的App几乎没有，主要是怕不安全。很多App是不支持导出什么的,而且存在别人的服务器上总感觉不好，要是公司倒闭了，我们的日记岂不是全没有，就算有导出功能，要迁移到另一个App上好像也是很麻烦的样子。而那些支持保存到Webdev上基本是不加密的，也很危险啊。Whatever，我现在有点想做一个移动端的东西，也就是日记本。&lt;/p&gt;&lt;p&gt;调研了一圈，移动端基本上有三种选择：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Java + Android&lt;/li&gt;&lt;li&gt;React Native&lt;/li&gt;&lt;li&gt;Flutter &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;三者之中，Java + Android 应该是最稳的，毕竟有点 Java 基础；React Native 应该是最理想的，因为很容易就迁移到网页上啊；Flutter 应该算是一个比较激进的做法了，比较新技术，有许多坑，不过现在应该还是算挺多人在用了。作为一个有志向的开发者，踩坑才是最好玩的事情啊。whatever，我觉得用 Flutter 来实现这个东西了。BTW，写这篇东西一方面是为了记录安装中遇到的坑，另一方面也是立Flag（捂脸）。&lt;/p&gt;&lt;h2&gt;安装 Flutter&lt;/h2&gt;&lt;p&gt;我使用的环境是 Manjaro Linux，所以可以不按照官网上的方法下载包然后安装，直接：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; pacman -S flutter&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;安装完后显示下面这个东西，只需要按照他这里说明的进行一些配置即可。有一点要注意的是，这些命令全部都需要 root 权限，即在命令前面加 sudo 即可。&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://imagehosting.wuxiaobai24.fun/blogFlutter-%E5%AE%89%E8%A3%85%E8%AE%B0%E5%BD%95-20200210175913-2020-2-10&quot; alt=&quot;安装Flutter后的输出&quot;/&gt;&lt;/p&gt;&lt;p&gt;基本上就安装成功了，可以按照&lt;code class=&quot;language-text&quot;&gt;flutter.cn&lt;/code&gt;中给出的安装教程一步步走即可。&lt;/p&gt;&lt;h2&gt;国情带来的坑&lt;/h2&gt;&lt;p&gt;在第一次运行&lt;code class=&quot;language-text&quot;&gt;flutter doctor&lt;/code&gt;之前记得把镜像源配置好，这里可以参考&lt;img src=&quot;https://flutter.dev/community/china&quot; alt=&quot;官方文档&quot;/&gt;：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;FLUTTER_STORAGE_BASE_URL&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;https://mirrors.tuna.tsinghua.edu.cn/flutter
&lt;span class=&quot;token builtin class-name&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;PUB_HOSTED_URL&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;https://mirrors.tuna.tsinghua.edu.cn/dart-pub&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后&lt;code class=&quot;language-text&quot;&gt;Gradle&lt;/code&gt;也有一个镜像源需要配置：&lt;/p&gt;&lt;p&gt;一个是项目中&lt;code class=&quot;language-text&quot;&gt;android/gradle/build.gradle&lt;/code&gt;:&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;groovy&quot;&gt;&lt;pre class=&quot;language-groovy&quot;&gt;&lt;code class=&quot;language-groovy&quot;&gt;buildscript &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    ext&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;kotlin_version &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;#x27;1.3.50&amp;#x27;&lt;/span&gt;
    repositories &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// google()&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// jcenter()&lt;/span&gt;
        maven &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; url &lt;span class=&quot;token string&quot;&gt;&amp;#x27;https://maven.aliyun.com/repository/google&amp;#x27;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        maven &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; url &lt;span class=&quot;token string&quot;&gt;&amp;#x27;https://maven.aliyun.com/repository/jcenter&amp;#x27;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        maven &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; url &lt;span class=&quot;token string&quot;&gt;&amp;#x27;http://maven.aliyun.com/nexus/content/groups/public&amp;#x27;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    dependencies &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        classpath &lt;span class=&quot;token string&quot;&gt;&amp;#x27;com.android.tools.build:gradle:3.5.0&amp;#x27;&lt;/span&gt;
        classpath &lt;span class=&quot;token string gstring&quot;&gt;&amp;quot;org.jetbrains.kotlin:kotlin-gradle-plugin:&lt;span class=&quot;token expression&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;$&lt;/span&gt;kotlin_version&lt;/span&gt;&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

allprojects &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    repositories &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// google()&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// jcenter()&lt;/span&gt;
        maven &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; url &lt;span class=&quot;token string&quot;&gt;&amp;#x27;https://maven.aliyun.com/repository/google&amp;#x27;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        maven &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; url &lt;span class=&quot;token string&quot;&gt;&amp;#x27;https://maven.aliyun.com/repository/jcenter&amp;#x27;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        maven &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; url &lt;span class=&quot;token string&quot;&gt;&amp;#x27;http://maven.aliyun.com/nexus/content/groups/public&amp;#x27;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;还是有&lt;code class=&quot;language-text&quot;&gt;/opt/flutter/packags/flutter_tools/gradle/flutter.gradle&lt;/code&gt;&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;groovy&quot;&gt;&lt;pre class=&quot;language-groovy&quot;&gt;&lt;code class=&quot;language-groovy&quot;&gt;buildscript &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    repositories &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// google()&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// jcenter()&lt;/span&gt;
        
        maven &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; url &lt;span class=&quot;token string&quot;&gt;&amp;#x27;https://plugins.gradle.org/m2/&amp;#x27;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        maven &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; url &lt;span class=&quot;token string&quot;&gt;&amp;#x27;http://maven.aliyun.com/nexus/content/repositories/google&amp;#x27;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        maven &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; url &lt;span class=&quot;token string&quot;&gt;&amp;#x27;http://maven.aliyun.com/nexus/content/groups/public/&amp;#x27;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        maven &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; url &lt;span class=&quot;token string&quot;&gt;&amp;#x27;http://maven.aliyun.com/nexus/content/repositories/jcenter&amp;#x27;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[Chromebook 体验]]></title><description><![CDATA[剁手的心路历程 缘起 大概是暑假的时候，刷手机的时候刷到了和Chromebook有点关系的东西吧，好像是在v2ex上看到了FydeOS的软文。随后就去了解了一下这个操作系统，从描述上来看，轻办公的话，好像还是不错的。讲道理，当时就挺心动了，好奇心驱使着我下载了FydeOS的ISO…]]></description><link>https://codeand.fun/posts/2019/10/07/chromebook/</link><guid isPermaLink="false">https://codeand.fun/posts/2019/10/07/chromebook/</guid><pubDate>Mon, 07 Oct 2019 19:50:44 GMT</pubDate><content:encoded>&lt;h2&gt;剁手的心路历程&lt;/h2&gt;&lt;h3&gt;缘起&lt;/h3&gt;&lt;p&gt;大概是暑假的时候，刷手机的时候刷到了和Chromebook有点关系的东西吧，好像是在v2ex上看到了FydeOS的软文。随后就去了解了一下这个操作系统，从描述上来看，轻办公的话，好像还是不错的。讲道理，当时就挺心动了，好奇心驱使着我下载了FydeOS的ISO，并在U盘上体验了一番，感觉略卡，顿时就没有了兴趣，而且他们家推的那款电脑好像看起来很廉价，2k的价格为啥我不去买iPad呢？因为当时刚发布没多久好像没看到几个评测，所以慢慢就对其失去了想法，但是关于Chromebook的种子已经埋在了我心里。&lt;/p&gt;&lt;h3&gt;重逢&lt;/h3&gt;&lt;p&gt;开学没多久就到了中秋，因为是新生，所以入学那几天都是不用上课的，但是也上了一天（刚好周四课贼多），所以感觉在上那些无聊的课程时如果能有个iPad或轻薄本的话应该会挺方便的。&lt;/p&gt;&lt;p&gt;大概是中秋假期的某个晚上，刷手机时又刷到了和Chromebook有关的东西吧，买一台Chromebook的想法又从我心中浮起。当时刚好比较闲，在Chromebook吧上看各位老哥关于Chromebook的分享和评测，并跑去下来一个CloudReady的镜像在虚拟机上玩耍了一下。虽然说是因为比较闲才去干这些的，但是其实当时应该是算在评估Chromebook对自己是否适合了。回想一下当时得出的结果应该是这样的：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Chromebook大多数比较轻薄，续航较好，很适合做二奶机（自己的笔记本太大太重了）&lt;/li&gt;&lt;li&gt;买对的机器的话，可以很方便的开一个Linux的虚拟机（对自己来说有一定的生产力，本人常年使用Linux）&lt;/li&gt;&lt;li&gt;很多情况需要梯子（反正我的梯子也没断过）&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;从上面来看，这东西应该是挺适合我的。因为贴吧有位老哥对三星那款Chromebook Plus做了评测，而且本人有点颜值党，所以对三星这款还是比较满意的。&lt;/p&gt;&lt;h3&gt;剁手&lt;/h3&gt;&lt;p&gt;由于Chromebook没有在国内发行，所以淘宝和京东什么的是搜不到什么东西的，想要买Chromebook大概就只有几种途径：&lt;/p&gt;&lt;ol&gt;&lt;li&gt;海淘&lt;/li&gt;&lt;li&gt;肉身翻出去买（因为在深圳，所以去香港澳门买东西还是比较方便的）&lt;/li&gt;&lt;li&gt;闲鱼收二手&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;恩，因为价格的原因，所以我还是选择了最轻松方便的闲鱼。在多次翻阅和比较后，我发现了一个比Chromebook Plus更好的选择，那就是Chromebook Plus v2。之所以说他是更好的选择，最主要是因为当时有位老哥给出来1k4的价格（因为机器A面有个小坑和两条划痕所以才那么低的），而且这款是支持电信LTE的。剁手嘛，总是会有点冲动的，在看到这个价格后没多久，我就和那位老哥联系了一下，并拍下了这款。&lt;/p&gt;&lt;h2&gt;Chromebook Plus V2 体验&lt;/h2&gt;&lt;h3&gt;硬件篇&lt;/h3&gt;&lt;p&gt;因为不是特别懂这块的东西，所以就不班门弄斧了，这里之见见主观的想法：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;键盘不算好，应该是低于笔记本的平均水平的，但是也不差，起码比MacBook的好（前几天刚好去体检店玩了一下，没有回弹的键盘实在是太难受了），同时键盘和普通的有点区别，首先没有Win键（这可以理解，毕竟本来就不打算让你装window嘛），其次caps lock键被换成了搜索键（搞得我现在用其他笔记本的时候老是按caps lock），最后他的F1-F12全部被替换成了一些功能键（好像问题不大，有些情况下好像还是会映射成对于F&lt;em&gt;键的，比如开启开发者模式后，Ctrl+Shift+F&lt;/em&gt;打开另一个tty，这和Linux的传统是一样的）。&lt;/li&gt;&lt;li&gt;触控板挺好用的，用来那么久了，基本没想过要插一个鼠标。&lt;/li&gt;&lt;li&gt;4G内存+32GB SSD实在是有点不够用啊，内存占有常年是满的，32GB装完系统和必要的东西后，基本上10GB都不一定有。&lt;/li&gt;&lt;li&gt;屏幕相当不错，触摸屏也挺好的。&lt;/li&gt;&lt;li&gt;摄像头没怎么体验过，两个摄像头好像都挺烂的，不过一般人也不会在笔记本上用到摄像头。&lt;/li&gt;&lt;li&gt;S Pen配合一些软件用起来相当好，就是笔有点小，拿久了会不舒服。&lt;/li&gt;&lt;li&gt;Chromebook Plus V2相比与Chromebook Plus多了一个LTE版本，亲测，可以插电信卡（应该是只能插电信卡），而且网络效果还行，没事不会断掉（断掉就重启），个人认为对于Chromebook这种上网本来说，随时随地的网络还是比较重要的，这也是我买V2版本的原因。&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;软件篇&lt;/h3&gt;&lt;p&gt;这部分是这篇文章的重点（写这篇文章的主要想法就是想记录下Chromebook上一些好用的应用），主要分为3个部分来展开，这三个部分是分别从Chrome，Linux，Android三个平台来介绍各个软件。&lt;/p&gt;&lt;h4&gt;Chrome&lt;/h4&gt;&lt;blockquote&gt;&lt;p&gt;Chrome主要是介绍一些插件和应用。&lt;/p&gt;&lt;/blockquote&gt;&lt;ul&gt;&lt;li&gt;Proxy SwitchyOmega：搭梯子时用到的&lt;/li&gt;&lt;li&gt;Adblock Plus：广告拦截&lt;/li&gt;&lt;li&gt;Evernote Web Clipper: 其实我已经弃用Evernote挺久的了，但是在Chromebook上Evernote的确是一个挺好的选择（主要是他安卓上优化的好，后面会提）&lt;/li&gt;&lt;li&gt;OneTab：一键把所有打开的Tab收起来，在Chromebook这种小内存的机子上，这东西太有用了&lt;/li&gt;&lt;li&gt;Vimium：在浏览器上使用vim快捷键，喜欢vim的和键盘党可以试一下，不适合大部分人&lt;/li&gt;&lt;li&gt;All-in-One Messenger：用来打开网页版的微信还是不错的选择，但在Chromebook上用微信的次数不多，不确定有没有更好的选择&lt;/li&gt;&lt;li&gt;Cog：用来看Chromebook的硬件信息的，感觉还可以，主要是能看到内存和CPU占用（Chromebook自带的任务管理器看不了，不过最近发现Ctrl + Alt + T打开crosh，里面自带了top命令，会用的人可以考虑用top）&lt;/li&gt;&lt;li&gt;Google Keep：ChromeOS自带，和S Pen配合还是挺好用的，但是同步需要梯子。&lt;/li&gt;&lt;li&gt;Minimalist Markdown Editor：很小巧的Markdown编辑器，这篇文章就是在这上面编辑的（当初码字还是很舒服的）&lt;/li&gt;&lt;li&gt;Secure Shell App：SSH Client，大半的生产力在上面，不过对中文的兼容不是很好，主要体现在输入中文时，显示会乱掉（估计是没有实时刷新），但是现在还没有找到更好的选择。同时他还可以安装SFTP到文件管理器上，感觉还算挺好用的&lt;/li&gt;&lt;li&gt;TeamViewer：TeamViewer是我见过全平台做的最好的一款产品了，虽然不常用，但是总是会有需要它的时候。&lt;/li&gt;&lt;li&gt;Text：自带的文本编辑器，编辑一下简单的文本文件（比如V2ray的配置文件）还是挺好用的。&lt;/li&gt;&lt;li&gt;Code Pad Text Editor: 代码编辑器，写这篇文章期间发现的，第一感觉还可以&lt;/li&gt;&lt;li&gt;&lt;del&gt;马克飞象：用来做Markdown编辑器还是挺好的，足够好看，而且能够同步到印象笔记中，但是他要收费，所以最后还是弃了&lt;/del&gt;&lt;/li&gt;&lt;li&gt;Firefox Send：传一些中小文件用的，速度上还不错，但是有点比较麻烦的就是它不是通过特殊的PIN码来分享，而是URL。把一个URL传到另一个机器上和传一个文件到另一个机器上的麻烦程度其实是一样的，个人认为这是它最大的缺点。不过我后面会有解决（妥协）办法。&lt;/li&gt;&lt;li&gt;Pushbullet：一个多平台的App，可以比较方便的传输信息，文件（传文件和图片什么的其实很慢），这就是用来解决Firefox Send需要把URL传到另一个机器上的方法。&lt;/li&gt;&lt;/ul&gt;&lt;h4&gt;Linux&lt;/h4&gt;&lt;p&gt;这部分只是简单介绍一下Chromebook上三个不同的Linux环境以及对它们的一些评价吧。&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;ChromeOS&lt;/p&gt;&lt;p&gt;众所周知，ChromeOS其实是一个Linux的发行版，所以在crosh输入shell其实是可以进入一个Linux环境的，但是ChromeOS的确不像其他常用的Linux发行版，他的终端支持的东西太少了，以至于很多东西想要安装上去其实很困难，例如如果你想要安装v2ray的话，通过go.sh其实是安装不上去的（反正我没成功）。同时，这个环境好像会因为ChromeOS的升级而被破换掉（亲身经历过，但不确定是不是运气刚好比较差）。因此，个人是不建议在这个环境安装太多东西的，不过还是有人弄出来一个ChromeOS的包管理器（chromebrew)，梯子好的话，安装起来并不困难，但是感觉没什么太大用处，我机子上只是用它安装了V2ray而已。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Crostini&lt;/p&gt;&lt;p&gt;这个东西是现在官方在推的，弄起来比较方便，在设置里面开启Linux终端，用起来还是比较方便的。这东西就是在ChromeOS上起了一个Linux的虚拟机，装的是Debian系统（有需要是可以换成其他系统的，在Reddit上有帖子介绍如何在把Debian换成Arch Linux），如果只是想要个命令行来跑一些小程序，用这个还是不错的，debian虽然装东西不如Arch那么方便，但是生态还是不错的，大部分Linux的软件都会有deb包。同时这个东西还有一点比较好的就是在这里面装GUI软件的话，其实可以很方便的在ChromeOS上打开（有点像VirtualBox的无缝模式），不过这样打开的软件是没法使用ChromeOS的输入法的，需要在debian上安装中文环境和输入法（这个网上介绍挺多的，不细讲）。BTW，由于屏幕是高分屏，然后Linux对其支持不太好，所以字体会显示的很小（有低分辨率模式，不过建议不要用，太糊了）&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Crouton&lt;/p&gt;&lt;p&gt;没搞懂这东西的原理，简单介绍一下他的效果吧。看起来也像是开了一个Linux虚拟机的样子，安装时可以选择不同的发行版（不过选择不多，基本都是debian系的，比如Ubuntu，Kail），同时可以选择安装不同的桌面（比如Unity，xfce，KDE）。一般情况下打开后切换到装好的Linux系统的桌面上，然后你就可以使用这个Linux啦，就像在虚拟机里面开全屏模式一样，可以用&lt;code class=&quot;language-text&quot;&gt;Ctrl + Alt + -&amp;gt;&lt;/code&gt;和&lt;code class=&quot;language-text&quot;&gt;Ctrl + Alt + &amp;lt;-&lt;/code&gt;在ChromeOS和Linux之间切换。这东西和Crostini一样也需要自己安装中文环境和输入法。要切来切去肯定比较麻烦，但是它还有个叫xiwi的东西可以实现在ChromeOS上打开LinuxGUI应用，不过体验没有Crostini好，也一样会有高分屏的问题。
还有一点比较重要的就是，Crouton安装起来比较麻烦，大部分包可以用镜像很快的下载下来，但是有个包没办法。个人的解决方法就是先直接用镜像安装，失败后再加http代理。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;说实话，ChromeOS对Linux的支持是我最不满意的一部分，无论那种方式都有很多坑，而且有些好像没法解决（起码我现在还没有解决办法）。我现在的情况是，在ChromeOS上只使用Chromebrew安装v2ray，然后开发用Crostini。对于Crouton，我是直接弃掉了。不过Crostini中文上的确支持不好，他的终端App和Secure Shell App采用的估计是同一套代码，所以中文输入时一样会乱掉。不知道什么原因，在Crostini上使用vscode实在是太卡了，卡成PPT的那种。&lt;/p&gt;&lt;h4&gt;Android&lt;/h4&gt;&lt;p&gt;个人觉得，ChromeOS蹭Android的应用的确满足了一部分人的刚需，Android上的一部分应用在Chromebook表现的非常好，当然也有坑点，但是相对于Linux那部分，个人还是比较满意Android的表现的。&lt;/p&gt;&lt;ul&gt;&lt;li&gt;MS Office 三件套：Word和ppt应该对大部分人来说是无法避免的东西。不过有点不好的就是，这个东西如果没有Office 365账号的话，是只能看，不能修改的。（hhh，我有学生账号）如果不想订阅Office 365的话，可以考虑下WPS，但是我感觉没有微软出的好用。BTW，&lt;strong&gt;大部分Android应用在用键盘输入的时候，输入法的提示栏会跑到左上方去，所以会很难受。&lt;/strong&gt;&lt;/li&gt;&lt;li&gt;OneDrive：同步神器（才不是因为有1TB容量我才用它的呢）&lt;/li&gt;&lt;li&gt;Squid：手写神器，试了很多款，就这个好用点，做做简单的笔记，免费版其实已经够用了。其实收费版好像也就导入PDF有点吸引力，不过这东西不支持PDF的书签，能导入PDF好像也没太大作用&lt;/li&gt;&lt;li&gt;Xodo：PDF神器，手写支持的很好（就是有时候有点卡）&lt;/li&gt;&lt;li&gt;Evernote：点名表扬一下，这个可能是对Chromebook支持最好的了，他会把输入法的提示栏拉到当前输入的位置（虽然会闪一下，但是相比其他的好很多了）&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;总结&lt;/h2&gt;&lt;p&gt;总的来说，Chromebook作为一个二奶机，还是很不错的选择，不贵的价格（特指二手的），足够好的屏幕和续航。虽然软件应用上还做的不够，但是这在一些轻办公环境下已经相当不错了。&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Use Travis CI]]></title><description><![CDATA[今天简单使用了一下 Travis CI 。 起因 因为搭建 Django-blog 时，每次更新一次代码，就需要手动登陆到服务器上进行一系列操作来重启服务，感觉过于麻烦且容易出错，因此想使用 CI/CD 工具来自动化这一过程。 所以这里就简单了解了一下 CI/CD…]]></description><link>https://codeand.fun/posts/2019/08/20/use-travis-ci/</link><guid isPermaLink="false">https://codeand.fun/posts/2019/08/20/use-travis-ci/</guid><pubDate>Tue, 20 Aug 2019 00:30:27 GMT</pubDate><content:encoded>&lt;p&gt;今天简单使用了一下&lt;a href=&quot;https://travis-ci.org&quot;&gt;Travis CI&lt;/a&gt;。&lt;/p&gt;&lt;h2&gt;起因&lt;/h2&gt;&lt;p&gt;因为搭建&lt;a href=&quot;https://github.com/wuxiaobai24/django-blog&quot;&gt;Django-blog&lt;/a&gt;时，每次更新一次代码，就需要手动登陆到服务器上进行一系列操作来重启服务，感觉过于麻烦且容易出错，因此想使用 CI/CD 工具来自动化这一过程。&lt;/p&gt;&lt;p&gt;所以这里就简单了解了一下 CI/CD，并尝试使用 &lt;a href=&quot;https://travis-ci.org&quot;&gt;Travis CI&lt;/a&gt; 来实现 Hexo 的自动化部署。&lt;/p&gt;&lt;p&gt;但考虑到 Travis CI 是一个 SaaS 服务，需要开发服务器的权限来完成部署，所以后面应该会先将&lt;code class=&quot;language-text&quot;&gt;Django-blog&lt;/code&gt;的部署方式转换成&lt;code class=&quot;language-text&quot;&gt;Docker&lt;/code&gt;的方式，然后在搭建&lt;code class=&quot;language-text&quot;&gt;Drone&lt;/code&gt;或&lt;code class=&quot;language-text&quot;&gt;Jenkins&lt;/code&gt;来完成 CI/CD&lt;/p&gt;&lt;h2&gt;CI/CD&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;CI(Continuous Integration)即&lt;strong&gt;持续集成&lt;/strong&gt;，个人理解是在提交代码后进行一些了测试来确保代码的正确性，保证每个开发者每次提交都会进行测试。&lt;/li&gt;&lt;li&gt;CD(Continuous Deploy)即&lt;strong&gt;自动部署&lt;/strong&gt;，个人理解是在完成了测试后将代码自动化的部署到服务器上，这样就不需要开发者或运维来手动进行代码拉取，设置配置，重启服务等操作了，而是将其自动化。&lt;strong&gt;这个东西其实就是我想要的&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Travis CI&lt;/h2&gt;&lt;p&gt;要使用&lt;code class=&quot;language-text&quot;&gt;Travis CI&lt;/code&gt;来完成自动化部署&lt;code class=&quot;language-text&quot;&gt;hexo&lt;/code&gt;可以分为以下几个步骤：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;在&lt;code class=&quot;language-text&quot;&gt;Travis CI&lt;/code&gt;网站上将 repo 加入构建&lt;/li&gt;&lt;li&gt;在Github生成&lt;code class=&quot;language-text&quot;&gt;Github Access Token&lt;/code&gt;并将其加入到&lt;code class=&quot;language-text&quot;&gt;Travis CI&lt;/code&gt;的环境变量中，这里使用的变量名是&lt;code class=&quot;language-text&quot;&gt;GITHUB_TOKEN&lt;/code&gt;&lt;/li&gt;&lt;li&gt;在repo上添加一个&lt;code class=&quot;language-text&quot;&gt;Travis CI&lt;/code&gt;的配置文件：&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;下面是&lt;code class=&quot;language-text&quot;&gt;.travis.yml&lt;/code&gt;配置文件&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;langaue&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; node_js
&lt;span class=&quot;token key atrule&quot;&gt;node_js&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; stable

&lt;span class=&quot;token key atrule&quot;&gt;branches&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;only&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; save

&lt;span class=&quot;token key atrule&quot;&gt;before_install&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; npm install &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;g hexo&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;cli
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; git clone https&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;//github.com/smduan/next.git themes/next

&lt;span class=&quot;token key atrule&quot;&gt;install&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; npm install
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; npm install hexo&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;deployer&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;git &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;save
    
&lt;span class=&quot;token key atrule&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; mv _next_config.yml themes/next/_config.yml
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; hexo clean
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; hexo generate

&lt;span class=&quot;token key atrule&quot;&gt;after_script&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; git config user.name &amp;quot;wuxiaobai24&amp;quot;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; git config user.email &amp;quot;wuxiaobai24@foxmail.com&amp;quot;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; sed &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;i &amp;quot;s/GITHUB_TOKEN/$&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;GITHUB_TOKEN&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;/g&amp;quot; ./_config.yml
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; hexo deploy&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[记一次Hexo迁移]]></title><description><![CDATA[很久没有写过Blog了, 而且也把系统换成了Manjaro, 所以又要再配置一次Hexo的环境等等, 为了下次迁移的时候, 能更快的搞定, 所以记录一下这次迁移的过程. 获取源文件 Hexo如果需要迁移的话, 只需要保留以下几个文件即可: _config.yml theme…]]></description><link>https://codeand.fun/posts/2019/02/14/ji-yi-ci-hexo-qian-yi/</link><guid isPermaLink="false">https://codeand.fun/posts/2019/02/14/ji-yi-ci-hexo-qian-yi/</guid><pubDate>Thu, 14 Feb 2019 09:08:44 GMT</pubDate><content:encoded>&lt;blockquote&gt;&lt;p&gt;很久没有写过Blog了, 而且也把系统换成了Manjaro, 所以又要再配置一次Hexo的环境等等, 为了下次迁移的时候, 能更快的搞定, 所以记录一下这次迁移的过程.&lt;/p&gt;&lt;/blockquote&gt;&lt;h2&gt;获取源文件&lt;/h2&gt;&lt;p&gt;Hexo如果需要迁移的话, 只需要保留以下几个文件即可:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;_config.yml&lt;/li&gt;&lt;li&gt;theme/&lt;/li&gt;&lt;li&gt;source/&lt;/li&gt;&lt;li&gt;scaffold/&lt;/li&gt;&lt;li&gt;package.json&lt;/li&gt;&lt;li&gt;.gitignore&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;因为之前已经迁移过一次了, 所以我的源文件都已经保存在github上了, 在&lt;a href=&quot;https://github.com/wuxiaobai24/wuxiaobai24.github.io&quot;&gt;wuxiaobai24.github.io&lt;/a&gt;起了一个&lt;code class=&quot;language-text&quot;&gt;save&lt;/code&gt;分支来保存文件.&lt;/p&gt;&lt;p&gt;所以获取源文件, 我只需要:&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shell&quot;&gt;&lt;pre class=&quot;language-shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; clone git@github.com:wuxiaobai24/wuxiaobai24.github.io.git&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2&gt;安装Hexo&lt;/h2&gt;&lt;p&gt;这一步网上大多教程都写的很清楚了, 这里简略提一下, 主要是以下几个步骤:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;安装npm&lt;/li&gt;&lt;li&gt;用npm安装hexo&lt;/li&gt;&lt;li&gt;hexo init blog&lt;/li&gt;&lt;li&gt;把上面提到的源文件全部拷贝到blog文件夹中&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;strong&gt;注意:这里的blog文件最好放在wuxiaobai24.github.io目录下&lt;/strong&gt;, 这样利用backups.sh可以很快的把源文件拷贝到blog文件夹中, 但是&lt;strong&gt;记得把backups.sh里面最后三行关于git的删去或注释掉&lt;/strong&gt;&lt;/p&gt;&lt;h2&gt;安装依赖&lt;/h2&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;首先先把主题安装下来先, 之前因为忘记了这个, 导致&lt;code class=&quot;language-text&quot;&gt;hexo generate&lt;/code&gt;失败&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shell&quot;&gt;&lt;pre class=&quot;language-shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;$ &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; clone git@github.com:litten/hexo-theme-yilia.git themes/yilia&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;npm install&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;检测是否成功&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;shell&quot;&gt;&lt;pre class=&quot;language-shell&quot;&gt;&lt;code class=&quot;language-shell&quot;&gt;$ hexo g
$ hexo s&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h2&gt;构建快速的写作环境&lt;/h2&gt;&lt;ol&gt;&lt;li&gt;将blog移到任何你想要放的位置, 然后把之前的&lt;code class=&quot;language-text&quot;&gt;wuxiaobai24.github.io&lt;/code&gt;文件夹删去&lt;/li&gt;&lt;li&gt;在blog目录下, &lt;code class=&quot;language-text&quot;&gt;git clone git@github.com:wuxiaobai24/wuxiaobai24.github.io.git&lt;/code&gt;&lt;/li&gt;&lt;li&gt;在vscode中安装&lt;code class=&quot;language-text&quot;&gt;vscode-hexo&lt;/code&gt;插件&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;主要的工作流为:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;vscode中&lt;code class=&quot;language-text&quot;&gt;&amp;gt; hexo new&lt;/code&gt;生成新的文章&lt;/li&gt;&lt;li&gt;写文章, 并&lt;code class=&quot;language-text&quot;&gt;&amp;gt; hexo generate&lt;/code&gt;&lt;/li&gt;&lt;li&gt;vscode中&lt;code class=&quot;language-text&quot;&gt;&amp;gt; hexo deplot&lt;/code&gt;部署&lt;/li&gt;&lt;li&gt;最后在命令行下切换到&lt;code class=&quot;language-text&quot;&gt;blog/wuxiaobai24.github.io&lt;/code&gt;中, 执行&lt;code class=&quot;language-text&quot;&gt;backups.sh&lt;/code&gt;备份源文件.&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;PS: 个人建议把主题的config.yml也备份一下.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[k近邻算法]]></title><description><![CDATA[刚看了有关 kNN 的东西，总结一下： kNN算法（k-近邻算法）是一种可用于分类和回归的非参数统计方法。 分类算法：最近的k个邻居进行投票得到类别 回归算法：最近的k…]]></description><link>https://codeand.fun/posts/2018/02/13/k-jin-lin-suan-fa/</link><guid isPermaLink="false">https://codeand.fun/posts/2018/02/13/k-jin-lin-suan-fa/</guid><pubDate>Tue, 13 Feb 2018 22:21:27 GMT</pubDate><content:encoded>&lt;p&gt;刚看了有关&lt;code class=&quot;language-text&quot;&gt;kNN&lt;/code&gt;的东西，总结一下：&lt;/p&gt;&lt;p&gt;kNN算法（k-近邻算法）是一种可用于分类和回归的非参数统计方法。&lt;/p&gt;&lt;ul&gt;&lt;li&gt;分类算法：最近的k个邻居进行投票得到类别&lt;/li&gt;&lt;li&gt;回归算法：最近的k个邻居的平均数&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;这里只讨论分类算法。&lt;/p&gt;&lt;p&gt;先给个直观的理解，比如现在我们要判断一个人是男生还是女生，我们只考虑身高、体重这两个特征。显然如何两个人的身高体重越相近，那么他们的性别就越相近。kNN就是基于这个直观的想法来做的，如果我们要判断&lt;code class=&quot;language-text&quot;&gt;x&lt;/code&gt;是什么类别，我们就在&lt;code class=&quot;language-text&quot;&gt;train data&lt;/code&gt;中找出与&lt;code class=&quot;language-text&quot;&gt;x&lt;/code&gt;最相邻的&lt;code class=&quot;language-text&quot;&gt;k&lt;/code&gt;个数据，然后通过投票机制来觉得最后的分类。&lt;/p&gt;&lt;p&gt;这里我们就需要定义距离了：&lt;/p&gt;&lt;p&gt;简单的就用欧几里得距离（即&lt;code class=&quot;language-text&quot;&gt;L2&lt;/code&gt;距离）
&lt;span class=&quot;math math-inline&quot;&gt;\sqrt((x_1 - y_1)^2 + ... + (x_2 - y_2)^2)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;给出demo代码（参考机器学习实战）：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;classify0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;inX&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; dataSet&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; labels&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; k&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    dataSetSize &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; dataSet&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;shape&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# 欧式距离计算&lt;/span&gt;
    diffMat &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; np&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;tile&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;inX&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dataSetSize&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; dataSet
    sqDiffMat &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; diffMat&lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;
    sqDistance &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; sqDiffMat&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token builtin&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;axis&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    distances &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; sqDistance&lt;span class=&quot;token operator&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0.5&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;#找出前k个距离最小的sample&lt;/span&gt;
    sortedDistIndicies &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; distances&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;argsort&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;# 这里返回的是indicies&lt;/span&gt;
    classCount &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;k&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        voteIlabel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; labels&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;sortedDistIndicies&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
        classCount&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;voteIlabel&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; classCount&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;get&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;voteIlabel&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
    sortedClassCount &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;classCount&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;items&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
                              key&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;operator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;itemgetter&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; reverse&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; sortedClassCount&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[杂记-2017-11-26]]></title><description><![CDATA[2017-11-26 悠闲的下午（其实只是不想写作业，不想背单词）我觉得写一篇blog来总结一下，毕竟已经过去了大半个学期。 这学期课很多，收获也很多。 从9月份的某一天开始，每天刷LeetCode,每天写Blog…]]></description><link>https://codeand.fun/posts/2017/11/26/za-ji-20171126/</link><guid isPermaLink="false">https://codeand.fun/posts/2017/11/26/za-ji-20171126/</guid><pubDate>Sun, 26 Nov 2017 14:40:57 GMT</pubDate><content:encoded>&lt;p&gt;2017-11-26&lt;/p&gt;&lt;p&gt;悠闲的下午（其实只是不想写作业，不想背单词）我觉得写一篇blog来总结一下，毕竟已经过去了大半个学期。&lt;/p&gt;&lt;p&gt;这学期课很多，收获也很多。&lt;/p&gt;&lt;p&gt;从9月份的某一天开始，每天刷LeetCode,每天写Blog,每天背单词。&lt;/p&gt;&lt;p&gt;说实话，习惯的力量真的很强大，其实每天刷道题这种想法早在上学期就有了，但是没错做几天就放弃了，最可怕的是一放弃，再次拿起来的时候就是下一次开始了。&lt;/p&gt;&lt;p&gt;不知道是不是因为这次每天都会写&lt;code class=&quot;language-text&quot;&gt;blog&lt;/code&gt;来记录刷题的过程，所以一直有个激励，虽然说有时候会因为做题而花很多时间（而且我的课又多），有时候也会因为没有时间而不得不找一道水题来做，不过即使是水题，换成暑假的我估计也做不出来，而且像&lt;code class=&quot;language-text&quot;&gt;dp&lt;/code&gt;的问题，之前是怎么都想不出来的，现在也慢慢的有了思路。&lt;/p&gt;&lt;p&gt;这种解决问题能力的提升算得上是这学期最大的收获了吧！&lt;/p&gt;&lt;p&gt;还有一些其他的，比如说上了一门大四的课（虽然个人感觉难度并没有大三的某些课难），进入冯老师的实验室做&lt;code class=&quot;language-text&quot;&gt;ML&lt;/code&gt;,虽然我什么都不会，恩，一点一点的学吧。&lt;/p&gt;&lt;p&gt;说了那么多好的事情，总要反省一下：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;至今没有养成好好看书的好习惯（好像这学期忙到课本都没好好看了）&lt;/li&gt;&lt;li&gt;Machine Learning 还菜的要死，虽然现在师兄师姐们不嫌弃（不知道是不是真的不嫌弃），但是还是要好好赶上去啊&lt;/li&gt;&lt;li&gt;一直没能好好锻炼身体，希望身体不要虚下去（这种时候一生病就惨咯）&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;恩，以后每天晚上都要去自习室学习&lt;code class=&quot;language-text&quot;&gt;Machine Learning&lt;/code&gt;的东西，每天都要把学到的东西总结一下。（等下就总结之前学的东西）&lt;/p&gt;&lt;p&gt;恍恍惚惚的好像大三又过去了一半，虽然已经决定读研了，但是感觉还是看不清未来的样子，也不知道之后会遇到什么，成为什么，whaterver,慢慢的走下去吧。&lt;/p&gt;</content:encoded></item><item><title><![CDATA[VBO_and_VAO.md]]></title><description><![CDATA[最近在写计算机图形学的期中作业，写一个简易的俄罗斯方块。在写的过程中感觉好像之前暑假看的 OpenGL 的东西都忘光光了，所以还是及时的写写笔记吧！ 顶点数组对象： Vertex Array Object,vao 顶点缓冲对象：Vertex Buffer Object,vbo…]]></description><link>https://codeand.fun/posts/2017/10/01/vbo-and-vao-md/</link><guid isPermaLink="false">https://codeand.fun/posts/2017/10/01/vbo-and-vao-md/</guid><pubDate>Sun, 01 Oct 2017 16:37:52 GMT</pubDate><content:encoded>&lt;p&gt;最近在写计算机图形学的期中作业，写一个简易的俄罗斯方块。在写的过程中感觉好像之前暑假看的&lt;code class=&quot;language-text&quot;&gt;OpenGL&lt;/code&gt;的东西都忘光光了，所以还是及时的写写笔记吧！&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;顶点数组对象： Vertex Array Object,vao&lt;/p&gt;&lt;p&gt;顶点缓冲对象：Vertex Buffer Object,vbo&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;在敲代码的时候就觉得老是会搞混这两个概念，所以今天就总结一下。&lt;/p&gt;&lt;p&gt;先来段代码：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; VERTICES_NUM &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    vec3 vertices&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;VERTICES_NUM&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    GLuint vao&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;glGenVertexArrays&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;vao&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;glBindVertexArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vao&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    GLuint buffer&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;glGenBuffers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;glBindBuffer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;GL_ARRAY_BUFFER&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;glBufferData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;GL_ARRAY_BUFFER&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vertices&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;vertices&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;CL_STATIC_DRAW&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    GLuint program &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;InitShader&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;quot;vshader.glsl&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;quot;fshader.glsl&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;glUseProgram&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;program&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    GLuint location &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;glGetAttribLocation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;program&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;quot;vPosition&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;glEnableVertexAttribArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;location&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;glVertexAttribPointer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;location&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;GL_FLOAT&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;GL_FALSE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;BUFFER_OFFSET&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token function&quot;&gt;glClearColor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;OpenGL里的对象都是通过&lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt;来管理的,有的地方叫做名字，或者说标识符，whatever,我们在这里统一用id。我们需要用&lt;code class=&quot;language-text&quot;&gt;glGen*&lt;/code&gt;模式的函数来获取未使用的id，这里的id可以想成是指针。&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;GLuint vao&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;                  &lt;span class=&quot;token comment&quot;&gt;//用来存放id的数组&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;glGenVertexArrays&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;vao&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;       &lt;span class=&quot;token comment&quot;&gt;//获取id，第一个参数是想要获取的个数&lt;/span&gt;
                                &lt;span class=&quot;token comment&quot;&gt;//第二个参数是存放这些id的数组&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;现在我们有了顶点数组对象的&lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt;了（换句话说，我们有了一个可以存放地址的指针），我们就需要真正的&lt;code class=&quot;language-text&quot;&gt;new&lt;/code&gt;一个对象出来。&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token function&quot;&gt;glBindVertexArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;vao&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;如果vao非0，并且是&lt;code class=&quot;language-text&quot;&gt;glGenVertexArrays()&lt;/code&gt;返回的，那么它创建一个新的顶点数组，并且==并且与其名称向关联==&lt;/li&gt;&lt;li&gt;如果vao已经被绑定到一个顶点数组对象中，那么这个函数的作用就是激活这个顶点数组。&lt;/li&gt;&lt;li&gt;如果为0，那么OpenGL将不再使用程序所分配的顶点数组对象，并且OpenGL状态将重设为顶点数组的默认状态。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;第一个很好理解就是等价于&lt;code class=&quot;language-text&quot;&gt;new&lt;/code&gt;,第二个作用可以理解为根据&lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt;获取对象（对指针解引用），第三个作用是在每次对某个顶点数组对象操作完后对当前顶点数组对象进行解绑。&lt;/p&gt;&lt;p&gt;有&lt;code class=&quot;language-text&quot;&gt;new&lt;/code&gt;就会有&lt;code class=&quot;language-text&quot;&gt;delete&lt;/code&gt;&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//void glDeleteVertexArray(GLsizei n,GLuint *arrays);&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;glDeleteVertexArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;vao&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;我们还可以判断一个&lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt;是否是一个用&lt;code class=&quot;language-text&quot;&gt;glGenVertexArray()&lt;/code&gt;创建并且没有被删除的顶点数组对象的&lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt;:&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;GLboolean &lt;span class=&quot;token function&quot;&gt;glIsVertexArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;GLuint array&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;现在我们已经有一个vao了，但是我们好像还不知道vao有什么用，要回答这个问题，我们还需要一些其他的背景知识，所以这个问题放到后面再回答。&lt;/p&gt;&lt;p&gt;我们之所以需要VAO与VBO是因为我们想要把某些顶点数组发送给图像渲染pipeline，而pipleline需要接受一些Vertex Data,然后再进行一些变换或修改并渲染。&lt;/p&gt;&lt;p&gt;&lt;img src=&quot;https://learnopengl-cn.github.io/img/01/04/pipeline.png&quot;/&gt;&lt;/p&gt;&lt;p&gt;我们在定义了顶点数据之后，我们需要把他发送给顶点着色器，我们的顶点数据通常是放在GPU的内存中的，我们利用顶点缓冲对象(vertext buffer objects,vbo)进行管理&lt;/p&gt;&lt;p&gt;vbo也有相应的函数进行申请&lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt;，绑定等等，与vao类似：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;glGenBuffers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;GLsizei n&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;GLuint &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;buffers&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;glBindBuffers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;GLenum traget&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;GLuint buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//target 的值可以为：&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//      GL_ARRAY_BUFFER&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//      GL_ELEMENT_ARRAY_BUFFER&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//      ...&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;glDeleteBuffers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;GLsizei n&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; GLuint &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;buffers&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
GLboolean &lt;span class=&quot;token function&quot;&gt;glIsBuffers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;GLuint buffer&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在申请完&lt;code class=&quot;language-text&quot;&gt;id&lt;/code&gt;并绑定后，我们可以想GPU的内存发送数组:&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;glBufferData&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;GLenum target&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;GLsizeiptr size&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;cons GLvoid &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;GLenum usage&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//target 与上面glBindBuffers的类似，&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//usage 是设置读取和写入的方式&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//      GL_STREAM_DRAM&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//      GL_DYNAMICDRAM&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//      ...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;在我们向GPU内存中发送完数据后，我们可能需要告诉OpenGL如何解释我们的数据:&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;GLuint location &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;glGetAttribLocation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;program&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&amp;quot;vPosition&amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;glEnableVertexAttribArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;location&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token function&quot;&gt;glVertexAttribPointer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;location&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;GL_FLOAT&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;GL_FALSE&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;BUFFER_OFFSET&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;我们先要向着色器程序获取顶点属性的位置值，即&lt;code class=&quot;language-text&quot;&gt;GLuint location = glGetAttribLocation(program,&amp;quot;vPosition&amp;quot;);&lt;/code&gt;我们应该可以在&lt;code class=&quot;language-text&quot;&gt;vshader.glsl&lt;/code&gt;中看到这样一句话&lt;code class=&quot;language-text&quot;&gt;in vec3 vPosition&lt;/code&gt;,他表示的是我们会给他一个类型为vec3的输入值，而&lt;code class=&quot;language-text&quot;&gt;glGetAttribLocation&lt;/code&gt;可以获取这个输入值的位置，这样我们才可以把我们的数据和这里的&lt;code class=&quot;language-text&quot;&gt;vPosition&lt;/code&gt;绑定起来。&lt;/p&gt;&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;glEnableVertexAttribArray(location)&lt;/code&gt;启用顶点属性（默认是禁用的)&lt;/p&gt;&lt;p&gt;而&lt;code class=&quot;language-text&quot;&gt;glVertexAttribPointer(location,3,GL_FLOAT,GL_FALSE,0,BUFFER_OFFSET(0));&lt;/code&gt;才是真正告诉OpenGL如何解释的函数。&lt;/p&gt;&lt;p&gt;他的参数解释分别为：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;顶点属性的位置值&lt;/li&gt;&lt;li&gt;顶点属性大小，因为我们传入的是&lt;code class=&quot;language-text&quot;&gt;vec3&lt;/code&gt;,所以是3&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;有了这些东西，我们就可以绘制某个物体了，但是如果我们需要绘制多个物体呢，这时VAO的作用就出来了。&lt;/p&gt;&lt;p&gt;如果我们只使用VBO，我们可能需要重复的调用&lt;code class=&quot;language-text&quot;&gt;glVertexAttribPointer&lt;/code&gt;等。&lt;/p&gt;&lt;p&gt;我们可以通过VAO来管理这些琐碎的设置，一个VAO会存储以下内容：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;glEnableVertexAttribArray&lt;/code&gt;和&lt;code class=&quot;language-text&quot;&gt;glDisableVertexAttribArray&lt;/code&gt;的调用。&lt;/li&gt;&lt;li&gt;通过&lt;code class=&quot;language-text&quot;&gt;glVertexAttribPointer&lt;/code&gt;设置的顶点属性配置。&lt;/li&gt;&lt;li&gt;通过&lt;code class=&quot;language-text&quot;&gt;glVertexAttribPointer&lt;/code&gt;调用与顶点属性关联的顶点缓冲对象。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;有了vao后，我们只需要在每次绘制前&lt;code class=&quot;language-text&quot;&gt;glBindVertexArray(vao)&lt;/code&gt;即可。&lt;/p&gt;</content:encoded></item><item><title><![CDATA[约瑟夫环]]></title><description><![CDATA[今天上数据结构实验课，有道题是约瑟夫环，感觉挺好玩的，就拿出来总结一下（今天的LeetCode那道题真的是太Easy了）。 约瑟夫环是一个数学的应用问题：已知n个人（以编号1，2，3...n分别表示）围坐在一张圆桌周围。从编号为k的人开始报数，数到m…]]></description><link>https://codeand.fun/posts/2017/09/28/yue-se-fu-huan-shi-xian/</link><guid isPermaLink="false">https://codeand.fun/posts/2017/09/28/yue-se-fu-huan-shi-xian/</guid><pubDate>Thu, 28 Sep 2017 19:12:00 GMT</pubDate><content:encoded>&lt;p&gt;今天上数据结构实验课，有道题是约瑟夫环，感觉挺好玩的，就拿出来总结一下（今天的LeetCode那道题真的是太Easy了）。&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;约瑟夫环是一个数学的应用问题：已知n个人（以编号1，2，3...n分别表示）围坐在一张圆桌周围。从编号为k的人开始报数，数到m的那个人出列；他的下一个人又从1开始报数，数到m的那个人又出列；依此规律重复下去，直到圆桌周围的人全部出列。&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;这里是用双向循环链表实现的：&lt;/p&gt;&lt;p&gt;先是类的申明：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;JCircle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ListNode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; val&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ListNode &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;prior&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;ListNode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; v&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;ListNode &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;ListNode &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;p &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;v&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;prior&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;p&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;friend&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;JCircle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getVal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; val&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	ListNode &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getNext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; next&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	ListNode &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getPrior&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; prior&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;JCircle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	ListNode &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;head&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; size&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;JCircle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token operator&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;JCircle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;move&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; k&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;token comment&quot;&gt;//向前移动k步 &lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;del&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;			&lt;span class=&quot;token comment&quot;&gt;//删除head所指向的ListNode并返回其 val &lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; k&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;	&lt;span class=&quot;token comment&quot;&gt;//报数 &lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;friend&lt;/span&gt; ostream &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;operator&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ostream&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; out&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;JCircle &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;jc&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; size &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;类的实现：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;JCircle&lt;/span&gt;&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;JCircle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	size &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	head &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ListNode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NULL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	head&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; head&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	head&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;prior &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; head&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ListNode &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;p &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; head&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt; n&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		p&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ListNode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;p&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		p&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;prior &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; p&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		p &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; p&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	head&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;prior &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; p&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token class-name&quot;&gt;JCircle&lt;/span&gt;&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;JCircle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	ListNode &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;p&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;size&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		p &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; head&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		head &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; head&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt; p&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;JCircle&lt;/span&gt;&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;move&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; k&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//	cout &amp;lt;&amp;lt; &amp;quot;move&amp;quot;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; k&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
		head &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; head&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//	cout &amp;lt;&amp;lt; &amp;quot; over\n&amp;quot;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;JCircle&lt;/span&gt;&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;del&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;size &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		ListNode &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;p &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; head&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; ret &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; p&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;val&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		head &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; head&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt; p&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		head&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; head&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;prior &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; head&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		size&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; ret&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	size&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	head&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;prior &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; head&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;prior&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	head&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;prior&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; head&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	ListNode &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;p &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; head&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; t &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; p&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;val&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	head &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; head&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt; p&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; t&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 

&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;JCircle&lt;/span&gt;&lt;span class=&quot;token double-colon punctuation&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; k&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;move&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;k&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;//	cout &amp;lt;&amp;lt; &amp;quot;count&amp;quot;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;del&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

ostream &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;operator&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ostream&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; out&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;JCircle &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt;jc&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	ListNode &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;p &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; jc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;head&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; n &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; jc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;size&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;token operator&quot;&gt;--&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		out &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; p&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getVal&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot; &amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		p &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; p&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getNext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;//out &amp;lt;&amp;lt; &amp;quot;asdsad\n&amp;quot;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; out&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;测试：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;
&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	
	&lt;span class=&quot;token comment&quot;&gt;//test&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;//人数  开始位置  报数 &lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;  n&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;  k&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;       m&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;cin &lt;span class=&quot;token operator&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; n &lt;span class=&quot;token operator&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; k &lt;span class=&quot;token operator&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt; m&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
		JCircle &lt;span class=&quot;token function&quot;&gt;jc&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;n&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		jc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;move&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;k&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;//cout &amp;lt;&amp;lt; jc &amp;lt;&amp;lt; endl; &lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;jc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
			cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; jc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;m&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&amp;quot; &amp;quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		cout &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; endl&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;想写这个的原因是，我写了很久，事实上回到宿舍写多一遍的时候，我也写了很久（现在是20:16:00），写了一个多小时了，感觉自己还不怎么熟悉一些的基本数据结构（虽然已经在之前的学院上过一次了，恩，相当水的一门课）。&lt;/p&gt;&lt;p&gt;重写一遍的感觉是，该掉的坑，我还是掉下去了，之前写了的一遍的效果就是，我能比较快的爬出来，而且不会纠结于选择双向链表还是单向链表。&lt;/p&gt;&lt;p&gt;写的过程中，也体会了一下双向链表的坑点：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;size==2&lt;/code&gt;时，不能用常规方法&lt;code class=&quot;language-text&quot;&gt;delete&lt;/code&gt;掉自己。&lt;/li&gt;&lt;li&gt;加入size会减少一些常见的错误，一些实现敲起来也会简单点（唯一一个一开始就选择正确的点）。&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;感觉以后要多总结一些一些基本的数据结构，不然做算法题的时候，会很难找到适合的数据结构。&lt;/p&gt;</content:encoded></item><item><title><![CDATA[链表排序]]></title><description><![CDATA[今天中午在 Lintcode 上刷了一道题—— 链表排序 题目很短： 在 O( n  log  n…]]></description><link>https://codeand.fun/posts/2017/09/19/lian-biao-pai-xu/</link><guid isPermaLink="false">https://codeand.fun/posts/2017/09/19/lian-biao-pai-xu/</guid><pubDate>Tue, 19 Sep 2017 13:45:00 GMT</pubDate><content:encoded>&lt;p&gt;今天中午在&lt;a href=&quot;http://www.lintcode.com&quot;&gt;Lintcode&lt;/a&gt;上刷了一道题——&lt;a href=&quot;http://www.lintcode.com/zh-cn/problem/sort-list/&quot;&gt;链表排序&lt;/a&gt;&lt;/p&gt;&lt;p&gt;题目很短：&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;在 O(&lt;em&gt;n&lt;/em&gt; log &lt;em&gt;n&lt;/em&gt;) 时间复杂度和常数级的空间复杂度下给链表排序。&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;最近几天也在做排序算法的实验，所以看到这道题想刷一下。&lt;/p&gt;&lt;p&gt;从题目的要求我们可以大概的想出几种能达到要求的排序：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;快速排序&lt;/li&gt;&lt;li&gt;归并排序&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;这里是归并排序的实现：&lt;/p&gt;&lt;p&gt;归并排序的大概思路是：&lt;/p&gt;&lt;p&gt;在待排序列中找到中间元素，将待排序列分成两个待排序列，分别对这两个待排序列递归地调用归并排序，当待排序列中元素只剩一个时，序列显然有序。&lt;/p&gt;&lt;p&gt;现在只需要将两个有序序列合并成一个有序序列。&lt;/p&gt;&lt;hr/&gt;&lt;p&gt;实现：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ListNode&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; val&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  ListNode&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; next&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;ListNode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; v&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;v&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;nullptr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

ListNode &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sortList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ListNode &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; head&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// write your code here&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;head &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;head&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; head&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  
  ListNode &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;fast&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;slow&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  fast &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; slow &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; head&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fast&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;nullptr&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; fast&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;nullptr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    fast &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; fast&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    slow &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; slow&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  fast &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; slow&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  slow &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; slow&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  fast&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;nullptr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  fast &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sortList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;head&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  slow &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;sortList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;slow&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;mergeList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fast&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;slow&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

ListNode &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;mergeList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;ListNode &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;l1&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;ListNode &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;l2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;l1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; l2&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;l2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; l1&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  ListNode&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; ret &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;ListNode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  ListNode&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;p &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ret&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;l1 &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; l2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;l1&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;val &lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; l2&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;val&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      ret&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; l2&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      ret &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ret&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      l2 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; l2&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      ret&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; l1&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      ret &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ret&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
      l1 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; l1&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  ret&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;l1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;l1&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;l2&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  ret &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; p&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;delete&lt;/span&gt; p&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; ret&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这里的难点就是找出中间元素，将一个序列分成两个序列，这里的实现是&lt;code class=&quot;language-text&quot;&gt;快慢指针&lt;/code&gt;来实现的，即：&lt;/p&gt;&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;ListNode &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;fast&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;slow&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
fast &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; slow &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; head&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;fast&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;nullptr&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; fast&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;nullptr&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  fast &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; fast&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  slow &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; slow&lt;span class=&quot;token operator&quot;&gt;-&amp;gt;&lt;/span&gt;next&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content:encoded></item><item><title><![CDATA[关于Blog]]></title><description><![CDATA[早在很久之前就想弄个Blog了，先后试过博客园，CSDN，简书这些现有的博客网站，恩，但是都没写几篇就把他忘记了。后来也想自己写一个，github中 flask-study 就是这样来的，然而死在了前端上。。。 昨天可能考完CCF CSP有点懵，就开始想搞个blog…]]></description><link>https://codeand.fun/posts/2017/09/18/guan-yu-blog/</link><guid isPermaLink="false">https://codeand.fun/posts/2017/09/18/guan-yu-blog/</guid><pubDate>Mon, 18 Sep 2017 08:45:00 GMT</pubDate><content:encoded>&lt;p&gt;早在很久之前就想弄个Blog了，先后试过博客园，CSDN，简书这些现有的博客网站，恩，但是都没写几篇就把他忘记了。后来也想自己写一个，github中&lt;a href=&quot;https://github.com/wuxiaobai24/flask-study&quot;&gt;flask-study&lt;/a&gt;就是这样来的，然而死在了前端上。。。&lt;/p&gt;&lt;p&gt;昨天可能考完CCF CSP有点懵，就开始想搞个blog，一开始也想着继续学学前端，自己搭一个出来，后来想着这学期课有点多，不知道要多久才能搭完，就先用github pages＋hexo 搭一个用用先。&lt;/p&gt;&lt;p&gt;说到CCF CSP就有点心塞，连续两年都是没做完第三题（搞得我会第四题一样），最烦的是每年第三天都是写一个Parser。今年是&lt;code class=&quot;language-text&quot;&gt;json&lt;/code&gt;,去年是&lt;code class=&quot;language-text&quot;&gt;Markdown&lt;/code&gt;。每次都做得很蹦，希望能混到几十分吧。&lt;/p&gt;&lt;p&gt;说到底，还是自己太渣了，每次写一些复杂的逻辑的时候，感觉大脑就不够用了，一旦程序达到300行，就开始有点接受不了了。这次考试暴露自己挺多不足的地方：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;数据结构的底子还不够扎实。&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;一遇到图就直接崩，遇到适合树结构的也不敢用。&lt;/p&gt;&lt;/blockquote&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;不会写注释&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;从这次做题的时候就可以感觉出来，如果一开始敲的时候加一些注释，后面就不会看自己代码都需要想好久，而且最近在写的sort算法，也不会记一些注释，写的时候老是觉得很简单，自己可以很容易记住，然而每次都打自己的脸。&lt;/p&gt;&lt;/blockquote&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;遇事没有韧性&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;总感觉自己老是会放弃，做题时也是这样，做第三题时老是想着“要不不写了，直接走吧”，好在忍了下来，不然估计连几十分都不敢奢望。&lt;/p&gt;&lt;/blockquote&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;对STL根本不熟悉&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;即使翻着书也不写不好，总是会忘记一下东西，最后还是用c那一套写了一堆。&lt;/p&gt;&lt;/blockquote&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;不会组织程序结构&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;总是会写出一个很长的函数，明明很多时候是可以把一些实现分成函数，然后分别测试的。在想要实现一个东西的时候，首先做得是打开编辑器开写，而不是思考怎么做。&lt;/p&gt;&lt;/blockquote&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;总结的有点心塞。。。&lt;/p&gt;&lt;p&gt;一点一点的改变吧。&lt;/p&gt;&lt;ul&gt;&lt;li&gt;把树和图的一些基本算法实现出来（开一个repositories来放一些算法）&lt;/li&gt;&lt;li&gt;写好注释（起码能让自己几天后一看就知道自己当时想的是什么）&lt;/li&gt;&lt;li&gt;坚持写blog，起码每周更新一次&lt;/li&gt;&lt;li&gt;尝试着研究一下STL（如果有时间的话，捂脸）&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;路还远着呢！&lt;/p&gt;</content:encoded></item></channel></rss>