forked from NJU-ProjectN/ics-pa-gitbook
-
Notifications
You must be signed in to change notification settings - Fork 0
/
4.2.html
1029 lines (503 loc) · 50.8 KB
/
4.2.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
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE HTML>
<html lang="" >
<head>
<meta charset="UTF-8">
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<title>虚实交错的魔法 · GitBook</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="description" content="">
<meta name="generator" content="GitBook 3.2.3">
<link rel="stylesheet" href="gitbook/style.css">
<link rel="stylesheet" href="gitbook/gitbook-plugin-page-footer-ex/style/plugin.css">
<link rel="stylesheet" href="gitbook/gitbook-plugin-callouts/plugin.css">
<link rel="stylesheet" href="gitbook/gitbook-plugin-highlight/website.css">
<link rel="stylesheet" href="gitbook/gitbook-plugin-search/search.css">
<link rel="stylesheet" href="gitbook/gitbook-plugin-fontsettings/website.css">
<link rel="stylesheet" href="styles.css">
<meta name="HandheldFriendly" content="true"/>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="apple-touch-icon-precomposed" sizes="152x152" href="gitbook/images/apple-touch-icon-precomposed-152.png">
<link rel="shortcut icon" href="gitbook/images/favicon.ico" type="image/x-icon">
<link rel="next" href="4.3.html" />
<link rel="prev" href="4.1.html" />
</head>
<body>
<div class="book">
<div class="book-summary">
<div id="book-search-input" role="search">
<input type="text" placeholder="Type to search" />
</div>
<nav role="navigation">
<ul class="summary">
<li class="chapter " data-level="1.1" data-path="./">
<a href="./">
Introduction
</a>
</li>
<li class="chapter " data-level="1.2" data-path="PA0.html">
<a href="PA0.html">
PA0 - 世界诞生的前夜: 开发环境配置
</a>
<ul class="articles">
<li class="chapter " data-level="1.2.1" data-path="0.1.html">
<a href="0.1.html">
Installing a GNU/Linux VM
</a>
</li>
<li class="chapter " data-level="1.2.2" data-path="0.2.html">
<a href="0.2.html">
First Exploration with GNU/Linux
</a>
</li>
<li class="chapter " data-level="1.2.3" data-path="0.3.html">
<a href="0.3.html">
Installing Tools
</a>
</li>
<li class="chapter " data-level="1.2.4" data-path="0.4.html">
<a href="0.4.html">
Configuring vim
</a>
</li>
<li class="chapter " data-level="1.2.5" data-path="0.5.html">
<a href="0.5.html">
More Exploration
</a>
</li>
<li class="chapter " data-level="1.2.6" data-path="0.6.html">
<a href="0.6.html">
Transferring Files between host and container
</a>
</li>
<li class="chapter " data-level="1.2.7" data-path="0.7.html">
<a href="0.7.html">
Acquiring Source Code for PAs
</a>
</li>
</ul>
</li>
<li class="chapter " data-level="1.3" data-path="PA1.html">
<a href="PA1.html">
PA1 - 开天辟地的篇章: 最简单的计算机
</a>
<ul class="articles">
<li class="chapter " data-level="1.3.1" data-path="1.1.html">
<a href="1.1.html">
在开始愉快的PA之旅之前
</a>
</li>
<li class="chapter " data-level="1.3.2" data-path="1.2.html">
<a href="1.2.html">
开天辟地的篇章
</a>
</li>
<li class="chapter " data-level="1.3.3" data-path="1.3.html">
<a href="1.3.html">
RTFSC
</a>
</li>
<li class="chapter " data-level="1.3.4" data-path="1.4.html">
<a href="1.4.html">
基础设施
</a>
</li>
<li class="chapter " data-level="1.3.5" data-path="1.5.html">
<a href="1.5.html">
表达式求值
</a>
</li>
<li class="chapter " data-level="1.3.6" data-path="1.6.html">
<a href="1.6.html">
监视点
</a>
</li>
<li class="chapter " data-level="1.3.7" data-path="1.7.html">
<a href="1.7.html">
i386手册
</a>
</li>
</ul>
</li>
<li class="chapter " data-level="1.4" data-path="PA2.html">
<a href="PA2.html">
PA2 - 简单复杂的机器: 冯诺依曼计算机系统
</a>
<ul class="articles">
<li class="chapter " data-level="1.4.1" data-path="2.1.html">
<a href="2.1.html">
不停计算的机器
</a>
</li>
<li class="chapter " data-level="1.4.2" data-path="2.2.html">
<a href="2.2.html">
RTFSC(2)
</a>
</li>
<li class="chapter " data-level="1.4.3" data-path="2.3.html">
<a href="2.3.html">
程序, 运行时环境与AM
</a>
</li>
<li class="chapter " data-level="1.4.4" data-path="2.4.html">
<a href="2.4.html">
基础设施(2)
</a>
</li>
<li class="chapter " data-level="1.4.5" data-path="2.5.html">
<a href="2.5.html">
输入输出
</a>
</li>
</ul>
</li>
<li class="chapter " data-level="1.5" data-path="PA3.html">
<a href="PA3.html">
PA3 - 穿越时空的旅程: 批处理系统
</a>
<ul class="articles">
<li class="chapter " data-level="1.5.1" data-path="3.1.html">
<a href="3.1.html">
最简单的操作系统
</a>
</li>
<li class="chapter " data-level="1.5.2" data-path="3.2.html">
<a href="3.2.html">
穿越时空的旅程
</a>
</li>
<li class="chapter " data-level="1.5.3" data-path="3.3.html">
<a href="3.3.html">
用户程序和系统调用
</a>
</li>
<li class="chapter " data-level="1.5.4" data-path="3.4.html">
<a href="3.4.html">
文件系统
</a>
</li>
<li class="chapter " data-level="1.5.5" data-path="3.5.html">
<a href="3.5.html">
批处理系统
</a>
</li>
</ul>
</li>
<li class="chapter " data-level="1.6" data-path="PA4.html">
<a href="PA4.html">
PA4 - 虚实交错的魔法: 分时多任务
</a>
<ul class="articles">
<li class="chapter " data-level="1.6.1" data-path="4.1.html">
<a href="4.1.html">
多道程序
</a>
</li>
<li class="chapter active" data-level="1.6.2" data-path="4.2.html">
<a href="4.2.html">
虚实交错的魔法
</a>
</li>
<li class="chapter " data-level="1.6.3" data-path="4.3.html">
<a href="4.3.html">
超越容量的界限
</a>
</li>
<li class="chapter " data-level="1.6.4" data-path="4.4.html">
<a href="4.4.html">
来自外部的声音
</a>
</li>
<li class="chapter " data-level="1.6.5" data-path="4.5.html">
<a href="4.5.html">
编写不朽的传奇
</a>
</li>
</ul>
</li>
<li class="chapter " data-level="1.7" data-path="PA5.html">
<a href="PA5.html">
PA5 - 天下武功唯快不破: 程序与性能
</a>
<ul class="articles">
<li class="chapter " data-level="1.7.1" data-path="5.1.html">
<a href="5.1.html">
浮点数的支持
</a>
</li>
<li class="chapter " data-level="1.7.2" data-path="5.2.html">
<a href="5.2.html">
通往高速的次元
</a>
</li>
<li class="chapter " data-level="1.7.3" data-path="5.3.html">
<a href="5.3.html">
天下武功唯快不破
</a>
</li>
</ul>
</li>
<li class="chapter " data-level="1.8" data-path="blank.html">
<a href="blank.html">
杂项
</a>
<ul class="articles">
<li class="chapter " data-level="1.8.1" data-path="why.html">
<a href="why.html">
为什么要学习计算机系统基础
</a>
</li>
<li class="chapter " data-level="1.8.2" data-path="submit.html">
<a href="submit.html">
实验提交要求
</a>
</li>
<li class="chapter " data-level="1.8.3" data-path="linux.html">
<a href="linux.html">
Linux入门教程
</a>
</li>
<li class="chapter " data-level="1.8.4" data-path="man.html">
<a href="man.html">
man入门教程
</a>
</li>
<li class="chapter " data-level="1.8.5" data-path="git.html">
<a href="git.html">
git入门教程
</a>
</li>
<li class="chapter " data-level="1.8.6" data-path="i386-intro.html">
<a href="i386-intro.html">
i386手册指令集阅读指南
</a>
</li>
<li class="chapter " data-level="1.8.7" data-path="exec.html">
<a href="exec.html">
指令执行例子
</a>
</li>
</ul>
</li>
<li class="divider"></li>
<li>
<a href="https://www.gitbook.com" target="blank" class="gitbook-link">
Published with GitBook
</a>
</li>
</ul>
</nav>
</div>
<div class="book-body">
<div class="body-inner">
<div class="book-header" role="navigation">
<!-- Title -->
<h1>
<i class="fa fa-circle-o-notch fa-spin"></i>
<a href="." >虚实交错的魔法</a>
</h1>
</div>
<div class="page-wrapper" tabindex="-1" role="main">
<div class="page-inner">
<div id="book-search-results">
<div class="search-noresults">
<section class="normal markdown-section">
<h2 id="程序和内存位置">程序和内存位置</h2>
<p>我们已经实现了一个多道程序的多任务系统,
但却在尝试运行第二个用户进程的时候遇到了问题.
如果你还记得编译Navy-apps中的程序时, 我们都把它们链接到<code>0x4000000</code>的内存位置,
你就会知道问题的原因了: 如果我们正在运行仙剑奇侠传,
同时也想运行hello程序, 它们的内容就会被相互覆盖!</p>
<p>出现上述问题的根本原因是, "在内存中可以同时存在多个进程"的条件被打破了.
显然我们需要对内存进行管理, 而不是让多个进程随意使用.
我们在PA3中提到操作系统有管理系统资源的义务,
在多任务操作系统中, 内存作为一种资源自然也是要被管理起来.
操作系统需要记录内存的分配情况, 需要运行一个新进程的时候,
就给它分配一片空闲的内存位置, 把它加载到这一内存位置上即可.</p>
<p>不过, 这片空闲的内存位置是操作系统的加载器在加载时刻指定的,
但进程代码真的可以在这一内存位置上正确运行吗?</p>
<h3 id="绝对代码">绝对代码</h3>
<p>一般来说, 程序的内存位置是在<a href="https://en.wikipedia.org/wiki/Link_time" target="_blank">链接时刻(link time)</a>确定的(Navy-apps中的程序就是这样),
以前的程序员甚至在程序中使用绝对地址来进行内存访问,
这两种代码称为绝对代码(absolute code).
绝对代码会假设程序对象(函数和数据)位于某个固定的位置,
比如链接时重定位之后, 程序就会认为某个变量<code>a</code>位于内存位置<code>0x4001234</code>,
如果我们把程序加载到别的位置, 加载后变量<code>a</code>的实际位置就改变了,
但程序中的绝对代码还是认为变量<code>a</code>仍然位于内存位置<code>0x4001234</code>,
访问<code>0x4001234</code>也就无法访问真正的变量<code>a</code>.
显然, 绝对代码只能在固定的内存位置才能正确运行.</p>
<p>但操作系统在加载时刻分配的空闲内存位置, 并不总是能让这种程序正确运行.
因此, 这个问题的一个解决方案, 就是让操作系统记录程序的加载位置,
当一个程序试图加载到一个已经被使用的内存位置时, 加载将会失败, 操作系统将返回一个错误.
为了避免加载失败, 一个方法是为每个程序维护多个不同加载地址的版本,
期望其中有一个版本可以被成功加载.</p>
<h3 id="可重定位代码">可重定位代码</h3>
<p>但这样太麻烦了. 为什么一定要提前确定一个程序的加载位置呢?
如果我们把链接时的重定位阶段往后推迟, 不就可以打破绝对代码的限制了吗?</p>
<p>于是有程序员开发了一类"<a href="https://en.wikipedia.org/wiki/Self-relocation" target="_blank">自重定位(self-relocation)</a>"的特殊程序,
这种程序可以在开始运行的时候, 先把自己重定位到其它内存位置, 然后再开始真正的运行.
这种重定位类型称为"<a href="https://en.wikipedia.org/wiki/Run_time_(program_lifecycle_phase)" target="_blank">运行时(run time)</a>重定位", 但这也并没有真正解决问题,
因为程序在运行时刻并不知道重定位的目标内存位置是否空闲.</p>
<p>既然只有操作系统才知道内存是否空闲, 那就干脆让加载器来进行重定位吧,
于是有了"<a href="https://en.wikipedia.org/wiki/Loader_(computing)" target="_blank">加载时(load time)</a>重定位"的说法.
具体地, 加载器会申请一个空闲的内存位置, 然后将程序加载到这个内存位置,
并把程序重定位到这个内存位置, 之后才会执行这个程序.
今天的GNU/Linux就是通过这种方式来插入<a href="https://en.wikipedia.org/wiki/Loadable_kernel_module" target="_blank">内核模块</a>的.</p>
<h3 id="位置无关代码">位置无关代码</h3>
<p>从某种程度上来说, 加载时重定位会带来额外的开销:
如果一个程序要被重复执行多次, 那么就要进行多次的加载时重定位.
早期的计算机速度较慢, 大家觉得加载时重定位的开销还是不能忽略的,
而且加载时重定位需要对整个程序进行处理,
如果程序比较大的话, 开销就更明显了.</p>
<p>有没有方法可以节省重定位的开销, 甚至不进行重定位呢?
但链接时的重定位又可能会产生绝对代码, 这并不是我们所希望的.
如果程序中的所有寻址, 都是针对程序位置来进行相对寻址操作,
这样的程序就可以被加载到任意位置执行, 而不会出现绝对代码的问题了,</p>
<p>这就是<a href="https://en.wikipedia.org/wiki/Position-independent_code" target="_blank">PIC(position-independent code, 位置无关代码)</a>的基本思想.
今天的动态库都是PIC, 这样它们就可以被加载到任意的内存位置了.
此外, 如果一个可执行文件全部由PIC组成, 那么它有一个新名字,
叫<a href="https://en.wikipedia.org/wiki/Position-independent_code#PIE" target="_blank">PIE(position-independent executable, 位置无关可执行文件)</a>.
编译器可以通过特定的选项编译出PIE.
和一般的程序不同, PIE还能在一定程度上对恶意的攻击程序造成了干扰:
恶意程序也无法提前假设PIE运行的地址.
也正是因为这一安全相关的特性, 最近的不少GNU/Linux的发行版上配置的gcc都默认生成PIE.
不过, 使用相对寻址会使得程序的代码量增大, 性能也会受到一些影响,
但对于早期的计算机来说, 内存是一种非常珍贵的资源,
降低性能也是大家不愿意看到的, 因此对于PIC和PIE, 大家也会慎重考虑.</p>
<div class="panel panel-info"><div class="panel-heading"><h5 class="panel-title" id="实现基于pie的loader建议二周目思考"><i class="fa fa-question-circle"></i> 实现基于PIE的loader(建议二周目思考)</h5></div><div class="panel-body"><p>天下并没有免费的午餐, PIE之所以能做到位置无关,
其实是要依赖于程序中一个叫<a href="https://www.technovelty.org/linux/plt-and-got-the-key-to-code-sharing-and-dynamic-libraries.html" target="_blank">GOT(global offset table, 全局偏移量表)</a>的数据结构.
要正确运行PIE, 操作系统中的加载器需要在加载程序的时候往GOT中填写正确的内容.</p><p>有兴趣的同学可以让Nanos-lite的loader支持PIE, 当然这需要了解一些ELF相关的细节,
具体细节可以参考ABI手册.</p></div></div>
<p>如果世界上的所有程序都是可重定位的, 或者是PIC, 内存覆盖的问题就不攻自破了.
但总有一些包含绝对代码的程序, 考虑到兼容问题, 还需要想办法运行它们.
有没有更好的, 一劳永逸的方案呢?</p>
<h2 id="虚实交错的魔法">虚实交错的魔法</h2>
<p>我们刚才是从程序本身来考量, 自然无法绕开绝对代码的问题.
为了解决这个问题, 我们需要从另一个方面 - 内存 - 来思考.
我们知道程序会经历编译, 链接, 加载, 运行这四个阶段,
绝对代码经过编译链接之后, 程序看到的内存地址就会确定下来了,
加载运行的时候就会让程序使用这一内存地址, 来保证程序可以正确运行.
一种尝试是把程序看到的内存和它运行时候真正使用的内存解耦开来.
这就是虚拟内存的思想.</p>
<p>所谓虚拟内存, 就是在真正的内存(也叫物理内存)之上的一层专门给进程使用的抽象.
有了虚拟内存之后, 进程只需要认为自己运行在虚拟地址上就可以了,
真正运行的时候, 才把虚拟地址映射到物理地址.
这样, 我们只要把程序链接到一个固定的虚拟地址,
加载的时候把它们加载到不同的物理地址,
并维护好虚拟地址到物理地址的映射关系, 就可以一劳永逸地解决上述问题了!</p>
<p>那么, 在进程运行的时候, 谁来把虚拟地址映射成物理地址呢?
我们在PA1中已经了解到指令的生命周期:</p>
<pre><code class="lang-c"><span class="hljs-keyword">while</span> (<span class="hljs-number">1</span>) {
从EIP指示的存储器位置取出指令;
执行指令;
更新EIP;
}
</code></pre>
<p>如果引入了虚拟内存机制, EIP就是一个虚拟地址了,
我们需要在访问存储器之前完成虚拟地址到物理地址的映射.
尽管操作系统管理着计算机中的所有资源, 在计算机看来它也只是一个程序而已.
作为一个在计算机上执行的程序而言, 操作系统不可能有能力干涉指令执行的具体过程.
所以让操作系统来把虚拟地址映射成物理地址, 是不可能实现的.
因此, 在硬件中进行这一映射是唯一的选择了:
我们在处理器和存储器之间添加一个新的硬件模块MMU(Memory Management Unit, 内存管理单元),
它是虚拟内存机制的核心, 肩负起这一机制最重要的地址映射功能.
需要说明的是, 我们刚才提到的"MMU位于处理器和存储器之间"只是概念上的说法.
事实上, 虚拟内存机制在现代计算机中是如此重要, 以至于MMU在物理上都实现在处理器芯片内部了.</p>
<p>但是, 只有操作系统才知道具体要把虚拟地址映射到哪些物理地址上.
所以, 虚拟内存机制是一个软硬协同才能生效的机制:
操作系统负责进行物理内存的管理,
加载进程的时候决定要把进程的虚拟地址映射到哪些物理地址;
等到进程真正运行之前, 还需要配置MMU, 把之前决定好的映射落实到硬件上,
进程运行的时候, MMU就会进行地址转换, 把进程的虚拟地址映射到操作系统希望的物理地址.
注意到这个映射是进程相关的: 不同的进程有不同的映射,
这意味着对不同的进程来说, 同一个虚拟地址可能会被映射到不同的物理地址.
这恰好一劳永逸地解决了内存覆盖的问题.
绝大部分多任务操作系统就是这样做的.</p>
<h3 id="分段">分段</h3>
<p>关于MMU具体如何进行地址映射, 目前主要有两种主流的方式.
最简单的方法就是, 物理地址=虚拟地址+偏移量.
这种最朴素的方式就是段式虚拟内存管理机制, 简称分段机制.
从直觉上来理解, 就是把物理内存划分成若干个段,
不同的进程就放到不同的段中运行, 进程不需要关心自己具体在哪一个段里面,
操作系统只要让不同的进程使用不同的偏移量, 进程之间就不会相互干扰了.</p>
<p>分段机制在硬件上的实现可以非常简单, 只需要在MMU中实现一个段基址寄存器就可以了.
操作系统在运行不同进程的时候, 就在段基址寄存器中设置不同的值,
MMU会把进程使用的虚拟地址加上段基址, 来生成真正用于访问内存的物理地址,
这样就实现了"让不同的进程使用不同的段"的目的.
作为教学操作系统的Minix就是这样工作的,
一些简单的嵌入式系统和实时系统, 也是通过分段机制来进行虚存管理.</p>
<p>实际上, 处理器中的分段机制有可能复杂得多.
例如i386由于历史原因, 为了兼容它的前身8086, 不得已引入了段描述符,
段选择符, 全局描述符表(GDT), 全局描述符表寄存器(GDTR)等概念,
段描述符中除了段基址之外, 还描述了段的长度, 类型, 粒度, 访问权限等等的属性,
为了弥补段描述符的性能问题, 又加入了描述符cache等概念...
我们可以目睹一下i386分段机制的风采:</p>
<pre><code> 15 0 31 0
LOGICAL +----------------+ +-------------------------------------+
ADDRESS | SELECTOR | | OFFSET |
+---+---------+--+ +-------------------+-----------------+
+------+ V |
| DESCRIPTOR TABLE |
| +------------+ |
| | | |
| | | |
| | | |
| | | |
| |------------| |
| | SEGMENT | BASE +---+ |
+->| DESCRIPTOR |-------------->| + |<------+
|------------| ADDRESS +-+-+
| | |
+------------+ |
V
LINEAR +------------+-----------+--------------+
ADDRESS | DIR | PAGE | OFFSET |
+------------+-----------+--------------+
</code></pre><p>咋看之下真是眼花缭乱, 让人一头雾水.</p>
<p>在NEMU中, 我们需要了解什么呢? 什么都不需要.
现在的大部分操作系统都不再使用分段机制, 就连i386手册中也提到可以想办法"绕过"它来提高性能:
将段基地址设成0, 长度设成4GB, 这样看来就像没有段的概念一样, 这就是i386手册中提到的"扁平模式".
当然, 这里的"绕过"并不是简单地将分段机制关掉(事实上也不可能关掉),
我们在PA3中提到的i386保护机制中关于特权级的概念, 其实就是i386分段机制提供的, 抛弃它是十分不明智的.
不过我们在NEMU中也没打算实现保护机制, 因此i386分段机制的各种概念, 我们也不会加入到NEMU中来.</p>
<footer class="page-footer-ex"> <span class="page-footer-ex-copyright"> By <a href="https://sashimi-yzh.github.io/" target="_blank">Zihao Yu</a>, 采用<a href="http://creativecommons.org/licenses/by-nc-sa/3.0/cn/" target="_blank">知识共享 署名-非商业性使用-相同方式共享 3.0 中国大陆 许可协议</a>发布 </span>            <span class="page-footer-ex-footer-update"> 此页面修订于: 2021-04-19 09:48:46 </span> </footer>
</section>
</div>
<div class="search-results">
<div class="has-results">
<h1 class="search-results-title"><span class='search-results-count'></span> results matching "<span class='search-query'></span>"</h1>
<ul class="search-results-list"></ul>
</div>
<div class="no-results">
<h1 class="search-results-title">No results matching "<span class='search-query'></span>"</h1>
</div>
</div>
</div>
</div>
</div>
</div>
<a href="4.1.html" class="navigation navigation-prev " aria-label="Previous page: 多道程序">
<i class="fa fa-angle-left"></i>
</a>
<a href="4.3.html" class="navigation navigation-next " aria-label="Next page: 超越容量的界限">
<i class="fa fa-angle-right"></i>
</a>
</div>
<script>
var gitbook = gitbook || [];
gitbook.push(function() {
gitbook.page.hasChanged({"page":{"title":"虚实交错的魔法","level":"1.6.2","depth":2,"next":{"title":"超越容量的界限","level":"1.6.3","depth":2,"path":"4.3.md","ref":"4.3.md","articles":[]},"previous":{"title":"多道程序","level":"1.6.1","depth":2,"path":"4.1.md","ref":"4.1.md","articles":[]},"dir":"ltr"},"config":{"gitbook":"3.x.x","theme":"default","variables":{},"plugins":["localized-footer","page-footer-ex","callouts"],"pluginsConfig":{"callouts":{"flag":{"alert":"success","picto":"fa-flag"},"question":{"alert":"info","picto":"fa-question-circle"},"info":{"alert":"info","picto":"fa-info-circle"},"todo":{"alert":"warning","picto":"fa-edit"},"caution":{"alert":"danger","picto":"fa-bullhorn"},"danger":{"alert":"danger","picto":"fa-exclamation"},"showTypeInHeader":false},"page-footer-ex":{"copyright":"By [Zihao Yu](https://sashimi-yzh.github.io/), 采用[知识共享 署名-非商业性使用-相同方式共享 3.0 中国大陆 许可协议](http://creativecommons.org/licenses/by-nc-sa/3.0/cn/)发布","markdown":true,"update_format":"YYYY-MM-DD HH:mm:ss","update_label":"此页面修订于: "},"search":{},"localized-footer":{"filename":"FOOTER.md","hline":"true"},"lunr":{"maxIndexSize":1000000,"ignoreSpecialCharacters":false},"fontsettings":{"theme":"white","family":"sans","size":2},"highlight":{},"sharing":{"facebook":true,"twitter":true,"google":false,"weibo":false,"instapaper":false,"vk":false,"all":["facebook","google","twitter","weibo","instapaper"]},"theme-default":{"styles":{"website":"styles/website.css","pdf":"styles/pdf.css","epub":"styles/epub.css","mobi":"styles/mobi.css","ebook":"styles/ebook.css","print":"styles/print.css"},"showLevel":false}},"structure":{"langs":"LANGS.md","readme":"README.md","glossary":"GLOSSARY.md","summary":"SUMMARY.md"},"pdf":{"pageNumbers":true,"fontSize":12,"fontFamily":"Arial","paperSize":"a4","chapterMark":"pagebreak","pageBreaksBefore":"/","margin":{"right":62,"left":62,"top":56,"bottom":56}},"styles":{"website":"styles.css","pdf":"styles.css"}},"file":{"path":"4.2.md","mtime":"2021-04-19T01:48:46.741Z","type":"markdown"},"gitbook":{"version":"3.2.3","time":"2021-04-19T01:48:56.435Z"},"basePath":".","book":{"language":""}});
});
</script>
</div>
<script src="gitbook/gitbook.js"></script>
<script src="gitbook/theme.js"></script>