-
Notifications
You must be signed in to change notification settings - Fork 0
/
atom.xml
407 lines (303 loc) · 103 KB
/
atom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>UoCat</title>
<subtitle>热烈的活在此刻</subtitle>
<link href="https://uocat.com/atom.xml" rel="self"/>
<link href="https://uocat.com/"/>
<updated>2024-08-15T00:40:16.441Z</updated>
<id>https://uocat.com/</id>
<author>
<name>tqcq</name>
</author>
<generator uri="https://hexo.io/">Hexo</generator>
<entry>
<title>异星工厂 - 无符号位移</title>
<link href="https://uocat.com/posts/3d6/"/>
<id>https://uocat.com/posts/3d6/</id>
<published>2023-09-04T15:50:56.000Z</published>
<updated>2024-08-15T00:40:16.441Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><h2 id="1-1-无符号位移原理"><a class="header-anchor" href="#1-1-无符号位移原理">¶</a>1.1 无符号位移原理</h2><h3 id="1-1-1-背景"><a class="header-anchor" href="#1-1-1-背景">¶</a>1.1.1 背景</h3><p>异星工厂中的<code>算数运算器</code>只提供了<code>有符号位移</code> (sar),但是想要造一个高性能计算机需要实现<code>无符号位移</code> (shr)。</p><h3 id="1-1-2-sar-实现-shr-的原理"><a class="header-anchor" href="#1-1-2-sar-实现-shr-的原理">¶</a>1.1.2 <code>sar</code> 实现 <code>shr</code> 的原理</h3><p>实现<code>无符号右移</code>有几个目标:</p><ul><li>高效:运算在 1 tick 以内(也就是说,和有符号位移速度一样快)</li><li>简单:不需要太多的电路,这样才能保证计算机小巧。</li><li>支持 32bit: 这样才能实现 32bit 计算机</li></ul><p>首先,我们来看看<code>有符号右移</code>的原理:</p><table><thead><tr><th>有符号右移</th><th>说明</th></tr></thead><tbody><tr><td> x >= 0</td><td> 此时,<code>sar</code> 和 <code>shr</code> 的结果一致</td></tr><tr><td> x < 0</td><td> 此时,<code>sar</code> 和 <code>shr</code> 的结果不一致,可以对比下面两张图 </td></tr></tbody></table><p><img src="https://uocat.com/images/749b6e6f57ae7f510f18578ab2681579.jpg" alt="shr" loading="lazy"></p><p><img src="https://uocat.com/images/fbd00634d2193cdc761cdbc8338a44cc.jpg" alt="sar" loading="lazy"></p><h3 id="1-1-3-实现负数的-无符号右移-shr"><a class="header-anchor" href="#1-1-3-实现负数的-无符号右移-shr">¶</a>1.1.3 实现负数的 <code>无符号右移</code> (<code>shr</code>)</h3><p>异星工厂中的算数运算器是 32-bit 有符号整数,我们利用加法溢出可以移除负数的最高位。</p><p>其中算数运算器的处理过程如下:</p><blockquote><p>注意输出侧会有一次求和,可以利用这次求和让符号位溢出</p></blockquote><p><img src="https://uocat.com/images/ec99d2580e533848add5f96b3ae392f6.jpg" alt="" loading="lazy"></p><blockquote><p> 现在我们通过设置 红色信号 A 为 0x8000000 = -2147483648,就可以实现将绿色信号中 A 的符号为移除的效果。</p></blockquote><h4 id="1-1-3-1-移位修正"><a class="header-anchor" href="#1-1-3-1-移位修正">¶</a>1.1.3.1 移位修正</h4><div class="admonition warning"><p class="admonition-title">例子</p><p>我们用 16bit 有符号距离感,假设有一个 16-bit 数字右移 8 位分为有符号和无符号两种讨论 A>>>8 的计算方法</p></div><p>将 A 设置为 0x8000000 之后,实现了下面的变换:</p><ul><li>1xxx xxxx xxxx xxxx -> 0xxx xxxx xxxx xxxx</li><li>0xxx xxxx xxxx xxxx -> 1xxx xxxx xxxx xxxx</li></ul><p>移位之后有:</p><ul><li>1xxx xxxx xxxx xxxx -> 0xxx xxxx xxxx xxxx -> 0000 0000 0xxx xxxx</li><li>0xxx xxxx xxxx xxxx -> 1xxx xxxx xxxx xxxx -> 1111 1111 1xxx xxxx</li></ul><p>这里非常接近我们需要的结果,因为我们只需要在最后两个数字的第 8 位加一个 1,就可以得到需要的结果:</p><ul><li>0000 0000 0xxx xxxx + 0000 0000 1000 0000 -> 0000 0000 1xxx xxxx</li><li>1111 1111 1xxx xxxx + 0000 0000 1000 0000 -> 0000 0000 0xxx xxxx</li></ul><blockquote><p>这里我们可以设置另外两个变量 X, Y<br>其中 X = Y = 0100 0000 0000 0000</p><p>当 A 为负数时,X,Y 会进位,替代被溢出丢失的符号位<br>当 A 位正数时,X,Y 会进位,但是这时是和我们设置的常量 0x80000000 求和溢出,X + Y + 0x8000000 = 0</p></blockquote><p><img src="https://uocat.com/images/68d06be109a382a0f6405eb5186a4ca5.jpg" alt="" loading="lazy"></p><h3 id="1-1-4-当移位-31-位时"><a class="header-anchor" href="#1-1-4-当移位-31-位时">¶</a>1.1.4 当移位 31 位时</h3><p>移位 31 位时,我们发现 X 和 Y 在求和之前都已经成为 0,无法进位抵消 A 的符号位,因此需要特判 B == 31 时,输出一个 A = 1 进行修正。</p><p>至此我们已经实现了一个 1 tick 的 shr 运算单元。</p><p><img src="https://uocat.com/images/b9cf6d41101ad11ee4b024798d308121.jpg" alt="" loading="lazy"></p><h2 id="1-2-无符号右移-shr-蓝图"><a class="header-anchor" href="#1-2-无符号右移-shr-蓝图">¶</a>1.2 无符号右移 shr 蓝图</h2><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">0eNq1ld2OmzAQhd9lrmEV/kqCtCt1n6JVVSECk81IYCNjokYR796xaSjdDbAk6k0kE8/xmflm7AvsyxZrRUJDcgHKpWgg+XGBht5EVppv+lwjJEAaK3BAZJVZZYr0sUJNuZvLak8i01JB5wCJAn9B4nXOokaBORWobgv43U8HUGjShL0juzinoq32qPiEQafCgtrKxRJzrdhQLUvkU2rZcLAU5nwjGHlPkQNnSNzwKeKDOFXBEWQzvoBnft4UohifRgUkAe8llbek7ZKddZ1J750hfy6xG3Y2Vzt+b0YrWaZ7PGYn4gDe9Ucm5f8KGnweSDU6/VDaEynd8pfBRL/DfYVevdGZQRx4ZlXVmbK2EnjmCNnqul2h+bXXrM9srRU6PShZpSRYA5JDVjbYTZRXYbFQXG9UWLMOudgO+J8Ltj3zCMJgob/nmmqK4l+lx0Bilh9N3Rs0MisbQNbIwK1veHm5D/kKqP57qFNcolm8/mfxftj4bxN5E7jDIcvrgMzDDndX2J69QQpSfTGs1C34Byo1qokbdWG8WjOvru+FcbgNvoTbhbt1Su3bSG0Qi0f37Bqx7/NigcV5d5PchBSthDRM5OZ6y/8HKt6dMF5HIsFm/Ng98CD1lePZsM9rMnrRHThxnrY4/pZx7fw4DuJdtA277je2Ga8W</span><br></pre></td></tr></tbody></table></figure>]]></content>
<summary type="html"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><h2 id="1-1-无符号位移原理"><a class="header-anchor" href="#1-1-无符号位移原理">¶</a>1.1 无符号位移原理</h2>
<h3 id="1-1-1-背景"><a class="header-anchor" href="#1-1-1-背景">¶</a>1.1.1 背景</h3>
<p>异星工厂中的<code>算数运算器</code>只提供了<code>有符号位移</code> (sar),但是想要造一个高性能计算机需要实现<code>无符号位移</code> (shr)。</p>
<h3 id="1-1-2-sar-实现-shr-的原理"><a class="header-anchor" href="#1-1-2-sar-实现-shr-的原理">¶</a>1.1.2 <code>sar</code> 实现 <code>shr</code> 的原理</h3>
<p>实现<code>无符号右移</code>有几个目标:</p>
<ul>
<li>高效:运算在 1 tick 以内(也就是说,和有符号位移速度一样快)</li>
<li>简单:不需要太多的电路,这样才能保证计算机小巧。</li>
<li>支持 32bit: 这样才能实现 32bit 计算机</li>
</ul>
<p>首先,我们来看看<code>有符号右移</code>的原理:</p>
<table>
<thead>
<tr>
<th>有符号右移</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td> x &gt;= 0</td>
<td> 此时,<code>sar</code> 和 <code>shr</code> 的结果一致</td>
</tr>
<tr>
<td> x &lt; 0</td>
<td> 此时,<code>sar</code> 和 <code>shr</code> 的结果不一致,可以对比下面两张图 </td>
</tr>
</tbody>
</table>
<p><img src="https://uocat.com/images/749b6e6f57ae7f510f18578ab2681579.jpg" alt="shr" loading="lazy"></p></summary>
<category term="Game" scheme="https://uocat.com/categories/Game/"/>
<category term="Factorio, 异星工厂, 无符号位移, shr" scheme="https://uocat.com/tags/Factorio-%E5%BC%82%E6%98%9F%E5%B7%A5%E5%8E%82-%E6%97%A0%E7%AC%A6%E5%8F%B7%E4%BD%8D%E7%A7%BB-shr/"/>
</entry>
<entry>
<title>git commit 签名</title>
<link href="https://uocat.com/posts/efdc/"/>
<id>https://uocat.com/posts/efdc/</id>
<published>2023-08-07T10:12:51.000Z</published>
<updated>2024-08-15T00:40:16.441Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><h2 id="1-1-创建自己的-GPG-密钥"><a class="header-anchor" href="#1-1-创建自己的-GPG-密钥">¶</a>1.1 创建自己的 GPG 密钥</h2><p>执行一下命令选择加密算法,并完善相关信息。</p><div class="admonition todo"><p class="admonition-title">步骤简介</p><ol><li>选择加密算法 (RSA 签名)</li><li> 设置密钥长度 (4096)</li><li> 设置密钥有效期 (1y),这是确保安全的最后防线</li><li>设置用户姓名、邮箱、注释(最好不要用常用邮箱,避免垃圾邮件骚扰)</li></ol></div><h3 id="1-1-1-运行-gpg-开始生成密钥"><a class="header-anchor" href="#1-1-1-运行-gpg-开始生成密钥">¶</a>1.1.1 运行 gpg 开始生成密钥</h3><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gpg --full-generate-key</span><br></pre></td></tr></tbody></table></figure><blockquote><p>输出如下,这里选择 4</p></blockquote><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">gpg (GnuPG) 2.2.27; Copyright (C) 2021 Free Software Foundation, Inc.</span><br><span class="line">This is free software: you are free to change and redistribute it.</span><br><span class="line">There is NO WARRANTY, to the extent permitted by law.</span><br><span class="line"></span><br><span class="line">Please <span class="keyword">select</span> what kind of key you want:</span><br><span class="line"> (1) RSA and RSA (default)</span><br><span class="line"> (2) DSA and Elgamal</span><br><span class="line"> (3) DSA (sign only)</span><br><span class="line"> (4) RSA (sign only)</span><br><span class="line"> (14) Existing key from card</span><br></pre></td></tr></tbody></table></figure><blockquote><p>这里我们生成的是主密钥,只负责分发子密钥,因此只需要具有签名功能即可<br>这里我选择 4. RSA,有如下几个原因</p><ul><li>RSA 久经验证,是行业标准。</li><li>相关研究认为更长的 RSA,参考此论文: <a href="https://eprint.iacr.org/2015/1018.pdf">A RIDDLE WRAPPED IN AN ENIGMA</a>。</li><li>RSA 在各个平台上都有很好的支持。</li></ul></blockquote><h3 id="1-1-2-设置密钥长度"><a class="header-anchor" href="#1-1-2-设置密钥长度">¶</a>1.1.2 设置密钥长度</h3><p>现在计算机性能都不差,可以选择 4096 位的密钥长度,这样可以更好的保护你的密钥。</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">RSA keys may be between 1024 and 4096 bits long.</span><br><span class="line">What keysize <span class="keyword">do</span> you want? (3072)</span><br></pre></td></tr></tbody></table></figure><h3 id="1-1-3-设置过期时常"><a class="header-anchor" href="#1-1-3-设置过期时常">¶</a>1.1.3 设置过期时常</h3><p>这里非常推荐设置一个过期时长,避免密钥被盗用,一般设置为 1 年。</p><blockquote><p>这里我们输入 <code>1y</code>,表示 1 年后过期。<br>如果有更高的安全需求,可以设置更短的过期时间。<br>即将过期的时候,可以通过 <code>gpg --edit-key <key-id></code> 命令来延长密钥的有效期。</p></blockquote><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Requested keysize is 4096 bits</span><br><span class="line">Please specify how long the key should be valid.</span><br><span class="line"> 0 = key does not expire</span><br><span class="line"> <n> = key expires <span class="keyword">in</span> n days</span><br><span class="line"> <n>w = key expires <span class="keyword">in</span> n weeks</span><br><span class="line"> <n>m = key expires <span class="keyword">in</span> n months</span><br><span class="line"> <n>y = key expires <span class="keyword">in</span> n years</span><br><span class="line">Key is valid <span class="keyword">for</span>? (0)</span><br></pre></td></tr></tbody></table></figure><h3 id="1-1-4-接下来输入身份信息"><a class="header-anchor" href="#1-1-4-接下来输入身份信息">¶</a>1.1.4 接下来输入身份信息</h3><p>从略</p><h3 id="1-1-5-为主密钥设定密码"><a class="header-anchor" href="#1-1-5-为主密钥设定密码">¶</a>1.1.5 为主密钥设定密码</h3><p>这一步应该设定一个强度高的密码。</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk</span><br><span class="line">x Please enter the passphrase to x</span><br><span class="line">x protect your new key x</span><br><span class="line">x x</span><br><span class="line">x Passphrase: ________________________________________ x</span><br><span class="line">x x</span><br><span class="line">x <OK> <Cancel> x</span><br><span class="line">mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj</span><br></pre></td></tr></tbody></table></figure><h3 id="1-1-6-完成创建"><a class="header-anchor" href="#1-1-6-完成创建">¶</a>1.1.6 完成创建</h3><div class="admonition warning"><p class="admonition-title">主密钥成就解锁</p><p>恭喜你,走到这一步已经获得了一个主密钥。</p></div><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">生成一个用于此用途的子密钥。</span><br><span class="line">pub rsa4096 2023-08-07 [SC] [expires:2024-08-06]</span><br><span class="line"> AC27EFC2205EE9272D6B87F8DD6E204C56810DCB</span><br><span class="line">uid tqcq <[email protected]></span><br></pre></td></tr></tbody></table></figure><h2 id="1-2-签发子密钥"><a class="header-anchor" href="#1-2-签发子密钥">¶</a>1.2 签发子密钥</h2><h3 id="1-2-1-首先进入gpg的交互模式"><a class="header-anchor" href="#1-2-1-首先进入gpg的交互模式">¶</a>1.2.1 首先进入 gpg 的交互模式</h3><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gpg --edit-key tqcq</span><br></pre></td></tr></tbody></table></figure><h3 id="1-2-2-添加子密钥"><a class="header-anchor" href="#1-2-2-添加子密钥">¶</a>1.2.2 添加子密钥</h3><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 这里的 gpg> 是 gpg 的交互模式提示符,不需要输入</span></span><br><span class="line">gpg> addkey</span><br></pre></td></tr></tbody></table></figure><h3 id="1-2-3-选择子密钥类型"><a class="header-anchor" href="#1-2-3-选择子密钥类型">¶</a>1.2.3 选择子密钥类型</h3><p>这里选择 10 即可,ECC 兼顾速度和安全性</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">Please <span class="keyword">select</span> what kind of key you want:</span><br><span class="line"> (3) DSA (sign only)</span><br><span class="line"> (4) RSA (sign only)</span><br><span class="line"> (5) Elgamal (encrypt only)</span><br><span class="line"> (6) RSA (encrypt only)</span><br><span class="line"> (7) DSA (<span class="built_in">set</span> your own capabilities)</span><br><span class="line"> (8) RSA (<span class="built_in">set</span> your own capabilities)</span><br><span class="line"> (10) ECC (sign only)</span><br><span class="line"> (11) ECC (<span class="built_in">set</span> your own capabilities)</span><br><span class="line"> (12) ECC (encrypt only)</span><br><span class="line"> (13) Existing key</span><br><span class="line">Your selection? 10</span><br><span class="line"></span><br></pre></td></tr></tbody></table></figure><h3 id="1-2-4-选择子密钥算法"><a class="header-anchor" href="#1-2-4-选择子密钥算法">¶</a>1.2.4 选择子密钥算法</h3><div class="admonition warning"><p class="admonition-title">注意</p><p>NIST、Brainpool、secp256k1 具有一些安全隐患,不推荐使用。</p></div><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">Please <span class="keyword">select</span> <span class="built_in">which</span> elliptic curve you want:</span><br><span class="line"> (1) Curve 25519 *default*</span><br><span class="line"> (2) Curve 448</span><br><span class="line"> (3) NIST P-256</span><br><span class="line"> (4) NIST P-384</span><br><span class="line"> (5) NIST P-521</span><br><span class="line"> (6) Brainpool P-256</span><br><span class="line"> (7) Brainpool P-384</span><br><span class="line"> (8) Brainpool P-512</span><br><span class="line"> (9) secp256k1</span><br><span class="line">Your selection? 1</span><br></pre></td></tr></tbody></table></figure><blockquote><p>设定过期时间即可生成子密钥</p></blockquote><h2 id="1-3-设置-git-签名"><a class="header-anchor" href="#1-3-设置-git-签名">¶</a>1.3 设置 git 签名</h2><h3 id="1-3-1-本地-git-签名设置"><a class="header-anchor" href="#1-3-1-本地-git-签名设置">¶</a>1.3.1 本地 git 签名设置</h3><p>这里我们用子密钥来签名</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">## 查看子密钥的 keyid</span></span><br><span class="line">gpg --list-keys --keyid-format=long </span><br><span class="line"></span><br><span class="line"><span class="comment">## git 设置签名密钥</span></span><br><span class="line">git config --global user.signingkey <sub-key-id></span><br><span class="line"><span class="comment">## 设置每次commit自动签名</span></span><br><span class="line">git config --global commit.gpgsign <span class="literal">true</span></span><br></pre></td></tr></tbody></table></figure><h3 id="1-3-2-Github-公钥设置"><a class="header-anchor" href="#1-3-2-Github-公钥设置">¶</a>1.3.2 Github 公钥设置</h3><p>首先导出你的公钥,用于验证签名</p><blockquote><p>这里 --armor 导出公钥为 ASCII 格式</p></blockquote><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gpg --armor --<span class="built_in">export</span> <sub-key-id></span><br></pre></td></tr></tbody></table></figure><ul><li>点击这里添加你的 Github 公钥: <a href="https://github.com/settings/gpg/new">https://github.com/settings/gpg/new</a></li></ul><p>添加完成后,你的提交就会被标记为 <code>Verified</code>。</p><div class="admonition error"><p class="admonition-title">注意</p><p>如果签名失败,请在环境变量中指定 <code>GPG_TTY</code>, 具体原因参考 <sup id="fnref:2"><a href="#fn:2" rel="footnote"><span class="hint--top hint--error hint--medium hint--rounded hint--bounce" aria-label="[gpg: signing failed: Inappropriate ioctl for device macOS](https://gist.github.com/repodevs/a18c7bb42b2ab293155aca889d447f1b)">[2]</span></a></sup>。</p><p><code>export GPG_TTY=$(tty)</code></p></div><h2 id="1-4-常用-GPG-命令"><a class="header-anchor" href="#1-4-常用-GPG-命令">¶</a>1.4 常用 GPG 命令</h2><p>列出所有密钥: <code>gpg --list-keys</code></p><h2 id="1-5-参考资料"><a class="header-anchor" href="#1-5-参考资料">¶</a>1.5 参考资料</h2><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;"><a href="https://idawnlight.com/2022/gpg-key-rotation-notes/">GPG 密钥轮换小记</a><a href="#fnref:1" rev="footnote"> ↩</a></span></li><li id="fn:2"><span style="display: inline-block; vertical-align: top; padding-right: 10px; margin-left: -40px">2.</span><span style="display: inline-block; vertical-align: top; margin-left: 10px;"><a href="https://gist.github.com/repodevs/a18c7bb42b2ab293155aca889d447f1b">gpg: signing failed: Inappropriate ioctl for device macOS</a><a href="#fnref:2" rev="footnote"> ↩</a></span></li></ol></div></div>]]></content>
<summary type="html"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><h2 id="1-1-创建自己的-GPG-密钥"><a class="header-anchor" href="#1-1-创建自己的-GPG-密钥">¶</a>1.1 创建自己的 GPG 密钥</h2>
<p>执行一下命令选择加密算法,并完善相关信息。</p>
<div class="admonition todo"><p class="admonition-title">步骤简介
</p><ol>
<li>选择加密算法 (RSA 签名)</li>
<li> 设置密钥长度 (4096)</li>
<li> 设置密钥有效期 (1y),这是确保安全的最后防线</li>
<li>设置用户姓名、邮箱、注释(最好不要用常用邮箱,避免垃圾邮件骚扰)</li>
</ol>
</div>
<h3 id="1-1-1-运行-gpg-开始生成密钥"><a class="header-anchor" href="#1-1-1-运行-gpg-开始生成密钥">¶</a>1.1.1 运行 gpg 开始生成密钥</h3>
<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gpg --full-generate-key</span><br></pre></td></tr></tbody></table></figure>
<blockquote>
<p>输出如下,这里选择 4</p>
</blockquote>
<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">gpg (GnuPG) 2.2.27; Copyright (C) 2021 Free Software Foundation, Inc.</span><br><span class="line">This is free software: you are free to change and redistribute it.</span><br><span class="line">There is NO WARRANTY, to the extent permitted by law.</span><br><span class="line"></span><br><span class="line">Please <span class="keyword">select</span> what kind of key you want:</span><br><span class="line"> (1) RSA and RSA (default)</span><br><span class="line"> (2) DSA and Elgamal</span><br><span class="line"> (3) DSA (sign only)</span><br><span class="line"> (4) RSA (sign only)</span><br><span class="line"> (14) Existing key from card</span><br></pre></td></tr></tbody></table></figure>
<blockquote>
<p>这里我们生成的是主密钥,只负责分发子密钥,因此只需要具有签名功能即可<br>
这里我选择 4. RSA,有如下几个原因</p>
<ul>
<li>RSA 久经验证,是行业标准。</li>
<li>相关研究认为更长的 RSA,参考此论文: <a href="https://eprint.iacr.org/2015/1018.pdf">A RIDDLE WRAPPED IN AN ENIGMA</a>。</li>
<li>RSA 在各个平台上都有很好的支持。</li>
</ul>
</blockquote>
<h3 id="1-1-2-设置密钥长度"><a class="header-anchor" href="#1-1-2-设置密钥长度">¶</a>1.1.2 设置密钥长度</h3></summary>
<category term="Tool" scheme="https://uocat.com/categories/Tool/"/>
<category term="gpg" scheme="https://uocat.com/tags/gpg/"/>
<category term="signing-commits" scheme="https://uocat.com/tags/signing-commits/"/>
</entry>
<entry>
<title>chrome-allow-devonthink</title>
<link href="https://uocat.com/posts/222f/"/>
<id>https://uocat.com/posts/222f/</id>
<published>2023-08-07T01:56:15.000Z</published>
<updated>2024-08-15T00:40:16.441Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><h2 id="1-1-取消Chrome中打开Devonthink的弹窗"><a class="header-anchor" href="#1-1-取消Chrome中打开Devonthink的弹窗">¶</a>1.1 取消 Chrome 中打开 Devonthink 的弹窗</h2><p>我在使用 Devonthink 的时候,经常会遇到一个问题,就是在 Chrome 中点击 Devonthink 的链接,会弹出一个提示框,让我选择是否允许打开 Devonthink。</p><h3 id="1-1-1-原因"><a class="header-anchor" href="#1-1-1-原因">¶</a>1.1.1 原因</h3><pre><code>出现这个问题的原因参见是Chrome商业版策略设置,对不信任的协议进行弹窗提示。</code></pre><blockquote><p>参见 <a href="https://chromeenterprise.google/policies/?policy=URLAllowlist">URLAllowlist</a></p></blockquote><h3 id="1-1-2-解决方案"><a class="header-anchor" href="#1-1-2-解决方案">¶</a>1.1.2 解决方案</h3><pre><code>在 Mac 的 URLAllowlist 中添加要允许的协议即可,对DEVONThink其协议为 `x-devonthink://*`,所以在Mac中执行以下命令即可解决问题。</code></pre><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">## Mac</span></span><br><span class="line">defaults write com.google.Chrome URLAllowlist -array-add <span class="string">'x-devonthink://*'</span></span><br></pre></td></tr></tbody></table></figure><blockquote><p>Linux 的配置方案参考 StackOverflow 问答:<br><a href="https://askubuntu.com/questions/1324149/how-to-configure-policies-preferences-for-chromium">how-to-configure-policies-preferences-for-chromium</a></p></blockquote>]]></content>
<summary type="html">disable the chrome alert when open devonthink</summary>
<category term="Tool" scheme="https://uocat.com/categories/Tool/"/>
<category term="devonthink" scheme="https://uocat.com/tags/devonthink/"/>
<category term="chrome" scheme="https://uocat.com/tags/chrome/"/>
</entry>
<entry>
<title>top-password-2023</title>
<link href="https://uocat.com/posts/606a/"/>
<id>https://uocat.com/posts/606a/</id>
<published>2023-08-06T02:44:36.000Z</published>
<updated>2024-08-15T00:40:16.441Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><h2 id="1-1-TopPassword-2023"><a class="header-anchor" href="#1-1-TopPassword-2023">¶</a>1.1 TopPassword 2023</h2><p>收集了我的服务器在线期间被扫描的 <code>Top10</code> 密码,仅供参考。</p><!-- ![](https://uocat.com/images/6355637b8d5a92ba4c291c1f4cf8aa95.jpg) --><figure class="highlight txt"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"> Mon Nov 13 01:13:50 PM UTC 2023</span><br><span class="line"> ┌ ┐</span><br><span class="line"> 123456 ┤■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 2022.0</span><br><span class="line"> 1234 ┤■■■■■■■■■■■■■■■■■■ 1118.0</span><br><span class="line"> admin ┤■■■■■■■■■■■■■■■ 954.0</span><br><span class="line"> root ┤■■■■■■■■■■■■■■■ 918.0</span><br><span class="line"> 123 ┤■■■■■■■■■■■■■ 818.0</span><br><span class="line"> test ┤■■■■■■■■■■■■ 745.0</span><br><span class="line"> 12345 ┤■■■■■■■■■■■■ 743.0</span><br><span class="line">password ┤■■■■■■■■■■■ 701.0</span><br><span class="line"> toor ┤■■■■■■■■■■ 602.0</span><br><span class="line"> qwerty ┤■■■■■■■■■ 567.0</span><br><span class="line"> └ ┘</span><br></pre></td></tr></tbody></table></figure><h2 id="1-2-Generate-command"><a class="header-anchor" href="#1-2-Generate-command">¶</a>1.2 Generate command</h2><p>执行如下命令即可生成上述图表。</p><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">grep <span class="string">'authentication for user.*with password'</span> log.txt | \</span><br><span class="line"> awk <span class="string">'{print $10}'</span> | \</span><br><span class="line"> <span class="built_in">sort</span> | \</span><br><span class="line"> <span class="built_in">uniq</span> -c | \</span><br><span class="line"> <span class="built_in">sort</span> -nrk1 | \</span><br><span class="line"> <span class="built_in">head</span> -n10 | \</span><br><span class="line"> awk <span class="string">'{print $2, $1}'</span> | \</span><br><span class="line"> uplot bar -d <span class="string">' '</span> -t <span class="string">"`date`"</span></span><br></pre></td></tr></tbody></table></figure><blockquote><p>uplot 是一个开源命令行绘图工具,参见此链接 <a href="https://github.com/red-data-tools/YouPlot">YouPlot</a></p></blockquote>]]></content>
<summary type="html"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><h2 id="1-1-TopPassword-2023"><a class="header-anchor" href="#1-1-TopPassword-2023">¶</a>1.1 TopPassword 2023</h2>
<p>收集了我的服务器在线期间被扫描的 <code>Top10</code> 密码,仅供参考。</p>
<!-- ![](https://uocat.com/images/6355637b8d5a92ba4c291c1f4cf8aa95.jpg) -->
<figure class="highlight txt"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"> Mon Nov 13 01:13:50 PM UTC 2023</span><br><span class="line"> ┌ ┐</span><br><span class="line"> 123456 ┤■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ 2022.0</span><br><span class="line"> 1234 ┤■■■■■■■■■■■■■■■■■■ 1118.0</span><br><span class="line"> admin ┤■■■■■■■■■■■■■■■ 954.0</span><br><span class="line"> root ┤■■■■■■■■■■■■■■■ 918.0</span><br><span class="line"> 123 ┤■■■■■■■■■■■■■ 818.0</span><br><span class="line"> test ┤■■■■■■■■■■■■ 745.0</span><br><span class="line"> 12345 ┤■■■■■■■■■■■■ 743.0</span><br><span class="line">password ┤■■■■■■■■■■■ 701.0</span><br><span class="line"> toor ┤■■■■■■■■■■ 602.0</span><br><span class="line"> qwerty ┤■■■■■■■■■ 567.0</span><br><span class="line"> └ ┘</span><br></pre></td></tr></tbody></table></figure>
<h2 id="1-2-Generate-command"><a class="header-anchor" href="#1-2-Generate-command">¶</a>1.2 Generate command</h2>
<p>执行如下命令即可生成上述图表。</p>
<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">grep <span class="string">'authentication for user.*with password'</span> log.txt | \</span><br><span class="line"> awk <span class="string">'{print $10}'</span> | \</span><br><span class="line"> <span class="built_in">sort</span> | \</span><br><span class="line"> <span class="built_in">uniq</span> -c | \</span><br><span class="line"> <span class="built_in">sort</span> -nrk1 | \</span><br><span class="line"> <span class="built_in">head</span> -n10 | \</span><br><span class="line"> awk <span class="string">'{print $2, $1}'</span> | \</span><br><span class="line"> uplot bar -d <span class="string">' '</span> -t <span class="string">"`date`"</span></span><br></pre></td></tr></tbody></table></figure>
<blockquote>
<p>uplot 是一个开源命令行绘图工具,参见此链接 <a href="https://github.com/red-data-tools/YouPlot">YouPlot</a></p>
</blockquote>
</summary>
<category term="Informantion" scheme="https://uocat.com/categories/Informantion/"/>
<category term="top-password" scheme="https://uocat.com/tags/top-password/"/>
<category term="2023" scheme="https://uocat.com/tags/2023/"/>
</entry>
<entry>
<title>Docker 常见问题</title>
<link href="https://uocat.com/posts/5954/"/>
<id>https://uocat.com/posts/5954/</id>
<published>2023-07-24T21:40:29.000Z</published>
<updated>2024-08-15T00:40:16.441Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><h2 id="1-1-Docer-常见问题"><a class="header-anchor" href="#1-1-Docer-常见问题">¶</a>1.1 >> Docer 常见问题</h2><h3 id="1-1-1-CI-CD-如何利用已有-Image-缓存"><a class="header-anchor" href="#1-1-1-CI-CD-如何利用已有-Image-缓存">¶</a>1.1.1 CI/CD 如何利用已有 Image 缓存</h3><p><strong>背景</strong>: 在流水线构建中,每次都可能是一个新的环境,想要利用已有镜像的缓存</p><div class="admonition todo"><p class="admonition-title">解决方案</p><p>通过每次拉取相关镜像,并指定将其作为缓存即可,同时减小 push 的大小。</p></div><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">docker pull <span class="variable">$BASE_IMAGE</span>` || <span class="built_in">echo</span> <span class="string">"no image"</span></span><br><span class="line">docker build --cache-from <span class="variable">$BASE_IMAGE</span> -t mytag</span><br></pre></td></tr></tbody></table></figure>]]></content>
<summary type="html"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><h2 id="1-1-Docer-常见问题"><a class="header-anchor" href="#1-1-Docer-常见问题">¶</a>1.1 &gt;&gt; Docer 常见问题</h2>
<h3 id="1-1-1-CI-CD-如何利用已有-Image-缓存"><a class="header-anchor" href="#1-1-1-CI-CD-如何利用已有-Image-缓存">¶</a>1.1.1 CI/CD 如何利用已有 Image 缓存</h3>
<p><strong>背景</strong>: 在流水线构建中,每次都可能是一个新的环境,想要利用已有镜像的缓存</p>
<div class="admonition todo"><p class="admonition-title">解决方案
</p><p>通过每次拉取相关镜像,并指定将其作为缓存即可,同时减小 push 的大小。</p>
</div>
<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">docker pull <span class="variable">$BASE_IMAGE</span>` || <span class="built_in">echo</span> <span class="string">"no image"</span></span><br><span class="line">docker build --cache-from <span class="variable">$BASE_IMAGE</span> -t mytag</span><br></pre></td></tr></tbody></table></figure>
</summary>
<category term="IT" scheme="https://uocat.com/categories/IT/"/>
<category term="Tool" scheme="https://uocat.com/categories/IT/Tool/"/>
<category term="docker" scheme="https://uocat.com/tags/docker/"/>
<category term="cache" scheme="https://uocat.com/tags/cache/"/>
</entry>
<entry>
<title>ResilioSync Pro Key</title>
<link href="https://uocat.com/posts/3675/"/>
<id>https://uocat.com/posts/3675/</id>
<published>2023-07-23T05:58:25.000Z</published>
<updated>2024-08-15T00:40:16.441Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><h2 id="1-1-这是一个-ResilioSync-的-Pro-许可证"><a class="header-anchor" href="#1-1-这是一个-ResilioSync-的-Pro-许可证">¶</a>1.1 这是一个 ResilioSync 的 Pro 许可证</h2><div class="admonition warning"><p class="admonition-title">提供文件的 MD5 如下</p><p>faf812f3cc2de8988ccb310bad30a145</p></div><figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 拷贝执行下面的代码即可在当前目录生成许可证</span></span><br><span class="line">ResilioSyncProKey=<span class="string">"YnRvczFfZXlKeklqb2dJbTV4TmpSbU5HZ3JXRGh4V0hGaWFXUm9kRXR5VFdkTmNFVmFNSGRZYVVKTGJFeHdTV0Z3U0RVeE16a3lhSGRxTUZGcFFXSk9UVEZHZDJKR1dHcEpRMEZoVjJ3NFYzWmlkVnBQZW5wSVRYWm1OVFJMV1UxWFZHVnNWRlpqUzNKR1FVcFlNbVZVTUd0dFQybENNbTh6UTFCalZGZDJWV2xDTHpSc1RUbFFOMUZzYWxWU1Z6UkVNVkZOVWt0V2NFaHdhRzVJVnpJdlptZHFOMDVNYVRobU1uaE5hMU5ETkVSd1JWVnBRMHBYWkhwUFdYRkliVzFPTUZkT1VFdDZRV2c0UmtKb2FuTnZVVk5CYTFoS04wOVdTMGM1V0Vsa1ZUY3pXbk5sVldOeFdXMVdWVW8wV0RjMFMwNXdZbWxZWmswdmVtbHNVMnBJSzBVNVkzWk1aMDkyWWxwbFZqbENaWGx2ZUROd1QzcFJZVUpPZUZOUVQzRllXRXBUUkhFMWJWUmhSWE12V0dwcFZHdEpWMjF1VkhKdWRWSm5iMDFEWjBSQk9IZEJTM1JJWWpSdlZrZHVXbTFqZVU4eE5saG9RM2R2TDJWa2VIRnhaejA5SWl3Z0ltUWlPaUFpWlhsS2FtRjVTVFpKUTBwcFpFYzVlbGw2Um1aYVdHeExZVzFPTlZOVVdrcFJNSEJKVmxab1lWWXhSbGRVYWtac1ZsZG9XVlpyV2xkTk1VcFhVMnRXVlZKVVJsWlpWRVpYWkZaYWNWVnNVbXBOTVVwNVdrY3hkMUZzVWtWUlZGWldVWHBzTVZacmFHdFVWazV3VDBoc1VGRXpVak5VVjNoclZqSk9jazFJYUZWaGVsSTFWWHBPUTFReVVsaGlSM1JUWWxWd2IxWnROVXRVUmxKWlZWUldWRko2UlhwV1ZWVTFUVlp3ZFZkdFJsVldiVkoxVlZkNFNrMXNXWGxYYmtac1ltMTRiMVpXYUhkbGJFVjNUVlZLYW1KWGFFNVhWbFl3WkZad1ZWSllaRlJTYkVwT1ZXNXdVMkpHYkhCa1JYQlZWbFJHU2xZd1VuTldNa1Y1WkVaU2FsWkZSWGRVYlRWdVRVZEtjazFXWkU1U1IyTjNWbXhXWVZSc1NuSk5WemxxVWxWd01GbFZVbE5sUlRGSllrWmFXbUV4UlhoVmJURnpUVVV4U1ZwSVpFNWlSM2hWV1d4b2IxSXlUa1ZTYkU1c1ZsaGtlVlZzV205T1YwWkdVbFJPVW1KV1NuVldWRVpEWVVkS1NWWnJXa3hOVjNoWlZtcEdiMkZ0U2pWUFZXeFNWbFJzVDFsdE1UTk5iRTV6VWxSQ1lXRnNTbEZXYlhCQ1pVWlJkMVZyU2xwaGExWjVWMjB3TVdSVk5YVlhibFpTVFRKbmVsbDZSbGRUYXpsR1RWVTFhRk5IZUZGVVJFRTFUVVpPYzJKRldsZFRSa3BYVmxWYVNrMXNVa1JrUmtwWFVqSm9VbFl3VWxOamJHeHlUbGhHVGxKSGVGcFhibXd3WWpKR1ZrMVZlRlpXTVZwVlUzcENkMlJGTlRaVmJscFVZVzE0U1ZwRVFuSmxWa1owVFZWc2FsSkdXWGRXUmxaVFpFWnJlV1ZJY0U5V2JXaExWMVprYjFNeFpFZFNhMXBxVFVoU01WVnNhRmRsYkUxM1ZHcFNhVkpzU2pWVVZtUjNaRmRPU0dGRk5XRmxiRlYzV1cweE5HSkZPVlZoUnpsVVUwVldlVlZXYUU1TlYxWlpWV3hTVGxJeVRUVlZSazVLWXpCc1JGTnRjR0ZSTUdzeVUxVk9TMkpIVmxaalNHUmFZbFJHYUZwSGRITmpWMGw1V2tkNGJGWllRVEpYYTJONFZERktTRk5ZYkZaaVdHaExXVmN3TldKc1RsaE9WVGxQVmpCd01GWkhlRWRoYlVwVllVaENWVkpWTlVOWlZscHlaVmRTU1ZGdFJsSk5SM041VlRGV1QxTXlWa2RXYmxKWFZrVktWRmx0Y3pGamJHdDNWMnMxVG1KVlZqTmFWVll3WVcxV2MxTnNhRnBsYTBweVZGVmFSbVZHUm5SbFJtUlVVbFJXTlZVeFpITk5NVzkzWWtoU1YyRnNTbkZWVkVKeVRXeE9WbFZyY0d4U1ZGWkdWbXhTVjFSc1drZGhla0pWVmxaS1ExbDZRbk5TUms1MFkwZHdUazFWV25kV1JFcHpVVzFHV0ZOcVZrNVdlbFpRVm10YVlWVkdiRFpSYlRsb1lrWndlbFpzWkhOVVZrVjNVbTVDWVZKWGFIcGFSRVozVmtaT1ZWZHJjRkpOU0VGNlZqSjRiMU15Vm5SVFdHeFBWakpvY0ZWVVFuTmxiRTVXVkd0MGEySlZOVXBXVnpWM1UyMUdkRTlYTldGWFIzaE1XV3hrU21WWFZraGtSMFpZVWxoQ1ZsWXllR3RVTWxaWFkwWnNWbFl5ZUZGWlZsWkhZMFpTZEdNemFGVk5WbHBJVmpKNFlWWkdTa2hWYTA1VlYwaENWRll5ZUVkV2JGWlZVbXhvVTFaR1draFdWM1JYVlRGV1YxVnJXazlXVm5CWVZGWldkMVV4VWxoalJrNVZWbXhzTkZkcVNuTlVWa1YzVW01Q1dtVnJjRmhaVldSVFUxWlNXR0pHUW1oV1ZWa3dWMjE0Ym1ReVRYZGlSVkpVWWxob2MxVXdWa2RqUmxGNVlrVktiRlpVUmxaV1ZsSkhWVVphUmxaWWJGVk5Sa3BEV2tSS1lWVnNRbFZOUjJ4dFZWUXdPVWxwZDJkSmJXeDFXbTA0YVU5cFFqZEpiVGw1V2tkV2VWTlhVV2xQYVVGcFdWYzFhR1JYZUcxWlZ6VXhZVEphZFdJeWRIVmlWekY2VFVSWk5XTlhiek5PUTBselNVTkthR05wU1RaSlJFRnpTVU5LYkdWSVFXbFBhVUY1VFZSUk1VOVVSVEpQUkVGM1RFTkJhVmt6U214SmFtOW5UVlJSTkUxVVVYbE9lazAwVG5sM1owbHVUakpaTUd4clNXcHZaMGx1VGpWaWJVNVJZMjA0ZUVscGQyZEpiVTU2WkVOSk5rbERTblpNVjJNeFRsVTFlbE5IVGxkV1UwbHpTVU5LZW1SdFRrUmlNbEpzU1dwdlowbHVUalZpYlU1UlkyMDRhVXhEUVdsWk1teHJTV3B2WjBsdFpIRmFWMjk1WW1sSmMwbERTakJsV0VKc1NXcHZaMGx1UW14amJrNTJZbTFHYzBscGQyZEpiVGwzWkVoTmFVOXBRamRKYlZwMllrZFNiR05zVG14Wk0wcHNaRU5KTmtsRFNrSldNRkpPVkhwU1JsVXhUa0pVYkdoQ1YyeEtWRTFyTUhsT1JscENUbXRrUWxJeFNsaFdWRkpSVGxaWmFVeERRV2xqTWxab1pFaE5hVTlwUVhobVdEQnpTVU5LYkdWSVFXbFBhVUY1VFZSUk1VOVVSVEpQUkVGM1psRTlQU0o5"</span></span><br><span class="line"><span class="built_in">echo</span> <span class="variable">$ResilioSyncProKey</span> | <span class="built_in">base64</span> -d > ResilioSyncPro.btskey</span><br></pre></td></tr></tbody></table></figure>]]></content>
<summary type="html"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><h2 id="1-1-这是一个-ResilioSync-的-Pro-许可证"><a class="header-anchor" href="#1-1-这是一个-ResilioSync-的-Pro-许可证">¶</a>1.1 这是一个 ResilioSync 的 Pro 许可证</h2>
<div class="admonition warning"><p class="admonition-title">提供文件的 MD5 如下
</p><p>faf812f3cc2de8988ccb310bad30a145</p>
</div>
<figure class="highlight bash"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 拷贝执行下面的代码即可在当前目录生成许可证</span></span><br><span class="line">ResilioSyncProKey=<span class="string">"YnRvczFfZXlKeklqb2dJbTV4TmpSbU5HZ3JXRGh4V0hGaWFXUm9kRXR5VFdkTmNFVmFNSGRZYVVKTGJFeHdTV0Z3U0RVeE16a3lhSGRxTUZGcFFXSk9UVEZHZDJKR1dHcEpRMEZoVjJ3NFYzWmlkVnBQZW5wSVRYWm1OVFJMV1UxWFZHVnNWRlpqUzNKR1FVcFlNbVZVTUd0dFQybENNbTh6UTFCalZGZDJWV2xDTHpSc1RUbFFOMUZzYWxWU1Z6UkVNVkZOVWt0V2NFaHdhRzVJVnpJdlptZHFOMDVNYVRobU1uaE5hMU5ETkVSd1JWVnBRMHBYWkhwUFdYRkliVzFPTUZkT1VFdDZRV2c0UmtKb2FuTnZVVk5CYTFoS04wOVdTMGM1V0Vsa1ZUY3pXbk5sVldOeFdXMVdWVW8wV0RjMFMwNXdZbWxZWmswdmVtbHNVMnBJSzBVNVkzWk1aMDkyWWxwbFZqbENaWGx2ZUROd1QzcFJZVUpPZUZOUVQzRllXRXBUUkhFMWJWUmhSWE12V0dwcFZHdEpWMjF1VkhKdWRWSm5iMDFEWjBSQk9IZEJTM1JJWWpSdlZrZHVXbTFqZVU4eE5saG9RM2R2TDJWa2VIRnhaejA5SWl3Z0ltUWlPaUFpWlhsS2FtRjVTVFpKUTBwcFpFYzVlbGw2Um1aYVdHeExZVzFPTlZOVVdrcFJNSEJKVmxab1lWWXhSbGRVYWtac1ZsZG9XVlpyV2xkTk1VcFhVMnRXVlZKVVJsWlpWRVpYWkZaYWNWVnNVbXBOTVVwNVdrY3hkMUZzVWtWUlZGWldVWHBzTVZacmFHdFVWazV3VDBoc1VGRXpVak5VVjNoclZqSk9jazFJYUZWaGVsSTFWWHBPUTFReVVsaGlSM1JUWWxWd2IxWnROVXRVUmxKWlZWUldWRko2UlhwV1ZWVTFUVlp3ZFZkdFJsVldiVkoxVlZkNFNrMXNXWGxYYmtac1ltMTRiMVpXYUhkbGJFVjNUVlZLYW1KWGFFNVhWbFl3WkZad1ZWSllaRlJTYkVwT1ZXNXdVMkpHYkhCa1JYQlZWbFJHU2xZd1VuTldNa1Y1WkVaU2FsWkZSWGRVYlRWdVRVZEtjazFXWkU1U1IyTjNWbXhXWVZSc1NuSk5WemxxVWxWd01GbFZVbE5sUlRGSllrWmFXbUV4UlhoVmJURnpUVVV4U1ZwSVpFNWlSM2hWV1d4b2IxSXlUa1ZTYkU1c1ZsaGtlVlZzV205T1YwWkdVbFJPVW1KV1NuVldWRVpEWVVkS1NWWnJXa3hOVjNoWlZtcEdiMkZ0U2pWUFZXeFNWbFJzVDFsdE1UTk5iRTV6VWxSQ1lXRnNTbEZXYlhCQ1pVWlJkMVZyU2xwaGExWjVWMjB3TVdSVk5YVlhibFpTVFRKbmVsbDZSbGRUYXpsR1RWVTFhRk5IZUZGVVJFRTFUVVpPYzJKRldsZFRSa3BYVmxWYVNrMXNVa1JrUmtwWFVqSm9VbFl3VWxOamJHeHlUbGhHVGxKSGVGcFhibXd3WWpKR1ZrMVZlRlpXTVZwVlUzcENkMlJGTlRaVmJscFVZVzE0U1ZwRVFuSmxWa1owVFZWc2FsSkdXWGRXUmxaVFpFWnJlV1ZJY0U5V2JXaExWMVprYjFNeFpFZFNhMXBxVFVoU01WVnNhRmRsYkUxM1ZHcFNhVkpzU2pWVVZtUjNaRmRPU0dGRk5XRmxiRlYzV1cweE5HSkZPVlZoUnpsVVUwVldlVlZXYUU1TlYxWlpWV3hTVGxJeVRUVlZSazVLWXpCc1JGTnRjR0ZSTUdzeVUxVk9TMkpIVmxaalNHUmFZbFJHYUZwSGRITmpWMGw1V2tkNGJGWllRVEpYYTJONFZERktTRk5ZYkZaaVdHaExXVmN3TldKc1RsaE9WVGxQVmpCd01GWkhlRWRoYlVwVllVaENWVkpWTlVOWlZscHlaVmRTU1ZGdFJsSk5SM041VlRGV1QxTXlWa2RXYmxKWFZrVktWRmx0Y3pGamJHdDNWMnMxVG1KVlZqTmFWVll3WVcxV2MxTnNhRnBsYTBweVZGVmFSbVZHUm5SbFJtUlVVbFJXTlZVeFpITk5NVzkzWWtoU1YyRnNTbkZWVkVKeVRXeE9WbFZyY0d4U1ZGWkdWbXhTVjFSc1drZGhla0pWVmxaS1ExbDZRbk5TUms1MFkwZHdUazFWV25kV1JFcHpVVzFHV0ZOcVZrNVdlbFpRVm10YVlWVkdiRFpSYlRsb1lrWndlbFpzWkhOVVZrVjNVbTVDWVZKWGFIcGFSRVozVmtaT1ZWZHJjRkpOU0VGNlZqSjRiMU15Vm5SVFdHeFBWakpvY0ZWVVFuTmxiRTVXVkd0MGEySlZOVXBXVnpWM1UyMUdkRTlYTldGWFIzaE1XV3hrU21WWFZraGtSMFpZVWxoQ1ZsWXllR3RVTWxaWFkwWnNWbFl5ZUZGWlZsWkhZMFpTZEdNemFGVk5WbHBJVmpKNFlWWkdTa2hWYTA1VlYwaENWRll5ZUVkV2JGWlZVbXhvVTFaR1draFdWM1JYVlRGV1YxVnJXazlXVm5CWVZGWldkMVV4VWxoalJrNVZWbXhzTkZkcVNuTlVWa1YzVW01Q1dtVnJjRmhaVldSVFUxWlNXR0pHUW1oV1ZWa3dWMjE0Ym1ReVRYZGlSVkpVWWxob2MxVXdWa2RqUmxGNVlrVktiRlpVUmxaV1ZsSkhWVVphUmxaWWJGVk5Sa3BEV2tSS1lWVnNRbFZOUjJ4dFZWUXdPVWxwZDJkSmJXeDFXbTA0YVU5cFFqZEpiVGw1V2tkV2VWTlhVV2xQYVVGcFdWYzFhR1JYZUcxWlZ6VXhZVEphZFdJeWRIVmlWekY2VFVSWk5XTlhiek5PUTBselNVTkthR05wU1RaSlJFRnpTVU5LYkdWSVFXbFBhVUY1VFZSUk1VOVVSVEpQUkVGM1RFTkJhVmt6U214SmFtOW5UVlJSTkUxVVVYbE9lazAwVG5sM1owbHVUakpaTUd4clNXcHZaMGx1VGpWaWJVNVJZMjA0ZUVscGQyZEpiVTU2WkVOSk5rbERTblpNVjJNeFRsVTFlbE5IVGxkV1UwbHpTVU5LZW1SdFRrUmlNbEpzU1dwdlowbHVUalZpYlU1UlkyMDRhVXhEUVdsWk1teHJTV3B2WjBsdFpIRmFWMjk1WW1sSmMwbERTakJsV0VKc1NXcHZaMGx1UW14amJrNTJZbTFHYzBscGQyZEpiVGwzWkVoTmFVOXBRamRKYlZwMllrZFNiR05zVG14Wk0wcHNaRU5KTmtsRFNrSldNRkpPVkhwU1JsVXhUa0pVYkdoQ1YyeEtWRTFyTUhsT1JscENUbXRrUWxJeFNsaFdWRkpSVGxaWmFVeERRV2xqTWxab1pFaE5hVTlwUVhobVdEQnpTVU5LYkdWSVFXbFBhVUY1VFZSUk1VOVVSVEpQUkVGM1psRTlQU0o5"</span></span><br><span class="line"><span class="built_in">echo</span> <span class="variable">$ResilioSyncProKey</span> | <span class="built_in">base64</span> -d &gt; ResilioSyncPro.btskey</span><br></pre></td></tr></tbody></table></figure>
</summary>
<category term="License" scheme="https://uocat.com/categories/License/"/>
<category term="resiliosync" scheme="https://uocat.com/tags/resiliosync/"/>
<category term="btsync" scheme="https://uocat.com/tags/btsync/"/>
</entry>
<entry>
<title>epoll - 基本使用和细节</title>
<link href="https://uocat.com/posts/f84b/"/>
<id>https://uocat.com/posts/f84b/</id>
<published>2023-07-22T01:48:19.000Z</published>
<updated>2024-08-15T00:40:16.441Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><h2 id="1-1-epoll-默认设置"><a class="header-anchor" href="#1-1-epoll-默认设置">¶</a>1.1 epoll 默认设置</h2><ul><li>epoll 默认处于水平触发 </li></ul><h2 id="1-2-epoll-Events"><a class="header-anchor" href="#1-2-epoll-Events">¶</a>1.2 epoll Events</h2><p>参考 epoll.h <sup id="fnref:1"><a href="#fn:1" rel="footnote"><span class="hint--top hint--error hint--medium hint--rounded hint--bounce" aria-label="[epoll.h](https://sites.uclouvain.be/SystInfo/usr/include/sys/epoll.h.html)">[1]</span></a></sup></p><table><thead><tr><th> 事件</th><th>简介</th><th>补充</th></tr></thead><tbody><tr><td> EPOLLIN</td><td> 文件描述符可读。</td><td>当有数据可读时触发该事件。</td></tr><tr><td>EPOLLPRI</td><td> 有紧急数据可读。</td><td>用于处理带外数据(out-of-band data)或优先级数据。</td></tr><tr><td>EPOLLOUT</td><td> 文件描述符可写。</td><td>当可以写入数据时触发该事件。</td></tr><tr><td>EPOLLRDNORM</td><td> 有普通数据可读。</td><td>类似于 EPOLLIN,用于读取操作。</td></tr><tr><td>EPOLLRDBAND</td><td> 有带外数据可读。</td><td>类似于 EPOLLPRI,用于处理带外数据。</td></tr><tr><td>EPOLLWRNORM</td><td> 可写入普通数据。</td><td>类似于 EPOLLOUT,用于写入操作。</td></tr><tr><td>EPOLLWRBAND</td><td> 可写入带外数据。</td><td>通常情况下不使用此事件。</td></tr><tr><td>EPOLLMSG</td><td> 有消息数据可读。</td><td>通常情况下不使用此事件。</td></tr><tr><td>EPOLLERR</td><td> 文件描述符发生错误。</td><td>当文件描述符发生错误时触发该事件。</td></tr><tr><td>EPOLLHUP</td><td> 文件描述符挂起。</td><td>当文件描述符的连接关闭时触发该事件。</td></tr><tr><td>EPOLLRDHUP</td><td> 文件描述符被远程关闭连接或半关闭连接。</td><td>在较新的内核版本中使用,旧版本使用 EPOLLHUP 来表示。</td></tr><tr><td>EPOLLEXCLUSIVE</td><td> 独占模式。</td><td>用于实现边缘触发(Edge Triggered)。</td></tr><tr><td>EPOLLWAKEUP</td><td> 唤醒等待的线程。</td><td>用于唤醒被 epoll_wait 阻塞的线程。</td></tr><tr><td>EPOLLONESHOT</td><td> 单次事件监听。</td><td>事件触发后需要重新添加到 epoll 集合中。</td></tr><tr><td>EPOLLET</td><td> 边缘触发模式。</td><td>边缘触发模式仅在文件描述符状态变化时通知一次,与水平触发模式不同。</td></tr></tbody></table><div class="admonition warning"><p class="admonition-title">warning</p><p><code>EPOLLEXCLUSIVE</code>: 可以用于<strong>缓解</strong>多进程共享的 socket 惊群问题。但是同一进程两次 epoll_wait 之间,如果有新的连接到来并被其他进程处理,当前进程仍旧会被唤醒。<sup id="fnref:2"><a href="#fn:2" rel="footnote"><span class="hint--top hint--error hint--medium hint--rounded hint--bounce" aria-label="[探索惊群 ⑤ - nginx - NGX_EXCLUSIVE_EVENT](https://wenfh2020.com/2021/10/11/thundering-herd-nginx-epollexclusive/)">[2]</span></a></sup> <img src="https://uocat.com/images/7be7684c59893530743e1d322a105983.jpg" alt="epoll_image_1"></p></div><h2 id="1-3-epoll-相关函数"><a class="header-anchor" href="#1-3-epoll-相关函数">¶</a>1.3 epoll 相关函数</h2><p>epoll 在 kernel-6.4.1 中有 6 个函数,如下所示</p><figure class="highlight c++"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">extern</span> <span class="type">int</span> <span class="title">epoll_create</span> <span class="params">(<span class="type">int</span> __size)</span> __THROW</span>;</span><br><span class="line"><span class="function"><span class="keyword">extern</span> <span class="type">int</span> <span class="title">epoll_create1</span> <span class="params">()</span> <span class="comment">// 相比 epoll_create,增加了flags参数</span></span></span><br><span class="line"><span class="function"><span class="keyword">extern</span> <span class="type">int</span> <span class="title">epoll_ctl</span> <span class="params">(<span class="type">int</span> __epfd, <span class="type">int</span> __op, <span class="type">int</span> __fd,</span></span></span><br><span class="line"><span class="params"><span class="function"> <span class="keyword">struct</span> epoll_event *__event)</span> __THROW</span>;</span><br><span class="line"><span class="function"><span class="keyword">extern</span> <span class="type">int</span> <span class="title">epoll_wait</span> <span class="params">(<span class="type">int</span> __epfd, <span class="keyword">struct</span> epoll_event *__events,</span></span></span><br><span class="line"><span class="params"><span class="function"> <span class="type">int</span> __maxevents, <span class="type">int</span> __timeout)</span></span></span><br><span class="line"><span class="function"><span class="keyword">extern</span> <span class="type">int</span> <span class="title">epoll_pwait</span> <span class="params">()</span> <span class="comment">// 可以设置阻塞过程中忽略的信号,防止被打断</span></span></span><br><span class="line"><span class="function"><span class="keyword">extern</span> <span class="type">int</span> <span class="title">epoll_pwait2</span> <span class="params">()</span> <span class="comment">// 相比 epoll_wait 增加了超时控制</span></span></span><br></pre></td></tr></tbody></table></figure><h3 id="1-3-1-基本操作"><a class="header-anchor" href="#1-3-1-基本操作">¶</a>1.3.1 基本操作</h3><h4 id="1-3-1-1-创建一个-epoll-实例"><a class="header-anchor" href="#1-3-1-1-创建一个-epoll-实例">¶</a>1.3.1.1 创建一个 <code>epoll</code> 实例:</h4><figure class="highlight c++"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// #include <sys/epoll.h></span></span><br><span class="line"></span><br><span class="line"><span class="type">int</span> epollfd = <span class="built_in">epoll_create1</span>(<span class="number">0</span>);</span><br><span class="line"><span class="keyword">if</span> (epollfd == <span class="number">-1</span>) { <span class="comment">// 返回 -1 代表失败, 这里必须检查</span></span><br><span class="line"> <span class="built_in">perror</span>(<span class="string">"epoll_create1"</span>);</span><br><span class="line"> <span class="keyword">return</span> EXIT_FAILURE;</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><h4 id="1-3-1-2-epoll-ctl-使用"><a class="header-anchor" href="#1-3-1-2-epoll-ctl-使用">¶</a>1.3.1.2 epoll_ctl 使用</h4><figure class="highlight c++"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// #include <sys/socket.h></span></span><br><span class="line"><span class="comment">// #include <sys/types.h></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> DEFAULT_PORT 8080</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> MAX_EVENTS 10</span></span><br><span class="line"></span><br><span class="line"><span class="type">int</span> ret = <span class="number">0</span>;</span><br><span class="line"><span class="comment">// ========= 创建 servfd =========</span></span><br><span class="line"><span class="type">int</span> servfd = <span class="built_in">socket</span>(AF_INET <span class="comment">/* IPv4 */</span>, SOCK_STREAM, <span class="number">0</span>);</span><br><span class="line"><span class="keyword">if</span> (servfd == <span class="number">-1</span>) {</span><br><span class="line"> <span class="comment">// check error msg by errno</span></span><br><span class="line"> <span class="built_in">perror</span>(<span class="string">"socket error"</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">-1</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">struct</span> sockaddr_in servaddr;</span><br><span class="line"><span class="built_in">memset</span>(&servaddr, <span class="number">0</span>, <span class="built_in">sizeof</span>(servaddr));</span><br><span class="line">servaddr.sin_family = AF_INET;</span><br><span class="line">servaddr.sin_addr.s_addr = <span class="built_in">htonl</span>(INADDR_ANY);</span><br><span class="line">servaddr.sin_port = <span class="built_in">htons</span>(DEFAULT_PORT);</span><br><span class="line"></span><br><span class="line">ret = <span class="built_in">bind</span>(servfd, (<span class="keyword">struct</span> sockaddr*) &servaddr, <span class="built_in">sizeof</span>(servaddr));</span><br><span class="line"><span class="keyword">if</span> (ret == <span class="number">-1</span>) {</span><br><span class="line"> <span class="comment">// check error msg by errno</span></span><br><span class="line"> <span class="built_in">perror</span>(<span class="string">"bind error"</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Linux2.2之前, 1024 是未完成链接队列最大长度,</span></span><br><span class="line"><span class="comment"> * Linux2.2之后,表示完成连接等待应用处理的队列长度,如果需要制定等待连接的队列长度,请使用 tcp_max_syn_backlog (man 7 tcp 可以查看细节)</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line">ret = <span class="built_in">listen</span>(servfd, <span class="number">1024</span>); </span><br><span class="line"><span class="keyword">if</span> (ret == <span class="number">-1</span>) {</span><br><span class="line"> <span class="comment">// check error msg by errno</span></span><br><span class="line"> <span class="built_in">perror</span>(<span class="string">"listen error"</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">-1</span></span><br><span class="line">}</span><br><span class="line"><span class="comment">// ========= 创建 servfd 结束 =========</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * struct epoll_event</span></span><br><span class="line"><span class="comment"> * {</span></span><br><span class="line"><span class="comment"> * uint32_t events; // Epoll events</span></span><br><span class="line"><span class="comment"> * epoll_data_t data; // User data variable</span></span><br><span class="line"><span class="comment"> * } __EPOLL_PACKED;</span></span><br><span class="line"><span class="comment"> **/</span></span><br><span class="line"><span class="keyword">struct</span> epoll_event ev;</span><br><span class="line"><span class="keyword">struct</span> <span class="title class_">epoll_event</span> events[MAX_EVENTS];</span><br><span class="line"></span><br><span class="line">ev.event = EPOLLIN; <span class="comment">// set read event</span></span><br><span class="line">ev.data.fd = servfd;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (;;) {</span><br><span class="line"> <span class="type">int</span> nready = <span class="built_in">epoll_wait</span>(epollfd, events, MAX_EVENTS, <span class="number">-1</span>);</span><br><span class="line"> <span class="keyword">if</span> (nready == <span class="number">-1</span>) {</span><br><span class="line"> <span class="built_in">perror</span>(<span class="string">"epoll_wait error"</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i < nready; i++) {</span><br><span class="line"> <span class="keyword">if</span> (events[i].data.fd == servfd) {</span><br><span class="line"> <span class="type">int</span> connfd = <span class="built_in">accept</span>(servfd, (<span class="keyword">struct</span> sockaddr*) &cliaddr, &addrlen);</span><br><span class="line"> <span class="keyword">if</span> (connfd == <span class="number">-1</span>) {</span><br><span class="line"> <span class="built_in">perror</span>(<span class="string">"accept error"</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="built_in">setnonblocking</span>(connfd);</span><br><span class="line"> <span class="comment">// 设置 读事件监听、ET模式</span></span><br><span class="line"> ev.events = EPOLLIN | EPOLLET;</span><br><span class="line"> ev.data.fd = connfd;</span><br><span class="line"> <span class="comment">// 这里添加客户端的 fd 到epoll中</span></span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">epoll_ctl</span>(epollfd, EPOLL_CTL_ADD, connfd, &ev) == <span class="number">-1</span>) {</span><br><span class="line"> <span class="built_in">perror</span>(<span class="string">"epoll_ctl: EPOLL_CTL_ADD error"</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="comment">// pass</span></span><br><span class="line"> <span class="comment">// 这里处理客户端sock的事件</span></span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><h2 id="1-4-常见问题"><a class="header-anchor" href="#1-4-常见问题">¶</a>1.4 常见问题</h2><div class="admonition todo"><p class="admonition-title">挖坑</p><p>惊群效应、C10K、连接丢失</p></div><h2 id="1-5-引用"><a class="header-anchor" href="#1-5-引用">¶</a>1.5 引用</h2><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;"><a href="https://sites.uclouvain.be/SystInfo/usr/include/sys/epoll.h.html">epoll.h</a><a href="#fnref:1" rev="footnote"> ↩</a></span></li><li id="fn:2"><span style="display: inline-block; vertical-align: top; padding-right: 10px; margin-left: -40px">2. </span><span style="display: inline-block; vertical-align: top; margin-left: 10px;"><a href="https://wenfh2020.com/2021/10/11/thundering-herd-nginx-epollexclusive/">探索惊群 ⑤ - nginx - NGX_EXCLUSIVE_EVENT</a><a href="#fnref:2" rev="footnote"> ↩</a></span></li><li id="fn:3"><span style="display: inline-block; vertical-align: top; padding-right: 10px; margin-left: -40px">3.</span><span style="display: inline-block; vertical-align: top; margin-left: 10px;"><a href="https://man7.org/linux/man-pages/man7/epoll.7.html">epoll(7) - Linux manual page </a><a href="#fnref:3" rev="footnote"> ↩</a></span></li></ol></div></div>]]></content>
<summary type="html"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><h2 id="1-1-epoll-默认设置"><a class="header-anchor" href="#1-1-epoll-默认设置">¶</a>1.1 epoll 默认设置</h2>
<ul>
<li>epoll 默认处于水平触发 </li>
</ul>
<h2 id="1-2-epoll-Events"><a class="header-anchor" href="#1-2-epoll-Events">¶</a>1.2 epoll Events</h2>
<p>参考 epoll.h <sup id="fnref:1"><a href="#fn:1" rel="footnote"><span class="hint--top hint--error hint--medium hint--rounded hint--bounce" aria-label="[epoll.h](https://sites.uclouvain.be/SystInfo/usr/include/sys/epoll.h.html)
">[1]</span></a></sup></p>
<table>
<thead>
<tr>
<th> 事件</th>
<th>简介</th>
<th>补充</th>
</tr>
</thead>
<tbody>
<tr>
<td> EPOLLIN</td>
<td> 文件描述符可读。</td>
<td>当有数据可读时触发该事件。</td>
</tr>
<tr>
<td>EPOLLPRI</td>
<td> 有紧急数据可读。</td>
<td>用于处理带外数据(out-of-band data)或优先级数据。</td>
</tr>
<tr>
<td>EPOLLOUT</td>
<td> 文件描述符可写。</td>
<td>当可以写入数据时触发该事件。</td>
</tr>
<tr>
<td>EPOLLRDNORM</td>
<td> 有普通数据可读。</td>
<td>类似于 EPOLLIN,用于读取操作。</td>
</tr>
<tr>
<td>EPOLLRDBAND</td>
<td> 有带外数据可读。</td>
<td>类似于 EPOLLPRI,用于处理带外数据。</td>
</tr>
<tr>
<td>EPOLLWRNORM</td>
<td> 可写入普通数据。</td>
<td>类似于 EPOLLOUT,用于写入操作。</td>
</tr>
<tr>
<td>EPOLLWRBAND</td>
<td> 可写入带外数据。</td>
<td>通常情况下不使用此事件。</td>
</tr>
<tr>
<td>EPOLLMSG</td>
<td> 有消息数据可读。</td>
<td>通常情况下不使用此事件。</td>
</tr>
<tr>
<td>EPOLLERR</td>
<td> 文件描述符发生错误。</td>
<td>当文件描述符发生错误时触发该事件。</td>
</tr>
<tr>
<td>EPOLLHUP</td>
<td> 文件描述符挂起。</td>
<td>当文件描述符的连接关闭时触发该事件。</td>
</tr>
<tr>
<td>EPOLLRDHUP</td>
<td> 文件描述符被远程关闭连接或半关闭连接。</td>
<td>在较新的内核版本中使用,旧版本使用 EPOLLHUP 来表示。</td>
</tr>
<tr>
<td>EPOLLEXCLUSIVE</td>
<td> 独占模式。</td>
<td>用于实现边缘触发(Edge Triggered)。</td>
</tr>
<tr>
<td>EPOLLWAKEUP</td>
<td> 唤醒等待的线程。</td>
<td>用于唤醒被 epoll_wait 阻塞的线程。</td>
</tr>
<tr>
<td>EPOLLONESHOT</td>
<td> 单次事件监听。</td>
<td>事件触发后需要重新添加到 epoll 集合中。</td>
</tr>
<tr>
<td>EPOLLET</td>
<td> 边缘触发模式。</td>
<td>边缘触发模式仅在文件描述符状态变化时通知一次,与水平触发模式不同。</td>
</tr>
</tbody>
</table>
<div class="admonition warning"><p class="admonition-title">warning</p><p><code>EPOLLEXCLUSIVE</code>: 可以用于<strong>缓解</strong>多进程共享的 socket 惊群问题。但是同一进程两次 epoll_wait 之间,如果有新的连接到来并被其他进程处理,当前进程仍旧会被唤醒。<sup id="fnref:2"><a href="#fn:2" rel="footnote"><span class="hint--top hint--error hint--medium hint--rounded hint--bounce" aria-label="[探索惊群 ⑤ - nginx - NGX_EXCLUSIVE_EVENT](https://wenfh2020.com/2021/10/11/thundering-herd-nginx-epollexclusive/)
">[2]</span></a></sup> <img src="https://uocat.com/images/7be7684c59893530743e1d322a105983.jpg" alt="epoll_image_1"></p>
</div>
<h2 id="1-3-epoll-相关函数"><a class="header-anchor" href="#1-3-epoll-相关函数">¶</a>1.3 epoll 相关函数</h2>
<p>epoll 在 kernel-6.4.1 中有 6 个函数,如下所示</p>
<figure class="highlight c++"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">extern</span> <span class="type">int</span> <span class="title">epoll_create</span> <span class="params">(<span class="type">int</span> __size)</span> __THROW</span>;</span><br><span class="line"><span class="function"><span class="keyword">extern</span> <span class="type">int</span> <span class="title">epoll_create1</span> <span class="params">()</span> <span class="comment">// 相比 epoll_create,增加了flags参数</span></span></span><br><span class="line"><span class="function"><span class="keyword">extern</span> <span class="type">int</span> <span class="title">epoll_ctl</span> <span class="params">(<span class="type">int</span> __epfd, <span class="type">int</span> __op, <span class="type">int</span> __fd,</span></span></span><br><span class="line"><span class="params"><span class="function"> <span class="keyword">struct</span> epoll_event *__event)</span> __THROW</span>;</span><br><span class="line"><span class="function"><span class="keyword">extern</span> <span class="type">int</span> <span class="title">epoll_wait</span> <span class="params">(<span class="type">int</span> __epfd, <span class="keyword">struct</span> epoll_event *__events,</span></span></span><br><span class="line"><span class="params"><span class="function"> <span class="type">int</span> __maxevents, <span class="type">int</span> __timeout)</span></span></span><br><span class="line"><span class="function"><span class="keyword">extern</span> <span class="type">int</span> <span class="title">epoll_pwait</span> <span class="params">()</span> <span class="comment">// 可以设置阻塞过程中忽略的信号,防止被打断</span></span></span><br><span class="line"><span class="function"><span class="keyword">extern</span> <span class="type">int</span> <span class="title">epoll_pwait2</span> <span class="params">()</span> <span class="comment">// 相比 epoll_wait 增加了超时控制</span></span></span><br></pre></td></tr></tbody></table></figure></summary>
<category term="Linux" scheme="https://uocat.com/categories/Linux/"/>
<category term="Learn" scheme="https://uocat.com/categories/Linux/Learn/"/>
<category term="epoll" scheme="https://uocat.com/tags/epoll/"/>
<category term="network" scheme="https://uocat.com/tags/network/"/>
</entry>
<entry>
<title>Study RxCpp(1)</title>
<link href="https://uocat.com/posts/6fcf/"/>
<id>https://uocat.com/posts/6fcf/</id>
<published>2023-07-09T08:22:14.000Z</published>
<updated>2024-08-15T00:40:16.441Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><h2 id="1-1-仓库信息"><a class="header-anchor" href="#1-1-仓库信息">¶</a>1.1 仓库信息</h2><p>以下是本笔记所使用的 <code>RxCpp</code> 仓库及其版本等信息。</p><span id="more"></span><table><thead><tr><th>A</th><th>B</th></tr></thead><tbody><tr><td> 链接 </td><td><a href="https://github.com/ReactiveX/RxCpp/">https://github.com/ReactiveX/RxCpp/</a></td></tr><tr><td>commit</td><td>761b932a80e2be6e2b62d232e754bd96fc448946</td></tr></tbody></table><h2 id="1-2-项目信息"><a class="header-anchor" href="#1-2-项目信息">¶</a>1.2 项目信息</h2><p>为了学习 RxCpp,我们会实际使用 <code>RxCpp</code>,便于测试,加深理解。</p><h3 id="1-2-1-构建简单的CMake项目"><a class="header-anchor" href="#1-2-1-构建简单的CMake项目">¶</a>1.2.1 构建简单的 <code>CMake</code> 项目</h3><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="built_in">mkdir</span> rxcpp-study</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="built_in">cd</span> rxcpp-study</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash"><span class="built_in">touch</span> CMakeList.txt main.cpp</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">tree</span></span><br><span class="line">.</span><br><span class="line">├── CMakeLists.txt</span><br><span class="line">└── main.cpp</span><br></pre></td></tr></tbody></table></figure><blockquote><p>这是一个简单的项目结构,我们将会一步一步完善这个项目。</p></blockquote><h4 id="1-2-1-1-首先是-CMakeList-txt"><a class="header-anchor" href="#1-2-1-1-首先是-CMakeList-txt">¶</a>1.2.1.1 首先是 <code>CMakeList.txt</code></h4><figure class="highlight cmake"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">cmake_minimum_required</span>(VERSION <span class="number">3.25</span>)</span><br><span class="line"><span class="keyword">project</span>(rxcpp_study)</span><br><span class="line"></span><br><span class="line"><span class="keyword">set</span>(CMAKE_CXX_STANDARD <span class="number">17</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">add_executable</span>(rxcpp_study main.cpp)</span><br><span class="line"></span><br></pre></td></tr></tbody></table></figure><h4 id="1-2-1-2-接下来写一个简单的-main-cpp"><a class="header-anchor" href="#1-2-1-2-接下来写一个简单的-main-cpp">¶</a>1.2.1.2 接下来写一个简单的 main.cpp</h4><figure class="highlight c++"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><iostream></span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> std::cout << <span class="string">"Hello, World!"</span> << std::endl;</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><h4 id="1-2-1-3-运行这个项目"><a class="header-anchor" href="#1-2-1-3-运行这个项目">¶</a>1.2.1.3 运行这个项目</h4><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">首先创建一个 build 目录,避免污染源代码目录</span></span><br><span class="line">mkdir build && cd build</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">开始生成配置文件</span></span><br><span class="line">cmake ..</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">用 make 构建项目</span></span><br><span class="line">make</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">以上完成之后,可以得到 rxcpp_study</span></span><br><span class="line">./rxcpp_study</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">执行完毕之后应该有以下输出:</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">Hello, World!</span></span><br><span class="line"></span><br></pre></td></tr></tbody></table></figure><h3 id="1-2-2-导入RxCpp库"><a class="header-anchor" href="#1-2-2-导入RxCpp库">¶</a>1.2.2 导入 RxCpp 库</h3><h4 id="1-2-2-1-导入为第三方库"><a class="header-anchor" href="#1-2-2-1-导入为第三方库">¶</a>1.2.2.1 导入为第三方库</h4><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_"># </span><span class="language-bash">首先用git管理仓库</span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">首先创建一个 third_party 目录来统一管理第三方库</span></span><br><span class="line">mkdir third_party</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">接下来将 RxCpp 放到该目录</span> </span><br><span class="line">git submodule add https://github.com/ReactiveX/RxCpp/ third_party/RxCpp</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">刚 <span class="built_in">clone</span> 的 RxCpp是默认分支,可能与本笔记版本不同,我们切换到统一版本</span></span><br><span class="line">cd third_party/RxCpp</span><br><span class="line">git checkout 761b932a80e2be6e2b62d232e754bd96fc448946</span><br></pre></td></tr></tbody></table></figure><blockquote><p>现在我们已经将 <code>RxCpp</code> 加入到我们的项目中来,并通过 <code>git </code>管理该项目。</p></blockquote><h4 id="1-2-2-2-在-CMakeList-txt-中引用-RxCpp"><a class="header-anchor" href="#1-2-2-2-在-CMakeList-txt-中引用-RxCpp">¶</a>1.2.2.2 在 <code>CMakeList.txt</code> 中引用 <code>RxCpp</code></h4><p>只需在 <code>CMakeList.txt</code> 中增加两行即可使用 <code>RxCpp</code>。</p><figure class="highlight cmake"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">cmake_minimum_required</span>(VERSION <span class="number">3.25</span>)</span><br><span class="line"><span class="keyword">project</span>(rxcpp_study)</span><br><span class="line"></span><br><span class="line"><span class="keyword">set</span>(CMAKE_CXX_STANDARD <span class="number">17</span>)</span><br><span class="line"></span><br><span class="line"><span class="keyword">add_executable</span>(rxcpp_study main.cpp)</span><br><span class="line"><span class="comment">## 以下是导入RxCpp 的头文件</span></span><br><span class="line"><span class="keyword">target_include_directories</span>(rxcpp_study</span><br><span class="line"> PRIVATE <span class="string">"${CMAKE_CURRENT_SOURCE_DIR}/third_party/RxCpp/Rx/v2/src"</span>)</span><br></pre></td></tr></tbody></table></figure><h4 id="1-2-2-3-使用-RxCpp"><a class="header-anchor" href="#1-2-2-3-使用-RxCpp">¶</a>1.2.2.3 使用 <code>RxCpp</code></h4><p>在 <code>main.cpp</code> 中导入 <code>rxcpp/rx.hpp</code> 即可</p><figure class="highlight c++"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><iostream></span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string"><rxcpp/rx.hpp></span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="type">int</span> <span class="title">main</span><span class="params">()</span> </span>{</span><br><span class="line"> rxcpp::observable<>::<span class="built_in">range</span>(<span class="number">1</span>, <span class="number">5</span>)</span><br><span class="line"> .<span class="built_in">as_blocking</span>()</span><br><span class="line"> .<span class="built_in">subscribe</span>([](<span class="type">int</span> value){ std::cout << value << std::endl;},</span><br><span class="line"> [](){});</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></tbody></table></figure><blockquote><p>运行结果如下:<br>1<br>2<br>3<br>4<br>5</p></blockquote>]]></content>
<summary type="html"><h2 id="1-1-仓库信息"><a class="header-anchor" href="#1-1-仓库信息">¶</a>1.1 仓库信息</h2>
<p>以下是本笔记所使用的 <code>RxCpp</code> 仓库及其版本等信息。</p></summary>
<category term="Learn" scheme="https://uocat.com/categories/Learn/"/>
<category term="c++" scheme="https://uocat.com/tags/c/"/>
</entry>
<entry>
<title>熊猫拿铁配置无线网卡</title>
<link href="https://uocat.com/posts/8231/"/>
<id>https://uocat.com/posts/8231/</id>
<published>2022-07-24T21:40:29.000Z</published>
<updated>2024-08-15T00:40:16.441Z</updated>
<content type="html"><![CDATA[<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><h2 id="1-1-熊猫拿铁配置无线网卡"><a class="header-anchor" href="#1-1-熊猫拿铁配置无线网卡">¶</a>1.1 熊猫拿铁配置无线网卡</h2><h3 id="1-1-1-背景"><a class="header-anchor" href="#1-1-1-背景">¶</a>1.1.1 背景</h3><p>入手了一个熊猫拿铁板子,无奈自带的 <code>Wi-Fi</code> 传输速率感人,遂决定增加一块无线网卡<code>水星UD6S</code>。</p><h3 id="1-1-2-安装驱动"><a class="header-anchor" href="#1-1-2-安装驱动">¶</a>1.1.2 安装驱动</h3><p>首先安装 <code>DKSM</code>,<code>DKSM</code>(<code>Dynamic Kernel Module Support</code>)是用来生成内核模块的框架,每次更新内核时,都会自动编译相关模块,保证更新后驱动的可用性。</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install -y dkms</span><br></pre></td></tr></tbody></table></figure><h3 id="1-1-3-编译驱动"><a class="header-anchor" href="#1-1-3-编译驱动">¶</a>1.1.3 编译驱动</h3><p>驱动使用了开源项目 <a href="https://github.com/brektrou/rtl8821CU">rtl8821CU</a>, 执行下面的命令,等待安装完成即可</p><figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash"><span class="comment"># 安装当前版本内核头文件</span></span></span><br><span class="line">sudo apt-get install -y linux-headers-`uname -r` </span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash"><span class="comment"># 安装相关工具</span></span></span><br><span class="line">sudo apt-get install -y make gcc bc git</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash"><span class="comment"># 克隆代码,然后编译安装</span></span></span><br><span class="line">git clone https://github.com/brektrou/rtl8821CU.git</span><br><span class="line">cd rtl8821CU && sudo bash dkms-install.sh</span><br></pre></td></tr></tbody></table></figure><h3 id="1-1-4-配置-wifi"><a class="header-anchor" href="#1-1-4-配置-wifi">¶</a>1.1.4 配置 wifi</h3><p>这里使用 <code>NetworkManager</code> 管理 <code>Wi-Fi</code></p><ul><li><p>首先安装 <code>NetworkManger</code></p> <figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install -y network-manager</span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash"><span class="comment"># 设置开机自启,并且立即启动 NetworkManager</span></span></span><br><span class="line">sudo systemctl enable --now NetworkManager</span><br></pre></td></tr></tbody></table></figure></li><li><p>查看可用设备</p> <figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">nmcli device</span></span><br><span class="line">DEVICE TYPE STATE CONNECTION</span><br><span class="line">wlx23438 wifi disconnected --</span><br><span class="line">wlan0 wifi disconnected --</span><br></pre></td></tr></tbody></table></figure><blockquote><p>这里有两个 wifi 设备,名字分别为 <code>wlx23438</code> 和 <code>wlan0</code></p></blockquote></li><li><p>查看可用 wifi</p> <figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">$ </span><span class="language-bash">nmcli device wifi</span></span><br><span class="line">IN-USE SSID MODE CHAN RATE SIGNAL BARS SECURITY</span><br><span class="line"> angell Infra 11 130 Mbit/s 49 ▂▄__ WPA2</span><br><span class="line"> 1104 Infra 1 270 Mbit/s 45 ▂▄__ WPA1 WPA2</span><br><span class="line"> -- Infra 1 270 Mbit/s 45 ▂▄__ WPA1 WPA2</span><br><span class="line"> HUAWEI-0H1G91 Infra 1 130 Mbit/s 45 ▂▄__ WPA2</span><br><span class="line"> Xiaomi_4892 Infra 11 270 Mbit/s 45 ▂▄__ WPA1 WPA2</span><br><span class="line"> CMCC-xjcf_5G Infra 1 130 Mbit/s 44 ▂▄__ WPA1 WPA2</span><br></pre></td></tr></tbody></table></figure></li><li><p>连接 wifi</p> <figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo nmcli device wifi connect "your-ssid" password "your-password" ifname wlx23438</span><br></pre></td></tr></tbody></table></figure><p>这里我们指定要链接的 <code>wifi</code> 和<code>密码</code>,并要求使用设备 <code>wlx23438</code>。</p></li></ul>]]></content>
<summary type="html"><link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/hint.css/2.4.1/hint.min.css"><h2 id="1-1-熊猫拿铁配置无线网卡"><a class="header-anchor" href="#1-1-熊猫拿铁配置无线网卡">¶</a>1.1 熊猫拿铁配置无线网卡</h2>
<h3 id="1-1-1-背景"><a class="header-anchor" href="#1-1-1-背景">¶</a>1.1.1 背景</h3>
<p>入手了一个熊猫拿铁板子,无奈自带的 <code>Wi-Fi</code> 传输速率感人,遂决定增加一块无线网卡<code>水星UD6S</code>。</p>
<h3 id="1-1-2-安装驱动"><a class="header-anchor" href="#1-1-2-安装驱动">¶</a>1.1.2 安装驱动</h3>
<p>首先安装 <code>DKSM</code>,<code>DKSM</code>(<code>Dynamic Kernel Module Support</code>)是用来生成内核模块的框架,每次更新内核时,都会自动编译相关模块,保证更新后驱动的可用性。</p>
<figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install -y dkms</span><br></pre></td></tr></tbody></table></figure>
<h3 id="1-1-3-编译驱动"><a class="header-anchor" href="#1-1-3-编译驱动">¶</a>1.1.3 编译驱动</h3>
<p>驱动使用了开源项目 <a href="https://github.com/brektrou/rtl8821CU">rtl8821CU</a>, 执行下面的命令,等待安装完成即可</p>
<figure class="highlight shell"><table><tbody><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">#</span><span class="language-bash"><span class="comment"># 安装当前版本内核头文件</span></span></span><br><span class="line">sudo apt-get install -y linux-headers-`uname -r` </span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash"><span class="comment"># 安装相关工具</span></span></span><br><span class="line">sudo apt-get install -y make gcc bc git</span><br><span class="line"><span class="meta prompt_"></span></span><br><span class="line"><span class="meta prompt_">#</span><span class="language-bash"><span class="comment"># 克隆代码,然后编译安装</span></span></span><br><span class="line">git clone https://github.com/brektrou/rtl8821CU.git</span><br><span class="line">cd rtl8821CU &amp;&amp; sudo bash dkms-install.sh</span><br></pre></td></tr></tbody></table></figure></summary>
<category term="IT" scheme="https://uocat.com/categories/IT/"/>
<category term="linux,server" scheme="https://uocat.com/tags/linux-server/"/>
</entry>
</feed>