OSTEP / Persistence-Disk

系统中各个组件和CPU连接方式如下:

ostep-sys-arch-of-io-device.png

总线分为三个层次:

  1. memory bus 连接内存和CPU
  2. general IO bus(PCI) 接入一些高性能IO设备比如显卡. 通常这些设备体积不大.
  3. peripheral IO bus(SATA/USB) 接入一些慢速设备比如键盘和鼠标等.

CPU和设备交互方式通常有两种: Port IO和MMIO(Memory Mapped IO).

I/O作为CPU和外设交流的一个渠道,主要分为两种,一种是Port I/O,一种是MMIO(Memory mapping I/O)。

前者就是我们常说的I/O端口,它实际上的应该被称为I/O地址空间。对于x86架构来说,通过IN/OUT指令访问。PC架构一共有65536个8bit的I/O端口,组成64KI/O地址空间,编号从0~0xFFFF。连续两个8bit的端口可以组成一个16bit的端口,连续4个组成一个32bit的端口。I/O地址空间和CPU的物理地址空间是两个不同的概念,例如I/O地址空间为64K,一个32bit的CPU物理地址空间是4G。MMIO占用CPU的物理地址空间,对它的访问可以使用CPU访问内存的指令进行。一个形象的比喻是把文件用mmap()后,可以像访问内存一样访问文件、同样,MMIO是用访问内存一样的方式访问I/O资源,如设备上的内存。

Port I/O和MMIO的主要区别在于1)前者不占用CPU的物理地址空间,后者占有(这是对x86架构说的,一些架构,如IA64,port I/O占用物理地址空间)。2)前者是顺序访问。也就是说在一条I/O指令完成前,下一条指令不会执行。例如通过Port I/O对设备发起了操作,造成了设备寄存器状态变化,这个变化在下一条指令执行前生效。uncache的MMIO通过uncahce memory的特性保证顺序性。

驱动程序代码在内核代码中占相当大的比例, 也是许多内核bug的根源.

Interestingly, because device drivers are needed for any device you might plug into your system, over time they have come to represent a huge percentage of kernel code. Studies of the Linux kernel reveal that over 70% of OS code is found in device drivers [C01]; for Windows-based systems, it is likely quite high as well. Thus, when people tell you that the OS has millions of lines of code, what they are really saying is that the OS has millions of lines of device-driver code. Of course, for any given installation, most of that code may not be active (i.e., only a few devices are connected to the system at a time). Perhaps more depressingly, as drivers are often written by “amateurs” (instead of full-time kernel developers), they tend to have many more bugs and thus are a primary contributor to kernel crashes [S03].