操作系统真象还原学习日志——第0章

目录

一、什么是操作系统

1、教科书定义

2、真象还原的解释

二、软件如何访问硬件

1、将外设的内存映射到地址空间

2、通过IO接口

三、应用程序如何与操作系统配合在一起

四、内存访问为什么要分段

1、分段利于地址重定位

2、分段使得16位地址线可访问1MB内存空间

五、代码中为什么分代码段、数据段?这与内存访问机制中的段是一回事吗?

1、程序分段的好处

2、程序分段、内存分段的关系

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

1、物理地址

2、线性地址、虚拟地址

3、有效地址、逻辑地址

七、局部变量与函数参数为什么要放在栈中

八、为什么说汇编语言比C语言快

九、BIOS中断、DOS中断、LINUX中断

十、Section和Segment的区别

十一、指令集、微架构

十二、计算机系统控制权交接


本文是笔者学习《操作系统真象还原》的读书笔记,若有侵权,请联系删除。笔者也是处于学习阶段,所陈述的内容如有错误,欢迎指正!

一、什么是操作系统

1、教科书定义

操作系统(Operating System,OS)是指控制和管理整个计算机系统的硬件和软件资源,并合理地组织调度计算机的工作和资源的分配,以提供给用户和其他软件方便的接口和环境,它是计算机系统中最基本的系统软件

2、真象还原的解释

①操作系统向用户进程提供系统调用,用户需要某一系统资源时,直接调用即可,不需要单独与硬件打交道。

形象化解释:对于原始人狩猎,需要制作武器。随着部落的出现,部落中专门有人负责制作武器,专门有人负责狩猎,狩猎者只需向部落申领武器即可,各司其职,效率变高了。这样子,即整合了大家在做同样一件事中相同的部分,又收回了相关权限。不再是所有人都可以制造兵器,这样子使得整个社会系统变得稳定。

②操作系统需要对资源进行宏观调控,有时会分成一定空间记录可控制信息,这些控制信息不会影响程序的执行,但是利于更好的管理相关资源。

形象化解释:现实生活中,并不需要领证才能在一起生活。但是领证方便对人口管理进行额外约束,不领证,将失去相关的统计数据,失去预测相关走向的依据。

二、软件如何访问硬件

1、将外设的内存映射到地址空间

CPU通过地址总线访问到该内存区域时,就落到了外设的内存中,这种映射使得CPU访问外设的内存就像访问主板上的物理内存一样。

例如:显卡,显卡是显示器的适配器。CPU不与显示器直接交互,只与显卡通信,显卡上有显存,CPU往显存上写字符,就会在显示屏上显示出来。至于为什么往显存上写字符就会显示在显示屏上,我们并不需要了解其中机理。

2、通过IO接口

CPU访问外设,就是访问IO接口,由IO接口将信息传递给外设,CPU不知道外设的存在,只负责操作接口。IO接口上有寄存器(端口),访问IO接口本质上就是访问相关寄存器。往相应的寄存器中输入什么,外设就会产生相应的反应,至于为什么,这是相关电路实现的

三、应用程序如何与操作系统配合在一起

应用程序是通过系统调用与操作系统配合完成某项功能的

应用程序是软件,操作系统也是软件。CPU对他们一视同仁,并不知道执行的是应用程序还是操作系统,CPU只知道去cs:ip寄存器中指向的内存去取指令。

应用程序是用某种语言编写的,而语言是编译器提供的。编译器决定怎么解释某种关键字以及某种语法。语言是编译器与开发者的约定,输入某种的语句,就是干某种事情。比如,C语言的printf就是输出字符串。但是如果编译器规定printf是输入,也未尝不可。只是编译器规定了printf是输出

编译器提供库函数,库函数中又有封装的系统调用。很多时候,我们写代码,并没有感觉使用了系统调用,这是因为库函数已经将系统调用封装在内了。我们可以跨过库函数,直接进行系统调用。

