<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>技术 on 日日是好日-我的生活记录</title>
    <link>http://www.ririshihaori.com:80/categories/%E6%8A%80%E6%9C%AF/</link>
    <description>Recent content in 技术 on 日日是好日-我的生活记录</description>
    <generator>Hugo</generator>
    <language>zh-cn</language>
    <lastBuildDate>Wed, 28 Apr 2021 11:26:26 +0800</lastBuildDate>
    <atom:link href="http://www.ririshihaori.com:80/categories/%E6%8A%80%E6%9C%AF/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>第一次提交golangci-lint报错</title>
      <link>http://www.ririshihaori.com:80/posts/2021/4/go_lint_errors/</link>
      <pubDate>Wed, 28 Apr 2021 11:26:26 +0800</pubDate>
      <guid>http://www.ririshihaori.com:80/posts/2021/4/go_lint_errors/</guid>
      <description>&lt;p&gt;　　第一次开发的分支代码直接提交到远程后，触发了gitlab的pipeline，先是报了lint的几个错误，&#xA;修改提交之后又报了unittest的错误。&lt;!-- raw HTML omitted --&gt;&#xA;　　之后在把本地分支push到远程分支之前可以先本地&lt;code&gt;golangci-lint run ./... &lt;/code&gt;过lint，再&lt;code&gt;go test -v -cover ./cmd/...&lt;/code&gt;过单元测试再提交。&lt;/p&gt;&#xA;&lt;!-- raw HTML omitted --&gt;&#xA;&lt;p&gt;　　这里报的lint的错误是&lt;code&gt;Implicit memory aliasing in for loop&lt;/code&gt;，刚开始以为是在for循环里的函数调用传地址会报错，后来根据https://stackoverflow.com/questions/62446118/implicit-memory-aliasing-in-for-loop 里的说法，发现是因为for _, x range y的写法,循环里如果有传地址的操作，其实传的一直是x的地址，据说多个协程的场景下可能会有风险。&lt;!-- raw HTML omitted --&gt;&#xA;　　修改的方式很简单，把for循环的写法改成使用index遍历的方式即可，或者把函数实现从传指针改成传值的方式也可以。&lt;/p&gt;</description>
    </item>
    <item>
      <title>K8S In Action读书笔记</title>
      <link>http://www.ririshihaori.com:80/posts/2021/4/k8s_in_action/</link>
      <pubDate>Wed, 21 Apr 2021 10:43:56 +0800</pubDate>
      <guid>http://www.ririshihaori.com:80/posts/2021/4/k8s_in_action/</guid>
      <description>&lt;!-- raw HTML omitted --&gt;</description>
    </item>
    <item>
      <title>Go语言学习资料汇总</title>
      <link>http://www.ririshihaori.com:80/posts/2021/4/go_learning/</link>
      <pubDate>Fri, 02 Apr 2021 14:37:10 +0800</pubDate>
      <guid>http://www.ririshihaori.com:80/posts/2021/4/go_learning/</guid>
      <description>&lt;p&gt;　　GO语言学习过程中遇到的一些比较好的资料：&lt;/p&gt;&#xA;&lt;h3 id=&#34;博文&#34;&gt;博文&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://lessisbetter.site/2019/06/09/golang-first-class-function&#34;&gt;First class function in Go&lt;/a&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;讲了go语言中函数如何作为一等公民&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://segmentfault.com/a/1190000017958702&#34;&gt;总结了才知道，原来channel有这么多用法！&lt;/a&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;讲channel定义和用法，有一些笔误，参考原文评论区&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://sanyuesha.com/2017/07/22/how-to-understand-go-interface/&#34;&gt;理解 Go interface 的 5 个关键点&lt;/a&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;有一点难，例子有点抽象&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://studygolang.com/articles/10167&#34;&gt;golang中defer的使用规则&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;学习站点&#34;&gt;学习站点&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://gobyexample.com/&#34;&gt;Go by Example&lt;/a&gt;（很短 有例子比较好理解）&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a href=&#34;http://go-database-sql.org/&#34;&gt;Go database/sql tutorial&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://books.studygolang.com/gopl-zh/&#34;&gt;Go 语言圣经&lt;/a&gt;（有比较具体的实例）&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;书籍&#34;&gt;书籍&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/tiancaiamao/go-internals&#34;&gt;《深入解析Go》&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/astaxie/Go-in-Action&#34;&gt;《Go实战开发》&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/Unknwon/the-way-to-go_ZH_CN&#34;&gt;《Go入门指南》&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/polaris1119/The-Golang-Standard-Library-by-Example&#34;&gt;《Go语言标准库》&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/astaxie/build-web-application-with-golang&#34;&gt;《Go Web 编程》&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/achun/Go-Blog-In-Action&#34;&gt;《Go语言博客实践》&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/qyuhen/book&#34;&gt;《Go语言学习笔记》&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;翻译&#34;&gt;翻译&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://golang.org/doc/effective_go.html&#34;&gt;Effective Go&lt;/a&gt; 英文版&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/Unknwon/the-way-to-go_ZH_CN&#34;&gt;The Way to Go&lt;/a&gt; 中文版&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/miekg/gobook&#34;&gt;《Learning Go》&lt;/a&gt;英文版:=&amp;gt;&lt;a href=&#34;https://github.com/mikespook/Learning-Go-zh-cn&#34;&gt;《Learning Go》&lt;/a&gt; 中文版&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;教程&#34;&gt;教程&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/Unknwon/go-fundamental-programming&#34;&gt;《Go编程基础》&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/Unknwon/go-web-foundation&#34;&gt;《Go Web基础》&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/Unknwon/go-rock-libraries-showcases&#34;&gt;《Go名库讲解》&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/hyper-carrot/go_command_tutorial&#34;&gt;Go 命令教程&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;</description>
    </item>
    <item>
      <title>K8s_informer</title>
      <link>http://www.ririshihaori.com:80/posts/2021/4/k8s_informer/</link>
      <pubDate>Thu, 01 Apr 2021 10:43:56 +0800</pubDate>
      <guid>http://www.ririshihaori.com:80/posts/2021/4/k8s_informer/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;https://cloudnative.to/blog/client-go-informer-source-code/&#34;&gt;https://cloudnative.to/blog/client-go-informer-source-code/&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>工作中常用Git操作总结</title>
      <link>http://www.ririshihaori.com:80/posts/2021/4/git_cmds/</link>
      <pubDate>Thu, 01 Apr 2021 10:42:24 +0800</pubDate>
      <guid>http://www.ririshihaori.com:80/posts/2021/4/git_cmds/</guid>
      <description>&lt;h3 id=&#34;基础操作&#34;&gt;基础操作&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;更新当前分支&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-git&#34; data-lang=&#34;git&#34;&gt;    git pull&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;&#xA;&lt;li&gt;取回其他分支的更新&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-git&#34; data-lang=&#34;git&#34;&gt;    git fetch&#xA;    git fetch xxx&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;&#xA;&lt;li&gt;基于当前分支创建新分支并切换到新分支&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-git&#34; data-lang=&#34;git&#34;&gt;    git co -b xxx&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;&#xA;&lt;li&gt;直接切换到某个本地分支&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-git&#34; data-lang=&#34;git&#34;&gt;    git co xxx&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;&#xA;&lt;li&gt;把改动加入缓冲区&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-git&#34; data-lang=&#34;git&#34;&gt;    git add xxx&#xA;    git add . &#xA;&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;&#xA;&lt;li&gt;提交时建议使用commitizen插件，可以生成规范化的commit message&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-git&#34; data-lang=&#34;git&#34;&gt;    git cz&#xA;    git commit&#xA;    git commit -m &amp;#34;xxx&amp;#34;&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;&#xA;&lt;li&gt;修补提交(添加补丁/修改commit message)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-git&#34; data-lang=&#34;git&#34;&gt;    git commit --amend&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;生成patch/打patch&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;未commit的改动&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code class=&#34;language-git&#34; data-lang=&#34;git&#34;&gt;git format-patch 【commit sha1 id】 -1                     //某次提交&#xA;git format-patch 【commit sha1 id】 -n                  // 某次提交含之前几次提交&#xA;git format-patch 【commit sha1 id】..【commit sha1 id】  // 某两次提交之间的所有patch&#xA;&#xA;git diff  【commit sha1 id】 【commit sha1 id】 &amp;gt;  【diff文件名】   // 两次提交之间差异&#xA;&#xA;&#xA;git apply patch&#xA;git apply --stat newpatch.patch&#xA;git apply --check newpatch.patch&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;已经commit的改动，&lt;/p&gt;</description>
    </item>
    <item>
      <title>Barrelfish操作系统(2) capability系统实现代码分析</title>
      <link>http://www.ririshihaori.com:80/posts/2020/7/barrelfish_capabilities/</link>
      <pubDate>Sat, 11 Jul 2020 11:22:15 +0800</pubDate>
      <guid>http://www.ririshihaori.com:80/posts/2020/7/barrelfish_capabilities/</guid>
      <description>&lt;h1 id=&#34;1capability系统设计实现概述&#34;&gt;1、Capability系统设计实现概述&lt;/h1&gt;&#xA;&lt;p&gt;　　一个capability其实就是一个指针，但又是指针的一个超集，一个capability往往含有两个成员，一个是指向某块内存的地址addr，另一个是权限rights，权限用以说明某进程可以对 &lt;strong&gt;通过该capability寻址得到的内存&lt;/strong&gt; 进行哪种操作（如只读、读写、只写）。&lt;/p&gt;&#xA;&lt;p&gt;　　因此，可以把capability理解为一种&lt;strong&gt;带有权限的指针&lt;/strong&gt; ，我在后文中提到“capability”时，既有可能是指保存该“capability”本身的那块内存，也有可能是指该“capability”所指向的那块内存。大家需要根据语境自行判断。举一个例子，比如后文提到的“l1_CNode用来存储l2_CNode”，这句话中的“l1_CNode”就是指类型为l1_CNode类型的capability所指向的某一段内存，而这句话中的“l2_CNode”是指保存l2_CNode类型的capability本身的那块内存，即该内存中的数据为地址+权限。&lt;/p&gt;&#xA;&lt;p&gt;　　Barrelfish内核为每一个dispatcher维护其CSpace（&lt;strong&gt;某进程拥有的所有capability构成该进程的CSpace&lt;/strong&gt;）,沿用seL4中CNode及两级寻址的方式设计，具体方式为在dcb（dispatcher control block,进程控制块）中保存Root_CNode的地址。&lt;/p&gt;&#xA;&lt;p&gt;　　Root_CNode是一块固定大小的内存，这块内存按照cte(capability table entry)的大小分为很多slots块，每一个slot块中可保存一个cte，一个cte就是一个capabiltiy，会指向另一块保存有数据的内存。&lt;/p&gt;&#xA;&lt;p&gt;　　Root_CNode又称为l1_CNode,Root_CNode中保存的cte必须是l2_CNode类型的capability,每个l2_CNode也指向一块固定大小的内存，这块内存其中也有很多slots,每个slots中可保存一个cte，l2_CNode中保存的cte就是系统中真实使用的各种其他类型的capability，如dispatcher类型的、ram类型的等等。&lt;/p&gt;&#xA;&lt;p&gt;　　l1_CNode(root_CNode)和l2_CNode都是用来存储capability的capability。只不过l1_CNode中保存的是l2_CNode类型的capability,而l2_CNode中保存的是其他非CNode类型的capability。&lt;/p&gt;&#xA;&lt;p&gt;　　查询一个dispatcher的任意一个capability，都需要经过其root_CNode，首先定位到保存该cap的l2_CNode，最后再定位到该cap。有点类似于两级页表寻址，Root_CNode是页目录，l2_CNode是页表，l2_CNode中的某个slot是页表项。每个进程的dcb中都保存了root_CNode的地址。通过该地址可以索引该进程的整个CSpace。&lt;/p&gt;&#xA;&lt;p&gt;　　l1_CNode和l2_CNode也是capability所有不同类型中的两种类型，与ram | dispatcher | &amp;hellip; 一样也是capability，所有capbility都有如下性质：即包含指向某一段内存的信息（虚地址addr、虚拟内存大小size）以及相关权限rights。&lt;/p&gt;&#xA;&lt;p&gt;　　内核中定义实现了capability的相关数据结构，定义实现如下：&lt;/p&gt;&#xA;&lt;p&gt;　　文件路径：kernel/include/capabilities.h&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;/**&#xA;&#x9;* \brief A CTE (Capability Table Entry).&#xA;&#x9;*&#xA;&#x9;* A CTE is an entry in a CNode, which in turn is an entry in CSpace, the&#xA;&#x9;* capability space. CSpace is a guarded tree structure. Refer to the seL4&#xA;&#x9;* reference manual for further information about how CSpace is implemented.&#xA;&#x9;*/&#xA;struct cte {&#xA;&#x9;struct capability   cap;           &#x9;///&amp;lt; The capability&#xA;&#x9;char padding0[ROUND_UP(sizeof(struct capability), 8)- sizeof(struct capability)];&#xA;&#x9;struct mdbnode      mdbnode;       &#x9;///&amp;lt; MDB &amp;#34;root&amp;#34; node for the cap&#xA;&#x9;char padding1[ROUND_UP(sizeof(struct mdbnode), 8) - sizeof(struct mdbnode)];&#xA;&#x9;struct delete_list  delete_node;    ///&amp;lt; State for in-progress delete cascades&#xA;&#xA;&#x9;/// Padding to fill the struct out to the size required by OBJBITS_CTE&#xA;&#x9;char padding[(1UL &amp;lt;&amp;lt; OBJBITS_CTE)&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;- sizeof(struct delete_list)&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;- ROUND_UP(sizeof(struct capability), 8)&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;- ROUND_UP(sizeof(struct mdbnode), 8)];&#xA;};&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;　　由于每个slots是固定大小，所以定义了一些padding用来对齐大小。我们首先关注第一个成员cap，后两个成员mdbnode和delete_node暂时不管，后面会详细说明。             &lt;br&gt;&#xA;　　注意到其中的第一个成员cap的类型为capability类型的结构体，该结构体定义如下:&lt;/p&gt;</description>
    </item>
    <item>
      <title>[转载]代码注释中的NOTE/XXX/HACK/FIXME/BUG/TODO</title>
      <link>http://www.ririshihaori.com:80/posts/2020/4/comments_tag/</link>
      <pubDate>Sat, 04 Apr 2020 15:55:52 +0800</pubDate>
      <guid>http://www.ririshihaori.com:80/posts/2020/4/comments_tag/</guid>
      <description>&lt;p&gt;看到&lt;a href=&#34;https://blog.csdn.net/xianghongai/article/details/79306361?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-3&amp;amp;utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-3&#34;&gt;一篇博客&lt;/a&gt;&#xA;解释代码注释中的各种tag解释得很有意思。&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;NOTE: Description of how the code works (when it isn’t self evident)          &lt;strong&gt;汝等凡人&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;XXX: Warning about possible pitfalls, can be used as NOTE:XXX:                &lt;strong&gt;陷阱&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;HACK: Not very well written or malformed code to circumvent a problem/bug.&#xA;Should be used as HACK:FIXME:                                             &lt;strong&gt;补锅踩雷填坑&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;FIXME: This works, sort of, but it could be done better. (usually code written in a hurry that needs rewriting) &lt;strong&gt;Fuck Me&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;BUG: There is a problem here.                              &lt;strong&gt;丢锅埋雷挖坑&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Go实现String Set</title>
      <link>http://www.ririshihaori.com:80/posts/2020/4/go_sets/</link>
      <pubDate>Wed, 01 Apr 2020 01:13:28 +0800</pubDate>
      <guid>http://www.ririshihaori.com:80/posts/2020/4/go_sets/</guid>
      <description>&lt;p&gt;基于map实现sets.go&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;package sets&#xA;&#xA;// An Empty struct does not take up any memory&#xA;type Empty struct{}&#xA;&#xA;// sets.String is a set of strings, implemented via map[string]struct{} for minimal memory consumption.&#xA;type String map[string]Empty&#xA;&#xA;&#xA;func NewString(items ...string) String {&#xA;&#x9;s := String{}&#xA;&#x9;s.Insert(items...)&#xA;&#x9;return s&#xA;}&#xA;&#xA;func (s String) Insert(items ...string) {&#xA;&#x9;for _, item := range items {&#xA;&#x9;&#x9;s[item] = Empty{}&#xA;&#x9;}&#xA;}&#xA;&#xA;func (s String) Delete(items ...string) {&#xA;&#x9;for _, item := range items {&#xA;&#x9;&#x9;delete(s, item)&#xA;&#x9;}&#xA;}&#xA;&#xA;func (s String) Has(item string) bool {&#xA;&#x9;_, res := s[item]&#xA;&#x9;return res&#xA;}&#xA;&#xA;// HasAll returns true if and only if all items are contained in the set.&#xA;func (s String) HasAll(items ...string) bool {&#xA;&#x9;for _, item := range items {&#xA;&#x9;&#x9;if !s.Has(item) {&#xA;&#x9;&#x9;&#x9;return false&#xA;&#x9;&#x9;}&#xA;&#x9;}&#xA;&#x9;return true&#xA;}&#xA;&#xA;// HasAny returns true if any items are contained in the set.&#xA;func (s String) HasAny(items ...string) bool {&#xA;&#x9;for _, item := range items {&#xA;&#x9;&#x9;if s.Has(item) {&#xA;&#x9;&#x9;&#x9;return true&#xA;&#x9;&#x9;}&#xA;&#x9;}&#xA;&#x9;return false&#xA;}&#xA;&#xA;// Difference returns a set of objects that are not in s2&#xA;func (s String) Difference(s2 String) String {&#xA;&#x9;res := NewString()&#xA;&#x9;for item := range s {&#xA;&#x9;&#x9;if !s2.Has(item) {&#xA;&#x9;&#x9;&#x9;res.Insert(item)&#xA;&#x9;&#x9;}&#xA;&#x9;}&#xA;&#x9;return res&#xA;}&#xA;&#xA;// Union returns a new set which includes items in either s1 or s2.&#xA;func (s1 String) Union(s2 String) String {&#xA;&#x9;res := NewString()&#xA;&#x9;for item := range s1 {&#xA;&#x9;&#x9;res.Insert(item)&#xA;&#x9;}&#xA;&#x9;for item := range s2 {&#xA;&#x9;&#x9;res.Insert(item)&#xA;&#x9;}&#xA;&#x9;return res&#xA;}&#xA;&#xA;// Intersection returns a new set which includes the item in BOTH s1 and s2&#xA;func (s1 String) Intersection(s2 String) String {&#xA;&#x9;res := NewString()&#xA;&#x9;if s1.Len() &amp;lt; s2.Len() {&#xA;&#x9;&#x9;for item := range s1 {&#xA;&#x9;&#x9;&#x9;if s2.Has(item) {&#xA;&#x9;&#x9;&#x9;&#x9;res.Insert(item)&#xA;&#x9;&#x9;&#x9;}&#xA;&#x9;&#x9;}&#xA;&#x9;} else {&#xA;&#x9;&#x9;for item := range s2 {&#xA;&#x9;&#x9;&#x9;if s1.Has(item) {&#xA;&#x9;&#x9;&#x9;&#x9;res.Insert(item)&#xA;&#x9;&#x9;&#x9;}&#xA;&#x9;&#x9;}&#xA;&#x9;}&#xA;&#x9;return res&#xA;}&#xA;&#xA;func (s String) Len() int {&#xA;&#x9;return len(s)&#xA;}&#xA;&#xA;func (s String) List() []string {&#xA;&#x9;res := make([]string, 0, len(s))&#xA;&#x9;for item := range s {&#xA;&#x9;&#x9;res = append(res, item)&#xA;    }&#xA;&#x9;return res&#xA;}&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;单元测试 sets_test.go&lt;/p&gt;</description>
    </item>
    <item>
      <title>[转载]Golang新手可能会踩的50个坑</title>
      <link>http://www.ririshihaori.com:80/posts/2020/3/go_traps_and_common_mistakes/</link>
      <pubDate>Sun, 29 Mar 2020 19:26:30 +0800</pubDate>
      <guid>http://www.ririshihaori.com:80/posts/2020/3/go_traps_and_common_mistakes/</guid>
      <description>&lt;p&gt;使用Golang时读到了这篇文章，感觉每一条都非常有用，所以转到这里。感谢原文作者和译者。&lt;/p&gt;&#xA;&lt;p&gt;译文地址：https://segmentfault.com/a/1190000013739000#articleHeader43     &lt;br&gt;&#xA;原文地址：http://devs.cloudimmunity.com/gotchas-and-common-mistakes-in-go-golang/&lt;/p&gt;&#xA;&lt;h2 id=&#34;前言&#34;&gt;前言&lt;/h2&gt;&#xA;&lt;p&gt;Go 是一门简单有趣的编程语言，与其他语言一样，在使用时不免会遇到很多坑，不过它们大多不是 Go 本身的设计缺陷。如果你刚从其他语言转到 Go，那这篇文章里的坑多半会踩到。&lt;/p&gt;&#xA;&lt;p&gt;如果花时间学习官方 doc、wiki、&lt;a href=&#34;https://groups.google.com/forum/#!forum/golang-nuts&#34;&gt;讨论邮件列表&lt;/a&gt;、 &lt;a href=&#34;https://github.com/robpike&#34;&gt;Rob Pike&lt;/a&gt; 的大量文章以及 Go 的源码，会发现这篇文章中的坑是很常见的，新手跳过这些坑，能减少大量调试代码的时间。&lt;/p&gt;&#xA;&lt;h3 id=&#34;1-左大括号--一般不能单独放一行&#34;&gt;1. 左大括号 &lt;code&gt;{&lt;/code&gt; 一般不能单独放一行&lt;/h3&gt;&#xA;&lt;p&gt;在其他大多数语言中，&lt;code&gt;{&lt;/code&gt; 的位置你自行决定。Go 比较特别，遵守分号注入规则（automatic semicolon injection）：编译器会在每行代码尾部特定分隔符后加 &lt;code&gt;;&lt;/code&gt; 来分隔多条语句，比如会在 &lt;code&gt;)&lt;/code&gt; 后加分号：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 错误示例&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;()&#x9;&#x9;&#x9;&#x9;&#x9;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;println(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hello world&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 等效于&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;();&#x9;&lt;span style=&#34;color:#75715e&#34;&gt;// 无函数体&#x9;&#x9;&#x9;&#x9;&#x9;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;println(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hello world&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&amp;gt; ./main.go: missing function body             &#xA;&amp;gt; ./main.go: syntax error: unexpected semicolon or newline before {&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 正确示例&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;main&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#x9;println(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;hello world&amp;#34;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}     &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;注意代码块等特殊情况：&lt;/p&gt;</description>
    </item>
    <item>
      <title>Kube-Batch学习笔记</title>
      <link>http://www.ririshihaori.com:80/posts/2020/1/kube-batch/</link>
      <pubDate>Thu, 09 Jan 2020 17:40:49 +0800</pubDate>
      <guid>http://www.ririshihaori.com:80/posts/2020/1/kube-batch/</guid>
      <description>&lt;h1 id=&#34;1概述&#34;&gt;1.概述&lt;/h1&gt;&#xA;&lt;p&gt;　　kube-batch是k8s下面向高性能计算领域的批调度器。&lt;/p&gt;&#xA;&lt;p&gt;　　k8s原生的调度器会将需要启动的容器，放到一个优先队列（Priority Queue）里面，每次从队列里面取出一个容器，将其调度到一个节点上。&lt;/p&gt;&#xA;&lt;p&gt;　　AI分布式训练需要所有worker都启动后，训练才能够开始进行。但是原生的调度器的调度是以pod为粒度的，对AI任务很不利，使用原生调度器，可能会出现以下问题：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;一个任务包含了10个worker，但是集群的资源只满足9个worker。原生调度器会将任务的9个worker调度并启动，而最后一个worker一直无法启动。这样训练一直无法开始，9个已经启动的worker的资源被浪费了。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;两个任务，各包含10个worker，集群的资源只能启动10个worker。两个任务分别有5个worker被启动了，但两个任务都无法开始训练。10个worker的资源被浪费了。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;　　由此可见，原生调度器对于分布式训练的调度存在问题，影响了资源的利用率。而Kubernetes社区提供了一个批调度器kube-batch， 它能够将一个训练任务的多个worker当做一个整体进行调度，只有当任务所有worker的资源都满足，才会将容器在节点上启动。（要不全部，要不全部不，all or none）     &lt;br&gt;&#xA;　　如图所示，kube-batch定义了job和pod group的概念，一个job对应一个pod group，一个pod group里有一个或者多个pod，分别对应一个或多个task。&lt;/p&gt;&#xA;&lt;!-- raw HTML omitted --&gt;&#xA;&lt;h1 id=&#34;2整体框架&#34;&gt;2.整体框架&lt;/h1&gt;&#xA;&lt;!-- raw HTML omitted --&gt;&#xA;&lt;p&gt;　　如图所示，kube-batch中有四个模块，分别是Cache、Session、Plugin和Action。         &lt;br&gt;&#xA;　　其中，Cache负责调用API Server的相关接口，维护整个系统内当前资源的分配状态，供调度器查询和计算。Session是调度器对pod/pod group/queue等进行调度时构建的一个对象，一次会话就是一次调度，调度时会从待调度的pod/queue中选择优先级最高的一个进行调度。          &lt;br&gt;&#xA;　　个人理解：调度时所依据的相关算法/规则/策略就是Plugin，调度产生的结果就是各种Action。&lt;/p&gt;&#xA;&lt;h3 id=&#34;21-cache&#34;&gt;2.1 Cache&lt;/h3&gt;&#xA;&lt;p&gt;　　Cache模块封装了对API Server的节点、容器等对象的数据同步逻辑。Kubernetes的数据保存在分布式存储etcd中，所有对数据的查询和操作都通过调用API Server的接口，而非直接操作etcd。在调度时，需要集群中的节点和容器的使用资源和状态等信息。Cache模块通过调用Kubernetes的SDK，通过watch机制监听集群中的节点、容器的状态变化，将信息同步到自己的数据结构中。        &lt;br&gt;&#xA;　　Cache模块还封装了对API server的接口的调用。比如Cache.Bind这个接口，会去调用API Server的Bind接口，将容器绑定到指定的节点上。在kube-batch中只有cache模块需要和API Server交互，其他模块只需要调用Cache模块的接口。&lt;/p&gt;&#xA;&lt;h3 id=&#34;22-session&#34;&gt;2.2 Session&lt;/h3&gt;&#xA;&lt;p&gt;　　Session模块是将其他三个模块串联起来的一个模块。Kube-batch在每个调度周期开始时，都会新建一个Session对象，这个Session的初始化时，会做以下操作：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;调用Cache.Snapshot接口，将Cache中节点、任务和队列的信息拷贝一份副本，之后在这个调度周期中使用这份副本进行调度。因为Cache的数据会不断变化，为了保持同个调度周期中的数据一致性，在一开始就拷贝了一份副本。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;将配置中的各个Plugin初始化，然后调用plugin的OnSessionOpen接口。Plugin在OnSessionOpen中，会初始化自己需要的数据，并将一些回调函数注册到session中。Plugin可以向Session中注册的函数是：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;jobOrderFns： 决定哪个训练任务优先被处理（调度、回收、抢占）&lt;/li&gt;&#xA;&lt;li&gt;queueOrderFns：决定哪个训练队列优先被处理&lt;/li&gt;&#xA;&lt;li&gt;taskOrderFns：决定任务中哪个容器优先被处理&lt;/li&gt;&#xA;&lt;li&gt;predicateFns： 判断某个节点是否满足容器的基本调度要求。比如容器中指定的节点的标签&lt;/li&gt;&#xA;&lt;li&gt;nodeOrderFns： 当多个节点满足容器的调度要求时，优先选择哪个节点&lt;/li&gt;&#xA;&lt;li&gt;preemptableFns： 决定某个容器是否可以被抢占&lt;/li&gt;&#xA;&lt;li&gt;reclaimableFns ：决定某个容器是否可以被回收&lt;/li&gt;&#xA;&lt;li&gt;overusedFns： 决定某个队列使用的资源是否超过限额，是的话不再调度对队列中的任务&lt;/li&gt;&#xA;&lt;li&gt;jobReadyFns：判断某个任务是否已经准备好，可以调用API Server的接口将任务的容器调度到节点&lt;/li&gt;&#xA;&lt;li&gt;jobPipelinedFns ： 判断某个任务是否处于Pipelined状态&lt;/li&gt;&#xA;&lt;li&gt;jobValidFns： 判断某个任务是否有效&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;　　Plugin不需要注册上面所有的函数，而是可以根据自己的需要，注册某几个函数。比如Predict plugin就只注册了predicateFns这个函数到Session中。      &lt;br&gt;&#xA;　　而某些plugin的使用与否（包括某些action使用与否）都由配置文件决定:(&lt;code&gt;kube-batch/pkg/scheduler/util.go&lt;/code&gt;)&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;var defaultSchedulerConf = `&#xA;actions: &amp;#34;allocate, backfill&amp;#34;&#xA;tiers:&#xA;- plugins:&#xA;  - name: priority&#xA;  - name: gang&#xA;- plugins:&#xA;  - name: drf&#xA;  - name: predicates&#xA;  - name: proportion&#xA;  - name: nodeorder&#xA;```　　&#xA;可知默认配置使用2种action(allocate和backfill)和6种plugin。（tiers是什么意思暂时不明）        &#xA;代码可以参考：&#xA;(`kube-batch/pkg/scheduler/framework/framework.go`)和&#xA;(`kube-batch/pkg/scheduler/framework/session.go`)&#xA;&#xA;### 2.3 Plugin&#xA;&#xA;　　Plugin模块顾名思义，提供了一种可插拔的方式，向调度提供不同的策略的实现。&#xA;&#xA;　　如整体框架中所示，目前有7个Plugin，它们分别是：   &#xA;&#xA;+ for Jobs&#xA;    + drf：实现了Dominant Resouce Fairenss算法，这个算法能够有效对多种“主要资源”（CPU、Memory、GPU）进行调度。&#xA;    + gang：实现了gang scheduling的逻辑，即保证任务所需worker同时被启动。&#xA;    + predict：判断某个节点是否满足容器的基本要求。&#xA;    + priority： 根据容器和队列设置的PriorityClass决定容器和队列的优先级。&#xA;    + node order：决定满足调度要求的节点中，哪个节点优先被选择。&#xA;    + conformance：&#xA;&#xA;+ for Queues:&#xA;    + proportion： 根据队列设置的权重决定每个队列分配到的资源。&#xA;&#xA;　　下面对部分plugin进行说明。&#xA;&#xA;#### 2.3.1 drf&#xA;&#xA;&#xA;&amp;lt;div align=center&amp;gt;&amp;lt;img src = &amp;#39;/2020/1/kube-batch/3.png&amp;#39; style=&amp;#34;zoom:70%&amp;#34; title=&amp;#34;drf&amp;#34;/&amp;gt;&amp;lt;/div&amp;gt;&#xA;&#xA;　　目的是尽量避免集群内某一类资源使用比例偏高，而其他类型资源使用比例却很低的不良状态。在调度时，让具有最低资源占用比例的任务具有高优先级。&#xA;代码位于`kube-batch/pkg/scheduler/plugins/drf/drf.go`，主要关注`onSessionOpen`函数：        &#xA;&#xA;1. 统计集群中所有node可分配资源总量&#xA;2. 统计Job资源申请，计算资源占比（资源申请/资源总量）&#xA;3. 注册Job排序函数，根据资源占比进行排序，主要资源占比越低job优先级越高&#xA;4. 注册事件处理函数，包括分配函数以及驱逐函数，函数实现比较简单，就是当task发生变化时，增加（分配）/减少（驱逐）Job资源申请总量，并且更新资源占比。&#xA;&#xA;　　drf注册2个function，分别是:&#xA;&#xA;+ `jobOrderFn` 是job的排序函数，会让share值越小的job排在最前面，即拥有最高的优先级，这个是实现drf的关键。           &#xA;+  `preemptableFn`返回可抢占的job列表，job的筛选规则是：如果待选job的share值大于将被调度的job的share值，则选中该待选job。      &#xA;&#xA;#### 2.3.2 gang&#xA;&#xA;　　gang需要实现的策略是只有当job中的全部pod，或者用户指定的某几个pod都分配到资源后，才真正将pod调度到node上。（即先从逻辑上分配资源给pod，等满足条件后才真正进行调度。）                &#xA;　　gang注册3个function，分别是：         &#xA;&#xA;+ `preemptableFn` 为避免gang的策略被preempt和reclaiｍ干扰，定义了preemptableFn,排除那些还未准备就绪的job，避免其被抢占。（虽然实际上这些job未真正调度到node上去，但是确实从逻辑上把资源分配给它了）&#xA;+ `jobOrderFn` 为让已经就绪的job尽快被调度到节点，定义了jobOrderFn ,让已经就绪的job拥有更高的优先级&#xA;+ `jobReadyFn` 用来判断一个job是否已经就绪。`jobReady`会调用所有注册了的 plugin的Ready判定函数，只有都判定为ready ,才返回true&#xA;　&#xA;&#xA;#### 2.3.3 predicates&#xA;&#xA;　　predicates注册预测函数,用来判断某个节点是否满足容器的基本要求，如         &#xA;&#xA;+ CheckNodeCondition Predicate&#xA;+ CheckNodeUnschedulable Predicate&#xA;+ NodeSelector Predicate&#xA;+ HostPorts Predicate&#xA;+ Toleration/Taint Predicate        &#xA;+ ...&#xA;&#xA;#### 2.3.4 priority&#xA;&#xA;　　priority注册         &#xA;&#xA;+ task排序函数，根据pod优先级排序&#xA;+ job排序函数，根据job优先级排序&#xA;&#xA;#### 2.3.5 proportion&#xA;&#xA;　　针对队列。&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;type queueAttr struct {&#xA;queueID api.QueueID       // 队列的id&#xA;name    string            // 队列的名字&#xA;weight  int32             // 队列的权重,决定分配到的资源的多少&#xA;share   float64           // 参考drf处的share&#xA;　&#xA;deserved  *api.Resource　 // 声明的资源总量&#xA;allocated *api.Resource   // 实际分配到的资源总量&#xA;request   *api.Resource   // 该队列中所有job声明的要分配的资源总量&#xA;}&lt;/p&gt;</description>
    </item>
    <item>
      <title>Kubernetes学习笔记</title>
      <link>http://www.ririshihaori.com:80/posts/2020/1/k8s/</link>
      <pubDate>Thu, 09 Jan 2020 13:32:38 +0800</pubDate>
      <guid>http://www.ririshihaori.com:80/posts/2020/1/k8s/</guid>
      <description>&lt;h1 id=&#34;背景&#34;&gt;背景&lt;/h1&gt;&#xA;&lt;p&gt;应用程序发展趋势：  &lt;br&gt;&#xA;　　单体应用 -&amp;gt; 微服务&lt;/p&gt;&#xA;&lt;p&gt;产生需求：  　&lt;br&gt;&#xA;　　微服务扩容、部署、软件环境需求差异、自动监控（运维）&lt;/p&gt;&#xA;&lt;h1 id=&#34;linux容器技术&#34;&gt;Linux容器技术&lt;/h1&gt;&#xA;&lt;p&gt;两种隔离机制：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Linux命名空间       &lt;br&gt;&#xA;使每个进程只能看到自己的系统视图（文件、进程、网络接口、主机名等）&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;Linux控制组(cgroups)        &lt;br&gt;&#xA;限制了进程能使用的资源量（CPU、内存、网络带宽等）&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h1 id=&#34;虚拟机与容器比较&#34;&gt;虚拟机与容器比较：&lt;/h1&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;前者需要在每个隔离单元中运行系统服务，而后者不需要&lt;/li&gt;&#xA;&lt;li&gt;前者在宿主操作系统上有多个虚拟机操作系统内核，后者只需要一个宿主机系统内核&lt;/li&gt;&#xA;&lt;li&gt;前者的好处是提供完全隔离的环境，可用于隔离少量进程；后者的好处是低消耗，可用于在同一台机器上运行大量被隔离的进程&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h1 id=&#34;docker&#34;&gt;Docker&lt;/h1&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;镜像（image）     &lt;br&gt;&#xA;　　镜像“层”的概念：使镜像分发更高效，减少存储空间（公用层只读，各自新的改动保存在新的层上）&lt;/li&gt;&#xA;&lt;li&gt;镜像仓库&lt;/li&gt;&#xA;&lt;li&gt;容器（container）&lt;/li&gt;&#xA;&lt;li&gt;Docker安装、build&amp;amp;run、Dockerfile、ps -a、rm、tag、push&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h1 id=&#34;rkt&#34;&gt;rkt&lt;/h1&gt;&#xA;&lt;p&gt;强调安全性、可构建性并遵从开放标准，使用OCI容器镜像，甚至可运行常规Docker镜像&lt;/p&gt;&#xA;&lt;h1 id=&#34;kubernetes介绍&#34;&gt;Kubernetes介绍&lt;/h1&gt;&#xA;&lt;p&gt;　　用于部署和管理容器化应用的软件系统，可以提高开发者和运维的效率&lt;/p&gt;&#xA;&lt;h3 id=&#34;kubernetes集群架构&#34;&gt;Kubernetes集群架构&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;主节点（控制面板）&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Kubernetes API服务器&lt;/li&gt;&#xA;&lt;li&gt;Scheduler（调度器）&lt;/li&gt;&#xA;&lt;li&gt;Controller manager（执行集群级别的功能，如复制组件、持续跟踪工作节点、处理节点失败）&lt;/li&gt;&#xA;&lt;li&gt;etcd（可靠的分布式存储，持久化存储集群配置）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;工作节点（运行用户实际部署的应用）&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Docker、rkt或其他的容器类型&lt;/li&gt;&#xA;&lt;li&gt;Kubelet（与API服务器通信，并管理它所在节点的容器）&lt;/li&gt;&#xA;&lt;li&gt;Kubernetes Service Proxy（kube-proxy）(负责组件之间的负载均衡网络流量)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;使用k8s的好处&#34;&gt;使用k8s的好处&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;简化应用程序部署（开发+运维）&lt;/li&gt;&#xA;&lt;li&gt;更好地利用硬件&lt;/li&gt;&#xA;&lt;li&gt;健康检查和自修复&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;kube-batch&#34;&gt;Kube-Batch&lt;/h3&gt;&#xA;&lt;p&gt;　　Kube-Batch是运行在k8s上面向机器学习/大数据/HPC的批调度器（batch scheduler）。            &lt;br&gt;&#xA;　　开源仓库：https://github.com/kubernetes-sigs/kube-batch&lt;/p&gt;&#xA;&lt;h1 id=&#34;使用minikube构建单节点集群&#34;&gt;使用Minikube构建单节点集群&lt;/h1&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;下载kubectl        &lt;br&gt;&#xA;&lt;code&gt;# curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.16.0/bin/linux/amd64/kubectl&lt;/code&gt;     &lt;br&gt;&#xA;&lt;code&gt;# mv kubectl /usr/local/bin/ &amp;amp;&amp;amp; chmod +x /usr/local/bin/kubectl&lt;/code&gt;         &lt;br&gt;&#xA;&lt;code&gt;# kubectl version&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;kubectl zsh下自动补全，~/.zshrc中增加：         &lt;br&gt;&#xA;&lt;code&gt;plugins=(kubectl)&lt;/code&gt;       &lt;br&gt;&#xA;&lt;code&gt;source &amp;lt;(kubectl completion zsh)&lt;/code&gt;           &lt;br&gt;&#xA;然后终端中source &lt;code&gt;~/.zshrc&lt;/code&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Python爬虫踩坑</title>
      <link>http://www.ririshihaori.com:80/posts/2019/12/python%E7%88%AC%E5%8F%96cfda/</link>
      <pubDate>Sun, 22 Dec 2019 17:53:58 +0800</pubDate>
      <guid>http://www.ririshihaori.com:80/posts/2019/12/python%E7%88%AC%E5%8F%96cfda/</guid>
      <description>&lt;p&gt;　　这两天跟着徐徐大佬学了一下爬虫，想用 python 爬一下cfda网站上的&lt;a href=&#34;http://mobile.cfda.gov.cn/datasearch/QueryList?tableId=36&amp;amp;searchF=Quick%20Search&amp;amp;pageIndex=1&amp;amp;pageSize=15&#34;&gt;药品数据&lt;/a&gt;，徐徐试了**&lt;code&gt;requests&lt;/code&gt;&lt;strong&gt;和&lt;/strong&gt;&lt;code&gt;selenium&lt;/code&gt;**的办法，&#xA;发现爬到的都是一串神秘字符串，如图，&lt;/p&gt;&#xA;&lt;!-- raw HTML omitted --&gt;&#xA;&lt;p&gt;　　因为浏览器能正常打开，所以猜测是服务器端用了某种压缩/动态渲染，就想着能不能用 &lt;code&gt;Selenium&lt;/code&gt; + &lt;code&gt;PhantomJs/ChromeDriver&lt;/code&gt; 这种无头浏览器来弄，&#xA;结果每次结果都是空的，Google了各种方法，StackOverflow上的办法大多是加命令参数/改程序版本，&#xA;结果好像加了各种命令选项都不行，这是最后的代码，&lt;/p&gt;&#xA;&lt;!-- raw HTML omitted --&gt;&#xA;&lt;p&gt;　　得到的&lt;code&gt;driver.page_source&lt;/code&gt;结果永远都是空的： &lt;br&gt;&#xA;&lt;strong&gt;&lt;code&gt;&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/strong&gt;    &lt;br&gt;&#xA;　　用&lt;code&gt;driver.save_screenshot(&#39;1.png&#39;)&lt;/code&gt;截图也只能截到空白的图片。   &lt;br&gt;&#xA;　　后来去掉&lt;code&gt;#options.add_argument(&amp;quot;--headless&amp;quot;)&lt;/code&gt;,弹出chrome浏览器的时候看了一下它的Cookie，发现比真实浏览器的少了一个名字叫&lt;code&gt;JSESSIONID&lt;/code&gt;的Cookie，代码输出一下Cookie：&lt;br&gt;&#xA;&lt;code&gt;print(driver.get_cookies())&lt;/code&gt;  &lt;br&gt;&#xA;　　发现确实只有后两个Cookie：&lt;/p&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;    [{&amp;#39;domain&amp;#39;: &amp;#39;mobile.cfda.gov.cn&amp;#39;, &amp;#39;expiry&amp;#39;: 1892368214, &amp;#39;httpOnly&amp;#39;: False, &amp;#39;name&amp;#39;: &amp;#39;tuNQaYE2WCOr80T&amp;#39;, &amp;#39;path&amp;#39;: &amp;#39;/&amp;#39;, &amp;#39;secure&amp;#39;: False, &amp;#39;value&amp;#39;: &amp;#39;44Kn.5S4Qs9FYazHg9cvpAh7RvvkX6CHCFFLnsNw3CWLTJqQ6uRw0fI8bg5vrYGQEX6hJa0J.RsRZXrnLpG9ViGS6qQB.h0ihFdotILVHmKWMi8rTSe4I7l24OjHVvISZagZFyCmw23._.vUSDK3RsDU47zozbhS.mSlLRCcnw4tiTC6vzgime927xft3LdtTnQXjiYoqH.ONQGdKHPdqzeGiwGMEjgoxEebyhgXrJn2tAr5hqtntejwrroOnMyvm77CXd8_V5QkuK5aINNj2DYlMrReJ7uKRLSx3FeepzkKvtT5WFd.hbAsVYU5eqbtb_Mq&amp;#39;},        &#xA;    {&amp;#39;domain&amp;#39;: &amp;#39;mobile.cfda.gov.cn&amp;#39;, &amp;#39;expiry&amp;#39;: 1892368213.81084, &amp;#39;httpOnly&amp;#39;: True, &amp;#39;name&amp;#39;: &amp;#39;tuNQaYE2WCOr80S&amp;#39;, &amp;#39;path&amp;#39;: &amp;#39;/&amp;#39;, &amp;#39;secure&amp;#39;: False, &amp;#39;value&amp;#39;: &amp;#39;hPNhBHTwoBvnsQ5znkw4QCEmXQJ7.5vsBR2r8eDpRyWyiYBaMsjvKkr75trGzXPe&amp;#39;}]&#xA;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;!-- raw HTML omitted --&gt;　　这是真实浏览器的Cookie：&lt;/p&gt;&#xA;&lt;!-- raw HTML omitted --&gt;&#xA;&lt;p&gt;　　可能就是因为这个原因打不开浏览器。  &lt;br&gt;&#xA;　　后来试着去群里问了一下，感谢@姬大神还有群里的@耿欣大佬，他俩告诉我可以用**&lt;a href=&#34;https://www.getpostman.com/&#34;&gt;Postman&lt;/a&gt;**发请求，然后生成带&lt;code&gt;Header&lt;/code&gt;的代码，如图，Postman能显示所有Cookie和Header信息,可以看到Header信息里，服务端用了&lt;code&gt;gzip&lt;/code&gt;还有&lt;code&gt;gb2312&lt;/code&gt;的编码格式(图3)：&lt;/p&gt;&#xA;&lt;!-- raw HTML omitted --&gt;&#xA;&lt;p&gt;　　点击右上角的&lt;strong&gt;Code&lt;/strong&gt;按钮可以生成各种版本的请求代码，生成之前可以设置一下 &lt;code&gt;Include Temporary Headers&lt;/code&gt; 选项让生成的代码含有现在的**&lt;code&gt;Headers&lt;/code&gt;**&lt;/p&gt;</description>
    </item>
    <item>
      <title>[持续更新]Leetcode刷题笔记</title>
      <link>http://www.ririshihaori.com:80/posts/2019/12/leetcode%E5%88%B7%E9%A2%98%E7%AC%94%E8%AE%B0/</link>
      <pubDate>Tue, 03 Dec 2019 00:23:55 +0800</pubDate>
      <guid>http://www.ririshihaori.com:80/posts/2019/12/leetcode%E5%88%B7%E9%A2%98%E7%AC%94%E8%AE%B0/</guid>
      <description>&lt;p&gt;　　&lt;/p&gt;&#xA;&lt;h2 id=&#34;1位运算与比较运算的优先级&#34;&gt;1.位运算与比较运算的优先级&lt;/h2&gt;&#xA;&lt;p&gt;　　&lt;a href=&#34;https://leetcode-cn.com/problems/can-i-win/&#34;&gt;题号464，我能赢吗&lt;/a&gt;，两人轮流从给出的等差数列中取数（数列从1开始直到n，n为给出的值），取出的数之和超过某个给出的目标值游戏结束，最后一个取数的人胜利。&#xA;作法主要是用递归模拟两个人的取数过程（因为假设两个人都足够聪明），用位运算模拟取数顺序（即两个人取数的情况一共有2^n种），由于题目规定n最大不超过20所以用一个数组来存所有可能的取数情况下的游戏结果。&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C++&#34; data-lang=&#34;C++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;int&lt;/span&gt; dp[&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&amp;lt;&lt;/span&gt; n] &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; {&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;};&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;　　按照这个思路实现了以后还是执行不对，debug最后发现是位运算和比较运算的优先级问题。问题出在这行代码：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C++&#34; data-lang=&#34;C++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; (stat &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt; select &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;　　==和!=的优先级高于&amp;amp;运算符，改成&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-C++&#34; data-lang=&#34;C++&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;if&lt;/span&gt; ((stat &lt;span style=&#34;color:#f92672&#34;&gt;&amp;amp;&lt;/span&gt; select) &lt;span style=&#34;color:#f92672&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;　　就好了。&lt;/p&gt;&#xA;&lt;p&gt;　　(另外说到用位来存情况就想到了之前走心群里遇到的一道高中排列组合题，题目是10颗一样的糖，每天至少吃一颗，一共有几种吃法？&#xA;泉哥的答案：C9_0 + C9_1 +&amp;hellip;+ c9_9=2^9，(至今没想明白为啥= =)&#xA;网上看到另一种思路：把10颗糖从左向右排成一列，第1天一定会吃第1颗糖，将它记为1，如果接下来的一颗糖和前一颗糖在同一天吃，就把这颗糖记为和前一颗糖相同的数字，即前一颗为1这一颗也为1，前一颗为0这一颗也为0，这样这列糖就可以表示为一个首位为1的10位二进制数，这样的数一共有2^9=512个，即为512种吃法。二进制真奇妙。&amp;#x1f606;)&lt;/p&gt;&#xA;&lt;h2 id=&#34;2双指针法解决链表问题&#34;&gt;2.双指针法解决链表问题&lt;/h2&gt;&#xA;&lt;h3 id=&#34;环形链表&#34;&gt;环形链表&lt;/h3&gt;&#xA;&lt;p&gt;　　检查链表有没有环推荐双指针法，因为具有O(1)的空间复杂度，也可以用其他方法比如哈希表法或者集合大小法。 &lt;br&gt;&#xA;　　&lt;a href=&#34;https://leetcode-cn.com/problems/linked-list-cycle-ii/&#34;&gt;环形链表Ⅱ题号142&lt;/a&gt;，双指针法的算法步骤（题解里已经有数学证明）（前半部分和环形链表Ⅰ的解法相同）：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;设置一快一慢两个指针，slow移动一下fast移动两下。若&lt;code&gt;fast == nullptr&lt;/code&gt;说明无环，若&lt;code&gt;fast == slow&lt;/code&gt;说明fast &lt;strong&gt;套圈&lt;/strong&gt; 了slow，链表存在环。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;此时将fast置为head，slow维持不变，然后两指针分别同时移动，相遇点即为成环点。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;相交链表&#34;&gt;相交链表&lt;/h3&gt;&#xA;&lt;p&gt;　　&lt;a href=&#34;https://leetcode-cn.com/problems/intersection-of-two-linked-lists/&#34;&gt;相交链表&lt;/a&gt;也可以用双指针法解决，具体做法：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;分别设置两个指针p1p2，从两个头结点headA和headB处开始遍历。&lt;/li&gt;&#xA;&lt;li&gt;若p1遍历到headA所在链表的结尾，则把p1设置为headB，继续遍历；若p2遍历到headB所在链表的结尾，则把p2设置为headA继续遍历。&lt;/li&gt;&#xA;&lt;li&gt;两指针相遇点即为相交点。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;　　原理很简单，设A、B两个链表不相交的部分分别为a、b，相交部分为merge，则&lt;code&gt;a + merge + b = b + merge + a&lt;/code&gt;，等号两侧分别为两个指针按照顺序走过的路径相加，因此相遇点就是相交点。&lt;/p&gt;&#xA;&lt;h2 id=&#34;3powxn&#34;&gt;3.Pow(x,n)&lt;/h2&gt;&#xA;&lt;p&gt;踩坑过程:&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;-&amp;gt; 直接递归调用自身     &#xA;-&amp;gt; 一些例子导致栈溢出     &#xA;-&amp;gt; 改用循环处理       &#xA;-&amp;gt; ｎ可能为负数没考虑到        &#xA;-&amp;gt; ｎ为负数时，ｎ变成-n，x变为1/x       &#xA;-&amp;gt; 一些例子会报错： `runtime error: negation of -2147483648 cannot be represented in type &#39;int&#39;`，问题出在n变为-n时，正数和负数的最大表示范围不一样。         &#xA;-&amp;gt; 用long long类型变量N代替n：`long long N = n;`    &#xA;-&amp;gt; 2.00000 -2147483648的例子还是会超出时间限制 感受到了深深的恶意      &#xA;-&amp;gt; 向题解低头，用二分递归实现，简洁优雅卧槽&#xA;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;最终代码：&lt;/p&gt;</description>
    </item>
    <item>
      <title>双系统Ubuntu硬盘扩容&#43;卸载Ubuntu系统 </title>
      <link>http://www.ririshihaori.com:80/posts/2019/12/ubuntu%E6%89%A9%E5%AE%B9/</link>
      <pubDate>Mon, 02 Dec 2019 00:23:55 +0800</pubDate>
      <guid>http://www.ririshihaori.com:80/posts/2019/12/ubuntu%E6%89%A9%E5%AE%B9/</guid>
      <description>&lt;p&gt;　　开发板子需要安装Xilinx的Vivado安装环境，安装时发现需要win10专业版，家庭版不行，所以想着装到双系统的Ubuntu1604下，就去机房弄了块硬盘。&lt;/p&gt;&#xA;&lt;h2 id=&#34;双系统给ubuntu扩容&#34;&gt;双系统给Ubuntu扩容&lt;/h2&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;win10下右键“计算机”-“管理”-“磁盘管理”,压缩卷并新建卷，选择按照NFTS格式格式化。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;重启进入ubuntu，使用&lt;code&gt;df -h&lt;/code&gt;查看ubuntu下磁盘挂载点，通过磁盘大小判断备用磁盘的名称，形如&lt;code&gt;/dev/sda2&lt;/code&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;使用&lt;code&gt;sudo umount /dev/sda2&lt;/code&gt;解挂载&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;使用&lt;code&gt;mkfs -t ext4 /dev/sda2&lt;/code&gt;将磁盘格式化为ext4格式&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;使用&lt;code&gt;ls -l /dev/disk/by-uuid&lt;/code&gt;查询sda2对应的UUID，假设其为“abcd”&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;使用&lt;code&gt;sudo vi /etc/fstab&lt;/code&gt;编辑fstab，在最后一行添加&lt;code&gt;UUID=abcd /home/open ext4 defaults 0 2&lt;/code&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;重启，发现已将磁盘挂载到&lt;code&gt;/home/open&lt;/code&gt;下&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;双系统删除ubuntu系统&#34;&gt;双系统删除Ubuntu系统&lt;/h2&gt;&#xA;&lt;p&gt;　　。。。扩容了以后发现vivado只支持64位系统，之前装的时候不小心装成了32位的，还是删了Ubuntu系统直接换虚拟机算了。 &lt;br&gt;&#xA;　　但是不能直接清空硬盘分区，会导致启动后win10也进不去，需要按照步骤来。删之前先备份了下&lt;code&gt;/home&lt;/code&gt;下的所有东西。&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;首先&lt;code&gt;win + R&lt;/code&gt;,然后输入&lt;code&gt;msinfo32&lt;/code&gt;回车，查看系统信息中的&lt;code&gt;BIOS模式&lt;/code&gt;来确认系统启动方式。(我这里是传统模式，即Legacy BIOS模式)。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;若为Legacy模式，可以下载并运行MbrFix程序或用类似于分区助手的软件修复mbr。重启win10没有GNU GRUB的系统选择界面则说明修复成功。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;之后就可以用分区助手或者右键&amp;quot;计算机&amp;quot;-“管理”-“磁盘管理”里面删除Ubuntu系统所在的硬盘分区了。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;</description>
    </item>
    <item>
      <title>Python提取Win10锁屏Spotlight</title>
      <link>http://www.ririshihaori.com:80/posts/2019/11/win10spotlight/</link>
      <pubDate>Wed, 27 Nov 2019 19:10:14 +0800</pubDate>
      <guid>http://www.ririshihaori.com:80/posts/2019/11/win10spotlight/</guid>
      <description>&lt;p&gt;　　刚才看见Win10锁屏界面的星空图特别好看，想要下载下来发微博。查了一下知乎上的方法：&lt;/p&gt;&#xA;&lt;p&gt;　　&lt;code&gt;win + r&lt;/code&gt;然后在弹出的运行框中运行&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;%localappdata%\Packages\Microsoft.Windows.ContentDeliveryManager_cw5n1h2txyewy\LocalState\Assets&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;　　会弹出一个文件夹，貌似锁屏图片文件就是存在这个文件夹里，只不过文件都没有后缀，想要看得手动加.jpg才能打开看。&lt;/p&gt;&#xA;&lt;p&gt;　　使用python实现，先查了一下用python怎么得到这个&lt;code&gt;%localappdata%&lt;/code&gt;路径,具体实现:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; os &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    localappdata &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; os&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;environ[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;LOCALAPPDATA&amp;#39;&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;　　有了路径然后就可以用pillow把图片转存出来。这是全部代码：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; os &#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;from&lt;/span&gt; PIL &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; Image&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;from&lt;/span&gt; shutil &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; copy2&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    localappdata &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; os&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;environ[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;LOCALAPPDATA&amp;#39;&lt;/span&gt;]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    srcPath &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;fr&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;localappdata&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;\Packages\Microsoft.Windows.ContentDeliveryManager_cw5n1h2txyewy\LocalState\Assets&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    destPath &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;fr&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;{&lt;/span&gt;os&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;getcwd()&lt;span style=&#34;color:#e6db74&#34;&gt;}&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;\pics&amp;#39;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fileList &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; os&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;listdir(srcPath)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    os&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;makedirs(destPath, exist_ok &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;True&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; item &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; fileList:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        im&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;Image&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;open(srcPath &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\\&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; item)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        copy2(srcPath &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\\&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; item, destPath &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\\&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; item &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;.jpg&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        print(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;成功拷到一个图片~~&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;!-- raw HTML omitted --&gt;</description>
    </item>
    <item>
      <title>MIT 6.824 Lab1实现</title>
      <link>http://www.ririshihaori.com:80/posts/2019/11/6.824lab1/</link>
      <pubDate>Tue, 26 Nov 2019 00:23:55 +0800</pubDate>
      <guid>http://www.ririshihaori.com:80/posts/2019/11/6.824lab1/</guid>
      <description>&lt;p&gt;　　本文实现MIT的&lt;a href=&#34;https://pdos.csail.mit.edu/6.824/index.html&#34;&gt;分布式系统课程（6.824）&lt;/a&gt;的配套实验一。&lt;br&gt;&#xA;　　本实验将用go语言实现一个MapReduce库，MapReduce的概念可以参考&lt;a href=&#34;http://static.googleusercontent.com/media/research.google.com/zh-CN//archive/mapreduce-osdi04.pdf&#34;&gt;Google的这篇论文&lt;/a&gt;。　　　　　&lt;/p&gt;&#xA;&lt;p&gt;　　首先拉取实验代码的仓库&lt;/p&gt;&#xA;&lt;pre&gt;&lt;code&gt;`git clone git://g.csail.mit.edu/6.824-golabs-2018 6.824`&#xA;&lt;/code&gt;&lt;/pre&gt;</description>
    </item>
    <item>
      <title>Ubuntu16.04升级Python3.7</title>
      <link>http://www.ririshihaori.com:80/posts/2019/11/ubuntu%E5%8D%87%E7%BA%A7python/</link>
      <pubDate>Tue, 26 Nov 2019 00:23:55 +0800</pubDate>
      <guid>http://www.ririshihaori.com:80/posts/2019/11/ubuntu%E5%8D%87%E7%BA%A7python/</guid>
      <description>&lt;p&gt;Ubuntu16.04默认带的Python是2.7.12和3.5，升级到Python3.7的步骤如下：&lt;/p&gt;&#xA;&lt;p&gt;第一步，增加ppa仓库:&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;$sudo add-apt-repository ppa:jonathonf/python-3.7&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;第二步，升级apt索引，更新python:&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;$sudo apt-get update&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;$sudo apt-get install python3.7&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;第三步，更换系统默认的软链命令Python3到新的Python3.7:&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;$sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.5 1&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;$sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.7 2&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;最后，update-alternatives命令可以修改系统默认命令的软链指向，通过以下命令，可以切换Python3的指向:&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;$sudo update-alternatives --config python3&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;查看python2 和 python3的版本:&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;$python2 --version&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;$python3 --verison&lt;/code&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Barrelfish操作系统 (1)系统介绍 </title>
      <link>http://www.ririshihaori.com:80/posts/2019/11/barrelfish-overview/</link>
      <pubDate>Mon, 25 Nov 2019 00:23:55 +0800</pubDate>
      <guid>http://www.ririshihaori.com:80/posts/2019/11/barrelfish-overview/</guid>
      <description>&lt;p&gt;　　网上貌似没有Barrelfish的中文文档，正好最近在写文献综述，所以这里整理一下，为以后想要研究这个系统的童鞋省一点时间。&lt;/p&gt;&#xA;&lt;h2 id=&#34;简介&#34;&gt;简介&lt;/h2&gt;&#xA;&lt;p&gt;　　Barrelfish是微软剑桥研究院和苏黎世理工大学提出的一个面向异构、众核体系的操作系统，其旨在解决异构、众核体系结构上操作系统的可扩展性问题。系统基于&lt;a href=&#34;https://zh.wikipedia.org/wiki/%E5%BE%AE%E5%85%A7%E6%A0%B8&#34;&gt;微内核&lt;/a&gt;和多内核(Multikernel)的思想设计。      &lt;br&gt;&#xA;　　多内核是指在每一个处理器核心上都运行一个操作系统内核实例，内核之间不共享任何内存（即使在有共享内存的硬件上），系统的其余部分是构建在这些内核之上的单核进程，可以视为一个分布式系统，系统节点之间基于显式的消息进行通信。即共享内存只用于显式的消息传递、数据传递以及动态启动其他内核时。用户级应用进程可以跨核部署并共享地址空间，但这个功能是由Barrelfish用户空间的运行时库提供的。下面是Barrelfish的架构示意图。其中的UMP(User Message Passing)和LMP(Local Message&#xA;Passing)是Barrelfish内的两种消息通信方式，UMP是跨核的消息通信，LMP是核内消息通信。&lt;/p&gt;&#xA;&lt;!-- raw HTML omitted --&gt;&#xA;&lt;!-- raw HTML omitted --&gt;&#xA;&lt;h2 id=&#34;内核cpu-driver&#34;&gt;内核(CPU Driver)&lt;/h2&gt;&#xA;&lt;p&gt;　　CPU Driver是Barrelfish的内核，运行于Barrelfish所运行的机器上的单个处理器核心里，支持多种处理器架构。CPU Driver是单线程、不可抢占的，运行在关中断的模式下。可以认为它在连续地运行异常处理程序，比如中断(interrupt)、异常(fault)、来自用户空间的系统调用(system call)。如果没有可以运行的异常处理程序，它就执行一个用户空间的任务。&lt;/p&gt;&#xA;&lt;p&gt;　　CPU Driver的功能包括:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;负责时钟中断和全部异常，并将其他高级中断转发到用户层&lt;/li&gt;&#xA;&lt;li&gt;调度本核上的所有用户进程(Dispatchers）&lt;/li&gt;&#xA;&lt;li&gt;基于Capabiltiy提供一组最基本的系统调用接口为用户应用和高级系统服务应用提供服务&lt;/li&gt;&#xA;&lt;li&gt;负责本核上的进程间通信&lt;/li&gt;&#xA;&lt;li&gt;对硬件的安全访问(MMU、APIC等等)&lt;/li&gt;&#xA;&lt;li&gt;对内存和内核对象的访问(基于capability(权能)实现)&lt;/li&gt;&#xA;&lt;li&gt;启动初始化过程和调起第一个用户进程&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;CPU Driver提供的系统调用：&lt;/p&gt;&#xA;&lt;!-- raw HTML omitted --&gt;&#xA;&lt;p&gt;　　CPU驱动程序不提供内核线程，原因有二。首先，Barrelfish提供给用户空间程序的处理器抽象是一个dispatcher，而不是线程（一个Dispatcher内可以有多个用户线程）。其次，由于内核是单线程的且不可抢占的，因此它仅为所有操作使用一个静态分配的堆栈。在执行完单个异常处理程序之后，将丢弃并重置此堆栈的内容。&lt;/p&gt;&#xA;&lt;p&gt;　　Barrelfish目前提供两种在编译时指定的调度方式：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;轮转调度(RR)&lt;/li&gt;&#xA;&lt;li&gt;基于速率的最早截止期调度法(rate-based earliest deadline scheduler) (具有更好的实时性)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;进程dispatcher&#34;&gt;进程(Dispatcher)&lt;/h2&gt;&#xA;&lt;p&gt;　　Dispatcher是内核调度的单元，相当于Unix中进程的概念。一个应用程序(在Barrelfish里称为domain)可以分布在多个核上，在每个核上都有一个dispatcher。Dispatcher不能在核间迁移。  &lt;br&gt;&#xA;　　当内核根据调度结果决定运行某一个dispatcher时，内核需要“upcall”该dispatcher，系统从内核态进入用户态，之后与该dispatcher对应的用户级代码开始执行用户空间的线程调度，以及处理其他事件（比如来自内核的缺页错误、或者Domain间消息）。  &lt;br&gt;&#xA;　　内核为每个dispatcher维护一个DCB (dispatcher控制块)，如图所示，DCB里面包含了这个dispatcher的各种信息，包括&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;CSpace（Capability空间，即所拥有的所有Capabiltiy，在内核中的形式是一个二级capability查询表）&lt;/li&gt;&#xA;&lt;li&gt;VSpace（页表，以vode类型的capability形式实现）&lt;/li&gt;&#xA;&lt;li&gt;一些调度参数&lt;/li&gt;&#xA;&lt;li&gt;指向用户空间dispacher结构体的指针（用于调度dispatcher内部的线程）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;!-- raw HTML omitted --&gt;&#xA;&lt;p&gt;　　每一个dispatcher可以有两种模式，分别是enabled和disabled，当处于enabled模式下时，该dispatcher运行dispatcher下的用户线程，当处于disabled模式下时，该dispatcher运行dispatcher自身代码（如管理TCB、运行线程队列中的线程）。     &lt;br&gt;&#xA;　　Dispatcher定义了一组upcall的接口，以供内核对自身进行调度。其中最主要的upcall是run()，当内核决定调度某个dispatcher时，它以指向该dispatcher的页表基址的capability为参数调用该dispatcher的run()，然后该dispatcher决定运行哪一个用户线程，恢复该线程的状态，并运行该线程。在dispatcher被run()之后，以及用户线程被执行之前，该dispatcher都是disable模式，在用户线程开始运行后，该dispatcher处于enabled模式。 &lt;br&gt;&#xA;　　当处于enabled模式下的disaptcher被抢占时，内核把所有寄存器状态存在该dispatcher的“enabled区域”（见上图），当该dispatcher之后重新被调度时，它可以从enabled区域恢复之前的寄存器状态，继续运行之前的用户线程，也可以调度另外一个用户线程来运行，但在执行另外一个用户线程之前必须先把之前的用户线程的寄存器状态存到TCB里。  &lt;br&gt;&#xA;　　当处于disabled模式下的dispatcher被抢占时，内核把所有寄存器状态存在该dispatcher的“disabled区域”（见上图）,当内核调度一个处于disabled模式下的dispatcher时，内核不会调用其run()类型的upcall，而是从disabled区域恢复之前的寄存器状态，允许之前被打断的dispatcher自身代码从被抢占处继续运行。&lt;/p&gt;&#xA;&lt;h2 id=&#34;运行时库runtime-library&#34;&gt;运行时库(Runtime library)&lt;/h2&gt;&#xA;&lt;p&gt;　　Barrelfish提供两个基本的库:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;标准C库&lt;/li&gt;&#xA;&lt;li&gt;lib barrelfish&#xA;　&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;　　后者实现了以下系统功能:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Python实现微博爬取&#43;统计高频词</title>
      <link>http://www.ririshihaori.com:80/posts/2019/11/%E5%BE%AE%E5%8D%9A%E7%88%AC%E5%8F%96%E5%B9%B6%E7%BB%9F%E8%AE%A1%E9%AB%98%E9%A2%91%E8%AF%8D/</link>
      <pubDate>Sat, 23 Nov 2019 13:57:11 +0800</pubDate>
      <guid>http://www.ririshihaori.com:80/posts/2019/11/%E5%BE%AE%E5%8D%9A%E7%88%AC%E5%8F%96%E5%B9%B6%E7%BB%9F%E8%AE%A1%E9%AB%98%E9%A2%91%E8%AF%8D/</guid>
      <description>&lt;p&gt;帮小乔爬了一下共青团中央的所有微博，做了一下高频词统计。&lt;/p&gt;&#xA;&lt;h2 id=&#34;爬取数据&#34;&gt;爬取数据&lt;/h2&gt;&#xA;&lt;p&gt;爬数据用的github上别人的项目，地址是https://github.com/dataabc/weibo-crawler &lt;br&gt;&#xA;爬之前需要设置好要爬的微博的微博id，以及时间范围、原创微博还是转发微博、是否爬图片、视频等选项。&#xA;然后直接运行&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;python weibo.py&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;这里把时间设置成1900-01-01，爬了共青团中央至2019-11-23的所有原创微博。&lt;br&gt;&#xA;这是爬好的数据，一共有两万多条数据。&lt;/p&gt;&#xA;&lt;!-- raw HTML omitted --&gt;&#xA;&lt;h2 id=&#34;统计高频词&#34;&gt;统计高频词&lt;/h2&gt;&#xA;&lt;p&gt;使用jieba分词并统计高频词频率&lt;br&gt;&#xA;先把微博内容提取出来&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;import&lt;/span&gt; csv&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;with&lt;/span&gt; open(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;3937348351.csv&amp;#39;&lt;/span&gt;,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;r&amp;#39;&lt;/span&gt; , encoding&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;utf-8&amp;#39;&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; csvfile:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        reader &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; csv&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;DictReader(csvfile)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        column &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; [row[&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;正文&amp;#39;&lt;/span&gt;] &lt;span style=&#34;color:#66d9ef&#34;&gt;for&lt;/span&gt; row &lt;span style=&#34;color:#f92672&#34;&gt;in&lt;/span&gt; reader]&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;with&lt;/span&gt; open(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;C:&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\\&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;Users&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\\&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;Lenovo&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\\&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;Desktop&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\\&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;词频统计&lt;/span&gt;&lt;span style=&#34;color:#ae81ff&#34;&gt;\\&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;in.txt&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;w&amp;#34;&lt;/span&gt;, encoding&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;utf-8&amp;#39;&lt;/span&gt;) &lt;span style=&#34;color:#66d9ef&#34;&gt;as&lt;/span&gt; f:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        f&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;write(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;join(column))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后使用jieba处理&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    stop &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; input(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;stop路径: &amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    jieba&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;analyse&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;set_stop_words(stop)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    file &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; input(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;输入文件路径: &amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    lines &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; open(file,encoding&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;utf8&amp;#39;&lt;/span&gt;)&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;read()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    new &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; input(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;输出文件路径: &amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    newfile &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; open(new,&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;w&amp;#34;&lt;/span&gt;,encoding&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;utf8&amp;#39;&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    num&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;int(input(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;高频词个数: &amp;#39;&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    newfile&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;write(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;  &amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;join(analyse&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;extract_tags(lines, topK&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;num, withWeight&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;False&lt;/span&gt;, allowPOS&lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt;())))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    newfile&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;close()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;高频词个数输入100，就可以得到共青团中央前100的高频词了，这是结果：&lt;/p&gt;</description>
    </item>
    <item>
      <title>Hello Again </title>
      <link>http://www.ririshihaori.com:80/posts/2019/11/hello/</link>
      <pubDate>Wed, 20 Nov 2019 20:20:31 +0800</pubDate>
      <guid>http://www.ririshihaori.com:80/posts/2019/11/hello/</guid>
      <description>&lt;p&gt;第三次搭博客了，从来没有养成写博客的习惯&lt;br&gt;&#xA;今天看了&lt;a href=&#34;https://www.xzywisdili.com/&#34;&gt;小徐的博客&lt;/a&gt;很受震撼，决心向小徐学习&amp;#x1f618;，开始认真写博客，记录一下平时踩的坑和心路历程&lt;/p&gt;&#xA;&lt;p&gt;博客这次用的是Hugo，先用apt-get安装了一下发现版本太老了，好多主题都用不了，发布的时候会报&lt;code&gt;function not found&lt;/code&gt;的错误，所以remove后直接上github下了最新的dep包 &lt;br&gt;&#xA;下完以后可以用命令建一个网站也就是一个文件夹：&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;$hugo new site blog&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;建好之后在content文件夹里面添加.md格式的src文件，然后改一下config文件就可以发布了&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;$hugo server --bind=0.0.0.0 --baseURL=http://www.ririshihaori.com -w -p 80&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;--bind&lt;/code&gt;好像设置成server ip 的话有点问题，因为阿里云的问题，所以设成0.0.0.0&lt;br&gt;&#xA;&lt;code&gt;-w&lt;/code&gt;是监视src变化的选项，一有变化随时刷新&#xA;&lt;code&gt;--baseURL&lt;/code&gt;和&lt;code&gt;-p&lt;/code&gt;设置地址和端口&lt;/p&gt;&#xA;&lt;p&gt;主题用的是&lt;a href=&#34;https://github.com/meibenny/elephants&#34;&gt;Elephants&lt;/a&gt;，极简主义~&amp;#x1f606;&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
