内存映射
内存映射(Memory-mapped I/O)是将磁盘文件的数据映射到内存,用户通过修改内存就能修改磁盘文件

父子进程间通信
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
|
#include <stdio.h> #include <sys/mman.h> #include <fcntl.h> #include <unistd.h> #include <sys/types.h> #include <stdlib.h> #include <string.h> #include <sys/wait.h>
int main() {
int fd = open("test.txt", O_RDWR); int size = lseek(fd, 0, SEEK_END);
void *ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if(ptr == MAP_FAILED) { perror("mmap"); exit(0); }
pid_t pid = fork(); if(pid > 0) { wait(NULL); char buf[64]; strcpy(buf, (char*)ptr); printf("read data : %s\n", buf); } else if(pid == 0){ strcpy((char *)ptr, "nihao a, son !!!"); }
munmap(ptr, size); return 0; }
|
内存映射的注意事项
- 如果对mmap的返回值(ptr)做++操作(ptr++),munmap是否能够成功?
void *ptr = mmap(…)
ptr++; 可以对其进行++ 操作
但是 munmap(ptr, len) // 错误,要保存地址
- 如果open时O_RDONLY,mmap时prot参数指定PROT_READ | PROT_WRITE会怎样?
错误,返回一个宏 MAP_FAILED
open() 函数中的权限建议和prot参数的权限保持一致
如果文件偏移量为1000会怎样?
偏移量是4k的整数倍,返回 MAP_FAILED
mmap什么情况下会调用失败?
- 第二个参数: length = 0 (映射数据长度) 不能再内存中映射为 0
- 第三个参数: prot
只指定了写权限
prot PROT_READ | PROT_WRITE
第5个参数(文件描述符) fd 通过open函数时指定的 O_RDONLY 或者 O_WRONLY
- 可以open的时候O_CREAT一个新文件来创建映射区吗?
可以的,但文件的大小如果为0的话,肯定不行
可以对新的文件进行扩展
lseek()
truncate()
void * ptr = mmap(null, 100, …)
4k
越界操作的是非法的内存 -> 段错误
使用内存映射实现文件拷贝
需要先创建一个test.txt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
|
#include <stdio.h> #include <sys/mman.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdlib.h> #include <string.h>
int main() {
int fd = open("test.txt", O_RDWR); if(fd == -1) { perror("open"); exit(-1); }
int len = lseek(fd, 0, SEEK_END);
int fd1 = open("cpy.txt", O_RDWR | O_CREAT, 0664);
truncate("cpy.txt", len); write(fd1, " ", 1);
void *ptr = mmap(NULL, len, PROT_READ| PROT_WRITE, MAP_SHARED, fd, 0); void *ptr1 = mmap(NULL, len, PROT_READ| PROT_WRITE, MAP_SHARED, fd1, 0);
if(ptr == MAP_FAILED) { perror("mmap"); exit(-1); }
if(ptr1 == MAP_FAILED) { perror("mmap"); exit(-1); }
memcpy(ptr1, ptr, len);
munmap(ptr, len); munmap(ptr1, len);
close(fd1); close(fd);
return 0; }
|
匿名映射
只能做父子进程中的通信
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
|
#include <stdio.h> #include <sys/mman.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/wait.h>
int main() {
int len = 4069; void *ptr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); if(ptr == MAP_FAILED) { perror("mmap"); exit(-1); }
pid_t pid = fork(); if(pid > 0) { strcpy((char *)ptr, "hello"); wait(NULL); } else if(pid == 0) { sleep(1); printf("%s\n", (char *)ptr); }
int ret = munmap(ptr, len); if(ret == -1) { perror("munmap"); exit(-1); }
return 0; }
|