linux内核分析:x86,BIOS到bootloader,内核初始化,syscall, 进程与线程

lec6:x86架构

计算机工作模式

linux内核分析:x86,BIOS到bootloader,内核初始化,syscall, 进程与线程_第1张图片

其中cpu管理了数据的存放 和运算,所以cpu里面还有一个控制单元

linux内核分析:x86,BIOS到bootloader,内核初始化,syscall, 进程与线程_第2张图片

x86的cpu内部

linux内核分析:x86,BIOS到bootloader,内核初始化,syscall, 进程与线程_第3张图片 8 个 16 位的通用寄存器,也就是刚才说的 CPU 内部的数据单元,分别是 AX、BX、CX、DX、SP、BP、SI、DI。这些寄存器主要用于在计算过程中暂存数据。其中 AX、BX、CX、DX 可以分成两个 8 位的寄存器来使用,分别是 AH、AL、BH、BL、CH、CL、DH、DL,其中 H 就是 High(高位),L 就是 Low(低位)的意思。

每个进程都分代码段和数据段,为了指向不同进程的地址空间,有四个 16 位的段寄存器,分别是 CS、DS、SS、ES。

其中,CS 就是代码段寄存器(Code Segment Register),通过它可以找到代码在内存中的位置;DS 是数据段的寄存器,通过它可以找到数据在内存中的位置。

SS 是栈寄存器(Stack Register)

在 CS 和 DS 中都存放着一个段的起始地址。代码段的偏移量在 IP 寄存器中,数据段的偏移量会放在通用寄存器中。

这时候问题来了,CS 和 DS 都是 16 位的,也就是说,起始地址都是 16 位的,IP 寄存器和通用寄存器都是 16 位的,偏移量也是 16 位的,但是 8086 的地址总线地址是 20 位。怎么凑够这 20 位呢?方法就是“起始地址 *16+ 偏移量”,也就是把 CS 和 DS 中的值左移 4 位,变成 20 位的,加上 16 位的偏移量,这样就可以得到最终 20 位的数据地址。对于 8086CPU,最多只能访问 1M 的内存空间,还要分成多个段,每个段最多 64K。

在 32 位处理器中,有 32 根地址总线,可以访问 2^32=4G 的内存。使用原来的模式肯定不行了,但是又不能完全抛弃原来的模式,因为这个架构是开放的。

linux内核分析:x86,BIOS到bootloader,内核初始化,syscall, 进程与线程_第4张图片

那我们索性就重新定义一把吧。CS、SS、DS、ES 仍然是 16 位的,但是不再是段的起始地址。段的起始地址放在内存的某个地方。这个地方是一个表格,表格中的一项一项是段描述符(Segment Descriptor)。这里面才是真正的段的起始地址。而段寄存器里面保存的是在这个表格中的哪一项,称为选择子(Selector)。 

当然为了快速拿到段起始地址,段寄存器会从内存中拿到 CPU 的描述符高速缓存器中。

因而到了 32 位的系统架构下,我们将前一种模式称为实模式(Real Pattern),后一种模式称为保护模式(Protected Pattern)。

当系统刚刚启动的时候,CPU 是处于实模式的,这个时候和原来的模式是兼容的。也就是说,哪怕你买了 32 位的 CPU,也支持在原来的模式下运行,只不过快了一点而已。

为啥x86要分两种结构

x86是一种常见的计算机处理器架构,它在设计上包含了实模式(Real Mode)和保护模式(Protected Mode)这两种工作模式。这种设计的目的是为了向后兼容早期的x86处理器,并为操作系统和应用程序提供更高级的功能和保护机制。

实模式是x86架构的最初模式,它是为了向后兼容早期的16位x86处理器而设计的。在实模式下,处理器只能访问最多1MB的内存,并且没有内存保护和多任务处理的能力。实模式下的寻址是通过段地址和偏移地址的组合来实现的,这种方式较为复杂且容易出错。

保护模式是x86架构引入的一种新的工作模式,为操作系统和应用程序提供了更高级的功能和保护机制。在保护模式下,处理器可以访问远大于1MB的内存,并且支持内存分页、虚拟内存、多任务处理、特权级别等功能。保护模式使用平坦的内存模型,即将所有的内存视为连续的线性地址空间,简化了内存管理和寻址方式。

通过实模式和保护模式的切换,x86处理器可以在向后兼容旧版本软件的同时,提供更高级的功能和保护机制。当计算机启动时,处理器处于实模式下,操作系统可以选择将处理器切换到保护模式,并利用保护模式的功能来管理内存、实现多任务处理等。这种设计使得x86架构在演变过程中能够兼顾向后兼容性和功能扩展性。

你可能感兴趣的:(linux内核,linux,运维,服务器)