分享

从零开始写一个操作系统内核笔记(一)

 山峰云绕 2023-04-09 发布于贵州

数据的表示方法:在计算机里 数据的表示由 0 1 0 1 组成称为 二进制
在这里插入图片描述
0:代表着 低电平 代表着开关的关
1:代表高电平 代表着开关的开
这跟 摩斯密码是一个原理的 , 通过组合 0 1 可以表示成不同的消息。
其实计算机系统内部是通过一系列的逻辑代数 组合 形成 不同的计算
包括: 与 或 非
与门: 假设 a 和 b 都是 1 那么就输出 1
其实这个概念也不难理解
假设有个 串联开关在这里插入图片描述
如上图 假设继电器 开关有两种状态 开状态1 关状态0 只有当 满足 2个继电器开关同时 为开 1 的时候 点灯就会点亮 亮代表1 不亮代表0 那么 就变可以得出:

AND开关1 (0)开关2(1)
开关1(0)00
开关2(1)01

在这里插入图片描述
或门: 其实就是一个并联电路 图上有2个继电器 a 和 继电器b 当继电器a的 开关被打开
电路会处于联通状态 当继电器b 被打开 也会属于 联通状态 所以 就有了如下定义:

或门开关a(1)开关b(0)
开关b(0)10
开关a(1)11

当 a 和 b 有一个是 1那么就是 1 这就是或运算 就像 中文或那样的 意思 2者之间有一个为真 就返回真。

在这里插入图片描述
非门: 上图 中 有一开关 a 当其处于 关闭时 电路是处于通路的状态 当 开关处于关闭 那么 电路就会处于 断路的状态。
设开关状态 0为 关闭 1位打开 电路状态 1 为通路 0 为断路 那么 就会有如下关系:

开关a 打开(1)开关a 关闭(0)
电路01

非就是取反, 取到一种状态定义的对立面的表示。开的对立面就是关喽。

其实 通过组合 上面这三中逻辑 就可以组合成 新的 一系列的 计算 逻辑 例如:与非 或非 异或 。本质就是在电路输出和另一个电路的输入相互叠加。

那么其实处理器就是将这样的电路通过封装 写入硅晶cpu, 那么你肯定要问为什么要用硅呢? 因为 组成cpu 的 其实就是上面图表示的电路 的叠加在一起 不过电路使用的是mos这样的半导体管组合成的,属于半导体材料。

)

好了开始解释下上面的图:

  • CPU 通过地址线、数据线和控制信号线组成的本地总线(或称为内部总线) 与系统其他部分进行数据通信。地址线用于提供内存或 I/O 设备的地址,即指明需要读/写数据的具体位置。 数据线用于在 CPU 和内存或 I/O 设备之间提供数据传输的通道,而控制线则负责指挥执行的具体读/写操 作。对于使用 80386 CPU 的 PC 机,其内部地址线和数据线都分别有 32 根,即都是 32 位的。因此地址寻 址空间范围有232 字节,从0到4GB。把cpu数据总线想象成你家 有10种快递 什么 韵达 申通 圆通 京东 百世 等等 由于有了那么多快递你买东西能同时由不同的快递送达,但是那么强大的快递 刚开始的时候肯定有很多地方是不能送达的 比如西藏,新疆 cpu就像网上的电商可以通过不同的快递给你寄送商品,但是如果有某些地址快递找不到,那么这些潜在的消费需求就不能被很好的利用。
  • 北桥芯片用于 与 CPU、内存和 AGP 视频接口,这些接口具有很高的传输速率。北桥芯片还起着存储器控制作用,因此 Intel把该芯片标号为MCH(Memory Controller Hub)芯片。南桥芯片用来管理低、中速的组件,例如, PCI 总线、IDE 硬盘接口、USB 端口等,因此南桥芯片的名称为 ICH(I/O Controller Hub)。之所以用“南、 北”桥来分别统称这两个芯片,是由于在 Intel 公司公布的典型 PC 机主板上,它们分别位于主版的下端和 上端(即地图上的南部和北部)位置,并起着与 CPU 进行通道桥接的作用。关于北桥南桥一个直观的印象就是 桥吗 起到沟通的作用 想象到人类社会组织结构 不同阶级 不同信仰的人群都会推选某一个专门的工会组织作为代表 表示这个群体的自由意愿。在电脑内部也是人以类聚物以群分的 北桥 和 南桥相当于 帮助cpu对一些低级的io设备 做管理。

I/O端口和寻址

