端口I/O

介绍:

一种I/O编址方式是端口映射I/O(port-mapped I/O), CPU使用专门的I/O指令对设备进行访问, 并把设备的地址称作端口号. 在执行其中的一条指令时,CPU使用地址总线选择所请求的I/O端口,使用数据总线在CPU寄存器和端口之间传送数据。

目的:

系统设计者的主要目的是提供对I/O编程的统一方法,但又不牺牲性能。为了达到这个目的,每个设备的I/O 端口都被组织成一组专用寄存器。CPU把要发给设备的命令写入控制寄存器(control register),并从状态寄存器(status register)中读出表示设备内部状态的值。CPU还可以通过读取输入寄存器(input register)的内容从设备取得数据,也可以通过向输出寄存器(output register)中写入字节而把数据输出到设备。

举例:

以x86为例,x86提供了in和out指令用于访问设备,其中in指令用于将设备寄存器中的数据传输到CPU寄存器中, out指令用于将CPU寄存器中的数据传送到设备寄存器中. 一个例子是使用out指令给串口发送命令字:

movl $0x41, %al
movl $0x3f8, %edx
outb %al, (%dx)

上述代码把数据0x41传送到0x3f8号端口所对应的设备寄存器中. CPU执行上述代码后, 会将0x41这个数据传送到串口的一个寄存器中, 串口接收之后, 发现是要输出一个字符A; 但对CPU来说, 它并不关心设备会怎么处理0x41这个数据, 只会老老实实地把0x41传送到0x3f8号端口. 事实上, 设备的API及其行为都会在相应的文档里面有清晰的定义, 在PA中我们无需了解这些细节, 只需要知道, 驱动开发者可以通过RTFM, 来编写相应程序来访问设备即可.

内存映射I/O

介绍:

MMIO(Memory mapping I/O)即内存映射I/O,它是PCI规范的一部分,I/O设备被放置在内存空间而不是I/O空间。从处理器的角度看,内存映射I/O后系统设备访问起来和内存一样。这样访问AGP/PCI-E显卡上的帧缓存,BIOS,PCI设备就可以使用读写内存一样的汇编指令完成,简化了程序设计的难度和接口的复杂性。I/O作为CPU和外设交流的一个渠道,主要分为两种,一种是Port I/O,一种是MMIO(Memory mapping I/O)。(来自百度百科)

目的:

早期的PC中,所有的IO设备(除了存储设备之外的设备)的内部存储或者寄存器都只能通过IO地址空间进行访问(Intel干的好事)。但是这种方式局限性很大,而且效率低,于是乎,软件开发者和硬件厂商都不能忍了……然后一种新的东西就出来了——MMIO。MMIO,即Memory Mapped IO,也就是说把这些IO设备中的内部存储和寄存器都映射到统一的存储地址空间(Memory Address Space)中。但是,为了兼容一些之前开发的软件,PCIe仍然支持IO地址空间,只是建议在新开发的软件中采用MMIO。

内存映射I/O这种编址方式非常巧妙, 它是通过不同的物理内存地址给设备编址的. 这种编址方式将一部分物理内存的访问"重定向"到I/O地址空间中, CPU尝试访问这部分物理内存的时候, 实际上最终是访问了相应的I/O设备, CPU却浑然不知.

这样以后, CPU就可以通过普通的访存指令来访问设备. 这也是内存映射I/O得天独厚的好处: 物理内存的地址空间和CPU的位宽都会不断增长, 内存映射I/O从来不需要担心I/O地址空间耗尽的问题.

从原理上来说, 内存映射I/O唯一的缺点就是, CPU无法通过正常渠道直接访问那些被映射到I/O地址空间的物理内存了. 但随着计算机的发展, 内存映射I/O的唯一缺点已经越来越不明显了: 现代计算机都已经是64位计算机, 物理地址线都有48根, 这意味着物理地址空间有256TB这么大, 从里面划出3MB的地址空间给显存, 根本就是不痛不痒.

对x86来说, 内存映射I/O的一个例子是NEMU中的物理地址区间[0xa1000000, 0xa1800000). 这段物理地址区间被映射到VGA内部的显存, 读写这段物理地址区间就相当于对读写VGA显存的数据. 例如:

memset((void *)0xa1000000, 0, SCR_SIZE);

会将显存中一个屏幕大小的数据清零, 即往整个屏幕写入黑色像素, 作用相当于清屏. 可以看到, 内存映射I/O的编程模型和普通的编程完全一样: 程序员可以直接把I/O设备当做内存来访问. 这一特性也是深受驱动开发者的喜爱.

参考文献:

输入输出 | 官方文档 (oscc.cc)

内存映射IO (MMIO) 简介 - 知乎 (zhihu.com)

PCIe扫盲——Memory & IO 地址空间 - 简书 (jianshu.com)

