前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >《操作系统导论》疑惑解答

《操作系统导论》疑惑解答

作者头像
小柔
发布2024-07-24 08:18:16
750
发布2024-07-24 08:18:16
举报
文章被收录于专栏:小柔博客园

内存相关

分段的内存管理方式有什么缺点为什么出现了分页的管理方式

分段的内存管理方式主要存在以下缺点:

  1. 外部碎片:当段的大小变化时,会在内存中产生一些难以利用的小空闲区域,这些区域被称为外部碎片。外部碎片的存在降低了内存的利用率。
  2. 需要额外的数据结构来记录段的信息,如段的起始地址、长度等,这增加了系统的开销。
  3. 分段管理不支持虚拟内存,因为每个段都需要连续的物理内存空间。

分页的管理方式出现的原因主要是为了解决分段管理方式的缺点,并提供更好的内存管理特性。分页管理的主要优点包括:

  1. 提高了内存利用率:分页管理能够将物理内存划分为固定大小的页面,并根据进程的需要分配不同数量的页面,避免了外部碎片的产生。
  2. 支持虚拟内存:分页管理允许进程使用比物理内存更大的虚拟内存,通过将虚拟地址空间划分为页面,并将页面映射到物理内存的不同位置,实现了虚拟内存的支持。
  3. 简化了内存管理:分页管理使用页表来记录每个页面在物理内存中的位置,简化了内存管理的复杂性。

总之,分页管理方式的出现主要是为了克服分段管理方式的缺点,提供更好的内存管理特性和更高的内存利用率。

现在主流的 操作系统都是用的分页的内存管理方式,但是为什么elf文件格式还有大部分的可执行程序文件还是用段来区分程序里不同的数据呢,那是不是地址访问的过程是:虚拟地址自带段标识 然后找到对应的段基址寄存器里面存储的是对应页表里面页基址的物理内存地址,然后加上对应的偏移地址找到对应的页基址+偏移量转换为物理内存地址进行访问

根据文心一言的回答来看,事实确实如此,首先通过段表找到页表,在通过页表找到物理内存地址

在现代操作系统中,确实分页是主导的内存管理方式,因为分页提供了内存的高效利用、保护和虚拟内存支持。然而,尽管内存管理在底层使用分页,但很多高级编程概念,包括可执行文件格式如ELF (Executable and Linkable Format),仍然使用“段”(segments)来组织代码和数据。

这里有几个原因:

  1. 兼容性:早期的操作系统和编程语言设计使用了分段的概念,因此很多现有的工具和约定都基于这个概念。为了兼容这些现有的工具和约定,现代操作系统和文件格式仍然支持段的概念。
  2. 简化编程:对于程序员来说,使用段(如代码段、数据段、BSS段等)可以简化程序的组织和链接过程。这些段通常对应于程序的不同逻辑部分,使得编程和调试更为直观。
  3. 加载器简化:操作系统的加载器(loader)在加载可执行文件时,会根据文件中的段信息来映射到内存中的相应位置。使用段可以减少加载器的复杂性。
  4. 虚拟地址到物理地址的转换:虽然操作系统内部使用分页来管理内存,但在虚拟地址到物理地址的转换过程中,段信息仍然起着作用。

地址访问过程:操作系统会维护一个段表(segment table),每个段在段表中有一个条目,条目中包含了该段的基地址和界限。当CPU进行地址转换时,它首先会查找段表,确定虚拟地址所在的段,然后使用该段的基地址和偏移量来查找页表。页表中的条目则指向实际的物理内存页。

所以,地址访问的过程大致如下:

  • CPU生成一个虚拟地址,这个地址通常包含段标识符和段内的偏移量。
  • 操作系统根据段标识符在段表中查找对应的段条目,获取该段的基地址和界限。
  • CPU使用段基地址和偏移量生成一个“线性地址”(也被称为有效地址或虚拟地址)。
  • 这个线性地址随后被送到MMU(内存管理单元),MMU再根据页表将其转换为物理地址。如果线性地址位于某个页的范围内,MMU就会查找该页的页表条目,从而得到对应的物理内存页基址。
  • 最后,物理内存页基址加上线性地址中的页内偏移量,就得到了最终要访问的物理内存地址。

这种“段+页”的组织方式允许操作系统在高层使用更直观的段来组织程序,同时在底层使用分页来实现高效的内存管理和保护。

什么是重定位表

重定位表的用途是在程序加载到内存时,修正程序中符号引用的地址。 换句话说,它是用来确保程序中的所有符号引用(如函数调用、变量访问等)都能正确指向它们在内存中的实际位置。

在编译和链接过程中,编译器和链接器会生成符号表和重定位表。符号表存储了程序中定义和引用的符号(如函数和变量)的信息,而重定位表则记录了符号引用需要修正的地址信息。

当程序加载到内存时,操作系统使用加载器来加载可执行文件,并查看重定位表。**加载器会根据重定位表中的信息,修正符号引用的地址,使得它们指向正确的内存位置。 **这样,当程序执行时,就可以通过修正后的虚拟地址来访问符号了。