在 CPU 和 I/O 适配器之间开始传输数据时,首先需要确定适配器的 I/O 位置,即端口地址。 在 CPU和 I/O 之间传输数据时,一般可以使用程序循环查询、中断处理和 DMA 传输方式。
CPU需要控制如鼠标 键盘 蓝牙 网卡 声卡等设备时需要和设备发生交互,那么既然要通讯那么他们之间肯定会有特定的协议通讯方法,在系统中是通过将 这些IO设备的内存地址映射成内存的一部分,这部分内存就是这些IO设备,可以向访问普通内存一样,相当于外围设备提供了一系列IO的接口,通过置入特定的值可以操作外部设备,也可以读取这些是被的值
在这里插入图片描述
就像给你提供了一个控制台一样,通过设置一些开关就能控制这些设备。
在这里插入图片描述
通过写入指定IO内存空间的值来控制设备.CGA 显示卡上显示内存的地址就直接占用了 存储器地址空间 0xB800 – 0xBC00 范围。因此若要让一个字符显示在屏幕上,可以直接使用内存操作指令 往这个内存区域执行写操作。
在这里插入图片描述
PC 机 I/O 接口数据传输控制方式一般可采用程序循环查询方式、中断处理方式和 DMA 传输方式。顾 名思义,循环查询方式是指 CPU 通过在程序中循环查询指定设备控制器中的状态来判断是否可以与设备 进行数据交换。这种方式不需要过多硬件支持,使用和编程都比较简单,但是特别耗费 CPU 宝贵时间。 因此在多任务操作系统中除非等待时间极短或必须,否则就不应该使用这种方式。在 Linux 操作系统中, 只有在设备或控制器能够立刻返回信息时才会在很少的几个地方采用这种方式。
中断处理控制方式需要有中断控制器的支持。在这种控制方式下,只有当 I/O 设备通过中断向 CPU 提 出处理请求时,CPU 才会暂时中断当前执行的程序转而去执行相应的 I/O 中断处理服务过程。当执行完该 中断处理服务过程后,CPU 又会继续执行刚才被中断的程序。在 I/O 控制器或设备发出中断请求时,CPU 通过使用中断向量表(或中断描述符表)来寻址相应的中断处理服务过程的入口地址。因此采用中断控制 方式时需要首先设置好中断向量表,并编制好相应的中断处理服务过程。Linux 操作系统中大多数设备 I/O 控制都采用中断处理方式。
下面介绍下 比较知名的intel x86 cpu的cpu结构 寄存器的相关知识:

在这里插入图片描述
当计算机上电初始化时,物理内存被设置成从地址 0 开始的连续区域。除了地址从 0xA0000 到 0xFFFFF (640K 到 1M 共 384K)和 0xFFFE0000 到 0xFFFFFFFF(4G 处的最后一 64K)范围以外的所有内存都可 用作系统内存。这两个特定范围被用于 I/O 设备和 BIOS 程序。假如我们的计算机中有 16MB 的物理内存, 那么在 Linux 0.1x 系统中,0–640K 将被用作存放内核代码和数据。Linux 内核不使用 BIOS 功能,也不使 用BIOS设置的中断向量表。640K-- 1M之间的384K仍然保留用作图中指明的用途。其中地址0xA0000 开始的 128K 用作显示内存缓冲区,随后部分用于其他控制卡的 ROM BIOS 或其映射区域,而 0xF0000 到 1M 范围用于高端系统 ROM BIOS 的映射区。1M–16M 将被内核用于作为可分配的主内存区。另外高速缓 冲区和内存虚拟盘也会占用内核代码和数据后面的一部分内存区域,该区域通常会跨越 640K – 1M 的区域。

内存中 数据一般 按字节访问 一个字节是 8位 也就是 8个0或1 11111111 一个字(word)是 2个字节 16位 一个双字(double byte) 是 4个字节 32位。
如果按照 字访问 那么 16位的 字 可以拆成 高 8位 和 低 8位
如果双字则是 高16位 低 16位
在这里插入图片描述
在这里插入图片描述
内存地址 可以按照1个字节访问 上图 0000 可以存储一个字节 也就是 8个位 0001 也存放了 1个字节 8个位 ,但是 通过特定的指令 设计 可以让cpu按照一定长度的访问 比如一次访问 一个 字 一个双字

假设有一个 16字节的存储容器 那么他的 地址范围是多少呢?
其实很简单 就是 0~ 2 << 16 -2 也就是 65535 用16进制 表示成 0x ~0xffff. 那么 可以保存多少个字呢 2 << 15 / 2<< 8 = 512个字

指令和指令集

