Mr Dk.'s BlogMr Dk.'s Blog
  • 🦆 About Me
  • ⛏️ Technology Stack
  • 🔗 Links
  • 🗒️ About Blog
  • Algorithm
  • C++
  • Compiler
  • Cryptography
  • DevOps
  • Docker
  • Git
  • Java
  • Linux
  • MS Office
  • MySQL
  • Network
  • Operating System
  • Performance
  • PostgreSQL
  • Productivity
  • Solidity
  • Vue.js
  • Web
  • Wireless
  • 🐧 How Linux Works (notes)
  • 🐧 Linux Kernel Comments (notes)
  • 🐧 Linux Kernel Development (notes)
  • 🐤 μc/OS-II Source Code (notes)
  • ☕ Understanding the JVM (notes)
  • ⛸️ Redis Implementation (notes)
  • 🗜️ Understanding Nginx (notes)
  • ⚙️ Netty in Action (notes)
  • ☁️ Spring Microservices (notes)
  • ⚒️ The Annotated STL Sources (notes)
  • ☕ Java Development Kit 8
GitHub
  • 🦆 About Me
  • ⛏️ Technology Stack
  • 🔗 Links
  • 🗒️ About Blog
  • Algorithm
  • C++
  • Compiler
  • Cryptography
  • DevOps
  • Docker
  • Git
  • Java
  • Linux
  • MS Office
  • MySQL
  • Network
  • Operating System
  • Performance
  • PostgreSQL
  • Productivity
  • Solidity
  • Vue.js
  • Web
  • Wireless
  • 🐧 How Linux Works (notes)
  • 🐧 Linux Kernel Comments (notes)
  • 🐧 Linux Kernel Development (notes)
  • 🐤 μc/OS-II Source Code (notes)
  • ☕ Understanding the JVM (notes)
  • ⛸️ Redis Implementation (notes)
  • 🗜️ Understanding Nginx (notes)
  • ⚙️ Netty in Action (notes)
  • ☁️ Spring Microservices (notes)
  • ⚒️ The Annotated STL Sources (notes)
  • ☕ Java Development Kit 8
GitHub
  • 🐧 Linux Kernel Comments
    • Chapter 2 - 微型计算机组成结构

      • Chapter 2 - 微型计算机组成结构
    • Chapter 3 - 内核编程语言和环境

      • Chapter 3 - 内核编程语言和环境
    • Chapter 4 - 80X86 保护模式及其编程

      • Chapter 4.1-4.2 - 80X86 系统寄存器和系统指令 & 保护模式内存管理
      • Chapter 4.3 - 分段机制
      • Chapter 4.4 - 分页机制
      • Chapter 4.5 - 保护
      • Chapter 4.6 - 中断和异常处理
      • Chapter 4.7 - 任务管理
      • Chapter 4.8 - 保护模式编程初始化
      • Chapter 4.9 - 一个简单的多任务内核实例
    • Chapter 5 - Linux 内核体系结构

      • Chapter 5.1-5.2 - Linux 内核模式 & 体系结构
      • Chapter 5.3 - Linux 内核对内存的管理和使用
      • Chapter 5.4-5.6 - 中断机制 & 系统调用 & 系统时间和定时
      • Chapter 5.7-5.9 - Linux 进程控制 & 堆栈使用 & 文件系统
    • Chapter 6 - 引导启动程序 (boot)

      • Chapter 6 - 引导启动程序 (boot)
    • Chapter 7 - 初始化程序 (init)

      • Chapter 7 - 初始化程序 (init)
    • Chapter 8 - 内核代码

      • Chapter 8.1 - 内核代码总体功能
      • Chapter 8.2 - asm.s 程序
      • Chapter 8.3 - traps.c 程序
      • Chapter 8.4 - sys_call.s 程序
      • Chapter 8.5 - mktime.c 程序
      • Chapter 8.6 - sched.c 程序
      • Chapter 8.7 - signal.c 程序
      • Chapter 8.8 - exit.c 程序
      • Chapter 8.9 - fork.c 程序
      • Chapter 8.10 - sys.c 程序
    • Chapter 9 - 块设备驱动程序

      • Chapter 9.1 - 块设备驱动程序 总体功能
      • Chapter 9.2 - blk.h 文件
      • Chapter 9.3 - hd.c 程序
      • Chapter 9.4 - ll_rw_blk.c 程序
      • Chapter 9.5 - ramdisk.c 程序
    • Chapter 10 - 字符设备驱动程序

      • Chapter 10.1 - 字符设备驱动程序 总体功能
      • Chapter 10.2 - keyboard.S 程序
      • Chapter 10.3 - console.c 程序
      • Chapter 10.4 - serial.c 程序
      • Chapter 10.5 - rs_io.s 程序
      • Chapter 10.6 - tty_io.c 程序
      • Chapter 10.7 - tty_ioctl.c 程序
    • Chapter 12 - 文件系统

      • Chapter 12.1 - 文件系统 总体功能
      • Chapter 12.2 - buffer.c 程序
      • Chapter 12.3 - bitmap.c 程序
      • Chapter 12.4 - truncate.c 程序
      • Chapter 12.5 - inode.c 程序
      • Chapter 12.6 - super.c 程序
      • Chapter 12.7 - namei.c 程序
      • Chapter 12.9 - block_dev.c 程序
      • Chapter 12.10 - file_dev.c 程序
      • Chapter 12.11 - pipe.c 程序
      • Chapter 12.12 - char_dev.c 程序
      • Chapter 12.13 - read_write.c 程序
      • Chapter 12.14 - open.c 程序
      • Chapter 12.15 - exec.c 程序
      • Chapter 12.16 - stat.c 程序
      • Chapter 12.17 - fcntl.c 程序
      • Chapter 12.18 - ioctl.c 程序
      • Chapter 12.19 - select.c 程序

