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

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

相关文章

解决pandas无法读取csv文件数据的问题

《解决pandas无法读取csv文件数据的问题》本文讲述作者用Pandas读取CSV文件时因参数设置不当导致数据错位,通过调整delimiter和on_bad_lines参数最终解决问题,并强调正确参... 目录一、前言二、问题复现1. 问题2. 通过 on_bad_lines=‘warn’ 跳过异常数据3

解决RocketMQ的幂等性问题

《解决RocketMQ的幂等性问题》重复消费因调用链路长、消息发送超时或消费者故障导致,通过生产者消息查询、Redis缓存及消费者唯一主键可以确保幂等性,避免重复处理,本文主要介绍了解决RocketM... 目录造成重复消费的原因解决方法生产者端消费者端代码实现造成重复消费的原因当系统的调用链路比较长的时

深度解析Nginx日志分析与499状态码问题解决

《深度解析Nginx日志分析与499状态码问题解决》在Web服务器运维和性能优化过程中,Nginx日志是排查问题的重要依据,本文将围绕Nginx日志分析、499状态码的成因、排查方法及解决方案展开讨论... 目录前言1. Nginx日志基础1.1 Nginx日志存放位置1.2 Nginx日志格式2. 499

kkFileView启动报错:报错2003端口占用的问题及解决

《kkFileView启动报错:报错2003端口占用的问题及解决》kkFileView启动报错因office组件2003端口未关闭,解决:查杀占用端口的进程,终止Java进程,使用shutdown.s... 目录原因解决总结kkFileViewjavascript启动报错启动office组件失败,请检查of

SpringBoot 异常处理/自定义格式校验的问题实例详解

《SpringBoot异常处理/自定义格式校验的问题实例详解》文章探讨SpringBoot中自定义注解校验问题,区分参数级与类级约束触发的异常类型,建议通过@RestControllerAdvice... 目录1. 问题简要描述2. 异常触发1) 参数级别约束2) 类级别约束3. 异常处理1) 字段级别约束

Python错误AttributeError: 'NoneType' object has no attribute问题的彻底解决方法

《Python错误AttributeError:NoneTypeobjecthasnoattribute问题的彻底解决方法》在Python项目开发和调试过程中,经常会碰到这样一个异常信息... 目录问题背景与概述错误解读:AttributeError: 'NoneType' object has no at

Spring的RedisTemplate的json反序列泛型丢失问题解决

《Spring的RedisTemplate的json反序列泛型丢失问题解决》本文主要介绍了SpringRedisTemplate中使用JSON序列化时泛型信息丢失的问题及其提出三种解决方案,可以根据性... 目录背景解决方案方案一方案二方案三总结背景在使用RedisTemplate操作redis时我们针对

Kotlin Map映射转换问题小结

《KotlinMap映射转换问题小结》文章介绍了Kotlin集合转换的多种方法,包括map(一对一转换)、mapIndexed(带索引)、mapNotNull(过滤null)、mapKeys/map... 目录Kotlin 集合转换:map、mapIndexed、mapNotNull、mapKeys、map

nginx中端口无权限的问题解决

《nginx中端口无权限的问题解决》当Nginx日志报错bind()to80failed(13:Permissiondenied)时,这通常是由于权限不足导致Nginx无法绑定到80端口,下面就来... 目录一、问题原因分析二、解决方案1. 以 root 权限运行 Nginx(不推荐)2. 为 Nginx

解决1093 - You can‘t specify target table报错问题及原因分析

《解决1093-Youcan‘tspecifytargettable报错问题及原因分析》MySQL1093错误因UPDATE/DELETE语句的FROM子句直接引用目标表或嵌套子查询导致,... 目录报js错原因分析具体原因解决办法方法一:使用临时表方法二:使用JOIN方法三:使用EXISTS示例总结报错原