应用程序加上操作系统提供的功能才算是完整的程序。我们平时写的代码,只是半成品,需要调用操作系统提供的函数才能完整地做成一件事。

我们常常听到的“陷入内核”,其实就是用户进程由于内部或外部中断发生,停止执行,去执行内核代码。注意,内核的代码并不属于用户进程

四、内存访问为什么要分段

内存按访问方式来看,其结构是长方形带子,地址依次升高。内存是随机读写设备,即访问其内部任何一处,不需要从头开始找,只要直接给出其地址即可。(个人觉得,内存与数组很类似)

1、分段利于地址重定位

分段是从CPU 8086开始的,当时的计算机没有虚拟地址,只有物理地址,访问任何内存单元均要给出真实的物理地址。如果整个内存中仅有一个段(即没有分段),那么整个内存某一个时刻只能运行一个程序。若采用“段基址+段内偏移地址”的形式,可以在内存中装入多个段(会存在段重叠的现象)。尽管此时仍是使用绝对物理地址,但是可以同时运行多个程序。(此处涉及到“并行”与“并发”的解释。此处同时运行多个程序,并不是说在某一个时刻,一个CPU可以同时运行多个程序,而是在某一段时间内,CPU在不同程度上对各个程序都有执行,这是并发。只有并行,才是真正意义上同时运行多个程序,这需要一个计算机内部有多个处理器)

2、分段使得16位地址线可访问1MB内存空间

偏移地址需要存入寄存器,而8086的寄存器只有16位,最大可访问64KB,而当时的内存空间有1MB。16位的地址线如何访问20位的地址空间?CPU的设计者在地址处理单元中做了操作,地址部件将段基址自动左移4位,再和16位的段内偏移地址相加,此时的地址便变成了20位地址。

五、代码中为什么分代码段、数据段?这与内存访问机制中的段是一回事吗?

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

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

在平坦模式下,硬件段寄存器中指向的内存段大小最大为4GB。在平坦模式下编程,操作系统将整个4GB内存都放在一个段中,我们就不需要来回切换段寄存器所指向的段。

补充:什么是平坦模式?

平坦模式是相对多段模式而言,平坦模式指一个段。在保护模式下,由于是32位的,寻址范围有4GB即可,段内偏移地址也是32位,在32位环境中只用一个段就能访问所有内存

在多段模式下编程,硬件段寄存器中指向的内存段大小不一。在多段模式下,程序分段是人为划分的。汇编这种低级语言允许程序员为自己的程序分段,能够灵活地编排布局。

补充:为什么CPU能源源不断地获取指令?

  • 当指令是连续紧凑的,通过指令机器码可以判断当前指令长度,当前指令地址+当前指令长度=下一跳指令的地址。
  • 不满足指令是连续的时,保证指令逻辑上是连续的,采用jmp等指令跨过非指令区即可

1、程序分段的好处

①可以为不同段赋予不同的属性

数据本身需要修改,数据需要有可写的属性。程序中的代码是不能修改的,若修改了代码的指令,可能会导致程序出错,所以代码应该被限制为只读。

补充:谁为各段添加属性?谁根据属性保护程序?

  • 编译器负责挑选出数据具备的属性,从而根据属性将程序分段,但是,此时编译器并没有为段添加属性
  • 操作系统通过设置全局描述符表来构建段描述符,在描述符中指定了段的位置、大小和属性,即操作系统为段添加了属性
  • CPU中的段寄存器提前被OS赋予相应的选择子,从而确定指向的段。在执行指令时,会根据段的属性判断指令的行为是否合法
  • 编译器、OS、CPU三者配合才能对程序起到保护作用,检测出指令中的违规行为

②可以提高CPU内部缓存的命中率

缓存起作用是程序的局部性原理。在CPU内部也有缓存机制,将程序中的代码与数据分离,有利于增强程序的局部性原理。CPU内部有针对数据和指令的两种缓存机制,将两者分开,会使得命中率提高,使程序运行的更快。

