Tim*_*Tim 4 linux io memory-mapped-file
在操作系统概念中,内存映射文件和内存映射 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 请求,以在物理内存中的映射位置读取和写入设备控制寄存器。
在 Linux 上,MMIO 可以从用户空间使用mmapon /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);
Run Code Online (Sandbox Code Playgroud)
在某些情况下。不过,这已经过时了,内核严格控制使用这种类型的访问可以做什么:访问/dev/mem requiresCAP_SYS_RAWIO,而现在的分发内核倾向于构建STRICT_DEVMEM并IO_STRICT_DEVMEM限制通过 /dev/mem内存中的几个范围进行访问,要么是 DOSEMU 所需的或 X,或映射到设备或以其他方式未使用(即为不由驱动程序处理的设备提供 MMIO)。
内存映射 I/O 是通过mmap()读取文件的某个区域然后使用映射的数据来完成的。
如果您使用现代操作系统,则操作系统会在内部执行大部分 I/O mmapp:
将文件的一部分映射到临时内核区域
copyout()将数据映射到用户地址空间。这会导致文件内容被错误地写入内核的临时内存区域。
取消区域映射
顺便说一句:如果您指的是从用户空间访问硬件,这通常是由 X 服务器完成的,该 X 服务器mmap()是来自图形板的硬件并从用户空间访问它。
在这种情况下,设备寄存器可以作为内存地址进行访问,您只需编写看起来就像在内核内部一样的代码。换句话说:您不使用 read() 或 write(),而只是取消引用指向硬件寄存器地址的指针。