目录
从根本上来说,计算机里面运转的程序有两种:管理计算机的程序和使用计算机的程序
关于内存的地方,分页那里
你理解题目中初始地址的含义(初址)吗?
其实就是说吧,
要写全地址,比如二进制,或者就是那个直接写数量大小那里,真的是喵喵蛙(题目一定要看清)
之后又一个很妙的地方,就是哪里一定要看清呢
就是关于那个scan算法,后面I/O输入输出那里,很6,
那个一个字符串序列是被全能全知的,所以说,要一个全知的视角来看待这个问题
然后就是在往前一点的问题
先进先出算法、最佳页面置换,缺页啥的,要看到底有没有预先存储,不然关于缺页的问题其实会吃大亏。
笑死了,很烦。
图11-5b分配模式还有另外一个好处:可以将输入输出和内存访问统一起来。即将输入输出设备里面的寄存 器或其他存储媒介编入内存地址(在用户程序地址之上),使得访问输入输出设备如同访问内存一样。这种 输入输出称为内存映射的输入输出。如果要访问的地址高于RAM的最高地址,则属于I/O操作,否则属于正 常内存操作。
单道编程的内存管理
最简单的内存管理是单道程序下的内存管理。在单道编程环境下,整个内存里面只有两个程序:一个是用户 程序,另一个是操作系统。由于只有一个用户程序,而操作系统所占用的内存空间是恒定的,我们可以将用 户程序总是加载到同一个内存地址上。即用户程序永远从同一个地方开始执行。在这种管理方式下,操作系 统永远跳转到同一个地方来启动用户程序。这样,用户程序里面的地址都可以事先计算出来,即在程序运行 前就计算出所有的物理地址。这种在运行前即将物理地址计算好的方式叫做静态地址翻译。
11.6.1 固定分区的多道编程内存管理
在这种模式下,当一个新的程序想要运行,必须排在一个共同的队列里等待。当有空闲分区时,才能进行加 载。由于程序大小和分区大小不一定匹配,有可能形成一个小程序占用一个大分区的情况,从而造成内存里 虽然有小分区闲置,但无法加载大程序的情况。如果在前面加载小程序时考虑到这一点,可以将小程序加载 到小分区里,就不会出现这种情况(或者说至少降低这种情况发生的概率)。这样,我们就想到也许可以采 用多个队列,即给每个分区一个队列。程序按照大小排在相应的队列里,如图11-9所示。
这样不同的程序有不同的对,就像在社会中不同的社会阶层有不同的待遇一样。当然,这种方式也有缺点, 就是如果还有空闲分区,但等待的程序不在该分区的等待队列上,就将造成有空间而不能运行程序的尴尬处 境
11.6.2 地址翻译的方法
在多道编程环境下,由于程序加载到内存的地址不是固定的(有多个地方可加载),我们必须对地址进行翻 译。那么如何来翻译呢? 我们看到,一个程序是加载到内存里事先划分好的某片区域,而且该程序是整个加载进去。该程序里面的虚 地址只要加上其所占区域的起始地址即可获得物理地址。因此,我们的翻译过程非常简单: 物理地址=虚拟地址+程序所在区域的起始地址程序所在区域的起始地址称为(程序)基址。
另外,由于有多个程序在内存空间中,我们需要进行地址保护。由于每个程序占用连续的一片内存空间,因 此只要其访问的地址不超出该片连续空间,则为合法访问。因此,地址保护也变得非常简单,只要访问的地 址满足下列条件即为合法访问: 程序所在区域的起始地址≤有效地址≤程序所在区域的起始地址+程序长度由此可见,我们只需要设置两个端 值:基址和极限,即可达到地址翻译和地址保护的目的。这两个端值可以由两个寄存器来存放,分别称为基 址寄存器和极限寄存器。在固定分区下,基址就是固定内存分区中各个区域的起始内存地址,而极限则是所 加载程序的长度(记住,不是内存各个分区的上限)。
请问“如何实现单道编程的内存管理”
单道编程的内存管理是一种简单的内存管理方式,通常用于早期的计算机系统。在单道编程中,整个内存空间被划分为一个单独的作业区域,只有一个程序在内存中运行。
下面是实现单道编程的内存管理的一般步骤:
-
内存分配:将整个内存空间划分为一个单独的作业区域,用于存放单个程序的指令和数据。通常,这个作业区域的大小是固定的,与程序的大小相匹配。
-
加载程序:将程序的指令和数据加载到作业区域中的适当位置。这包括将程序从外部存储器(如磁盘)读入到内存中,并将其放置在作业区域的起始位置。
-
内存保护:为了确保单道程序的安全性和稳定性,需要实施内存保护机制,防止程序越界访问其他程序或系统关键数据。这可以通过硬件或软件的方式实现,例如使用基址寄存器和界限寄存器来限制程序的内存访问范围。
-
执行程序:通过将程序的执行起点设置为作业区域的起始地址,开始执行加载到内存中的程序。在程序执行期间,它可以访问作业区域中的指令和数据,进行计算和操作。
-
完成程序:当程序执行完成或终止时,释放作业区域的内存空间,以便其他程序可以使用。
需要注意的是,单道编程的内存管理是一种简化的方式,不支持多道程序同时运行和内存共享。每次只能加载一个程序,并且整个内存空间都被分配给该程序。这种方式适用于资源受限的环境,但在现代操作系统中已经被更灵活的内存管理方式所取代。
固定地址的内存管理
这样不同的程序有不同的对,就像在社会中不同的社会阶层有不同的待遇一样。当然,这种方式也有缺点, 就是如果还有空闲分区,但等待的程序不在该分区的等待队列上,就将造成有空间而不能运行程序的尴尬处 境
请问“操作系统应该被存储到哪个位置更加合理呢?”
操作系统的存储位置应该是在非易失性存储器中,如硬盘或固态硬盘 (SSD)。这是因为操作系统是计算机系统的核心软件,负责管理和控制计算机的硬件资源以及提供各种系统服务。将操作系统存储在非易失性存储器中有以下几个原因:
-
持久性:非易失性存储器是一种永久性存储介质,它可以在断电后保留数据。这使得操作系统能够在计算机重新启动时从存储设备加载并恢复到运行状态。
-
存储容量和速度:非易失性存储器通常具有较大的存储容量,并且具备较快的读取速度。操作系统需要占用相当大的存储空间,以存储其核心组件、驱动程序和系统文件。而非易失性存储器能够提供足够的空间和较快的读取速度来满足操作系统的需求。
-
可靠性:非易失性存储器通常具有较高的可靠性和数据持久性。相对于易失性存储器如随机访问存储器 (RAM),非易失性存储器在断电或系统故障时不会丢失数据,这对于操作系统的稳定性和可靠性非常重要。
需要注意的是,操作系统在运行时会被加载到计算机的内存中进行执行。但是,操作系统的源代码、可执行文件和系统文件通常存储在非易失性存储器中,以便在需要时能够进行引导和加载到内存中。
总而言之,将操作系统存储在非易失性存储器中是更合理的选择,以确保持久性、存储容量和速度以及可靠性。
物理地址=虚拟地址+程序所在区域的起始地址程序所在区域的起始地址称为(程序)基址。
介绍一下编译器好吗?
当然!编译器是一种软件工具,用于将高级编程语言(如C、C++、Java等)编写的源代码转换为低级机器语言或字节码,以便计算机能够理解和执行。它是构建软件应用程序的关键组件之一。
以下是编译器的一些主要功能和组成部分:
-
词法分析(Lexical Analysis):编译器首先将源代码分解成一系列词法单元(tokens),例如关键字、标识符、运算符等。这个过程通常涉及扫描源代码并将其分割成词法单元流。
-
语法分析(Syntax Analysis):在语法分析阶段,编译器使用词法单元流构建语法树(Syntax Tree)或抽象语法树(Abstract Syntax Tree),以验证源代码是否符合语法规则。它检查语法错误并捕获代码结构。
-
语义分析(Semantic Analysis):语义分析阶段对语法正确的代码进行进一步的分析。它检查变量声明和使用、类型匹配、函数调用等语义规则,并生成符号表用于后续的类型检查和代码生成。
-
中间代码生成(Intermediate Code Generation):在这一阶段,编译器生成中间代码,它是一种抽象的、与特定机器无关的表示形式。中间代码通常比源代码更容易进行优化和转换,并且可以被用于生成不同的目标代码。
-
优化(Optimization):编译器的优化阶段旨在改进生成的目标代码的质量和性能。它通过识别和应用各种优化技术来改善程序的执行效率,如常量折叠、循环展开、代码消除等。
-
目标代码生成(Code Generation):在目标代码生成阶段,编译器将中间代码转换为特定目标机器的机器代码或可执行文件。这个过程包括寄存器分配、指令选择、内存管理等。
编译器通常由多个模块组成,每个模块负责不同的任务。它们协同工作以完成源代码到目标代码的转换过程。编译器的目标是生成高效、可执行的代码,并提供有关代码错误和警告的反馈信息,以帮助开发人员改进程序。
总而言之,编译器在软件开发过程中起到了至关重要的作用,它将高级语言代码转换为计算机可以理解和执行的形式,为程序员提供了更高的抽象层次和开发效率。
一个程序可以一半放在磁盘上,一半放在内存上
非固定分区的思想很简单:除了划分给操作系统的空间外,其余的内存空间是作为一个整体存在的。当一个 程序需要占用内存空间时,就在该片空间里面分出一个大小刚刚满足程序所需的空间;再来一个程序,则在 剩下的空间里面再这样分出一块来。在这种模式下,一个程序可以加载到任何地方,也可以和物理内存一样 大。例如,一开始内存里只有操作系统。这时候进程A来了,我们从最底下分出一片与进程A大小一样的内 存空间;然后进程B来了,我们在进程A上面的大片空间分出一片与进程B大小一样的内存空间;然后进程C 来了,我们就在进程B上面再分出一片与C大小一样的内存空间。这样,进程A、进程B、进程C的起始地址 都不是固定的,如图11-11所示。
那还有没有别的办法呢?有,给该程序换一个空间。就是当一个程序所占空间不够时,我们将其倒到磁盘 上,再加载到一片更大的内存空间。这种将程序倒到磁盘上,再加载进内存的管理方式称为交换 (swap)。
交换的含义
交换就是将一个进程从内存倒到磁盘上,再将其从磁盘上加载到内存中的过程。这种交换的主要目的是为程 序找到一片更大的空间,从而防止一个程序因空间不够而崩溃。交换的另一目的,是实现进程切换,也就是 将一个程序暂停一会儿,让另一个程序运行。不过使用交换进行进程切换的成本颇高,一般不这样做。
介绍一下操作系统的基址和极限
在操作系统中,基址(Base Address)和极限(Limit)是用于内存分段和内存保护的概念。
基址是指内存段的起始地址,表示一个段在内存中的起始位置。极限是指内存段的长度或大小,表示一个段在内存中的结束位置。基址和极限通常以一对的方式存储在硬件的段寄存器中。
通过使用基址和极限,操作系统可以实现内存的分段和保护,以提供更好的内存管理和安全性。
内存分段是一种内存管理技术,将内存划分为若干个连续的段,每个段有唯一的标识符和长度。每个段可以包含一组相关的数据或指令。通过基址和极限,操作系统可以确定每个段在内存中的位置和大小,以便在程序执行时进行正确的地址转换。
内存保护是操作系统的重要功能之一。通过设置合适的基址和极限,可以限制程序对内存的访问范围,防止程序越界访问其他段的内存,提高系统的安全性和稳定性。当程序访问超出其所分配的段空间时,会触发异常或中断,由操作系统进行处理。
基址和极限的组合提供了一种机制,使操作系统能够对内存进行合理的管理、隔离和保护。通过动态设置不同的基址和极限,操作系统可以为每个进程分配独立的内存空间,并确保它们之间的互不干扰。
需要注意的是,现代操作系统往往采用分页机制(Page-based Memory Management)或者分段与分页相结合的方式来管理内存,而基址和极限的概念在这种情况下可能并不直接适用。这些概念仍然具有历史意义,并对理解早期操作系统和底层硬件的工作原理很有帮助。
关于交换,其实是一种不让进程白白占用资源的一种方式,
因为它大,不能够进行计算,那就放在主存里面没有任何意义了,
那就把它存到磁盘中去,
之后,等到主存有能够容下它的空间之后,再把它放进去。