Chapter 2 - 微型计算机组成结构

Created by : Mr Dk.

2019 / 07 / 18 09:55

Nanjing, Jiangsu, China


任何一个系统都可被认为由四部分组成:

  • 输入
  • 输出
  • 处理中心 - 加工输入,得到输出
  • 能源部分 - 为整个系统提供能源供给

对于计算机系统来说,由于输入和输出的大部分通道都是共享使用的:

  • 输入/输出 (I/O)
  • 处理中心
  • 能源

2.1 微型计算机组成原理

CPU 通过 地址线、数据线、控制线 组成的本地总线 (内部总线) 与系统其它部分进行通信

  • 地址线提供内存或 I/O 设备的地址
  • 数据线负责数据传输
  • 控制线负责指挥具体的读 / 写操作

2-3

现代 PC 主板由两个超大规模芯片组成 chipset:

  • 北桥 (Northbridge) 芯片 - Intel: MCH (Memory Controller Hub)
    • 拥有很高的传输速率
    • 连接 CPU、内存、AGP 视频接口
  • 南桥 (Southbridge) 芯片 - Intel: ICH (I/O Controller Hub)
    • 管理中、低速的硬件
    • PCI 总线、硬盘接口、USB 接口等

2.2 I/O 端口寻址和访问控制方式

2.2.1 I/O 端口和寻址

CPU 需要访问 I/O 接口控制器或控制卡上的数据和状态信息,首先需要制定它们的地址,即 I/O 端口地址 / 端口。通常 I/O 控制器包含:

  • 数据端口
  • 命令端口
  • 状态端口

端口地址的设置方法:

  • 统一编址
    • 将 I/O 控制器的端口地址归入存储器寻址地址空间范围内
    • 使用内存访问指令可以访问 I/O
  • 独立编址
    • 将 I/O 控制器和控制卡的寻址空间单独作为一个独立的地址空间对待
    • 使用专用的 I/O 指令来访问端口

