-
Notifications
You must be signed in to change notification settings - Fork 0
/
feed.json
172 lines (172 loc) · 299 KB
/
feed.json
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
{
"version": "https://jsonfeed.org/version/1",
"title": "陌上尘归处",
"subtitle": "人生无根蒂,飘如陌上尘",
"icon": "http://yuanmxc.site/images/favicon.ico",
"description": "不乱于心,不困于情;不畏将来,不念过往。",
"home_page_url": "http://yuanmxc.site",
"items": [
{
"id": "http://yuanmxc.site/%E7%AC%94%E8%AE%B0/ArchLinux%20%E5%AE%89%E8%A3%85%20CUDA%20%E3%80%81TensorRT%20%20%E5%92%8CTensorRT-YOLO%20%E8%AE%B0%E5%BD%95/",
"url": "http://yuanmxc.site/%E7%AC%94%E8%AE%B0/ArchLinux%20%E5%AE%89%E8%A3%85%20CUDA%20%E3%80%81TensorRT%20%20%E5%92%8CTensorRT-YOLO%20%E8%AE%B0%E5%BD%95/",
"title": "",
"date_published": "2024-07-20T05:11:46.531Z",
"content_html": "<h1 id=\"archlinux-安装-cuda-tensorrt-和tensorrt-yolo-记录\"><a class=\"anchor\" href=\"#archlinux-安装-cuda-tensorrt-和tensorrt-yolo-记录\">#</a> ArchLinux 安装 CUDA 、TensorRT 和 TensorRT-YOLO 记录</h1>\n<h2 id=\"安装tensorrt-和-cuda\"><a class=\"anchor\" href=\"#安装tensorrt-和-cuda\">#</a> 安装 TensorRT 和 CUDA</h2>\n<ol>\n<li>\n<p>根据 <span class=\"exturl\" data-url=\"aHR0cHM6Ly9naXRodWIuY29tL2xhdWdoMTIzMjEvVGVuc29yUlQtWU9MTw==\">TensorRT-YOLO</span> Github 页面使用教程中的 <span class=\"exturl\" data-url=\"aHR0cHM6Ly9naXRodWIuY29tL2xhdWdoMTIzMjEvVGVuc29yUlQtWU9MTy9ibG9iL21haW4vZG9jcy9jbi9idWlsZF9hbmRfaW5zdGFsbC5tZA==\">快速编译安装 </span> 进行,编译前首先要安装 xmake CUDA 和 TensorRT。</p>\n<p>xmake 简单,只需要:</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>yay <span class=\"token parameter variable\">-S</span> xmake</pre></td></tr></table></figure></li>\n<li>\n<p>安装 CUDA 和 TensorRT</p>\n<ul>\n<li>\n<p>安装 CUDA :</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>yay <span class=\"token parameter variable\">-S</span> cuda</pre></td></tr></table></figure><p>版本为最新版 cuda-12.5.1-1</p>\n</li>\n<li>\n<p>在安装 TensorRT :</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>yay <span class=\"token parameter variable\">-S</span> tensorrt</pre></td></tr></table></figure><p>遇到错误,AUR 提供的 TensorRT 目前仍是 10.1.0.27-1 版本,而 CUDA 和 TensorRT 的版本必须是一一对应的,TensorRT 使用 CUDA 。</p>\n<p>吐槽一下,“适配” 这件事做的不是很好,摘自 Archlinux AUR 的 <span class=\"exturl\" data-url=\"aHR0cHM6Ly9hdXIuYXJjaGxpbnV4Lm9yZy9wYWNrYWdlcy90ZW5zb3JydA==\">tensorrt</span> 软件包下一个老哥的评论(已置顶):</p>\n<blockquote>\n<p>它(指 AUR 提供的 tensorrt 10.1.0.27-1)无法针对 cuda 12.5 构建,将 cuda 降级到 12.4.1,它将起作用。长话短说:关于这一点有两个问题。首先,tensorrt 10.0.1 显然不支持 cuda 12.5,正如您在<span class=\"exturl\" data-url=\"aHR0cHM6Ly9naXRodWIuY29tL05WSURJQS9UZW5zb3JSVC90cmVlL3YxMC4wLjE/dGFiPXJlYWRtZS1vdi1maWxlI29wdGlvbmFsLS0taWYtbm90LXVzaW5nLXRlbnNvcnJ0LWNvbnRhaW5lci1zcGVjaWZ5LXRoZS10ZW5zb3JydC1nYS1yZWxlYXNlLWJ1aWxkLXBhdGg=\">上游文档</span>中看到的那样。其次,官方仓库中提供的当前版本的 nvidia 驱动程序不支持 cuda 12.5(cuda 12.5 是在没有支持它的驱动程序的情况下推送的),您可以在<span class=\"exturl\" data-url=\"aHR0cHM6Ly9naXRsYWIuYXJjaGxpbnV4Lm9yZy9hcmNobGludXgvcGFja2FnaW5nL3BhY2thZ2VzL2N1ZGEvLS9pc3N1ZXMvNw==\">此链接</span>的 Arch Linux cuda 软件包问题页面中阅读更多详细信息。</p>\n</blockquote>\n<p>两个解决办法:</p>\n<ol>\n<li>\n<p>使用 downgrade 降级 CUDA 到 12.4.1 :</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">sudo</span> downgrade cuda</pre></td></tr></table></figure><p>但是下载速度异常缓慢,几十 kb 每秒(刚开始还比较快),故放弃。</p>\n<p>我也尝试过在英伟达官网进行下载 CUDA ,首先你必须注册一个账号,其次,官网上 CUDA 只支持特定的几个 Linux 发行版,其中刚好没有 ArchLinux(那 AUR 的软件包是从何而来的?)</p>\n</li>\n<li>\n<p>手动安装 TensorRT 的 10.2.0 版本:</p>\n<p>在 NVIDIA 的 GitHub <span class=\"exturl\" data-url=\"aHR0cHM6Ly9naXRodWIuY29tL05WSURJQS9UZW5zb3JSVA==\">TensorRT</span> 下克隆存储库并进行安装。</p>\n<p>原本打算在本机上进行安装,最后 cmake 时遇到报错,问 GPT 说是 gcc 版本和 CUDA 的编译器 nvcc 版本的问题,继续查。</p>\n<p>最后发现 CUDA 12.4, 12.5 版本最大支持的 GCC 版本竟然是 13.2。查看本机的 gcc 版本为:</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>gcc <span class=\"token parameter variable\">-v</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>gcc 版本 <span class=\"token number\">14.1</span>.1 <span class=\"token number\">20240522</span> <span class=\"token punctuation\">(</span>GCC<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>而其我并不是在英伟达官网找到的(没找到,理论上应该有),是 Google 之后在 <span class=\"exturl\" data-url=\"aHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNjYyMjQ1NC9jdWRhLWluY29tcGF0aWJsZS13aXRoLW15LWdjYy12ZXJzaW9u\">一篇帖子</span> 下的评论找到的,这篇帖子发布于 2011 年,但我甚至能看到今年的评论。</p>\n<p>评论的老哥给了一个 CUDA 版本和其支持的最高 GCC 版本的对应表格以及更多信息,首次评论在 Sep 23, 2017 at 14:23 ,最新编辑在 <span class=\"exturl\" data-url=\"aHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9wb3N0cy80NjM4MDYwMS9yZXZpc2lvbnM=\">Jun 18 at 19:16</span> ,应该是相关开发人员?</p>\n<p>因为降级 gcc 会破坏其他依赖,无法降级,本来打算按教程使用 docker 来用的,但是这位老哥下面给出了方法,简单来说就是安装旧版本的 gcc ,之后让 CUDA 的编译器 nvcc 使用旧版本的 gcc。</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 安装适配的旧版本 gcc</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">sudo</span> pacmane <span class=\"token parameter variable\">-S</span> gcc13</pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\"># 在 CUDA 文件夹中添加符号链接:</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token builtin class-name\">cd</span> /opt/cuda</pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token function\">sudo</span> <span class=\"token function\">ln</span> <span class=\"token parameter variable\">-s</span> /usr/bin/gcc-13 /usr/local/cuda/bin/gcc </pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token function\">sudo</span> <span class=\"token function\">ln</span> <span class=\"token parameter variable\">-s</span> /usr/bin/g++-13 /usr/local/cuda/bin/g++</pre></td></tr></table></figure><p>这位老哥的评论下最新的评论在 <span class=\"exturl\" data-url=\"aHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNjYyMjQ1NC9jdWRhLWluY29tcGF0aWJsZS13aXRoLW15LWdjYy12ZXJzaW9uI2NvbW1lbnQxMzcyNjE2ODVfNDYzODA2MDE=\">CommentedJan 22 at 12:27</span> ,方法有用。</p>\n</li>\n</ol>\n</li>\n</ul>\n</li>\n<li>\n<p>在解决了各种版本问题后,我目前安装的环境如下:</p>\n<ul>\n<li>\n<p>ArchLinux AUR 安装的 cuda-12.5.1-1。</p>\n</li>\n<li>\n<p>在 NVIDIA 的 GitHub <span class=\"exturl\" data-url=\"aHR0cHM6Ly9naXRodWIuY29tL05WSURJQS9UZW5zb3JSVC9yZWxlYXNlcw==\">TensorRT Releases </span> 安装的 TensorRT OSS v10.2.0 存储库。</p>\n</li>\n<li>\n<p>yay 安装 cuda-12.5.1-1 时安装 cuda-cudnn-9.2.0.82-1。</p>\n</li>\n<li>\n<p>指定上面安装的 gcc13 ,让 CUDA 的编译器 nvcc 使用。</p>\n</li>\n</ul>\n<p>然后按照在 NVIDIA 的 GitHub <span class=\"exturl\" data-url=\"aHR0cHM6Ly9naXRodWIuY29tL05WSURJQS9UZW5zb3JSVCNidWlsZA==\">TensorRT Build</span> 的教程进行安装。</p>\n<p>根据上面写的推荐版本 cuda-12.5.0 + cuDNN-8.9 ,使用 downgrade 降级安装 cuDNN-8.9 版本。</p>\n<p>最后至此开始正式 build。</p>\n</li>\n<li>\n<p>按教程安装 <span class=\"exturl\" data-url=\"aHR0cHM6Ly9kZXZlbG9wZXIubnZpZGlhLmNvbS9kb3dubG9hZHMvY29tcHV0ZS9tYWNoaW5lLWxlYXJuaW5nL3RlbnNvcnJ0LzEwLjIuMC90YXJzL1RlbnNvclJULTEwLjIuMC4xOS5MaW51eC54ODZfNjQtZ251LmN1ZGEtMTIuNS50YXIuZ3o=\">TensorRT 10.2.0.19 for CUDA 12.5, Linux x86_64</span> ,解压并设置 <code>TRT_LIBPATH</code> 到~/.zshrc ,然后在 TensorRT 目录下执行下面操作:</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token builtin class-name\">cd</span> <span class=\"token variable\">$TRT_OSSPATH</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre> <span class=\"token function\">mkdir</span> <span class=\"token parameter variable\">-p</span> build <span class=\"token operator\">&&</span> <span class=\"token builtin class-name\">cd</span> build</pre></td></tr><tr><td data-num=\"3\"></td><td><pre> cmake <span class=\"token punctuation\">..</span> <span class=\"token parameter variable\">-DTRT_LIB_DIR</span><span class=\"token operator\">=</span><span class=\"token variable\">$TRT_LIBPATH</span> <span class=\"token parameter variable\">-DTRT_OUT_DIR</span><span class=\"token operator\">=</span><span class=\"token variable\"><span class=\"token variable\">`</span><span class=\"token builtin class-name\">pwd</span><span class=\"token variable\">`</span></span>/out</pre></td></tr><tr><td data-num=\"4\"></td><td><pre> <span class=\"token function\">make</span> -j<span class=\"token variable\"><span class=\"token variable\">$(</span>nproc<span class=\"token variable\">)</span></span></pre></td></tr></table></figure><p>cmake 遇到部分警告,make 遇到错误。而且报错似乎是代码方面的错误,多方查阅也没有解决。放弃。</p>\n</li>\n<li>\n<p>第二天,由于 NVIDIA 的 GitHub <span class=\"exturl\" data-url=\"aHR0cHM6Ly9naXRodWIuY29tL05WSURJQS9UZW5zb3JSVCNidWlsZA==\">TensorRT Build</span> 的教程所给示例都是 Ubuntu 的,并且 英伟达官网的 CUDA 也没有提供 Archlinux 版本。怀疑是不是因为系统的原因。今天尝试降级 cuda 发现下载速度不再缓慢,于是换成上面第二个方案。</p>\n</li>\n<li>\n<p>使用 yay 安装 tensorRT 安装的是 tensorrt-10.1.0.27-1 版本,查看对应的 cuda 版本为 cuda-12.4.0 + cuDNN-8.9,两个都降级到对应版本。yay 安装。</p>\n<p>有警告,单线程很慢,但是好得没报错,突然想起一个问题,在 NVIDIA 的 GitHub <span class=\"exturl\" data-url=\"aHR0cHM6Ly9naXRodWIuY29tL05WSURJQS9UZW5zb3JSVCNidWlsZA==\">TensorRT Build</span> 的教程中让安装了 <span class=\"exturl\" data-url=\"aHR0cHM6Ly9kZXZlbG9wZXIubnZpZGlhLmNvbS9kb3dubG9hZHMvY29tcHV0ZS9tYWNoaW5lLWxlYXJuaW5nL3RlbnNvcnJ0LzEwLjIuMC90YXJzL1RlbnNvclJULTEwLjIuMC4xOS5MaW51eC54ODZfNjQtZ251LmN1ZGEtMTIuNS50YXIuZ3o=\">TensorRT 10.2.0.19 for CUDA 12.5, Linux x86_64</span> ,这个东西当时我在使用 yay 安装 TrnsorRT 时没有安装,也看到 <span class=\"exturl\" data-url=\"aHR0cHM6Ly9pdm9uYmxvZy5jb20vcG9zdHMvYXJjaGxpbnV4LWluc3RhbGwtbnZpZGlhLWRyaXZlcnMv\">这篇帖子</span> 说到这点:</p>\n<blockquote>\n<ol>\n<li>因為軟體授權限制,無法直接用 yay 裝,需要手動複製 AUR 儲存庫</li>\n</ol>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">sudo</span> pacman <span class=\"token parameter variable\">-S</span> base-devel</pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">git</span> clone https://aur.archlinux.org/tensorrt.git</pre></td></tr></table></figure><ol>\n<li>然後到<span class=\"exturl\" data-url=\"aHR0cHM6Ly9kZXZlbG9wZXIubnZpZGlhLmNvbS9udmlkaWEtdGVuc29ycnQtZG93bmxvYWQ=\"> Nvidia 官網</span>註冊帳號,下載 <code>tar.gz</code> 檔 (注意版本需跟 CUDA 一致),放到 <code>tensorrt</code> 目錄</li>\n</ol>\n</blockquote>\n<p>原文就是繁体,这里说的去官网注册账号下载 <code>tar.gz</code> 檔说的就是 <span class=\"exturl\" data-url=\"aHR0cHM6Ly9kZXZlbG9wZXIubnZpZGlhLmNvbS9kb3dubG9hZHMvY29tcHV0ZS9tYWNoaW5lLWxlYXJuaW5nL3RlbnNvcnJ0LzEwLjIuMC90YXJzL1RlbnNvclJULTEwLjIuMC4xOS5MaW51eC54ODZfNjQtZ251LmN1ZGEtMTIuNS50YXIuZ3o=\">TensorRT 10.2.0.19 for CUDA 12.5, Linux x86_64</span> 这个东西,叫作 TensorRT GA ,在 TensorRT 安装时需要指定 TensorRT GA 发布构建路径。</p>\n<p>所以在我在上面安装了 TensorRT GA 并将其路径添加到~/.zshrc 之后,重新使用 yay 安装就成功了(当时没有发现错误是因为没有找到 TensorRT GA 是因为什么,它没写?还是我没仔细看,绕了一大圈),后来发现 CUDA 版本也是最新版,依然可以使用 yay 安装。(也就是说不用降级也可以,高版本 CUDA 是支持低版本 TensorRT 的)。</p>\n<p>所以总结一下 CUDA 通过 yay 直接安装,TensorRT 在通过 yay 安装之前需要先安装 <span class=\"exturl\" data-url=\"aHR0cHM6Ly9kZXZlbG9wZXIubnZpZGlhLmNvbS9kb3dubG9hZHMvY29tcHV0ZS9tYWNoaW5lLWxlYXJuaW5nL3RlbnNvcnJ0LzEwLjIuMC90YXJzL1RlbnNvclJULTEwLjIuMC4xOS5MaW51eC54ODZfNjQtZ251LmN1ZGEtMTIuNS50YXIuZ3o=\">TensorRT 10.2.0.19 for CUDA 12.5, Linux x86_64</span> 并设置环境变量指定路径。之后也可以通过 yay 安装。</p>\n<p>回顾一下 Archlinux AUR 的 <span class=\"exturl\" data-url=\"aHR0cHM6Ly9hdXIuYXJjaGxpbnV4Lm9yZy9wYWNrYWdlcy90ZW5zb3JydA==\">tensorrt</span> 软件包下一个老哥的评论上说明的两个问题,第一个问题:</p>\n<p>CUDA 12.4 适用于 TensorRT 10.1.0.27。 CUDA 12.5 适用于 TensorRT 10.2.0.19。1 我这里下载的是后者,后面 <code>tensorrt_yolo</code> 指定的路径也是 TensorRT 10.2.0.19 。</p>\n<p>第二个问题是英伟达没有提供驱动,这个问题已经解决了,目前最新的驱动已经支持。</p>\n<p>不管如何 CUDA 和 TensorRT 总算是装好了。</p>\n</li>\n</ol>\n<h2 id=\"tensorrt_yolo\"><a class=\"anchor\" href=\"#tensorrt_yolo\">#</a> <code>tensorrt_yolo</code></h2>\n<p><span class=\"exturl\" data-url=\"aHR0cHM6Ly9naXRodWIuY29tL2xhdWdoMTIzMjEvVGVuc29yUlQtWU9MTy9ibG9iL21haW4vZG9jcy9jbi9idWlsZF9hbmRfaW5zdGFsbC5tZA==\">TensorRT-YOLO/docs/cn/build_and_install.md </span></p>\n<h2 id=\"deploy-编译\"><a class=\"anchor\" href=\"#deploy-编译\">#</a> <code>Deploy</code> 编译</h2>\n<p>按照上面给的文档进行编译安装。</p>\n<p>本机环境:</p>\n<ul>\n<li>Linux: gcc/g++\t13.3.0(不知道上面降级和使用旧的 gcc 是否有影作用)</li>\n<li>Xmake\tv2.9.3+20240624</li>\n<li>CUDA \t12.5.1-1</li>\n<li>TensorRT\t10.1.0.27-1</li>\n</ul>\n<p>为了满足部署需求,您可以使用 Xmake 进行 <code>Deploy</code> 编译。此过程支持动态库和静态库的编译:</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">git</span> clone https://github.com/laugh12321/TensorRT-YOLO</pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token builtin class-name\">cd</span> TensorRT-YOLO</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>xmake f <span class=\"token parameter variable\">-k</span> shared <span class=\"token parameter variable\">--tensorrt</span><span class=\"token operator\">=</span><span class=\"token string\">\"C:/Program Files/NVIDIA GPU Computing Toolkit/TensorRT/v8.6.1.6\"</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\"># xmake f -k static --tensorrt=\"C:/Program Files/NVIDIA GPU Computing Toolkit/TensorRT/v8.6.1.6\"</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>xmake <span class=\"token parameter variable\">-P</span> <span class=\"token builtin class-name\">.</span> <span class=\"token parameter variable\">-r</span></pre></td></tr></table></figure><p><code>--tensorrt="C:/Program Files/NVIDIA GPU Computing Toolkit/TensorRT/v8.6.1.6"</code> 的路径替换为自己的路径,这个路径经过我的探索,最后发现实际在 <span class=\"exturl\" data-url=\"aHR0cHM6Ly9kZXZlbG9wZXIubnZpZGlhLmNvbS9kb3dubG9hZHMvY29tcHV0ZS9tYWNoaW5lLWxlYXJuaW5nL3RlbnNvcnJ0LzEwLjIuMC90YXJzL1RlbnNvclJULTEwLjIuMC4xOS5MaW51eC54ODZfNjQtZ251LmN1ZGEtMTIuNS50YXIuZ3o=\">TensorRT 10.2.0.19 for CUDA 12.5, Linux x86_64</span> 下,在我这里是: <code>your_path/TensorRT-10.2.0.19/targets/x86_64-linux-gnu/</code></p>\n<h2 id=\"编译安装-tensorrt_yolo\"><a class=\"anchor\" href=\"#编译安装-tensorrt_yolo\">#</a> 编译安装 <code>tensorrt_yolo</code></h2>\n<p>跳过 PyPI 安装 <code>tensorrt_yolo</code> 模块部分。</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>pip <span class=\"token function\">install</span> <span class=\"token parameter variable\">--upgrade</span> build</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>python <span class=\"token parameter variable\">-m</span> build <span class=\"token parameter variable\">--wheel</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>pip <span class=\"token function\">install</span> dist/tensorrt_yolo/tensorrt_yolo-4.*-py3-none-any.whl</pre></td></tr></table></figure><p>上面是文档给的步骤,在 TensorRT-YOLO 下 执行,第三个路径在我这里不争取。我这里对应的文件是是: <code>TensorRT-YOLO/dist/tensorrt_yolo-4.0.0-py3-none-any.whl</code> ,因此路径写 <code> dist/tensorrt_yolo-4.0.0-py3-none-any.whl</code> 。</p>\n<h2 id=\"跑模型推理示例\"><a class=\"anchor\" href=\"#跑模型推理示例\">#</a> 跑模型推理示例</h2>\n<p>按照 <span class=\"exturl\" data-url=\"aHR0cHM6Ly9naXRodWIuY29tL2xhdWdoMTIzMjEvVGVuc29yUlQtWU9MTy9ibG9iL21haW4vZGVtby9kZXRlY3QvUkVBRE1FLm1k\">模型推理示例</span> 进行。</p>\n<h3 id=\"模型导出\"><a class=\"anchor\" href=\"#模型导出\">#</a> 模型导出</h3>\n<p>首先,从 <span class=\"exturl\" data-url=\"aHR0cHM6Ly9naXRodWIuY29tL3VsdHJhbHl0aWNzL2Fzc2V0cy9yZWxlYXNlcy9kb3dubG9hZC92OC4yLjAveW9sb3Y4cy5wdA==\">YOLOv8s</span> 下载 YOLOv8s 模型并保存到 <code>models</code> 文件夹中。</p>\n<p>注:上面是原文,这里的 <code>models</code> 文件夹经过我实际测试,实际上是 <code>/TensorRT-YOLO/demo/detect/</code> 下的 models 文件夹。同时工作目录现在默认也是 <code>/TensorRT-YOLO/demo/detect/</code> 。</p>\n<p>然后,使用以下指令将模型导出为带有 <span class=\"exturl\" data-url=\"aHR0cHM6Ly9naXRodWIuY29tL05WSURJQS9UZW5zb3JSVC90cmVlL21haW4vcGx1Z2luL2VmZmljaWVudE5NU1BsdWdpbg==\">EfficientNMS</span> 插件的 ONNX 格式:</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>trtyolo <span class=\"token builtin class-name\">export</span> <span class=\"token parameter variable\">-w</span> yolov8s.pt <span class=\"token parameter variable\">-v</span> yolov8 <span class=\"token parameter variable\">-o</span> models</pre></td></tr></table></figure><p>执行以上命令后,将在 <code>models</code> 文件夹下生成名为 <code>yolov8s.onnx</code> 的文件。然后,使用 <code>trtexec</code> 工具将 ONNX 文件转换为 TensorRT engine:</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>trtexec <span class=\"token parameter variable\">--onnx</span><span class=\"token operator\">=</span>models/yolov8s.onnx <span class=\"token parameter variable\">--saveEngine</span><span class=\"token operator\">=</span>models/yolov8s.engine <span class=\"token parameter variable\">--fp16</span></pre></td></tr></table></figure><p>到这里都没哟遇到什么错误,第二个命令运行时我这里看起来像卡住了一样,不过最终是跑通了的。</p>\n<h3 id=\"模型推理\"><a class=\"anchor\" href=\"#模型推理\">#</a> 模型推理</h3>\n<p>这里只讲 C++ 部分。</p>\n<p>使用 C++ 进行推理前,请确保您已按照 <span class=\"exturl\" data-url=\"aHR0cHM6Ly9naXRodWIuY29tL2xhdWdoMTIzMjEvVGVuc29yUlQtWU9MTy9ibG9iL21haW4vZG9jcy9jbi9idWlsZF9hbmRfaW5zdGFsbC5tZCNkZXBsb3ktJUU3JUJDJTk2JUU4JUFGJTkx\">Deploy 编译指南</span> 对 Deploy 进行了编译。</p>\n<p>接着,使用 xmake 将 <code>detect.cpp</code> 编译为可执行文件:</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>xmake f <span class=\"token parameter variable\">-P</span> <span class=\"token builtin class-name\">.</span> <span class=\"token parameter variable\">--tensorrt</span><span class=\"token operator\">=</span><span class=\"token string\">\"/path/to/your/TensorRT\"</span> <span class=\"token parameter variable\">--deploy</span><span class=\"token operator\">=</span>/path/to/your/TensorRT-YOLO</pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>xmake <span class=\"token parameter variable\">-P</span> <span class=\"token builtin class-name\">.</span> <span class=\"token parameter variable\">-r</span></pre></td></tr></table></figure><p>注:上面是原文,这里的 <code>"/path/to/your/TensorRT"</code> 就是前面安装的 <span class=\"exturl\" data-url=\"aHR0cHM6Ly9kZXZlbG9wZXIubnZpZGlhLmNvbS9kb3dubG9hZHMvY29tcHV0ZS9tYWNoaW5lLWxlYXJuaW5nL3RlbnNvcnJ0LzEwLjIuMC90YXJzL1RlbnNvclJULTEwLjIuMC4xOS5MaW51eC54ODZfNjQtZ251LmN1ZGEtMTIuNS50YXIuZ3o=\">TensorRT 10.2.0.19 for CUDA 12.5, Linux x86_64</span> 下的一个路径, <code>your_path/TensorRT-10.2.0.19/targets/x86_64-linux-gnu/</code> 。后面的 deploy 路径就是你的 TensorRT-YOLO 路径。</p>\n<p>在执行上述命令后,将在根目录的 <code>build</code> 目录下生成名为 <code>detect</code> 的可执行文件。最后,您可以直接运行可执行文件或使用 <code>xmake run</code> 命令进行推理。使用 <code>--help</code> 查看详细指令选项:</p>\n<p>注;上面是原文,我这里生成的 <code>detect</code> 的可执行文件位于 <code>/TensorRT-YOLO/demo/detect/build/linux/x86_64/release/</code> 下,同时还有一个 <code>libdeploy.so</code> 文件也在这个目录下。</p>\n<blockquote>\n<p>要加速推理过程,请使用 <code>--cudaGraph</code> 指令,但此功能仅支持静态模型,不支持动态模型。</p>\n</blockquote>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>xmake run <span class=\"token parameter variable\">-P</span> <span class=\"token builtin class-name\">.</span> detect <span class=\"token parameter variable\">-e</span> models/yolov8s.engine <span class=\"token parameter variable\">-i</span> images <span class=\"token parameter variable\">-o</span> output <span class=\"token parameter variable\">-l</span> labels.txt <span class=\"token parameter variable\">--cudaGraph</span></pre></td></tr></table></figure><p>注:这里命令中的路径一定要正确,工作目录在 <code>/TensorRT-YOLO/demo/detect/</code> 下时,为:</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>./build/linux/x86_64/release/detect <span class=\"token parameter variable\">-e</span> models/yolov8s.engine <span class=\"token parameter variable\">-i</span> images <span class=\"token parameter variable\">-o</span> output <span class=\"token parameter variable\">-l</span> labels.txt <span class=\"token parameter variable\">--cudaGraph</span></pre></td></tr></table></figure><p>使用 xmake run 的命令没去试,直接运行 detect 就行了。输出图像在 output 文件夹下,生成文本描述 <code>labels.txt</code> 。</p>\n",
"tags": []
},
{
"id": "http://yuanmxc.site/C++/C++%E5%87%BD%E6%95%B0/",
"url": "http://yuanmxc.site/C++/C++%E5%87%BD%E6%95%B0/",
"title": "C++ 函数",
"date_published": "2024-06-02T03:17:03.979Z",
"content_html": "<ol>\n<li>\n<p>根据高分辨率的时钟为种子,生成指定长度的随机 ID 的函数</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\">// 生成指定长度的随机 ID</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>std<span class=\"token double-colon punctuation\">::</span>string <span class=\"token function\">randomId</span><span class=\"token punctuation\">(</span>size_t length<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre> <span class=\"token keyword\">using</span> std<span class=\"token double-colon punctuation\">::</span>chrono<span class=\"token double-colon punctuation\">::</span>high_resolution_clock<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre> <span class=\"token keyword\">static</span> <span class=\"token keyword\">thread_local</span> std<span class=\"token double-colon punctuation\">::</span>mt19937 <span class=\"token function\">rng</span><span class=\"token punctuation\">(</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre> <span class=\"token generic-function\"><span class=\"token function\">static_cast</span><span class=\"token generic class-name\"><span class=\"token operator\"><</span><span class=\"token keyword\">unsigned</span> <span class=\"token keyword\">int</span><span class=\"token operator\">></span></span></span><span class=\"token punctuation\">(</span>high_resolution_clock<span class=\"token double-colon punctuation\">::</span><span class=\"token function\">now</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">time_since_epoch</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">count</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre> <span class=\"token keyword\">static</span> <span class=\"token keyword\">const</span> std<span class=\"token double-colon punctuation\">::</span>string <span class=\"token function\">characters</span><span class=\"token punctuation\">(</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre> <span class=\"token string\">\"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre> std<span class=\"token double-colon punctuation\">::</span>string <span class=\"token function\">id</span><span class=\"token punctuation\">(</span>length<span class=\"token punctuation\">,</span> <span class=\"token char\">'0'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre> std<span class=\"token double-colon punctuation\">::</span>uniform_int_distribution<span class=\"token operator\"><</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span> <span class=\"token function\">uniform</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span><span class=\"token punctuation\">(</span>characters<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre> std<span class=\"token double-colon punctuation\">::</span><span class=\"token function\">generate</span><span class=\"token punctuation\">(</span>id<span class=\"token punctuation\">.</span><span class=\"token function\">begin</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> id<span class=\"token punctuation\">.</span><span class=\"token function\">end</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token operator\">&</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span> <span class=\"token keyword\">return</span> characters<span class=\"token punctuation\">.</span><span class=\"token function\">at</span><span class=\"token punctuation\">(</span><span class=\"token function\">uniform</span><span class=\"token punctuation\">(</span>rng<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre> <span class=\"token keyword\">return</span> id<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token punctuation\">}</span></pre></td></tr></table></figure><figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">using</span> std<span class=\"token double-colon punctuation\">::</span>chrono<span class=\"token double-colon punctuation\">::</span>high_resolution_clock<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 这行代码引入了 `std::chrono::high_resolution_clock`,这是一个用于测量时间的标准库类。</span></pre></td></tr></table></figure><figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">static</span> <span class=\"token keyword\">thread_local</span> std<span class=\"token double-colon punctuation\">::</span>mt19937 <span class=\"token function\">rng</span><span class=\"token punctuation\">(</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token generic-function\"><span class=\"token function\">static_cast</span><span class=\"token generic class-name\"><span class=\"token operator\"><</span><span class=\"token keyword\">unsigned</span> <span class=\"token keyword\">int</span><span class=\"token operator\">></span></span></span><span class=\"token punctuation\">(</span>high_resolution_clock<span class=\"token double-colon punctuation\">::</span><span class=\"token function\">now</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">time_since_epoch</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">count</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>这行代码定义了一个静态局部变量 <code>rng</code> ,它是一个 <code>std::mt19937</code> 类型的伪随机数生成器。通过使用当前时间的高分辨率时钟的计数作为种子,我们创建了一个每次函数调用时都会生成不同随机数序列的生成器。</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">static</span> <span class=\"token keyword\">const</span> std<span class=\"token double-colon punctuation\">::</span>string <span class=\"token function\">characters</span><span class=\"token punctuation\">(</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>\t<span class=\"token string\">\"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>这行代码定义了一个静态常量字符串 <code>characters</code> ,它包含了用于生成随机 ID 的字符集。它包括数字、大写字母和小写字母。</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>std<span class=\"token double-colon punctuation\">::</span>string <span class=\"token function\">id</span><span class=\"token punctuation\">(</span>length<span class=\"token punctuation\">,</span> <span class=\"token char\">'0'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>这行代码创建了一个名为 <code>id</code> 的 <code>std::string</code> 对象,长度为 <code>length</code> ,并将其初始化为由字符 <code>'0'</code> 组成的字符串。</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>std<span class=\"token double-colon punctuation\">::</span>uniform_int_distribution<span class=\"token operator\"><</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span> <span class=\"token function\">uniform</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token keyword\">int</span><span class=\"token punctuation\">(</span>characters<span class=\"token punctuation\">.</span><span class=\"token function\">size</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>这行代码定义了一个均匀分布的整数生成器 <code>uniform</code> ,它生成范围在 <code>0</code> 到 <code>characters.size() - 1</code> 之间的整数。</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>std<span class=\"token double-colon punctuation\">::</span><span class=\"token function\">generate</span><span class=\"token punctuation\">(</span>id<span class=\"token punctuation\">.</span><span class=\"token function\">begin</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> id<span class=\"token punctuation\">.</span><span class=\"token function\">end</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token operator\">&</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span> <span class=\"token keyword\">return</span> characters<span class=\"token punctuation\">.</span><span class=\"token function\">at</span><span class=\"token punctuation\">(</span><span class=\"token function\">uniform</span><span class=\"token punctuation\">(</span>rng<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>这行代码使用 <code>std::generate</code> 算法,将随机选择的字符填充到 <code>id</code> 字符串中。 <code>generate</code> 函数接受一个范围(由 <code>id.begin()</code> 和 <code>id.end()</code> 表示),并使用 lambda 表达式作为生成器函数。lambda 表达式使用 <code>characters</code> 字符串和 <code>uniform(rng)</code> 生成的随机索引来填充字符。</p>\n</li>\n</ol>\n",
"tags": [
"C++"
]
},
{
"id": "http://yuanmxc.site/C++/C++%E5%B0%8F%E8%AE%B0/",
"url": "http://yuanmxc.site/C++/C++%E5%B0%8F%E8%AE%B0/",
"title": "C++ 小记",
"date_published": "2024-06-02T01:56:41.038Z",
"content_html": "<ol>\n<li>\n<p><code>std::holds_alternative<std::string>(data)</code> 是一个类型检查的表达式,用于检查给定的变量 <code>data</code> 是否包含 <code>std::string</code> 类型的值。</p>\n<p><code>std::holds_alternative</code> 是 C++ 标准库中的一个函数模板,它的作用是判断给定的变量是否包含指定的类型。</p>\n</li>\n<li>\n<p><code>std::promise<void></code> 是 C++ 标准库中的一个模板类,用于提供一种机制,允许一个线程在某个时间点产生一个值(或异常),并使其他线程能够等待并获取该值(或异常)。</p>\n<p>在你提供的代码中, <code>wsPromise</code> 是一个名为 <code>wsPromise</code> 的对象,它是 <code>std::promise<void></code> 类型的实例。这意味着它是一个用于产生 <code>void</code> 类型值的 <code>promise</code> 对象。</p>\n<p><code>std::promise</code> 类提供了两个主要操作: <code>set_value()</code> 和 <code>set_exception()</code> 。通过调用 <code>set_value()</code> ,可以在 <code>promise</code> 对象上设置一个值(在这种情况下,是 <code>void</code> 类型的值),然后通过调用 <code>get_future()</code> 获得一个与该 <code>promise</code> 相关联的 <code>std::future</code> 对象,其他线程可以通过该 <code>future</code> 对象等待并获取该值。</p>\n<p>以下是一个简单的示例,展示了如何使用 <code>std::promise<void></code> 和相关的类来实现线程间的同步:</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\"><iostream></span></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre> <span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\"><thread></span></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\"><future></span></span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">worker</span><span class=\"token punctuation\">(</span>std<span class=\"token double-colon punctuation\">::</span>promise<span class=\"token operator\"><</span><span class=\"token keyword\">void</span><span class=\"token operator\">></span><span class=\"token operator\">&</span> promise<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre> <span class=\"token comment\">// 模拟一些耗时的工作</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre> std<span class=\"token double-colon punctuation\">::</span>this_thread<span class=\"token double-colon punctuation\">::</span><span class=\"token function\">sleep_for</span><span class=\"token punctuation\">(</span>std<span class=\"token double-colon punctuation\">::</span>chrono<span class=\"token double-colon punctuation\">::</span><span class=\"token function\">seconds</span><span class=\"token punctuation\">(</span><span class=\"token number\">2</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre> </pre></td></tr><tr><td data-num=\"9\"></td><td><pre> <span class=\"token comment\">// 工作完成后,设置 promise 的值</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre> promise<span class=\"token punctuation\">.</span><span class=\"token function\">set_value</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token punctuation\">}</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre> std<span class=\"token double-colon punctuation\">::</span>promise<span class=\"token operator\"><</span><span class=\"token keyword\">void</span><span class=\"token operator\">></span> wsPromise<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre> std<span class=\"token double-colon punctuation\">::</span>future<span class=\"token operator\"><</span><span class=\"token keyword\">void</span><span class=\"token operator\">></span> wsFuture <span class=\"token operator\">=</span> wsPromise<span class=\"token punctuation\">.</span><span class=\"token function\">get_future</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre> </pre></td></tr><tr><td data-num=\"17\"></td><td><pre> <span class=\"token comment\">// 创建一个工作线程,并传递 promise 作为参数</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre> std<span class=\"token double-colon punctuation\">::</span>thread <span class=\"token function\">workerThread</span><span class=\"token punctuation\">(</span>worker<span class=\"token punctuation\">,</span> std<span class=\"token double-colon punctuation\">::</span><span class=\"token function\">ref</span><span class=\"token punctuation\">(</span>wsPromise<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre> </pre></td></tr><tr><td data-num=\"20\"></td><td><pre> <span class=\"token comment\">// 等待工作线程完成</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre> wsFuture<span class=\"token punctuation\">.</span><span class=\"token function\">wait</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre> </pre></td></tr><tr><td data-num=\"23\"></td><td><pre> std<span class=\"token double-colon punctuation\">::</span>cout <span class=\"token operator\"><<</span> <span class=\"token string\">\"Worker thread finished.\"</span> <span class=\"token operator\"><<</span> std<span class=\"token double-colon punctuation\">::</span>endl<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre> </pre></td></tr><tr><td data-num=\"25\"></td><td><pre> workerThread<span class=\"token punctuation\">.</span><span class=\"token function\">join</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre> </pre></td></tr><tr><td data-num=\"27\"></td><td><pre> <span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre><span class=\"token punctuation\">}</span></pre></td></tr></table></figure><p>在上述示例中, <code>worker()</code> 函数是一个工作线程执行的函数。它接受一个 <code>std::promise<void></code> 对象作为参数,并通过调用 <code>set_value()</code> 来设置该 <code>promise</code> 对象的值。主线程使用 <code>get_future()</code> 获取与 <code>promise</code> 对象相关联的 <code>std::future</code> 对象,并使用 <code>wait()</code> 函数等待工作线程完成。一旦工作线程完成并设置了 <code>promise</code> 的值,主线程将继续执行。</p>\n<p>需要注意的是, <code>std::promise</code> 和 <code>std::future</code> 提供了一种线程间通信的机制,其中一个线程通过 <code>promise</code> 设置值,而另一个线程通过 <code>future</code> 等待并获取该值。</p>\n</li>\n<li>\n<p><code>std::promise</code> 类中的 <code>set_exception()</code> 函数用于在 <code>promise</code> 对象上设置一个异常,以通知与之关联的 <code>std::future</code> 对象所在的线程。</p>\n<p>当某个线程调用 <code>set_exception()</code> 函数并提供一个异常作为参数时,与该 <code>promise</code> 对象关联的 <code>std::future</code> 对象上的等待操作将会收到该异常(通过 <code>std::future</code> 对象的 <code>get()</code> 函数或 <code>wait()</code> 函数调用时抛出)。</p>\n<p>以下是一个示例,展示了如何使用 <code>std::promise</code> 的 <code>set_exception()</code> 函数来传递异常:</p>\n<figure class=\"highlight cpp\"><figcaption data-lang=\"C++\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\"><iostream></span></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre> <span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\"><thread></span></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\"><future></span></span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre> <span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\"><stdexcept></span></span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">worker</span><span class=\"token punctuation\">(</span>std<span class=\"token double-colon punctuation\">::</span>promise<span class=\"token operator\"><</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span><span class=\"token operator\">&</span> promise<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre> <span class=\"token keyword\">try</span> <span class=\"token punctuation\">{</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre> <span class=\"token comment\">// 模拟一些工作</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre> std<span class=\"token double-colon punctuation\">::</span>this_thread<span class=\"token double-colon punctuation\">::</span><span class=\"token function\">sleep_for</span><span class=\"token punctuation\">(</span>std<span class=\"token double-colon punctuation\">::</span>chrono<span class=\"token double-colon punctuation\">::</span><span class=\"token function\">seconds</span><span class=\"token punctuation\">(</span><span class=\"token number\">2</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre> </pre></td></tr><tr><td data-num=\"11\"></td><td><pre> <span class=\"token comment\">// 抛出一个异常</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre> <span class=\"token keyword\">throw</span> std<span class=\"token double-colon punctuation\">::</span><span class=\"token function\">runtime_error</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"Something went wrong.\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre> </pre></td></tr><tr><td data-num=\"14\"></td><td><pre> <span class=\"token comment\">// 设置 promise 的值(这行代码不会执行)</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre> promise<span class=\"token punctuation\">.</span><span class=\"token function\">set_value</span><span class=\"token punctuation\">(</span><span class=\"token number\">42</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre> <span class=\"token punctuation\">}</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre> <span class=\"token comment\">// 捕获异常,并通过 promise 设置异常</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre> promise<span class=\"token punctuation\">.</span><span class=\"token function\">set_exception</span><span class=\"token punctuation\">(</span>std<span class=\"token double-colon punctuation\">::</span><span class=\"token function\">current_exception</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre> <span class=\"token punctuation\">}</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre><span class=\"token punctuation\">}</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre></pre></td></tr><tr><td data-num=\"22\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre> std<span class=\"token double-colon punctuation\">::</span>promise<span class=\"token operator\"><</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span> wsPromise<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre> std<span class=\"token double-colon punctuation\">::</span>future<span class=\"token operator\"><</span><span class=\"token keyword\">int</span><span class=\"token operator\">></span> wsFuture <span class=\"token operator\">=</span> wsPromise<span class=\"token punctuation\">.</span><span class=\"token function\">get_future</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre> </pre></td></tr><tr><td data-num=\"26\"></td><td><pre> <span class=\"token comment\">// 创建一个工作线程,并传递 promise 作为参数</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre> std<span class=\"token double-colon punctuation\">::</span>thread <span class=\"token function\">workerThread</span><span class=\"token punctuation\">(</span>worker<span class=\"token punctuation\">,</span> std<span class=\"token double-colon punctuation\">::</span><span class=\"token function\">ref</span><span class=\"token punctuation\">(</span>wsPromise<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre> </pre></td></tr><tr><td data-num=\"29\"></td><td><pre> <span class=\"token keyword\">try</span> <span class=\"token punctuation\">{</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre> <span class=\"token comment\">// 等待工作线程完成</span></pre></td></tr><tr><td data-num=\"31\"></td><td><pre> <span class=\"token keyword\">int</span> result <span class=\"token operator\">=</span> wsFuture<span class=\"token punctuation\">.</span><span class=\"token function\">get</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"32\"></td><td><pre> std<span class=\"token double-colon punctuation\">::</span>cout <span class=\"token operator\"><<</span> <span class=\"token string\">\"Worker thread finished with result: \"</span> <span class=\"token operator\"><<</span> result <span class=\"token operator\"><<</span> std<span class=\"token double-colon punctuation\">::</span>endl<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"33\"></td><td><pre> <span class=\"token punctuation\">}</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> std<span class=\"token double-colon punctuation\">::</span>exception<span class=\"token operator\">&</span> ex<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></pre></td></tr><tr><td data-num=\"34\"></td><td><pre> std<span class=\"token double-colon punctuation\">::</span>cout <span class=\"token operator\"><<</span> <span class=\"token string\">\"Worker thread threw an exception: \"</span> <span class=\"token operator\"><<</span> ex<span class=\"token punctuation\">.</span><span class=\"token function\">what</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\"><<</span> std<span class=\"token double-colon punctuation\">::</span>endl<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"35\"></td><td><pre> <span class=\"token punctuation\">}</span></pre></td></tr><tr><td data-num=\"36\"></td><td><pre> </pre></td></tr><tr><td data-num=\"37\"></td><td><pre> workerThread<span class=\"token punctuation\">.</span><span class=\"token function\">join</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"38\"></td><td><pre> </pre></td></tr><tr><td data-num=\"39\"></td><td><pre> <span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"40\"></td><td><pre><span class=\"token punctuation\">}</span></pre></td></tr></table></figure><p>在上述示例中, <code>worker()</code> 函数模拟一个工作线程执行的工作。在这个例子中,工作线程抛出了一个 <code>std::runtime_error</code> 异常,然后通过 <code>set_exception()</code> 函数将异常传递给与 <code>promise</code> 对象关联的 <code>std::future</code> 对象。主线程使用 <code>get()</code> 函数获取 <code>std::future</code> 对象上的值时,如果工作线程抛出了异常, <code>get()</code> 函数将重新抛出该异常,然后可以在主线程中捕获并处理该异常。</p>\n<p>总而言之, <code>set_exception()</code> 函数允许在 <code>promise</code> 对象上设置异常,以便将异常传递给与之关联的 <code>std::future</code> 对象所在的线程,从而实现线程间的异常传递和处理。</p>\n</li>\n<li>\n<p><code>std::cin.ignore()</code> 是 C++ 标准库中 <code>std::cin</code> 流的成员函数之一。它的作用是忽略输入流中的字符。</p>\n<p><code>std::cin.ignore()</code> 函数通常与 <code>std::cin</code> 结合使用,用于清除输入缓冲区中的字符,以便接下来的输入操作不会受到之前输入的影响。</p>\n<p>该函数可以在两种形式下使用:</p>\n<ol>\n<li><code>std::cin.ignore()</code> :调用函数时不传递参数。它会忽略输入流中的下一个字符,无论是换行符、空格符还是其他字符。</li>\n<li><code>std::cin.ignore(n, delim)</code> :调用函数时传递两个参数。其中, <code>n</code> 是要忽略的字符数, <code>delim</code> 是可选的定界符(默认为换行符)。\n<ul>\n<li>如果提供了 <code>n</code> ,则会忽略输入流中的前 <code>n</code> 个字符。</li>\n<li>如果同时提供了 <code>n</code> 和 <code>delim</code> ,则会忽略输入流中的字符,直到遇到定界符 <code>delim</code> 为止。</li>\n</ul>\n</li>\n</ol>\n<p>这些函数在某些情况下很有用,例如当需要清除输入缓冲区中的残留字符时,或者在读取不同类型的数据之前需要忽略一些字符。</p>\n</li>\n<li>\n<p>部分 C 语言库,在 c++ 文件中使用需要用 <code>extern "C"{}</code> 的形式包裹起来,否则编译链接时会找不到库中函数的实现,例如 FFmpeg 库中的库:</p>\n</li>\n</ol>\n<pre><code>```C++\nextern "C" {\n#include <libavcodec/avcodec.h>\n#include <libavcodec/packet.h>\n#include <libavformat/avformat.h>\n}\n```\n</code></pre>\n",
"tags": [
"C++"
]
},
{
"id": "http://yuanmxc.site/%E9%9A%8F%E7%AC%94/%E7%AC%AC%E4%B8%80%E6%AC%A1%E9%9A%8F%E7%AC%94/",
"url": "http://yuanmxc.site/%E9%9A%8F%E7%AC%94/%E7%AC%AC%E4%B8%80%E6%AC%A1%E9%9A%8F%E7%AC%94/",
"title": "第一次随笔",
"date_published": "2024-03-26T12:51:51.467Z",
"content_html": "<h1 id=\"起因\"><a class=\"anchor\" href=\"#起因\">#</a> 起因</h1>\n<p>3.25 晚上整理博客,QQ 上看到一段话,还不错,正好博客弄好了,” 关于 “这部分还不知道放些什么东西。随笔这些写上面感觉还不错,于是开始在博客上写随笔。但是敲来敲去,总觉得哪里有些怪,不自然。看着屏幕上写的东西,总感觉有那么一丝丝奇怪。</p>\n<p><strong>逃避</strong> — 差不多就是这样。选择困难症又开始了,博客上要不要 "记录生活",写写随笔,还是只写技术,写随笔写什么,怎么写。</p>\n<h1 id=\"高中旧物\"><a class=\"anchor\" href=\"#高中旧物\">#</a> 高中旧物</h1>\n<p>初中高中的时候也有写过一些记录当时所思所想的文字,尤其是高三压力大那时候,晚上猫在被窝打灯写,虽然大部分是和 ys 有关,但是也包含了自己当时的所思所想,也给了自己不少坚持下去的动力。</p>\n<p>但毕业以后,人生开始踏入新的阶段,整理之前的旧物时又开始选择。那时的自己喜欢简约,什么东西都整整齐齐,有条理,同时也不想无关的东西来占用自己的空间和时间。” 断舍离 “践行的很好,包括现在也是。</p>\n<p>“长时间用不到的东西扔掉就好了,即使未来某一天想用到它,也就是那么很短的一段时间。想回忆的时候感触万千,但部分时间他们都是无用之物 “。就是这种想法。我现在也觉得没错。三年过去,对于那些记录,也就现在有那么一点” 如果没有扔掉,现在看看也不不错 “的想法,其他时间根本就没想。</p>\n<h1 id=\"写吧\"><a class=\"anchor\" href=\"#写吧\">#</a> 写吧</h1>\n<p>写随笔在自己看来其实一件很好的事情,鼓励自己,反省自己,记录生活,,但是 “有写他们的时间我为什么不去做些其他的事情呢” 这种想法总会占据上风。事实也确实如此,比如现在写这篇文章就要花不少时间。</p>\n<p>正在纠结的时候学弟过来给我看了他昨晚写的博客,也是随笔,简单的记录生活,简单的排版,简单的描述,看着还不错,是自己犹犹豫豫不敢写的东西。</p>\n<p>看完后又去看了一下他的友链中一个人的博客。是 23 届一个学前端的女生,写了几篇博客记录自己的生活,文笔也不错,写的很好,一连看了几篇,虽然所有图片都无法查看(应该是图床没配好)但是让我看的心情变得不错。也下定决心开是写些东西。</p>\n<h1 id=\"后谈\"><a class=\"anchor\" href=\"#后谈\">#</a> 后谈</h1>\n<p>其实写这些花费时间是肯定的,但不一定就是” 浪费 “,写或者不写而引发的一系列反应会导致什么结果。写了这些可能让自己心情变好?影响学习效率?影响心态?时间总是要花费的,无非就是这段时间花费是不是花在你想做的事情上。如果写随笔是想做的事情,那也就是不用犹豫了。</p>\n<p>以后有时间,想写了就写一些,随时、随地、随便。也不用太在乎排版啊,观感啊这些。始终觉得写东西首先是给自己看的,其次才是给别人看。</p>\n<p>修博客的时候不知道写什么话放在首页好,后来发现自己用了很久的 QQ 签名不就很不错嘛:</p>\n<p><strong>不乱于心,不困于情;不畏将来,不念过往。</strong></p>\n<p>是丰子恺先生写的。顺带查了一下,这句话是丰子恺先生《无宠不惊过一生》的一句诗。</p>\n<p>全诗如下:</p>\n<p><em>不乱于心,不困于情;不畏将来,不念过往。如此,安好!</em><br />\n<em> 深谋若谷,深交若水;深明大义,深悉小节,已然,静舒!</em><br />\n<em> 善宽以怀,善感以恩;善博以浪,善精以业。这般。最佳!</em><br />\n<em> 勿感于时,勿伤于怀;勿耽美色,勿沉虚妄。从今,进取!</em><br />\n<em> 无愧于天,无愧于地。无怍于人,无惧于鬼。这样。人生!</em></p>\n<p>写的是真不错啊。记下记下,后面还想开一些好词、好句之类的地方,收藏一下,初高中的东西都丢了,那时候因为要写作文,” 顺带 “收集了不少自己觉得不错的好词、好诗、好句,可惜都遗失了,不过现在开始,慢慢找回来吧。</p>\n<p>打字打的手疼,好像还没一次性连续打这么多字。估计还有很多错字,已经不想再检查了,今天先到这里吧。</p>\n<p>下面是那天晚上写的东西,也就先这么放着:</p>\n<p>也不知道这里该写些什么,感觉有很多想写的,又感觉没什么写的。就瞎写得了,随性一点也不错。想起啥写啥。“以后会优化”</p>\n<blockquote>\n<p>三年后,你结婚了,下班回家看着你不爱的人,烦得吃不下饭,床都不愿意上,话也不想说,你会不会后悔曾经太听家人的话;</p>\n<p>三年后,你结婚了,下班回家看着你当初奋不顾身要嫁的人,对你很是厌烦,只知道打游戏,话都懒得跟你说,再看看满屋的狼藉,吵闹的孩子,没洗的碗筷,他甚至家都不愿意回,你会不会后悔曾经不听家人的话;</p>\n<p>三年后,你未婚,看见朋友都幸福美满,你流露出羡慕的眼神,可又看到他们为了房贷,车贷,孩子的费用,柴米油盐的平淡和枯燥锁纠缠,你庆幸自由且随意;</p>\n<p>三年后,你仍没有结婚,看到别人家烟花满巷,内心的孤独和失落油然而生,对未来的迷茫无从安放。那一刻你会不会觉得自己是芸芸众生中最普通的一员,你是否会后悔当初决定不结婚;</p>\n<p>巷子里的猫很自由,却没有归宿,围墙里的狗有归宿,终身都得低头,人生这道选择题,怎么选都会有遗憾,人总以为自己没有过的路上开满了鲜花,凡事看的太透,人间便无趣了,该来的都回来,该走的也都会走。别抗拒,别挽留,太注重细节的人注定不会快乐。</p>\n</blockquote>\n<p>QQ 看点偶然看到的。例子终究是例子,你自己的生活什么样不是别人说出来的。有人陪或者三年后自己差不多也该到结婚的时候了吧,人生即将打下一个基调。婚可能还是要结的,孩子可能还是要要的,自己的想法应该还没到扭转这个路线的能力?决心?自己也说不清。“传统路线” 还是自由选择,就交给将来的自己去抉择把。至少现在觉得养孩子,还贷还不是自己想要的生活。不喜欢背负着太多压力,不喜欢没有选择,不喜欢” 不得不 “,喜欢” 所做的一切都是因为自己原意去做,想去做,想去过什么生活,想成为什么样的人 “。未来的事情交给未来就好了,未来总会成为现在的。</p>\n<p>最后几句话和前面关系不大吧。“凡事看的太透,人间便无趣了” 这话怎么感觉说的这么像自己的状态。很多事情都没什么大兴趣,“无所谓”“都行”。</p>\n<p>有些后悔初中高中写的东西没保存了,高三末写的那个本子啊,就,之前的心态好想是对过去的没什么可留恋的。</p>\n",
"tags": [
"随笔"
]
},
{
"id": "http://yuanmxc.site/Archlinux/ArchLinux%E4%BD%BF%E7%94%A8%E8%AE%B0%E5%BD%95/",
"url": "http://yuanmxc.site/Archlinux/ArchLinux%E4%BD%BF%E7%94%A8%E8%AE%B0%E5%BD%95/",
"title": "ArchLinux使用记录",
"date_published": "2024-03-26T11:49:10.133Z",
"content_html": "<h2 id=\"零\"><a class=\"anchor\" href=\"#零\">#</a> 零</h2>\n<p>强烈推荐阅读:<span class=\"exturl\" data-url=\"aHR0cHM6Ly9hcmNobGludXhzdHVkaW8uZ2l0aHViLmlvL0FyY2hMaW51eFR1dG9yaWFsLyMvP2lkPWFyY2gtbGludXgtJUU1JUFFJTg5JUU4JUEzJTg1JUU0JUJEJUJGJUU3JTk0JUE4JUU2JTk1JTk5JUU3JUE4JThCLWFyY2h0dXRvcmlhbC1hcmNoLWxpbnV4LXN0dWRpbw==\">Arch Linux 安装使用教程</span> 和 <span class=\"exturl\" data-url=\"aHR0cHM6Ly9hcmNobGludXhzdHVkaW8uZ2l0aHViLmlvL0FyY2hMaW51eFR1dG9yaWFsLyMvP2lkPWFyY2gtbGludXgtJUU1JUFFJTg5JUU4JUEzJTg1JUU0JUJEJUJGJUU3JTk0JUE4JUU2JTk1JTk5JUU3JUE4JThCLWFyY2h0dXRvcmlhbC1hcmNoLWxpbnV4LXN0dWRpbw==\">archlinux 简明指南</span> 。 这两本书都是内容非常详尽的 Arch Linux 安装和使用教程,包括 Arch Linux 安装、基本配置、日产使用、常用软件安装等内容,可以帮助初学者解决很多问题。</p>\n<p>笔者本人使用笔记本单固态应硬盘安装 windows10 + ArchLinux 双系统,推荐按照 <span class=\"exturl\" data-url=\"aHR0cHM6Ly9hcmNobGludXhzdHVkaW8uZ2l0aHViLmlvL0FyY2hMaW51eFR1dG9yaWFsLyMvP2lkPWFyY2gtbGludXgtJUU1JUFFJTg5JUU4JUEzJTg1JUU0JUJEJUJGJUU3JTk0JUE4JUU2JTk1JTk5JUU3JUE4JThCLWFyY2h0dXRvcmlhbC1hcmNoLWxpbnV4LXN0dWRpbw==\">archlinux 简明指南</span> 的安装步骤进行安装。</p>\n<p>安装过程需要注意:</p>\n<ol>\n<li>\n<p>清楚你即将使用的命令做了什么,不要一味回车回车...</p>\n</li>\n<li>\n<p>按照教程的大纲,分模块进行,分清每一块做了什么,不要一行一行,遇见一个敲一个,先通读知晓这一块是做什么之后,返回来按照自己需要的去做。</p>\n</li>\n<li>\n<p>不要过分地 “多线程” 操作试图节省时间,稳中前进,不出错就是最快的。</p>\n</li>\n<li>\n<p>仔细对照好输入的命令是否正确,确认每个命令的结果是否符合预期。</p>\n<p><span class=\"exturl\" data-url=\"aHR0cHM6Ly9iYnMuYXJjaGxpbnV4Y24ub3JnL2luZGV4LnBocA==\">Arclinux 中文论坛</span> 众多 Archlinux 使用者汇集的地方,同时有着较为官方的信息和软件包,很多问题可以在这里解决。</p>\n</li>\n</ol>\n<h2 id=\"部分命令记录\"><a class=\"anchor\" href=\"#部分命令记录\">#</a> 部分命令记录</h2>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">sudo</span> <span class=\"token function\">fdisk</span> <span class=\"token parameter variable\">-l</span> <span class=\"token comment\"># 查看磁盘和分区信息</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>df-h <span class=\"token comment\"># 显示文件系统磁盘空间使用情况</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token function\">sudo</span> <span class=\"token function\">umount</span> /dev/sdX <span class=\"token comment\"># 卸载 U 盘,“/dev/sdX” 为你要卸载的 U 盘设备名称。</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token function\">sudo</span> mkfs.vfat /dev/sdX <span class=\"token comment\"># 将 U 盘格式化为 FAT32 文件系统 /</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token function\">printenv</span> <span class=\"token comment\"># 查看所有的环境变量</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token builtin class-name\">echo</span> <span class=\"token operator\">&</span><span class=\"token environment constant\">PATH</span> <span class=\"token comment\"># 查看特定环境变量的值(echo $http_proxy)</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token builtin class-name\">export</span> <span class=\"token assign-left variable\">http_proxy</span><span class=\"token operator\">=</span><span class=\"token string\">\"http://127.0.0.1:7890\"</span> <span class=\"token comment\"># 设置代理服务器,设置 http_proxy 和 https_proxy 环境变量</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token builtin class-name\">export</span> <span class=\"token assign-left variable\">https_proxy</span><span class=\"token operator\">=</span><span class=\"token string\">\"http://127.0.0.1:7890\"</span></pre></td></tr></table></figure><p>以下命令需要安装后才能使用:</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>tree <span class=\"token parameter variable\">-A</span> 使用ASNI绘图字符显示树状图而非以ASCII字符组合</pre></td></tr><tr><td data-num=\"2\"></td><td><pre> <span class=\"token parameter variable\">-C</span> 使用颜色区分文件类型</pre></td></tr><tr><td data-num=\"3\"></td><td><pre> <span class=\"token parameter variable\">-N</span> 支持显示中文字符</pre></td></tr><tr><td data-num=\"4\"></td><td><pre> <span class=\"token parameter variable\">-a</span> 显示隐藏文件<span class=\"token punctuation\">(</span>以.开头<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre> <span class=\"token parameter variable\">-d</span> 只显示目录</pre></td></tr><tr><td data-num=\"6\"></td><td><pre> <span class=\"token parameter variable\">-h</span> 使用人易读的单位显示文件大小</pre></td></tr><tr><td data-num=\"7\"></td><td><pre> <span class=\"token parameter variable\">-L</span> <span class=\"token punctuation\">[</span>num<span class=\"token punctuation\">]</span> 指定显示的最大深度</pre></td></tr></table></figure><p>##Pacman 包管理:</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">sudo</span> pacman <span class=\"token parameter variable\">-Syu</span> <span class=\"token comment\"># 升级系统</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">sudo</span> pacman <span class=\"token parameter variable\">-S</span> package_name <span class=\"token comment\"># 安装软件包</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token function\">sudo</span> pacman <span class=\"token parameter variable\">-Syu</span> package_name <span class=\"token comment\"># 升级系统并安装软件包,ArchLinux 不支持部分升级,建议用此命令先升级再安装</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token function\">sudo</span> pacman <span class=\"token parameter variable\">-Syyu</span> <span class=\"token comment\"># 升级系统 yy 标记强制刷新 u 标记升级动作</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token function\">sudo</span> pacman <span class=\"token parameter variable\">-Ss</span> package_name <span class=\"token comment\"># 搜索包含相关内容的软件包</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token function\">sudo</span> pacman <span class=\"token parameter variable\">-R</span> package_name <span class=\"token comment\"># 删除软件包</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token function\">sudo</span> pacman <span class=\"token parameter variable\">-Qi</span> package_name <span class=\"token comment\"># 查看软件包信息 </span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token function\">sudo</span> pacman <span class=\"token parameter variable\">-Q</span> <span class=\"token comment\"># 查看安装的软件包 </span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token function\">sudo</span> pacman <span class=\"token parameter variable\">-Rs</span> package_name <span class=\"token comment\"># 删除软件包,及其所有没有被其他已安装软件包使用的依赖包</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token function\">sudo</span> pacman <span class=\"token parameter variable\">-Si</span> package_name <span class=\"token comment\"># 从数据库中搜索软件包的信息</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token function\">sudo</span> pacman <span class=\"token parameter variable\">-Qdt</span> <span class=\"token comment\"># 找出孤立包 Q 为查询本地软件包数据库 d 标记依赖包 t 标记不需要的包 dt 合并标记孤立包</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token function\">sudo</span> pacman <span class=\"token parameter variable\">-Rs</span> <span class=\"token variable\"><span class=\"token variable\">$(</span>pacman <span class=\"token parameter variable\">-Qtdq</span><span class=\"token variable\">)</span></span> <span class=\"token comment\"># 删除孤立软件包</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token function\">sudo</span> pacman <span class=\"token parameter variable\">-U</span> abc.pkg.tar.gz <span class=\"token comment\"># 安装下载的 abc 包,或新编译的本地 abc 包</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre><span class=\"token function\">sudo</span> pacman <span class=\"token parameter variable\">-Fy</span> <span class=\"token comment\"># 更新命令查询文件列表数据库</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token function\">sudo</span> pacman <span class=\"token parameter variable\">-F</span> xxx <span class=\"token comment\"># 当不知道某个命令属于哪个包时,用来查询某个 xxx 命令属于哪个包</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre><span class=\"token function\">sudo</span> pacman <span class=\"token parameter variable\">-Sc</span> <span class=\"token comment\"># 清理没有安装的所有缓存包,和没有被使用的同步数据库</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>yay <span class=\"token parameter variable\">-Syu</span> <span class=\"token comment\"># 升级官方和 AUR 的软件包,包括 pacman, -syyu 强制升级</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre>yay <span class=\"token parameter variable\">-S</span> abc <span class=\"token comment\"># 安装 abc 包</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre>yay <span class=\"token parameter variable\">-Ss</span> abc <span class=\"token operator\">|</span> <span class=\"token function\">grep</span> 已安装 <span class=\"token comment\"># 搜索已安装且包含 abc 的包</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre>yay <span class=\"token parameter variable\">-R</span> 包名 <span class=\"token comment\"># 删除软件包 (不包括前后缀,版本号)</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre><span class=\"token function\">sudo</span> <span class=\"token function\">rm</span> /var/lib/pacman/db.lck <span class=\"token comment\"># 删除 /var/lib/pacman/db.lck 锁</span></pre></td></tr></table></figure><h2 id=\"系统服务的操作与介绍\"><a class=\"anchor\" href=\"#系统服务的操作与介绍\">#</a> 系统服务的操作与介绍</h2>\n<p>Linux 系统中运行着各种服务,你需要掌握查询,变更服务状态的方式。同时对创建服务最好也有大致的了解。这里讲述命令 <code>systemctl</code> 的用法。以 dhcpcd 为例</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>systemctl start dhcpcd <span class=\"token comment\"># 启动服务</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>systemctl stop dhcpcd <span class=\"token comment\"># 停止服务</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>systemctl restart dhcpcd <span class=\"token comment\"># 重启服务</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>systemctl reload dhcpcd <span class=\"token comment\"># 重新加载服务以及它的配置文件</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>systemctl status dhcpcd <span class=\"token comment\"># 查看服务状态</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>systemctl <span class=\"token builtin class-name\">enable</span> dhcpcd <span class=\"token comment\"># 设置开机启动服务</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>systemctl <span class=\"token builtin class-name\">enable</span> <span class=\"token parameter variable\">--now</span> dhcpcd <span class=\"token comment\"># 设置服务为开机启动并立即启动这个单元:</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>systemctl disable dhcpcd <span class=\"token comment\"># 取消开机自动启动</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>systemctl daemon-reload dhcpcd <span class=\"token comment\"># 重新载入 systemd 配置 扫描新增或变更的服务单元 不会重新加载变更的配置 加载变更的配置用 reload</span></pre></td></tr></table></figure><h2 id=\"换源-阿里云\"><a class=\"anchor\" href=\"#换源-阿里云\">#</a> 换源 - 阿里云</h2>\n<p>编辑文件 <code>/etc/pacman.d/mirrorlist</code> :</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">sudo</span> <span class=\"token function\">vim</span> /etc/pacman.d/mirrorlist</pre></td></tr></table></figure><p>在镜像源列表最顶端添加:</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>Server <span class=\"token operator\">=</span> http://mirrors.aliyun.com/archlinux/<span class=\"token variable\">$repo</span>/os/<span class=\"token variable\">$arch</span></pre></td></tr></table></figure><blockquote>\n<p>参考:<span class=\"exturl\" data-url=\"aHR0cHM6Ly9kZXZlbG9wZXIuYWxpeXVuLmNvbS9taXJyb3IvYXJjaGxpbnV4Y24/c3BtPWEyYzZoLjEzNjUxMTAyLjAuMC4zZTIyMWIxMU5jOFVwWQ==\">阿里云开发者社区 > 镜像站 > archlinuxcn</span></p>\n</blockquote>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">sudo</span> pacman <span class=\"token parameter variable\">-Syy</span> <span class=\"token operator\">&&</span> <span class=\"token function\">sudo</span> pacman <span class=\"token parameter variable\">-S</span> archlinuxcn-keyring <span class=\"token comment\"># 安装 archlinuxcn-keyring 包导入 GPG key</span></pre></td></tr></table></figure><h2 id=\"安装yay\"><a class=\"anchor\" href=\"#安装yay\">#</a> 安装 yay</h2>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">sudo</span> pacman <span class=\"token parameter variable\">-S</span> yay</pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token comment\">#安装完成后再次更新</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>yay <span class=\"token parameter variable\">-Syyu</span> <span class=\"token operator\">&&</span> yay <span class=\"token parameter variable\">-Sys</span></pre></td></tr></table></figure><h2 id=\"常见问题及其解决\"><a class=\"anchor\" href=\"#常见问题及其解决\">#</a> 常见问题及其解决</h2>\n<ul>\n<li>\n<p>使用 yay 命令时报错:</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>搜索 AUR 时出错: response decoding failed: invalid character <span class=\"token string\">'<'</span> looking <span class=\"token keyword\">for</span></pre></td></tr></table></figure><ul>\n<li>解决:</li>\n</ul>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>yay <span class=\"token parameter variable\">--aururl</span> <span class=\"token string\">\"https://aur.archlinux.org\"</span> <span class=\"token parameter variable\">--save</span></pre></td></tr></table></figure></li>\n<li>\n<p>Telegram 无法登陆:</p>\n<ul>\n<li>解决:<br />\nSETTING 中添加地址,使用代理,port 选择代理所使用端口号。</li>\n</ul>\n</li>\n<li>\n<p>连接显示器无法使用:</p>\n<ul>\n<li>解决:<br />\n根据<span class=\"exturl\" data-url=\"aHR0cHM6Ly9hcmNobGludXhzdHVkaW8uZ2l0aHViLmlvL0FyY2hMaW51eFR1dG9yaWFsLyMv\"> Linux 安装使用教程</span>中<strong>显卡驱动</strong>所描述进行即可。</li>\n</ul>\n</li>\n<li>\n<p>VSCode 无法唤出外部终端:</p>\n<ul>\n<li>解决:<br />\n <code>.vscode</code> 文件中设置启用外部终端,在 <code>settings.json</code> 文件中加入 "terminal.external.linuxExec": "/usr/bin/konsole", "" 内指要调用的终端 bin/konsole。</li>\n</ul>\n</li>\n<li>\n<p>在升级系统(syu)时,出现以下内容:</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>错误:python-markdown: 来自 <span class=\"token string\">\"Caleb Maclennan <alerque@archlinux.org>\"</span> 的签名是勉强信任的</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>:: 文件 /var/cache/pacman/pkg/python-markdown-3.3.6-1-any.pkg.tar.zst 已损坏 <span class=\"token punctuation\">(</span>无效或已损坏的软件包 <span class=\"token punctuation\">(</span>PGP 签名<span class=\"token punctuation\">))</span>.</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>打算删除吗? <span class=\"token punctuation\">[</span>Y/n<span class=\"token punctuation\">]</span> </pre></td></tr><tr><td data-num=\"4\"></td><td><pre>错误:trash-cli: 来自 <span class=\"token string\">\"Alexander Epaneshnikov <alex19ep@archlinux.org>\"</span> 的签名是勉强信任的</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>:: 文件 /var/cache/pacman/pkg/trash-cli-0.21.10.24-1-any.pkg.tar.zst 已损坏 <span class=\"token punctuation\">(</span>无效或已损坏的软件包 <span class=\"token punctuation\">(</span>PGP 签名<span class=\"token punctuation\">))</span>.</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>打算删除吗? <span class=\"token punctuation\">[</span>Y/n<span class=\"token punctuation\">]</span> </pre></td></tr><tr><td data-num=\"7\"></td><td><pre>错误:无法提交处理 <span class=\"token punctuation\">(</span>无效或已损坏的软件包<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>发生错误,没有软件包被更新。</pre></td></tr></table></figure><ul>\n<li>\n<p>解决:</p>\n<p>终端输入: <code>sudo pacman-key --init && sudo pacman-key --populate && sudo pacman -Syyu</code></p>\n<p>可能的方法: <code>sudo pacman -S archlinux-keyring</code></p>\n</li>\n</ul>\n</li>\n</ul>\n<h2 id=\"使用docker\"><a class=\"anchor\" href=\"#使用docker\">#</a> 使用 Docker</h2>\n<ol>\n<li>\n<p>安装:</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">sudo</span> pacman <span class=\"token parameter variable\">-S</span> <span class=\"token function\">docker</span> <span class=\"token comment\"># 安装 Docker -Ss 搜索 Docker 软件包</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">sudo</span> systemctl <span class=\"token builtin class-name\">enable</span> docker.service <span class=\"token comment\"># 开启 Docker 开机自启动服务</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token function\">sudo</span> systemctl start docker.service <span class=\"token comment\"># 启动 Docker 服务</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\"># 安装好 docker 后自动建立了 docker 组,不需要自己添加 docker 组,只需要把当前工作用户加入 docker 组即可</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token function\">sudo</span> gpasswd <span class=\"token parameter variable\">-a</span> <span class=\"token environment constant\">$USER</span> <span class=\"token function\">docker</span> <span class=\"token comment\"># 把工作用户加入 Docker 组,避免使用 root 账号工作</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token comment\">#重启系统生效</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token function\">sudo</span> systemctl disable docker.service <span class=\"token comment\"># 关闭开机自启动服务</span></pre></td></tr></table></figure></li>\n<li>\n<p>获取镜像:</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">docker</span> pull archlinux <span class=\"token comment\"># 下载镜像</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">docker</span> image <span class=\"token function\">ls</span> <span class=\"token comment\"># 列出镜像列表</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token function\">docker</span> <span class=\"token function\">ps</span> <span class=\"token parameter variable\">-a</span> <span class=\"token comment\"># 列出容器列表</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token function\">docker</span> run <span class=\"token parameter variable\">-it</span> archlinux /bin/bash <span class=\"token comment\"># 用所给镜像启动一个新的容器</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token function\">docker</span> run <span class=\"token parameter variable\">--rm</span> <span class=\"token parameter variable\">-it</span> <span class=\"token parameter variable\">--net</span><span class=\"token operator\">=</span>host gpt-academic <span class=\"token comment\"># 用所给镜像启动一个新的容器</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token function\">docker</span> <span class=\"token builtin class-name\">exec</span> <span class=\"token parameter variable\">-it</span> <span class=\"token operator\"><</span>CONTAINER_NAME<span class=\"token operator\">></span> <span class=\"token function\">bash</span> <span class=\"token comment\"># 进入一个正在运行的 docker (在容器内部创建一个子进程)</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token function\">docker</span> stop <span class=\"token punctuation\">[</span>contaionerID<span class=\"token punctuation\">]</span> <span class=\"token comment\"># 终止镜像</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token function\">docker</span> rmi <span class=\"token variable\"><span class=\"token variable\">$(</span><span class=\"token function\">docker</span> images <span class=\"token parameter variable\">-q</span><span class=\"token variable\">)</span></span> <span class=\"token comment\"># 删除所有镜像</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token function\">docker</span> stop <span class=\"token variable\"><span class=\"token variable\">$(</span><span class=\"token function\">docker</span> <span class=\"token function\">ps</span> <span class=\"token parameter variable\">-aq</span><span class=\"token variable\">)</span></span> <span class=\"token comment\"># 停止所有容器</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token function\">docker</span> container <span class=\"token function\">rm</span> <span class=\"token punctuation\">[</span>contaionerID<span class=\"token punctuation\">]</span> <span class=\"token comment\"># 删除一个处于终止状态的容器</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token function\">docker</span> container <span class=\"token function\">rm</span> <span class=\"token variable\"><span class=\"token variable\">$(</span><span class=\"token function\">docker</span> images <span class=\"token parameter variable\">-q</span><span class=\"token variable\">)</span></span> <span class=\"token comment\"># 删除所有容器</span></pre></td></tr></table></figure></li>\n<li>\n<p>配置镜像:</p>\n<p>启动镜像,配置初始开发环境,安装了一些包(可能有些没有用),</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">docker</span> run <span class=\"token parameter variable\">-t</span> <span class=\"token parameter variable\">-i</span> archlinux /bin/bash <span class=\"token comment\"># 启动镜像</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token comment\"># 在 docker 内输入以下内容</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token function\">sed</span> <span class=\"token parameter variable\">-i</span> <span class=\"token string\">'1i Server = http://mirrors.aliyun.com/archlinux/$repo/os/$arch'</span> /etc/pacman.d/mirrorlist <span class=\"token punctuation\">\\</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre> <span class=\"token operator\">&&</span> <span class=\"token function\">sed</span> <span class=\"token parameter variable\">-i</span> <span class=\"token string\">'1i Server = https://mirrors.tencent.com/archlinux/$repo/os/$arch'</span> /etc/pacman.d/mirrorlist <span class=\"token punctuation\">\\</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre> <span class=\"token operator\">&&</span> <span class=\"token function\">sed</span> <span class=\"token parameter variable\">-i</span> <span class=\"token string\">'$i [archlinuxcn]'</span> /etc/pacman.conf <span class=\"token punctuation\">\\</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre> <span class=\"token operator\">&&</span> <span class=\"token function\">sed</span> <span class=\"token parameter variable\">-i</span> <span class=\"token string\">'$i SigLevel = TrustAll'</span> /etc/pacman.conf <span class=\"token punctuation\">\\</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre> <span class=\"token operator\">&&</span> <span class=\"token function\">sed</span> <span class=\"token parameter variable\">-i</span> <span class=\"token string\">'$i Server = https://repo.archlinuxcn.org/$arch'</span> /etc/pacman.conf <span class=\"token punctuation\">\\</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre> <span class=\"token operator\">&&</span> <span class=\"token function\">sed</span> <span class=\"token parameter variable\">-i</span> <span class=\"token parameter variable\">-r</span> <span class=\"token string\">'s/^NoExtract\\s*=\\s*.*/# \\0/g'</span> /etc/pacman.conf <span class=\"token punctuation\">\\</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre> <span class=\"token operator\">&&</span> pacman <span class=\"token parameter variable\">-Syyu</span> <span class=\"token parameter variable\">--noconfirm</span> <span class=\"token punctuation\">\\</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre> <span class=\"token operator\">&&</span> pacman <span class=\"token parameter variable\">-Sy</span> <span class=\"token parameter variable\">--noconfirm</span> archlinuxcn-keyring <span class=\"token operator\">&&</span> pacman <span class=\"token parameter variable\">-Su</span> --noconfirm<span class=\"token punctuation\">\\</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre> <span class=\"token operator\">&&</span> pacman <span class=\"token parameter variable\">-Syy</span> <span class=\"token parameter variable\">--noconfirm</span> <span class=\"token function\">git</span> <span class=\"token function\">vim</span> neovim <span class=\"token function\">zsh</span> oh-my-zsh-git jdk-openjdk jdk8-openjdk jdk11-openjdk <span class=\"token punctuation\">\\</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre> maven yay <span class=\"token function\">zsh</span> python3 go nodejs <span class=\"token function\">npm</span> <span class=\"token function\">yarn</span> tmux python2 zsh-autosuggestions zsh-syntax-highlighting <span class=\"token punctuation\">\\</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre> zsh-theme-powerlevel10k ranger python-pip python-neovim wl-clipboard fzf ripgrep man-db <span class=\"token punctuation\">\\</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre> gcc clang base-devel wqy-zenhei noto-fonts-cjk <span class=\"token function\">wget</span> <span class=\"token function\">unzip</span> thefuck <span class=\"token punctuation\">\\</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre> <span class=\"token operator\">&&</span> <span class=\"token function\">ln</span> <span class=\"token parameter variable\">-sf</span> /usr/share/zoneinfo/Asia/Shanghai /etc/localtime <span class=\"token punctuation\">\\</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre> <span class=\"token operator\">&&</span> pacman <span class=\"token parameter variable\">-Scc</span> <span class=\"token parameter variable\">--noconfirm</span> <span class=\"token punctuation\">\\</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre> <span class=\"token operator\">&&</span> <span class=\"token function\">rm</span> <span class=\"token parameter variable\">-rf</span> /var/lib/pacman/sync/* /var/cache/pacman/pkg/* <span class=\"token punctuation\">\\</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre> <span class=\"token operator\">&&</span> <span class=\"token builtin class-name\">echo</span> <span class=\"token string\">\"\"</span> <span class=\"token operator\">></span> /var/log/pacman.log</pre></td></tr></table></figure><p>精简版本:</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">sed</span> <span class=\"token parameter variable\">-i</span> <span class=\"token string\">'1i Server = http://mirrors.aliyun.com/archlinux/$repo/os/$arch'</span> /etc/pacman.d/mirrorlist <span class=\"token punctuation\">\\</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre> <span class=\"token operator\">&&</span> <span class=\"token function\">sed</span> <span class=\"token parameter variable\">-i</span> <span class=\"token string\">'1i Server = https://mirrors.tencent.com/archlinux/$repo/os/$arch'</span> /etc/pacman.d/mirrorlist <span class=\"token punctuation\">\\</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre> <span class=\"token operator\">&&</span> <span class=\"token function\">sed</span> <span class=\"token parameter variable\">-i</span> <span class=\"token string\">'$i [archlinuxcn]'</span> /etc/pacman.conf <span class=\"token punctuation\">\\</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre> <span class=\"token operator\">&&</span> <span class=\"token function\">sed</span> <span class=\"token parameter variable\">-i</span> <span class=\"token string\">'$i SigLevel = TrustAll'</span> /etc/pacman.conf <span class=\"token punctuation\">\\</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre> <span class=\"token operator\">&&</span> <span class=\"token function\">sed</span> <span class=\"token parameter variable\">-i</span> <span class=\"token string\">'$i Server = https://repo.archlinuxcn.org/$arch'</span> /etc/pacman.conf <span class=\"token punctuation\">\\</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre> <span class=\"token operator\">&&</span> <span class=\"token function\">sed</span> <span class=\"token parameter variable\">-i</span> <span class=\"token parameter variable\">-r</span> <span class=\"token string\">'s/^NoExtract\\s*=\\s*.*/# \\0/g'</span> /etc/pacman.conf <span class=\"token punctuation\">\\</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre> <span class=\"token operator\">&&</span> pacman <span class=\"token parameter variable\">-Syyu</span> <span class=\"token parameter variable\">--noconfirm</span> <span class=\"token punctuation\">\\</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre> <span class=\"token operator\">&&</span> pacman <span class=\"token parameter variable\">-Sy</span> <span class=\"token parameter variable\">--noconfirm</span> archlinuxcn-keyring <span class=\"token operator\">&&</span> pacman <span class=\"token parameter variable\">-Su</span> --noconfirm<span class=\"token punctuation\">\\</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre> <span class=\"token operator\">&&</span> pacman <span class=\"token parameter variable\">-Syy</span> <span class=\"token parameter variable\">--noconfirm</span> <span class=\"token function\">git</span> <span class=\"token function\">vim</span> neovim <span class=\"token punctuation\">\\</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre> maven yay go <span class=\"token function\">npm</span> <span class=\"token function\">yarn</span> tmux <span class=\"token punctuation\">\\</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre> ranger python-pip python-neovim wl-clipboard fzf ripgrep man-db <span class=\"token punctuation\">\\</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre> gcc clang base-devel wqy-zenhei noto-fonts-cjk <span class=\"token function\">wget</span> <span class=\"token function\">unzip</span> thefuck <span class=\"token punctuation\">\\</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre> <span class=\"token operator\">&&</span> <span class=\"token function\">ln</span> <span class=\"token parameter variable\">-sf</span> /usr/share/zoneinfo/Asia/Shanghai /etc/localtime <span class=\"token punctuation\">\\</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre> <span class=\"token operator\">&&</span> pacman <span class=\"token parameter variable\">-Scc</span> <span class=\"token parameter variable\">--noconfirm</span> <span class=\"token punctuation\">\\</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre> <span class=\"token operator\">&&</span> <span class=\"token function\">rm</span> <span class=\"token parameter variable\">-rf</span> /var/lib/pacman/sync/* /var/cache/pacman/pkg/* <span class=\"token punctuation\">\\</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre> <span class=\"token operator\">&&</span> <span class=\"token builtin class-name\">echo</span> <span class=\"token string\">\"\"</span> <span class=\"token operator\">></span> /var/log/pacman.log</pre></td></tr></table></figure></li>\n<li>\n<p>配置 vscode:</p>\n<p>下载插件:Remote Development Pack(包含 Remote-Containers),Docker。打开插件,在 CONTAINERS 中右键 Attach Visual Studio Code,在 vscode 中运行了镜像,重新安装一些扩展,当作一个新的 archlinux 一样使用。</p>\n</li>\n<li>\n<p>容器和本地间的文件传输:</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">docker</span> <span class=\"token function\">ps</span> <span class=\"token parameter variable\">-a</span> <span class=\"token comment\"># 获得容器 ID</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">docker</span> <span class=\"token function\">cp</span> 本地文件路径 ID全称:容器路径 <span class=\"token comment\"># 本地文件复制到容器</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token function\">docker</span> <span class=\"token function\">cp</span> ID全称:容器文件路径 本地路径 <span class=\"token comment\"># 容器文件复制到本地</span></pre></td></tr></table></figure></li>\n</ol>\n<h2 id=\"typorapicgogithub图床\"><a class=\"anchor\" href=\"#typorapicgogithub图床\">#</a> Typora+PicGo+Github 图床</h2>\n<p>整体遵循:<span class=\"exturl\" data-url=\"aHR0cHM6Ly9qdWVqaW4uY24vcG9zdC82ODQ0OTA0MTM3NDA3MDg2NjAwI2hlYWRpbmctOA==\">https://juejin.cn/post/6844904137407086600#heading-8</span></p>\n<ol>\n<li>创建 GIthub 仓库并创建 Token 并复制</li>\n<li>下载 PicGo(app)并配置,包括时间戳命名,选择 github 图床,仓库名,分支用 main,设定 Token</li>\n<li>下载并配置 node.js</li>\n<li>配置 Typora 并测试图床</li>\n</ol>\n<h3 id=\"编译安装从-github-下载的源码\"><a class=\"anchor\" href=\"#编译安装从-github-下载的源码\">#</a> 编译安装从 GitHub 下载的源码</h3>\n<ol>\n<li>\n<p>执行以下命令,生成 Makefile 文件:</p>\n<p><code>./autogen.sh</code></p>\n</li>\n<li>\n<p>如果下载的源代码中已经包含了 Makefile 文件,则可以跳过此步骤。</p>\n</li>\n<li>\n<p>执行以下命令,配置编译选项:</p>\n<p><code>./configure</code></p>\n<p>configure 脚本会检查系统环境和依赖库,并生成 Makefile 文件。可以通过指定不同的选项来定制编译过程。</p>\n<p>例如,可以使用 --prefix 选项指定安装目录,使用 --enable-shared 选项生成共享库等。</p>\n</li>\n<li>\n<p>执行以下命令,开始编译:</p>\n<p><code>make</code></p>\n<p>这个命令会编译源代码,并生成可执行文件或共享库等。</p>\n</li>\n<li>\n<p>执行以下命令,安装编译好的文件:</p>\n</li>\n<li>\n<p><code>sudo make install</code></p>\n<p>这个命令会将编译好的文件安装到系统中,通常是 /usr/local 目录。 如果在执行 configure 或 make 命令时遇到了错误,可以根据错误信息进行调整。通常情况下,错误信息会提示缺少依赖库或者系统环境不兼容等问题。</p>\n</li>\n</ol>\n<h2 id=\"安装deb包\"><a class=\"anchor\" href=\"#安装deb包\">#</a> 安装 deb 包</h2>\n<ol>\n<li>使用 yay 安装 debtap。 <code>yay -S debtap</code></li>\n<li>升级的 debtap。 <code>sudo debtap -U</code></li>\n<li>转换 deb 包,生成一个 <code>yourfile.zst</code> 文件。 <code>sudo debtap yourfile.deb</code> (接两次回车)</li>\n<li>安装转换后的包。 <code>sudo pacman -U yourfile.zst</code></li>\n</ol>\n<h2 id=\"压缩文件\"><a class=\"anchor\" href=\"#压缩文件\">#</a> 压缩文件</h2>\n<ul>\n<li><code>-c</code> :生成一个新的归档文件</li>\n<li><code>-f</code> :输出到文件中,</li>\n<li><code>-z</code> & <code>-j</code> :将 tar 压缩成 gzip 和 bzip2 格式。</li>\n<li><code>archive</code> :压缩文件的名称</li>\n<li><code>/path/to/folder</code> :要压缩的文件夹的路径。</li>\n</ul>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 将文件夹压缩成 .tar 文件:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>copy codetar <span class=\"token parameter variable\">-cf</span> archive.tar /path/to/folder</pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\"># 将文件夹压缩成 .tar.gz 文件:</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>copy codetar <span class=\"token parameter variable\">-czf</span> archive.tar.gz /path/to/folder</pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token comment\"># 将文件夹压缩成 .tar.bz2 文件:</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>copy codetar <span class=\"token parameter variable\">-cjf</span> archive.tar.bz2 /path/to/folder</pre></td></tr></table></figure><h2 id=\"安装qq\"><a class=\"anchor\" href=\"#安装qq\">#</a> 安装 QQ</h2>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>yay <span class=\"token parameter variable\">-Ss</span> linuxqq <span class=\"token comment\"># 在 AUR 查找 linuxQQ </span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>yay <span class=\"token parameter variable\">-S</span> linuxqq <span class=\"token comment\"># 从 AUR 安装 linuxqq</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token function\">sudo</span> pacman <span class=\"token parameter variable\">-Rns</span> linuxqq <span class=\"token comment\"># 删除 linuxqq 及不再需要的依赖</span></pre></td></tr></table></figure><h3 id=\"登陆后闪退的可能解决办法\"><a class=\"anchor\" href=\"#登陆后闪退的可能解决办法\">#</a> 登陆后闪退的可能解决办法:</h3>\n<p>删除 <code>~/.config/QQ</code> 下的所有文件,重启 QQ 进行登陆并在设置里关闭 QQ 自己的更新。</p>\n<p>其他问题请自行在 Google 或者在<span class=\"exturl\" data-url=\"aHR0cHM6Ly9iYnMuYXJjaGxpbnV4Y24ub3JnL2luZGV4LnBocA==\"> Arch 中文社区</span>寻找解决方案</p>\n<h2 id=\"安装-fcitx5及中文输入法\"><a class=\"anchor\" href=\"#安装-fcitx5及中文输入法\">#</a> 安装 fcitx5 及中文输入法</h2>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">sudo</span> pacman <span class=\"token parameter variable\">-S</span> fcitx5-im </pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">sudo</span> pacman <span class=\"token parameter variable\">-S</span> fcitx5-chinese-addons fcitx5-rime</pre></td></tr></table></figure><p><code>sudo vim /etc/environment</code> ,添加如下内容,之后重启输入法:</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token assign-left variable\">GTK_IM_MODULE</span><span class=\"token operator\">=</span>fcitx</pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token assign-left variable\">QT_IM_MODULE</span><span class=\"token operator\">=</span>fcitx</pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token assign-left variable\"><span class=\"token environment constant\">XMODIFIERS</span></span><span class=\"token operator\">=</span>@im<span class=\"token operator\">=</span>fcitx</pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token assign-left variable\">SDL_IM_MODULE</span><span class=\"token operator\">=</span>fcitx</pre></td></tr></table></figure><p>在设置中找到输入法,添加输入法,选拼音</p>\n<h3 id=\"中文标点消失\"><a class=\"anchor\" href=\"#中文标点消失\">#</a> 中文标点消失:</h3>\n<ul>\n<li>\n<p>编辑~/.config/fcitx/data/punc.mb.zh_CN,自行查找</p>\n</li>\n<li>\n<p>[ctrl+.]</p>\n</li>\n</ul>\n<h2 id=\"安装zsh\"><a class=\"anchor\" href=\"#安装zsh\">#</a> 安装 zsh</h2>\n<h3 id=\"编辑配置文件\"><a class=\"anchor\" href=\"#编辑配置文件\">#</a> 编辑配置文件:</h3>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">vim</span> ~/.zshrc</pre></td></tr></table></figure><p>目前的:</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">if</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">[</span> <span class=\"token parameter variable\">-r</span> <span class=\"token string\">\"<span class=\"token variable\">${XDG_CACHE_HOME<span class=\"token operator\">:-</span>$HOME<span class=\"token operator\">/</span>.cache}</span>/p12k-instant-prompt-<span class=\"token variable\">${(<span class=\"token operator\">%</span>)<span class=\"token operator\">:-</span><span class=\"token operator\">%</span>n}</span>.zsh\"</span> <span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> <span class=\"token keyword\">then</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre> <span class=\"token builtin class-name\">source</span> <span class=\"token string\">\"<span class=\"token variable\">${XDG_CACHE_HOME<span class=\"token operator\">:-</span>$HOME<span class=\"token operator\">/</span>.cache}</span>/p11k-instant-prompt-<span class=\"token variable\">${(<span class=\"token operator\">%</span>)<span class=\"token operator\">:-</span><span class=\"token operator\">%</span>n}</span>.zsh\"</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">fi</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token assign-left variable\">ZSH</span><span class=\"token operator\">=</span>/usr/share/oh-my-zsh/</pre></td></tr><tr><td data-num=\"7\"></td><td><pre></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token assign-left variable\">ZSH_THEME</span><span class=\"token operator\">=</span><span class=\"token string\">\"powerlevel10k/powerlevel10k\"</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token assign-left variable\">plugins</span><span class=\"token operator\">=</span><span class=\"token punctuation\">(</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>\t<span class=\"token function\">sudo</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre>\t<span class=\"token function\">git</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre>\tautojump</pre></td></tr><tr><td data-num=\"14\"></td><td><pre>\tzsh-syntax-highlighting</pre></td></tr><tr><td data-num=\"15\"></td><td><pre>\tzsh-autosuggestions</pre></td></tr><tr><td data-num=\"16\"></td><td><pre><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre></pre></td></tr><tr><td data-num=\"18\"></td><td><pre><span class=\"token assign-left variable\">ZSH_CACHE_DIR</span><span class=\"token operator\">=</span><span class=\"token environment constant\">$HOME</span>/.cache/oh-my-zsh</pre></td></tr><tr><td data-num=\"19\"></td><td><pre><span class=\"token keyword\">if</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">[</span> <span class=\"token operator\">!</span> <span class=\"token parameter variable\">-d</span> <span class=\"token variable\">$ZSH_CACHE_DIR</span> <span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> <span class=\"token keyword\">then</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre> <span class=\"token function\">mkdir</span> <span class=\"token variable\">$ZSH_CACHE_DIR</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre><span class=\"token keyword\">fi</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre></pre></td></tr><tr><td data-num=\"23\"></td><td><pre></pre></td></tr><tr><td data-num=\"24\"></td><td><pre><span class=\"token builtin class-name\">source</span> <span class=\"token variable\">$ZSH</span>/oh-my-zsh.sh</pre></td></tr><tr><td data-num=\"25\"></td><td><pre></pre></td></tr><tr><td data-num=\"26\"></td><td><pre><span class=\"token comment\"># To customize prompt, run `p10k configure` or edit ~/.p10k.zsh.</span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre><span class=\"token punctuation\">[</span><span class=\"token punctuation\">[</span> <span class=\"token operator\">!</span> <span class=\"token parameter variable\">-f</span> ~/.p10k.zsh <span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">||</span> <span class=\"token builtin class-name\">source</span> ~/.p10k.zsh</pre></td></tr><tr><td data-num=\"28\"></td><td><pre><span class=\"token comment\"># other name</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre><span class=\"token builtin class-name\">alias</span> <span class=\"token assign-left variable\">sp</span><span class=\"token operator\">=</span><span class=\"token string\">'sudo pacman'</span> </pre></td></tr><tr><td data-num=\"30\"></td><td><pre><span class=\"token builtin class-name\">alias</span> <span class=\"token assign-left variable\">syyu</span><span class=\"token operator\">=</span><span class=\"token string\">'yay -Syyu'</span> <span class=\"token comment\"># 强制升级系统和软件包</span></pre></td></tr><tr><td data-num=\"31\"></td><td><pre><span class=\"token builtin class-name\">alias</span> <span class=\"token assign-left variable\">syu</span><span class=\"token operator\">=</span><span class=\"token string\">'yay -Syu'</span> <span class=\"token comment\"># 升级系统和软件包</span></pre></td></tr><tr><td data-num=\"32\"></td><td><pre><span class=\"token builtin class-name\">alias</span> <span class=\"token assign-left variable\">c</span><span class=\"token operator\">=</span><span class=\"token string\">'clear'</span> <span class=\"token comment\"># 清屏</span></pre></td></tr><tr><td data-num=\"33\"></td><td><pre><span class=\"token builtin class-name\">alias</span> <span class=\"token assign-left variable\">e</span><span class=\"token operator\">=</span><span class=\"token string\">'exit'</span> <span class=\"token comment\"># 退出终端</span></pre></td></tr><tr><td data-num=\"34\"></td><td><pre><span class=\"token builtin class-name\">alias</span> <span class=\"token assign-left variable\">qq</span><span class=\"token operator\">=</span><span class=\"token string\">'rm -rf ~/.config/QQ/ && linuxqq &'</span> <span class=\"token comment\"># 启动 QQ 时删除文件</span></pre></td></tr><tr><td data-num=\"35\"></td><td><pre></pre></td></tr><tr><td data-num=\"36\"></td><td><pre><span class=\"token comment\"># git 快捷键 cd+add+commit+push+cd</span></pre></td></tr><tr><td data-num=\"37\"></td><td><pre></pre></td></tr><tr><td data-num=\"38\"></td><td><pre><span class=\"token comment\"># 将本地 Note 仓库提交到 gihub</span></pre></td></tr><tr><td data-num=\"39\"></td><td><pre><span class=\"token builtin class-name\">alias</span> <span class=\"token assign-left variable\">gpn</span><span class=\"token operator\">=</span><span class=\"token string\">'cd /home/origin/Code/repository/Note && git add . && git commit -m \\\"update\\\" && git push && cd -'</span></pre></td></tr><tr><td data-num=\"40\"></td><td><pre></pre></td></tr><tr><td data-num=\"41\"></td><td><pre><span class=\"token comment\"># 将本地 Code_c 仓库提交到 gihub</span></pre></td></tr><tr><td data-num=\"42\"></td><td><pre><span class=\"token builtin class-name\">alias</span> <span class=\"token assign-left variable\">gpc</span><span class=\"token operator\">=</span><span class=\"token string\">'cd /home/origin/Code/repository/Code_c && git add . && git commit -m \\\"update\\\" && git push && cd -'</span></pre></td></tr><tr><td data-num=\"43\"></td><td><pre></pre></td></tr><tr><td data-num=\"44\"></td><td><pre><span class=\"token comment\"># 将本地 Code_cc 仓库提交到 gihub</span></pre></td></tr><tr><td data-num=\"45\"></td><td><pre><span class=\"token builtin class-name\">alias</span> <span class=\"token assign-left variable\">gpcc</span><span class=\"token operator\">=</span><span class=\"token string\">'cd /home/origin/Code/repository/Code_cc && git add . && git commit -m \\\"update\\\" && git push && cd -'</span></pre></td></tr><tr><td data-num=\"46\"></td><td><pre></pre></td></tr><tr><td data-num=\"47\"></td><td><pre><span class=\"token comment\"># 将本地 Python 仓库提交到 gihub</span></pre></td></tr><tr><td data-num=\"48\"></td><td><pre><span class=\"token builtin class-name\">alias</span> <span class=\"token assign-left variable\">gppy</span><span class=\"token operator\">=</span><span class=\"token string\">'cd /home/origin/Code/repository/Code_py && git add . && git commit -m \\\"update\\\" && git push && cd -'</span></pre></td></tr><tr><td data-num=\"49\"></td><td><pre></pre></td></tr><tr><td data-num=\"50\"></td><td><pre><span class=\"token comment\"># 将本地 my-xv6-labs-2022 仓库提交到 gihub</span></pre></td></tr><tr><td data-num=\"51\"></td><td><pre><span class=\"token builtin class-name\">alias</span> <span class=\"token assign-left variable\">gplab</span><span class=\"token operator\">=</span><span class=\"token string\">'cd /home/origin/Code/repository/my-xv6-labs-2022 && git add . && git commit -m \\\"update\\\" && git push &&cd -'</span></pre></td></tr><tr><td data-num=\"52\"></td><td><pre></pre></td></tr><tr><td data-num=\"53\"></td><td><pre><span class=\"token builtin class-name\">export</span> <span class=\"token assign-left variable\">GOPATH</span><span class=\"token operator\">=</span><span class=\"token string\">\"<span class=\"token environment constant\">$HOME</span>/go\"</span></pre></td></tr><tr><td data-num=\"54\"></td><td><pre><span class=\"token builtin class-name\">export</span> <span class=\"token assign-left variable\"><span class=\"token environment constant\">PATH</span></span><span class=\"token operator\">=</span><span class=\"token string\">\"<span class=\"token environment constant\">$PATH</span>:/usr/lib/go/bin:<span class=\"token variable\">$GOPATH</span>/bin\"</span></pre></td></tr><tr><td data-num=\"55\"></td><td><pre><span class=\"token builtin class-name\">export</span> <span class=\"token assign-left variable\"><span class=\"token environment constant\">PATH</span></span><span class=\"token operator\">=</span>/usr/sbin:<span class=\"token environment constant\">$PATH</span></pre></td></tr></table></figure><p>## 为一个文件或目录创建一个符号链接:</p>\n<p>在 <code>/usr/local/local</code> 中存有已经建立的符号链接,在 <code>/usr/share</code> 中有通过自行下载的装包安装的软件,如通过官网安装包安装的 code。</p>\n<p>输入 <code>ln -s [文件/目录路径] [建立后的软链接名称]</code> ,即可建立链接。如: <code>ln -s /usr/share/code/code code</code></p>\n<h2 id=\"更改默认jva环境\"><a class=\"anchor\" href=\"#更改默认jva环境\">#</a> 更改默认 Jva 环境</h2>\n<h3 id=\"安装java环境java-20-jdk\"><a class=\"anchor\" href=\"#安装java环境java-20-jdk\">#</a> 安装 Java 环境(Java-20-jdk)</h3>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">sudo</span> pacman <span class=\"token parameter variable\">-Sy</span> <span class=\"token parameter variable\">--needed</span> <span class=\"token parameter variable\">--noconfirm</span> jdk</pre></td></tr></table></figure><p>输入</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>archlinux-java status</pre></td></tr></table></figure><p>若出现类似下面,即为安装成功</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>Available Java environments:</pre></td></tr><tr><td data-num=\"2\"></td><td><pre> java-21-jdk</pre></td></tr><tr><td data-num=\"3\"></td><td><pre> java-21-openjdk</pre></td></tr><tr><td data-num=\"4\"></td><td><pre> java-8-openjdk <span class=\"token punctuation\">(</span>default<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>若 java-21-openjdk 为 default 则已成功将 java21 设置为默认环境,若不是,则输入</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">sudo</span> archlinux-java <span class=\"token builtin class-name\">set</span> java-20-openjdk<span class=\"token punctuation\">[</span>你想要设为默认的java环境名<span class=\"token punctuation\">]</span></pre></td></tr></table></figure><p>后输入 <code>archlinux-java status</code> 查看, java-21-openjdk 已是 default</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>Available Java environments:</pre></td></tr><tr><td data-num=\"2\"></td><td><pre> java-21-jdk</pre></td></tr><tr><td data-num=\"3\"></td><td><pre> java-21-openjdk <span class=\"token punctuation\">(</span>default<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre> java-8-openjdk</pre></td></tr></table></figure><h2 id=\"archlinux内存管理\"><a class=\"anchor\" href=\"#archlinux内存管理\">#</a> ArchLinux 内存管理</h2>\n<ol>\n<li>\n<p>清除 Arch Linux 上的包缓存和 AUR 软件包</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>pacman <span class=\"token parameter variable\">-Scc</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>yay <span class=\"token parameter variable\">-Scc</span></pre></td></tr></table></figure><p>Arch Linux 在 /var/cache/pacman/pkg/ 目录中存储下载的每个软件包,包括升级。如果更新破坏了软件包,便于回滚到以前的版本。 /home/origin/.cache/yay 存有 AUR 的软件包。下面的名令将从缓存 /var/cache/pacman/pkg/ 中删除当前未安装的所有包。在命令中添加另一个 **-c**(最后有两个 c)标志将删除所有缓存的包。</p>\n</li>\n<li>\n<p>删除孤立的软件包</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">sudo</span> pacman <span class=\"token parameter variable\">-Qtdq</span> 查看删除孤立的软件包</pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">sudo</span> pacman <span class=\"token parameter variable\">-Rns</span> <span class=\"token variable\"><span class=\"token variable\">$(</span>pacman <span class=\"token parameter variable\">-Qtdq</span><span class=\"token variable\">)</span></span></pre></td></tr></table></figure></li>\n<li>\n<p>清理日志,设置了固定大小为 50M,多的日志会被删掉。</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>journalctl --vacuum-size<span class=\"token operator\">=</span>50M</pre></td></tr></table></figure></li>\n</ol>\n<h2 id=\"python-使用-pip-遇到问题\"><a class=\"anchor\" href=\"#python-使用-pip-遇到问题\">#</a> python 使用 pip 遇到问题</h2>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>pip <span class=\"token function\">install</span> scikit-learn</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>error: externally-managed-environment</pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>× This environment is externally managed</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>╰─<span class=\"token operator\">></span> To <span class=\"token function\">install</span> Python packages system-wide, try <span class=\"token string\">'pacman -S</pre></td></tr><tr><td data-num=\"6\"></td><td><pre> python-xyz'</span>, where xyz is the package you are trying to</pre></td></tr><tr><td data-num=\"7\"></td><td><pre> install.</pre></td></tr><tr><td data-num=\"8\"></td><td><pre> </pre></td></tr><tr><td data-num=\"9\"></td><td><pre> If you wish to <span class=\"token function\">install</span> a non-Arch-packaged Python package,</pre></td></tr><tr><td data-num=\"10\"></td><td><pre> create a virtual environment using <span class=\"token string\">'python -m venv path/to/venv'</span><span class=\"token builtin class-name\">.</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre> Then use path/to/venv/bin/python and path/to/venv/bin/pip.</pre></td></tr><tr><td data-num=\"12\"></td><td><pre> </pre></td></tr><tr><td data-num=\"13\"></td><td><pre> If you wish to <span class=\"token function\">install</span> a non-Arch packaged Python application,</pre></td></tr><tr><td data-num=\"14\"></td><td><pre> it may be easiest to use <span class=\"token string\">'pipx install xyz'</span>, <span class=\"token function\">which</span> will manage a</pre></td></tr><tr><td data-num=\"15\"></td><td><pre> virtual environment <span class=\"token keyword\">for</span> you. Make sure you have python-pipx</pre></td></tr><tr><td data-num=\"16\"></td><td><pre> installed via pacman.</pre></td></tr><tr><td data-num=\"17\"></td><td><pre></pre></td></tr><tr><td data-num=\"18\"></td><td><pre>note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.</pre></td></tr><tr><td data-num=\"19\"></td><td><pre>hint: See PEP <span class=\"token number\">668</span> <span class=\"token keyword\">for</span> the detailed specification.</pre></td></tr></table></figure><p>解决:</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">sudo</span> <span class=\"token function\">rm</span> /usr/lib/python3.11/EXTERNALLY-MANAGED</pre></td></tr></table></figure><h2 id=\"修改用户名及用户目录\"><a class=\"anchor\" href=\"#修改用户名及用户目录\">#</a> 修改用户名及用户目录</h2>\n<ol>\n<li>切换终端,用 root 账户登录;</li>\n<li>编辑 /etc/passwd 文件,将旧用户名替换为新用户名;</li>\n<li>编辑 /etc/shadow 文件,将旧用户名替换为新用户名;</li>\n<li>编辑 /etc/group 文件,将旧用户名替换为新用户名;</li>\n<li>重命名 home 文件: mv /home/oldusername/home/newusername</li>\n</ol>\n<p>注:目录名的改变会导致一些固定路径的配置项发生错误,需要手动修改路径。</p>\n<h2 id=\"linux-修改u盘名称\"><a class=\"anchor\" href=\"#linux-修改u盘名称\">#</a> Linux 修改 U 盘名称</h2>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">sudo</span> pacman <span class=\"token parameter variable\">-S</span> <span class=\"token function\">mtools</span> <span class=\"token comment\"># 安装工具</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">sudo</span> <span class=\"token function\">vim</span> /etc/mtools.conf <span class=\"token comment\"># 然后修改配置文件</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\"># 在这个文件最后添加下面一行</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token assign-left variable\">mtools_skip_check</span><span class=\"token operator\">=</span><span class=\"token number\">1</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token function\">sudo</span> mlabel <span class=\"token parameter variable\">-i</span> /dev/sdb1 ::DISK2 <span class=\"token comment\"># sdb1 是 U 盘,SISK2 是修改后的名称(自动改大写)</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token function\">sudo</span> <span class=\"token function\">eject</span> /dev/sdb1 <span class=\"token comment\"># 修改完成</span></pre></td></tr></table></figure>",
"tags": [
"ArchLinux"
]
},
{
"id": "http://yuanmxc.site/C++/C++%20Primer%E7%AC%94%E8%AE%B0/",
"url": "http://yuanmxc.site/C++/C++%20Primer%E7%AC%94%E8%AE%B0/",
"title": "C++ Primer笔记",
"date_published": "2024-03-26T11:49:10.133Z",
"content_html": "<p>注意:本文并不是教你学 C++,这只是笔者学习 C<ins> 过程中记录的相关知识,适用于已经对 C</ins> 有所了解的读者进行复习和查询,读者至少对 C 和 C++ 有所了解。</p>\n<h2 id=\"小记\"><a class=\"anchor\" href=\"#小记\">#</a> 小记:</h2>\n<ol>\n<li>\n<p>有符号和无符号一起用,有符号转无符号。</p>\n</li>\n<li>\n<p>double(一般 16 有效位)一般和 float(一般 7 有效位)运算代价相同,用 double 即可。</p>\n</li>\n<li>\n<p>char16_t 和 char32_t 为 Unicode 字符,包含所有自然语言字符。</p>\n</li>\n<li>\n<p>泛化的转义序列: <code>\\x</code> 后跟 1 或多个十六进制数字或者 <code>\\</code> 后跟多个八进制数字: <code>\\12</code> (换行符) <code> \\x4d</code> (字符 M)</p>\n</li>\n<li>\n<p>初始化不是赋值,定义变量时若未指定初始值,变量被<strong>默认初始化</strong>,“默认值” 由变量类型和定义位置决定。定义在任何函数体之外的内置类型变量会被默认初始化为 0,定义在函数体内部的内置类型变量不被初始化,它的值是未定义的。每个类各自决定初始化对象的方式。</p>\n</li>\n<li>\n<p>声明使得名字为程序所知,定义负责创建于名字关联的实体。变量能且只能被定义一次,但是可以被多次声明。任何包含了显式初始化的声明即成为定义。多个文件使用同一变量,只能有一个定义,其他文件必须声明才能使用,决不能定义该变量。</p>\n<pre><code class=\"language-c++\">extern int i; // 声明i而非定义i\nint j; // 声明并定义j\nextern double pi = 3.1415926; // 定义,extern作用被抵消\n</code></pre>\n</li>\n<li>\n<p>引用只是一个已经存在的对象的另一个名字,它和它的初始值(一个对象)一直绑定在一起,必须被初始化。对引用的操作就是对于它绑定的对象的操作(可以视为替换)。引用本身不是对象,无法定义引用的引用和指针。</p>\n<pre><code class=\"language-c++\">int ival = 1024;\nint &refVal = ival;\nrefVal = 2;\n</code></pre>\n</li>\n<li>\n<p><code>::</code> 作用域运算符,使用 <code>::reuserd</code> 的方式可以访问被局部变量覆盖的全局变量,全局作用域本身没有名字,所以 <code>::</code> 左侧为空时会向全局作用域发起请求。</p>\n</li>\n<li>\n<p>把 int 变量直接赋给指针是错误的操作,即使他的值为 0。</p>\n</li>\n<li>\n<p>对指针的引用:</p>\n</li>\n</ol>\n<pre><code class=\"language-c++\">int i = 21;\nint *p;\nint *&r = p;\nr = &i; // 令p指向i\n*r = 0; // 将p指向的变量i的值改为0\n</code></pre>\n<ol start=\"11\">\n<li>\n<ul>\n<li>\n<p>当以编译时初始化的方式定义一个 const 对象时,例如: <code>const int bufSize = 512;</code> ,编译器会将在编译过程中用到该变量的地方都替换成对应的值。</p>\n</li>\n<li>\n<p>默认状态下,const 对象被设定为仅在文件内有效。当多个文件中出现同名 const 变量时,等同于在不同文件中分别定义了独立的变量</p>\n</li>\n<li>\n<p>当希望 const 变量初始值不是常量表达式,但需要在文件间共享,即和其他对象一样,只在一个地方定义 const 变量,而在其他多个文件中声明并使用它,则不管是声明还是定义都添加 extern 关键字,这样只需要定义一次就可以了。</p>\n<pre><code class=\"language-c++\">// file_1.cc 定义并初始化了一个常量,该常量能被其他文件访问\nextern const int bufSize = fcn();\n// file_1.h 头文件\nextern const int bufSize; // 与file_1.cc 中定义的bufSize是同一个\n</code></pre>\n</li>\n</ul>\n</li>\n<li>\n<p>对 const 对象的引用称之为对常量的引用(<strong>常量引用</strong>)。不能让一个非常量引用指向一个常量对象。</p>\n</li>\n<li>\n<p>一般来说引用的类型应该与其所引用的对象的类型一致,但有下面两个例外:</p>\n<ul>\n<li>\n<p>对 const 的引用可能引用一个并非 const 的对象。</p>\n<pre><code class=\"language-c++\">int i = 42;\nint &r1 = i;\nconst int &r2 = i; // r2绑定对象i但是不允许通过r2修改i的值。\n</code></pre>\n</li>\n<li>\n<p>初始化常量引用时允许使用任意表达式作为初始值,只要该表达式的结果能转换成引用的类型即可,尤其,允许为一个常量引用绑定非常量的对象、字面值,甚至是一个表达式:</p>\n<pre><code class=\"language-c++\">double i = 3.14;\nconst int &r1 = i; // 正确,double可以转换成int,常量引用可以绑定非常量对象\nconst int &r2 = 42; // 正确:r2是一个常量引用,可以绑定字面值\nconst int &r3 = r1 * 2; // 正确:r3是一个常量引用,可以绑定表达式\nint &r4 = r1 *2 // 错误:r4是一个普通的非常量引用\n</code></pre>\n<p>以上面第 1、2 行代码为例,当一个常量引用被绑定到另一种类型上时,编译器把 i 转化一个整形常量 3,这个 3 是一个临时量对象,是编译器需要的一个用来暂存表达式求值结果时临时创建的一个未命名的对象。</p>\n</li>\n</ul>\n</li>\n<li>\n<p>一般来说指针的类型应该与其所指对象的类型一致,但有下面两个例外:</p>\n<ul>\n<li>允许一个指向常量的指针指向另一个非常量的对象。</li>\n<li>常量指针可以指向非常量对象。</li>\n</ul>\n</li>\n<li>\n<p><strong>顶层 const</strong> 表示指针本身是一个常量,<strong>底层 const</strong> 表示指针所值的对象是一个常量。当执行对象的拷贝操作时,拷入和拷出的对象必须具有相同的底层 const 资格,或者两个对象的数据类型必须能够转换,一般来说,非常量可以转换成常量,反之则不行。</p>\n</li>\n<li>\n<p>将变量声明为 constexptr 类型,让编译器来验证变量的值是否是一个常量表达式(值不会改变且在编译过程就能得到计算结果的表达式)。</p>\n<pre><code class=\"language-c++\">constexpr =int mf = 20;\n</code></pre>\n</li>\n<li>\n<p>定义类型别名:</p>\n<pre><code class=\"language-c++\">typedef double wages; // wages是double的同义词\ntypedef wasges base, *p; // base是double的同义词,p是double*的同义词\nusing SI = Sales_item; // SI是Sales_item的同义词\n</code></pre>\n</li>\n<li>\n<p>简单的把类型别名替换成它原本样子可能是错误的,后两句如果进行简单的文本替换,基本数据类型变为 const char .</p>\n<pre><code class=\"language-c++\">const char *cstr = 0; // 声明的是一个指向 const char 的指针\ntypedef char *pstring; // pstring的类型是指向char的指针\nconst pstring cstr = 0; // cstr是指向char的常量指针\nconst pstring *ps; // ps是一个指针,他指向的对象是一个指向char的常量指针\n</code></pre>\n</li>\n<li>\n<p>auto 一般会忽略掉<strong>顶层 const</strong> ,同时<strong>底层 const</strong> 会被保留。想保留,需要用 const atuo 。设置一个类型为 auto 的引用时,初始值中的顶层常量属性仍然被保留。</p>\n</li>\n<li>\n<p>decltype ( ) 返回()中表达式的类型。如果 decltype 使用的表达式是一个变量,则 decltype 返回该变量的类型(包括顶层 const 和引用在内)。如果表达式的内容是解引用操作,则 decltype 将得到引用类型。decltype 使用的表达式是变量,该变量是否有括号会影响结果,如果无括号,得到的类型是该变量的类型,如果有括号,得到的是该变量对应的引用类型。</p>\n<pre><code class=\"language-c++\">decltype (f()) sum = x; // sum的类型就是函数f的返回类型,编译器并不实际调用f()\n// decltype的结果可以是引用类型\nint i = 42, *p = &i, &r = i;\ndecltype(r + 0) b; // 正确:加法的结果是int,因此b是一个(未初始化的)int\ndecltype(*p) c; // 错误:*p的类型是int,但他是解引用操作,所以c的类型是int&,必须初始化\ndecltype((i)) d; // 错误:使用(i)得到的是 int& 类型,必须初始化\n</code></pre>\n</li>\n<li>\n<p>头文件保护符 <code>#ifndef</code> 、 <code>#ifdef</code> 、 <code>#endif</code> 应该包含在头文件中,即使头文件(目前还)没有被包含在任何其他头文件中。头文件不应该使用 using 声明。</p>\n</li>\n<li>\n<p>string 字符串使用字符串字面值初始化时,不包含字符串字面值最后隐藏的空字符,字符串字面值实际上包含写出来的字符和隐藏的空字符。</p>\n</li>\n<li>\n<p>cin 在读取 string 时,string 对象会自动忽略开头的空白(空格符、换行符、制表符等),并从第一个真正的字符开始读起,直到遇见下一次处空白为止。</p>\n</li>\n<li>\n<p><code>getline(cin, line)</code> 读取一整行,参数是一个输入流和一个 string 对象,函数从输入流中读入内容,直到遇到换行符为止(换行符也被读进来了),然后把所读的对象存入到 string 对象中(但是不存读入的换行符)。如果一开始就输入换行符,那么得到空 string。触发 getline 函数返回的换行符实际上被丢掉了。</p>\n</li>\n<li>\n<p>sting 操作中的 size () 等函数,返回的数字类型配套的, <code>size()</code> 返回 <code>string:: size_type</code> 类型,一个无符号整型,使用 <code>auto</code> 或者 <code>decltype()</code> 推断变量类型来存比较好。注意无符号整型和有符号整型混用的问题。</p>\n</li>\n<li>\n<p>string 比较规则:返回两个 string 对象第一个不同字符的比较结果,若全相同,则长的大。</p>\n</li>\n<li>\n<p>当把 string 对象和字符字面值及字符串字面值混在一条语句中使用时,必须确保每个加法运算符的两侧的运算对象至少有一个是 string,字符串字面值不是 string 对象。</p>\n</li>\n<li>\n<p>string 的下标运算符接收的参数是 string::size_type 类型的值,返回值是该位置上字符的引用。在范围 for 语句中也需要使用引用来修改 string 中的字符,使用 char 的话没有改变原 string 对象。</p>\n</li>\n<li>\n<p><strong>string</strong>:</p>\n<pre><code class=\"language-c++\">// 初始化\nstring s1; // 默认初始化,空字符串\nstring s2 = ""; // 拷贝初始化,空字符串\nstring s3 = "hello"; // 拷贝初始化\nstring s4("world"); // 拷贝初始化,使用构造函数定义并初始化字符串\nstring s5(10,'c'); // 直接初始化,是十个c的字符串\nstring s6 = string(10,'c') // 拷贝初始化,创建了一个临时对象然后拷贝给s6\n// 成员函数\ns[n] // 返回n位置上的字符的引用\ns.empty() // s是否为空,空为真,不空为假\ns.length() // 或者 s.size(),返回s中字符个数\ns.at(n); // 返回下标为n的字符\ns.find("ld"); // 返回 "ld" 在字符串中的位置n\ns.replace(6, 5, "there"); // 把 "world" 替换成 "there"\ns.substr(0, 5); // 返回i字符串的前5个字符组成的字符串\ns.substr(6); // 返回从字符串的第7个字符到末尾的字符组成的字符串\ns.insert(6, "there"); // 在下标为6的位置插入there“,后面字符顺延\ns.insert(6, 1, '-'); // 在第6个位置插入 '-',后面字符顺延\n</code></pre>\n</li>\n<li>\n<p>使用花括号初始化 vector 对象时,会优先使用列表初始化,提供的值必须与元素类型相同,如果不同,无法执行列表初始化,编译器会尝试使用默认初始化 vector 对象。</p>\n</li>\n<li>\n<p>一般创建一个空的 vector ,再向里面添加元素更好,直接初始化可能性能更差,同时,如果改变了 vector 容量,不应使用范围 for 循环,范围 for 语句内不应该改变其所遍历序列的大小。不能使用下标形式为 vector 添加元素,只能对已存在的元素执行下标操作。</p>\n</li>\n<li>\n<p>** 类模板 vector **:</p>\n<p>vector 定义在头文件中,需要包含,并位于 std 命名空间中。</p>\n<pre><code class=\"language-c++\">vector<double> v; // 创建空容器\nvector<string> v1{10}; // 10不是string,使用默认初始化,初始化有10个string的vectoer\nvector<double> v(20, 1.0); // 直接初始化有20个double的vectoe,初始值均为1.0,没有第二个参数初始值默认均为0,使用花括号也可\nvector<int> values2{1,2,3,4,2,1}; // 指定元素个数和初始值\nvector<int> values3(values2); // 创建和alces相同的容器\nvector<int> values4(begin(value2,begin(v。alue2)+3)) // 使用指针或者迭代器来指定初始值范\n</code></pre>\n<p>vector 容器包含的成员函数:</p>\n<pre><code class=\"language-c++\">begin()\t // 返回指向容器中第一个元素的迭代器。\nend()\t // 返回指向容器最后一个元素所在位置后一个位置的迭代器。\nfront()\t // 返回第一个元素的引用。\nback()\t // 返回最后一个元素的引用。\ndata()\t // 返回指向容器中第一个元素的指针。\nassign() // 用新元素替换原有内容。\npush_back()\t// 在序列的尾部添加一个元素。\npop_back()\t// 移出序列尾部的元素。\ninsert()\t// 在指定的位置插入一个或多个元素。\nerase()\t // 移出一个元素或一段元素。\nclear()\t // 移出所有的元素,容器大小变为 0。\nrbegin() // 返回指向最后一个元素的迭代器。\nrend()\t // 返回指向第一个元素所在位置前一个位置的迭代器。\ncbegin() // 和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。\ncend()\t // 和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。\ncrbegin() // 和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。\ncrend()\t // 和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。\nsize()\t // 返回实际元素个数 类型是vector<T>::size_type,T为vector存储的元素类型。\nmax_size()// 返回元素个数的最大值。这通常是一个很大的值,一般是 2^32-1,所以我们很少会用到这个函数。\nresize() // 改变实际元素的个数。\ncapacity()// 返回当前容量。\nempty()\t // 判断容器中是否有元素,若无元素,则返回 true;反之,返回 false。\nreserve() // 增加容器的容量。\nshrink _to_fit() // 将内存减少到等于当前元素实际所使用的大小。\noperator[ ]\t // 重载了 [ ] 运算符,可以向访问数组中元素那样,通过下标即可访问甚至修改 vector 容器中的元素。\nat()\t // 使用经过边界检查的索引访问元素。\nswap()\t // 交换两个容器的所有元素。\nemplace()\t // 在指定的位置直接生成一个元素。\nemplace_back()\t// 在序列尾部生成一个元素。\n</code></pre>\n</li>\n<li>\n<p>如果容器为空,begin 和 end 都返回尾后迭代器。</p>\n</li>\n<li>\n<p>标准容器迭代器的部分运算符:</p>\n<pre><code class=\"language-c++\">*it // 返回迭代器it所指元素的引用\n(*it).empty() // it指示一个strng类型并判断string是否为空,必须加(),否则先进行点运算\nit->empty() // 解引用it并获取该元素的名为mem的成员,等价于(*it).empty()\n++it // 令it指示容器中的下一个元素\n--it // 令it指示容器中的上一个元素\nit1 == it2 // 判断两个选代器是否相等,如果两个选代器指示的是同一个元素或者它们是同一个容器的尾后选代器,则相等;反之,不相等\n+、-、+=、-=、<、>、<=、>=\n</code></pre>\n</li>\n<li>\n<p>某些对 vector 的操作(任何可能改变 vertor 对象容量的操作)会使迭代器失效,比如 push_back,不能在范围 for 循环中向 vector 对象添加元素。</p>\n</li>\n<li>\n<p>遍历一个 vector :</p>\n<pre><code class=\"language-c++\">vector<int> vec = {1,2,3,4};\n// 范围for循环\nfor(const auto& element : vec){\n cout << element << endl;\n}\n// 迭代器遍历\nfor(vector<int>::iterator it = vec.begin(); it != vec.end(); ++it){\n cout << *it << end;\n}\n// 索引遍历\nfor(size_t i = 0; i < vec.size(); ++i){\n cout << vec[i] << endl;\n}\n</code></pre>\n</li>\n<li>\n<p>使用迭代器的二分搜索:</p>\n<pre><code class=\"language-c++\">// text必须是有序的\n// beg和end表示我们搜索的范围\nauto beg = text.begin(), end=text.end();\nauto mid = text.begin() + (end-beg)/2; // 初始状态下的中间点\n// 当还有元素尚未检查并且我们还没有找到sought时执行循环\nwhile(mid != end && *mid != sought)\n if (sought < *mid) // 如果要找的元素在前半部分\n end = mid; // 新end为旧mid,beg不变\n else // 否则,我们要找的元素在后半部分\n beg = mid + 1 // 新beg为旧mid+1,end不变\n mid = beg + (end-beg)/2; // 同样方法计算新的中间点\n</code></pre>\n</li>\n<li>\n<p>数组的维度(元素个数)必须是常量表达式。默认情况下数据元素北默认初始化。字符数组使用字符串字面值初始化时,后面隐藏的 '\\0' 会被包含进去,空间不够时报错。数组不允许拷贝和赋值。</p>\n</li>\n<li>\n<p>数组本身是对象,存放对象,不存在引用的数组,但存在数组的引用。</p>\n<pre><code class=\"language-c++\">unsigned cnt = 42; //不是常量表达式\nconstexpr unsigned sz = 42;//常量表达式\nint *parr[sz]; //含有42个整型指针的数组\nstring bad[cnt];; //错误:cnt不是常量表达式\nstring strs[get_size()]; //当get_size是constexpr时正确;否则错误\n</code></pre>\n</li>\n<li>\n<p>当数组作为一个 auto 变量的初始值时,推断得到的类型是指针而非数组;使用 decltype 关键字时返回的类型是数组。</p>\n</li>\n<li>\n<p>标准库函数 begin () 和 end () 获取数组的首元素指针和尾元素下一指针。两个指针相减的结果类型是 ptrdiff_t 的标准库类型,是带符号类型。如果两个指针分别指向不相关的对象,不能比较他们,未定义行为。</p>\n</li>\n<li>\n<p>使用数组下标等同于使用指针,同时内置的下标运算(数组下标)可以处理负值,但标准库类型 string 和 vector 的下标运算必须是无符号类型。</p>\n</li>\n<li>\n<p>尽量少使用 C 风格字符串,内存管理麻烦,多用 string,string 的成员函数 c_str () 可以把 string 转化成 char*。</p>\n</li>\n<li>\n<p>数组无法拷贝和赋值,不能用 vector 初始化数组,但可以用数组初始化 vector ,只需之名拷贝区域的首元素地址和尾后地址:</p>\n<pre><code class=\"language-c++\">int int_arr[] = {0, 1, 2, 3, 4, 5};\n// ivec有6个元素,分别是intarr中对应元素的副本\nvector<int> ivec(begin(int_arr),end(int_arr));\n</code></pre>\n</li>\n<li>\n<p>当一个对象被用作右值的时候,用的是对象的值(内容);当对象被用作左值的时候,用的是对象的身份(在内存中的位置)。</p>\n</li>\n</ol>\n<h3 id=\"运算符\"><a class=\"anchor\" href=\"#运算符\">#</a> 运算符</h3>\n<ol start=\"45\">\n<li>\n<p>有 4 种运算符明确规定了运算对象的求值顺序。逻辑与(&&)运算符和逻辑或(||)运算符规定先求左侧运算对象的值,只有当左侧运算对象的值为真 / 假时才继续求右侧运算对象的值。条件( ?: )运算符和逗号( , )运算符。其他运算符,如 + 、>> 等未规定左右运算对象的求值顺序,先求左右表达式中的哪一个都有可能。如果表达式影响同一对象,求值先后顺序对结果有影响,那么它是一个错误的表达式,将产生未定义行为。</p>\n</li>\n<li>\n<p>布尔值不应该参与运算,大多数运算符会把布尔值提升为 int 类型,true 为 1,求负后为 -1 ,再转回布尔值时仍为 1 ,还是 true。</p>\n</li>\n<li>\n<p>求商向 0 取整(直接切除小数部分)。取余时,除了 -m 导致溢出的情况,m % (-n) 等于 m % n,( -m ) % n 等于 -( m % n ),即左右都为负,结果是两个正数取余后结果取反,一正一负,结果等于两个正数取余。</p>\n</li>\n<li>\n<p>位运算符的运算对象是 “小整数”,它的值会被自动提升成较大的整数类型”,如何处理负数对象的 “符号位” 依赖于机器,而且此时的左移操作可能会改变符号位的值,因此是一种未定义的行为。左移在右侧插入 0。右移时,无符号类型左侧插入 0,带符号类型插入符号位的副本或者值为 0 的二进制位,如何选择视具体情况而定。</p>\n</li>\n<li>\n<p>sizeof 运算符对解引用指针进行运算不会验证指针是否有效,对指针进行运算返回指针本身所占空间大小,对数组返回整个数组所占空间大小。对 sring 或者 vector 运算返回该类型固定部分的大小。sizeof 返回值是一个常量表达式。</p>\n</li>\n<li>\n<p>逗号( , )运算符按照从左向右的顺序求值,运算结果是右侧表达式的值。</p>\n</li>\n<li>\n<p>无符号和有符号数一起运算时,无符号类型所占位数大于等于有符号类型,则有符号类型转为无符号类型;如果无符号类型所占位数小于有符号类型,比如 long 和 unsigned int ( long 大于 int 时),则 unsigned int 转为 long</p>\n</li>\n<li>\n<p>命名的强制类型转换具有如下形式: <code>cast-name(expression)</code> ,static_cast 是一种只要类型不包含底层 const 都可用。const_cast 只能改变运算对象的底层 const, 不能进行类型转换。</p>\n</li>\n<li>\n<p>switch case 语句中,后面的 case 标签可以使用前面的 case 标签定义过的变量,但是该变量的初始化无效(如果前 case 标签被跳过的话),包括类似 string 的默认初始化。即:不允许跨过变量的初始化语句直接跳转到该变量作用域内的另一个位置。</p>\n</li>\n<li></li>\n</ol>\n<h3 id=\"常用函数\"><a class=\"anchor\" href=\"#常用函数\">#</a> 常用函数</h3>\n<pre><code class=\"language-c++\">// cctype 头文件中的函数\nisalnur(c) // 当c是字母或数字时为真\nisalpha(c) // 当c是字母时为真\niscntrl(n) // 当c是控制字符时为真\nisdigit(c) // 当c是数字时为真\nisgraph(c) // 当c不是空格但可打印时为真\nislower(c) // 当c是小写字母时为真\nisprint(c) // 当c是可打印字符时为真(即c是空格或c具有可视形式)\nispunct(c) // 当c是标点符号时为真(即c不是控制字符、数字、字母、可打印空白中的一种)\nisspace(c) // 当c是空白时为真(即c是空格、横向制表符、纵向制表符、回车符、换行符、进纸符中的一种)\nisupper(c) // 当c是大写字母时为真\nisxdigit(c) // 当c是十六进制数字时为其\ntolower(c) // 如果c是大写字母,输出对应的小写字母:否则原样输出c\ntoupper(c) // 如果c是小写字母,输出对应的大写字母:否则原样输出c\n</code></pre>\n<h3 id=\"头文件\"><a class=\"anchor\" href=\"#头文件\">#</a> 头文件:</h3>\n<pre><code class=\"language-C++\">#include <initializer_list>\n#include <iostream>\n#include <istream>\n#include <ostream>\n#include <stdexcept>\n#include <string>\n#include <cstdarg> // 使用va_list可变参数列表\n#include <system_error>\n#include <vector> // 使用vector容器\n#include <string>\n#include <cstdlib> // 预处理变量NULL\n#include <cctype> // 使用nullptr,isalnum(),isalpha()等\n#include <cstddef> // 使用size_t,ptrdiff_t\n#include <iterator> // 使用begin(),end()\n#include <stdexcept> // 异常类,如runtime_error,p176\n</code></pre>\n<h3 id=\"全局区\"><a class=\"anchor\" href=\"#全局区\">#</a> 全局区</h3>\n<pre><code class=\"language-c++\">#include <cassert> // assert,预处理宏\nusing std::cin; // using声明,当我们使用cin时,意味着使用的std::cin\nusing namespace std;// 头文件内容会拷贝到所有引用他的文件里,一般不应包含using声明(易造成名字冲突)\n\n// 如果定义了预处理变量MIN,就继续到#endif,#indef和#indef叫预处理百年\n#ifdef MIN\n#define MKSTR(x) #x // "x"\n#endif\n\n// 如果没有定义预处理变量MIN,就继续到#endif,一般头文件的预处理变量定义都需要这样写\n#ifndef MIN \n#define MIN(a, b) (a < b ? a : b)\n#define concat(a, B) a##b // xy\n#define NDEBUG // 定了他 assert什么都不做,没定义则指执行运行时检查\n#endif\n\nextern const int i = 123; // a文件里定义并初始化i,加extern使其能被其他文件使用\n</code></pre>\n<h3 id=\"数据结构\"><a class=\"anchor\" href=\"#数据结构\">#</a> 数据结构</h3>\n<ol>\n<li>\n<p>stack 容器</p>\n<p>头文件,c 在 std 命名空间。stack 容器适配器的模板有两个参数。第一个参数是存储对象的类型,第二个参数是底层容器的类型。stack 的底层容器默认是 deque 容器,因此模板类型其实是 stack。通过指定第二个模板类型参数,可以使用任意类型的底层容器,只要它们支持 back ()、push_back ()、pop_back ()、empty ()、size () 这些操作。下面展示了如何定义一个使用 list 的堆栈:</p>\n<pre><code class=\"language-c++\">stack<string> words1; // 省略第一个参数,用默认的底层容器deque<T>实现\nstack<string, list<string>> words2 // 底层容器使用list<T>\n</code></pre>\n<p>创建堆栈时,不能用对象来初始化,但是可以用另一个容器来初始化,只要堆栈的底层容器类型和这个容器的类型相同,且必须使用圆括号。例如:</p>\n<pre><code class=\"language-c++\">list<double> values {1.414, 3.14159265, 2.71828};\nstack<double, list<double>> my_stack (values);\n</code></pre>\n<p>第二条语句生成了一个包含 value 元素副本的 my_stack。这里不能在 stack 构造函数中使用初始化列表,必须使用圆括号。如果没有在第二个 stack 模板类型参数中将底层容器指定为 list,那么底层容器可能是 deque,这样就不能用 list 的内容来初始化 stack;只能接受 deque。</p>\n<p>stack 模板定义了拷贝构造函数,因而可以复制现有的 stack 容器:</p>\n</li>\n</ol>\n<pre><code class=\"language-c++\">stack copy_stack {my_stack}\n</code></pre>\n<p>堆栈操作:(T 为栈中元素类型)</p>\n<ul>\n<li>\n<p>push (const T& obj) 可以将对象副本压入栈顶。这是通过调用底层容器的 push_back () 函数完成的。</p>\n<ul>\n<li>pop () 弹出栈顶元素但没有返回它。</li>\n</ul>\n</li>\n<li>\n<p>top () 返回一个栈顶元素的引用但没有弹出,类型为 T&。如果栈为空,返回值未定义。</p>\n<ul>\n<li>\n<p>size () 返回栈中元素的个数。</p>\n</li>\n<li>\n<p>empty () 在栈中没有元素的情况下返回 true。</p>\n</li>\n<li>\n<p>emplace () 用传入的参数调用构造函数,在栈顶生成对象。</p>\n</li>\n<li>\n<p>swap (stack & other_stack) 将当前栈中的元素和参数中的元素交换。参数所包含元素的类型必须和当前栈的相同。对于 stack 对象有一个特例化的全局函数 swap () 可以使用。</p>\n</li>\n</ul>\n</li>\n</ul>\n<ol start=\"2\">\n<li>\n<p>类模板</p>\n<p>vector 定义在头文件中,需要包含,并位于 std 命名空间中。</p>\n<pre><code class=\"language-c++\">vector<double> values; // 创建空容器\nvector<double> values1(20, 1.0); // 开始就有20个int,初始值均为1.0,没有第二个参数初始值默认均为0\nvector<int> values2{1,2,3,4,2,1}; // 指定元素个数和初始值\nvector<int> values3(values2); // 创建和alces相同的容器\nvector<int> values4(begin(value2,begin(v。alue2)+3)) // 使用指针或者迭代器来指定初始值范围\n</code></pre>\n<p>vector 容器包含的成员函数:</p>\n<pre><code class=\"language-c++\">begin()\t // 返回指向容器中第一个元素的迭代器。\nend()\t // 返回指向容器最后一个元素所在位置后一个位置的迭代器。\nfront()\t // 返回第一个元素的引用。\nback()\t // 返回最后一个元素的引用。\ndata()\t // 返回指向容器中第一个元素的指针。\nassign() // 用新元素替换原有内容。\npush_back()\t// 在序列的尾部添加一个元素。\npop_back()\t// 移出序列尾部的元素。\ninsert()\t// 在指定的位置插入一个或多个元素。\nerase()\t // 移出一个元素或一段元素。\nclear()\t // 移出所有的元素,容器大小变为 0。\nrbegin() // 返回指向最后一个元素的迭代器。\nrend()\t // 返回指向第一个元素所在位置前一个位置的迭代器。\ncbegin() // 和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。\ncend()\t // 和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。\ncrbegin() // 和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。\ncrend()\t // 和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。\nsize()\t // 返回实际元素个数。\nmax_size()// 返回元素个数的最大值。这通常是一个很大的值,一般是 2^32-1,所以我们很少会用到这个函数。\nresize() // 改变实际元素的个数。\ncapacity()// 返回当前容量。\nempty()\t // 判断容器中是否有元素,若无元素,则返回 true;反之,返回 false。\nreserve() // 增加容器的容量。\nshrink _to_fit() // 将内存减少到等于当前元素实际所使用的大小。\noperator[ ]\t // 重载了 [ ] 运算符,可以向访问数组中元素那样,通过下标即可访问甚至修改 vector 容器中的元素。\nat()\t // 使用经过边界检查的索引访问元素。\nswap()\t // 交换两个容器的所有元素。\nemplace()\t // 在指定的位置直接生成一个元素。\nemplace_back()\t// 在序列尾部生成一个元素。\n</code></pre>\n</li>\n<li>\n<p>哈希表</p>\n<p>头文件 <code><unordered_map></code> ,在 std 名命名空间中。它将数据存储为键值对,其中键是唯一的。 声明和初始化:</p>\n<pre><code class=\"language-c++\">unordered_map<string, int> map1\n</code></pre>\n</li>\n</ol>\n",
"tags": [
"C++"
]
},
{
"id": "http://yuanmxc.site/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E5%92%8C%E7%AE%97%E6%B3%95/%E7%AE%97%E6%B3%95%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/",
"url": "http://yuanmxc.site/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E5%92%8C%E7%AE%97%E6%B3%95/%E7%AE%97%E6%B3%95%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/",
"title": "算法学习笔记",
"date_published": "2024-03-26T11:49:10.133Z",
"content_html": "<h2 id=\"总览\"><a class=\"anchor\" href=\"#总览\">#</a> 总览</h2>\n<p><strong>7 个数据结构</strong>:</p>\n<ul>\n<li>数组</li>\n<li>链表</li>\n<li>栈</li>\n<li>队列</li>\n<li>哈希表</li>\n<li>二叉树</li>\n<li>堆</li>\n</ul>\n<p><strong>10 个算法</strong>:</p>\n<ul>\n<li>递归</li>\n<li>排序</li>\n<li>二分查找</li>\n<li>搜索</li>\n<li>哈希算法</li>\n<li>贪心算法</li>\n<li>分治算法</li>\n<li>回溯算法</li>\n<li>动态规划</li>\n<li>字符串匹配算法</li>\n</ul>\n<h2 id=\"数据结构的基本操作\"><a class=\"anchor\" href=\"#数据结构的基本操作\">#</a> 数据结构的基本操作</h2>\n<p>数据结构的基本操作包括:增删查改,即遍历和访问。</p>\n<p>数据结构的遍历和访问的两种形式:线性、非线性,线性以 for/while 迭代为代表,非线性以递归为代表。</p>\n<ol>\n<li>\n<p>数组遍历框架(线性迭代):</p>\n<pre><code class=\"language-c++\">void traverse(vector<int> arr){\n for(int i = 0; i < arr.size(); i++){\n // 迭代访问每个元素arr[i]\n }\n}\n\nvoid traverse(vector<int> arr){ \n for(auto &i : arr){\n // 迭代访问每个元素i\n }\n}\n</code></pre>\n</li>\n<li>\n<p>链表遍历框架(迭代或者递归):</p>\n<pre><code class=\"language-c++\">// 基本的单链表节点\nclass ListNode {\n public:\n int val;\n ListNode *next;\n};\n\nvoid traverse(ListNode head){\n for(ListNode *p = heda; p != nullptr; p = p->next){\n // 迭代访问 p->val\n }\n}\n\nvoid traverse(ListNode head){\n traverse(head->next);\n}\n</code></pre>\n</li>\n<li>\n<p>二叉树遍历框架,典型的非线性递归遍历结构:</p>\n<pre><code class=\"language-c++\">// 基本的二叉树节点\nstruct TreeNode {\n int val;\n TreeNode* left;\n TreeNode* righe;\n};\n\nvoid traverse(TreeNode* root) {\n // 递归访问二叉树每个节点root\n traverse(root->left):\n traverse(root->right);\n}\n</code></pre>\n</li>\n<li>\n<p>二叉树扩展为 N 叉树遍历结构:</p>\n<pre><code class=\"language-c++\">// 基本的 N 叉树节点\nclass TreeNode {\n int val;\n vector<TreeNode*> children;\n};\n\nvoid traverse(TreeNode *root) {\n // 递归访问 N 叉树每个节点\n for (TreeNode *child : root->children)\n traverse(child);\n}\n</code></pre>\n</li>\n</ol>\n<h3 id=\"刷题顺序\"><a class=\"anchor\" href=\"#刷题顺序\">#</a> 刷题顺序:</h3>\n<ol>\n<li>\n<p>数组、链表相关:单链表翻转、前缀和数组、二分搜索等基础算法。</p>\n</li>\n<li>\n<p>二叉树。</p>\n</li>\n<li>\n<p>回溯,动态规划、回溯算法等面试常考。</p>\n</li>\n</ol>\n<h3 id=\"二叉树框架\"><a class=\"anchor\" href=\"#二叉树框架\">#</a> 二叉树框架</h3>\n<pre><code class=\"language-c++5\">void traverse(TreeNode *root) {\n // 前序位置\n traverse(root->left);\n // 中序位置\n traverse(root->right);\n // 后序位置\n}\n</code></pre>\n",
"tags": [
"数据结构和算法"
]
},
{
"id": "http://yuanmxc.site/%E7%AC%94%E8%AE%B0/6.s081%E7%AC%94%E8%AE%B0/",
"url": "http://yuanmxc.site/%E7%AC%94%E8%AE%B0/6.s081%E7%AC%94%E8%AE%B0/",
"title": "6.s081笔记",
"date_published": "2024-03-26T11:49:10.133Z",
"content_html": "<h2 id=\"课程第一节-指导书第一-二章\"><a class=\"anchor\" href=\"#课程第一节-指导书第一-二章\">#</a> 课程第一节 && 指导书第一、二章</h2>\n<ol>\n<li>操作系统一般需要做到:\n<ul>\n<li>抽象硬件,实现了高层级的接口和抽象,例如进程,文件系统。</li>\n<li>在多个应用程序之间共用硬件资源,多个程序能够互不干扰地运行,multiplex(多路复用)。</li>\n<li>多个程序之间互不干扰。隔离性(Isolation),不同的活动之间不能相互干扰。</li>\n<li>能在需要的时候实现共享(Sharing)。</li>\n<li>Security 或者 Permission System 或者是 Access Control System(权限系统或者门禁系统)。</li>\n<li>不阻止应用程序获得高性能,甚至需要帮助应用程序获得高性能(Performance)。</li>\n<li>同一个操作系统需要能够支持大量不同的用户场景。</li>\n</ul>\n</li>\n<li>Kernel 中的服务:文件系统,进程管理系统。</li>\n<li>系统调用与程序中的函数调用的区别是系统调用会实际运行到系统内核中,并执行内核中对于系统调用的实现。Kernel 会有特殊的权限能直接访问各种各样的硬件,例如磁盘。而普通的用户程序是没有办法直接访问这些硬件的。</li>\n<li>构建操作系统时,在操作系统下面就是硬件,编程环境比较恶劣。1. 高效易用 — 接近硬件底层,为应用程序提供抽象的高层的可移植接口。2. 要提供一个简单的接口,同时又包含了强大的功能。3. 需要内核具备灵活的接口,又需要在某种程度上限制应用程序,因为你会想要安全性。我们希望给程序员完全的自由,但是实际上又不能是真正的完全自由。</li>\n<li>fork 还会拷贝文件描述符表单。两个进程的指令是一样的,数据是一样的,栈是一样的,同时,两个进程又有各自独立的地址空间,它们都认为自己的内存从 0 开始增长,但这里是不同的内存。有一些细节偶尔会导致父子进程不一致。子进程 fork () 返回 0, 父进程返回子进程进程号。子进程不会从 main () 函数开始执行,而是直接从 fork () 系统调用返回,就好像是他自己调用了 fork。</li>\n<li><code>exec("filename",argv)</code> 从指定的文件中读取并加载指令,并替代当前调用进程的指令。会保留当前的文件描述符表单,通常来说 exec 系统调用不会返回,除非调用出错返回 - 1。</li>\n<li>Shell 会执行 fork,之后 fork 出的子进程再调用 exec5 系统调用。</li>\n<li><code>fork()</code> 的子进程用 <code>exit(num)</code> 退出后,在父进程中可以用 <code>wait(&status)</code> 来获取子进程的退出状态。wait () 的返回值是子进程号, <code>status</code> 的值即是子进程 <code>exit()</code> 的参数的值。</li>\n<li>如果没有子进程的进程调用了 wait,wait 会立即返回 - 1,表明出现错误了。没有直接的方法让子进程等待父进程退出。</li>\n<li>如果一个进程调用 fork 两次,如果它想要等两个子进程都退出,它需要调用 wait 两次。每个 wait 会在一个子进程退出时立即返回。当 wait 返回时,你实际上没有必要知道哪个子进程退出了,但是 wait 返回了子进程的进程号,所以在 wait 返回之后,你就可以知道是哪个子进程退出了。</li>\n<li><code>int fd[2]; pipe(fd)</code> 创建管道, <code>fd[0]</code> 用来从管道读数据, <code>fd[1]</code> 用来向管道写数据。返回 0 代表成功,返回 - 1 失败。管道是不是文件取决于操作系统创建管道的方式,一般来说用 pipe () 创建的管道都不是文件。而创建基于文件的管道,通常叫做有名管道或 FIFO 文件(先进先出文件)。两个进程只要知道管道的名字也能用它来通信,即使它们是非父子进程关系。如果试图读取一个空的管道,也不会发生错误,因为程序会等待管道中出现东西。当子进程结束时,管道会关闭。f <code>gets()</code> 将会收到 <code>EOF</code> (End Of File, 文件结束符) ,于是 <code>fgets()</code> 函数返回 0,循环就结束了。管道只能单向通信。但是可以通过创建两个管道,一个从父进程连接到子进程,另一个从子进程连接到父进程来实现双向通信 。</li>\n</ol>\n<h2 id=\"课程第三节-指导书第三章\"><a class=\"anchor\" href=\"#课程第三节-指导书第三章\">#</a> 课程第三节 && 指导书第三章</h2>\n<ol>\n<li>\n<p>需要操作系统的隔离性,保证应用程序间不会相互影响。需要操作系统抽象硬件资源,不让应用程序看到硬件资源。一个应用程序不能长时间占用 CPU, 需要协同调度,如果没有操作系统,这很难。从内存的角度来说,如果应用程序直接运行在硬件资源之上,那么每个应用程序的文本,代码和数据都直接保存在物理内存中。这可能会导致一个程序越界操作另一个程序的内存。</p>\n</li>\n<li>\n<p>fork 创建了进程。进程本身不是 CPU,但是它们对应了 CPU,它们使得你可以在 CPU 上运行计算任务。应用程序不能直接与 CPU 交互,只能与进程交互。操作系统内核会完成不同进程在 CPU 上的切换。所以,<strong>操作系统不是直接将 CPU 提供给应用程序,而是向应用程序提供 “进程”,进程抽象了 CPU,这样操作系统才能在多个应用程序之间复用一个或者多个 CPU。</strong></p>\n</li>\n<li>\n<p>处理器有几个核,就可以同时运行几个进程,但可以分时复用 CPU,比如一个进程用 100ms , 之后,另一个进程用 100ms。</p>\n</li>\n<li>\n<p>我们可以认为 exec 抽象了内存。当我们在执行 exec 系统调用的时候,我们会传入一个文件名,而这个文件名对应了一个应用程序的内存镜像。内存镜像里面包括了程序对应的指令,全局的数据。应用程序可以逐渐扩展自己的内存,但是<strong>应用程序并没有直接访问物理内存的权限</strong>,例如<strong>应用程序不能直接访问物理内存</strong>的 1000-2000 这段地址。不能直接访问的原因是,操作系统会提供内存隔离并控制内存,操作系统会在应用程序和硬件资源之间提供一个中间层。exec 是这样一种系统调用,它表明了应用程序不能直接访问物理内存。</p>\n</li>\n<li>\n<p>files 基本上来说抽象了磁盘。<strong>应用程序不会直接读写挂在计算机上的磁盘本身</strong>,并且在 Unix 中这也是不被允许的。在 Unix 中,与存储系统交互的唯一方式就是通过 files。Files 提供了非常方便的磁盘抽象,你可以对文件命名,读写文件等等。之后,<strong>操作系统会决定如何将文件与磁盘中的块对应,确保一个磁盘块只出现在一个文件中,并且确保用户 A 不能操作用户 B 的文件</strong>。通过 files 的抽象,可以<strong>实现不同用户之间和同一个用户的不同进程之间的文件强隔离。</strong></p>\n</li>\n<li>\n<p>操作系统应该具有防御性(Defensive),能够应对恶意的应用程序,阻止其控制内核。</p>\n</li>\n<li>\n<p>硬件对于强隔离的支持包括:user/kernle mode 和虚拟内存。</p>\n</li>\n<li>\n<p><code>user/kertnle mode</code> (用户态和内核态)是处理器的两种操作模式(还有第三种机器模式,主要用于配置计算机),运行在 <code>kernel mode</code> 时,CPU 可以运行特定权限的指令(privileged instructions);当运行在 <code>user mode</code> 时,CPU 只能运行普通权限的指令(unprivileged instructions)普通程序运行在 user mode,内核空间的程序运行在 kernel mode , 操作系统位于内核空间。</p>\n</li>\n<li>\n<p>普通指令如寄存器相加减的 ADD , SUB , 跳转 JRC、BRANCH 等,所有程序都允许执行。特殊权限指令是一些直接操纵硬件的指令和设置保护的指令,只能被内核执行,列如:page table 寄存器,关闭时钟中断等。用户代码都会通过内核访问硬件。</p>\n</li>\n<li>\n<p>在处理器里面有一个 flag , 为 1 是 user mode,为 0 是 kernel mode。用户程序通过系统调用来切换到 kernel mode, 执行系统调用时会通过<strong> ECALL(处理器的一个指令)触发一个软中断</strong>(software interrupt),软中断会查询操作系统预先设定的中断向量表,并执行<strong>中断处理程序</strong>。中断处理程序在内核中,这样就完成了 user mode 到 kernel mode 的切换,并执行用户程序想要执行的特殊权限指令,内核会检查并判断是否允许应用执行系统调用。</p>\n</li>\n<li>\n<p>BIOS 是一段计算机自带的代码,它会先启动,之后它会启动操作系统。</p>\n</li>\n<li>\n<p>操作系统会给每个进程设置一个他自己独有的 <code> page table</code> 页表(首先是指令,然后是全局变量,然后是栈区,每个进程有两个栈区:一个用户栈区和一个内核栈区,最后是一个堆区域)来映射一块和其他进程不重合的物理内存。两个正在运行的进程都有内存地址 0 , 但并不是同一个物理内存地址,而是映射到不同的物理内存地址。这样就给了我们内存的强隔离性。C 让你得到更多对于硬件资源的底层控制能力。</p>\n</li>\n<li>\n<p>内中的操作系统代码越多,Bug 越多。让整个操作系统代码都运行在 kernel mode 中称为<strong> Monolithic Kernel Design(宏内核)</strong>,缺点是容易出 Bug,优点是每个模块都在一个程序中,紧密集成,可以提供良好的性能。</p>\n</li>\n<li>\n<p>尽量减少内核中的代码,被称为<strong> Micro Kernel Design(微内核)</strong>,将操作系统的大部分代码运行在内核之外,作为普通的用户程序来运行(比如文件系统),这意味着更少的 Bug , 问题是,这会出现<strong>两次用户空间 <-> 内核空间的切换</strong>,比如:shell 通过内核中的<strong> IPC 系统</strong>(进程间通信系统:管道,FIFO , 消息队列,信号量,共享内存。这里是消息队列)发送一条消息,内核查看后把消息发给文件系统,文件系统完成工作后发回给 IPC 系统结果,IPC 系统再将消息发给 shell。性能更差,而且 page cache 被隔开了,不好共享。</p>\n</li>\n<li>\n<p>内核编译过程:Makefile 会读取一个<strong> C 文件</strong>(pro.c);之后调用 gcc 编译器,生成一个<strong>汇编语言文件</strong>(proc.s);之后走到汇编解释器,生成<strong>汇编语言的二进制格式</strong>(proc.c)。对所有内核文件都做相同的操作。之后系统加载器(Loadee)会将所有的.o 文件<strong>链接</strong>在一起,并生成<strong>内核文件</strong>,就是在 QUME 中运行的文件。</p>\n</li>\n<li>\n<p>QEMU 相当于模拟了一个计算机系统或者计算机主板,它仿真了 RISC-V 处理器,来运行 XV6 。QEMU 主循环中每个 CPU 核做一件事情:读取 4 或 8 字节的 RISC-V 指令;解释 RISC-V 指令,并止找出对应的操作码(op code)(ADD,SUB 之类);在软件中执行相应的指令。它要维护寄存器状态。仿真普通权限指令和特殊权限指令。跑在 QEMU 上的代码和跑在真正的 RISC-V 处理器上是一样的。</p>\n</li>\n<li>\n<p>操作系统必须满足三个要求:<strong>多路复用、隔离和交互</strong>。多路复用要求可以运行比处理器数量更多的进程;隔离要求进程间互不影响,交互又要求进程间可以交互。</p>\n</li>\n<li>\n<p>RISC-V 指令(用户和内核指令)使用的是虚拟地址,而机器的 RAM 或物理内存是由物理地址索引的,RISC-V 页表硬件通过将每个虚拟地址映射的物理地址来为这两种地址建立联系。RISC-V 页表在逻辑上是一个页表( Page Table Entries/PTE)条目组成的数组(数组中含有 PPN 和一些标识位 Flags),如下图,通过虚拟地址寻找页表数组中的 PPN,再加上原虚拟地址中的后十二位组成一个物理虚拟地址。</p>\n<p><img src="/home/origin/Code/repository/Note/All_picture/6.s081_note/p1-1669426857667-10.png" alt="img" style="zoom: 67%;" /></p>\n<p>实际的转换分为三个步骤,页表以三级树形结构存储在物理内存中。页硬件使用 27 位中的前 9 位在根页表页面中选择 PTE,中间 9 位在树的下一级页表页面中选择 PTE,最后 9 位选择最终的 PTE。</p>\n<p><img src="/home/origin/Code/repository/Note/All_picture/6.s081_note/p2.png" alt="img" style="zoom:67%;" /></p>\n<p>如果转换地址所需的三个 PTE 中的任何一个不存在,页式硬件就会引发页面故障异常(page-fault exception),并让内核来处理该异常。</p>\n</li>\n<li>\n<p>Xv6 为每个进程维护一个页表来描述每个进程的用户地址空间,外加一个单独描述内核地址空间的页表。Xv6 物理起始地址是 0X80000000 , 内核通过读写这个地址以下的物理地址与设备交互。</p>\n</li>\n</ol>\n",
"tags": [
"笔记"
]
},
{
"id": "http://yuanmxc.site/%E7%AC%94%E8%AE%B0/CMake%E5%AD%A6%E4%B9%A0/",
"url": "http://yuanmxc.site/%E7%AC%94%E8%AE%B0/CMake%E5%AD%A6%E4%B9%A0/",
"title": "CMake学习",
"date_published": "2024-03-26T11:49:10.133Z",
"content_html": "<h2 id=\"前言\"><a class=\"anchor\" href=\"#前言\">#</a> 前言</h2>\n<p>注:本文只考虑构建在 LInux 下使用 cmake 构建 C++ 项目。</p>\n<h3 id=\"make-和-makefile\"><a class=\"anchor\" href=\"#make-和-makefile\">#</a> make 和 makefile</h3>\n<p>gcc 编译 c 程序文件,链接静态库和动态库,FFmpeg:<span class=\"exturl\" data-url=\"aHR0cHM6Ly9mZm1wZWcueGlhbndhaXpoaXlpbi5uZXQvYmFzZS1jb21waWxlL2xpbnV4LWMtc2luZ2xlLmh0bWw=\">https://ffmpeg.xianwaizhiyin.net/base-compile/linux-c-single.html</span></p>\n<p>Make 和 Makefile 快速入门:<span class=\"exturl\" data-url=\"aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L05haXN1X2t1bi9hcnRpY2xlL2RldGFpbHMvMTE2OTE4NTcx\">https://blog.csdn.net/Naisu_kun/article/details/116918571</span></p>\n<p><code>cmake</code> 是 <code>makefile</code> 的上层工具,它们的目的正是为了产生可移植的 makefile,并简化自己动手写 makefile 时的巨大工作量。</p>\n<p>常用命令如下:</p>\n<figure class=\"highlight cmake\"><figcaption data-lang=\"CMake\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># cmake 最低版本需求</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">cmake_minimum_required</span><span class=\"token punctuation\">(</span><span class=\"token property\">VERSION</span> <span class=\"token number\">3.13</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\"># 工程名称</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">project</span><span class=\"token punctuation\">(</span>cmake_study<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token comment\"># 设置 c++ 标准,这里是 c++11</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token keyword\">set</span><span class=\"token punctuation\">(</span><span class=\"token variable\">CMAKE_CXX_STANDARD</span> <span class=\"token number\">11</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\"># 编译源码生成目标</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token keyword\">add_executable</span><span class=\"token punctuation\">(</span>cmake_study src/main.cc<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h4 id=\"setset定义变量\"><a class=\"anchor\" href=\"#setset定义变量\">#</a> <code>SET(set)</code> :定义变量</h4>\n<p><strong>语法</strong>: <code>SET(VAR [VALUE] [CACHE TYPE DOCSTRING [FORCE]]) </code></p>\n<p><strong>指令功能</strong>:用来显式的定义变量</p>\n<p><strong>例子</strong> : <code>SET (SRC_LST main.c other.c)</code></p>\n<p><strong>说明</strong>:用变量代替值,例子中定义 <code>SRC_LST</code> 代替后面的字符串。</p>\n<p>我们可以使用 <code>${NAME}</code> 来获取变量的名称。</p>\n<p><strong>cmake 常用变量</strong></p>\n<table>\n<thead>\n<tr>\n<th style=\"text-align:left\">环境变量名</th>\n<th style=\"text-align:left\">描述</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"text-align:left\">CMAKE_BINARY_DIR, PROJECT_BINARY_DIR, <code><projectname></code> _BINARY_DIR</td>\n<td style=\"text-align:left\">如果是 <code>in source</code> 编译,指得就是工程顶层目录,如果是 <code>out-of-source</code> 编译,指的是工程编译发生的目录。PROJECT_BINARY_DIR 跟其他指令稍有区别,现在,你可以理解为他们是一致的。</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">CMAKE_SOURCE_DIR, PROJECT_SOURCE_DIR, <code><projectname></code> _SOURCE_DIR</td>\n<td style=\"text-align:left\">工程顶层目录。</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">CMAKE_CURRENT_SOURCE_DIR</td>\n<td style=\"text-align:left\">当前处理的 CMakeLists.txt 所在的路径,比如上面我们提到的 src 子目录。</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">CMAKE_CURRRENT_BINARY_DIR</td>\n<td style=\"text-align:left\">如果是 <code>in-source</code> 编译,它跟 CMAKE_CURRENT_SOURCE_DIR 一致,如果是 <code>out-of-source</code> 编译,他指的是 target 编译目录。</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">EXECUTABLE_OUTPUT_PATH , LIBRARY_OUTPUT_PATH</td>\n<td style=\"text-align:left\">最终目标文件存放的路径。</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">PROJECT_NAME</td>\n<td style=\"text-align:left\">通过 PROJECT 指令定义的项目名称。</td>\n</tr>\n</tbody>\n</table>\n<p><strong>cmake 系统信息</strong></p>\n<table>\n<thead>\n<tr>\n<th style=\"text-align:left\">系统信息变量名</th>\n<th style=\"text-align:left\">描述</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"text-align:left\">CMAKE_MAJOR_VERSION</td>\n<td style=\"text-align:left\">CMAKE 主版本号,比如 2.4.6 中的 2</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">CMAKE_MINOR_VERSION</td>\n<td style=\"text-align:left\">CMAKE 次版本号,比如 2.4.6 中的 4</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">CMAKE_PATCH_VERSION</td>\n<td style=\"text-align:left\">CMAKE 补丁等级,比如 2.4.6 中的 6</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">CMAKE_SYSTEM</td>\n<td style=\"text-align:left\">系统名称,比如 Linux-2.6.22</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">CMAKE_SYSTEM_NAME</td>\n<td style=\"text-align:left\">不包含版本的系统名,比如 Linux</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">CMAKE_SYSTEM_VERSION</td>\n<td style=\"text-align:left\">系统版本,比如 2.6.22</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">CMAKE_SYSTEM_PROCESSOR</td>\n<td style=\"text-align:left\">处理器名称,比如 i686.</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">UNIX</td>\n<td style=\"text-align:left\">在所有的类 UNIX 平台为 TRUE, 包括 OS X 和 cygwin</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">WIN32</td>\n<td style=\"text-align:left\">在所有的 win32 平台为 TRUE, 包括 cygwin</td>\n</tr>\n</tbody>\n</table>\n<p><strong>cmake 编译选项</strong></p>\n<table>\n<thead>\n<tr>\n<th style=\"text-align:left\">编译控制开关名</th>\n<th style=\"text-align:left\">描述</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td style=\"text-align:left\">BUILD_SHARED_LIBS</td>\n<td style=\"text-align:left\">使用 <code>ADD_LIBRARY</code> 时生成动态库</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">BUILD_STATIC_LIBS</td>\n<td style=\"text-align:left\">使用 <code>ADD_LIBRARY</code> 时生成静态库</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">CMAKE_C_FLAGS</td>\n<td style=\"text-align:left\">设置 C 编译选项,也可以通过指令 ADD_DEFINITIONS () 添加。</td>\n</tr>\n<tr>\n<td style=\"text-align:left\">CMAKE_CXX_FLAGS</td>\n<td style=\"text-align:left\">设置 C++ 编译选项,也可以通过指令 ADD_DEFINITIONS () 添加。</td>\n</tr>\n</tbody>\n</table>\n<h2 id=\"不引入第三方库\"><a class=\"anchor\" href=\"#不引入第三方库\">#</a> 不引入第三方库</h2>\n<p>目录结构:</p>\n<figure class=\"highlight markdown\"><figcaption data-lang=\"markdown\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>./Demo1</pre></td></tr><tr><td data-num=\"2\"></td><td><pre> |</pre></td></tr><tr><td data-num=\"3\"></td><td><pre> +--- main.cc</pre></td></tr><tr><td data-num=\"4\"></td><td><pre> |</pre></td></tr><tr><td data-num=\"5\"></td><td><pre> +--- math/</pre></td></tr><tr><td data-num=\"6\"></td><td><pre> |</pre></td></tr><tr><td data-num=\"7\"></td><td><pre> +--- MathFunctions.cc</pre></td></tr><tr><td data-num=\"8\"></td><td><pre> |</pre></td></tr><tr><td data-num=\"9\"></td><td><pre> +--- MathFunctions.h</pre></td></tr></table></figure><p>需要在项目根目录 Demo1 和 math 目录里各编写一个 CMakeLists.txt 文件。将 math 目录里的文件编译成静态库再由 main 函数调用。</p>\n<p>math 目录中的 CMakeLists.txt:</p>\n<figure class=\"highlight cmake\"><figcaption data-lang=\"CMake\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 查找当前目录下的所有源文件</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token comment\"># 并将名称保存到 DIR_LIB_SRCS 变量</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">aux_source_directory</span><span class=\"token punctuation\">(</span>. DIR_LIB_SRCS<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token comment\"># 生成静态链接库 MathFunctions</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token keyword\">add_library</span> <span class=\"token punctuation\">(</span>MathFunctions <span class=\"token punctuation\">${</span>DIR_LIB_SRCS<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>根目录中的 CMakeLists.txt :</p>\n<figure class=\"highlight cmake\"><figcaption data-lang=\"CMake\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># CMake 最低版本号要求</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">cmake_minimum_required</span> <span class=\"token punctuation\">(</span><span class=\"token property\">VERSION</span> <span class=\"token number\">2.8</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\"># 项目名称信息,同时会自动生成 PROJECT_NAME 变量,使用 ${PROJECT_NAME} 即可访问到 Demo1</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">project</span> <span class=\"token punctuation\">(</span>Demo1<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\"># 查找当前目录下的所有源文件</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token comment\"># 并将名称保存到 DIR_SRCS 变量,使用 ${DIR_SRCS} 可访问到</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token keyword\">aux_source_directory</span><span class=\"token punctuation\">(</span>. DIR_SRCS<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token comment\"># 添加 math 子目录</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token keyword\">add_subdirectory</span><span class=\"token punctuation\">(</span>math<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre></pre></td></tr><tr><td data-num=\"14\"></td><td><pre><span class=\"token comment\"># 指定生成目标 </span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token keyword\">add_executable</span><span class=\"token punctuation\">(</span>Demo main.cc<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre></pre></td></tr><tr><td data-num=\"17\"></td><td><pre><span class=\"token comment\"># 添加链接库</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre><span class=\"token keyword\">target_link_libraries</span><span class=\"token punctuation\">(</span>Demo MathFunctions<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>单独命令:</p>\n<figure class=\"highlight cmake\"><figcaption data-lang=\"CMake\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 将从第二个往后的参数保存到 DIR_SRCS 变量中,使用 ${DIR_SRCS} 可以访问到</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">set</span><span class=\"token punctuation\">(</span>DIR_SRCS</pre></td></tr><tr><td data-num=\"3\"></td><td><pre> MathFunctions.cc</pre></td></tr><tr><td data-num=\"4\"></td><td><pre> main.cc</pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><h2 id=\"引入第三方库\"><a class=\"anchor\" href=\"#引入第三方库\">#</a> 引入第三方库</h2>\n<h3 id=\"目录结构\"><a class=\"anchor\" href=\"#目录结构\">#</a> 目录结构:</h3>\n<figure class=\"highlight markdown\"><figcaption data-lang=\"markdown\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>.</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>├── CMakeLists.txt</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>├── main.cpp</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>└── README.adoc</pre></td></tr></table></figure><h3 id=\"本地导入find_package\"><a class=\"anchor\" href=\"#本地导入find_package\">#</a> 本地导入(find_package)</h3>\n<p>以 boost 为例,MakeLists.txt:</p>\n<figure class=\"highlight cmake\"><figcaption data-lang=\"CMake\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">cmake_minimum_required</span><span class=\"token punctuation\">(</span><span class=\"token property\">VERSION</span> <span class=\"token number\">3.5</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">project</span> <span class=\"token punctuation\">(</span>third_party_include<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\"># 使用库文件系统和系统查找 Boost,找到了,Boost_FOUND 为真,否则为假</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">find_package</span><span class=\"token punctuation\">(</span>Boost <span class=\"token number\">1.46.1</span> REQUIRED COMPONENTS filesystem system<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token comment\"># 1.46.1 代表需要库的最低版本;REQUIRED 表示找不到会报错;COMPONENTS 用于检测该库的对应组件是否存在,如果不存在则认为找到的库不满足条件。</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token keyword\">if</span><span class=\"token punctuation\">(</span>Boost_FOUND<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre> <span class=\"token keyword\">message</span> <span class=\"token punctuation\">(</span><span class=\"token string\">\"boost found\"</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token keyword\">else</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre> <span class=\"token keyword\">message</span> <span class=\"token punctuation\">(</span>FATAL_ERROR <span class=\"token string\">\"Cannot find Boost\"</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token keyword\">endif</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token comment\"># 指定生成目标</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre><span class=\"token keyword\">add_executable</span><span class=\"token punctuation\">(</span>third_party_include main.cpp<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre></pre></td></tr><tr><td data-num=\"16\"></td><td><pre><span class=\"token comment\"># 添加链接库</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre><span class=\"token keyword\">target_link_libraries</span><span class=\"token punctuation\">(</span>third_party_include <span class=\"token namespace\">PRIVATE</span> <span class=\"token inserted class-name\">Boost::filesystem</span><span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>这里使用 <code>find_package</code> 命令来在本地搜索对应的第三方库,Boost 代表需要查询的库名称;1.46.1 代表需要库的最低版本;REQUIRED 表示该库是必须的,如果找不到会报错;COMPONENTS 用于检测该库的对应组件是否存在,如果不存在则认为找到的库不满足条件。</p>\n<h3 id=\"外部导入fetchcontent\"><a class=\"anchor\" href=\"#外部导入fetchcontent\">#</a> 外部导入(FetchContent)</h3>\n<p>以 GoogleTest 库为例:</p>\n<figure class=\"highlight cmake\"><figcaption data-lang=\"CMake\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">cmake_minimum_required</span><span class=\"token punctuation\">(</span><span class=\"token property\">VERSION</span> <span class=\"token number\">3.14</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">project</span><span class=\"token punctuation\">(</span>my_project<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">set</span><span class=\"token punctuation\">(</span><span class=\"token variable\">CMAKE_CXX_STANDARD</span> <span class=\"token number\">11</span><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token comment\"># 引入 FetchContent 模块</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token keyword\">include</span><span class=\"token punctuation\">(</span>FetchContent<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token comment\"># 获取第三方库,可以是一个 URL 或者一个 Git 仓库</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token function\">FetchContent_Declare</span><span class=\"token punctuation\">(</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre> googletest</pre></td></tr><tr><td data-num=\"11\"></td><td><pre> URL https://github.com/google/googletest/archive/609281088cfefc76f9d0ce82e1ff6c30cc3591e5.zip</pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre></pre></td></tr><tr><td data-num=\"14\"></td><td><pre><span class=\"token comment\"># 将这个第三方库引入项目</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token function\">FetchContent_MakeAvailable</span><span class=\"token punctuation\">(</span>googletest<span class=\"token punctuation\">)</span></pre></td></tr></table></figure>",
"tags": [
"笔记"
]
},
{
"id": "http://yuanmxc.site/%E7%AC%94%E8%AE%B0/Git%E4%BD%BF%E7%94%A8%E7%AC%94%E8%AE%B0/",
"url": "http://yuanmxc.site/%E7%AC%94%E8%AE%B0/Git%E4%BD%BF%E7%94%A8%E7%AC%94%E8%AE%B0/",
"title": "Git使用笔记",
"date_published": "2024-03-26T11:49:10.133Z",
"content_html": "<p>远程仓库指 github 仓库(repositoris),本地仓库指自己被 git 管理的文件夹(含有.git 文件夹)。</p>\n<ul>\n<li>\n<p>重新与远程仓库建立联系,并可以提交代码(自己远程仓库有代码,本地无代码,比如重装系统或者换电脑):</p>\n</li>\n<li>\n<p>如果只是本地没有了仓库,在与远程仓库建立链接时提示” 远程 origin 已存在 ",可以直接 commit+push。</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 克隆远程仓库到本地仓库</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">git</span> clone git@github.com:username/repository_name.git<span class=\"token punctuation\">(</span>远程仓库地址ssh)</pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\"># cd 进本地仓库</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token builtin class-name\">cd</span> 仓库</pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token comment\"># 初始化 git</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token function\">git</span> init</pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\"># 与远程仓库建立链接(关联远程仓库,远程仓库名字叫 origin)</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token function\">git</span> remote <span class=\"token function\">add</span> origin git@github.com:username/repository_name.git<span class=\"token punctuation\">(</span>远程仓库地址ssh<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token comment\"># 获取远程更新</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token function\">git</span> fetch origin</pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token comment\"># 把更新的内容合并到本地分支</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token function\">git</span> merge origin/main</pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token comment\"># 对代码进行一些修改</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre><span class=\"token function\">git</span> <span class=\"token function\">add</span> <span class=\"token builtin class-name\">.</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token function\">git</span> commit <span class=\"token parameter variable\">-m</span> <span class=\"token string\">\"...\"</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre><span class=\"token function\">git</span> push origin main</pre></td></tr></table></figure></li>\n<li>\n<p>创建一个新的仓库:</p>\n</li>\n</ul>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 首先在 github 上创建一个空仓库(之后其实就可以看到教程了)</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\"># 创建一个 README.md 文件,并写入 \"# test\"</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token builtin class-name\">echo</span> <span class=\"token string\">\"# test\"</span> <span class=\"token operator\">>></span> README.md </pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token comment\"># 初始化.git 文件夹</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token function\">git</span> init</pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\"># 将刚刚创建的 README.md 文件加入 git 管理</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token function\">git</span> <span class=\"token function\">add</span> README.md </pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token comment\"># 创建一个提交(即刚刚 README.md 文件的变化)</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token function\">git</span> commit <span class=\"token parameter variable\">-m</span> <span class=\"token string\">\"first commit\"</span> </pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token comment\"># 创建分支 main 作为默认分支</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token function\">git</span> branch <span class=\"token parameter variable\">-M</span> main</pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token comment\"># 与远程仓库建立连接,远程仓库的名字默认是 origin(可换)</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre><span class=\"token function\">git</span> remote <span class=\"token function\">add</span> origin git@github.com:username/repository_name.git(远程仓库地址ssh)</pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token comment\"># 将提交推送到远程仓库(-u 是指第一次提交)</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre><span class=\"token function\">git</span> push <span class=\"token parameter variable\">-u</span> origin main</pre></td></tr></table></figure><ul>\n<li>\n<p>把本地的仓库提交到一个新建立的远程仓库(即远程仓库为空,本地已经有了一个包含.git 文件的仓库,希望不改变内容,将本地仓库推送到远程并关联)</p>\n</li>\n<li>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 与远程仓库建立连接(关联)</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">git</span> remote <span class=\"token function\">add</span> origin git@github.com:username/repository_name.git(远程仓库地址ssh)</pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\"># 与远程仓库建立连接,远程仓库的名字默认是 origin(可换)</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token function\">git</span> branch <span class=\"token parameter variable\">-M</span> main</pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token comment\"># 将提交推送到远程仓库(-u 是指第一次提交)</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token function\">git</span> push <span class=\"token parameter variable\">-u</span> origin <span class=\"token punctuation\">[</span>分支名<span class=\"token punctuation\">]</span></pre></td></tr></table></figure></li>\n<li>\n<p>远程 origin/upstream 已存在:</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 查看远程配置</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">git</span> remote <span class=\"token parameter variable\">-v</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\"># 删除远程配置 </span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token function\">git</span> remote <span class=\"token function\">rm</span> <span class=\"token punctuation\">[</span>远程仓库名<span class=\"token punctuation\">]</span> (一般是origin或者upstream)</pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token comment\"># 更改远程配置(可以直接修改,不需要上一步的删除)</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token function\">git</span> remote set-url upstream <span class=\"token punctuation\">[</span>upstream的新地址<span class=\"token punctuation\">]</span></pre></td></tr></table></figure></li>\n<li>\n<p>fatal: 拒绝合并无关的历史:</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 需要将远程仓库和本地仓库关联起来:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">git</span> branch --set-upstream-to<span class=\"token operator\">=</span>origin/main main</pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\"># 然后使用 git pull 整合远程仓库和本地仓库</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token function\">git</span> pull --allow-unrelated-histories<span class=\"token comment\"># 忽略版本不同造成的影响</span></pre></td></tr></table></figure></li>\n</ul>\n<p>如何给开源社区提交 PR</p>\n<p>假设官方 GitHub 名叫 [officialName],你的 GitHub 名叫 [yourName],GitHub 仓库名字叫 [repository]。</p>\n<ol>\n<li>\n<p>网页操作:在官 C 语言代码方 GitHub 仓库 fork 一个相同的仓库到你的 GitHub.</p>\n</li>\n<li>\n<p>在你的仓库复制代码地址 [your code SSH/HTTPS],在官方仓库复制代码地址 [official code SSH/HTTPS],然后</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 克隆你 GitHub 仓库到本地</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">git</span> clone <span class=\"token punctuation\">[</span>your code SSH/HTTPS<span class=\"token punctuation\">]</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\"># 添加官方仓库地址</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token function\">git</span> remote <span class=\"token function\">add</span> upstream <span class=\"token punctuation\">[</span>official code SSH/HTTPS<span class=\"token punctuation\">]</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token comment\"># 检查仓库的远程信息</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token function\">git</span> remote <span class=\"token parameter variable\">-v</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\"># 远程信息输出应为:</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre>origin <span class=\"token punctuation\">[</span>your code SSH/HTTPS<span class=\"token punctuation\">]</span> <span class=\"token punctuation\">(</span>fetch<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre>origin <span class=\"token punctuation\">[</span>your code SSH/HTTPS<span class=\"token punctuation\">]</span> <span class=\"token punctuation\">(</span>push<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>upstream <span class=\"token punctuation\">[</span>official code SSH/HTTPS<span class=\"token punctuation\">]</span> <span class=\"token punctuation\">(</span>fetch<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre>upstream <span class=\"token punctuation\">[</span>official code SSH/HTTPS<span class=\"token punctuation\">]</span> <span class=\"token punctuation\">(</span>push<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>fetch 和 push 分别代表你在 fetch(拉取)和 push(推送)的 GitHub 仓库的地址,origin 代表你的 GitHub 仓库,upstream 代表官方的 GitHub 仓库。</p>\n</li>\n<li>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 从 upstream 中获取最新的代码下载到本地,但是不会自动合并到本地分支中。一般和下面第二个命令一起使用。</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">git</span> fetch upstream</pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\"># 将 upstream 的 master 分支合并到当前本地分支中,如果有冲突需要手动解决(本地分支的代码就与 upstream 的 master 分支保持同步)</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token function\">git</span> merge upstream/master</pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token comment\"># 创建并切换到名为 fixBug 的新分支</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token function\">git</span> checkout <span class=\"token parameter variable\">-b</span> fixBug</pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\"># 将当前分支 fixBug 推送到远程仓库 origin 上,并将本地分支和远程分支关联起来。</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token function\">git</span> push <span class=\"token parameter variable\">-u</span> origin fixBug</pre></td></tr></table></figure></li>\n<li>\n<p>之后,你可以在 fixBug 分支上进行一些修改,然后通过一下步骤将修改好的代码 push 到 GitHub 仓库的对应分支。</p>\n<p>当你需要切换分支时,你必须 commit 当前的代码。</p>\n<p>你的每一次 comiit 都会有所记录,当你 push 后,会把所有的 commit 都交上去,如果你 commit 的文件涉及到一个 pr,那么 pr 中也会有所修改,记录你的 commit。</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 查看修改了那些文件</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">git</span> status</pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\"># 查看修改内容</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token function\">git</span> <span class=\"token function\">diff</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token comment\"># add 提交</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token function\">git</span> <span class=\"token function\">add</span> <span class=\"token builtin class-name\">.</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\"># commit 提交(如果官方仓需要 Signed-off-by 检查的就带账号邮箱信息)</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token function\">git</span> commit <span class=\"token parameter variable\">-m</span> <span class=\"token string\">\"xxxxx\"</span> <span class=\"token parameter variable\">-s</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token comment\"># 将过去的 n 个 commit 合并为一个 commit(等待尝试)</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token function\">git</span> rebase <span class=\"token parameter variable\">-i</span> HEAD~n <span class=\"token comment\"># 打开一个编辑器,将第二行开始的每一行的第一个单词从 pick 改为 squash。然后保存文件并退出。另一个编辑器会打开,在这里修改最终的提交信息。</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token comment\"># 将本次提交合并到上一次提交,如果你上一次提交已经 push 过,需要使用 --force 或者 --force-with-lease 选项来强制推送。可能会覆盖其他人在远程仓库上做的修改,谨慎使用。</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token function\">git</span> commit <span class=\"token parameter variable\">--amend</span> <span class=\"token comment\"># 会打开一个编辑器,让你修改提交信息。</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token comment\"># push 到远程仓</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre><span class=\"token function\">git</span> push origin</pre></td></tr></table></figure></li>\n<li>\n<p>此时,你的 GitHub 仓库的 fixBug 分支的代码已经发生了变化,在 Pull requests 界面你可以找到提交 PR 的方法,然后就就可以按照社区要去提供代码了。对于本地的代码,一旦你创建分支之后,master 和 fixBug 就是两份代码了,你在 fixBug 的修改并不会影响到 master 的的代码。你可以通过 <code>git checkout [分支名]</code> 来切换到你想要的分支。你可以创建多个分支来确保工作的顺利进行。</p>\n</li>\n<li>\n<p>其他有用的命令</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 分支操作:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token comment\"># 查看所有分支</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token function\">git</span> bC语言代码</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>ranch(*代表当前所在分支)</pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token comment\"># 删除分支</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token function\">git</span> branch <span class=\"token parameter variable\">-d</span> <span class=\"token punctuation\">[</span>branchName<span class=\"token punctuation\">]</span><span class=\"token punctuation\">(</span>-d换为-D强制删除<span class=\"token punctuation\">)</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\"># 更改分支名</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token function\">git</span> branch <span class=\"token parameter variable\">-m</span> <span class=\"token punctuation\">[</span>oldName<span class=\"token punctuation\">]</span> <span class=\"token punctuation\">[</span>newName<span class=\"token punctuation\">]</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token comment\"># 从远程仓库 upstream 拉取代码(获取最新的代码,但不会将其合并到本地)</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token function\">git</span> fetch upstream</pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token comment\"># 从远程仓库 origin 拉取代码(获取最新的代码,但不会将其合并到本地)</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token function\">git</span> fetch origin</pre></td></tr><tr><td data-num=\"14\"></td><td><pre><span class=\"token comment\"># 比较本地仓库当前的分支 HEAD 和 upstream/master 分支之间的差异</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token function\">git</span> <span class=\"token function\">diff</span> HEAD upstream/master</pre></td></tr><tr><td data-num=\"16\"></td><td><pre></pre></td></tr><tr><td data-num=\"17\"></td><td><pre><span class=\"token comment\"># 显示本地的 commit 历史版本</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre><span class=\"token function\">git</span> log </pre></td></tr><tr><td data-num=\"19\"></td><td><pre><span class=\"token comment\"># 根据 commit 历史版本号,可以进行版本回退</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre><span class=\"token function\">git</span> reset <span class=\"token punctuation\">[</span>版本号<span class=\"token punctuation\">]</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre><span class=\"token comment\"># 将本地分支重置为最新拉取的 upstream 仓库的版本</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre><span class=\"token function\">git</span> reset <span class=\"token parameter variable\">--hard</span> upstream/<span class=\"token operator\"><</span>upstream_branch_name<span class=\"token operator\">></span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre><span class=\"token comment\"># 将本地分支重置为 oorigin 仓库的版本</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre><span class=\"token function\">git</span> reset <span class=\"token parameter variable\">--hard</span> origin/<span class=\"token operator\"><</span>origin_branch_name<span class=\"token operator\">></span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre><span class=\"token comment\"># 将本地仓库的更改推送到 origin(-f 选项强制推送更改,这将覆盖 origin 仓库中的所有更改)</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre><span class=\"token function\">git</span> push <span class=\"token parameter variable\">-f</span> origin <span class=\"token operator\"><</span>local_branch_name<span class=\"token operator\">></span></pre></td></tr><tr><td data-num=\"27\"></td><td><pre></pre></td></tr><tr><td data-num=\"28\"></td><td><pre><span class=\"token comment\"># 删除本地未跟踪的目录和文件(d 和 f 分别指目录和文件)</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre><span class=\"token function\">git</span> clean <span class=\"token parameter variable\">-df</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre><span class=\"token comment\"># 从 origin 指定的 (自己的)GitHub 仓库拉取代码</span></pre></td></tr><tr><td data-num=\"31\"></td><td><pre><span class=\"token function\">git</span> fetch origin</pre></td></tr></table></figure></li>\n</ol>\n",
"tags": [
"笔记"
]
},
{
"id": "http://yuanmxc.site/%E7%AC%94%E8%AE%B0/Linux_coding/",
"url": "http://yuanmxc.site/%E7%AC%94%E8%AE%B0/Linux_coding/",
"title": "Linux_coding",
"date_published": "2024-03-26T11:49:10.133Z",
"content_html": "<h2 id=\"目录文件相关\"><a class=\"anchor\" href=\"#目录文件相关\">#</a> 目录 / 文件相关</h2>\n<h3 id=\"存储信息的结构体\"><a class=\"anchor\" href=\"#存储信息的结构体\">#</a> 存储信息的结构体:</h3>\n<ul>\n<li>\n<p><code>DIR* dp</code> : <strong>某个目录的信息</strong> (opendir 返回,做 readir 参数)</p>\n<p>头文件: <code>dirent.h</code></p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">struct</span> <span class=\"token class-name\">__dirstream</span> </pre></td></tr><tr><td data-num=\"2\"></td><td><pre> <span class=\"token punctuation\">{</span> </pre></td></tr><tr><td data-num=\"3\"></td><td><pre> <span class=\"token keyword\">void</span> <span class=\"token operator\">*</span>__fd<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 文件描述符</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre> <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>__data<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 目录块</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre> <span class=\"token keyword\">int</span> __entry_data<span class=\"token punctuation\">;</span> <span class=\"token comment\">//data 对应的条目号 </span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre> <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>__ptr<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 块中的当前指针</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre> <span class=\"token keyword\">int</span> __entry_ptr<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 条目号对应的指针 </span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre> <span class=\"token class-name\">size_t</span> __allocation<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 为块分配的空间</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre> <span class=\"token class-name\">size_t</span> __size<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 块中的总有效数据</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre> <span class=\"token function\">__libc_lock_define</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">,</span> __lock<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span><span class=\"token comment\">// 此结构的互斥锁</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span> </pre></td></tr><tr><td data-num=\"12\"></td><td><pre> </pre></td></tr><tr><td data-num=\"13\"></td><td><pre><span class=\"token keyword\">typedef</span> <span class=\"token keyword\">struct</span> <span class=\"token class-name\">__dirstream</span> DIR<span class=\"token punctuation\">;</span></pre></td></tr></table></figure></li>\n<li>\n<p><code>struct dirent *entry</code> : <strong>某个文件在目录里的简略信息</strong> (readir 返回)</p>\n<p>头文件: <code>dirent.h</code></p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">struct</span> <span class=\"token class-name\">dirent</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre> <span class=\"token punctuation\">{</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre> __ino_t d_ino<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 文件的 inode 节点号</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre> __off_t d_off<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 在目录文件中的偏移</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre> <span class=\"token keyword\">unsigned</span> <span class=\"token keyword\">short</span> <span class=\"token keyword\">int</span> d_reclen<span class=\"token punctuation\">;</span><span class=\"token comment\">// 文件名字长度</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre> <span class=\"token keyword\">unsigned</span> <span class=\"token keyword\">char</span> d_type<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 文件类型 </span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre> <span class=\"token keyword\">char</span> d_name<span class=\"token punctuation\">[</span><span class=\"token number\">256</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\t\t <span class=\"token comment\">// 文件名字 </span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure></li>\n<li>\n<p><code>stat</code> 结构体 : <strong>某个文件的详细信息</strong></p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">struct</span> <span class=\"token class-name\">stat</span> <span class=\"token punctuation\">{</span> </pre></td></tr><tr><td data-num=\"2\"></td><td><pre> <span class=\"token class-name\">mode_t</span> st_mode<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 文件类型、访问权限 </span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre> <span class=\"token class-name\">ino_t</span> st_ino<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 索引节点号 </span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre> <span class=\"token class-name\">dev_t</span> st_dev<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 文件使用的设备号 </span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre> <span class=\"token class-name\">dev_t</span> st_rdev<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 设备文件的设备号 </span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre> <span class=\"token class-name\">nlink_t</span> st_nlink<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 文件的硬连接数 </span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre> <span class=\"token class-name\">uid_t</span> st_uid<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 所有者用户识别号 </span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre> <span class=\"token class-name\">gid_t</span> st_gid<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 组识别号 </span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre> <span class=\"token class-name\">off_t</span> st_size<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 以字节为单位的文件容量 </span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre> <span class=\"token class-name\">time_t</span> st_atime<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 最后一次访问该文件的时间 </span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre> <span class=\"token class-name\">time_t</span> st_mtime<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 最后一次修改该文件的时间 </span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre> <span class=\"token class-name\">time_t</span> st_ctime<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 最后一次改变该文件状态的时间 </span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre> <span class=\"token class-name\">blksize_t</span> st_blksize<span class=\"token punctuation\">;</span><span class=\"token comment\">// 文件内容所占的磁盘块的大小 </span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre> <span class=\"token class-name\">blkcnt_t</span> st_blocks<span class=\"token punctuation\">;</span> <span class=\"token comment\">// 文件内容所占的磁盘块的数量 </span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre><span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><h3 id=\"相关函数\"><a class=\"anchor\" href=\"#相关函数\">#</a> 相关函数:</h3>\n</li>\n<li>\n<p><code>chdir()</code></p>\n<p>用途: <code>int chdir(const char * path)</code></p>\n<p>切换到参数指定的目录,成功返回 0 , 失败返回 - 1 , 置 errno</p>\n</li>\n<li>\n<p><code>getcwd()</code></p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\"><unistd.h></span></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">char</span> <span class=\"token operator\">*</span><span class=\"token function\">getcwd</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>buf<span class=\"token punctuation\">,</span> <span class=\"token class-name\">size_t</span> size<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>用途:将当前目录的绝对路径拷贝到参数 <code>buffer</code> 所指的空间,参数 <code>size</code> 为 <code>buf</code> 所指的空间大小。 <code>bu</code> f 为 <code>NULL</code> , <code>size</code> 为 0 时, <code>getcwd</code> 调用 <code>malloc</code> 来动态分配内存一个空间存储绝对路径,返回指向这个空间的指针,此时要注意后面释放 <code>buf</code> 内存,防止内存泄漏。成功返回指向绝对路径的指针,失败返回 <code>NULL</code> ,置 <code>errno</code> 。</p>\n</li>\n<li>\n<p>mkdir()</p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\"><sys/types.h></span> </span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\"><sys/stat.h></span></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">mkdir</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>pathname<span class=\"token punctuation\">,</span> <span class=\"token class-name\">mode_t</span> mode<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>用途:在当前目录下按照 mode 指定的权限创建名为 <code>pathname</code> 的目录,成功返回 0,失败返回 - 1,置 <code>errno</code></p>\n<p>mode 简述(不全):使用掩码,后三位数字从左往右依次表示文件所有者权限、用户组权限、其他用户权限。1:只执行,2:只写入,4:只可读,7:读、写、执行,3:执行 + 写,5:读 + 执行,依次类推。可以只写后三位数字。</p>\n</li>\n<li>\n<p>rmdir()</p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\"><unistd.h></span></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">rmdir</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>pathname<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>用途:在当前目录下删除名为 <code>pathname</code> 的空目录,成功返回 0,失败返回 - 1,置 <code>errno</code></p>\n</li>\n<li>\n<p><code>opendir()</code></p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\"><sys/types.h></span></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\"><dirent.h></span></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>DIR <span class=\"token operator\">*</span><span class=\"token function\">opendir</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>name<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>DIR <span class=\"token operator\">*</span><span class=\"token function\">fdopendir</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> fd<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>用途:打开参数 name 或 fd 指定的目录,创建一个目录流。成功返回一个 <code>DIR</code> 指针,失败返回 <code>NULL</code> ,置 <code>errno</code></p>\n</li>\n<li>\n<p><code>readdir()</code></p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>include <span class=\"token operator\"><</span>dirent<span class=\"token punctuation\">.</span>h<span class=\"token operator\">></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">struct</span> <span class=\"token class-name\">dirent</span><span class=\"token operator\">*</span><span class=\"token function\">readdir</span><span class=\"token punctuation\">(</span>DIR <span class=\"token operator\">*</span>dirp<span class=\"token punctuation\">)</span></pre></td></tr></table></figure><p>用途:读取参数 dirp 指定的目录流,成功返回指向目录内当前偏移量指向的文件的简略信息的 <code>dirent</code> 结构指针,失败或者到达目录尾则返回 <code>NULL</code></p>\n</li>\n<li>\n<p><code>closedir()</code></p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\"><sys/types.h></span></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\"><dirent.h></span></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">closedir</span><span class=\"token punctuation\">(</span>DIR <span class=\"token operator\">*</span>dirp<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>用途:关闭参数 dirp 指定的目录流,成功返回 0,失败返回 - 1,置 ereno</p>\n</li>\n<li>\n<p><code>stat() fstat() lstat()</code></p>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\"><sys/stat.h></span> </span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\"><unistd.h></span></span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">stat</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>path<span class=\"token punctuation\">,</span> <span class=\"token keyword\">struct</span> <span class=\"token class-name\">stat</span> <span class=\"token operator\">*</span>struct_stat<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">lstat</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> <span class=\"token keyword\">char</span> <span class=\"token operator\">*</span>path<span class=\"token punctuation\">,</span><span class=\"token keyword\">struct</span> <span class=\"token class-name\">stat</span> <span class=\"token operator\">*</span>struct_stat<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">fstat</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> fdp<span class=\"token punctuation\">,</span> <span class=\"token keyword\">struct</span> <span class=\"token class-name\">stat</span> <span class=\"token operator\">*</span>struct_stat<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>用途:通过文件名 path 或者文件描述符 fdp 获取文件详细信息,将信息保存在 struct_stat 结构体中,成功返回 0, 失败返回 - 1 并,置 errno。</p>\n<p>区别:stat 没有处理字符链接 (软链接)的能力,如果一个文件是符号链接 (软链接),stat 会直接返回它所指向的文件的属性;而 lstat 返回的就是这个符号链接的内容。目录在 linux 中也是一个文件,文件的内容就是这这个目录下面所有文件与 inode 的对应关系。硬链接就是在某一个目录下面将一个文件名与一个 inode 关联起来,就是添加一条记录。软链接也叫符号链接,这个文件的内容就是一个字符串,这个字符串就是它所链接的文件的绝对或者相对地址。</p>\n</li>\n</ul>\n",
"tags": [
"笔记"
]
},
{
"id": "http://yuanmxc.site/%E7%AC%94%E8%AE%B0/%E7%9F%A5%E8%AF%86%E5%B0%8F%E7%82%B9/",
"url": "http://yuanmxc.site/%E7%AC%94%E8%AE%B0/%E7%9F%A5%E8%AF%86%E5%B0%8F%E7%82%B9/",
"title": "知识小点",
"date_published": "2024-03-26T11:49:10.133Z",
"content_html": "<ul>\n<li>辅助理解递归:明确这个函数是做什么的,然后在这个函数里有需要做这一步,比如按扩展先序创建二叉树,函数作用为:“创建输入节点的子树,先左子树,后右子树”。然后创建左右子树的时候是递归调用。</li>\n<li>管道和进程间通信,即 <code>pipe()</code> + <code>fork()</code> 的形式,注意关掉无用的文件文件描述符,否则会造成文件描述符的浪费,并且 fork () 后关闭比较麻烦。先 pipe (),之后先把<strong>能立刻用完 **** 之后就不在用的符</strong>立刻用完,然后将他们关掉,再 fork ()。因为子进程会继承父进程的文件描述符。例:<span class=\"exturl\" data-url=\"aHR0cDovL3h2Ni5kZ3Muem9uZS9sYWJzL3JlcXVpcmVtZW50cy9sYWIxLmh0bWw=\">MIT6.S081 lab 的第三个求 2-35 内的素数</span>。</li>\n</ul>\n<figure class=\"highlight c\"><figcaption data-lang=\"c\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token macro property\"><span class=\"token directive-hash\">#</span><span class=\"token directive keyword\">include</span> <span class=\"token string\"><stidio.h></span></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">void</span> <span class=\"token function\">is_primes</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> fd_father<span class=\"token punctuation\">[</span><span class=\"token number\">2</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre> <span class=\"token keyword\">int</span> fd_child<span class=\"token punctuation\">[</span><span class=\"token number\">2</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span><span class=\"token comment\">// 该进程的子进程的管道读写符</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre> <span class=\"token function\">pipe</span><span class=\"token punctuation\">(</span>fd_child<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre></pre></td></tr><tr><td data-num=\"7\"></td><td><pre> <span class=\"token comment\">// 打印一定是素数的数(第一个写进来的数)</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre> <span class=\"token keyword\">int</span> p <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre> <span class=\"token function\">read</span><span class=\"token punctuation\">(</span>fd_father<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">&</span>p<span class=\"token punctuation\">,</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span>p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre> <span class=\"token function\">printf</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"prime %d\\n\"</span><span class=\"token punctuation\">,</span> p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre> <span class=\"token comment\">// 如果 n 是 p 的整数倍,那他一定不是素数,丢弃;否则,可能是素数,写给子进程。</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre> <span class=\"token keyword\">int</span> n<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"13\"></td><td><pre> <span class=\"token keyword\">int</span> left <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 剩下几个数字没有判断。</span></pre></td></tr><tr><td data-num=\"14\"></td><td><pre> <span class=\"token keyword\">while</span><span class=\"token punctuation\">(</span><span class=\"token function\">read</span><span class=\"token punctuation\">(</span>fd_father<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">&</span>n<span class=\"token punctuation\">,</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span>p<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">!=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></pre></td></tr><tr><td data-num=\"15\"></td><td><pre> <span class=\"token keyword\">if</span><span class=\"token punctuation\">(</span>n <span class=\"token operator\">%</span> p <span class=\"token operator\">!=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></pre></td></tr><tr><td data-num=\"16\"></td><td><pre> <span class=\"token function\">write</span><span class=\"token punctuation\">(</span>fd_child<span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">&</span>n<span class=\"token punctuation\">,</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span>n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"17\"></td><td><pre> left<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"18\"></td><td><pre> <span class=\"token punctuation\">}</span></pre></td></tr><tr><td data-num=\"19\"></td><td><pre> <span class=\"token punctuation\">}</span></pre></td></tr><tr><td data-num=\"20\"></td><td><pre> <span class=\"token function\">close</span><span class=\"token punctuation\">(</span>fd_father<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"21\"></td><td><pre> <span class=\"token function\">close</span><span class=\"token punctuation\">(</span>fd_child<span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"22\"></td><td><pre> <span class=\"token keyword\">if</span><span class=\"token punctuation\">(</span>left <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span> <span class=\"token comment\">// 说明所有数都判断完了,为了避免最后一层还会执行后面的 fork, 避免出现多个 0.</span></pre></td></tr><tr><td data-num=\"23\"></td><td><pre> <span class=\"token function\">exit</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"24\"></td><td><pre> <span class=\"token punctuation\">}</span></pre></td></tr><tr><td data-num=\"25\"></td><td><pre> <span class=\"token comment\">// 上面同理,先把自己进程的读端和子进程的写端用完,关掉,再开子进程。</span></pre></td></tr><tr><td data-num=\"26\"></td><td><pre> </pre></td></tr><tr><td data-num=\"27\"></td><td><pre> <span class=\"token keyword\">if</span><span class=\"token punctuation\">(</span><span class=\"token function\">fork</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span> <span class=\"token comment\">// 该进程的子进程</span></pre></td></tr><tr><td data-num=\"28\"></td><td><pre> <span class=\"token function\">is_primes</span><span class=\"token punctuation\">(</span>fd_child<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 子进程读取父进程进程写进来数字,并判断是否为素数:可能是素数的,写给孙进程然后递归调用,一定不是素数的,丢弃。</span></pre></td></tr><tr><td data-num=\"29\"></td><td><pre> <span class=\"token punctuation\">}</span></pre></td></tr><tr><td data-num=\"30\"></td><td><pre> <span class=\"token function\">wait</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"31\"></td><td><pre><span class=\"token punctuation\">}</span></pre></td></tr><tr><td data-num=\"32\"></td><td><pre></pre></td></tr><tr><td data-num=\"33\"></td><td><pre><span class=\"token keyword\">int</span> <span class=\"token function\">main</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> argc<span class=\"token punctuation\">,</span> <span class=\"token keyword\">char</span><span class=\"token operator\">*</span><span class=\"token operator\">*</span> atgv<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></pre></td></tr><tr><td data-num=\"34\"></td><td><pre> <span class=\"token keyword\">int</span> fd_child<span class=\"token punctuation\">[</span><span class=\"token number\">2</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 子进程的管道读写端</span></pre></td></tr><tr><td data-num=\"35\"></td><td><pre> <span class=\"token function\">pipe</span><span class=\"token punctuation\">(</span>fd_child<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"36\"></td><td><pre></pre></td></tr><tr><td data-num=\"37\"></td><td><pre> <span class=\"token comment\">// 先把数字写进子进程管道,并关掉写端。存存储器,系统总线,主存,磁盘。</span></pre></td></tr><tr><td data-num=\"38\"></td><td><pre></pre></td></tr><tr><td data-num=\"39\"></td><td><pre>操作系统管理硬件。进程(处理器,主存,i<span class=\"token operator\">/</span>o设备),虚拟内存(主存,i<span class=\"token operator\">/</span>o设备),文件(i<span class=\"token operator\">/</span>o设备)。</pre></td></tr><tr><td data-num=\"40\"></td><td><pre></pre></td></tr><tr><td data-num=\"41\"></td><td><pre>并发运行:一个进程的指令和另一个进程的指令交错执行。这种交错执行的机制叫上下文切换,进程间切换由内核管理。</pre></td></tr><tr><td data-num=\"42\"></td><td><pre></pre></td></tr><tr><td data-num=\"43\"></td><td><pre>上下文:操作系统保持跟踪进程运行所需的所有状态信息。</pre></td></tr><tr><td data-num=\"44\"></td><td><pre></pre></td></tr><tr><td data-num=\"45\"></td><td><pre>内核:操作系统代码常驻主存的一部分,不是独立的进程。是系统全部进程所用代码和数据结构的集合。</pre></td></tr><tr><td data-num=\"46\"></td><td><pre></pre></td></tr><tr><td data-num=\"47\"></td><td><pre>栈位于用户虚拟地址空间顶部,编译器用它来实现函数调用,和堆一样,用户栈在程序执行期间可以动态地扩展和收缩 。 调用函数时,栈会增长;从一个函数返回时,栈会收缩 。</pre></td></tr><tr><td data-num=\"48\"></td><td><pre></pre></td></tr><tr><td data-num=\"49\"></td><td><pre>内核虚拟内存:程序无法读写,或调用内核代码定义的函数,需要调用内核来执行操作。</pre></td></tr><tr><td data-num=\"50\"></td><td><pre></pre></td></tr><tr><td data-num=\"51\"></td><td><pre><span class=\"token operator\"><</span>img title<span class=\"token operator\">=</span><span class=\"token string\">\"\"</span> src<span class=\"token operator\">=</span><span class=\"token string\">\"file:///home/yuanye/图片/2022-10-06%2017-25-26%20的屏幕截图.png\"</span> alt<span class=\"token operator\">=</span><span class=\"token string\">\"2022-10-06 17-25-26 的屏幕截图.png\"</span> width<span class=\"token operator\">=</span><span class=\"token string\">\"309\"</span> data<span class=\"token operator\">-</span>align<span class=\"token operator\">=</span><span class=\"token string\">\"center\"</span><span class=\"token operator\">></span></pre></td></tr><tr><td data-num=\"52\"></td><td><pre></pre></td></tr><tr><td data-num=\"53\"></td><td><pre>PC:程序计数器(寄存器),ALU(算数<span class=\"token operator\">/</span>逻辑单元)</pre></td></tr><tr><td data-num=\"54\"></td><td><pre> <span class=\"token keyword\">for</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">int</span> i <span class=\"token operator\">=</span> <span class=\"token number\">2</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\"><=</span> <span class=\"token number\">35</span><span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">{</span></pre></td></tr><tr><td data-num=\"55\"></td><td><pre> <span class=\"token function\">write</span><span class=\"token punctuation\">(</span>fd_child<span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">&</span>i<span class=\"token punctuation\">,</span> <span class=\"token keyword\">sizeof</span><span class=\"token punctuation\">(</span>i<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"56\"></td><td><pre> <span class=\"token punctuation\">}</span></pre></td></tr><tr><td data-num=\"57\"></td><td><pre> <span class=\"token function\">close</span><span class=\"token punctuation\">(</span>fd_child<span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"58\"></td><td><pre> </pre></td></tr><tr><td data-num=\"59\"></td><td><pre> <span class=\"token comment\">// 创建子进程,只需要子进程的读端。</span></pre></td></tr><tr><td data-num=\"60\"></td><td><pre> <span class=\"token keyword\">if</span><span class=\"token punctuation\">(</span><span class=\"token function\">fork</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span> </pre></td></tr><tr><td data-num=\"61\"></td><td><pre> <span class=\"token function\">is_primes</span><span class=\"token punctuation\">(</span>fd_child<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 子进程读取父进程进程写进来数字,并判断是否为素数:可能是素数的,写给孙进程然后递归调用,一定不是素数的,丢弃。</span></pre></td></tr><tr><td data-num=\"62\"></td><td><pre> <span class=\"token punctuation\">}</span> </pre></td></tr><tr><td data-num=\"63\"></td><td><pre> <span class=\"token function\">wait</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"64\"></td><td><pre> <span class=\"token function\">exit</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"65\"></td><td><pre><span class=\"token punctuation\">}</span></pre></td></tr></table></figure>",
"tags": [
"笔记"
]
},
{
"id": "http://yuanmxc.site/writing/%E9%9A%8F%E8%AE%B0/",
"url": "http://yuanmxc.site/writing/%E9%9A%8F%E8%AE%B0/",
"title": "随记",
"date_published": "2024-03-26T11:49:10.133Z",
"content_html": "<h2 id=\"真寻bot\"><a class=\"anchor\" href=\"#真寻bot\">#</a> 真寻 bot:</h2>\n<p>docker pull ubuntu 下镜像</p>\n<p>docker run -it --network=host --name="zhenxunbot" ubuntu 本机网络启动</p>\n<p>passwd 设置 root 密码</p>\n<ul>\n<li>\n<p>每次进 docker 都要设置代理:</p>\n<p>export ALL_PROXY='socks5://127.0.0.1:7890'<br />\nexport https_proxy="<span class=\"exturl\" data-url=\"aHR0cDovLzEyNy4wLjAuMTo3ODkw\">http://127.0.0.1:7890</span>"<br />\ncurl <span class=\"exturl\" data-url=\"aHR0cDovL2NpcC5jYw==\">cip.cc</span> 查看当前网络代理</p>\n</li>\n<li>\n<p>安装所需软件</p>\n<p>apt update<br />\napt install git vim curl python3 python3-pip</p>\n</li>\n<li>\n<p>换源:</p>\n<p>vim etc/apt/sources.list,加入</p>\n<pre><code class=\"language-JSON\">deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy main restricted universe multiverse\ndeb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-updates main restricted universe multiverse\ndeb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-backports main restricted universe multiverse\ndeb http://security.ubuntu.com/ubuntu/ jammy-security main restricted universe multiverse\n</code></pre>\n</li>\n<li>\n<p>安装 gocq,下载源码,启动,选 3,</p>\n</li>\n<li>\n<p>修改 <code>config.yml</code> 文件,QQ 号和 universal: ws://your_websocket_universal.server</p>\n</li>\n<li>\n<p>vim device.json 换协议为 2,连手机热点,扫码</p>\n</li>\n<li>\n<p>装数据库 :apt install postgresql postgresql-contrib</p>\n</li>\n<li>\n<p>启动数据库:service postgresql start 开机自启:update-rc.d postgresql defaults</p>\n</li>\n<li>\n<p>创建数据库和用户</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">sudo</span> <span class=\"token function\">su</span> - postgres <span class=\"token comment\"># 切换用户</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>psql</pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\"># 用户名↓ # 密码↓</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\"># CREATE USER uname WITH PASSWORD 'zhenxun'; # 创建用户(可不执行)</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre></pre></td></tr><tr><td data-num=\"6\"></td><td><pre> <span class=\"token comment\">#密码↓</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre>alter user postgres with password <span class=\"token string\">'zhenxun_bot'</span><span class=\"token punctuation\">;</span> <span class=\"token comment\"># 修改 postgres 的密码</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre></pre></td></tr><tr><td data-num=\"9\"></td><td><pre> <span class=\"token comment\"># 数据库名称↓ 所有者 (用户名)↓</span></pre></td></tr><tr><td data-num=\"10\"></td><td><pre>CREATE DATABASE zhenxun_bot OWNER postgres<span class=\"token punctuation\">;</span> <span class=\"token comment\"># 创建数据库</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token punctuation\">\\</span>q <span class=\"token comment\"># 退出</span></pre></td></tr></table></figure><p>exit</p>\n<p>su - root 切回</p>\n</li>\n<li>\n<p>下载真寻 bot 源码</p>\n</li>\n<li>\n<p>安装依赖(在真寻 bot 目录内):</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>pip3 <span class=\"token function\">install</span> poetry <span class=\"token comment\"># 使用 poetry 管理 python 包</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>poetry <span class=\"token function\">install</span> <span class=\"token comment\"># 安装依赖</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>poetry shell <span class=\"token comment\"># 进入虚拟环境(以下在虚拟环境下执行)</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>pip3 <span class=\"token function\">install</span> playwright</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>playwright <span class=\"token function\">install</span> chromium</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>playwright install-deps chromium</pre></td></tr></table></figure></li>\n<li>\n<p>设置超级用户,打开 <strong>.env.dev</strong> 文件,在 <code>SUPERUSERS</code> 中添加自己的 QQ</p>\n</li>\n<li>\n<h3 id=\"填写数据库数据\"><a class=\"anchor\" href=\"#填写数据库数据\">#</a> 填写数据库数据</h3>\n</li>\n</ul>\n<figure class=\"highlight text\"><figcaption data-lang=\"text\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>SUPERUSERS=[\"123456789\"]</pre></td></tr></table></figure><p>填写数据库数据</p>\n<p><strong> <code>configs</code> </strong> 目录并打开 <strong> <code>config.py</code> </strong> 文件</p>\n<figure class=\"highlight text\"><figcaption data-lang=\"text\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>bind: str = \"\" # 数据库连接链接</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>sql_name: str = \"postgres\"</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>user: str = \"\" # 数据用户名</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>password: str = \"\" # 数据库密码</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>address: str = \"\" # 数据库地址</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>port: str = \"\" # 数据库端口</pre></td></tr><tr><td data-num=\"7\"></td><td><pre>database: str = \"\" # 数据库名称</pre></td></tr></table></figure><p>修改为:</p>\n<figure class=\"highlight text\"><figcaption data-lang=\"text\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>bind: str = \"\" # 数据库连接链接</pre></td></tr><tr><td data-num=\"2\"></td><td><pre>sql_name: str = \"postgres\"</pre></td></tr><tr><td data-num=\"3\"></td><td><pre>user: str = \"postgres\"</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>password: str = \"zhenxun_bot\"</pre></td></tr><tr><td data-num=\"5\"></td><td><pre>address: str = \"127.0.0.1\"</pre></td></tr><tr><td data-num=\"6\"></td><td><pre>port: str = \"5432\"</pre></td></tr><tr><td data-num=\"7\"></td><td><pre>database: str = \"zhenxun_bot\"</pre></td></tr></table></figure><ul>\n<li>\n<p>启动真寻</p>\n</li>\n<li>\n<p>依赖模块缺少,比如 nonobot,tortoise,adapter,一般是依赖问题,是执行 poetry shell 时出现报错,如果报错为:PyYAML 安装失败,就修改 pyprojecr.toml 文件(包含所有要下载的依赖)中的 PyYAML=“5.3.0”,然后再次执行 poetry install,如果说有红字不匹配,执行 poetry lock --no-update 后再次执行 poetry install,所有依赖安装完毕后运行,没有问题,均是在虚拟环境中。 <code>poetry show</code> 会显示已安装和未安装的依赖以及版本</p>\n</li>\n<li>\n<p>开机需保证:go-cq 正常运行(如果报红字,说明还有一个 go-cq 在跑,把它关掉),</p>\n<p>数据库启动,在虚拟环境中。</p>\n</li>\n</ul>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>poetry <span class=\"token function\">install</span> <span class=\"token comment\"># 安装依赖</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>poetry shell <span class=\"token comment\"># 进入虚拟环境</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>python3 bot.py</pre></td></tr></table></figure><h2 id=\"va_list\"><a class=\"anchor\" href=\"#va_list\">#</a> va_list</h2>\n<p>是一个 C++ 中用于处理可变数量参数的机制。它是一个指向可变参数列表的类型,用于在函数中访问和处理不定数量的参数。</p>\n<p>具体来说,va_list 是一个指向参数列表的指针,它是通过标准头文件中的宏和函数来操作的。使用 va_list,我们可以在函数中按顺序访问和提取可变数量的参数。</p>\n<p>下面是一个简单的示例,演示了如何使用 va_list 来处理可变数量的参数:</p>\n<pre><code class=\"language-C++\">#include <cstdarg>\n#include <iostream>\n\nvoid printValues(int numArgs, ...)\n{\n va_list args;\n va_start(args, numArgs);\n\n for (int i = 0; i < numArgs; ++i)\n {\n int value = va_arg(args, int);\n std::cout << value << " ";\n }\n\n va_end(args);\n}\n\nint main()\n{\n printValues(3, 1, 2, 3); // 输出: 1 2 3\n\n return 0;\n}\n</code></pre>\n<p>在上面的示例中,printValues 函数接收一个整数参数 numArgs,它表示后续可变数量参数的个数。通过使用 va_list,我们可以在函数中使用 va_start 宏来初始化可变参数列表,然后使用 va_arg 宏按顺序提取参数的值,直到达到指定的参数个数。最后,我们使用 va_end 宏来清理可变参数列表。</p>\n<p>需要注意的是,使用 va_list 需要小心处理参数类型和个数的一致性,以及遵循正确的使用方式,以避免出现未定义行为或错误。</p>\n<h2 id=\"const-noexcept-和-final\"><a class=\"anchor\" href=\"#const-noexcept-和-final\">#</a> const noexcept 和 final</h2>\n<p>const, noexcept, 和 final 是 C++ 中的关键字,用于修饰函数或类的特性。</p>\n<ol>\n<li>const:它用于修饰函数或类的成员函数,表示该函数不会修改对象的状态。在一个 const 成员函数中,不能修改类的非 mutable 成员变量,也不能调用非 const 成员函数,以确保函数的调用不会对对象的状态造成改变。</li>\n<li>noexcept:它用于修饰函数,表示该函数不会抛出异常。在 C++ 中,函数可以声明为 noexcept 以指示其不会引发异常。这对于编写异常安全的代码以及进行性能优化很有用。</li>\n<li>final:它用于修饰类或虚函数,表示该类不可被继承或该虚函数不可被派生类重写。当一个类被声明为 final 时,它不能作为基类,不能被其他类继承。当一个虚函数被声明为 final 时,派生类将不能重写该虚函数。</li>\n</ol>\n<p>这些关键字可以帮助程序员在代码中明确表示其意图,并在一定程度上增加代码的可读性和可靠性。</p>\n",
"tags": [
"writing"
]
},
{
"id": "http://yuanmxc.site/%E6%9C%AA%E5%88%86%E7%B1%BB/Hexo+Github%20Pages%20%E6%90%AD%E5%BB%BA%E4%B8%AA%E4%BA%BA%E5%8D%9A%E5%AE%A2/",
"url": "http://yuanmxc.site/%E6%9C%AA%E5%88%86%E7%B1%BB/Hexo+Github%20Pages%20%E6%90%AD%E5%BB%BA%E4%B8%AA%E4%BA%BA%E5%8D%9A%E5%AE%A2/",
"title": "Hexo+Github Pages 搭建个人博客",
"date_published": "2024-03-26T11:49:10.133Z",
"content_html": "<ul>\n<li>\n<p>安装 Hexo</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 安装 node.js 和 npm</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">sudo</span> pacman <span class=\"token parameter variable\">-S</span> nodejs <span class=\"token function\">npm</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token comment\"># 安装 hexo</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token function\">sudo</span> <span class=\"token function\">npm</span> <span class=\"token function\">install</span> <span class=\"token parameter variable\">-g</span> hexo-cli</pre></td></tr></table></figure></li>\n<li>\n<p>前期准备</p>\n<ol>\n<li>\n<p>Hexo 配置</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token comment\"># 新建一个存放博客相关文件的文件夹(以 your_blog 为例)</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>hexo init your_blog <span class=\"token comment\"># 初始化</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token builtin class-name\">cd</span> your_blog</pre></td></tr><tr><td data-num=\"4\"></td><td><pre>hexo new “HelloWorld” <span class=\"token comment\"># 生成 HelloWorld.md 文件(你的文章),存放在 /your_blogyour_blog/sources/_post/ 目录下</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre>hexo generate <span class=\"token comment\"># 将 /your_blog/sources/_post/ 目录下的 Markdown 文件解析成可以使用浏览器查看的 HTML 文件,存在 blog/public 目录下</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre>hexo server <span class=\"token comment\"># 在本地运行服务,可以在提示的网址进行预览博客</span></pre></td></tr></table></figure></li>\n<li>\n<p>Hexo 配合 Github Page</p>\n<p>在 /your_blog/ 下安装使用 Git 进行部署所需的依赖项</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token function\">npm</span> <span class=\"token function\">install</span> hexo-deployer-git <span class=\"token parameter variable\">--save</span></pre></td></tr></table></figure><p>在 /your_blog/_config.yml 中修改 deploy 属性 (注意:之后有空格)</p>\n<figure class=\"highlight yml\"><figcaption data-lang=\"YAML\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token key atrule\">deploy</span><span class=\"token punctuation\">:</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre> <span class=\"token key atrule\">type</span><span class=\"token punctuation\">:</span> git</pre></td></tr><tr><td data-num=\"3\"></td><td><pre> <span class=\"token key atrule\">repository</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">[</span>你的仓库地址<span class=\"token punctuation\">,</span>如果有ssh推荐使用ssh<span class=\"token punctuation\">]</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre> <span class=\"token key atrule\">branch</span><span class=\"token punctuation\">:</span> master</pre></td></tr></table></figure></li>\n<li>\n<p>部署:</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>hexo deploy <span class=\"token comment\"># 将本地文件推送到 Github 仓库 同时更新你的 Github page 个人博客展示界面</span></pre></td></tr></table></figure></li>\n<li>\n<p>以后更新博客的流程:</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>hexo new “HelloWorld” <span class=\"token comment\"># 生成 HelloWorld.md 文件(你的文章),或者手动在 your_blog/sources/_post/ 目录下创建 md,并编辑</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>hexo g <span class=\"token comment\"># 将 Markdown 文件解析成 HTML 文件</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>hexo server <span class=\"token comment\"># 本地预览(可无)</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre>hexo d <span class=\"token comment\"># 推送更新</span></pre></td></tr></table></figure></li>\n<li>\n<p>注意</p>\n<ul>\n<li>\n<p>短时间内对本地配置文件进行修改后,推荐使用 <code>Hexo cl</code> 命令来清除缓存,之后在执行 <code>Hexo s</code> 来查看修改后的效果。</p>\n</li>\n<li>\n<p>你的 Github 本地仓库应该位于 your_blog 目录下,不要更改,博客网站就是仓库中的文件生成的。执行 hexo d 命令时会帮你更改仓库中的文件,不需要管同时,执行 hexo 命令需要在 your_blog 目录下进行操作。</p>\n</li>\n</ul>\n</li>\n</ol>\n</li>\n<li>\n<p>在 Github 绑定购买的自定义域名(如有)</p>\n</li>\n<li>\n<p>更换主题 推荐主题: <span class=\"exturl\" data-url=\"aHR0cHM6Ly9zaG9rYS5sb3N0eXUubWUvY29tcHV0ZXItc2NpZW5jZS9ub3RlL3RoZW1lLXNob2thLWRvYy8=\">Hexo 主题 Shoka & multi-markdown-it 渲染器使用说明</span>,或者自行下载喜欢的主题。</p>\n<ol>\n<li>\n<p>一般主题都会有详细的配置和插件配置教程,以 shoka 为例,大体过程如下:</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token builtin class-name\">cd</span> your_blog <span class=\"token comment\"># 进你的博客目录</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token function\">git</span> clone https://github.com/amehime/hexo-theme-shoka.git ./themes/shoka <span class=\"token comment\"># 克隆 github 仓库到 /blog/themes/ 下</span></pre></td></tr></table></figure><p>主题目录内一般有 example 文件夹,提供配置文件的 demo 供参考。</p>\n</li>\n<li>\n<p>安装依赖插件</p>\n<p>按照具体所给教程进行,可能不需要。</p>\n</li>\n<li>\n<p>修改配置文件 your_blog/_config.yml ,把 theme 改为 shoka。</p>\n</li>\n<li>\n<p>重新生成静态文件并推送。</p>\n<figure class=\"highlight bash\"><figcaption data-lang=\"bash\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre>hexo generate <span class=\"token comment\"># 将 /your_blog/sources/_post/ 目录下的 Markdown 文件解析成可以使用浏览器查看的 HTML 文件,存在 blog/public 目录下</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre>hexo server <span class=\"token comment\"># 本地预览(可无)</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre>hexo deploy <span class=\"token comment\"># 将本地已有的文件推送到 Github 仓库 同时更新你的 Github page 个人博客展示界面</span></pre></td></tr></table></figure></li>\n</ol>\n</li>\n</ul>\n",
"tags": []
},
{
"id": "http://yuanmxc.site/%E6%9C%AA%E5%88%86%E7%B1%BB/SQL/",
"url": "http://yuanmxc.site/%E6%9C%AA%E5%88%86%E7%B1%BB/SQL/",
"title": "SQL",
"date_published": "2024-03-26T11:49:10.133Z",
"content_html": "<ol>\n<li>\n<p>查询表的数据:</p>\n<ul>\n<li>基本查询:</li>\n</ul>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">SELECT</span> <span class=\"token operator\">*</span> <span class=\"token keyword\">FROM</span> <span class=\"token operator\"><</span>表名<span class=\"token operator\">></span></pre></td></tr></table></figure><p>\t\tELECT 是关键字,表示将要执行一个查询,* 表示 “所有列”,FROM 表示将要从哪个表查询</p>\n<ul>\n<li>条件查询:</li>\n</ul>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">SELECT</span> <span class=\"token operator\">*</span> <span class=\"token keyword\">FROM</span> <span class=\"token operator\"><</span>表名<span class=\"token operator\">></span> <span class=\"token keyword\">WHERE</span> <span class=\"token operator\"><</span>条件表达式<span class=\"token operator\">></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token keyword\">SELECT</span> <span class=\"token operator\">*</span> <span class=\"token keyword\">FROM</span> students <span class=\"token keyword\">WHERE</span> score <span class=\"token operator\">>=</span> <span class=\"token number\">80</span> <span class=\"token operator\">AND</span> gender <span class=\"token operator\">=</span> <span class=\"token string\">'M'</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><p>\t\t多个条件表达式可以用 <code>AND</code> 或者 <code>OR</code> 连接 <code><条件1> AND/OR <条件2></code> , <code>NOT <条件></code> ,表示 “不符合该条件” 的记录<br />\n\t\t使用 <code><></code> 判断不相等,使用 <code>=</code> 判断相等,使用 <code>LIKE</code> 判断相似, <code>name LIKE 'ab%'</code> , <code>%</code> 表示任意字符,例如 <code>'ab%'</code> 将匹配 <code>'ab'</code> , <code>'abc'</code> , <code>'abcd'</code> ,要组合三个或者更多的条件,就需要用小括号 <code>()</code> 表示如何进行条件运算,否则,优先级: <code>NOT>AND>OR</code></p>\n<ul>\n<li>\n<p>投影查询:</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">SELECT</span> 列<span class=\"token number\">1</span><span class=\"token punctuation\">,</span> 列<span class=\"token number\">2</span><span class=\"token punctuation\">,</span> 列<span class=\"token number\">3</span> <span class=\"token keyword\">FROM</span> <span class=\"token operator\"><</span>表名<span class=\"token operator\">></span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token comment\"># 从 students 表中返回 id、score 和 name 这三列:</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">SELECT</span> id<span class=\"token punctuation\">,</span> score<span class=\"token punctuation\">,</span> name <span class=\"token keyword\">FROM</span> students<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token comment\"># 可以给每一列起一个别名</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token keyword\">SELECT</span> 列<span class=\"token number\">1</span> 别名<span class=\"token number\">1</span><span class=\"token punctuation\">,</span> 列<span class=\"token number\">2</span> 别名<span class=\"token number\">2</span><span class=\"token punctuation\">,</span> 列<span class=\"token number\">3</span> 别名<span class=\"token number\">3</span> <span class=\"token keyword\">FROM</span> <span class=\"token operator\"><</span>表名<span class=\"token operator\">></span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token comment\"># 以下 SELECT 语句将列名 score 重命名为 points,而 id 和 name 列名保持不变:</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token keyword\">SELECT</span> id<span class=\"token punctuation\">,</span> score points<span class=\"token punctuation\">,</span> name <span class=\"token keyword\">FROM</span> students<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre></pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token comment\"># 投影查询同样可以接 WHERE 条件,实现复杂的查询:</span></pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token keyword\">SELECT</span> id<span class=\"token punctuation\">,</span> score points<span class=\"token punctuation\">,</span> name <span class=\"token keyword\">FROM</span> students <span class=\"token keyword\">WHERE</span> gender <span class=\"token operator\">=</span> <span class=\"token string\">'M'</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure></li>\n<li>\n<p>排序:</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">SELECT</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token keyword\">ORDER</span> <span class=\"token keyword\">BY</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token comment\"># 按 score 从低到高:</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">SELECT</span> id<span class=\"token punctuation\">,</span> name<span class=\"token punctuation\">,</span> gender<span class=\"token punctuation\">,</span> score <span class=\"token keyword\">FROM</span> students <span class=\"token keyword\">ORDER</span> <span class=\"token keyword\">BY</span> score<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"4\"></td><td><pre><span class=\"token comment\"># 默认排序是 ASC “升序”,ASC 可以省略,末尾加上 DESC 表示 “倒序”:</span></pre></td></tr><tr><td data-num=\"5\"></td><td><pre><span class=\"token keyword\">SELECT</span> id<span class=\"token punctuation\">,</span> name<span class=\"token punctuation\">,</span> gender<span class=\"token punctuation\">,</span> score <span class=\"token keyword\">FROM</span> students <span class=\"token keyword\">ORDER</span> <span class=\"token keyword\">BY</span> score <span class=\"token keyword\">DESC</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"6\"></td><td><pre><span class=\"token comment\"># 使用 ORDER BY score DESC, gender 表示先按 score 列倒序,如果有相同分数的,再按 gender 列排序:</span></pre></td></tr><tr><td data-num=\"7\"></td><td><pre><span class=\"token keyword\">SELECT</span> id<span class=\"token punctuation\">,</span> name<span class=\"token punctuation\">,</span> gender<span class=\"token punctuation\">,</span> score <span class=\"token keyword\">FROM</span> students <span class=\"token keyword\">ORDER</span> <span class=\"token keyword\">BY</span> score <span class=\"token keyword\">DESC</span><span class=\"token punctuation\">,</span> gender<span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"8\"></td><td><pre><span class=\"token comment\"># 如果有 WHERE 子句,那么 ORDER BY 子句要放到 WHERE 子句后面:</span></pre></td></tr><tr><td data-num=\"9\"></td><td><pre><span class=\"token keyword\">SELECT</span> id<span class=\"token punctuation\">,</span> name<span class=\"token punctuation\">,</span> gender<span class=\"token punctuation\">,</span> score</pre></td></tr><tr><td data-num=\"10\"></td><td><pre><span class=\"token keyword\">FROM</span> students</pre></td></tr><tr><td data-num=\"11\"></td><td><pre><span class=\"token keyword\">WHERE</span> class_id <span class=\"token operator\">=</span> <span class=\"token number\">1</span></pre></td></tr><tr><td data-num=\"12\"></td><td><pre><span class=\"token keyword\">ORDER</span> <span class=\"token keyword\">BY</span> score <span class=\"token keyword\">DESC</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure><ul>\n<li>分页查询,聚合查询,多表查询,连接查询略</li>\n</ul>\n</li>\n</ul>\n<ol>\n<li>\n<p>插入数据:</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">INSERT</span> <span class=\"token keyword\">INTO</span> <span class=\"token operator\"><</span>表名<span class=\"token operator\">></span> <span class=\"token punctuation\">(</span>字段<span class=\"token number\">1</span><span class=\"token punctuation\">,</span> 字段<span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">VALUES</span> <span class=\"token punctuation\">(</span>值<span class=\"token number\">1</span><span class=\"token punctuation\">,</span> 值<span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token comment\"># 向 students 表插入一条新记录,先列举出需要插入的字段名称,然后在 VALUES 子句中依次写出对应字段的值:</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">INSERT</span> <span class=\"token keyword\">INTO</span> students <span class=\"token punctuation\">(</span>class_id<span class=\"token punctuation\">,</span> name<span class=\"token punctuation\">,</span> gender<span class=\"token punctuation\">,</span> score<span class=\"token punctuation\">)</span> <span class=\"token keyword\">VALUES</span> <span class=\"token punctuation\">(</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'大牛'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'M'</span><span class=\"token punctuation\">,</span> <span class=\"token number\">80</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure></li>\n<li>\n<p>修改数据:</p>\n<figure class=\"highlight sql\"><figcaption data-lang=\"SQL\"></figcaption><table><tr><td data-num=\"1\"></td><td><pre><span class=\"token keyword\">UPDATE</span> <span class=\"token operator\"><</span>表名<span class=\"token operator\">></span> <span class=\"token keyword\">SET</span> 字段<span class=\"token number\">1</span><span class=\"token operator\">=</span>值<span class=\"token number\">1</span><span class=\"token punctuation\">,</span> 字段<span class=\"token number\">2</span><span class=\"token operator\">=</span>值<span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span> <span class=\"token keyword\">WHERE</span> <span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">;</span></pre></td></tr><tr><td data-num=\"2\"></td><td><pre><span class=\"token comment\"># 更新 students 表 id=1 的记录的 name 和 score 这两个字段,先写出 UPDATE students SET name=' 大牛 ', score=66,然后在 WHERE 子句中写出需要更新的行的筛选条件 id=1:</span></pre></td></tr><tr><td data-num=\"3\"></td><td><pre><span class=\"token keyword\">UPDATE</span> students <span class=\"token keyword\">SET</span> name<span class=\"token operator\">=</span><span class=\"token string\">'大牛'</span><span class=\"token punctuation\">,</span> score<span class=\"token operator\">=</span><span class=\"token number\">66</span> <span class=\"token keyword\">WHERE</span> id<span class=\"token operator\">=</span><span class=\"token number\">1</span><span class=\"token punctuation\">;</span></pre></td></tr></table></figure></li>\n</ol>\n<p>参考:<span class=\"exturl\" data-url=\"aHR0cHM6Ly93d3cubGlhb3h1ZWZlbmcuY29tLw==\">廖雪峰的官方网站</span></p>\n</li>\n</ol>\n",
"tags": []
},
{
"id": "http://yuanmxc.site/%E6%9C%AA%E5%88%86%E7%B1%BB/TCP%E7%9A%84%E5%8F%AF%E9%9D%A0%E6%95%B0%E6%8D%AE%E4%BC%A0%E8%BE%93/",
"url": "http://yuanmxc.site/%E6%9C%AA%E5%88%86%E7%B1%BB/TCP%E7%9A%84%E5%8F%AF%E9%9D%A0%E6%95%B0%E6%8D%AE%E4%BC%A0%E8%BE%93/",
"title": "TCP的可靠数据传输",
"date_published": "2024-03-26T11:49:10.133Z",
"content_html": "<h2 id=\"简述\"><a class=\"anchor\" href=\"#简述\">#</a> 简述</h2>\n<p>\t 众所周知,TCP 是传输层中一种面向连接的、可靠的、基于字节流的通信协议,是网络通信中十分重要的桥梁。本文集中于对可靠的数据传输、流量控制以及拥塞控制三个内容的简单描述,需要读者对 TCP 有一定了解。</p>\n<h2 id=\"可靠的数据传输\"><a class=\"anchor\" href=\"#可靠的数据传输\">#</a> 可靠的数据传输</h2>\n<h3 id=\"超时重传-快速重传-sack重传\"><a class=\"anchor\" href=\"#超时重传-快速重传-sack重传\">#</a> 超时重传、快速重传、sack 重传</h3>\n<p> 我们都知道,在 TCP 中,当发送端的数据到达接收端时,接收端会返回一个确认应答消息,表示已收到消息。但过程往往不会这么顺利,数据可能在错综复杂的网络中丢失。此时,就需要利用重传机制解决。</p>\n<h4 id=\"超时重传\"><a class=\"anchor\" href=\"#超时重传\">#</a> 超时重传:</h4>\n<p>\t\t当发送端发出一个数据包后,会启动一个定时器(<strong>超时重传时间 <code>RTO</code> </strong>),,等待接收端确认收到这个数据包。如果没有在定时范围内收到接收端的确认报文,发送端将重发数据包。这里有两种情况:发送的数据包丢失或者确认应答丢失。</p>\n<p>\t\t显然, <code>RTO</code> 应该略大于正常情况下发送端数据发送时刻与发送端收到确认报文时刻的差值(包的往返时间 <code>RTT</code> ),但由于网络环境的不确定性, <code>RTT</code> 在不断变化,因此 <code>RTO</code> 的值实际上需要很复杂的计算才能得以确定,这里不多做展开。</p>\n<p>\t\t<strong>超时间隔加倍</strong>:每当遇到一次超时重传的时候,都会将下一次超时时间间隔设为先前值的两倍。两次超时,就说明网络环境差,不宜频繁反复发送。</p>\n<h4 id=\"快速重传\"><a class=\"anchor\" href=\"#快速重传\">#</a> 快速重传:</h4>\n<p>超时重传也有一些问题,报文段丢失后的等待重传时间相对较长,效率较低。因此又衍生出了<strong>快速重传</strong>。</p>\n<p>\t\t先介绍一下<strong>累计确认机制</strong>:当接收端收到比期望序号大的报文段时,会重复发送最近一次确认的报文段的确认信号,称之为冗余 ACK(duplicate ACK)。如图所示,报文段 1 成功接收并被确认 ACK 2,接收端的期待序号为 2,当报文段 2 丢失,报文段 3 失序到来,与接收端的期望不匹配,接收端重复发送冗余 ACK 2。</p>\n<p><img data-src=\"/home/origin/Code/repository/Note/All_picture/TCP%E7%9A%84%E5%8F%AF%E9%9D%A0%E6%95%B0%E6%8D%AE%E4%BC%A0%E8%BE%93/11151952-9b8206ec45e63ba1.jpg\" alt=\"\" /></p>\n<p>\t\t这样,如果在 <code>RTO</code> 范围内,发送端会收到连续的<strong>三个重复冗余 ACK</strong>(实际上收到 4 个相同 ACK,第一个是正常的,后三个才是冗余的),发送端便知晓哪个报文段在传输过程中丢失了,于是重发该报文段,不需要等待 <code>RTO</code> 再重传,提高了效率。这便是<strong>快速重传机制</strong>。</p>\n<p>\t\t这里采用三次冗余 ACK 的原因也很耐人寻味,我们知道 TCP 包是封装在 IP 包内的,IP 包在传输时会乱序,因此 TCP 包到达接收端也是乱序的,这也会造成接收端发送冗余 ACK 给发送端。因此我们不能仅凭某一两次的冗余 ACK 就进行重传。选取三次是经过统计所得出的一个估计值,均衡考虑的最优结果。</p>\n<h4 id=\"sack重传\"><a class=\"anchor\" href=\"#sack重传\">#</a> SACK 重传</h4>\n<p>\t\t快速重传解决了超时时间较长的问题,我们还有另外一个问题:<strong>重传的时候,是重传一个,还是重传所有</strong>。传一个会导致多次触发快速重传,每个丢失的报文都需要三次冗余 ACK,传所有报文时,如果后面的部分报文已经收到,会造成重复发送,导致资源浪费。因此有了 ** <code>SACK</code> 方法 **。</p>\n<p>\t\t在 TCP 头部选项字段里加一个 <code>SACK</code> 的东西,发送端可以根据它知道哪些数据收到了,哪些数据没收到,从而只重传丢失的数据。</p>\n<p>\t\t基于 <code>SACK</code> 方法,还有一种 ** <code>Duplicate SACK</code> ** 机制又称 <strong> <code>D-SACK</code> </strong>,它使用 <code>SACK </code> 方法来告诉「发送方」有哪些数据被重复接收了。</p>\n<p>\t\t当连续发送报文时,如果一个报文因网络而延迟到达(已经触发快速重传继续传输后续报文时接收端收到之前延时的报文),回应的 ack 中的 <code>sack</code> 就会告诉发送端接收端重复接收了之前已经接收到的报文(即<strong>知道该报文延迟</strong>)。</p>\n<p>\t\t通过这种方式,发送方还可以知道是<strong>自己发送的报文丢失</strong>还是<strong>接收方回应的 ACK 确认报文丢失</strong>。</p>\n<h2 id=\"流量控制\"><a class=\"anchor\" href=\"#流量控制\">#</a> 流量控制</h2>\n<p>\t\t由于接收方和发送方的条件不同会会出现发送方数据发送过快,但接收方来不及接受,导致数据丢失的问题,基于此, <code>TCP</code> 出现了<strong>流量控制</strong>机制。</p>\n<p>\t\tTCP 依靠<strong>滑动窗口</strong>进行流量控制,在 TCP 中有一个字段叫 <code>window</code> ,用来<strong>让接收端告诉发送端自己还有多少缓冲区可以接收数据</strong>。这样发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来。类似于一个先进先出的队列。同时发送方也会有一个滑动窗口,表示自己发送的数据包是否已经收到了接收方的确认报文。双方通过报文的 <code>window</code> 字段告诉对方自己目前的窗口大小。</p>\n<p>发送方的滑动窗口示意:</p>\n<p><img data-src=\"/home/origin/Code/repository/Note/All_picture/TCP%E7%9A%84%E5%8F%AF%E9%9D%A0%E6%95%B0%E6%8D%AE%E4%BC%A0%E8%BE%93/18-1676462686327-6.jpg\" alt=\"\" /></p>\n<p>接收方的滑动窗口示意:</p>\n<p><img data-src=\"/home/origin/Code/repository/Note/All_picture/TCP%E7%9A%84%E5%8F%AF%E9%9D%A0%E6%95%B0%E6%8D%AE%E4%BC%A0%E8%BE%93/image-20230215201601943.png\" alt=\"\" /></p>\n<h2 id=\"拥塞控制\"><a class=\"anchor\" href=\"#拥塞控制\">#</a> 拥塞控制</h2>\n<p>\t\t在网络出现拥堵时,如果继续发送大量数据包,可能会导致数据包时延、丢失等,这时 TCP 就会重传数据,但是一重传就会导致网络的负担更重,于是会导致更大的延迟以及更多的丢包,导致恶性循环,因此有了<strong>拥塞控制</strong>来避免发送端的数据填满网络造成拥堵。主要通过三个算法来实现,分别是:<strong>慢开始 (slow-start)</strong>、<strong>拥塞避免 (congestion avoidance)</strong>、和<strong>快恢复 (fast recovery)</strong>。。</p>\n<p>\t\t首先我们需要一个状态变量来表示网络的拥堵状况 ——<strong> 拥塞窗口</strong>( <code>cwnd</code> ),只要网络中没有出现阻塞,窗口就会增大,网络中出现阻塞,窗口就会减小。一个传输轮次传输 <code>cwnd</code> 个报文。</p>\n<p><strong>慢启动</strong>:</p>\n<p>\t\t当发送端每收到 1 个确认 ACK(一轮可能收到多个),拥塞窗口的大小就会加 1。这使得拥塞窗口呈指数级增长( <code>cwnd</code> 为 2 时,一轮收到 2 个 ACK, <code>cwnd</code> + 2 = 4; <code>cwnd</code> 为 4 时,一轮收到 4 个 ACK , <code>cwnd</code> + 4 = 8)。</p>\n<p>\t\t当 cwnd 的值超过慢启动门限(ssthresh 一般情况下为 65535 字节)时,慢启动算法停止,使用<strong>拥塞避免算法</strong>。</p>\n<p><strong>拥塞避免</strong>:</p>\n<p>\t\t每收到一个 ACK 报文,拥塞窗口 <code>cwnd</code> 增加 <code>1/cwnd</code> 。这使得拥塞窗口呈线性增长( <code>cwnd</code> 为 10 时,一轮收到 10 个 ACK, <code>cwnd</code> + 10/10 = 11; <code>cwnd</code> 为 11 时,一轮收到 11 个 ACK , <code>cwnd</code> + 11/11 = 12)。</p>\n<p>\t\t当<strong>超时重传拥塞</strong>发生以后, <code>ssthresh</code> 设置为 <code>cwnd/2</code> 。 <code>cwnd</code> 重置为 1。</p>\n<p>\t\t当<strong>快速重传拥塞</strong>发生以后, <code>cwnd</code> = <code>cwnd/2</code> , <code>ssthresh = cwnd</code> 进入快速恢复算法,</p>\n<p><strong>快恢复算法</strong>:</p>\n<p>\t\t进入快恢复算法时,已经发生了<strong>快速重传拥塞</strong>, <code>cwnd</code> 和 <code>ssthresh</code> 已被更新,之后进行如下操作:</p>\n<ol>\n<li>\n<p>拥塞窗口 <code>cwnd = ssthresh + 3</code> (表示有三个数据包被收到)。</p>\n</li>\n<li>\n<p>重传丢失的数据包。</p>\n</li>\n<li>\n<p>如果收到的 ACK 是重复的,cwnd 增加 1。</p>\n</li>\n<li>\n<p>如果收到新数据的 ACK,把拥塞窗口设置为第 1 步中 ssthresh 的值,因为 ACK 已经确认了新数据,快速恢复过程可以结束,可以再次进入拥塞避免阶段。</p>\n<p>下图表示了所有的拥塞算法。</p>\n</li>\n</ol>\n<p><img data-src=\"/home/Yuanmxc/Code/repository/Note/All_picture/TCP%E7%9A%84%E5%8F%AF%E9%9D%A0%E6%95%B0%E6%8D%AE%E4%BC%A0%E8%BE%93/image-20230215210457706.png\" alt=\"image-20230215210457706\" /></p>\n",
"tags": []
},
{
"id": "http://yuanmxc.site/%E7%AC%94%E8%AE%B0/Csapp%E7%AC%94%E8%AE%B0/",
"url": "http://yuanmxc.site/%E7%AC%94%E8%AE%B0/Csapp%E7%AC%94%E8%AE%B0/",
"title": "Csapp笔记",
"date_published": "2024-03-26T11:49:10.133Z",
"content_html": "<h2 id=\"第一章计算机系统漫游\"><a class=\"anchor\" href=\"#第一章计算机系统漫游\">#</a> 第一章:计算机系统漫游</h2>\n<ol>\n<li>\n<p>硬件:CPU,寄存器文件,高速缓存存储器,系统总线,主存,磁盘。</p>\n</li>\n<li>\n<p>操作系统管理硬件。进程(处理器,主存,i/o 设备),虚拟内存(主存,i/o 设备),文件(i/o 设备)。</p>\n</li>\n<li>\n<p>并发运行:一个进程的指令和另一个进程的指令交错执行。这种交错执行的机制叫上下文切换,进程间切换由内核管理。</p>\n</li>\n<li>\n<p>上下文:操作系统保持跟踪进程运行所需的所有状态信息。</p>\n</li>\n<li>\n<p>内核:操作系统代码常驻主存的一部分,不是独立的进程。是系统全部进程所用代码和数据结构的集合。</p>\n</li>\n<li>\n<p>栈位于用户虚拟地址空间顶部,编译器用它来实现函数调用,和堆一样,用户栈在程序执行期间可以动态地扩展和收缩 。 调用函数时,栈会增长;从一个函数返回时,栈会收缩 。</p>\n</li>\n<li>\n<p>内核虚拟内存:程序无法读写,或调用内核代码定义的函数,需要调用内核来执行操作。</p>\n</li>\n<li>\n<p>PC:程序计数器(寄存器),ALU(算数 / 逻辑单元)</p>\n</li>\n</ol>\n",
"tags": [
"笔记"
]
}
]
}