内存映射IO(MMIO)的更多相关文章

  1. linux中的 IO端口映射和IO内存映射

    参考自:http://blog.csdn.net/zyhorse2010/article/details/6590488 CPU地址空间 (一)地址的概念 1)物理地址:CPU地址总线传来的地址,由硬 ...

  2. 浅谈内存映射I/O(MMIO)与端口映射I/O(PMIO)的区别

    最近在看NVMeDirect和SPDK的源码,觉得有必要梳理一下MMIO和PMIO的区别.关于MMIO和PMIO,维基百科上是这么讲滴, Memory-mapped I/O (MMIO) and po ...

  3. Java NIO内存映射---上G大文件处理(转)

    林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 摘要:本文主要讲了java中内存映射的原理及过程,与传统IO进行了对比,最后,用实例说明了结果 ...

  4. 深入理解内存映射mmap

    内存映射mmap是Linux内核的一个重要机制,它和虚拟内存管理以及文件IO都有直接的关系,这篇细说一下mmap的一些要点. 修改(2015-11-12):Linux的虚拟内存管理是基于mmap来实现 ...

  5. 计算机底层知识拾遗(九)深入理解内存映射mmap

    内存映射mmap是Linux内核的一个重要机制,它和虚拟内存管理以及文件IO都有直接的关系,这篇细说一下mmap的一些要点. 修改(2015-11-12):Linux的虚拟内存管理是基于mmap来实现 ...

  6. 内存映射文件(Memory-Mapped File)

    Java Memory-Mapped File所使用的内存分配在物理内存而不是JVM堆内存,且分配在OS内核. 1: 内存映射文件及其应用 - 实现一个简单的消息队列 / 计算机程序的思维逻辑 在一般 ...

  7. System.IO之内存映射文件共享内存

    内存映射文件是利用虚拟内存把文件映射到进程的地址空间中去,在此之后进程操作文件,就 像操作进程空间里的地址一样了,比如使用c语言的memcpy等内存操作的函数.这种方法能够很好的应用在需要频繁处理一个 ...

  8. Java IO 学习(三)缓冲IO / 直接IO / 内存映射

    缓冲IO 在介绍缓冲IO之前需要先了解一下常用的机械硬盘的原理与特点 一个机械硬盘中装有多个盘片 每个盘片上有多个同心圆(磁道) 每个同心圆又由多个弧(扇区)组成,每个弧上都记录了等量的数据(比方说5 ...

  9. JAVA NIO FileChannel 内存映射文件

      文件通道总是阻塞式的. 文件通道不能创建,只能通过(RandomAccessFile.FileInputStream.FileOutputStream)getChannel()获得,具有与File ...

随机推荐

  1. ShadeRec类定义

    这个类主要是用于记录碰撞数据的类,书中已经说的很清楚了.这个类之后会慢慢扩展,会在本随笔中扩展,先定义简单的,方便编译看看效果. 类声明(World是之后主程序中的类,最后测试时再实现): #ifnd ...

  2. 基于EasyExcel实现的分页数据下载封装

    功能概述 主要实现的功能: 1.分页查询,避免一次性查询全部数据加载到内存引起频繁FULL GC甚至OOM 2.当数据量超过单个工作簿最大行数(1048575)时,自动将数据写入新的工作簿 3.支持百 ...

  3. 在centos服务器里安装opencv的坑:mportError: libXrender.so.1: cannot open shared object file: No such file or directory and wrong ELF class: ELFCLASS32

    centos7服务器安装opencv (其他版本服务器一样) 安装opencv: pip install opencv-python 导入cv2 import cv2 报错:importError: ...

  4. Web 布局设计(一):固定侧边栏

    前言 闲着无事,做一些实战练习,今天实现一个如标题所示的布局设计.通过此次布局设计,我希望掌握position属性值 fixed.absolute.relative.width和height属性值 i ...

  5. feign的fallback操作

    Fallback可以帮助我们在使用Feign去调用另外一个服务时,如果出现了问题,走服务降级,返回一个错误数据,避免功能因为一个服务出现问题,全部失效. 依赖: <dependency> ...

  6. 刷题记录:Codeforces Round #734 (Div. 3)

    Codeforces Round #734 (Div. 3) 20210920.网址:https://codeforces.com/contest/1551. 编程细节:下标定义不要一会[1,n]一会 ...

  7. JZOJ3542冒泡排序

    题面 下面是一段实现冒泡排序算法的C++代码: for (int i=1;i<=n-1;i++)  for (int j=1;j<=n-i ;j++)  if(a[j]>a[j+1] ...

  8. 【java】学习路径42-六种字符流使用实例

    第一种 OutputStreamWriter OutputStreamReader 第二种 FileWriter FileReader 第三种 BufferedWriter BufferedReade ...

  9. 【JAVA】学习路径35-InputStream使用例子

    import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; pu ...

  10. 第三十八篇:vue3路由

    好家伙,水博客怎么说 1.0.安装:简简单单的淘宝镜像安装 装一下淘宝镜像(一般都有) npm install -g cnpm --registry=https://registry.npm.taob ...