③节省内存

当一个程序的多个副本在同时运行时,分段使得内存中仅有一个代码共享段即可。

2、程序分段、内存分段的关系

程序中的段只是逻辑上的划分,用于对不同数据进行归类,但可以用CPU中的段寄存器指向它们,然后用内存分段机制区访问程序中的段。内存分段是处理器为访问内存而采用的机制,程序分段是人为划分的内存区域,本身也是内存,所以处理器在访问该区域时,也会采用内存分段机制,用段寄存器指向该区域的起始地址。

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

1、物理地址

物理地址是物理内存真正的地址,相当于内存中每个存储单元的门牌号,具有唯一性。不管在什么模式下,CPU最终都要以物理地址去访问内存

在实模式下,“段基址+段内偏移地址”经过段部件的处理,直接就是物理地址

补充:段寄存器位宽

  • CS:代码段寄存器
  • DS:数据段寄存器
  • ES、FS、GS:附加段寄存器,值为附加数据段的段基值,也可额外做它用
  • SS:堆栈段寄存器
  • 对于32位的CPU,有两种工作模式:实模式与保护模式。不管在哪种模式下,段寄存器位宽均为16位

2、线性地址、虚拟地址

在保护模式下,“段基址+段内偏移地址”称为线性地址,然而此时的“段基址”已经不是真正的地址了,而是一个选择子,本质上是一个索引。通过选择子,确定全局描述符表中的段描述符,从而确定真正的段基址和段大小。

在开启分页之前,线性地址将被当成物理地址使用,可直接访问内存。

在开启分页之后,线性地址又称虚拟地址,两者并无区别,需要通过页部件转换成具体物理地址。

3、有效地址、逻辑地址

无论在哪种模式下,段内偏移地址又称为有效地址,也称逻辑地址。

七、局部变量与函数参数为什么要放在栈中

局部变量的作用域是局部,不具有全局性,只有自己再用,放在数据段中浪费空间,放在自己的栈中,随时可以清理。

函数参数也具有局部性,只有该函数才会用到。函数在程序执行过程中调用的,无法预测何时调用和调用几次,而函数参数和函数返回值都需要内存来存储。如果放在数据段,需要的内存无法提前预知。

八、为什么说汇编语言比C语言快

无论何种语言,都是在CPU上运行的。无论何种语言,到了CPU这,都是机器语言。

之所以说汇编语言更快,是因为汇编指令数更少,从而“显得”执行快。这是因为,C编译器为了使得C程序员方便编程,将一些细节隐藏了,而隐藏的部分是由C编译器解决的。不单单如此,为了更具通用性、易用性等。以上优点都需要C编译器添加额外的代码来作为支撑。所以,C生成汇编时,也相应的添加了一些指令。在两者都转化为机器语言时,自然而然,C代码的指令会较多。

例如:C语言中的printf函数,虽然只有一个语句,但背后的工作量却不小,需要检查数据类型、格式、小数点保留位数……,而汇编语言只需往显存mov字符即可。

九、BIOS中断、DOS中断、LINUX中断

某事件来自CPU外部,也就是该事件由外部设备发出并通知了CPU,这个事件就称为中断。

BIOS和DOS都是存在于实模式下的程序,由它们建立的中断调用都是建立在中断向量表中的。它们是通过软中断指令“int 中断号”来调用的。

