/
lecture-06-5.srt
596 lines (445 loc) · 10.5 KB
/
lecture-06-5.srt
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
0
00:00:00,000 --> 00:00:06,400
1
00:00:06,600 --> 00:00:11,400
接下来我们讲快表和多级页表
2
00:00:11,440 --> 00:00:12,600
那在刚才我们说
3
00:00:12,640 --> 00:00:14,640
快表是利用缓存的机制
4
00:00:14,680 --> 00:00:17,040
来减少对内存的访问
5
00:00:17,080 --> 00:00:20,720
而多级页表 是通过间接引用的方式
6
00:00:20,760 --> 00:00:23,360
来减少页表的长度
7
00:00:23,400 --> 00:00:25,560
那么它们具体怎么做的呢
8
00:00:25,600 --> 00:00:30,040
快表实际上就是把近期访问过的页表项
9
00:00:30,080 --> 00:00:31,720
缓存到CPU里头
10
00:00:31,760 --> 00:00:35,240
底下是我们在前面没有使用快表的时候
11
00:00:35,280 --> 00:00:39,240
正常情况下 你获取物理页号的过程
12
00:00:39,280 --> 00:00:43,520
逻辑页号在内存当中去查页表
13
00:00:43,560 --> 00:00:49,000
找到物理页号 然后得到物理地址
14
00:00:49,040 --> 00:00:51,880
那现在在这里缓存之后怎么办呢
15
00:00:51,920 --> 00:00:55,400
我在CPU里头 加上一组关联存储器
16
00:00:55,440 --> 00:00:56,840
关联存储器是什么呢
17
00:00:56,880 --> 00:00:59,160
关联存储器是说我这里有一个key
18
00:00:59,200 --> 00:01:01,800
我进来之后它可以并行的
19
00:01:01,840 --> 00:01:04,920
同时查所有的这些表项
20
00:01:04,960 --> 00:01:07,960
有匹配的 把匹配的找出来
21
00:01:08,000 --> 00:01:08,880
那你说这里
22
00:01:08,920 --> 00:01:12,120
原先在内存里访问一次你觉得费事
23
00:01:12,160 --> 00:01:14,160
到这里来你访问这么多次
24
00:01:14,200 --> 00:01:15,600
它就不费事吗
25
00:01:15,640 --> 00:01:16,440
实际上在这里头呢
26
00:01:16,480 --> 00:01:18,240
由于是在CPU里头
27
00:01:18,280 --> 00:01:19,720
它的速度会很快
28
00:01:19,760 --> 00:01:23,440
当然由于它的速度快 成本高 功耗大
29
00:01:23,480 --> 00:01:25,440
所以这个地方不能做的很大
30
00:01:25,480 --> 00:01:27,120
如果说匹配得上
31
00:01:27,160 --> 00:01:30,120
那这时候呢它直接得到它的物理页号
32
00:01:30,160 --> 00:01:32,480
也就相当于我逻辑页号作为key
33
00:01:32,520 --> 00:01:34,000
找到它的物理页号
34
00:01:34,040 --> 00:01:35,720
那我就得到你的物理页号
35
00:01:35,760 --> 00:01:38,080
这就不需要到内存当中访问了
36
00:01:38,120 --> 00:01:40,000
如果说在这里头你找的时候
37
00:01:40,040 --> 00:01:41,640
因为你这里容量很小
38
00:01:41,680 --> 00:01:43,720
肯定没有办法把整个页表
39
00:01:43,760 --> 00:01:46,600
全部装到这个CPU里头去
40
00:01:46,640 --> 00:01:48,240
好 那这些有不命中的
41
00:01:48,280 --> 00:01:49,880
那不命中的时候呢
42
00:01:49,920 --> 00:01:51,240
它就会从这儿
43
00:01:51,280 --> 00:01:54,640
你得再去找内存当中的页表
44
00:01:54,680 --> 00:01:56,560
这时候你只能是两次访问了
45
00:01:56,600 --> 00:01:58,080
好 找到这个页表之后呢
46
00:01:58,120 --> 00:02:01,240
我得到它的页帧号
47
00:02:01,280 --> 00:02:03,160
同时我把这个内容
48
00:02:03,200 --> 00:02:06,800
再缓存到CPU里的快表里头去
49
00:02:06,840 --> 00:02:10,840
下次再访问这一页里的数据的时候
50
00:02:10,880 --> 00:02:13,680
你就不必要再去访问内存了
51
00:02:13,720 --> 00:02:15,200
好 如果说我们在这里头
52
00:02:15,240 --> 00:02:19,760
99%的访问我都是在这个TLB里
53
00:02:19,800 --> 00:02:21,120
快表里命中的
54
00:02:21,160 --> 00:02:23,720
那只有一次1%
55
00:02:23,760 --> 00:02:26,640
是要到物理内存当中去查页表的
56
00:02:26,680 --> 00:02:29,560
这时我们的性能就能大幅度提高
57
00:02:29,600 --> 00:02:32,840
这是快表的基本原理
58
00:02:32,880 --> 00:02:35,680
好 接下来我们介绍多级页表
59
00:02:35,720 --> 00:02:37,880
多级页表是通过间接引用
60
00:02:37,920 --> 00:02:41,680
将页号分成若干级
61
00:02:41,720 --> 00:02:42,800
比如说在这里头
62
00:02:42,840 --> 00:02:46,400
我们原来的逻辑地址的格式
63
00:02:46,440 --> 00:02:48,400
是页号加页内偏移
64
00:02:48,440 --> 00:02:50,840
现在变成了三级页号
65
00:02:50,880 --> 00:02:54,720
P1 P2 P3 然后再加上页内偏移
66
00:02:54,760 --> 00:02:58,320
和它相对应的 我们的页表呢
67
00:02:58,360 --> 00:03:01,040
也会因此而形成一个树状结构
68
00:03:01,080 --> 00:03:05,080
比如说原来一张大的线性页表
69
00:03:05,120 --> 00:03:07,080
我把它切成若干段
70
00:03:07,120 --> 00:03:08,920
这切到段的个数呢
71
00:03:08,960 --> 00:03:13,080
和你最后一级页表的宽度是一致的
72
00:03:13,120 --> 00:03:17,160
然后它每一个子页表的起头呢
73
00:03:17,200 --> 00:03:20,960
作为上一级页表的物理页号
74
00:03:21,000 --> 00:03:22,480
填到上一级页表当中
75
00:03:22,520 --> 00:03:26,040
在第二级的页表的宽度
76
00:03:26,080 --> 00:03:29,240
和你第二级页号的宽度是一致的
77
00:03:29,280 --> 00:03:32,880
然后再一个 第二级页表的起头
78
00:03:32,920 --> 00:03:36,680
再作为第一级页表项的物理页号
79
00:03:36,720 --> 00:03:38,680
那这时候它的项数
80
00:03:38,720 --> 00:03:41,960
和你第一级页表的宽度是相一致的
81
00:03:42,000 --> 00:03:43,360
在这种情况下
82
00:03:43,400 --> 00:03:49,160
我们要访问相应的物理内存单元
83
00:03:49,200 --> 00:03:50,280
那怎么访问呢
84
00:03:50,320 --> 00:03:53,520
是从第一级查第二级 再查第三级
85
00:03:53,560 --> 00:03:58,000
那这时候我们整个访问次数就是K+1
86
00:03:58,040 --> 00:04:00,040
你这里是三级 那就是四次
87
00:04:00,080 --> 00:04:04,480
具体的访问过程是这样的
88
00:04:04,520 --> 00:04:08,080
第一级作为第一级页表的偏移
89
00:04:08,120 --> 00:04:10,320
找到第二级页表上的起始
90
00:04:10,360 --> 00:04:12,120
第二级页表项
91
00:04:12,160 --> 00:04:13,800
再作为在第二级页表当中的偏移
92
00:04:13,840 --> 00:04:17,720
加在一起找到第三级页表项的
93
00:04:17,760 --> 00:04:19,880
起始页号 物理页号
94
00:04:19,920 --> 00:04:22,680
然后这地方呢 这一页呢
95
00:04:22,720 --> 00:04:25,360
每一页这些页表都是和页相对齐的
96
00:04:25,400 --> 00:04:28,280
所以从这儿呢它就不再有页内偏移
97
00:04:28,320 --> 00:04:29,760
好 然后从这儿找到
98
00:04:29,800 --> 00:04:31,800
最后的 你要实际访问的
99
00:04:31,840 --> 00:04:35,520
那个内存单元的物理页号
100
00:04:35,560 --> 00:04:38,920
再加上最后一次物理内存的访问
101
00:04:38,960 --> 00:04:40,600
那通过这种方式
102
00:04:40,640 --> 00:04:44,880
我们可以有效地减少每一级页表的长度
103
00:04:44,920 --> 00:04:49,480
那如果说 你是所有的页表项都存在的话
104
00:04:49,520 --> 00:04:53,200
你用多级页表实际上对它的存储并没有减少
105
00:04:53,240 --> 00:04:56,080
但实际上 我们实际运行的进程呢
106
00:04:56,120 --> 00:04:59,760
多数并不会用到整个所有的页表
107
00:04:59,800 --> 00:05:03,200
所有的内存地址空间 逻辑地址空间
108
00:05:03,240 --> 00:05:04,320
在这种情况下
109
00:05:04,360 --> 00:05:07,720
我们可以通过各级页表当中的存在位
110
00:05:07,760 --> 00:05:10,480
把那些不存在的给省掉
111
00:05:10,520 --> 00:05:12,400
如果说我在第一级页表里头
112
00:05:12,440 --> 00:05:15,080
有一个下一块区域都不存在的话
113
00:05:15,120 --> 00:05:15,880
那么这样一来
114
00:05:15,920 --> 00:05:19,360
我节省出来的空间就会大幅度增加
115
00:05:19,400 --> 00:05:21,640
我使用的空间就会大幅度减少
116
00:05:21,680 --> 00:05:22,880
好 用这种方式呢
117
00:05:22,920 --> 00:05:24,400
实际上我们使用多级页表呢
118
00:05:24,440 --> 00:05:26,960
可以有效地的减少页表的大小
119
00:05:27,000 --> 00:05:28,600
下面我们通过一个简单的
120
00:05:28,640 --> 00:05:30,560
但是更具体的例子 二级页表
121
00:05:30,600 --> 00:05:32,160
我们看它是怎么做的
122
00:05:32,200 --> 00:05:37,360
这儿呢我们把20位的地址总线
123
00:05:37,400 --> 00:05:39,720
把它切成了三段
124
00:05:39,760 --> 00:05:41,720
0到10 1K
125
00:05:41,760 --> 00:05:45,400
10位作为页内偏移
126
00:05:45,440 --> 00:05:49,920
然后前面切成两个五位的页号
127
00:05:49,960 --> 00:05:51,160
第一级和第二级
128
00:05:51,200 --> 00:05:53,360
那在实际访问的时候是什么样
129
00:05:53,400 --> 00:05:56,040
这是这里头第一级
130
00:05:56,080 --> 00:05:58,280
那第一级页表的起头在哪呢
131
00:05:58,320 --> 00:05:59,920
它是写到固定寄存器里的
132
00:05:59,960 --> 00:06:01,360
在因特尔的CPU上
133
00:06:01,400 --> 00:06:03,360
有一个叫CR3的寄存器
134
00:06:03,400 --> 00:06:07,040
好 在这个寄存器里头存的起始位置
135
00:06:07,080 --> 00:06:09,000
加上你的第一级的页号
136
00:06:09,040 --> 00:06:11,240
作为它的索引 下标
137
00:06:11,280 --> 00:06:12,960
找到相应的页表项
138
00:06:13,000 --> 00:06:16,800
这是第二级页表的起始页号
139
00:06:16,840 --> 00:06:19,000
好 那第二级页表呢
140
00:06:19,040 --> 00:06:20,280
你找这个起始位置
141
00:06:20,320 --> 00:06:22,920
加上第二级的页表号
142
00:06:22,960 --> 00:06:28,240
把它俩找到你的实际的物理页号
143
00:06:28,280 --> 00:06:32,840
那这时候把偏移直接搬过来
144
00:06:32,880 --> 00:06:35,360
那就得到你的物理地址了
145
00:06:35,400 --> 00:06:36,720
有了这样一种做法呢
146
00:06:36,760 --> 00:06:38,280
我们就可以很方便地
147
00:06:38,320 --> 00:06:42,520
利用多级页表减少你整个页表的长度
148
00:06:42,560 --> 00:06:42,600