操作系统真象还原:一些你可能正感到迷惑的问题

2024-05-29 22:04

本文主要是介绍操作系统真象还原:一些你可能正感到迷惑的问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

第0章-一些你可能正感到迷惑的问题

这是我看操作系统真象还原这本书的一些记录:

4 软件是如何访问硬件的

硬件在输入输出上大体分为串行和并行,相应的接口也就是串行接口和并行接口。串行硬件通过串行接口与 CPU 通信,反过来也是, CPU 通过串行接口与串行设备数据传输。并行设备的访问类似,只不过是通过并行接口进行的。

访问外部硬件有两个方式:

  1. 将某个外设的内存映射到一定范围的地址空间中, CPU 通过地址总线访问该内存区域时会落到外设的内存中,这种映射让 CPU 访问外设的内存就如同访问主板上的物理内存一样。例如显存:它被映射到主机物理内存上的低端 1MB 的0xB8000~0xBFFFF。CPU 访问这片内存就是访问显存,住这片内存上写字节便是往屏幕上打印内容。
  2. 外设是通过 IO 接口与 CPU 通信的, CPU 访问外设,就是访问 IO 接口,由 IO 接口将信息传递给另一端的外设,也就是说, CPU 从来不知道有这些设备的存在,它只知道自己操作的 IO 接口。

5 应用程序是什么,和操作系统是如何配到一起工作的

编译器提供了一套库函数,库函数中又有封装的系统调用,这样的代码集合称之为运行库。 C 语言的运行库称为 C 运行库,就是所谓的 CRT。

应用程序加上操作系统提供功能才算是完整的程序

7 内存访问为什么要分段

CPU 采用 “段基址+段内偏移地址”的形式访问内存,就需要专门提供段基址寄存器,这些是 cs 、 ds 、es 等

程序分段又是为了将大内存分成可以访问的小段,通过这样变通的方法便能够访问到所有内存了

8 代码中为什么分为代码段、数据段?

首先,程序不是一定要分段才能运行的,分段只是为了使程序更加优美 。

x86 平台的处理器是必须要用分段机制访问内存的,正因为如此,处理器才提供了段寄存器,用来指定待访问的内存段起始地址。

分段是必然的,只是在平坦模型下,硬件段寄存器中指向的内存段为最大的 4GB ,而在多段模式下编程,硬件段寄存器中指向的内存段大小不一 。

对于在代码中的分段,有的是操作系统做的,有的是程序员自己划分的 。 如果是在多段模型下编程 ,我们必然会在源码中定义多个段,然后需要不断地切换段寄存器所指向的段,这样才能访问到不同段中的数据,所以说,在多段模型下的程序分段是程序员人为划分的。如果是在平坦模型下编程,操作系统将整个 4GB 内存都放在同一个段中,我们就不需要来回切换段寄存器所指向的段 。 对于代码中是否要分段,这取决于操作系统是否在平坦模型下

由于处理器支持了具有分页机制的虚拟内存,操作系统也采用了分页模型,因此编译器会将程序按内 容划分成代码段和数据段,如编译器 gcc会把 C 语言写 出的程序划分成代码段、数据段、栈段、 .bss 段、堆等部分 。 这会由操作系统将编译器编译出来的用户程序中的各个段分配到不同的物理内存上 。 对于目前咱们用高级语言编码来说,我们之所以不用关心如何将程序分段,正是由于编译器按平坦模型编译,而程序所依赖的操作系统又采用了虚拟内存管理,即处理器的分页机制。

这就是 Intel 处理器的程序计数器 es: eip能够自动获得下一条指令的原理,即将当前 eip 中的地址加上当前指令机器码的大小便是内存中下一条指令的起始地址 。 即使指令间有空隙或其他非指令的数据,这也仅仅是在物理上将其断开了,依然可以用 jmp指令将非指令部分跳过以保持指令在逻辑上连续

为了让程序内指令接连不断地执行,要把指令全部排在一起,形成一片连续的指令区域,这就是代码段 。 把数据连续地并排在一起存储形成的段落,就称为数据段。

  1. 编译器负责挑选出数据具备的属性,从而根据属性将程序片段分类,比如,划分出了只读属性的代码段和可写属性的数据段。
  2. 操作系统通过设置 GOT 全局描述符表来构建段描述符,在段描述符中指定段的位置、大小及属性(包括 S字段和 TYPE 字段)。也就是说,操作系统认为代码应该是只读的,所以给用来指向代码段的那个段描述符设置了只读的属性,这才是真正给段添加属性的地方。
  3. CPU中的段寄存器提前被操作系统赋予相应的选择子从而确定了指向的段。在执行指令时,会根据该段的属性来判断指令的行为,若有返回则发出异常。

9 物理地址、逻辑地址、有效地址、线性地址、虚拟地址

物理地址就是物理内存真正的地址,相当于内存中每个存储单元的门牌号,具有唯一性。在实模式下,“段基址+段内偏移地址”经过段部件的处理,直接输出的就是物理地址, CPU可以直接用此地址访问内存 。

而在保护模式下,"段基址+段内偏移地址”称为线性地址,不过,此时的段基址已经不再是真正的地址了,而是一个称为选择子的东西 。它本质是个索引,类似于数组下标,通过这个索引便能在 GDT中找到相应的段描述符,在该描述符中记录了该段的起始、大小等信息,这样便得到了段基址。若没有开启地址分页功能, 此线性地址就被当作物理地址来用,可直接访问内存。 若开启了分页功能,此线性地址又多了一个名字,就是虚拟地址

