0 00:00:00,000 --> 00:00:06,920 1 00:00:07,200 --> 00:00:11,680 接下来我们讨论段式存储管理 2 00:00:11,760 --> 00:00:13,320 那在段式存储管理里头 3 00:00:13,440 --> 00:00:15,440 我们会来说明 4 00:00:15,560 --> 00:00:19,040 段的地址空间是如何来组织的 5 00:00:19,120 --> 00:00:21,480 然后在段式存储管理当中 6 00:00:21,600 --> 00:00:26,200 我的内存访问是如何进行的 7 00:00:26,240 --> 00:00:28,520 8 00:00:28,600 --> 00:00:31,080 那在段式存储管理当中 9 00:00:31,120 --> 00:00:32,920 我们把进程的地址空间 10 00:00:32,960 --> 00:00:35,880 看成由若干个段组成的 11 00:00:35,920 --> 00:00:37,440 每一个段 在这里 12 00:00:37,480 --> 00:00:38,480 是给出了一些实例 13 00:00:38,520 --> 00:00:41,040 你比如说我的程序 14 00:00:41,080 --> 00:00:43,680 有主程序有子模块 15 00:00:43,720 --> 00:00:45,680 那各个子模块我可以看成是 16 00:00:45,720 --> 00:00:48,640 相对独立的一个段 17 00:00:48,680 --> 00:00:50,960 主代码呢我看成是一个段 18 00:00:51,000 --> 00:00:53,040 然后我的公共库 19 00:00:53,080 --> 00:00:55,160 可以看成是另外一个段 20 00:00:55,200 --> 00:00:58,520 这几个呢都是代码 21 00:00:58,560 --> 00:01:01,000 同时还有一些堆 22 00:01:01,040 --> 00:01:03,960 初始化的数据 堆栈 23 00:01:04,000 --> 00:01:07,920 符号表 这样一些数据段 24 00:01:07,960 --> 00:01:09,240 好 那在这里头 25 00:01:09,280 --> 00:01:11,600 我们把它看成是一个 26 00:01:11,640 --> 00:01:13,240 组织成一个段地址空间的话 27 00:01:13,280 --> 00:01:15,960 实际这时我们希望是能够达到 28 00:01:16,000 --> 00:01:18,320 把进程的地址空间能够 29 00:01:18,360 --> 00:01:20,720 以更精细 更灵活的方式 30 00:01:20,760 --> 00:01:22,600 把它分离开 31 00:01:22,640 --> 00:01:23,600 分离开之后呢 32 00:01:23,640 --> 00:01:26,280 我可以实现更好的共享 33 00:01:26,320 --> 00:01:27,640 34 00:01:27,840 --> 00:01:31,640 好 有了上面关于段地址空间的描述 35 00:01:31,800 --> 00:01:33,000 这时候呢我们就可以 36 00:01:33,080 --> 00:01:35,000 把逻辑地址空间 37 00:01:35,040 --> 00:01:40,200 转换成一个不连续的二维结构 38 00:01:40,240 --> 00:01:41,640 那在这里头呢我们看到 39 00:01:41,680 --> 00:01:44,760 我们把代码分成了几个部分 40 00:01:44,800 --> 00:01:47,720 两个部分 数据 堆栈 41 00:01:47,760 --> 00:01:50,160 堆 那这几个部分呢 42 00:01:50,200 --> 00:01:51,320 各个部分内部呢 43 00:01:51,360 --> 00:01:52,440 它是需要连续的 44 00:01:52,480 --> 00:01:54,560 我会用它的偏移呢来进行访问 45 00:01:54,600 --> 00:01:58,960 但各个部分之间 我们很少有跨越 46 00:01:59,000 --> 00:02:02,920 从一个段访问另一个段的这种情况 47 00:02:02,960 --> 00:02:04,160 以一个段的基址 48 00:02:04,200 --> 00:02:06,760 去访问另一个段的这种情况 49 00:02:06,800 --> 00:02:08,080 好 有了这个讨论之后 50 00:02:08,120 --> 00:02:12,320 我们就可以把段地址空间的逻辑视图 51 00:02:12,360 --> 00:02:15,080 转换成一个这样的结构 52 00:02:15,120 --> 00:02:17,120 那到物理地址空间里头呢 53 00:02:17,160 --> 00:02:19,040 它就可以是不连续的 54 00:02:19,080 --> 00:02:21,880 那由于各个段之间我们是相对可以 55 00:02:21,920 --> 00:02:23,960 把它很好地分离开 那这个里头呢 56 00:02:24,000 --> 00:02:25,000 这种不连续呢 57 00:02:25,040 --> 00:02:27,080 对我们的访问带来的影响 58 00:02:27,120 --> 00:02:29,280 是相对来说比较小的 59 00:02:29,320 --> 00:02:31,200 好 有了这种概念之后 60 00:02:31,240 --> 00:02:32,680 那么这时候我们来看 61 00:02:32,720 --> 00:02:34,520 我的访问过程是什么样的 62 00:02:34,560 --> 00:02:35,920 首先有了这一段之后 63 00:02:35,960 --> 00:02:38,320 我们可以把它理解为段呢实际上是 64 00:02:38,360 --> 00:02:39,360 每个段是什么 65 00:02:39,400 --> 00:02:43,040 每个段是访问方式和存储数据 66 00:02:43,080 --> 00:02:44,920 存储的到底是什么数据 67 00:02:44,960 --> 00:02:46,640 到底用什么样的方式在访问 68 00:02:46,680 --> 00:02:50,000 这个相对一致的一段地址空间 69 00:02:50,040 --> 00:02:53,040 好 这一段呢我要求它是连续的 70 00:02:53,080 --> 00:02:54,440 好 有了这个之后 71 00:02:54,480 --> 00:02:57,400 那我们说如果每一个段呢 72 00:02:57,440 --> 00:03:00,680 对应到一块连续的内存块 73 00:03:00,720 --> 00:03:03,080 然后若干个段组成了 74 00:03:03,120 --> 00:03:05,840 进程的逻辑地址空间 75 00:03:05,880 --> 00:03:07,360 有了这个之后 76 00:03:07,400 --> 00:03:09,800 我们再来看段的访问是什么 77 00:03:09,840 --> 00:03:11,360 我就会把逻辑地址 78 00:03:11,400 --> 00:03:13,120 分成一个二元组 79 00:03:13,160 --> 00:03:16,720 段号和段内偏移 80 00:03:16,760 --> 00:03:19,200 那原来的地址 81 00:03:19,240 --> 00:03:23,160 我们是一个连续的若干位 82 00:03:23,200 --> 00:03:26,800 好 现在呢 在段式地址空间里呢 83 00:03:26,840 --> 00:03:33,960 我们把它分成两段 段号和段内偏移 84 00:03:34,000 --> 00:03:34,920 转化过来之后呢 85 00:03:34,960 --> 00:03:36,200 我们看到的逻辑结构呢 86 00:03:36,240 --> 00:03:39,160 变成是段号和段内偏移 87 00:03:39,200 --> 00:03:41,000 这个时候分开之后 88 00:03:41,040 --> 00:03:42,240 那我再访问的时候 89 00:03:42,280 --> 00:03:45,800 我必须把它转换成原来的地址 90 00:03:45,840 --> 00:03:48,960 好 有了这种地址的划分之后 91 00:03:49,000 --> 00:03:52,000 那它的访问过程会变成什么样子呢 92 00:03:52,040 --> 00:03:56,120 好 这是进程的地址空间 93 00:03:56,160 --> 00:03:58,160 这是物理的地址空间 94 00:03:58,200 --> 00:04:00,680 然后程序在CPU上执行 95 00:04:00,720 --> 00:04:02,400 它要访问一个存储单元的时候 96 00:04:02,440 --> 00:04:04,520 首先是它的逻辑地址 97 00:04:04,560 --> 00:04:06,800 在段地址空间里头 98 00:04:06,840 --> 00:04:08,920 我们把它分成两段 99 00:04:08,960 --> 00:04:11,400 段号和段内偏移 100 00:04:11,440 --> 00:04:13,560 这个首先用段号 101 00:04:13,600 --> 00:04:16,880 我们去查进程的段表 102 00:04:16,920 --> 00:04:17,840 那若干个段 103 00:04:17,880 --> 00:04:19,840 所有的段在这里都有一项 104 00:04:19,880 --> 00:04:22,720 每一项对应一个段描述符 105 00:04:22,760 --> 00:04:24,960 这里基本内容是 106 00:04:25,000 --> 00:04:28,040 段的起始地址和它的长度 107 00:04:28,080 --> 00:04:29,360 那这里的内容呢 108 00:04:29,400 --> 00:04:31,840 我们是可以用操作系统的软件 109 00:04:31,880 --> 00:04:33,480 来对它进行控制的 110 00:04:33,520 --> 00:04:35,000 也就是说我在这里头 111 00:04:35,040 --> 00:04:36,400 每个段在什么位置呢 112 00:04:36,440 --> 00:04:38,080 它的相关信息我是由 113 00:04:38,120 --> 00:04:39,600 操作系统可以控制的 114 00:04:39,640 --> 00:04:41,200 好 有了这里头 115 00:04:41,240 --> 00:04:43,160 我可以得到段的长度之后 116 00:04:43,200 --> 00:04:45,080 那硬件在里做什么呢 117 00:04:45,120 --> 00:04:48,400 存储管理单元MMU 118 00:04:48,440 --> 00:04:50,760 它就会把这个长度和你的偏移 119 00:04:50,800 --> 00:04:53,240 取出来两个做比较 120 00:04:53,280 --> 00:04:55,760 看看是不是越界 121 00:04:55,800 --> 00:04:57,000 如果越界 那这时候 122 00:04:57,040 --> 00:04:58,320 就会出异常 123 00:04:58,360 --> 00:05:00,520 如果说 124 00:05:00,720 --> 00:05:02,800 你的偏移是小于它的长度的 125 00:05:02,840 --> 00:05:04,320 那这是一个合法的访问 126 00:05:04,360 --> 00:05:08,480 然后在MMU里头呢再利用段基址和 127 00:05:08,520 --> 00:05:10,320 你的偏移两个加到一起 128 00:05:10,360 --> 00:05:13,400 就可以找到你实际要访问的内容了 129 00:05:13,440 --> 00:05:14,840 有了这个访问之后 130 00:05:14,880 --> 00:05:17,440 那我们基于段的这种机制 131 00:05:17,480 --> 00:05:18,480 就可以工作起来了 132 00:05:18,520 --> 00:05:18,560