重定位的过程是确保程序在不同环境下(如不同的内存布局或不同的操作系统)都能正确运行的关键步骤之一。通过重定位,程序可以在不同的环境中适应不同的内存布局和符号地址,从而实现可移植性和灵活性。

通过符号重定向,我们可以**将一个符号的引用链接到另一个符号上。 这样,当程序执行时,会根据重定向的规则跳转到正确的符号上。 **符号重定向通常用于实现动态库的加载和卸载、不同程序之间的接口转换等功能。

符号表的重定位是如何进行匹配的

在链接阶段,链接器会**将目标文件中的符号引用与实际符号进行匹配,以实现正确的链接。 **匹配的信息主要包括以下方面:

  1. 符号名称:链接器会根据符号表中的符号名称进行匹配,确保引用的符号与实际符号具有相同的名称。
  2. 符号类型:链接器还会检查符号的类型的匹配性。例如,一个函数引用的符号应该与实际函数的类型匹配,包括参数个数、参数类型和返回值类型等。
  3. 符号属性:符号表中的符号属性包括符号的地址、大小、存储方式等信息。链接器会根据这些属性进行匹配,确保引用的符号与实际符号具有相同的属性。

在AOT静态链接过程中,由于链接发生在编译阶段,因此无法在运行时确定符号的具体地址。因此,链接器会根据符号表中的符号属性生成符号的虚拟地址(Virtual Address)。

虚拟地址是指在程序执行时,程序使用的地址空间中的假地址,它与实际的物理内存地址并不一致。在程序加载到内存中后,操作系统会将虚拟地址映射到实际的物理地址,从而实现正确的内存访问。

符号表是不是记录了符号的虚拟内存地址

在符号表中,每个符号都有一个对应的标识符虚拟地址。这个虚拟地址是符号在程序中的位置信息,而不是真实的内存地址。在程序运行时,动态链接器会使用这个虚拟地址来找到符号的定义。

**一旦找到了符号的定义,动态链接器就会将符号引用转换为真实的内存地址。 **这个过程是通过将虚拟地址转换为物理地址来实现的。物理地址是程序在内存中的真实位置信息。

因此,你的理解是正确的:符号-》标识符虚拟地址-》内存地址。这是动态链接过程中符号解析的基本过程

如何理解符号表和重定位表

当然可以。让我们通过一个简单的例子来理解符号表、重定位表以及它们如何工作。

假设我们有两个源文件: main.c utils.c

main.c 的内容如下:

代码语言:javascript
复制
#include <stdio.h>
extern int add(int a, int b); // 声明在 utils.c 中定义的函数

int main() {
    int sum = add(2, 3);
    printf("The sum is: %d\n", sum);
    return 0;
}

utils.c 的内容如下:

代码语言:javascript
复制
int add(int a, int b) {
    return a + b;
}

现在,让我们看看编译器和链接器是如何处理这些文件的:

  1. ****编译阶段
    • 编译器编译 main.c 生成 main.o (目标文件),并在符号表中记录 add 函数的引用,因为它是在其他文件中定义的。
    • 同样地,编译器编译 utils.c 生成 utils.o ,并在符号表中记录 add 函数的定义。
  1. ****链接阶段
    • 链接器将 main.o utils.o 链接成一个可执行文件。
    • 链接器查看 main.o 的符号表,发现 add 函数的引用,然后查看 utils.o 的符号表,找到 add 函数的定义。
    • 链接器生成重定位表,其中包含将 main.o 中对 add 函数的引用修正为 utils.o add 函数实际地址的信息。
  1. ****加载阶段
    • 当程序加载到内存中时,操作系统使用加载器来加载可执行文件。
    • 加载器查看重定位表,并将 main.o 中对 add 函数的引用修正为 add 函数在内存中的实际虚拟地址。
  1. ****执行阶段
    • 程序开始执行,当 main 函数调用 add 函数时,它使用修正后的虚拟地址来访问 add 函数。
    • MMU(内存管理单元)负责将虚拟地址转换为物理地址,以便从物理内存中读取或写入数据。

在这个例子中,

重定位表包含了将 main.o 中对 add 函数的引用修正为 add 函数在 utils.o 中的实际虚拟内存地址的信息。这样,当程序执行时,就可以正确地调用 add 函数了。

编译链接重定位的相关流程

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-07-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 内存相关
    • 分段的内存管理方式有什么缺点为什么出现了分页的管理方式
      • 现在主流的 操作系统都是用的分页的内存管理方式,但是为什么elf文件格式还有大部分的可执行程序文件还是用段来区分程序里不同的数据呢,那是不是地址访问的过程是:虚拟地址自带段标识 然后找到对应的段基址寄存器里面存储的是对应页表里面页基址的物理内存地址,然后加上对应的偏移地址找到对应的页基址+偏移量转换为物理内存地址进行访问
        • 什么是重定位表
          • 符号表的重定位是如何进行匹配的
          • 符号表是不是记录了符号的虚拟内存地址
        • 如何理解符号表和重定位表
          • 编译链接重定位的相关流程
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档