关于中断向量表

  • 中断向量表中每个中断向量大小为4字节,中断向量中描述了中断处理程序的段基址和段内偏移地址
  • 中断向量表中的中断例程是BIOS建立的。每一种外设,都有自己的内存,这些内存都是只读存储器ROM,里面存着硬件的功能调用例程及初始化代码。ROM的第一、二个存储单元分别是0x55、0xAA,第三个存储单元存储以512字节为单位的代码长度,从第四个存储单元开始就是真实的代码。硬件会将ROM映射到内存中的某个区域。BIOS在运行期间,会扫描指定内存,若发现某区域前两个字节分别是0x55和0xAA,对该区域做累加和,若结果与第三个字节的值相同,则从第四个字节进入,开始执行硬件自带的例程来初始化硬件。最后,BIOS填写中断向量表中相关项
  • 中断向量表是CPU原生支持的,不需要谁来创建。软件只要执行“int 中断向量号”,CPU就会把向量号当成下标,去中断向量表中定位中断处理程序并执行

中断向量表中第0H~1FH项是BIOS中断。0x20~0x27是DOS中断。两者的中断向量号不能冲突。

DOS中断只占用0x21这个中断号,即DOS只有这一个中断例程。DOS需要先往ah寄存器存入子功能号,然后执行“int 0x21”,中断处理程序会根据ah中的值来调用子功能。

Linux内核是在进入保护模式后才建立中断例程的。不过在保护模式下,不存在中断向量表,而有中断描述符表。Linux是通过“int 0x80”指令进入中断处理程序后再根据eax寄存器的值来调用不同的子功能函数。

在实模式下,执行int指令会自动访问中断向量表。而在保护模式下,则会自动访问中断描述符表。

十、Section和Segment的区别

在汇编代码中,用关键字section或segment来表示一段区域,它们是编译器提供的伪指令。这段区域,被称为节。对于语法而言,关键字section与segment并无区别。

汇编器根据语法规则,会将汇编代码中表示“节”的语法关键字section或segment在目标文件中编译成“节”(section)。我们知道,所有的程序必须加载到内存中才能运行,而内存的访问会涉及到全局描述符表中段描述符的访问权限等属性,保护模式下,对任何内存进行访问都需要经过段描述符。在编译过后,链接器将访问权限相同的“节”合并起来,称为“段”(segment)。OS将为不同的“段”分配不同的选择子,从而指向不同的段描述符,实现它们不同的访问权限。

section称为节,诞生于目标文件中(编译后)。segment称为段,诞生于可执行文件(链接后)。

十一、指令集、微架构

目前CPU中的指令,无论是哪种指令集,都由操作码操作数两部分组成。

CPU处理的都是01二进制串,如何知道哪些是操作码?哪些是操作数?这是由于有了指令格式,我们人为规定了操作码和操作数的大小和位置。当CPU在译码阶段识别出操作码之后,就能确定需要什么样的操作数了。

指令集是一套约定,里面规定的是有哪些指令指令的二进制编码指令格式等。

微架构是指令集的物理实现,也就是电路级实现。

十二、计算机系统控制权交接

计算机在接电之后运行的就是基本输入输出系统BIOS。BIOS只完成一些检测和初始化工作。

BIOS将接力棒递给MBR(Main Boot Record),MBR位于整个硬盘最开始的扇区。BIOS会把MBR引导程序加载到物理地址0x7c00,然后跳过去执行,就完成了BIOS向MBR交权。

MBR中的内容:

  • 446字节的引导程序及参数
  • 64字节的分区表(一个分区项16字节,可容纳4个分区项)
  • 2字节结束标记0x55和0xaa

MBR需要向OBR(OS Boot Record)交权。MBR的分区表中的分区项的第一个字节为分区活动标记,若为0x80则该分区有OBR,若为0x0则没有OBR。OBR位于分区的第一个扇区,其前三个字节存放了跳转指令。MBR找到活动分区后,跳到活动分区的OBR的起始处,该起始处的跳转指令将处理器带入操作系统引导程序,从而完成了MBR的交权。

由于MBR只有一个,为了解决分区数量限制问题,提出了EBR,EBR兼容MBR中的分区表。EBR位于各子扩展分区中最开始的扇区,理论上,EBR可以有无数个。

MBR、EBR、OBR都包含引导程序,结束标记都是0x55和0xaa。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值