2.2.2 接口访问控制

  • 循环查询方式
    • CPU 在程序中循环查询设备控制器中的状态,判断是否可以进行数据交换
    • 不需要硬件支持、简单
    • 耗费 CPU 的时间
  • 中断处理控制方式
    • 需要中断控制器的支持
    • I/O 设备向 CPU 提出中断请求
  • 直接存储器访问 (DMA, Direct Memory Access) 方式
    • 用于 I/O 设备与系统内存之间进行批量数据传送
    • 由专门的 DMA 控制器控制,不需要 CPU 插手
    • 无需软件介入

2.3 主存储器、BIOS 和 CMOS 存储器

2.3.1 主存储器

早期 8088/8086 CPU 只有 20 根地址线,因此内存寻址范围最高为 1 MB。Intel 32-bit CPU 可寻址 4GB 的地址,并通过 CPU 上的新特性,可以寻址 64GB 的物理内存。但为了与原来的 PC 在 软件 上兼容,1 MB 以下的物理内存使用分配依旧与最早期的使用方式一致。

2.3.2 基本输入/输出程序 BIOS

8088/8086 (20 bit 地址线) 启动方式

2-4

20 根地址线只能寻址 0x00000 - 0xFFFFF 共 1MB 的地址空间,其中,ROM (BIOS) 和 RAM 统一编址:

  • RAM 占据低端地址 768KB
    • 其中基本内存为 0x00000 - 0x9FFFF 共 640KB
    • 显示内存缓冲区为 0xA0000 - 0xBFFFF 共 128KB
  • ROM 占据从 0xC0000 - 0xFFFFF 开始的高端地址 256KB
    • 其中,系统 BIOS 占用最后的 64 KB 或更多 (0xF0000 - 0xFFFFF)

CPU 复位时,CS 寄存器设为 0xFFFF,IP 寄存器设为 0x0000 - 地址指向 0xFFFF0,即 ROM BIOS 中的最后 16B 处、此处放置了一条 JMP 指令,指向 BIOS 程序的真正入口地址。此时,CPU 控制权被 BIOS 获得:

  • BIOS 首先执行系统自检 POST (Power-On-Self-Test)
  • 并在 RAM 最低端建立中断向量表等 OS 需要使用的配置表
  • 初始化硬件 - 首先初始化显卡,并将后续硬件信息显示在 (显示缓冲区)
  • 按照 CMOS 设定的启动顺序,依次寻找主引导记录
  • 将主引导记录加载到 0x7C00 的位置 - 512B
  • 检测 MBR 最后两个字节是否为 0x55 和 0xAA,如果是,则可以启动
  • 跳转到引导程序的入口,将控制权交由引导程序

80386 (32 bit 地址线) 启动方式

32 位地址线可以寻址 0x00000000 - 0xFFFFFFFF 共 4G 的地址空间。

2-5

  • ROM (Flash Memory) 被编址在了 4G 内存的最高端
    • Flash Memory 的大小可以为 256KB - 2MB
  • 32-bit CPU 复位后,通过硬件机制,使其访问的第一条指令位于 0xFFFFFFF0,即最后 16B 处
  • 同样,这里也有一条 JMP 指令,跳转到 BIOS 真正的入口
  • 在完成硬件自检和初始化操作后,BIOS 会将与原先兼容的 64 KB 系统 BIOS 拷贝到内存低端 1M 的最后 64KB 处,并跳转到该处,使 CPU 真正运行在实地址模式下
  • BIOS 寻找引导程序并加载至 0x7C00 处

个人理解,首先,ROM 和 RAM 的编址应当是连续的,如果再将 1M 地址空间中的高 256KB 分配给ROM,RAM 的地址将不再连续。所以永远将 ROM 编址在内存最高端,为了兼容,因此 BIOS 需要将兼容的一段 BIOS 复制到 RAM 中对应原先 ROM 的地址处。因此,这一段 RAM 称为 BIOS Shadow。然后跳转到 BIOS Shadow 的程序入口,这样,启动的过程就与原先兼容。总之:

  1. ROM 永远编址在内存最高端
  2. CPU 复位后访问的第一条指令总位于内存最高端的最后 16B 处
  3. 不管 BIOS 中有多少新特性,Flash ROM 总体大小有多大,最终 BIOS 总需要将兼容程序拷贝到 1M 空间最后 64KB,并跳转过去,使 CPU 在实地址模式下启动