无论在实模式或是保护模式下,段内偏移地址又称为有效地址,也称为逻辑地址,这是程序员可见的地址 。

在这里插入图片描述

11 什么是平坦模式

平坦模型是相对于多段模型来说的,所以说平坦模型指的就是一个段 。

12 寄存器

  1. CS一代码段寄存器( Code Segment Register),其值为代码段的段基值
  2. DS一数据段寄存器( Data Segment Register),其值为数据段的段基值。
  3. ES一附加段寄存器( Extra Segment Register),其值为附加数据段的段基值,称为“附加”是因为此段寄存器用途不像其他 sreg 那样固定,可以额外做他用。
  4. FS一附加段寄存器( Extra Segment Register ),其值为附加数据段的段基值,同上,用途不固定,使用上灵活机动。
  5. GS一附加段寄存器( Extra Segment Register),其值为附加数据段的段基值。
  6. SS一堆枝段寄存器( Stack Segment Register),其值为堆栈段的段值。

在实模式下, CS 、 DS 、 ES 、 SS 中的值为段基址,是具体的物理地址,内存单元的逻辑地址仍为“段基值:段内偏移量”的形式。在保护模式下,装入段寄存器的不再是段地址,而是“段选择子” ( Selector),当然,选择子也是数值,其依然为 16 位宽度。

这篇关于操作系统真象还原:一些你可能正感到迷惑的问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1014754

相关文章

解读为什么@Autowired在属性上被警告,在setter方法上不被警告问题

《解读为什么@Autowired在属性上被警告,在setter方法上不被警告问题》在Spring开发中,@Autowired注解常用于实现依赖注入,它可以应用于类的属性、构造器或setter方法上,然... 目录1. 为什么 @Autowired 在属性上被警告?1.1 隐式依赖注入1.2 IDE 的警告:

解决java.lang.NullPointerException问题(空指针异常)

《解决java.lang.NullPointerException问题(空指针异常)》本文详细介绍了Java中的NullPointerException异常及其常见原因,包括对象引用为null、数组元... 目录Java.lang.NullPointerException(空指针异常)NullPointer

Android开发中gradle下载缓慢的问题级解决方法

《Android开发中gradle下载缓慢的问题级解决方法》本文介绍了解决Android开发中Gradle下载缓慢问题的几种方法,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、网络环境优化二、Gradle版本与配置优化三、其他优化措施针对android开发中Gradle下载缓慢的问

关于Nginx跨域问题及解决方案(CORS)

《关于Nginx跨域问题及解决方案(CORS)》文章主要介绍了跨域资源共享(CORS)机制及其在现代Web开发中的重要性,通过Nginx,可以简单地解决跨域问题,适合新手学习和应用,文章详细讲解了CO... 目录一、概述二、什么是 CORS?三、常见的跨域场景四、Nginx 如何解决 CORS 问题?五、基

MySQL安装时initializing database失败的问题解决

《MySQL安装时initializingdatabase失败的问题解决》本文主要介绍了MySQL安装时initializingdatabase失败的问题解决,文中通过图文介绍的非常详细,对大家的学... 目录问题页面:解决方法:问题页面:解决方法:1.勾选红框中的选项:2.将下图红框中全部改为英

Nginx启动失败:端口80被占用问题的解决方案

《Nginx启动失败:端口80被占用问题的解决方案》在Linux服务器上部署Nginx时,可能会遇到Nginx启动失败的情况,尤其是错误提示bind()to0.0.0.0:80failed,这种问题通... 目录引言问题描述问题分析解决方案1. 检查占用端口 80 的进程使用 netstat 命令使用 ss

mybatis和mybatis-plus设置值为null不起作用问题及解决

《mybatis和mybatis-plus设置值为null不起作用问题及解决》Mybatis-Plus的FieldStrategy主要用于控制新增、更新和查询时对空值的处理策略,通过配置不同的策略类型... 目录MyBATis-plusFieldStrategy作用FieldStrategy类型每种策略的作

linux下多个硬盘划分到同一挂载点问题

《linux下多个硬盘划分到同一挂载点问题》在Linux系统中,将多个硬盘划分到同一挂载点需要通过逻辑卷管理(LVM)来实现,首先,需要将物理存储设备(如硬盘分区)创建为物理卷,然后,将这些物理卷组成... 目录linux下多个硬盘划分到同一挂载点需要明确的几个概念硬盘插上默认的是非lvm总结Linux下多

Python Jupyter Notebook导包报错问题及解决

《PythonJupyterNotebook导包报错问题及解决》在conda环境中安装包后,JupyterNotebook导入时出现ImportError,可能是由于包版本不对应或版本太高,解决方... 目录问题解决方法重新安装Jupyter NoteBook 更改Kernel总结问题在conda上安装了

pip install jupyterlab失败的原因问题及探索

《pipinstalljupyterlab失败的原因问题及探索》在学习Yolo模型时,尝试安装JupyterLab但遇到错误,错误提示缺少Rust和Cargo编译环境,因为pywinpty包需要它... 目录背景问题解决方案总结背景最近在学习Yolo模型,然后其中要下载jupyter(有点LSVmu像一个