-
Notifications
You must be signed in to change notification settings - Fork 0
/
ospp之旅(四).html
592 lines (446 loc) · 46.4 KB
/
ospp之旅(四).html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 3.9.0">
<link rel="apple-touch-icon" sizes="180x180" href="/images/icons/logo64.png">
<link rel="icon" type="image/png" sizes="32x32" href="/images/icons/logo32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/images/icons/logo32.png">
<link rel="mask-icon" href="/images/icons/logo200.png" color="#222">
<link rel="stylesheet" href="/css/main.css">
<link rel="stylesheet" href="/lib/font-awesome/css/font-awesome.min.css">
<script id="hexo-configurations">
var NexT = window.NexT || {};
var CONFIG = {
root: '/',
scheme: 'Gemini',
version: '7.4.2',
exturl: false,
sidebar: {"position":"left","display":"post","offset":12,"onmobile":false},
copycode: {"enable":true,"show_result":true,"style":null},
back2top: {"enable":true,"sidebar":false,"scrollpercent":false},
bookmark: {"enable":false,"color":"#222","save":"auto"},
fancybox: false,
mediumzoom: false,
lazyload: false,
pangu: false,
algolia: {
appID: '',
apiKey: '',
indexName: '',
hits: {"per_page":10},
labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
},
localsearch: {"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},
path: '',
motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
translation: {
copy_button: '复制',
copy_success: '复制成功',
copy_failure: '复制失败'
},
sidebarPadding: 40
};
</script>
<meta name="description" content="前言在做OSPP项目的过程中,导师问我要不顺便参加OpenEuler的开源实习,正好libvirt有几个开源实习的任务,让我顺便一起做了。本来我就已经参加了这个活动,待在MindSpore社区,现在正好在OpenEuler社区也领一些任务做,涨涨积分。看了一下virt-sig组的任务之后,我选择先做libvirt 6.2.0支持vhostuser类型磁盘这个任务。">
<meta name="keywords" content="OSPP,开源,操作系统,虚拟化">
<meta property="og:type" content="article">
<meta property="og:title" content="OSPP之旅(四)">
<meta property="og:url" content="http://www.fisheryung.top/ospp之旅(四).html">
<meta property="og:site_name" content="Fisher's Blog">
<meta property="og:description" content="前言在做OSPP项目的过程中,导师问我要不顺便参加OpenEuler的开源实习,正好libvirt有几个开源实习的任务,让我顺便一起做了。本来我就已经参加了这个活动,待在MindSpore社区,现在正好在OpenEuler社区也领一些任务做,涨涨积分。看了一下virt-sig组的任务之后,我选择先做libvirt 6.2.0支持vhostuser类型磁盘这个任务。">
<meta property="og:locale" content="zh-CN">
<meta property="og:image" content="http://www.fisheryung.top/images/ospp/compile_errors.png">
<meta property="og:image" content="http://www.fisheryung.top/images/ospp/test_errors_by_enums.jpg">
<meta property="og:image" content="http://www.fisheryung.top/images/ospp/test_success.png">
<meta property="og:image" content="http://www.fisheryung.top/images/ospp/vhostuser_vm_start.jpg">
<meta property="og:updated_time" content="2022-08-17T08:47:49.106Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="OSPP之旅(四)">
<meta name="twitter:description" content="前言在做OSPP项目的过程中,导师问我要不顺便参加OpenEuler的开源实习,正好libvirt有几个开源实习的任务,让我顺便一起做了。本来我就已经参加了这个活动,待在MindSpore社区,现在正好在OpenEuler社区也领一些任务做,涨涨积分。看了一下virt-sig组的任务之后,我选择先做libvirt 6.2.0支持vhostuser类型磁盘这个任务。">
<meta name="twitter:image" content="http://www.fisheryung.top/images/ospp/compile_errors.png">
<link rel="canonical" href="http://www.fisheryung.top/ospp之旅(四).html">
<script id="page-configurations">
// https://hexo.io/docs/variables.html
CONFIG.page = {
sidebar: "",
isHome: false,
isPost: true,
isPage: false,
isArchive: false
};
</script>
<title>OSPP之旅(四) | Fisher's Blog</title>
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-111555456-1"></script>
<script>
var host = window.location.hostname;
if (host !== "localhost" || !true) {
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-111555456-1');
}
</script>
<noscript>
<style>
.use-motion .brand,
.use-motion .menu-item,
.sidebar-inner,
.use-motion .post-block,
.use-motion .pagination,
.use-motion .comments,
.use-motion .post-header,
.use-motion .post-body,
.use-motion .collection-header { opacity: initial; }
.use-motion .site-title,
.use-motion .site-subtitle {
opacity: initial;
top: initial;
}
.use-motion .logo-line-before i { left: initial; }
.use-motion .logo-line-after i { right: initial; }
</style>
</noscript>
</head>
<body itemscope itemtype="http://schema.org/WebPage">
<div class="container use-motion">
<div class="headband"></div>
<header class="header" itemscope itemtype="http://schema.org/WPHeader">
<div class="header-inner"><div class="site-brand-container">
<div class="site-meta">
<div>
<a href="/" class="brand" rel="start">
<span class="logo-line-before"><i></i></span>
<span class="site-title">Fisher's Blog</span>
<span class="logo-line-after"><i></i></span>
</a>
</div>
<p class="site-subtitle">自由尋覓快樂別人從沒法感受</p>
</div>
<div class="site-nav-toggle">
<div class="toggle" aria-label="切换导航栏">
<span class="toggle-line toggle-line-first"></span>
<span class="toggle-line toggle-line-middle"></span>
<span class="toggle-line toggle-line-last"></span>
</div>
</div>
</div>
<nav class="site-nav">
<ul id="menu" class="menu">
<li class="menu-item menu-item-home">
<a href="/" rel="section"><i class="fa fa-fw fa-home"></i>首页</a>
</li>
<li class="menu-item menu-item-about">
<a href="/about/" rel="section"><i class="fa fa-fw fa-user"></i>关于</a>
</li>
<li class="menu-item menu-item-tags">
<a href="/tags/" rel="section"><i class="fa fa-fw fa-tags"></i>标签</a>
</li>
<li class="menu-item menu-item-archives">
<a href="/archives/" rel="section"><i class="fa fa-fw fa-archive"></i>归档</a>
</li>
</ul>
</nav>
</div>
</header>
<div class="back-to-top">
<i class="fa fa-arrow-up"></i>
<span>0%</span>
</div>
<div class="reading-progress-bar"></div>
<a href="https://github.com/FisherWY" class="github-corner" title="Follow me on GitHub" aria-label="Follow me on GitHub" rel="noopener" target="_blank"><svg width="80" height="80" viewBox="0 0 250 250" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a>
<main class="main">
<div class="main-inner">
<div class="content-wrap">
<div class="content">
<div class="posts-expand">
<article itemscope itemtype="http://schema.org/Article" class="post-block " lang="zh-CN">
<link itemprop="mainEntityOfPage" href="http://www.fisheryung.top/ospp之旅(四).html">
<span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
<meta itemprop="image" content="/images/icons/avatar.jpg">
<meta itemprop="name" content="Fisher">
<meta itemprop="description" content="记录学习生活中的点滴">
</span>
<span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
<meta itemprop="name" content="Fisher's Blog">
</span>
<header class="post-header">
<h1 class="post-title" itemprop="name headline">
OSPP之旅(四)
</h1>
<div class="post-meta">
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-o"></i>
</span>
<span class="post-meta-item-text">发表于</span>
<time title="创建时间:2022-07-17 10:05:11" itemprop="dateCreated datePublished" datetime="2022-07-17T10:05:11+08:00">2022-07-17</time>
</span>
<span class="post-meta-item">
<span class="post-meta-item-icon">
<i class="fa fa-calendar-check-o"></i>
</span>
<span class="post-meta-item-text">更新于</span>
<time title="修改时间:2022-08-17 16:47:49" itemprop="dateModified" datetime="2022-08-17T16:47:49+08:00">2022-08-17</time>
</span>
<span id="/ospp之旅(四).html" class="post-meta-item leancloud_visitors" data-flag-title="OSPP之旅(四)" title="阅读次数">
<span class="post-meta-item-icon">
<i class="fa fa-eye"></i>
</span>
<span class="post-meta-item-text">阅读次数:</span>
<span class="leancloud-visitors-count"></span>
</span>
</div>
</header>
<div class="post-body" itemprop="articleBody">
<h1 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h1><p>在做OSPP项目的过程中,导师问我要不顺便参加OpenEuler的开源实习,正好<code>libvirt</code>有几个开源实习的任务,让我顺便一起做了。本来我就已经参加了这个活动,待在MindSpore社区,现在正好在OpenEuler社区也领一些任务做,涨涨积分。看了一下virt-sig组的任务之后,我选择先做<code>libvirt 6.2.0支持vhostuser类型磁盘</code>这个任务。</p><a id="more"></a>
<h1 id="任务分析"><a href="#任务分析" class="headerlink" title="任务分析"></a>任务分析</h1><p>目前的<code>libvirt 6.2.0</code>版本不支持<code>vhostuser</code>类型的磁盘,而最新版已经支持该特性,因此该特性应该在更高的版本中支持的,所以我们需要定位其最初支持的那个版本。定位的方法很简单,就是查询官网上面的<code>Release Changes</code>,地址在<a href="https://libvirt.org/news.html" target="_blank" rel="noopener">这里</a>,通过搜索可以了解到,该特性最初在<code>libvirt 7.1.0</code>版本中支持。</p>
<p>了解到该特性最初支持的版本之后,使用Git将仓库切换到<code>v7.1.0</code>版本,搜索提交日志,将支持该特性相关的commits找出来,与当前<code>v6.2.0</code>版本的代码进行对比,观察代码的变化,确定哪些是需要进行修改的,哪些是可以保留的。在我一页页翻着Git logs时,导师发了一个<code>bugzilla</code>的<a href="https://bugzilla.redhat.com/show_bug.cgi?id=1884659" target="_blank" rel="noopener">链接</a>过来,里面包含了支持<code>vhostuser</code>类型磁盘相关的所有commits,使一筹莫展的我醍醐灌顶,根据链接中提到的commits分析,随后回合即可。</p>
<h1 id="回合过程"><a href="#回合过程" class="headerlink" title="回合过程"></a>回合过程</h1><h2 id="流程简介"><a href="#流程简介" class="headerlink" title="流程简介"></a>流程简介</h2><p>我的回合流程有以下几个步骤:</p>
<ol>
<li><code>git cherry-pick</code>将相关commits合并到当前分支</li>
<li>解决<code>cherry-pick</code>过程中产生的代码冲突,尚不清楚功能的新代码和新文件倾向于保留</li>
<li>尝试编译,遇到错误根据错误日志解决问题,直至编译成功</li>
<li>运行测试,根据测试结果寻找相应错误地方,并将错误解决</li>
<li>删去多余的代码,<code>cherry-pick</code>过程中不可避免的拉取了一些多余的代码,将其删去,保证代码精简</li>
</ol>
<h2 id="问题一:代码冲突"><a href="#问题一:代码冲突" class="headerlink" title="问题一:代码冲突"></a>问题一:代码冲突</h2><p><code>cherry-pick</code>过程中不可避免地会产生代码冲突,尤其是跨了一个大版本的库,因此我采取的策略如下:</p>
<ol>
<li>对于<code>Makefile</code>冲突文件,均采取舍弃的策略。由于<code>6.2.0</code>的构建系统为<code>make</code>,而<code>7.1.0</code>版本的构建系统更换为<code>meson</code>,因此有关<code>meson.build</code>的新增文件一律舍弃,并做好文件变动记录,手动在<code>Makefile</code>中添加需要编译的文件。</li>
<li>对于代码发生移动的更改,均采取舍弃的策略。在<code>7.1.0</code>版本中,许多代码从原本的文件中抽离出来,使得代码和文件结构更加模块化,而在<code>6.2.0</code>版本中,由于移动代码涉及到的变动非常大,包括:头文件、函数名、Makefile等均需要做出改动,因此只能采取舍弃的策略。</li>
<li>对于代码发生冲突的区域,分析代码的变动,在保证函数功能不发生变化的情况下合入更改。由于发生改动的函数可能被很多其他模块所使用,因此在合入更改的适合需要分析更改是否会影响到函数本身的功能,避免其他模块出现不可预测的错误。</li>
</ol>
<p>将有关commits全部合入之后,检查发生变动的所有文件,检查是否存在明显的语法错误,检查完毕后便可以尝试手动编译。</p>
<h2 id="问题二:编译错误"><a href="#问题二:编译错误" class="headerlink" title="问题二:编译错误"></a>问题二:编译错误</h2><p>下面这张图很好地说明了我在编译过程中遇到的问题</p>
<p><img src="images/ospp/compile_errors.png" alt="编译错误"></p>
<p>错误日志提供的信息还是很详细的,按照日志定位到错误的地方,解决对应的问题就可以了。我在编译过程中遇到的问题主要是<code>枚举类缺少相应枚举字段</code>以及<code>switch分支缺少对应case</code>,将其补充上即可。同时需要注意的是,<code>6.2.0</code>到<code>7.1.0</code>中间支持了很多其他特性,这些特性在<code>cherry-pick</code>的过程中同时写入到了枚举类中,但实际上并没有对应的代码支持这些特性,因此需要将这些“假支持”的特性给删掉。</p>
<p>解决完以上问题后,编译就能成功了,编译成功也意味着合入的代码在编译链接的过程中是没有错误了,剩余的工作就要测试验证功能是否正常工作。</p>
<h2 id="问题三:枚举顺序引发的惨案"><a href="#问题三:枚举顺序引发的惨案" class="headerlink" title="问题三:枚举顺序引发的惨案"></a>问题三:枚举顺序引发的惨案</h2><p>由于我没有<code>Jenkins</code>之类的自动化测试环境,我只能手动地去跑一些跟本次任务相关的测试用例,待导师上班之后再问问他如何自动化运行所有测试。</p>
<p>因为在代码回合的过程中发现修改的测试数据都集中在<code>qemucapabilitiesdata</code>这个文件夹中,因此跟本次任务相关的单元测试主要是<code>build/tests/*cap*</code>相关的测试。运行一下测试就会发现报错,并提示运行一个更为详细的debug命令,运行该命令后会得到一个详细的错误报告,提示出现错误的地方。</p>
<p><img src="images/ospp/test_errors_by_enums.jpg" alt="枚举引发的错误"></p>
<p>从上图可以看到,预期输出应为<code>vhost-user-blk</code>,而实际输出为<code>object.qapified</code>,这个错误是由枚举类的顺序错误引起的,我将这两个字段顺序放反了,却并没有注意到。这个小错误卡浪费了我一堆时间,最终在对比<code>7.1.0</code>版本中的文件历史记录时发现并想起这个问题。这也说明枚举类中的字段是按顺序编号的,顺序弄反之后输出的结果也是相反的。</p>
<p>最终,将顺序改正之后再编译一次,再次运行测试,就能全部通过了。</p>
<p><img src="images/ospp/test_success.png" alt="测试通过"></p>
<h2 id="回合总结"><a href="#回合总结" class="headerlink" title="回合总结"></a>回合总结</h2><p>回合的过程就是一个<code>Code review</code>的过程,需要我们去了解每段代码的功能,解决产生的冲突,回合的过程中需要注意的点就是尽量不影响其他代码模块的功能。同时,做好Git commit的记录,操作的步骤切分的详细一点,在出现问题后回滚便会十分方便。</p>
<h1 id="生成补丁"><a href="#生成补丁" class="headerlink" title="生成补丁"></a>生成补丁</h1><p>测试确认功能没问题后,就能够使用<code>git format-patch</code>命令根据commit记录生成Patch补丁,再将补丁应用到<code>libvirt-rpm</code>制品仓中,构建新版本的软件包,并最终测试功能。</p>
<h2 id="Format-patch"><a href="#Format-patch" class="headerlink" title="Format-patch"></a>Format-patch</h2><p>在项目根目录下创建一个文件夹,用于存放生成的Patch文件<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">mkdir patches</span><br><span class="line">git format-patch master -o patches</span><br></pre></td></tr></table></figure></p>
<p>此时会生成很多补丁文件,由于旧的补丁文件在制品仓中已经存在,我们只要用自己的Commit制作的Patches即可。</p>
<h2 id="构建软件包"><a href="#构建软件包" class="headerlink" title="构建软件包"></a>构建软件包</h2><p>将制品仓的补丁和自己制作的补丁都移动到<code>~/rpmbuild/SOURCES/</code>中,同时编辑<code>libvirt.spec</code>文件,将自己制作的补丁文件按照顺序写到补丁列表中。<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">Patch0141: 0142-src-add-missing-virstoragefile.h-includes.patch</span><br><span class="line">Patch0142: 0143-virstoragefile-properly-include-virstoragefile.h-hea.patch</span><br><span class="line">Patch0143: 0144-virstoragefile-change-virStorageSource-drv-to-void-p.patch</span><br><span class="line">Patch0144: 0145-qemu_alias-introduce-qemuDomainGetVhostUserAlias-hel.patch</span><br><span class="line">Patch0145: 0146-docs-introduces-new-vhostuser-disk-type.patch</span><br><span class="line">Patch0146: 0147-conf-implement-support-for-vhostuser-disk.patch</span><br><span class="line">Patch0147: 0148-qemu_capabilities-introduce-vhost-user-blk-capabilit.patch</span><br><span class="line">Patch0148: 0149-qemu-implement-vhost-user-blk-support.patch</span><br><span class="line">Patch0149: 0150-qemu-capabilities-Introduce-QEMU_CAPS_VIRTIO_BLK_SCS.patch</span><br><span class="line">Patch0150: 0151-Set-QEMU_CAPS_VIRTIO_BLK_SCSI_DEFAULT_DISABLED-when-.patch</span><br></pre></td></tr></table></figure></p>
<p>然后运行构建命令<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> ~/rpmbuild</span><br><span class="line">rpmbuild -ba SPECS/libvirt.spec</span><br></pre></td></tr></table></figure></p>
<p>构建完成后覆盖安装升级<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo rpm -ivh RPMS/x86_64/libvirt*</span><br></pre></td></tr></table></figure></p>
<h2 id="测试功能"><a href="#测试功能" class="headerlink" title="测试功能"></a>测试功能</h2><p>由于SELinux的特性会使得<code>vhost-user-blk</code>的Socket没有连接权限,因此我们需要先将SELinux关掉。<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo setenforce 0</span><br></pre></td></tr></table></figure></p>
<p>接下来创建一个<code>qcow2</code>硬盘文件,然后用<code>qemu-storage-daemon</code>创建一个<code>vhost-user-blk</code>类型的Socket。有几种不同类型的<code>vhostuser</code>硬盘,具体如何创建Socket可以参考QEMU的<a href="https://qemu-project.gitlab.io/qemu/tools/qemu-storage-daemon.html" target="_blank" rel="noopener">文档</a>。<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">qemu-img create -f qcow2 share-disk.qcow2 1G</span><br><span class="line"></span><br><span class="line">qemu-storage-daemon \</span><br><span class="line"> --blockdev driver=file,node-name=share-file,filename=share-disk.qcow2 \</span><br><span class="line"> --blockdev driver=qcow2,node-name=share-disk,file=share-file \</span><br><span class="line"> --<span class="built_in">export</span> <span class="built_in">type</span>=vhost-user-blk,id=share-disk,addr.type=unix,addr.path=share-disk.sock,node-name=share-disk,writable=on</span><br></pre></td></tr></table></figure></p>
<p>此时在目录下能够看到一个名为<code>share-disk.sock</code>的Socket文件,虚拟机硬盘配置中就可以使用这个文件了。</p>
<p>接下来编写一个虚拟机配置文件,从欧拉的文档中复制一份下来即可,将其命名为<code>openEuler.xml</code>。需要注意的是,<code>vhost-user-blk</code>类型磁盘要求内存的类型是共享的,需要在XML中配置一下<code>memoryBacking</code>。<br><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">domain</span> <span class="attr">type</span>=<span class="string">'qemu'</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">name</span>></span>openEuler<span class="tag"></<span class="name">name</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">memory</span> <span class="attr">unit</span>=<span class="string">'GiB'</span>></span>2<span class="tag"></<span class="name">memory</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">memoryBacking</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">source</span> <span class="attr">type</span>=<span class="string">'memfd'</span>/></span></span><br><span class="line"> <span class="tag"><<span class="name">access</span> <span class="attr">mode</span>=<span class="string">'shared'</span>/></span></span><br><span class="line"> <span class="tag"></<span class="name">memoryBacking</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">vcpu</span>></span>2<span class="tag"></<span class="name">vcpu</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">os</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">type</span> <span class="attr">arch</span>=<span class="string">'aarch64'</span> <span class="attr">machine</span>=<span class="string">'virt'</span>></span>hvm<span class="tag"></<span class="name">type</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">loader</span> <span class="attr">readonly</span>=<span class="string">'yes'</span> <span class="attr">type</span>=<span class="string">'pflash'</span>></span>/usr/share/edk2/aarch64/QEMU_EFI-pflash.raw<span class="tag"></<span class="name">loader</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">nvram</span>></span>/var/lib/libvirt/qemu/nvram/openEulerVM.fd<span class="tag"></<span class="name">nvram</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">os</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">features</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">acpi</span>/></span></span><br><span class="line"> <span class="tag"><<span class="name">gic</span> <span class="attr">version</span>=<span class="string">'3'</span>/></span></span><br><span class="line"> <span class="tag"></<span class="name">features</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">cpu</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">topology</span> <span class="attr">sockets</span>=<span class="string">'1'</span> <span class="attr">cores</span>=<span class="string">'2'</span> <span class="attr">threads</span>=<span class="string">'1'</span>/></span></span><br><span class="line"> <span class="tag"></<span class="name">cpu</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">iothreads</span>></span>1<span class="tag"></<span class="name">iothreads</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">clock</span> <span class="attr">offset</span>=<span class="string">'utc'</span>/></span></span><br><span class="line"> <span class="tag"><<span class="name">on_poweroff</span>></span>destroy<span class="tag"></<span class="name">on_poweroff</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">on_reboot</span>></span>restart<span class="tag"></<span class="name">on_reboot</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">on_crash</span>></span>restart<span class="tag"></<span class="name">on_crash</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">devices</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">emulator</span>></span>/usr/libexec/qemu-kvm<span class="tag"></<span class="name">emulator</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">disk</span> <span class="attr">type</span>=<span class="string">'vhostuser'</span> <span class="attr">device</span>=<span class="string">'disk'</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">driver</span> <span class="attr">name</span>=<span class="string">'qemu'</span> <span class="attr">type</span>=<span class="string">'qcow2'</span> <span class="attr">queues</span>=<span class="string">"1"</span>/></span></span><br><span class="line"> <span class="tag"><<span class="name">source</span> <span class="attr">type</span>=<span class="string">'unix'</span> <span class="attr">path</span>=<span class="string">'/root/vm/share-disk.sock'</span>/></span></span><br><span class="line"> <span class="tag"><<span class="name">target</span> <span class="attr">dev</span>=<span class="string">'vda'</span> <span class="attr">bus</span>=<span class="string">'virtio'</span>/></span></span><br><span class="line"> <span class="tag"><<span class="name">boot</span> <span class="attr">order</span>=<span class="string">'2'</span>/></span></span><br><span class="line"> <span class="tag"></<span class="name">disk</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">disk</span> <span class="attr">type</span>=<span class="string">'file'</span> <span class="attr">device</span>=<span class="string">'cdrom'</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">driver</span> <span class="attr">name</span>=<span class="string">'qemu'</span> <span class="attr">type</span>=<span class="string">'raw'</span>/></span></span><br><span class="line"> <span class="tag"><<span class="name">source</span> <span class="attr">file</span>=<span class="string">'/root/vm/openEuler-22.03-LTS-aarch64-dvd.iso'</span>/></span></span><br><span class="line"> <span class="tag"><<span class="name">readonly</span>/></span></span><br><span class="line"> <span class="tag"><<span class="name">target</span> <span class="attr">dev</span>=<span class="string">'sdb'</span> <span class="attr">bus</span>=<span class="string">'scsi'</span>/></span></span><br><span class="line"> <span class="tag"><<span class="name">boot</span> <span class="attr">order</span>=<span class="string">'1'</span>/></span></span><br><span class="line"> <span class="tag"></<span class="name">disk</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">interface</span> <span class="attr">type</span>=<span class="string">'bridge'</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">source</span> <span class="attr">bridge</span>=<span class="string">'br0'</span>/></span></span><br><span class="line"> <span class="tag"><<span class="name">model</span> <span class="attr">type</span>=<span class="string">'virtio'</span>/></span></span><br><span class="line"> <span class="tag"></<span class="name">interface</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">console</span> <span class="attr">type</span>=<span class="string">'pty'</span>/></span></span><br><span class="line"> <span class="tag"><<span class="name">video</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">model</span> <span class="attr">type</span>=<span class="string">'virtio'</span>/></span></span><br><span class="line"> <span class="tag"></<span class="name">video</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">controller</span> <span class="attr">type</span>=<span class="string">'scsi'</span> <span class="attr">index</span>=<span class="string">'0'</span> <span class="attr">model</span>=<span class="string">'virtio-scsi'</span>/></span></span><br><span class="line"> <span class="tag"><<span class="name">controller</span> <span class="attr">type</span>=<span class="string">'usb'</span> <span class="attr">model</span>=<span class="string">'ehci'</span>/></span></span><br><span class="line"> <span class="tag"><<span class="name">input</span> <span class="attr">type</span>=<span class="string">'tablet'</span> <span class="attr">bus</span>=<span class="string">'usb'</span>/></span></span><br><span class="line"> <span class="tag"><<span class="name">input</span> <span class="attr">type</span>=<span class="string">'keyboard'</span> <span class="attr">bus</span>=<span class="string">'usb'</span>/></span></span><br><span class="line"> <span class="tag"><<span class="name">graphics</span> <span class="attr">type</span>=<span class="string">'vnc'</span> <span class="attr">port</span>=<span class="string">'5900'</span> <span class="attr">listen</span>=<span class="string">'0.0.0.0'</span> <span class="attr">passwd</span>=<span class="string">'n8VfjbFK'</span>/></span></span><br><span class="line"> <span class="tag"></<span class="name">devices</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">seclabel</span> <span class="attr">type</span>=<span class="string">'dynamic'</span> <span class="attr">model</span>=<span class="string">'dac'</span> <span class="attr">relabel</span>=<span class="string">'yes'</span>/></span></span><br><span class="line"><span class="tag"></<span class="name">domain</span>></span></span><br></pre></td></tr></table></figure></p>
<p>定义并启动虚拟机,使用VNC连接虚拟机屏幕,观察虚拟机是否启动成功,硬盘是否正确地挂载,能够正确地读写文件。<br><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">virsh define openEuler.xml</span><br><span class="line">virsh start openEuler</span><br></pre></td></tr></table></figure></p>
<p><img src="images/ospp/vhostuser_vm_start.jpg" alt="启动虚拟机"></p>
</div>
<footer class="post-footer">
<div class="post-tags">
<a href="/tags/ospp/" rel="tag"># OSPP</a>
<a href="/tags/开源/" rel="tag"># 开源</a>
<a href="/tags/操作系统/" rel="tag"># 操作系统</a>
<a href="/tags/虚拟化/" rel="tag"># 虚拟化</a>
</div>
<div class="post-nav">
<div class="post-nav-next post-nav-item">
<a href="/ospp之旅(三).html" rel="next" title="OSPP之旅(三)">
<i class="fa fa-chevron-left"></i> OSPP之旅(三)
</a>
</div>
<span class="post-nav-divider"></span>
<div class="post-nav-prev post-nav-item">
<a href="/git合并多个commit.html" rel="prev" title="Git合并多个Commit">
Git合并多个Commit <i class="fa fa-chevron-right"></i>
</a>
</div>
</div>
</footer>
</article>
</div>
</div>
</div>
<div class="toggle sidebar-toggle">
<span class="toggle-line toggle-line-first"></span>
<span class="toggle-line toggle-line-middle"></span>
<span class="toggle-line toggle-line-last"></span>
</div>
<aside class="sidebar">
<div class="sidebar-inner">
<ul class="sidebar-nav motion-element">
<li class="sidebar-nav-toc">
文章目录
</li>
<li class="sidebar-nav-overview">
站点概览
</li>
</ul>
<!--noindex-->
<div class="post-toc-wrap sidebar-panel">
<div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#前言"><span class="nav-number">1.</span> <span class="nav-text">前言</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#任务分析"><span class="nav-number">2.</span> <span class="nav-text">任务分析</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#回合过程"><span class="nav-number">3.</span> <span class="nav-text">回合过程</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#流程简介"><span class="nav-number">3.1.</span> <span class="nav-text">流程简介</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#问题一:代码冲突"><span class="nav-number">3.2.</span> <span class="nav-text">问题一:代码冲突</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#问题二:编译错误"><span class="nav-number">3.3.</span> <span class="nav-text">问题二:编译错误</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#问题三:枚举顺序引发的惨案"><span class="nav-number">3.4.</span> <span class="nav-text">问题三:枚举顺序引发的惨案</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#回合总结"><span class="nav-number">3.5.</span> <span class="nav-text">回合总结</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#生成补丁"><span class="nav-number">4.</span> <span class="nav-text">生成补丁</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#Format-patch"><span class="nav-number">4.1.</span> <span class="nav-text">Format-patch</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#构建软件包"><span class="nav-number">4.2.</span> <span class="nav-text">构建软件包</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#测试功能"><span class="nav-number">4.3.</span> <span class="nav-text">测试功能</span></a></li></ol></li></ol></div>
</div>
<!--/noindex-->
<div class="site-overview-wrap sidebar-panel">
<div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
<img class="site-author-image" itemprop="image" alt="Fisher"
src="/images/icons/avatar.jpg">
<p class="site-author-name" itemprop="name">Fisher</p>
<div class="site-description" itemprop="description">记录学习生活中的点滴</div>
</div>
<div class="site-state-wrap motion-element">
<nav class="site-state">
<div class="site-state-item site-state-posts">
<a href="/archives/">
<span class="site-state-item-count">97</span>
<span class="site-state-item-name">日志</span>
</a>
</div>
<div class="site-state-item site-state-tags">
<a href="/tags/">
<span class="site-state-item-count">25</span>
<span class="site-state-item-name">标签</span></a>
</div>
</nav>
</div>
<div class="links-of-author motion-element">
<span class="links-of-author-item">
<a href="https://github.com/FisherWY" title="GitHub → https://github.com/FisherWY" rel="noopener" target="_blank"><i class="fa fa-fw fa-github"></i>GitHub</a>
</span>
<span class="links-of-author-item">
<a href="mailto:[email protected]" title="E-Mail → mailto:[email protected]" rel="noopener" target="_blank"><i class="fa fa-fw fa-envelope"></i>E-Mail</a>
</span>
</div>
</div>
</div>
</aside>
<div id="sidebar-dimmer"></div>
</div>
</main>
<footer class="footer">
<div class="footer-inner">
<div class="beian"><a href="http://beian.miit.gov.cn" rel="noopener" target="_blank">粤ICP备2022017631号-1 </a>
<img src="/images/icons/beian.png" style="display: inline-block;">
</div>
<div class="copyright">
©
<span itemprop="copyrightYear">2023</span>
<span class="with-love">
<i class="fa fa-user"></i>
</span>
<span class="author" itemprop="copyrightHolder">Fisher</span>
</div>
<div class="powered-by">由 <a href="https://hexo.io" class="theme-link" rel="noopener" target="_blank">Hexo</a> 强力驱动 v3.9.0
</div>
<span class="post-meta-divider">|</span>
<div class="theme-info">主题 – <a href="https://theme-next.org" class="theme-link" rel="noopener" target="_blank">NexT.Gemini</a> v7.4.2
</div>
<script>
function leancloudSelector(url) {
return document.getElementById(url).querySelector('.leancloud-visitors-count');
}
if (CONFIG.page.isPost) {
function addCount(Counter) {
var visitors = document.querySelector('.leancloud_visitors');
var url = visitors.getAttribute('id').trim();
var title = visitors.getAttribute('data-flag-title').trim();
Counter('get', `/classes/Counter?where=${JSON.stringify({ url })}`)
.then(response => response.json())
.then(({ results }) => {
if (results.length > 0) {
var counter = results[0];
Counter('put', '/classes/Counter/' + counter.objectId, { time: { '__op': 'Increment', 'amount': 1 } })
.then(response => response.json())
.then(() => {
leancloudSelector(url).innerText = counter.time + 1;
})
.catch(error => {
console.log('Failed to save visitor count', error);
})
} else {
leancloudSelector(url).innerText = 'Counter not initialized! More info at console err msg.';
console.error('ATTENTION! LeanCloud counter has security bug, see how to solve it here: https://github.com/theme-next/hexo-leancloud-counter-security. \n However, you can still use LeanCloud without security, by setting `security` option to `false`.');
}
})
.catch(error => {
console.log('LeanCloud Counter Error', error);
});
}
} else {
function showTime(Counter) {
var visitors = document.querySelectorAll('.leancloud_visitors');
var entries = [...visitors].map(element => {
return element.getAttribute('id').trim();
});
Counter('get', `/classes/Counter?where=${JSON.stringify({ url: { '$in': entries } })}`)
.then(response => response.json())
.then(({ results }) => {
if (results.length === 0) {
document.querySelectorAll('.leancloud_visitors .leancloud-visitors-count').forEach(element => {
element.innerText = 0;
});
return;
}
for (var i = 0; i < results.length; i++) {
var item = results[i];
var url = item.url;
var time = item.time;
leancloudSelector(url).innerText = time;
}
for (var i = 0; i < entries.length; i++) {
var url = entries[i];
var element = leancloudSelector(url);
if (element.innerText == '') {
element.innerText = 0;
}
}
})
.catch(error => {
console.log('LeanCloud Counter Error', error);
});
}
}
fetch('https://app-router.leancloud.cn/2/route?appId=l8bvleb0PFB0er4hTWo3bGL1-gzGzoHsz')
.then(response => response.json())
.then(({ api_server }) => {
var Counter = (method, url, data) => {
return fetch(`https://${api_server}/1.1${url}`, {
method: method,
headers: {
'X-LC-Id': 'l8bvleb0PFB0er4hTWo3bGL1-gzGzoHsz',
'X-LC-Key': 'vOPowrKK83zOB6LhLKYOsGd1',
'Content-Type': 'application/json',
},
body: JSON.stringify(data)
});
};
if (CONFIG.page.isPost) {
const localhost = /http:\/\/(localhost|127.0.0.1|0.0.0.0)/;
if (localhost.test(document.URL)) return;
addCount(Counter);
} else if (document.querySelectorAll('.post-title-link').length >= 1) {
showTime(Counter);
}
});
</script>
</div>
</footer>
</div>
<script src="/lib/anime.min.js"></script>
<script src="/lib/velocity/velocity.min.js"></script>
<script src="/lib/velocity/velocity.ui.min.js"></script>
<script src="/js/utils.js"></script><script src="/js/motion.js"></script>
<script src="/js/schemes/pisces.js"></script>
<script src="/js/next-boot.js"></script>
<script>
(function(){
var bp = document.createElement('script');
var curProtocol = window.location.protocol.split(':')[0];
bp.src = (curProtocol === 'https') ? 'https://zz.bdstatic.com/linksubmit/push.js' : 'http://push.zhanzhang.baidu.com/push.js';
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(bp, s);
})();
</script>
<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"pluginRootPath":"live2dw/","pluginJsPath":"lib/","pluginModelPath":"assets/","tagMode":false,"debug":false,"display":{"position":"left","width":175,"height":350},"model":{"jsonPath":"/live2dw/assets/koharu.model.json"},"mobile":{"show":false},"log":false});</script></body>
</html>