2.3.3 CMOS 存储器

Complementary Metal Oxide Semiconductor,互补金属氧化物半导体,存储容量很小: 64 / 128B。存放:

  • 实时时钟信息
  • 系统硬件配置信息

CMOS 的地址空间在基本内存地址空间之外,需要使用 I/O 指令访问。


2.4 控制器和控制卡

  • 控制器指集成在计算机主板上的控制部件
  • 控制卡指通过扩展插槽进入计算机的控制卡部件,扩展插槽与系统总线连接,接口标准包含:
    • ISA, Industry Standard Architecture 总线
    • EISA, Extended ISA 总线
    • PCI, Peripheral Component Interconnect 总线
    • AGP, Accelerated Graphics Port 总线

控制卡可以随着集成度的提高而被集成到主板上,因此控制器和控制卡没有实质上的区别。

2.4.1 中断控制器

使用两片级联的 8259A 可编程中断控制芯片组成中断控制器,能为 15 个设备提供独立的中断功能。ROM BIOS 对 8259A 芯片进行初始化:

  • 分配 15 级中断优先级
  • 在内存最低端建立中断向量表

Linux 不会直接使用 BIOS 设置好的中断号,在内核初始化期间,重新对 8259A 进行设置,将所有硬件中断号全部映射到 0x20 以上。

2.4.2 DMA 控制器

由 Intel 8237 及其兼容芯片实现,外设与内存之间的数据传输能在不受 CPU 控制的条件下进行。

2.4.3 定时 / 计数器

Intel 8253/8254 芯片提供了三个独立的 16 位计数器通道,分别被用于:

  • 时钟计时中断信号
  • 动态内存 DRAM 刷新定时电路
  • 主机扬声器音调合成

Linux 0.12 只对通道 0 进行了重新设置,使其工作在方式 3 下:

  • 每隔 10 ms 发出一个信号,产生中断请求 IRQ0
  • 该中断时 Linux 0.12 内核工作的脉搏
  • 用于定时切换当前执行的任务和统计每个任务使用的系统资源量

2.4.4 键盘控制器

键盘上有一个处理器称为 键盘编码器 (Intel 8048),专门用于扫描按键状态信息:扫描码。

  • 当按键按下时,键盘编码器发送 接通码 (Make Code)
  • 当按键松开时,键盘编码器发送 断开码 (Break Code)

主机的键盘控制器对扫描码进行解码,并将解码后的数据发送到 OS 的键盘数据队列中。键盘控制器收到串行数据后,将 键盘扫描码 转换为 系统扫描码,并通过 IRQ1 向 CPU 发出中断请求。CPU 调用键盘中断处理程序读取控制器中的扫描码。

2.4.5 串行控制卡

异步串行通信的帧包含:

  • 起始位
  • 数据位
  • 奇偶校验位
  • 停止位

PC 上电时,RESET 信号使 UART 内部寄存器和控制逻辑复位。此后若要使用,需要对其进行初始化编程。

2.4.6 显示控制

。

2.4.7 软盘和硬盘控制器

通常使用上下两个磁头在盘片的上下两面读写数据,磁头上分别有一个读线圈和写线圈。由于磁盘旋转,盘片上的磁介质相对磁头作匀速运动。

  • 磁头在切割磁介质的磁感线,从而产生感应电流
  • 根据磁介质状态的方向不同,感应电流方向不同,从而区分 0 和 1
  • 每个磁道都有存放信息的特定格式,因此能够区分各磁道的比特流

磁盘控制器是 CPU 和驱动器之间的逻辑接口电路

  • 从 CPU 接受请求命令
  • 向驱动器发送寻道、读/写和控制信号
  • 控制和转换数据流格式
    • 分离驱动器上的 metadata
    • CPU 的并行数据流和驱动器的串行数据流之间的转换

对磁盘控制器的编程:

  • 通过 I/O 端口设置控制器中的相关寄存器
  • 通过寄存器获取操作结果
Edit this page on GitHub