目录
一、相关概念
二、代码样例
三、与 Direct IO 的不同
内存映射是一种常见的操作系统技术,它允许程序将磁盘文件映射到进程的地址空间中,从而使得程序可以像访问内存一样访问文件。这种技术可以极大地简化文件的读写操作,并且可以提高程序的性能。
内存映射是通过将磁盘文件映射到进程的地址空间中来实现的。在这种方式下,操作系统会将文件的某个区域映射到进程的虚拟地址空间中,从而使得程序可以直接访问这个区域的数据。
在 Linux 系统中,内存映射是通过调用 mmap() 函数来实现的。这个函数的原型如下:
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
/*
addr:指定映射的起始地址。如果为 NULL,则由操作系统自动选择一个地址。
length:指定映射的长度。
prot:指定映射区域的保护方式。可以是以下几种值的组合:
PROT_READ:可读。
PROT_WRITE:可写。
PROT_EXEC:可执行。
flags:指定映射区域的标志。可以是以下几种值的组合:
MAP_SHARED:与其他进程共享映射区域。
MAP_PRIVATE:不与其他进程共享映射区域。
MAP_FIXED:指定映射区域的起始地址。如果指定了这个标志,则 addr 参数必须为非 NULL。
MAP_ANONYMOUS:不映射任何文件,而是映射一段匿名的内存区域。
fd:指定要映射的文件描述符。
offset:指定要映射的文件的偏移量。
*/
下面代码的作用是读取一个文件的内容,并将其输出到屏幕上。然后,它将文件的内容修改为 "Hello, world!",并将修改后的内容写回到磁盘中。
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char *argv[]) {
int fd;
char *addr;
struct stat sb;
if (argc != 2) {
fprintf(stderr, "Usage: %s \n", argv[0]);
exit(EXIT_FAILURE);
}
fd = open(argv[1], O_RDWR);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
if (fstat(fd, &sb) == -1) {
perror("fstat");
exit(EXIT_FAILURE);
}
addr = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (addr == MAP_FAILED) {
perror("mmap");
exit(EXIT_FAILURE);
}
printf("The file content is: %s\n", addr);
strcpy(addr, "Hello, world!");
if (msync(addr, sb.st_size, MS_SYNC) == -1) {
perror("msync");
exit(EXIT_FAILURE);
}
if (munmap(addr, sb.st_size) == -1) {
perror("munmap");
exit(EXIT_FAILURE);
}
close(fd);
return 0;
}
内存映射和 Direct IO 都是用来提高文件读写性能的技术,但它们之间有一些不同。
首先,内存映射是将文件映射到进程的地址空间中,而 Direct IO 是直接使用文件描述符进行读写操作。因此,内存映射可以充分利用虚拟内存系统的优势,而 Direct IO 则可以避免缓存的影响。
其次,内存映射可以实现文件的共享访问,而 Direct IO 则不行。这是因为 Direct IO 会绕过文件系统缓存,而文件系统缓存是用来实现文件共享访问的。
最后在内存映射中,修改过的数据会被缓存在内存中,并不会立即写回到磁盘中。如果需要将数据写回到磁盘中,可以使用 msync() 函数或者 munmap() 函数来实现。而 Direct IO 是可以直接将数据写入磁盘的。