<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>纸蛇</title>
  
  <subtitle>Papersnake</subtitle>
  <link href="https://blog.pka.moe/atom.xml" rel="self"/>
  
  <link href="https://blog.pka.moe/"/>
  <updated>2020-07-29T10:12:00.000Z</updated>
  <id>https://blog.pka.moe/</id>
  
  <author>
    <name>Papersnake</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>

  <follow_challenge>
    <feedId>58856051670814792</feedId>
    <userId>56199145723887616</userId>
  </follow_challenge>
  
  <entry>
    <title>旁路攻击：一道典型题的分析</title>
    <link href="https://blog.pka.moe/side-channel-attack/"/>
    <id>https://blog.pka.moe/side-channel-attack/</id>
    <published>2020-07-29T10:12:00.000Z</published>
    <updated>2020-07-29T10:12:00.000Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><p>分析 <strong>side-channel attack</strong> 的典型题 <a href="https://github.com/ctfs/write-ups-2015/tree/master/csaw-ctf-2015/reverse/wyvern-500">CSAW CTF 2015 - wyvern</a>。</p><span id="more"></span><h2><span id="csaw-quals-2015-wyvern-500">CSAW QUALS 2015: wyvern-500</span></h2><p><strong>Category:</strong> Reversing <strong>Points:</strong> 500 <strong>Solves:</strong> 96 <strong>Description:</strong></p><blockquote><p>There’s a dragon afoot, we need a hero. Give us the dragon’s secret and we’ll give you a flag.HINT: static is only 1 of 2 methods to RE. IDA torrent unnecessary</p><p><a href="https://github.com/ctfs/write-ups-2015/blob/master/csaw-ctf-2015/reverse/wyvern-500/wyvern_c85f1be480808a9da350faaa6104a19b"><span id="inline-blue">下载文件</span></a></p></blockquote><p>程序是 C++写的 64 位 ELF，运行时需要输入 secret 验证，然后输出验证结果。</p><pre><code class="basic">+-----------------------+|    Welcome Hero       |+-----------------------+[!] Quest: there is a dragon prowling the domain.        brute strength and magic is our only hope. Test your skill.Enter the dragon&#39;s secret: flag[-] You have failed. The dragon&#39;s power, speed and intelligence was greater.</code></pre><p>使用 IDA Pro 反编译，查看伪码，注意到关键语句：</p><pre><code class="c">std::vector&lt;int,std::allocator&lt;int&gt;&gt;::push_back(&amp;hero, &amp;secret_100);std::vector&lt;int,std::allocator&lt;int&gt;&gt;::push_back(&amp;hero, &amp;secret_214);std::vector&lt;int,std::allocator&lt;int&gt;&gt;::push_back(&amp;hero, &amp;secret_266);std::vector&lt;int,std::allocator&lt;int&gt;&gt;::push_back(&amp;hero, &amp;secret_369);std::vector&lt;int,std::allocator&lt;int&gt;&gt;::push_back(&amp;hero, &amp;secret_417);std::vector&lt;int,std::allocator&lt;int&gt;&gt;::push_back(&amp;hero, &amp;secret_527);std::vector&lt;int,std::allocator&lt;int&gt;&gt;::push_back(&amp;hero, &amp;secret_622);std::vector&lt;int,std::allocator&lt;int&gt;&gt;::push_back(&amp;hero, &amp;secret_733);std::vector&lt;int,std::allocator&lt;int&gt;&gt;::push_back(&amp;hero, &amp;secret_847);std::vector&lt;int,std::allocator&lt;int&gt;&gt;::push_back(&amp;hero, &amp;secret_942);std::vector&lt;int,std::allocator&lt;int&gt;&gt;::push_back(&amp;hero, &amp;secret_1054);std::vector&lt;int,std::allocator&lt;int&gt;&gt;::push_back(&amp;hero, &amp;secret_1106);std::vector&lt;int,std::allocator&lt;int&gt;&gt;::push_back(&amp;hero, &amp;secret_1222);std::vector&lt;int,std::allocator&lt;int&gt;&gt;::push_back(&amp;hero, &amp;secret_1336);std::vector&lt;int,std::allocator&lt;int&gt;&gt;::push_back(&amp;hero, &amp;secret_1441);std::vector&lt;int,std::allocator&lt;int&gt;&gt;::push_back(&amp;hero, &amp;secret_1540);std::vector&lt;int,std::allocator&lt;int&gt;&gt;::push_back(&amp;hero, &amp;secret_1589);std::vector&lt;int,std::allocator&lt;int&gt;&gt;::push_back(&amp;hero, &amp;secret_1686);std::vector&lt;int,std::allocator&lt;int&gt;&gt;::push_back(&amp;hero, &amp;secret_1796);std::vector&lt;int,std::allocator&lt;int&gt;&gt;::push_back(&amp;hero, &amp;secret_1891);std::vector&lt;int,std::allocator&lt;int&gt;&gt;::push_back(&amp;hero, &amp;secret_1996);std::vector&lt;int,std::allocator&lt;int&gt;&gt;::push_back(&amp;hero, &amp;secret_2112);std::vector&lt;int,std::allocator&lt;int&gt;&gt;::push_back(&amp;hero, &amp;secret_2165);std::vector&lt;int,std::allocator&lt;int&gt;&gt;::push_back(&amp;hero, &amp;secret_2260);std::vector&lt;int,std::allocator&lt;int&gt;&gt;::push_back(&amp;hero, &amp;secret_2336);std::vector&lt;int,std::allocator&lt;int&gt;&gt;::push_back(&amp;hero, &amp;secret_2412);std::vector&lt;int,std::allocator&lt;int&gt;&gt;::push_back(&amp;hero, &amp;secret_2498);std::vector&lt;int,std::allocator&lt;int&gt;&gt;::push_back(&amp;hero, &amp;secret_2575);v6 = std::string::length(v11) - 1LL != legend &gt;&gt; 2;</code></pre><h2><span id="思路一找规律">思路一：找规律</span></h2><p>观察到 <code>secret_\d*</code> 字段中的数字每次相差不大，且 100 正好是 d（dragon 首字母） 的 ASCII 符号，所以猜测 secret 为数字差代表的 ASCII。（<a href="https://ohaithe.re/post/129657401392/csaw-quals-2015-reversing-500-wyvern">这篇文章</a> 从伪码中直接读出了加密方法）</p><pre><code class="c">a = [0,100,214,266,369,417,527,622,733,847,942,1054,1106,1222,1336,1441,1540,1589,1686,1796,1891,1996,2112,2165,2260,2336,2412,2498,2575]for i in range(1,len(a)):    print(chr(a[i]-a[i-1]),end=&quot;&quot;)</code></pre><p>得到结果 dr4g0n_or_p4tric1an_it5_LLVM</p><h2><span id="思路二side-channel-attack">思路二：side-channel attack</span></h2><p>legend 的值为初始的 0x73 ，故结果长度为 legend &gt;&gt; 2 &#x3D; 28，观察发现（或者直接假设）检查函数会将输入的字符一个个检测，一旦错误就直接退出，因此前几位正确的 secret 执行的指令更多。通过外部工具观察执行指令次数来破解 secret。</p><h3><span id="pintools">Pintools</span></h3><p>工具使用 Intel 的 <a href="https://software.intel.com/en-us/articles/pin-a-dynamic-binary-instrumentation-tool">Pintools</a> 中 inscount0.so 模块，代码如下：</p><pre><code class="python">import osimport reflag = &#39;&#39;chars = []for i in range(47,58):    chars.append(chr(i))for i in range(65,91):    chars.append(chr(i))for i in range(97,123):    chars.append(chr(i))chars.append(&#39;@&#39;)chars.append(&#39;_&#39;)move = Truecur_max = 0while(move):    move = False    for c in chars:        s = flag + c        s = s.ljust(28,&#39;A&#39;) #补全 28 位        cmd = os.popen(&quot;echo &#39;%s&#39; | ../../../../pin -t inscount0.so -- /root/pwn/wyvern;cat ./inscount.out&quot; % s).read()        cnt = int(re.search(&quot;Count ([0-9]*)&quot;, cmd).group(1)) #统计指令数量        if c==&#39;/&#39;:            cur_max = max(cnt,cur_max)        if cnt &gt; cur_max:            print(s)            flag = flag + c            cur_max = cnt            move = True            index = 0            breakprint(&quot;flag:&quot;)print(flag)</code></pre><p>（思路来自 <a href="https://bruce30262.github.io/csaw-ctf-2015-wyvern/">这篇文章</a>）</p><h2><span id="ltrace">ltrace</span></h2><p>strace 用来跟踪一个进程的系统调用或信号产生的情况，ltrace 用来跟踪进程调用库函数的情况。</p><p>思路和使用 Pin 工具一致，实现更加简洁，速度也更快（代码来自 <a href="https://gist.github.com/inaz2/1682e7254b1c7a2cf641">inaz2</a>）。</p><pre><code class="python">from subprocess import Popen, PIPEsecret_length = Nonefor i in xrange(40):        p = Popen([&#39;ltrace&#39;, &#39;./wyvern&#39;], stdin=PIPE, stdout=PIPE, stderr=PIPE)        line = &#39;A&#39; * i + &#39;\\n&#39;        stdout, stderr = p.communicate(line)        num_lines = len(stderr.split(&#39;\\n&#39;))        if num_lines != 42:                secret_length = i                breakprint &quot;[+] secret length = %d&quot; % secret_lengthsecret = bytearray(&#39;A&#39; * i)for i in xrange(secret_length):        results = []        for c in xrange(0x20, 0x7f):                p = Popen([&#39;ltrace&#39;, &#39;./wyvern&#39;], stdin=PIPE, stdout=PIPE, stderr=PIPE)                secret[i] = chr(c)                line = str(secret) + &#39;\\n&#39;                stdout, stderr = p.communicate(line)                num_lines = len(stderr.split(&#39;\\n&#39;))                results.append((num_lines, secret[i]))        results.sort(reverse=True)        secret[i] = results[0][1]        print &quot;[+] secret = %s&quot; % str(secret)</code></pre><p>可以很快得到结果。</p><pre><code class="bash">[+] secret length = 28[+] secret = dAAAAAAAAAAAAAAAAAAAAAAAAAAA[+] secret = drAAAAAAAAAAAAAAAAAAAAAAAAAA[+] secret = dr4AAAAAAAAAAAAAAAAAAAAAAAAA[+] secret = dr4gAAAAAAAAAAAAAAAAAAAAAAAA[+] secret = dr4g0AAAAAAAAAAAAAAAAAAAAAAA[+] secret = dr4g0nAAAAAAAAAAAAAAAAAAAAAA[+] secret = dr4g0n_AAAAAAAAAAAAAAAAAAAAA[+] secret = dr4g0n_oAAAAAAAAAAAAAAAAAAAA[+] secret = dr4g0n_orAAAAAAAAAAAAAAAAAAA[+] secret = dr4g0n_or_AAAAAAAAAAAAAAAAAA[+] secret = dr4g0n_or_pAAAAAAAAAAAAAAAAA[+] secret = dr4g0n_or_p4AAAAAAAAAAAAAAAA[+] secret = dr4g0n_or_p4tAAAAAAAAAAAAAAA[+] secret = dr4g0n_or_p4trAAAAAAAAAAAAAA[+] secret = dr4g0n_or_p4triAAAAAAAAAAAAA[+] secret = dr4g0n_or_p4tricAAAAAAAAAAAA[+] secret = dr4g0n_or_p4tric1AAAAAAAAAAA[+] secret = dr4g0n_or_p4tric1aAAAAAAAAAA[+] secret = dr4g0n_or_p4tric1anAAAAAAAAA[+] secret = dr4g0n_or_p4tric1an_AAAAAAAA[+] secret = dr4g0n_or_p4tric1an_iAAAAAAA[+] secret = dr4g0n_or_p4tric1an_itAAAAAA[+] secret = dr4g0n_or_p4tric1an_it5AAAAA[+] secret = dr4g0n_or_p4tric1an_it5_AAAA[+] secret = dr4g0n_or_p4tric1an_it5_LAAA[+] secret = dr4g0n_or_p4tric1an_it5_LLAA[+] secret = dr4g0n_or_p4tric1an_it5_LLVA[+] secret = dr4g0n_or_p4tric1an_it5_LLVM</code></pre><p>最后将 secret 输入，得到 flag：</p><pre><code class="bash">+-----------------------+|    Welcome Hero       |+-----------------------+[!] Quest: there is a dragon prowling the domain.        brute strength and magic is our only hope. Test your skill.Enter the dragon&#39;s secret: dr4g0n_or_p4tric1an_it5_LLVMsuccess[+] A great success! Here is a flag&#123;dr4g0n_or_p4tric1an_it5_LLVM&#125;</code></pre>]]></content>
    
    
    <summary type="html">&lt;p&gt;分析 &lt;strong&gt;side-channel attack&lt;/strong&gt; 的典型题 &lt;a href=&quot;https://github.com/ctfs/write-ups-2015/tree/master/csaw-ctf-2015/reverse/wyvern-500&quot;&gt;CSAW CTF 2015 - wyvern&lt;/a&gt;。&lt;/p&gt;</summary>
    
    
    
    <category term="CTF" scheme="https://blog.pka.moe/categories/CTF/"/>
    
    
    <category term="PWN" scheme="https://blog.pka.moe/tags/PWN/"/>
    
  </entry>
  
  <entry>
    <title>Python 常用技巧</title>
    <link href="https://blog.pka.moe/python-skills/"/>
    <id>https://blog.pka.moe/python-skills/</id>
    <published>2020-07-27T12:40:00.000Z</published>
    <updated>2020-07-27T12:40:00.000Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><p>在 Leetcode 上划水写写 Python3 ，主要追求程序的简洁和实现的精巧。</p><span id="more"></span><!-- toc --><ul><li><a href="#zen-of-python">Zen of Python</a></li><li><a href="#lru_cache">lru_cache</a><ul><li><a href="#509-%E6%96%90%E6%B3%A2%E9%82%A3%E5%A5%91%E6%95%B0">509. 斐波那契数</a></li><li><a href="#329-%E7%9F%A9%E9%98%B5%E4%B8%AD%E7%9A%84%E6%9C%80%E9%95%BF%E9%80%92%E5%A2%9E%E8%B7%AF%E5%BE%84">329. 矩阵中的最长递增路径</a></li><li><a href="#functools">functools</a></li></ul></li><li><a href="#%E4%BD%BF%E7%94%A8%E5%BC%82%E5%B8%B8%E6%8A%9B%E5%87%BA%E6%9C%BA%E5%88%B6%E8%A7%A3%E5%86%B3%E9%97%AE%E9%A2%98">使用异常抛出机制解决问题</a><ul><li><a href="#%E4%BB%80%E4%B9%88%E6%98%AF%E5%BC%82%E5%B8%B8">什么是异常？</a></li><li><a href="#%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86">异常处理</a></li><li><a href="#%E5%B7%A7%E7%94%A8%E5%BC%82%E5%B8%B8%E6%8A%9B%E5%87%BA%E6%9C%BA%E5%88%B6">巧用异常抛出机制</a></li><li><a href="#350-%E4%B8%A4%E4%B8%AA%E6%95%B0%E7%BB%84%E7%9A%84%E4%BA%A4%E9%9B%86-ii">350. 两个数组的交集 II</a></li></ul></li><li><a href="#%E8%BF%AD%E4%BB%A3%E5%99%A8-iter">迭代器 iter</a><ul><li><a href="#392-%E5%88%A4%E6%96%AD%E5%AD%90%E5%BA%8F%E5%88%97">392. 判断子序列</a></li></ul></li></ul><!-- tocstop --><h2><span id="zen-of-python">Zen of Python</span></h2><blockquote><p><strong>生活的最好状态是冷冷清清的风风火火。 ——木心</strong></p></blockquote><pre><code class="python">&gt;&gt;&gt; import thisThe Zen of Python, by Tim PetersBeautiful is better than ugly.Explicit is better than implicit.Simple is better than complex.Complex is better than complicated.Flat is better than nested.Sparse is better than dense.Readability counts.Special cases aren't special enough to break the rules.Although practicality beats purity.Errors should never pass silently.Unless explicitly silenced.In the face of ambiguity, refuse the temptation to guess.There should be one-- and preferably only one --obvious way to do it.Although that way may not be obvious at first unless you're Dutch.Now is better than never.Although never is often better than *right* now.If the implementation is hard to explain, it's a bad idea.If the implementation is easy to explain, it may be a good idea.Namespaces are one honking great idea -- let's do more of those!</code></pre><h2><span id="lru_cache">lru_cache</span></h2><p><code>lru_cache</code> 属于 <code>functools</code> ，是一个为函数提供缓存功能的装饰器，利用的是 <a href="https://en.wikipedia.org/wiki/Cache_algorithms#Examples">最久未使用算法 (Least recently used)</a> 进行缓存。适合在<strong>需要重用之前计算结果，且函数参数可哈希</strong>的情况下使用。比如<strong>动态规划、记忆化搜索</strong>，可以减少存储计算结果的代码。</p><p>该函数的默认调用参数为<code>@functools.lru_cache(maxsize=128, typed=False)</code>。特别的，如果 <em>maxsize</em> 设为 <code>None</code>，LRU 特性将被禁用且缓存可无限增长。</p><h3><span id="509-斐波那契数">509. 斐波那契数</span></h3><pre><code class="python">class Solution:    @lru_cache(None)    def fib(self, N: int) -&gt; int:        if N &lt; 2:            return N        return self.fib(N-1) + self.fib(N-2)</code></pre><h3><span id="329-矩阵中的最长递增路径">329. 矩阵中的最长递增路径</span></h3><blockquote><p>给定一个整数矩阵，找出最长递增路径的长度。</p><p>对于每个单元格，你可以往上，下，左，右四个方向移动。 你不能在对角线方向上移动或移动到边界外（即不允许环绕）。</p></blockquote><p>直接使用 <code>dfs</code> + <code>lru_cache</code> ：</p><pre><code class="python">class Solution:    def longestIncreasingPath(self, matrix: List[List[int]]) -&gt; int:        @lru_cache(None)        def dfs(i,j):            res = 1            if i-1&gt;=0 and matrix[i-1][j]&gt;matrix[i][j]:                res=max(res,dfs(i-1,j)+1)            if i+1&lt;len(matrix) and matrix[i+1][j]&gt;matrix[i][j]:                res=max(res,dfs(i+1,j)+1)            if j-1&gt;=0 and matrix[i][j-1]&gt;matrix[i][j]:                res=max(res,dfs(i,j-1)+1)            if j+1&lt;len(matrix[0]) and matrix[i][j+1]&gt;matrix[i][j]:                res=max(res,dfs(i,j+1)+1)            return res        res = 0        for i in range(len(matrix)):            for j in range(len(matrix[0])):                res = max(res,dfs(i,j))        return res</code></pre><h3><span id="functools">functools</span></h3><blockquote><p><a href="https://docs.python.org/zh-cn/3/library/functools.html#module-functools"><code>functools</code></a> 模块应用于高阶函数，即参数或（和）返回值为其他函数的函数。 通常来说，此模块的功能适用于所有可调用对象。</p></blockquote><p>看起来还有很多的功能可以挖掘。</p><h2><span id="使用异常抛出机制解决问题">使用异常抛出机制解决问题</span></h2><h3><span id="什么是异常">什么是异常？</span></h3><ul><li>异常即是一个事件，该事件会在程序执行过程中发生，影响了程序的正常执行。</li><li>一般情况下，在 Python 无法正常处理程序时就会发生一个异常。</li><li>异常是 Python 对象，表示一个错误。</li><li>当 Python 脚本发生异常时我们需要捕获处理它，否则程序会终止执行。</li></ul><h3><span id="异常处理">异常处理</span></h3><p>捕捉异常可以使用 try/except 语句。</p><p>try/except 语句用来检测 try 语句块中的错误，从而让 except 语句捕获异常信息并处理。</p><p>如果你不想在异常发生时结束你的程序，只需在 try 里捕获它。</p><p>以下为简单的语法：</p><pre><code class="python">try:&lt;语句&gt;        #运行别的代码except &lt;名字&gt;：&lt;语句&gt;        #如果在 try 部份引发了'name'异常except &lt;名字&gt;，&lt;数据&gt;:&lt;语句&gt;        #如果引发了'name'异常，获得附加的数据else:&lt;语句&gt;        #如果没有异常发生</code></pre><p>try 的工作原理是，当开始一个 try 语句后，python 就在当前程序的上下文中作标记，这样当异常出现时就可以回到这里，try 子句先执行，接下来会发生什么依赖于执行时是否出现异常。</p><ul><li>如果当 try 后的语句执行时发生异常，python 就跳回到 try 并执行第一个匹配该异常的 except 子句，异常处理完毕，控制流就通过整个 try 语句（除非在处理异常时又引发新的异常）。</li><li>如果在 try 后的语句里发生了异常，却没有匹配的 except 子句，异常将被递交到上层的 try，或者到程序的最上层（这样将结束程序，并打印默认的出错信息）。</li><li>如果在 try 子句执行时没有发生异常，python 将执行 else 语句后的语句（如果有 else 的话），然后控制流通过整个 try 语句。</li></ul><h3><span id="巧用异常抛出机制">巧用异常抛出机制</span></h3><p>当遇到<strong>索引访问越界或者不被数据结构认可的处理方式</strong>时，可以采用 <code>try &amp; except</code> 语句减少合法性判断的代码。</p><h3><span id="350-两个数组的交集-ii">350. 两个数组的交集 II</span></h3><blockquote><p>给定两个数组，编写一个函数来计算它们的交集。</p></blockquote><pre><code class="python">class Solution:    def intersect(self, nums1: List[int], nums2: List[int]) -&gt; List[int]:        res = []        for num in nums1:            try:                nums2.remove(num)                res.append(num)            except:                continue                return res</code></pre><h2><span id="迭代器-iter">迭代器 iter</span></h2><p>迭代器的好处是 <code>for in</code> 遍历时，迭代器自身也会移动，适合处理只需要使用一次的数据。</p><h3><span id="392-判断子序列">392. 判断子序列</span></h3><blockquote><p>给定字符串 s 和 t ，判断 s 是否为 t 的子序列。</p><p>你可以认为 s 和 t 中仅包含英文小写字母。字符串 t 可能会很长（长度 ~= 500,000），而 s 是个短字符串（长度 &lt;=100）。</p><p>字符串的一个子序列是原始字符串删除一些（也可以不删除）字符而不改变剩余字符相对位置形成的新字符串。（例如，”ace”是”abcde”的一个子序列，而”aec”不是）。</p></blockquote><pre><code class="python">class Solution:    def isSubsequence(self, s: str, t: str) -&gt; bool:        t = iter(t)        return all(c in t for c in s) #t 在 c in t 的查找过程中不断右移</code></pre>]]></content>
    
    
    <summary type="html">&lt;p&gt;在 Leetcode 上划水写写 Python3 ，主要追求程序的简洁和实现的精巧。&lt;/p&gt;</summary>
    
    
    
    <category term="Coding" scheme="https://blog.pka.moe/categories/Coding/"/>
    
    
    <category term="python" scheme="https://blog.pka.moe/tags/python/"/>
    
  </entry>
  
  <entry>
    <title>使用 Github Actions 将 Hexo 托管至腾讯云</title>
    <link href="https://blog.pka.moe/hexo-deploy/"/>
    <id>https://blog.pka.moe/hexo-deploy/</id>
    <published>2020-07-08T15:45:00.000Z</published>
    <updated>2020-07-08T15:45:00.000Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><p>上车了腾讯云 9.9 元包年（500G 存储+2000G 流量）的 <a href="https://cloud.tencent.com/product/wh">静态网站托管</a> 活动，于是考虑使用 GitHub Actions 实现 Hexo 的自动化生成和部署，以及利用腾讯云和 Github Pages 实现国内外 CDN 加速。</p><span id="more"></span><p>首先创建新项目，将 Hexo 目录下的必要文件上传至 master 分支（Hexo 应该会自动生成 .gitignore 文件）。</p><p>然后利用 GitHub Actions 自动化生成静态文件并部署至 gh-pages 分支。</p><p>在 blog 仓库的 Actions 选项卡下点击新建 workflow ，编写如下配置。</p><pre><code class="yaml">name: Deploy Blogon: [push] # 当有新 push 时运行jobs:    build:        runs-on: ubuntu-latest # 在最新版的 Ubuntu 系统下运行                steps:        - name: Checkout # 将仓库内 master 分支的内容下载到工作目录            uses: actions/checkout@v1                    - name: Setup Node.js # 配置 Node 环境            uses: actions/setup-node@v1            with:                node-version: 12                - name: Setup Hexo            env:                ACTION_DEPLOY_KEY: $&#123;&#123; secrets.ACTION_DEPLOY_KEY &#125;&#125;                 #在 setting/secret 下添加名称为 ACTION_DEPLOY_KEY 的私钥            run: |                # set up private key for deploy                mkdir -p ~/.ssh/                echo &quot;$ACTION_DEPLOY_KEY&quot; | tr -d &#39;\r&#39; &gt; ~/.ssh/id_rsa # 配置秘钥                chmod 600 ~/.ssh/id_rsa                ssh-keyscan github.com &gt;&gt; ~/.ssh/known_hosts                # set git infomation                git config --global user.name &#39;prnake&#39;                git config --global user.email &#39;prnake@gmail.com&#39;                # install dependencies                npm i -g hexo-cli # 安装 hexo                npm i            - name: Deploy            run: |                # publish                hexo generate &amp;&amp; hexo deploy # 执行部署程序</code></pre><p>同时在 hexo 的配置文件 _config.yml 中添加 deploy 相关的参数，例如：</p><pre><code class="yaml">deploy:    type: git    repo: git@github.com:prnake/blog.git    branch: gh-pages</code></pre><p>每当有新的 push 发生时，都会触发 GitHub Actions ，生成静态文件并 push 至 gh-pages 分支。</p><p>同时在 Hexo 的 source 目录下添加 CNAME 文件，填入需要解析到的域名，这样每次 gh-pages 变化时 github 都会自动运行 Page Build 并设置解析。</p><p>接下来使用 <a href="https://github.com/TencentCloudBase/cloudbase-action">Tencent CloudBase Github Action</a> 将 gh-pages 分支部署到腾讯云开发平台，这里的思路是检测 Page Build 的动作。</p><p>先使用 cloudbase-cli 完成项目的第一次部署，并生成配置文件 <code>cloudbaserc.json</code>。</p><p>创建一个新的 workflow ，编写如下配置。</p><pre><code class="yaml">name: Tencent CloudBaseon: [push]jobs:  deploy:    runs-on: ubuntu-latest    name: Tencent Cloudbase    steps:      - name: Checkout        uses: actions/checkout@v2        with:          ref: master      - name: Deploy static to Tencent CloudBase        id: deployStatic        uses: TencentCloudBase/cloudbase-action@v2        with:          secretId: $&#123;&#123; secrets.SECRET_ID &#125;&#125;          secretKey: $&#123;&#123; secrets.SECRET_KEY &#125;&#125;          envId: $&#123;&#123; secrets.ENV_ID &#125;&#125;</code></pre><p>其中的 SECRET_ID 和 SECRET_KEY 在腾讯云 <a href="https://console.cloud.tencent.com/cam/capi">访问管理</a> 页面获取，ENV_ID 即环境 Id，在云开发的 <a href="https://console.cloud.tencent.com/tcb/env/overview">控制台</a> 获取，并添加到 setting&#x2F;secret 中。</p><p>这样，每当有新 push 时， github 都会自动生成 Hexo 的静态博客文件并部署到腾讯云和 Github Pages 。</p><p>由于腾讯云 CDN 缺乏国外服务器，所以国外线路走 Github 自己的 CDN 更好。使用 DNS 服务（例如 <a href="https://www.dnspod.cn/">DNSPod</a>）将域名国内 CNAME 至腾讯云，国外 CNAME 至 Github 平台即可。</p><p><img src="/images/hexo-deploy1.png" alt="CNAME"></p><p>最后进行一下延迟测试。</p><p><img src="/images/hexo-deploy2.png" alt="PING TEST"></p><p>总的返回 ip 有 18 个，其中 github 4 个，腾讯云 14 个，全球解析延迟基本控制在 30ms。相比之前使用的七牛云延迟应该有所上升，但网站加载时的首字节时间（TTFB）大幅下降，因此网站的实际访问体验明显变快了（虽然为了加载字体和渲染 Live2D 依然要耗费大量时间），这估计与回源效率和服务器质量有关。</p><p>总的部署可以参考 <a href="https://github.com/prnake/blog.pka.moe">本博客的 Github 项目</a>。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;上车了腾讯云 9.9 元包年（500G 存储+2000G 流量）的 &lt;a href=&quot;https://cloud.tencent.com/product/wh&quot;&gt;静态网站托管&lt;/a&gt; 活动，于是考虑使用 GitHub Actions 实现 Hexo 的自动化生成和部署，以及利用腾讯云和 Github Pages 实现国内外 CDN 加速。&lt;/p&gt;</summary>
    
    
    
    <category term="Tools" scheme="https://blog.pka.moe/categories/Tools/"/>
    
    
  </entry>
  
  <entry>
    <title>Pthreads - 共享内存式编程</title>
    <link href="https://blog.pka.moe/pthreads/"/>
    <id>https://blog.pka.moe/pthreads/</id>
    <published>2020-04-05T10:37:52.000Z</published>
    <updated>2020-04-05T10:37:52.000Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><p>本文是在 Pthreads 学习过程中产生的入门级教程。</p><span id="more"></span><!-- toc --><ul><li><a href="#%E5%BC%95%E5%85%A5">引入</a><ul><li><a href="#helloworld">hello,world</a></li><li><a href="#%E7%9F%A9%E9%98%B5%E4%B9%98%E6%B3%95">矩阵乘法</a></li></ul></li><li><a href="#%CF%80%E7%9A%84%E8%AE%A1%E7%AE%97">π的计算</a><ul><li><a href="#%E8%92%99%E7%89%B9%E5%8D%A1%E6%B4%9B%E6%96%B9%E6%B3%95">蒙特卡洛方法</a></li><li><a href="#%CF%80%E7%9A%84%E8%8E%B1%E5%B8%83%E5%B0%BC%E8%8C%A8%E5%85%AC%E5%BC%8F">π的莱布尼茨公式</a></li><li><a href="#%E5%8F%8D%E6%AD%A3%E5%88%87%E7%BA%A7%E6%95%B0%E6%AC%A7%E6%8B%89%E5%8F%98%E6%8D%A2">反正切级数欧拉变换</a></li></ul></li><li><a href="#%E4%BF%A1%E5%8F%B7%E9%87%8Fsemaphore">信号量（semaphore）</a><ul><li><a href="#%E4%BB%8B%E7%BB%8D">介绍</a></li><li><a href="#%E7%94%9F%E4%BA%A7%E8%80%85-%E6%B6%88%E8%B4%B9%E8%80%85%E5%90%8C%E6%AD%A5%E6%A8%A1%E5%9E%8B">生产者-消费者同步模型</a><ul><li><a href="#%E4%BB%80%E4%B9%88%E6%98%AF%E7%94%9F%E4%BA%A7%E8%80%85-%E6%B6%88%E8%B4%B9%E8%80%85%E6%A8%A1%E5%9E%8B">什么是生产者-消费者模型</a></li><li><a href="#%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E4%BD%BF%E7%94%A8%E7%94%9F%E4%BA%A7%E8%80%85%E6%B6%88%E8%B4%B9%E8%80%85%E6%A8%A1%E5%9E%8B">为什么要使用生产者消费者模型</a></li><li><a href="#%E7%94%9F%E4%BA%A7%E8%80%85-%E6%B6%88%E8%B4%B9%E8%80%85%E6%A8%A1%E5%9E%8B%E7%9A%84%E7%89%B9%E7%82%B9">生产者-消费者模型的特点</a></li><li><a href="#%E7%94%9F%E4%BA%A7%E8%80%85-%E6%B6%88%E8%B4%B9%E8%80%85%E6%A8%A1%E5%9E%8B%E7%9A%84%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF%E7%94%9F%E4%BA%A7%E8%80%85-%E6%B6%88%E8%B4%B9%E8%80%85%E6%A8%A1%E5%9E%8B%E7%9A%84%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF">生产者-消费者模型的应用场景生产者-消费者模型的应用场景</a></li><li><a href="#%E7%94%9F%E4%BA%A7%E8%80%85-%E6%B6%88%E8%B4%B9%E8%80%85%E6%A8%A1%E5%9E%8B%E7%9A%84%E4%BC%98%E7%82%B9">生产者-消费者模型的优点</a></li></ul></li></ul></li><li><a href="#%E4%BA%92%E6%96%A5%E9%87%8F%E5%92%8C%E4%BF%A1%E5%8F%B7%E9%87%8F%E7%9A%84%E6%AF%94%E8%BE%83">互斥量和信号量的比较</a><ul><li><a href="#%E4%BA%92%E6%96%A5%E9%87%8F%E5%92%8C%E4%BF%A1%E5%8F%B7%E9%87%8F%E7%9A%84%E5%8C%BA%E5%88%AB">互斥量和信号量的区别</a></li><li><a href="#%E7%94%A8%E4%BA%92%E6%96%A5%E9%87%8F%E5%AE%9E%E7%8E%B0%E7%94%9F%E4%BA%A7%E8%80%85-%E6%B6%88%E8%B4%B9%E8%80%85%E6%A8%A1%E5%9E%8B">用互斥量实现生产者-消费者模型</a></li></ul></li><li><a href="#%E8%B7%AF%E9%9A%9C%E5%92%8C%E6%9D%A1%E4%BB%B6%E5%8F%98%E9%87%8F">路障和条件变量</a></li><li><a href="#%E5%A4%9A%E7%BA%BF%E7%A8%8B%E9%93%BE%E8%A1%A8%E5%92%8C-pthreads-%E8%AF%BB%E5%86%99%E9%94%81">多线程链表和 Pthreads 读写锁</a><ul><li><a href="#%E5%A4%9A%E7%BA%BF%E7%A8%8B%E9%93%BE%E8%A1%A8%E7%9A%84%E4%B8%8D%E5%90%8C%E5%AE%9E%E7%8E%B0">多线程链表的不同实现</a></li><li><a href="#%E4%B8%8D%E5%90%8C%E5%AE%9E%E7%8E%B0%E6%96%B9%E6%A1%88%E7%9A%84%E5%BC%80%E9%94%80%E5%88%86%E6%9E%90">不同实现方案的开销分析</a></li></ul></li><li><a href="#%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8%E6%80%A7">线程安全性</a><ul><li><a href="#thread-safe-c-library-functions">Thread-safe C library functions</a></li><li><a href="#c-library-functions-that-are-not-thread-safe">C library functions that are not thread-safe</a></li></ul></li><li><a href="#%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99">参考资料</a></li></ul><!-- tocstop --><h2><span id="引入">引入</span></h2><h3><span id="helloworld">hello,world</span></h3><p>这是一个标准的”hello,world”程序：</p><pre><code class="cpp">#include &lt;stdio.h&gt;#include &lt;stdlib.h&gt;#include &lt;pthread.h&gt; const int MAX_THREADS = 64;/* Global variable:  accessible to all threads */int thread_count;  void Usage(char* prog_name);void *Hello(void* rank);  /* Thread function *//*--------------------------------------------------------------------*/int main(int argc, char* argv[]) {     long       thread;  /* Use long in case of a 64-bit system */     pthread_t* thread_handles;      /* Get number of threads from command line */     if (argc != 2) Usage(argv[0]);     thread_count = strtol(argv[1], NULL, 10);       if (thread_count &lt;= 0 || thread_count &gt; MAX_THREADS) Usage(argv[0]);     thread_handles = malloc (thread_count*sizeof(pthread_t));      for (thread = 0; thread &lt; thread_count; thread++)      pthread_create(&amp;thread_handles[thread], NULL,    Hello, (void*) thread);       printf("Hello from the main thread\n");     for (thread = 0; thread &lt; thread_count; thread++)     pthread_join(thread_handles[thread], NULL);      free(thread_handles);     return 0;}  /* main *//*-------------------------------------------------------------------*/void *Hello(void* rank) {     long my_rank = (long) rank;  /* Use long in case of 64-bit system */      printf("Hello from thread %ld of %d\n", my_rank, thread_count);     return NULL;}  /* Hello *//*-------------------------------------------------------------------*/void Usage(char* prog_name) {     fprintf(stderr, "usage: %s &lt;number of threads&gt;\n", prog_name);     fprintf(stderr, "0 &lt; number of threads &lt;= %d\n", MAX_THREADS);     exit(0);}  /* Usage */</code></pre><p>核心代码：</p><pre><code class="cpp">    #include &lt;pthread.h&gt; //引入，编译时加条件 -lpthread    void *Hello(void* rank);    long       thread;      pthread_t* thread_handles;     thread_handles = malloc (thread_count*sizeof(pthread_t));    pthread_create(&amp;thread_handles[thread], NULL,      Hello, (void*) thread);     pthread_join(thread_handles[thread], NULL); </code></pre><p>注意 pthread_create 调用函数必须是** void *类型<strong>，pthread_create 创建的线程可以直接运行（接收系统调度），pthread_join 用于接收线程的</strong>返回值**。</p><h3><span id="矩阵乘法">矩阵乘法</span></h3><p>总体来说 Pthread 比 OpenMpi 要清爽，不考虑线程之间的通讯的话代码量少很多，更好理解。</p><p> 就矩阵乘法来说，数据保存都在全局变量不需要传递，只需要传递线程编号 rank 即可，Pthread 核心调用和 “hello,world” 一模一样。</p><pre><code>for (thread = 0; thread &lt; thread_count; thread++)      pthread_create(&amp;thread_handles[thread], NULL,         Pth_mat_vect, (void*) thread);for (thread = 0; thread &lt; thread_count; thread++)      pthread_join(thread_handles[thread], NULL);</code></pre><h2><span id="π的计算">π的计算</span></h2><p>这算是第一个实用并且比较重要的例子。π的算法很多，这里的计算只是要测试代码能力，不纠结算法效率的差异。</p><p> 与矩阵乘法不太一样，这里用到的方法可能会对相同的全局变量同时做读写操作，同时的访问，称为**竞争条件 (race conditions)**，可能导致结果出错，因此需要使用一定的机制避免——我们引入忙等待和互斥量。 </p><p><img src="/images/pthreads1.png" alt="忙等待和互斥量"></p><h3><span id="蒙特卡洛方法">蒙特卡洛方法</span></h3><p>参考：<a href="https://www.cnblogs.com/sdxk/p/4093484.html">蒙特卡洛方法计算圆周率的三种实现</a> </p><p>蒙特卡洛方法实现计算圆周率的方法比较简单，其思想是假设我们向一个正方形的标靶上随机投掷飞镖，靶心在正中央，标靶的长和宽都是 2 英尺。同时假设有一个圆与标靶内切。圆的半径是 1 英尺，面积是π平方英尺。如果击中点在标靶上是均匀分布的（我们总会击中正方形），那么飞镖击中圆的数量近似满足等式：</p><p>飞镖落在圆内的次数/飞镖落在标靶内的总次数=π/4</p><p>我们可以用这个公式和随机数产生器来估计π的值。</p><pre><code>#include&lt;stdlib.h&gt;#include&lt;stdio.h&gt;#include&lt;math.h&gt;#include&lt;pthread.h&gt;int thread_count;long long int num_in_circle,n;pthread_mutex_t mutex;void* compute_pi(void* rank);int main(int argc,char* argv[]){    long    thread;    pthread_t* thread_handles;    thread_count=strtol(argv[1],NULL,10);    printf("please input the number of point\n");    scanf("%lld",&amp;n);    thread_handles=(pthread_t*)malloc(thread_count*sizeof(pthread_t));    pthread_mutex_init(&amp;mutex,NULL);    for(thread=0;thread&lt;thread_count;thread++)        pthread_create(&amp;thread_handles[thread],NULL,compute_pi,(void*)thread);    for(thread=0;thread&lt;thread_count;thread++)        pthread_join(thread_handles[thread],NULL);    pthread_mutex_destroy(&amp;mutex);    double pi=4*(double)num_in_circle/(double)n;    printf("The esitimate value of pi is %lf\n",pi);}void* compute_pi(void* rank){    long long int local_n;    local_n=n/thread_count;    double x,y,distance_squared;    for(long long int i=0;i&lt;local_n;i++){        x=(double)rand()/(double)RAND_MAX;        y=(double)rand()/(double)RAND_MAX;        distance_squared=x*x+y*y;        if(distance_squared&lt;=1){            pthread_mutex_lock(&amp;mutex);            num_in_circle++;            pthread_mutex_unlock(&amp;mutex);            }    }    return NULL;}</code></pre><p>计数的核心代码为：</p><pre><code>//pthread_mutex_t mutex; //记得全局//pthread_mutex_init(&amp;mutex,NULL);pthread_mutex_lock(&amp;mutex);num_in_circle++;pthread_mutex_unlock(&amp;mutex);  //pthread_mutex_destroy(&amp;mutex);</code></pre><p>我们希望一个线程执行<code>num_in_circle++;</code>时，其他线程不能操作，这段代码被称为<strong>临界区</strong>。</p><p> mutex 为 Pthread 定义的<strong>互斥量（互斥锁</strong>），其作用与更加直观的<strong>忙等待</strong>效果类似：</p><pre><code>while(flag!=my_rank);num_in_circle++;flag = (flag+1)% thread_count;</code></pre><p>但显然，<strong>互斥量</strong>的作用机制不需要依赖次序，因此使用互斥量效率更高。尤其当创建线程多于系统并行进程数时，<strong>忙等待</strong>可能和系统调度冲突造成短暂阻塞。 </p><p>注意，无法通过以下代码实现<strong>互斥量</strong>功能：</p><pre><code>//int flag = 1;while(flag!=1);flag = 0;num_in_circle++;flag = 1;</code></pre><p>因为对 flag 的赋值操作自身就可能造成<strong>竞争条件</strong>，导致非预期结果。</p><h3><span id="π的莱布尼茨公式">π的莱布尼茨公式</span></h3><p>由 <mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -0.912ex;" xmlns="http://www.w3.org/2000/svg" width="16.357ex" height="3.281ex" role="img" focusable="false" viewbox="0 -1047.1 7229.7 1450.1"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mfrac"><g data-mml-node="mi" transform="translate(220,394) scale(0.707)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z"/></g><g data-mml-node="mn" transform="translate(244.7,-345) scale(0.707)"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z"/></g><rect width="603.1" height="60" x="120" y="220"/></g></g><g data-mml-node="mo" transform="translate(1120.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z"/></g><g data-mml-node="munderover" transform="translate(2176.6,0)"><g data-mml-node="mo"><path data-c="2211" d="M61 748Q64 750 489 750H913L954 640Q965 609 976 579T993 533T999 516H979L959 517Q936 579 886 621T777 682Q724 700 655 705T436 710H319Q183 710 183 709Q186 706 348 484T511 259Q517 250 513 244L490 216Q466 188 420 134T330 27L149 -187Q149 -188 362 -188Q388 -188 436 -188T506 -189Q679 -189 778 -162T936 -43Q946 -27 959 6H999L913 -249L489 -250Q65 -250 62 -248Q56 -246 56 -239Q56 -234 118 -161Q186 -81 245 -11L428 206Q428 207 242 462L57 717L56 728Q56 744 61 748Z"/></g><g data-mml-node="TeXAtom" transform="translate(1089,477.1) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="221E" d="M55 217Q55 305 111 373T254 442Q342 442 419 381Q457 350 493 303L507 284L514 294Q618 442 747 442Q833 442 888 374T944 214Q944 128 889 59T743 -11Q657 -11 580 50Q542 81 506 128L492 147L485 137Q381 -11 252 -11Q166 -11 111 57T55 217ZM907 217Q907 285 869 341T761 397Q740 397 720 392T682 378T648 359T619 335T594 310T574 285T559 263T548 246L543 238L574 198Q605 158 622 138T664 94T714 61T765 51Q827 51 867 100T907 217ZM92 214Q92 145 131 89T239 33Q357 33 456 193L425 233Q364 312 334 337Q285 380 233 380Q171 380 132 331T92 214Z"/></g></g><g data-mml-node="TeXAtom" transform="translate(1089,-285.4) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D45B" d="M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z"/></g><g data-mml-node="mo" transform="translate(600,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z"/></g><g data-mml-node="mn" transform="translate(1378,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z"/></g></g></g><g data-mml-node="mstyle" transform="translate(4643.6,0)"><g data-mml-node="mspace"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(4977.2,0)"><g data-mml-node="mfrac"><g data-mml-node="mrow" transform="translate(220,516.8) scale(0.707)"><g data-mml-node="mo"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z"/></g><g data-mml-node="mo" transform="translate(389,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z"/></g><g data-mml-node="mn" transform="translate(1167,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z"/></g><g data-mml-node="msup" transform="translate(1667,0)"><g data-mml-node="mo"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z"/></g><g data-mml-node="TeXAtom" transform="translate(422,363) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D45B" d="M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z"/></g></g></g></g><g data-mml-node="mrow" transform="translate(285.5,-345) scale(0.707)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z"/></g><g data-mml-node="mi" transform="translate(500,0)"><path data-c="1D45B" d="M21 287Q22 293 24 303T36 341T56 388T89 425T135 442Q171 442 195 424T225 390T231 369Q231 367 232 367L243 378Q304 442 382 442Q436 442 469 415T503 336T465 179T427 52Q427 26 444 26Q450 26 453 27Q482 32 505 65T540 145Q542 153 560 153Q580 153 580 145Q580 144 576 130Q568 101 554 73T508 17T439 -10Q392 -10 371 17T350 73Q350 92 386 193T423 345Q423 404 379 404H374Q288 404 229 303L222 291L189 157Q156 26 151 16Q138 -11 108 -11Q95 -11 87 -5T76 7T74 17Q74 30 112 180T152 343Q153 348 153 366Q153 405 129 405Q91 405 66 305Q60 285 60 284Q58 278 41 278H27Q21 284 21 287Z"/></g><g data-mml-node="mo" transform="translate(1100,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z"/></g><g data-mml-node="mn" transform="translate(1878,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z"/></g></g><rect width="2012.5" height="60" x="120" y="220"/></g></g></g></g></g></svg></mjx-container> ，即 <mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -1.602ex;" xmlns="http://www.w3.org/2000/svg" width="36.457ex" height="4.638ex" role="img" focusable="false" viewbox="0 -1342 16113.8 2050"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="TeXAtom" data-mjx-texclass="ORD"><g data-mml-node="mstyle"><g data-mml-node="mstyle"><g data-mml-node="mspace"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(278,0)"><g data-mml-node="mfrac"><g data-mml-node="mi" transform="translate(220,676)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z"/></g><g data-mml-node="mn" transform="translate(255,-686)"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z"/></g><rect width="770" height="60" x="120" y="220"/></g></g><g data-mml-node="mo" transform="translate(1288,0)"><path data-c="21" d="M78 661Q78 682 96 699T138 716T180 700T199 661Q199 654 179 432T158 206Q156 198 139 198Q121 198 119 206Q118 209 98 431T78 661ZM79 61Q79 89 97 105T141 121Q164 119 181 104T198 61Q198 31 181 16T139 1Q114 1 97 16T79 61Z"/></g><g data-mml-node="mo" transform="translate(1843.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z"/></g><g data-mml-node="mn" transform="translate(2899.6,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z"/></g><g data-mml-node="mstyle" transform="translate(3399.6,0)"><g data-mml-node="mspace"/></g><g data-mml-node="mo" transform="translate(3788.8,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z"/></g><g data-mml-node="mstyle" transform="translate(4566.8,0)"><g data-mml-node="mspace"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(4956,0)"><g data-mml-node="mfrac"><g data-mml-node="mn" transform="translate(220,676)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z"/></g><g data-mml-node="mn" transform="translate(220,-686)"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z"/></g><rect width="700" height="60" x="120" y="220"/></g></g><g data-mml-node="mstyle" transform="translate(5896,0)"><g data-mml-node="mspace"/></g><g data-mml-node="mo" transform="translate(6285.2,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z"/></g><g data-mml-node="mstyle" transform="translate(7063.2,0)"><g data-mml-node="mspace"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(7452.4,0)"><g data-mml-node="mfrac"><g data-mml-node="mn" transform="translate(220,676)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z"/></g><g data-mml-node="mn" transform="translate(220,-686)"><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z"/></g><rect width="700" height="60" x="120" y="220"/></g></g><g data-mml-node="mstyle" transform="translate(8392.4,0)"><g data-mml-node="mspace"/></g><g data-mml-node="mo" transform="translate(8781.7,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z"/></g><g data-mml-node="mstyle" transform="translate(9559.7,0)"><g data-mml-node="mspace"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(9948.9,0)"><g data-mml-node="mfrac"><g data-mml-node="mn" transform="translate(220,676)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z"/></g><g data-mml-node="mn" transform="translate(220,-686)"><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z"/></g><rect width="700" height="60" x="120" y="220"/></g></g><g data-mml-node="mstyle" transform="translate(10888.9,0)"><g data-mml-node="mspace"/></g><g data-mml-node="mo" transform="translate(11278.1,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z"/></g><g data-mml-node="mstyle" transform="translate(12056.1,0)"><g data-mml-node="mspace"/></g><g data-mml-node="TeXAtom" data-mjx-texclass="ORD" transform="translate(12445.3,0)"><g data-mml-node="mfrac"><g data-mml-node="mn" transform="translate(220,676)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z"/></g><g data-mml-node="mn" transform="translate(220,-686)"><path data-c="39" d="M352 287Q304 211 232 211Q154 211 104 270T44 396Q42 412 42 436V444Q42 537 111 606Q171 666 243 666Q245 666 249 666T257 665H261Q273 665 286 663T323 651T370 619T413 560Q456 472 456 334Q456 194 396 97Q361 41 312 10T208 -22Q147 -22 108 7T68 93T121 149Q143 149 158 135T173 96Q173 78 164 65T148 49T135 44L131 43Q131 41 138 37T164 27T206 22H212Q272 22 313 86Q352 142 352 280V287ZM244 248Q292 248 321 297T351 430Q351 508 343 542Q341 552 337 562T323 588T293 615T246 625Q208 625 181 598Q160 576 154 546T147 441Q147 358 152 329T172 282Q197 248 244 248Z"/></g><rect width="700" height="60" x="120" y="220"/></g></g><g data-mml-node="mstyle" transform="translate(13385.3,0)"><g data-mml-node="mspace"/></g><g data-mml-node="mo" transform="translate(13774.6,0)"><path data-c="2212" d="M84 237T84 250T98 270H679Q694 262 694 250T679 230H98Q84 237 84 250Z"/></g><g data-mml-node="mstyle" transform="translate(14552.6,0)"><g data-mml-node="mspace"/></g><g data-mml-node="mo" transform="translate(14941.8,0)"><path data-c="22EF" d="M78 250Q78 274 95 292T138 310Q162 310 180 294T199 251Q199 226 182 208T139 190T96 207T78 250ZM525 250Q525 274 542 292T585 310Q609 310 627 294T646 251Q646 226 629 208T586 190T543 207T525 250ZM972 250Q972 274 989 292T1032 310Q1056 310 1074 294T1093 251Q1093 226 1076 208T1033 190T990 207T972 250Z"/></g></g></g></g></g></svg></mjx-container> 计算 pi 的近似值，这个值的精确度没有随机因素，只与计算深度有关。我们将数据分段计算，最后再用<strong>互斥量</strong>机制相加。</p><pre><code>#include &lt;stdio.h&gt;#include &lt;stdlib.h&gt;#include &lt;math.h&gt;#include &lt;pthread.h&gt;const int MAX_THREADS = 1024;long thread_count;long long n;double sum;void* Thread_sum(void* rank);/* Only executed by main thread */void Get_args(int argc, char* argv[]);void Usage(char* prog_name);double Serial_pi(long long n);int main(int argc, char* argv[]) {   long       thread;  /* Use long in case of a 64-bit system */   pthread_t* thread_handles;   /* Get number of threads from command line */   Get_args(argc, argv);   thread_handles = (pthread_t*) malloc (thread_count*sizeof(pthread_t));    sum = 0.0;   for (thread = 0; thread &lt; thread_count; thread++)        pthread_create(&amp;thread_handles[thread], NULL,          Thread_sum, (void*)thread);     for (thread = 0; thread &lt; thread_count; thread++)       pthread_join(thread_handles[thread], NULL);    sum = 4.0*sum;   printf("With n = %lld terms,\n", n);   printf("   Our estimate of pi = %.15f\n", sum);   sum = Serial_pi(n);   printf("   Single thread est  = %.15f\n", sum);   printf("                   pi = %.15f\n", 4.0*atan(1.0));   free(thread_handles);   return 0;}  /* main */void* Thread_sum(void* rank) {   long my_rank = (long) rank;   double factor;   long long i;   long long my_n = n/thread_count;   long long my_first_i = my_n*my_rank;   long long my_last_i = my_first_i + my_n;   double my_sum = 0.0;   if (my_first_i % 2 == 0)      factor = 1.0;   else      factor = -1.0;   for (i = my_first_i; i &lt; my_last_i; i++, factor = -factor) {      my_sum += factor/(2*i+1);   }   pthread_mutex_lock(&amp;mutex);   sum += my_sum;   pthread_mutex_unlock(&amp;mutex);   return NULL;}  /* Thread_sum */double Serial_pi(long long n) {   double sum = 0.0;   long long i;   double factor = 1.0;   for (i = 0; i &lt; n; i++, factor = -factor) {      sum += factor/(2*i+1);   }   return 4.0*sum;}  /* Serial_pi */void Get_args(int argc, char* argv[]) {   if (argc != 3) Usage(argv[0]);   thread_count = strtol(argv[1], NULL, 10);     if (thread_count &lt;= 0 || thread_count &gt; MAX_THREADS) Usage(argv[0]);   n = strtoll(argv[2], NULL, 10);   if (n &lt;= 0) Usage(argv[0]);}  /* Get_args */void Usage(char* prog_name) {   fprintf(stderr, "usage: %s &lt;number of threads&gt; &lt;n&gt;\n", prog_name);   fprintf(stderr, "   n is the number of terms and should be &gt;= 1\n");   fprintf(stderr, "   n should be evenly divisible by the number of threads\n");   exit(0);}  /* Usage */</code></pre><p>反正都不怎么精确就是了。</p><h3><span id="反正切级数欧拉变换">反正切级数欧拉变换</span></h3><p>虽然求 pi 的例子能很好地引入<strong>互斥量</strong>机制，参考 <a href="https://www.zhihu.com/question/312520105/answer/601728029">目前求 π 的算法中哪种收敛最快？ - byoshovel 的回答 - 知乎</a>，我们使用线性效率的<strong>反正切级数欧拉变换公式</strong>：</p><p> <mjx-container class="MathJax" jax="SVG"><svg style="vertical-align: -1.238ex;" xmlns="http://www.w3.org/2000/svg" width="22.453ex" height="3.687ex" role="img" focusable="false" viewbox="0 -1082.7 9924.2 1629.8"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(1,-1)"><g data-mml-node="math"><g data-mml-node="mfrac"><g data-mml-node="mi" transform="translate(220,394) scale(0.707)"><path data-c="1D70B" d="M132 -11Q98 -11 98 22V33L111 61Q186 219 220 334L228 358H196Q158 358 142 355T103 336Q92 329 81 318T62 297T53 285Q51 284 38 284Q19 284 19 294Q19 300 38 329T93 391T164 429Q171 431 389 431Q549 431 553 430Q573 423 573 402Q573 371 541 360Q535 358 472 358H408L405 341Q393 269 393 222Q393 170 402 129T421 65T431 37Q431 20 417 5T381 -10Q370 -10 363 -7T347 17T331 77Q330 86 330 121Q330 170 339 226T357 318T367 358H269L268 354Q268 351 249 275T206 114T175 17Q164 -11 132 -11Z"/></g><g data-mml-node="mn" transform="translate(244.7,-345) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z"/></g><rect width="603.1" height="60" x="120" y="220"/></g><g data-mml-node="mo" transform="translate(1120.8,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z"/></g><g data-mml-node="munderover" transform="translate(2176.6,0)"><g data-mml-node="mo"><path data-c="2211" d="M61 748Q64 750 489 750H913L954 640Q965 609 976 579T993 533T999 516H979L959 517Q936 579 886 621T777 682Q724 700 655 705T436 710H319Q183 710 183 709Q186 706 348 484T511 259Q517 250 513 244L490 216Q466 188 420 134T330 27L149 -187Q149 -188 362 -188Q388 -188 436 -188T506 -189Q679 -189 778 -162T936 -43Q946 -27 959 6H999L913 -249L489 -250Q65 -250 62 -248Q56 -246 56 -239Q56 -234 118 -161Q186 -81 245 -11L428 206Q428 207 242 462L57 717L56 728Q56 744 61 748Z"/></g><g data-mml-node="TeXAtom" transform="translate(1089,477.1) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="221E" d="M55 217Q55 305 111 373T254 442Q342 442 419 381Q457 350 493 303L507 284L514 294Q618 442 747 442Q833 442 888 374T944 214Q944 128 889 59T743 -11Q657 -11 580 50Q542 81 506 128L492 147L485 137Q381 -11 252 -11Q166 -11 111 57T55 217ZM907 217Q907 285 869 341T761 397Q740 397 720 392T682 378T648 359T619 335T594 310T574 285T559 263T548 246L543 238L574 198Q605 158 622 138T664 94T714 61T765 51Q827 51 867 100T907 217ZM92 214Q92 145 131 89T239 33Q357 33 456 193L425 233Q364 312 334 337Q285 380 233 380Q171 380 132 331T92 214Z"/></g></g><g data-mml-node="TeXAtom" transform="translate(1089,-285.4) scale(0.707)" data-mjx-texclass="ORD"><g data-mml-node="mi"><path data-c="1D458" d="M121 647Q121 657 125 670T137 683Q138 683 209 688T282 694Q294 694 294 686Q294 679 244 477Q194 279 194 272Q213 282 223 291Q247 309 292 354T362 415Q402 442 438 442Q468 442 485 423T503 369Q503 344 496 327T477 302T456 291T438 288Q418 288 406 299T394 328Q394 353 410 369T442 390L458 393Q446 405 434 405H430Q398 402 367 380T294 316T228 255Q230 254 243 252T267 246T293 238T320 224T342 206T359 180T365 147Q365 130 360 106T354 66Q354 26 381 26Q429 26 459 145Q461 153 479 153H483Q499 153 499 144Q499 139 496 130Q455 -11 378 -11Q333 -11 305 15T277 90Q277 108 280 121T283 145Q283 167 269 183T234 206T200 217T182 220H180Q168 178 159 139T145 81T136 44T129 20T122 7T111 -2Q98 -11 83 -11Q66 -11 57 -1T48 16Q48 26 85 176T158 471L195 616Q196 629 188 632T149 637H144Q134 637 131 637T124 640T121 647Z"/></g><g data-mml-node="mo" transform="translate(521,0)"><path data-c="3D" d="M56 347Q56 360 70 367H707Q722 359 722 347Q722 336 708 328L390 327H72Q56 332 56 347ZM56 153Q56 168 72 173H708Q722 163 722 153Q722 140 707 133H70Q56 140 56 153Z"/></g><g data-mml-node="mn" transform="translate(1299,0)"><path data-c="30" d="M96 585Q152 666 249 666Q297 666 345 640T423 548Q460 465 460 320Q460 165 417 83Q397 41 362 16T301 -15T250 -22Q224 -22 198 -16T137 16T82 83Q39 165 39 320Q39 494 96 585ZM321 597Q291 629 250 629Q208 629 178 597Q153 571 145 525T137 333Q137 175 145 125T181 46Q209 16 250 16Q290 16 318 46Q347 76 354 130T362 333Q362 478 354 524T321 597Z"/></g></g></g><g data-mml-node="mfrac" transform="translate(4754.4,0)"><g data-mml-node="mrow" transform="translate(671.8,516.8) scale(0.707)"><g data-mml-node="mo"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z"/></g><g data-mml-node="mn" transform="translate(389,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z"/></g><g data-mml-node="mi" transform="translate(889,0)"><path data-c="1D458" d="M121 647Q121 657 125 670T137 683Q138 683 209 688T282 694Q294 694 294 686Q294 679 244 477Q194 279 194 272Q213 282 223 291Q247 309 292 354T362 415Q402 442 438 442Q468 442 485 423T503 369Q503 344 496 327T477 302T456 291T438 288Q418 288 406 299T394 328Q394 353 410 369T442 390L458 393Q446 405 434 405H430Q398 402 367 380T294 316T228 255Q230 254 243 252T267 246T293 238T320 224T342 206T359 180T365 147Q365 130 360 106T354 66Q354 26 381 26Q429 26 459 145Q461 153 479 153H483Q499 153 499 144Q499 139 496 130Q455 -11 378 -11Q333 -11 305 15T277 90Q277 108 280 121T283 145Q283 167 269 183T234 206T200 217T182 220H180Q168 178 159 139T145 81T136 44T129 20T122 7T111 -2Q98 -11 83 -11Q66 -11 57 -1T48 16Q48 26 85 176T158 471L195 616Q196 629 188 632T149 637H144Q134 637 131 637T124 640T121 647Z"/></g><g data-mml-node="mo" transform="translate(1410,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z"/></g><g data-mml-node="mo" transform="translate(1799,0)"><path data-c="21" d="M78 661Q78 682 96 699T138 716T180 700T199 661Q199 654 179 432T158 206Q156 198 139 198Q121 198 119 206Q118 209 98 431T78 661ZM79 61Q79 89 97 105T141 121Q164 119 181 104T198 61Q198 31 181 16T139 1Q114 1 97 16T79 61Z"/></g><g data-mml-node="mo" transform="translate(2077,0)"><path data-c="21" d="M78 661Q78 682 96 699T138 716T180 700T199 661Q199 654 179 432T158 206Q156 198 139 198Q121 198 119 206Q118 209 98 431T78 661ZM79 61Q79 89 97 105T141 121Q164 119 181 104T198 61Q198 31 181 16T139 1Q114 1 97 16T79 61Z"/></g></g><g data-mml-node="mrow" transform="translate(220,-370.3) scale(0.707)"><g data-mml-node="mo"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z"/></g><g data-mml-node="mn" transform="translate(389,0)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z"/></g><g data-mml-node="mi" transform="translate(889,0)"><path data-c="1D458" d="M121 647Q121 657 125 670T137 683Q138 683 209 688T282 694Q294 694 294 686Q294 679 244 477Q194 279 194 272Q213 282 223 291Q247 309 292 354T362 415Q402 442 438 442Q468 442 485 423T503 369Q503 344 496 327T477 302T456 291T438 288Q418 288 406 299T394 328Q394 353 410 369T442 390L458 393Q446 405 434 405H430Q398 402 367 380T294 316T228 255Q230 254 243 252T267 246T293 238T320 224T342 206T359 180T365 147Q365 130 360 106T354 66Q354 26 381 26Q429 26 459 145Q461 153 479 153H483Q499 153 499 144Q499 139 496 130Q455 -11 378 -11Q333 -11 305 15T277 90Q277 108 280 121T283 145Q283 167 269 183T234 206T200 217T182 220H180Q168 178 159 139T145 81T136 44T129 20T122 7T111 -2Q98 -11 83 -11Q66 -11 57 -1T48 16Q48 26 85 176T158 471L195 616Q196 629 188 632T149 637H144Q134 637 131 637T124 640T121 647Z"/></g><g data-mml-node="mo" transform="translate(1410,0)"><path data-c="2B" d="M56 237T56 250T70 270H369V420L370 570Q380 583 389 583Q402 583 409 568V270H707Q722 262 722 250T707 230H409V-68Q401 -82 391 -82H389H387Q375 -82 369 -68V230H70Q56 237 56 250Z"/></g><g data-mml-node="mn" transform="translate(2188,0)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z"/></g><g data-mml-node="mo" transform="translate(2688,0)"><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z"/></g><g data-mml-node="mo" transform="translate(3077,0)"><path data-c="21" d="M78 661Q78 682 96 699T138 716T180 700T199 661Q199 654 179 432T158 206Q156 198 139 198Q121 198 119 206Q118 209 98 431T78 661ZM79 61Q79 89 97 105T141 121Q164 119 181 104T198 61Q198 31 181 16T139 1Q114 1 97 16T79 61Z"/></g><g data-mml-node="mo" transform="translate(3355,0)"><path data-c="21" d="M78 661Q78 682 96 699T138 716T180 700T199 661Q199 654 179 432T158 206Q156 198 139 198Q121 198 119 206Q118 209 98 431T78 661ZM79 61Q79 89 97 105T141 121Q164 119 181 104T198 61Q198 31 181 16T139 1Q114 1 97 16T79 61Z"/></g></g><rect width="2768.9" height="60" x="120" y="220"/></g><g data-mml-node="msup" transform="translate(7763.3,0)"><g data-mml-node="mrow"><g data-mml-node="mo" transform="translate(0 -0.5)"><path data-c="28" d="M152 251Q152 646 388 850H416Q422 844 422 841Q422 837 403 816T357 753T302 649T255 482T236 250Q236 124 255 19T301 -147T356 -251T403 -315T422 -340Q422 -343 416 -349H388Q359 -325 332 -296T271 -213T212 -97T170 56T152 251Z"/></g><g data-mml-node="mfrac" transform="translate(458,0)"><g data-mml-node="mn" transform="translate(220,394) scale(0.707)"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z"/></g><g data-mml-node="mn" transform="translate(220,-345) scale(0.707)"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z"/></g><rect width="553.6" height="60" x="120" y="220"/></g><g data-mml-node="mo" transform="translate(1251.6,0) translate(0 -0.5)"><path data-c="29" d="M305 251Q305 -145 69 -349H56Q43 -349 39 -347T35 -338Q37 -333 60 -307T108 -239T160 -136T204 27T221 250T204 473T160 636T108 740T60 807T35 839Q35 850 50 850H56H69Q197 743 256 566Q305 425 305 251Z"/></g></g><g data-mml-node="mi" transform="translate(1742.6,592) scale(0.707)"><path data-c="1D458" d="M121 647Q121 657 125 670T137 683Q138 683 209 688T282 694Q294 694 294 686Q294 679 244 477Q194 279 194 272Q213 282 223 291Q247 309 292 354T362 415Q402 442 438 442Q468 442 485 423T503 369Q503 344 496 327T477 302T456 291T438 288Q418 288 406 299T394 328Q394 353 410 369T442 390L458 393Q446 405 434 405H430Q398 402 367 380T294 316T228 255Q230 254 243 252T267 246T293 238T320 224T342 206T359 180T365 147Q365 130 360 106T354 66Q354 26 381 26Q429 26 459 145Q461 153 479 153H483Q499 153 499 144Q499 139 496 130Q455 -11 378 -11Q333 -11 305 15T277 90Q277 108 280 121T283 145Q283 167 269 183T234 206T200 217T182 220H180Q168 178 159 139T145 81T136 44T129 20T122 7T111 -2Q98 -11 83 -11Q66 -11 57 -1T48 16Q48 26 85 176T158 471L195 616Q196 629 188 632T149 637H144Q134 637 131 637T124 640T121 647Z"/></g></g></g></g></svg></mjx-container> </p><p>代码自 <a href="https://blog.csdn.net/qin_zhangyongheng/article/details/8033942">用 c++高精度的计算π的值，可精确到 n 位</a> :</p><pre><code>#include&lt;stdio.h&gt;#include&lt;math.h&gt;int a[100000];int main(){    float s;    int b, x, n, c, i, j, d, l;    scanf("%d",&amp;x);    for (s = 0, n = 1; n &lt;= 5000; n++)    {        s = s + log10((2 * n + 1) / n);        if (s &gt; x + 1)        break;    }    for (i = 0; i &lt;= x + 5; i++)        a[i] = 0;    for (c = 1, j = n; j &gt;= 1; j--) //按公式分布计算。    {        d = 2 * j + 1;        for (i = 0; i &lt;= x + 4; i++) //各位实施除 2j+1.            {        a[i] = c / d;        c = (c % d) * 10 + a[i + 1];        }        a[x + 5] = c / d;        for (b = 0, i = x + 5; i &gt;= 0; i--) //各位实施乘 j            {        a[i] = a[i] * j + b;        b = a[i] / 10;        a[i] = a[i] % 10;        }        a[0] = a[0] + 1;        c = a[0]; //整数加 1.    }    for (b = 0, i = x + 5; i &gt;= 0; i--) //按公式各位乘 2    {        a[i] = a[i] * 2 + b;        b = a[i] / 10;        a[i] = a[i] % 10;    }    printf("\nPI=%d.",a[0]); //诸位输出计算结果。    for (l = 10, i = 1; i &lt;= x; i++)    {        printf("%d",a[i]);        l++;          if (l % 10 == 0)        printf(" ");        if (l % 50 == 0)        printf("\n");    }    printf("\n");    return 0;}</code></pre><p>这种方法和其他方法，或者无法准确切分数据块让 pthread 处理，或者计算结果依赖前项虽然肯定可以并行化处理，但通常要修改公式，改写成 pthread 并行较为困难。看之后学习有没有办法处理。</p><h2><span id="信号量semaphore">信号量（semaphore）</span></h2><h3><span id="介绍">介绍</span></h3><p>互斥量是有明显缺点的，我们只能控制临界区每个时刻至多只有一个线程在访问，但不能跨线程控制临界区在我们想执行的时候开始。</p><p> 当然，使用 while 结构的<strong>忙等待机制</strong>能够解决这个问题，但忙等待本身效率不高。</p><p> 荷兰计算机科学家_艾兹赫尔·戴克斯特拉_提出了<strong>信号量（semaphore）</strong>的概念。在系统中，给予每一个进程一个信号量，代表每个进程当前的状态，未得到控制权的进程会在特定地方被强迫停下来，等待可以继续进行的信号到来。（来自 <a href="https://zh.wikipedia.org/wiki/%E4%BF%A1%E5%8F%B7%E9%87%8F">信号量</a> - Wikipedia）总的来说，信号量的作用是给予进程控制权。</p><p><img src="/images/pthreads2.png" alt="信号量"></p><p>分析如下代码：</p><pre><code>#include &lt;stdio.h&gt;#include &lt;stdlib.h&gt;#include &lt;pthread.h&gt;#include &lt;semaphore.h&gt;#define BARRIER_COUNT 100int thread_count;int counter;sem_t barrier_sems[BARRIER_COUNT];sem_t count_sem;void Usage(char* prog_name);void *Thread_work(void* rank);int main(int argc, char* argv[]) {   long       thread, i;   pthread_t* thread_handles;    if (argc != 2)      Usage(argv[0]);   thread_count = strtol(argv[1], NULL, 10);   thread_handles = malloc (thread_count*sizeof(pthread_t));   for (i = 0; i &lt; BARRIER_COUNT; i++)      sem_init(&amp;barrier_sems[i], 0, 0);   sem_init(&amp;count_sem, 0, 1);   for (thread = 0; thread &lt; thread_count; thread++)      pthread_create(&amp;thread_handles[thread], (pthread_attr_t*) NULL,          Thread_work, (void*) thread);   for (thread = 0; thread &lt; thread_count; thread++) {      pthread_join(thread_handles[thread], NULL);   }   sem_destroy(&amp;count_sem);   for (i = 0; i &lt; BARRIER_COUNT; i++)      sem_destroy(&amp;barrier_sems[i]);   free(thread_handles);   return 0;}  /* main */void Usage(char* prog_name) {   fprintf(stderr, "usage: %s &lt;number of threads&gt;\n", prog_name);   exit(0);}  /* Usage */void *Thread_work(void* rank) {   long my_rank = (long) rank;   int i, j;   for (i = 0; i &lt; BARRIER_COUNT; i++) {      sem_wait(&amp;count_sem);      if (counter == thread_count - 1) {         counter = 0;         sem_post(&amp;count_sem);         for (j = 0; j &lt; thread_count-1; j++)            sem_post(&amp;barrier_sems[i]);      } else {         counter++;         sem_post(&amp;count_sem);         sem_wait(&amp;barrier_sems[i]);      }      if (my_rank == 0) {         printf("All threads completed barrier %d\n", i);         fflush(stdout);      }   }   return NULL;}  /* Thread_work */</code></pre><p>其中与<strong>信号量</strong>有关的核心代码为：</p><pre><code>//#include &lt;semaphore.h&gt;//sem_t barrier_sems[BARRIER_COUNT];//sem_t count_sem;//sem_init(&amp;barrier_sems[i], 0, 0); 第三个参数代表初始值//sem_init(&amp;count_sem, 0, 1);//sem_destroy();for (i = 0; i &lt; BARRIER_COUNT; i++) {      sem_wait(&amp;count_sem);      if (counter == thread_count - 1) {         counter = 0;         sem_post(&amp;count_sem);         for (j = 0; j &lt; thread_count-1; j++)            sem_post(&amp;barrier_sems[i]);      } else {         counter++;         sem_post(&amp;count_sem);         sem_wait(&amp;barrier_sems[i]);      }      if (my_rank == 0) {         printf("All threads completed barrier %d\n", i);         fflush(stdout);      }</code></pre><p>其中<code>sem_t</code>可视作<code>unsigned int</code>，<code>sem_post()</code>为信号量增加 1，<code>sem_wait(&amp;sem)</code>持续检测信号量，直到信号量大于 0 才继续运行，并将信号量减 1。 </p><p>因此这段代码将<code>0～thread_count - 2</code>的进程锁住，在最后一个线程统一解锁。（毫无意义）注意<code>sem_wait(&amp;count_sem);</code>和<code>sem_post(&amp;count_sem);</code>一一对应，用于控制更改 counter 值的这一个临界区。</p><h3><span id="生产者-消费者同步模型">生产者-消费者同步模型</span></h3><p>以下内容来自 <a href="https://zhuanlan.zhihu.com/p/73442055">经典并发同步模式：生产者-消费者设计模式 | 知乎</a></p><h4><span id="什么是生产者-消费者模型">什么是生产者-消费者模型</span></h4><p>比如有两个进程 A 和 B，它们共享一个<strong>固定大小的缓冲区</strong>，A 进程产生数据放入缓冲区，B 进程从缓冲区中取出数据进行计算，那么这里其实就是一个生产者和消费者的模型，A 相当于生产者，B 相当于消费者。</p><p><img src="/images/pthreads3.png" alt="生产者-消费者模型"></p><h4><span id="为什么要使用生产者消费者模型">为什么要使用生产者消费者模型</span></h4><p>在多线程开发中，如果生产者生产数据的速度很快，而消费者消费数据的速度很慢，那么生产者就必须等待消费者消费完了数据才能够继续生产数据，因为生产那么多也没有地方放啊；同理如果消费者的速度大于生产者那么消费者就会经常处理等待状态，所以为了达到生产者和消费者生产数据和消费数据之间的<strong>平衡</strong>，那么就需要一个缓冲区用来存储生产者生产的数据，所以就引入了生产者-消费者模型。</p><h4><span id="生产者-消费者模型的特点">生产者-消费者模型的特点</span></h4><ul><li>保证生产者不会在缓冲区满的时候继续向缓冲区放入数据，而消费者也不会在缓冲区空的时候，消耗数据</li><li>当缓冲区满的时候，生产者会进入休眠状态，当下次消费者开始消耗缓冲区的数据时，生产者才会被唤醒，开始往缓冲区中添加数据；当缓冲区空的时候，消费者也会进入休眠状态，直到生产者往缓冲区中添加数据时才会被唤醒</li></ul><p><img src="/images/pthreads4.png" alt="生产者-消费者模型"></p><h4><span id="生产者-消费者模型的应用场景生产者-消费者模型的应用场景">生产者-消费者模型的应用场景生产者-消费者模型的应用场景</span></h4><p>生产者-消费者模型一般用于将生产数据的一方和消费数据的一方分割开来，将生产数据与消费数据的过程解耦开来</p><ul><li><p>Excutor 任务执行框架：</p></li><li><ul><li>通过将任务的提交和任务的执行解耦开来，提交任务的操作相当于生产者，执行任务的操作相当于消费者</li><li>例如使用 Excutor 构建 web 服务器，用于处理线程的请求：生产者将任务提交给线程池，线程池创建线程处理任务，如果需要运行的任务数大于线程池的基本线程数，那么就把任务扔到阻塞队列（通过线程池+阻塞队列的方式比只使用一个阻塞队列的效率高很多，因为消费者能够处理就直接处理掉了，不用每个消费者都要先从阻塞队列中取出任务再执行）</li></ul></li><li><p>消息中间件 activeMQ:</p></li><li><ul><li>双十一的时候，会产生大量的订单，那么不可能同时处理那么多的订单，需要将订单放入一个队列里面，然后由专门的线程处理订单。这里用户下单就是生产者，处理订单的线程就是消费者；再比如 12306 的抢票功能，先由一个容器存储用户提交的订单，然后再由专门处理订单的线程慢慢处理，这样可以在短时间内支持高并发服务</li></ul></li><li><p>任务的处理时间比较长的情况下：</p></li><li><ul><li>比如上传附近并处理，那么这个时候可以将用户上传和处理附件分成两个过程，用一个队列暂时存储用户上传的附近，然后立刻返回用户上传成功，然后有专门的线程处理队列中的附近</li></ul></li></ul><h4><span id="生产者-消费者模型的优点">生产者-消费者模型的优点</span></h4><ul><li>解耦：将生产者类和消费者类进行解耦，消除代码之间的依赖性，简化工作负载的管理</li><li>复用：通过将生产者类和消费者类独立开来，那么可以对生产者类和消费者类进行独立的复用与扩展</li><li>调整并发数：由于生产者和消费者的处理速度是不一样的，可以调整并发数，给予慢的一方多的并发数，来提高任务的处理速度</li><li>异步：对于生产者和消费者来说能够各司其职，生产者只需要关心缓冲区是否还有数据，不需要等待消费者处理完；同样的对于消费者来说，也只需要关注缓冲区的内容，不需要关注生产者，通过异步的方式支持高并发，将一个耗时的流程拆成生产和消费两个阶段，这样生产者因为执行 put() 的时间比较短，而支持高并发</li><li>支持分布式：生产者和消费者通过队列进行通讯，所以不需要运行在同一台机器上，在分布式环境中可以通过 redis 的 list 作为队列，而消费者只需要轮询队列中是否有数据。同时还能支持集群的伸缩性，当某台机器宕掉的时候，不会导致整个集群宕掉</li></ul><p>（引用结束）</p><p> <strong>在我们的例子中，信号量的值可看作生产者数量，<code>sem_wait(&amp;count_sem);</code>代表等待的消费者和消费过程。</strong></p><h2><span id="互斥量和信号量的比较">互斥量和信号量的比较</span></h2><h3><span id="互斥量和信号量的区别">互斥量和信号量的区别</span></h3><p>参考 <a href="zhihu.com/question/47704079">semaphore 和 mutex 的区别？ | 知乎</a> 一句话概括（来自 <a href="https://www.zhihu.com/question/47704079/answer/135859188">二律背反</a>）：</p><blockquote><p>互斥量 (mutex)：<strong>保护共享资源。</strong></p><p>信号量 (semaphore)：<strong>调度线程</strong>。</p></blockquote><h3><span id="用互斥量实现生产者-消费者模型">用互斥量实现生产者-消费者模型</span></h3><p>尽管生产者-消费者同步采用信号量很容易实现，但它也能用互斥量来实现。基本的想 法是：让生产者线程和消费者线程共享一个互斥量。用一个被主线程初始化为 false 的 标志变量来表示是否有产品可以被“消费”。在下面的代码中，通过修改 if 条件，我们可以构建需要的生产者-消费者模型。</p><pre><code>void *Thread_work(void* rank) {    long my_rank = (long) rank;    int send = 0, recv = 0;    while(1) {        pthread_mutex_lock(&amp;mutex);        if(msg) {            if (my_rank == receiver &amp;&amp; !recv) {                //消费                msg = 0;                recv = 1;            }        } else {            if (!send) {                        //生产                msg = 1;                send = 1;                receiver = receiver_rank; //receiver_rank 代表接收核编号            }        }        pthread_mutex_unlock(&amp;mutex);        if (send &amp;&amp; recv) break; //跳出循环条件，这里是一次生产，一次消费    }    return NULL;}</code></pre><p>如果消费者线程首先进入循环，它会看到没有可用的信息 (<strong>message_available</strong> 值为 <code>false</code>) 并在调用 <code>pthread_mutex_unlock</code> 后返回。消费者线程重复上述过程，直到生产者线程生产出信息。 </p><p>我们给出每个线程都生产一次，消费一次的核心代码：</p><pre><code>void *Thread_work(void* rank) {    long my_rank = (long) rank;    int send = 0, recv = 0;    while(1) {        pthread_mutex_lock(&amp;mutex);        if(msg) {      //消费            if (my_rank == receiver &amp;&amp; !recv) {                printf("Th %ld &gt; Received: %s\n",                                       my_rank, message);                msg = 0;                recv = 1;            }        } else {            if (!send) {        //生产                sprintf(message, "hello from rank %ld",                                       my_rank);                msg = 1;                send = 1;                receiver = (my_rank+1) % thread_count;            }        }        pthread_mutex_unlock(&amp;mutex);        if (send &amp;&amp; recv) break; //跳出循环条件，这里是一次生产，一次消费    }    return NULL;}</code></pre><h2><span id="路障和条件变量">路障和条件变量</span></h2><p>Pthreads 中实现路障的最好方式之一是<strong>条件变量</strong>。基本实现如图所示：</p><p><img src="/images/pthreads5.png" alt="条件变量"></p><p>当然条件变量也要初始化和销毁，与互斥量的调用方法类似。官方文档如下：</p><blockquote><p><code>#include &lt;semaphore.h&gt;</code><br>        初始化条件变量：<br><code>int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);</code><br>        该函数第一个参数为条件变量指针，第二个参数为条件变量属性指针（一般设为 NULL）。该函数按照条件变量属性对条件变量进程初始化。<br>无条件等待：<br><code> int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);</code><br>        该函数第一个参数为条件变量指针，第二个为互斥量指针。该函数调用前，需本线程加锁互斥量，加锁状态的时间内函数完成线程加入等待队列操作 ，线程进入等待前函数解锁互斥量。在满足条件离开 pthread_cond_wait 函数之前重新获得互斥量并加锁，因此，本线程之后需要再次解锁互斥量。<br>通知一个线程：<br><code>int pthread_cond_signal(pthread_cond_t *cond);</code><br>        该函数的参数为条件变量指针。该函数向队列第一个等待线程发送信号，解除这个线程的阻塞状态。<br>通知所有线程：<br><code>int pthread_cond_broadcast(pthread_cond_t *cond);</code><br>        该函数的参数为条件变量指针。该函数想队列所有等待线程发送信号，解除这些线程的阻塞状态。<br>销毁条件变量：<br><code>int pthread_cond_destroy(pthread_cond_t *cond);</code><br>    该函数销毁条件变量。</p></blockquote><h2><span id="多线程链表和-pthreads-读写锁">多线程链表和 Pthreads 读写锁</span></h2><h4><span id="多线程链表的不同实现">多线程链表的不同实现</span></h4><p>考虑一个不降序列链表查找，加入和删除的实现，再多线程调用时，每个位置应该只有一个线程访问，我们可以把整个链表作为一个临界区（<strong>实际上是串行</strong>），也可以为每个节点设置独立的互斥量和临界区。</p><p> 但如果我们区分<strong>读写操作</strong>，那么每个位置可以同时被多个线程读取，因此可以引入更有效率的<strong>Pthreads 读写锁</strong>。 </p><p>以下是读写锁在多线程链表上的实现：</p><pre><code>#include&lt;pthread.h&gt;pthread_rwlock_t rwlock;pthread_rwlock_init(&amp;rwlock,NULL);//读写锁初始化：该函数第一个参数为读写锁指针，第二个参数为读写锁属性指针（置为 NULL 即可）pthread_rwlock_rdlock(&amp;rwlock); //加读锁Member(value); //查找pthread_rwlock_unlock(&amp;rwlock);pthread_rwlock_wrlock(&amp;rwlock); //加写锁Insert(value); //插入pthread_rwlock_unlock(&amp;rwlock);pthread_rwlock_wrlock(&amp;rwlock); //加写锁Delete(value); //删除pthread_rwlock_unlock(&amp;rwlock);pthread_rwlock_destroy(&amp;rwlock);</code></pre><p>多个线程能通过调用读锁函数而同时获得锁，但只有一个线程能通过写锁函数获得锁。因此，如果任何线程拥有了读锁，则任何请求写锁的线程将阻塞在写锁函数的调用上。而且，如果任何线程拥有了写锁，则任何想获取读或写锁的线程将阻塞在它们对应的锁函数上。</p><h4><span id="不同实现方案的开销分析">不同实现方案的开销分析</span></h4><p><img src="/images/pthreads6.png" alt="开销分析"></p><p>可以看出，过多的枷锁和解锁开销过大，而并行使用读写锁在 Member 占比极大时才优于串行实现的方案。</p><h2><span id="线程安全性">线程安全性</span></h2><blockquote><p>线程安全是程式设计中的术语，指某个函数、函数库在多线程环境中被调用时，能够正确地处理多个线程之间的共享变量，使程序功能正确完成。</p><p>假设有间银行只有 1000 元，而两个人同时提领 1000 元时就可能会拿到总计 2000 元的金额。为了避免这个问题，该间银行提款时应该使用互斥锁，即意味着针对同一个资源处理时，前一个人提领交易完成后才处理下一笔交易。但这种手法会使得效能降低。</p><p>一般来说，线程安全的函数应该为每个调用它的线程分配专门的空间，来储存需要单独保存的状态（如果需要的话），不依赖于“线程惯性”，把多个线程共享的变量正确对待（如，通知编译器该变量为“易失（volatile）”型，阻止其进行一些不恰当的优化），而且，线程安全的函数一般不应该修改全局对象。 </p><p>很多 C 库代码（比如某些** strtok **的实现，它将“多次调用中需要保持不变的状态”储存在静态变量中，导致不恰当的共享）不是线程安全的，在多线程环境中调用这些函数时，要进行特别的预防措施，或者寻找别的替代方案。</p></blockquote><p>下面给出 c 语言的线程安全函数和非线程安全函数。（来自 <a href="http://www.keil.com/support/man/docs/armlib/armlib_chr1359122864458.htm">Thread-safe C library functions</a> 和 <a href="http://www.keil.com/support/man/docs/armlib/armlib_chr1359122864707.htm">C library functions that are not thread-safe</a>）</p><h3><span id="thread-safe-c-library-functions">Thread-safe C library functions</span></h3><p>The following table shows the C library functions that are thread-safe.</p><table><thead><tr><th align="left">Functions</th><th align="left">Description</th></tr></thead><tbody><tr><td align="left"><code>calloc(), free(), malloc(), realloc()</code></td><td align="left">The heap functions are thread-safe if the <code>_mutex_</code>* functions are implemented.All threads share a single heap and use mutexes to avoid data corruption when there is concurrent access. Each heap implementation is responsible for doing its own locking. If you supply your own allocator, it must also do its own locking. This enables it to do fine-grained locking if required, rather than protecting the entire heap with a single mutex (coarse-grained locking).</td></tr><tr><td align="left"><code>alloca()</code></td><td align="left"><code>alloca()</code> is thread-safe because it allocates memory on the stack.</td></tr><tr><td align="left"><code>abort(), raise(), signal(), fenv.h</code></td><td align="left">The ARM® signal handling functions and floating-point exception traps are thread-safe.The settings for signal handlers and floating-point traps are global across the entire process and are protected by locks. Data corruption does not occur if multiple threads call <code>signal()</code> or an fenv.h function at the same time. However, be aware that the effects of the call act on all threads and not only on the calling thread.</td></tr><tr><td align="left"><code>clearerr(), fclose(), feof(),ferror(), fflush(), fgetc(),fgetpos(), fgets(), fopen(),fputc(), fputs(), fread(),freopen(), fseek(), fsetpos(),ftell(), fwrite(), getc(),getchar(), gets(), perror(),putc(), putchar(), puts(),rewind(), setbuf(), setvbuf(),tmpfile(), tmpnam(), ungetc()</code></td><td align="left">The <code>stdio</code> library is thread-safe if the <code>_mutex_</code>* functions are implemented.Each individual stream is protected by a lock, so two threads can each open their own <code>stdio</code> stream and use it, without interfering with one another.If two threads both want to read or write the same stream, locking at the <code>fgetc()</code> and <code>fputc()</code> level prevents data corruption, but it is possible that the individual characters output by each thread might be interleaved in a confusing way.Note<code>tmpnam()</code> also contains a static buffer but this is only used if the argument is <code>NULL</code>. To ensure that your use of <code>tmpnam()</code> is thread-safe, supply your own buffer space.</td></tr><tr><td align="left"><code>fprintf(), printf(), vfprintf(), vprintf(), fscanf(), scanf()</code></td><td align="left">When using these functions:The standard C <code>printf()</code> and <code>scanf()</code> functions use <code>stdio</code> so they are thread-safe.The standard C <code>printf()</code> function is susceptible to changes in the locale settings if called in a multithreaded program.</td></tr><tr><td align="left"><code>clock()</code></td><td align="left"><code>clock()</code> contains static data that is written once at program startup and then only ever read. Therefore, <code>clock()</code> is thread-safe provided no extra threads are already running at the time that the library is initialized.</td></tr><tr><td align="left"><code>errno</code></td><td align="left"><code>errno</code> is thread-safe.Each thread has its own <code>errno</code> stored in a <code>__user_perthread_libspace</code> block. This means that each thread can call <code>errno</code>-setting functions independently and then check <code>errno</code> afterwards without interference from other threads.</td></tr><tr><td align="left"><code>atexit()</code></td><td align="left">The list of exit functions maintained by <code>atexit()</code> is process-global and protected by a lock.In the worst case, if more than one thread calls <code>atexit()</code>, the order that exit functions are called cannot be guaranteed.</td></tr><tr><td align="left"><code>abs(), acos(), asin(),atan(), atan2(), atof(),atol(), atoi(), bsearch(),ceil(), cos(), cosh(),difftime(), div(), exp(),fabs(), floor(), fmod(),frexp(), labs(), ldexp(),ldiv(), log(), log10(),memchr(), memcmp(), memcpy(),memmove(), memset(), mktime(),modf(), pow(), qsort(),sin(), sinh(), sqrt(),strcat(), strchr(), strcmp(),strcpy(), strcspn(), strlcat(),strlcpy(), strlen(), strncat(),strncmp(), strncpy(), strpbrk(),strrchr(), strspn(), strstr(),strxfrm(), tan(), tanh()</code></td><td align="left">These functions are inherently thread-safe.</td></tr><tr><td align="left"><code>longjmp(), setjmp()</code></td><td align="left">Although <code>setjmp()</code> and <code>longjmp()</code> keep data in <code>__user_libspace</code>, they call the <code>__alloca_*</code> functions, that are thread-safe.</td></tr><tr><td align="left"><code>remove(), rename(), time()</code></td><td align="left">These functions use interrupts that communicate with the ARM debugging environments. Typically, you have to reimplement these for a real-world application.</td></tr><tr><td align="left"><code>snprintf(), sprintf(), vsnprintf(),vsprintf(), sscanf(), isalnum(),isalpha(), iscntrl(), isdigit(),isgraph(), islower(), isprint(),ispunct(), isspace(), isupper(),isxdigit(), tolower(), toupper(),strcoll(), strtod(), strtol(),strtoul(), strftime()</code></td><td align="left">When using these functions, the string-based functions read the locale settings. Typically, they are thread-safe. However, if you change locale in mid-session, you must ensure that these functions are not affected.The string-based functions, such as <code>sprintf()</code> and <code>sscanf()</code>, do not depend on the <code>stdio</code> library.</td></tr><tr><td align="left"><code>stdin, stdout, stderr</code></td><td align="left">These functions are thread-safe.</td></tr></tbody></table><h3><span id="c-library-functions-that-are-not-thread-safe">C library functions that are not thread-safe</span></h3><p>The following table shows the C library functions that are not thread-safe.</p><table><thead><tr><th align="left">Functions</th><th align="left">Description</th></tr></thead><tbody><tr><td align="left"><code>asctime(), localtime(), strtok()</code></td><td align="left">These functions are all thread-unsafe. Each contains a static buffer that might be overwritten by another thread between a call to the function and the subsequent use of its return value.ARM® supplies reentrant versions, <code>_asctime_r()</code>, <code>_localtime_r()</code>, and <code>_strtok_r()</code>. ARM recommends that you use these functions instead to ensure safety.NoteThese reentrant versions take additional parameters. <code>_asctime_r()</code> takes an additional parameter that is a pointer to a buffer that the output string is written into. <code>_localtime_r()</code> takes an additional parameter that is a pointer to a <code>struct tm</code>, that the result is written into. <code>_strtok_r()</code> takes an additional parameter that is a pointer to a <code>char</code> pointer to the next token.</td></tr><tr><td align="left"><code>exit()</code></td><td align="left">Do not call <code>exit()</code> in a multithreaded program even if you have provided an implementation of the underlying <code>_sys_exit()</code> that actually terminates all threads.In this case, <code>exit()</code> cleans up before calling <code>_sys_exit()</code> so disrupts other threads.</td></tr><tr><td align="left"><code>gamma(), lgamma(), lgammaf(), lgammal()</code></td><td align="left">These extended mathlib functions use a global variable, _signgam, so are not thread-safe.</td></tr><tr><td align="left"><code>mbrlen(), mbsrtowcs(), mbrtowc(), wcrtomb(), wcsrtombs()</code></td><td align="left">The C90 multibyte conversion functions (defined in stdlib.h) are not thread-safe, for example <code>mblen()</code> and <code>mbtowc()</code>, because they contain internal static state that is shared between all threads without locking.However, the extended restartable versions (defined in wchar.h) are thread-safe, for example <code>mbrtowc()</code> and <code>wcrtomb()</code>, provided you pass in a pointer to your own mbstate_t object. You must exclusively use these functions with non-NULL mbstate_t * parameters if you want to ensure thread-safety when handling multibyte strings.</td></tr><tr><td align="left"><code>rand(), srand()</code></td><td align="left">These functions keep internal state that is both global and unprotected. This means that calls to <code>rand()</code> are never thread-safe.ARM recommends that you do one of the following:Use the reentrant versions <code>_rand_r()</code> and <code>_srand_r()</code> supplied by ARM. These use user-provided buffers instead of static data within the C library.Use your own locking to ensure that only one thread ever calls <code>rand()</code> at a time, for example, by defining <code>rand()</code> if you want to avoid changing your code.Arrange that only one thread ever needs to generate random numbers.Supply your own random number generator that can have multiple independent instances.Note<code>_rand_r()</code> and <code>_srand_r()</code> both take an additional parameter that is a pointer to a buffer storing the state of the random number generator.</td></tr><tr><td align="left"><code>setlocale(), localeconv()</code></td><td align="left"><code>setlocale()</code> is used for setting and reading locale settings. The locale settings are global across all threads, and are not protected by a lock. If two threads call <code>setlocale()</code> to simultaneously modify the locale settings, or if one thread reads the settings while another thread is modifying them, data corruption might occur. Also, many other functions, for example <code>strtod()</code> and <code>sprintf()</code>, read the current locale settings. Therefore, if one thread calls <code>setlocale()</code> concurrently with another thread calling such a function, there might be unexpected results.Multiple threads reading the settings simultaneously is thread-safe in simple cases and if no other thread is simultaneously modifying those settings, but where internally an intermediate buffer is required for more complicated returned results, unexpected results can occur unless you use a reentrant version of <code>setlocale()</code>.ARM recommends that you either:Choose the locale you want and call <code>setlocale()</code> once to initialize it. Do this before creating any additional threads in your program so that any number of threads can read the locale settings concurrently without interfering with one another.Use the reentrant version <code>_setlocale_r()</code> supplied by ARM. This returns a string that is either a pointer to a constant string, or a pointer to a string stored in a user-supplied buffer that can be used for thread-local storage, rather than using memory within the C library. The buffer must be at least <code>_SETLOCALE_R_BUFSIZE</code> bytes long, including space for a trailing <code>NUL</code>.Be aware that <code>_setlocale_r()</code> is not fully thread-safe when accessed concurrently to change locale settings. This access is not lock-protected.Also, be aware that <code>localeconv()</code> is not thread-safe. Call the ARM function <code>_get_lconv()</code> with a pointer to a user-supplied buffer instead.</td></tr></tbody></table><h2><span id="参考资料">参考资料</span></h2><p>并行计算导论。Introduction to Parallel Computing. Ananth Grama.</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;本文是在 Pthreads 学习过程中产生的入门级教程。&lt;/p&gt;</summary>
    
    
    
    <category term="Coding" scheme="https://blog.pka.moe/categories/Coding/"/>
    
    <category term="CS" scheme="https://blog.pka.moe/categories/Coding/CS/"/>
    
    
    <category term="Pthreads" scheme="https://blog.pka.moe/tags/Pthreads/"/>
    
    <category term="并行编程" scheme="https://blog.pka.moe/tags/%E5%B9%B6%E8%A1%8C%E7%BC%96%E7%A8%8B/"/>
    
  </entry>
  
  <entry>
    <title>使用 Node.js 建立 info 的简单代理服务器</title>
    <link href="https://blog.pka.moe/info-proxy/"/>
    <id>https://blog.pka.moe/info-proxy/</id>
    <published>2020-02-15T12:06:00.000Z</published>
    <updated>2020-02-15T12:06:00.000Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><p>主要需求是在校外结合 RSSHub 订阅 info ，避免错过重要通知。</p><span id="more"></span><p>首先利用清华大学提供的 <a href="https://webvpn.tsinghua.edu.cn/">WEBVPN</a> 搭建实现自动登录功能的代理服务器。（新版 WEBVPN 只是校内代理，相较于以前自动登录 info 的 SSLVPN 风险较小）</p><p>学习并使用 Node.js，使用单语句<code>req.pipe(request).pip(res)</code>实现不完美的网页代理（在这里够用了）。</p><pre><code class="javascript">var request = require(&quot;request&quot;);var express = require(&quot;express&quot;);//登陆 post 地址let url = &#39;https://webvpn.tsinghua.edu.cn/do-login?local_login=true&#39;;//登陆的用户邮箱和密码let user = &#123;    username: &#39;&#39;,    password: &#39;&#39;,&#125;;//登陆 post 的所有数据let datas = &#123;    auth_type: &#39;local&#39;,    username: user.username,    sms_code: &#39;&#39;,    password: user.password,    remember_cookie: &#39;on&#39;,&#125;;//设置头部let ua = `Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36`;let headers = &#123;    &#39;User-Agent&#39;: ua,&#125;;let opts = &#123;    url: url,    method: &#39;POST&#39;,    headers: headers,    form: datas,&#125;;//模拟登陆var cookie;request(opts, (e, r, b) =&gt; &#123;    cookie = r.headers[&#39;set-cookie&#39;];&#125;);var app = express();app.use(&quot;/&quot;, function (req, res) &#123;    request(&#123;            url: &quot;https://webvpn.tsinghua.edu.cn/http/77726476706e69737468656265737421f9f9479369247b59700f81b9991b2631506205de/initial/letter.gif&quot;,            headers: &#123;                Cookie: cookie,                 &#39;User-Agent&#39;: ua,            &#125;&#125;,(e, r, b) =&gt; &#123;                //检测 cookie 是否失效                if(b.indexOf(&#39;html&#39;)&gt;0)&#123;                    request(opts, (e, r, b) =&gt; &#123;                        cookie = r.headers[&#39;set-cookie&#39;];                    &#125;);                &#125;            &#125;    );    //增强安全性    if(req.url.match(/^\/(http|wengine-vpn)/))&#123;        req.pipe(request(&#123;                url: &quot;https://webvpn.tsinghua.edu.cn&quot; + req.url,                headers: &#123;                    Cookie: cookie,                     &#39;User-Agent&#39;: ua,                &#125;,                encoding: null,                qs: req.query,                method: req.method            &#125;)).pipe(res);    &#125;    &#125;);app.listen(process.env.PORT || 3000);</code></pre><p>同时使用 <a href="https://docs.rsshub.app/university.html#qing-hua-da-xue">RSSHub</a> 实现了清华大学校内信息发布平台的 RSS 化。</p>]]></content>
    
    
    <summary type="html">&lt;p&gt;主要需求是在校外结合 RSSHub 订阅 info ，避免错过重要通知。&lt;/p&gt;</summary>
    
    
    
    <category term="Coding" scheme="https://blog.pka.moe/categories/Coding/"/>
    
    
    <category term="NodeJs" scheme="https://blog.pka.moe/tags/NodeJs/"/>
    
    <category term="Proxy" scheme="https://blog.pka.moe/tags/Proxy/"/>
    
  </entry>
  
  <entry>
    <title>THUCTF 2019 - Writeup</title>
    <link href="https://blog.pka.moe/thuctf-2019-writeup/"/>
    <id>https://blog.pka.moe/thuctf-2019-writeup/</id>
    <published>2019-10-10T15:46:06.000Z</published>
    <updated>2019-10-10T15:46:06.000Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><p>第一次参加 CTF 比赛，虽然水，但 Writeup 还是要写的。（不然没有奖金）</p><span id="more"></span><ol><li>入域：一道快乐的送分题</li></ol><hr><p><img src="/images/thuctf2019001.png" alt="img"></p><p>得到 flag：THUCTF{Welcome_To_THUCTF2019}</p><p>早上 7 点起床，发现大佬 <a href="https://mcfx.us/">mcfx</a> 已经提交了三道题，于是决定沿着他的路径做题。</p><p><img src="/images/thuctf2019002.png" alt="img"></p><h2><span id="2xor-cipher">2.xor cipher</span></h2><p>Google 一下，发现是异或密码，找到相关文章：<a href="https://blog.csdn.net/qq_41079177/article/details/89196428">CTF 题目中 XOR 加密解法脚本</a> 和相关题目 <a href="https://chybeta.github.io/2017/09/16/%E9%97%AE%E9%BC%8E%E6%9D%AF-CTF-writeup/">问鼎杯 CTF writeup</a>，安装 xortool（为了正常运行还装了 ubuntu 虚拟机）</p><p><img src="/images/thuctf2019001-3358223.png" alt="img"></p><p>大约得到 THUCTF{xor_es_eteres&#x3D;&amp;enq}，还需要进一步处理。</p><p>得到初步解密的结果，找到原文：<a href="https://en.wikipedia.org/wiki/XOR_cipher">Wikiped – XOR cipher</a></p><p><img src="/images/thuctf2019002-3358223.png" alt="img"></p><p>现在已知明文和密文，只需求解密钥，由异或运算性质 A⨁B&#x3D;C⇒A⨁C&#x3D;B 或 B⨁C&#x3D;A，再对明文和密文进行一次异或运算即得 flag。下面是加密&#x2F;解密源码：</p><pre><code class="python">#!/usr/bin/pythonkey = &#39;THUCTF&#123;xo3_1s_1terestr1nq&#125;&#39; flag = &#39;&#39;with open(&#39;cipher.txt&#39;) as f:    con = f.read()    for i in range(len(con)):        flag += chr(ord(con[i]) ^ ord(key[i%26]))f = open(&#39;flag.txt&#39;, &#39;w&#39;)print(flag)f.write(flag)f.close()</code></pre><h2><span id="3listentome">3.ListenToMe</span></h2><p>文件只有一段音频，Google 查找类似题，发现使用 Audacity 的频谱图观察，没看出什么东西。</p><p>然后去听原始音频，发现是摩尔斯电码，解密后得到：</p><p><img src="/images/thuctf2019001-3358253.png" alt="img"></p><p>还是我去看 Spectrogram 频谱图…</p><p>又自己折腾了一会儿 Audacity，发现要“缩放到合适大小“（为什么以往 write up 都不说 …(｡•ˇ‸ˇ•｡) … 还是我太水了吗），然后 Flag 就出来了。</p><p><img src="/images/thuctf2019002-3358253.png" alt="img">THUCTF{Can_You_Hear_UlTRASOUND}</p><h2><span id="4ics-scavengers">4.ICS Scavengers</span></h2><p>分析文件格式，发现是一道流量分析题，用 Wireshark 打开分析，追踪 TCP 流，找到有意义的信息。</p><p><img src="/images/thuctf2019001-3358267.png" alt="img"></p><p>第一个是 Base64 加密字符串，直接解密即可。</p><p><img src="/images/thuctf2019002-3358267.png" alt="img"><img src="/images/thuctf2019003.png" alt="img"></p><p>第二个明文给出。</p><p><img src="/images/thuctf2019004.png" alt="img"></p><p>第三个是 Base64 编码的图片，解码即可。</p><p><img src="/images/thuctf2019005.png" alt="img"><img src="/images/thuctf2019006.png" alt="img"></p><p>三段 Flag 合成最终的 Flag：</p><p><img src="/images/thuctf2019007.png" alt="img"></p><ol start="5"><li>后记</li></ol><hr><p>为什么我只写了 3 道题呢？</p><ul><li>完全没有基础，100%萌新</li><li>后天被各种活动和微积分线代离散新生研讨课按在地上摩擦，无法拿出大量时间学 Pwn 或者 Web，也没有时间想题</li><li>懒</li></ul><p>这应该算是一个好的开头吧，我想。最近一直遇到的都是学习难度大、曲线陡的问题，都耗时间，但都要坚持。 <strong>只要，一直提高就好了吧。</strong></p>]]></content>
    
    
    <summary type="html">&lt;p&gt;第一次参加 CTF 比赛，虽然水，但 Writeup 还是要写的。（不然没有奖金）&lt;/p&gt;</summary>
    
    
    
    <category term="CS" scheme="https://blog.pka.moe/categories/CS/"/>
    
    
    <category term="CTF" scheme="https://blog.pka.moe/tags/CTF/"/>
    
  </entry>
  
  <entry>
    <title>Hello World</title>
    <link href="https://blog.pka.moe/hello-world/"/>
    <id>https://blog.pka.moe/hello-world/</id>
    <published>2019-06-21T12:00:00.000Z</published>
    <updated>2019-06-21T12:00:00.000Z</updated>
    
    <content type="html"><![CDATA[<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><p>Welcome to <a href="https://hexo.io/">Hexo</a>!</p><span id="more"></span><p>Welcome to <a href="https://hexo.io/">Hexo</a><sup id="fnref:1"><a href="#fn:1" rel="footnote"><span class="hint--top hint--error hint--medium hint--rounded hint--bounce" aria-label="Hexo 是一个快速、简洁且高效的博客框架。">[1]</span></a></sup>! This is your very first post. Check <a href="https://hexo.io/docs/">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a href="https://hexo.io/docs/troubleshooting.html">troubleshooting</a> or you can ask me on <a href="https://github.com/hexojs/hexo/issues">GitHub</a>.</p><p><span id="inline-blue">Papersnake</span></p><p><mjx-container class="MathJax" jax="SVG" display="true" width="full" style="min-width: 20.339ex;"><svg style="vertical-align: -3.733ex; min-width: 20.339ex;" xmlns="http://www.w3.org/2000/svg" width="100%" height="8.597ex" role="img" focusable="false"><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="scale(0.0181,-0.0181) translate(0, -2150)"><g data-mml-node="math"><g data-mml-node="mtable" transform="translate(2078,0) translate(-2078,0)"><g transform="translate(0 2150) matrix(1 0 0 -1 0 0) scale(55.25)"><svg data-table="true" preserveaspectratio="xMidYMid" viewbox="2417 -2150 1 3800"><g transform="matrix(1 0 0 -1 0 0)"><g data-mml-node="mlabeledtr"><g data-mml-node="mtd"><g data-mml-node="mrow"><g data-mml-node="mo"><path data-c="23A1" d="M319 -645V1154H666V1070H403V-645H319Z" transform="translate(0,996)"/><path data-c="23A3" d="M319 -644V1155H403V-560H666V-644H319Z" transform="translate(0,-1006)"/><svg width="667" height="402" y="49" x="0" viewbox="0 100.5 667 402"><path data-c="23A2" d="M319 0V602H403V0H319Z" transform="scale(1,1.002)"/></svg></g><g data-mml-node="mtable" transform="translate(667,0)"><g data-mml-node="mtr" transform="translate(0,1400)"><g data-mml-node="mtd"><g data-mml-node="mn"><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z"/></g></g><g data-mml-node="mtd" transform="translate(1500,0)"><g data-mml-node="mn"><path data-c="32" d="M109 429Q82 429 66 447T50 491Q50 562 103 614T235 666Q326 666 387 610T449 465Q449 422 429 383T381 315T301 241Q265 210 201 149L142 93L218 92Q375 92 385 97Q392 99 409 186V189H449V186Q448 183 436 95T421 3V0H50V19V31Q50 38 56 46T86 81Q115 113 136 137Q145 147 170 174T204 211T233 244T261 278T284 308T305 340T320 369T333 401T340 431T343 464Q343 527 309 573T212 619Q179 619 154 602T119 569T109 550Q109 549 114 549Q132 549 151 535T170 489Q170 464 154 447T109 429Z"/></g></g><g data-mml-node="mtd" transform="translate(3000,0)"><g data-mml-node="mn"><path data-c="33" d="M127 463Q100 463 85 480T69 524Q69 579 117 622T233 665Q268 665 277 664Q351 652 390 611T430 522Q430 470 396 421T302 350L299 348Q299 347 308 345T337 336T375 315Q457 262 457 175Q457 96 395 37T238 -22Q158 -22 100 21T42 130Q42 158 60 175T105 193Q133 193 151 175T169 130Q169 119 166 110T159 94T148 82T136 74T126 70T118 67L114 66Q165 21 238 21Q293 21 321 74Q338 107 338 175V195Q338 290 274 322Q259 328 213 329L171 330L168 332Q166 335 166 348Q166 366 174 366Q202 366 232 371Q266 376 294 413T322 525V533Q322 590 287 612Q265 626 240 626Q208 626 181 615T143 592T132 580H135Q138 579 143 578T153 573T165 566T175 555T183 540T186 520Q186 498 172 481T127 463Z"/></g></g></g><g data-mml-node="mtr"><g data-mml-node="mtd"><g data-mml-node="mn"><path data-c="34" d="M462 0Q444 3 333 3Q217 3 199 0H190V46H221Q241 46 248 46T265 48T279 53T286 61Q287 63 287 115V165H28V211L179 442Q332 674 334 675Q336 677 355 677H373L379 671V211H471V165H379V114Q379 73 379 66T385 54Q393 47 442 46H471V0H462ZM293 211V545L74 212L183 211H293Z"/></g></g><g data-mml-node="mtd" transform="translate(1500,0)"><g data-mml-node="mn"><path data-c="35" d="M164 157Q164 133 148 117T109 101H102Q148 22 224 22Q294 22 326 82Q345 115 345 210Q345 313 318 349Q292 382 260 382H254Q176 382 136 314Q132 307 129 306T114 304Q97 304 95 310Q93 314 93 485V614Q93 664 98 664Q100 666 102 666Q103 666 123 658T178 642T253 634Q324 634 389 662Q397 666 402 666Q410 666 410 648V635Q328 538 205 538Q174 538 149 544L139 546V374Q158 388 169 396T205 412T256 420Q337 420 393 355T449 201Q449 109 385 44T229 -22Q148 -22 99 32T50 154Q50 178 61 192T84 210T107 214Q132 214 148 197T164 157Z"/></g></g><g data-mml-node="mtd" transform="translate(3000,0)"><g data-mml-node="mn"><path data-c="36" d="M42 313Q42 476 123 571T303 666Q372 666 402 630T432 550Q432 525 418 510T379 495Q356 495 341 509T326 548Q326 592 373 601Q351 623 311 626Q240 626 194 566Q147 500 147 364L148 360Q153 366 156 373Q197 433 263 433H267Q313 433 348 414Q372 400 396 374T435 317Q456 268 456 210V192Q456 169 451 149Q440 90 387 34T253 -22Q225 -22 199 -14T143 16T92 75T56 172T42 313ZM257 397Q227 397 205 380T171 335T154 278T148 216Q148 133 160 97T198 39Q222 21 251 21Q302 21 329 59Q342 77 347 104T352 209Q352 289 347 316T329 361Q302 397 257 397Z"/></g></g></g><g data-mml-node="mtr" transform="translate(0,-1400)"><g data-mml-node="mtd"><g data-mml-node="mn"><path data-c="37" d="M55 458Q56 460 72 567L88 674Q88 676 108 676H128V672Q128 662 143 655T195 646T364 644H485V605L417 512Q408 500 387 472T360 435T339 403T319 367T305 330T292 284T284 230T278 162T275 80Q275 66 275 52T274 28V19Q270 2 255 -10T221 -22Q210 -22 200 -19T179 0T168 40Q168 198 265 368Q285 400 349 489L395 552H302Q128 552 119 546Q113 543 108 522T98 479L95 458V455H55V458Z"/></g></g><g data-mml-node="mtd" transform="translate(1500,0)"><g data-mml-node="mn"><path data-c="38" d="M70 417T70 494T124 618T248 666Q319 666 374 624T429 515Q429 485 418 459T392 417T361 389T335 371T324 363L338 354Q352 344 366 334T382 323Q457 264 457 174Q457 95 399 37T249 -22Q159 -22 101 29T43 155Q43 263 172 335L154 348Q133 361 127 368Q70 417 70 494ZM286 386L292 390Q298 394 301 396T311 403T323 413T334 425T345 438T355 454T364 471T369 491T371 513Q371 556 342 586T275 624Q268 625 242 625Q201 625 165 599T128 534Q128 511 141 492T167 463T217 431Q224 426 228 424L286 386ZM250 21Q308 21 350 55T392 137Q392 154 387 169T375 194T353 216T330 234T301 253T274 270Q260 279 244 289T218 306L210 311Q204 311 181 294T133 239T107 157Q107 98 150 60T250 21Z"/></g></g><g data-mml-node="mtd" transform="translate(3000,0)"><g data-mml-node="mn"><path data-c="39" d="M352 287Q304 211 232 211Q154 211 104 270T44 396Q42 412 42 436V444Q42 537 111 606Q171 666 243 666Q245 666 249 666T257 665H261Q273 665 286 663T323 651T370 619T413 560Q456 472 456 334Q456 194 396 97Q361 41 312 10T208 -22Q147 -22 108 7T68 93T121 149Q143 149 158 135T173 96Q173 78 164 65T148 49T135 44L131 43Q131 41 138 37T164 27T206 22H212Q272 22 313 86Q352 142 352 280V287ZM244 248Q292 248 321 297T351 430Q351 508 343 542Q341 552 337 562T323 588T293 615T246 625Q208 625 181 598Q160 576 154 546T147 441Q147 358 152 329T172 282Q197 248 244 248Z"/></g></g></g></g><g data-mml-node="mo" transform="translate(4167,0)"><path data-c="23A4" d="M0 1070V1154H347V-645H263V1070H0Z" transform="translate(0,996)"/><path data-c="23A6" d="M263 -560V1155H347V-644H0V-560H263Z" transform="translate(0,-1006)"/><svg width="667" height="402" y="49" x="0" viewbox="0 100.5 667 402"><path data-c="23A5" d="M263 0V602H347V0H263Z" transform="scale(1,1.002)"/></svg></g></g></g></g></g></svg><svg data-labels="true" preserveaspectratio="xMaxYMid" viewbox="1278 -2150 1 3800"><g data-labels="true" transform="matrix(1 0 0 -1 0 0)"><g data-mml-node="mtd" id="mjx-eqn:1"><g data-mml-node="mtext"><path data-c="28" d="M94 250Q94 319 104 381T127 488T164 576T202 643T244 695T277 729T302 750H315H319Q333 750 333 741Q333 738 316 720T275 667T226 581T184 443T167 250T184 58T225 -81T274 -167T316 -220T333 -241Q333 -250 318 -250H315H302L274 -226Q180 -141 137 -14T94 250Z"/><path data-c="31" d="M213 578L200 573Q186 568 160 563T102 556H83V602H102Q149 604 189 617T245 641T273 663Q275 666 285 666Q294 666 302 660V361L303 61Q310 54 315 52T339 48T401 46H427V0H416Q395 3 257 3Q121 3 100 0H88V46H114Q136 46 152 46T177 47T193 50T201 52T207 57T213 61V578Z" transform="translate(389,0)"/><path data-c="29" d="M60 749L64 750Q69 750 74 750H86L114 726Q208 641 251 514T294 250Q294 182 284 119T261 12T224 -76T186 -143T145 -194T113 -227T90 -246Q87 -249 86 -250H74Q66 -250 63 -250T58 -247T55 -238Q56 -237 66 -225Q221 -64 221 250T66 725Q56 737 55 738Q55 746 60 749Z" transform="translate(889,0)"/></g></g></g></svg></g></g></g></g></svg></mjx-container></p><div id="footnotes"><hr><div id="footnotelist"><ol style="list-style: none; padding-left: 0; margin-left: 40px"><li id="fn:1"><span style="display: inline-block; vertical-align: top; padding-right: 10px; margin-left: -40px">1.</span><span style="display: inline-block; vertical-align: top; margin-left: 10px;">Hexo 是一个快速、简洁且高效的博客框架。<a href="#fnref:1" rev="footnote"> ↩</a></span></li></ol></div></div>]]></content>
    
    
    <summary type="html">&lt;p&gt;Welcome to &lt;a href=&quot;https://hexo.io/&quot;&gt;Hexo&lt;/a&gt;!&lt;/p&gt;</summary>
    
    
    
    <category term="随便写写" scheme="https://blog.pka.moe/categories/%E9%9A%8F%E4%BE%BF%E5%86%99%E5%86%99/"/>
    
    
  </entry>
  
</feed>