在这里插入图片描述
什么是寄存器呢?
是寄存器 和内存是一样的主要用来存储 数据 但是那为什么要寄存器 而不是直接访问 内内存呢 ?主要是因为cpu是很快的,可能是内存的上百倍的速度 如果 每次计算 都要通过内存的话 那么 cpu的速度就会被内存速度拖累,因为在访问内存的时候 等待时就不能干其他事情了,这就像木桶效应一样,往往可能决定系统性能的是系统的最短的短板,在现代计算机里最大短板 俨然就是io的 读取 cpu访问 一级缓存,二级缓存从,缓存访问内存,内存访问硬盘,就是为了弥补这种硬件性能带来的缺陷,加入哪一天硬盘访问速度 能和内存相当 那么内存也就不需要了,虽然很难但还是要对未来抱有希望的。

上面说了内存里 数据是怎么存放的,那么光是存放数据 如果没有定义怎么取数据 怎么对内存操作那么 那么计算机也是运行不起来的,那么 在内存中数据是怎么操作的呢?
对于内存中的数据 其实是 通过指令 来操作的。
那么指令集 是怎么构成的呢?
它由三部分 : 操作码 操作数1 操作数2
例如 mov ax,1 这条指令的 mov代表传递 将 1 这个立即数 传入 ax寄存器是一个16位的寄存器 又分为 al 和 ah 两个低8位的寄存器。
mov ax,[0x0ff1] 什么是立即数呢 其实表示的是 直接的值 而 [0x0ff1] 这个其实是 c语言里的指针 通过这个地址 寻找到 值 赋值给 寄存器ax

什么是低端字节序,高端字节序?
假设 一次取多个字节 那么 01 10 这两个 字节 01 是 高位 10 是低位 把 高位 放在前面 就是 打断存储 把 低位放在前面就是小端 存储 intelcpu 使用的是 小端 存储

低地址 低位 高地址 高位 小端存储
低地址 高位 高地址 低位 大端存储

应用程序的内存地址每次是固定的吗?
加入 写一个程序 每次写死了 自己该被分配的 内存地址 如果那么写的话 你 电脑那么多程序 怎么保证 这两个程序的内存地址不会冲突呢?
这显然是不可取的 那么在内存里 实际是怎么解决这个问题的呢?
使用相对位置,而不是使用真实的物理地址,程序每次都重新计算内存地址进行加载。在intel cpu 就是分段机制了,
段地址 + 偏移地址 形式
代码段寄存器(CS),数据段寄存器(DS)
在这里插入图片描述
A1 02 00 这条指令 是将 0002H处 传到 ax 寄存器 而 0002H不是绝对的 物理地址
而是根据当前DS段地址 + 0002H 计算出来的才是实际的物理地址。
假设此时Ds数据段地址是:1000H 那么 计算 后的 物理地址是 1000H * 16 + 0002H = 10002H 为什么要乘以 16 那是因为 寄存器只能 保存16 位 的数据 但是8086提供了 20根的地址线。这样它的寻址能力就是 2 << 19 =1048576 bytes 也就是 1M的空间。 但是 16位的寄存器直接相加 得到的 偏移 那还是 16位 没法 表示所有20位的地址空间,所以就有了 通过 段地址 * 16 + 偏移 这样 就能产生 20位的地址了。

8086 处理器 内部有8个16位的通用寄存器 ,分别 叫 AX,BX,CX,DX,SI,DI,BP,SP
在这里插入图片描述这里面 AX BX CX DX 又可以 划分为 AH(High) AL(Low) 的 高 8位 和 低八位 寄存器 。
分割出来的 高8位 寄存器 和 低八位寄存器相互之间 是可以独立使用的 不会互相影响。

如果Ds 为 25BCH 那么 物理地址访问范围为多少?
0x25BC * 16 + 0xffff 为段最大地址 为 '0x35bbf’ 。

总结几点:
内存的最小单位是byte 1字节 =8bit
内存连续读写多个字节时分为小端读取和大端读取
小端读取:低地址放低位高地址放高位 intelcpux86,DEC
大端读取:高地址放低位,低地址放高位 IBM,Sun,PowerPC
ARM架构的cpu则同时支持大小端,具体看硬件选择。
0x12345678 从左到右依次递减 0x12 是最高位 0x78是最低位 在intel 32位cpu内存是这样存储的
0x00000001:0x78 0x00000002:0x56 0x00000003:0x34 0x00000004:0x12 。
这是小端存储。bmp使用的小端存储,jpg则是大端存储这是由开发者自己当初设计时规定的。而网络数据发送是大端所以在x86体系的cpu上发送网络数据需要转换字节顺序。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多