在操作系统概念中,内存映射文件和内存映射 I/O 是两个不同的东西。请参阅下文有关内存映射 I/O 的内容。
要使用内存映射文件,我们有mmap()
.
要使用内存映射I/O,我们可以使用哪些函数?内存映射 I/O 是否仅由操作系统内部使用,不向 Linux 上的程序员公开和使用?
谢谢。
对于 I/O,如第 1.2.1 节所述,每个 I/O 控制器都包含用于保存命令和正在传输的数据的寄存器。通常,特殊的 I/O 指令允许在这些寄存器和系统内存之间进行数据传输。为了更方便地访问 I/O 设备,许多计算机体系结构提供了内存映射 I/O。在这种情况下,存储器地址范围被预留并映射到设备寄存器。对这些内存地址的读取和写入会导致数据传入和传出设备寄存器。此方法适用于响应时间较快的设备,例如视频控制器。在 IBM PC 中,屏幕上的每个位置都映射到一个内存位置。在屏幕上显示文本几乎与将文本写入适当的内存映射位置一样简单。
...
处理器如何向控制器发出命令和数据来完成 I/O 传输?简而言之,控制器具有一个或多个用于数据和控制信号的寄存器。处理器通过读取和写入这些寄存器中的位模式来与控制器进行通信。发生这种通信的一种方式是通过使用特殊的 I/O 指令指定将字节或字传输到 I/O 端口地址。 I/O 指令触发总线线路来选择正确的设备并将位移入或移出设备寄存器。或者,设备控制器可以支持内存映射 I/O。在这种情况下,设备控制寄存器被映射到处理器的地址空间。 CPU 使用标准数据传输指令执行 I/O 请求,以在物理内存中的映射位置读取和写入设备控制寄存器。
答案1
在 Linux 上,MMIO 可以从用户空间mmap
使用/dev/mem
.例如,X 服务器执行以下操作:
fd = open("/dev/mem", O_RDWR);
if (ioBase == NULL) {
ioBase = (volatile unsigned char *) mmap(0, 0x20000,
PROT_READ | PROT_WRITE,
MAP_SHARED, fd, ioBase_phys);
}
close(fd);
在某些情况下。但这已经过时了,内核严格控制使用这种类型的访问可以做什么:访问/dev/mem
需要CAP_SYS_RAWIO
,现在的发行版内核往往是用STRICT_DEVMEM
并IO_STRICT_DEVMEM
限制访问通过 /dev/mem
内存中的几个范围,要么是 DOSEMU 或 X 所需的,要么映射到设备或未使用的(IE为不由驱动程序处理的设备提供 MMIO)。
答案2
内存映射 I/O 是通过mmap()
读取文件的某个区域然后使用映射的数据来完成的。
如果您使用现代操作系统,则操作系统会在内部执行大部分 I/O mmapp:
将文件的一部分映射到临时内核区域
copyout()
将数据映射到用户地址空间。这会导致文件内容被错误地写入内核的临时内存区域。取消区域映射
顺便说一句:如果您指的是从用户空间访问硬件,这通常是由 X 服务器完成的,该 X 服务器是mmap()
来自图形板的硬件并从用户空间访问它。
在这种情况下,设备寄存器可以作为内存地址进行访问,您只需编写看起来就像在内核内部一样的代码。换句话说:您不使用 read() 或 write(),而只是取消引用指向硬件寄存器地址的指针。