MMAP机制分析
#+PREVIEW_BEGIN
用strace跟踪常见命令,可以看到有大量 mmap
调用:
~$ strace ls 2>&1 | grep mmap mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f1da2f60000 mmap(NULL, 152705, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f1da2f3a000 mmap(NULL, 2259664, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f1da2b18000 mmap(0x7f1da2d3c000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x24000) = 0x7f1da2d3c000 mmap(0x7f1da2d3e000, 6864, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f1da2d3e000 mmap(NULL, 3795360, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f1da2779000 mmap(0x7f1da2b0e000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x195000) = 0x7f1da2b0e000 mmap(0x7f1da2b14000, 14752, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f1da2b14000 ...
通过 /proc/<pid>/maps
查看指定进程映射了哪几个文件:
~$ cat /proc/self/maps 556e0e237000-556e0e23f000 r-xp 00000000 08:02 786434 /bin/cat 556e0e43e000-556e0e43f000 r--p 00007000 08:02 786434 /bin/cat 556e0e43f000-556e0e440000 rw-p 00008000 08:02 786434 /bin/cat 556e0fdb0000-556e0fdd1000 rw-p 00000000 00:00 0 [heap] 7f7a531df000-7f7a5352e000 r--p 00000000 08:02 558542 /usr/lib/locale/locale-archive 7f7a5352e000-7f7a536c3000 r-xp 00000000 08:02 9699336 /lib/x86_64-linux-gnu/libc-2.24.so 7f7a536c3000-7f7a538c3000 ---p 00195000 08:02 9699336 /lib/x86_64-linux-gnu/libc-2.24.so 7f7a538c3000-7f7a538c7000 r--p 00195000 08:02 9699336 /lib/x86_64-linux-gnu/libc-2.24.so 7f7a538c7000-7f7a538c9000 rw-p 00199000 08:02 9699336 /lib/x86_64-linux-gnu/libc-2.24.so 7f7a538c9000-7f7a538cd000 rw-p 00000000 00:00 0 7f7a538cd000-7f7a538f0000 r-xp 00000000 08:02 9699331 /lib/x86_64-linux-gnu/ld-2.24.so 7f7a53ac5000-7f7a53ac7000 rw-p 00000000 00:00 0 7f7a53acb000-7f7a53af0000 rw-p 00000000 00:00 0 7f7a53af0000-7f7a53af1000 r--p 00023000 08:02 9699331 /lib/x86_64-linux-gnu/ld-2.24.so 7f7a53af1000-7f7a53af2000 rw-p 00024000 08:02 9699331 /lib/x86_64-linux-gnu/ld-2.24.so 7f7a53af2000-7f7a53af3000 rw-p 00000000 00:00 0 7ffc991b3000-7ffc991d4000 rw-p 00000000 00:00 0 [stack] 7ffc991e8000-7ffc991ea000 r--p 00000000 00:00 0 [vvar] 7ffc991ea000-7ffc991ec000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
#+PREVIEW_END
1 使用mmap读写文件
如下程序更新一个文件,让文件内容在字母A-Z之间变动:
#include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/mman.h> #include <sys/stat.h> #include <sys/types.h> #include <fcntl.h> #include <unistd.h> int main(int argc, char *argv[]) { int fd; pid_t pid; struct stat sb; char *addr, val, cmdbuf[128]; const char *pathname = "/tmp/mmap.test"; if (argc > 1) pathname = argv[1]; printf("pathname: %s\n", pathname); fd = open(pathname, O_RDWR|O_CREAT, S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH); if (-1 == fd) { perror("open failed"); return EXIT_FAILURE; } /* ensure up to 2MB */ lseek(fd, 1024*1024*2, SEEK_CUR); write(fd, "", 1); if (-1 == fstat(fd, &sb)) { perror("fstat failed"); return EXIT_FAILURE; } if (!S_ISREG(sb.st_mode)) { perror("Not a Regular file"); return EXIT_FAILURE; } printf("file size:%lu\n", sb.st_size); addr = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (!addr) { perror("mmap failed"); } val = addr[0]; if ('A' > val || 'Z' <= val) val = 'A'; val += 1; memset(addr, val, sb.st_size); pid = getpid(); sprintf(cmdbuf, "ls -l /proc/%u/map_files/", pid); system(cmdbuf); printf("---------------------------\n"); sprintf(cmdbuf, "cat /proc/%u/maps", pid); system(cmdbuf); return 0; }
#+RESULTS:
total 0
pathname: /tmp/mmap.test
file size:2097153
lr---–— 1 yanyg yanyg 64 Jan 26 15:20 555f1c428000-555f1c429000 -> /tmp/babel-M94bzk/C-bin-W4q33F
lr---–— 1 yanyg yanyg 64 Jan 26 15:20 555f1c629000-555f1c62a000 -> /tmp/babel-M94bzk/C-bin-W4q33F
lr---–— 1 yanyg yanyg 64 Jan 26 15:20 555f1c62a000-555f1c62b000 -> /tmp/babel-M94bzk/C-bin-W4q33F
lrw--–— 1 yanyg yanyg 64 Jan 26 15:20 7ff4f04be000-7ff4f06bf000 -> /tmp/mmap.test
lr---–— 1 yanyg yanyg 64 Jan 26 15:20 7ff4f06bf000-7ff4f0854000 -> /lib/x86_64-linux-gnu/libc-2.24.so
lr---–— 1 yanyg yanyg 64 Jan 26 15:20 7ff4f0854000-7ff4f0a54000 -> /lib/x86_64-linux-gnu/libc-2.24.so
lr---–— 1 yanyg yanyg 64 Jan 26 15:20 7ff4f0a54000-7ff4f0a58000 -> /lib/x86_64-linux-gnu/libc-2.24.so
lr---–— 1 yanyg yanyg 64 Jan 26 15:20 7ff4f0a58000-7ff4f0a5a000 -> /lib/x86_64-linux-gnu/libc-2.24.so
lr---–— 1 yanyg yanyg 64 Jan 26 15:20 7ff4f0a5e000-7ff4f0a81000 -> /lib/x86_64-linux-gnu/ld-2.24.so
lr---–— 1 yanyg yanyg 64 Jan 26 15:20 7ff4f0c81000-7ff4f0c82000 -> /lib/x86_64-linux-gnu/ld-2.24.so
lr---–— 1 yanyg yanyg 64 Jan 26 15:20 7ff4f0c82000-7ff4f0c83000 -> /lib/x86_64-linux-gnu/ld-2.24.so
555f1c428000-555f1c429000 r-xp 00000000 08:02 11927613 /tmp/babel-M94bzk/C-bin-W4q33F
555f1c629000-555f1c62a000 r–p 00001000 08:02 11927613 /tmp/babel-M94bzk/C-bin-W4q33F
555f1c62a000-555f1c62b000 rw-p 00002000 08:02 11927613 /tmp/babel-M94bzk/C-bin-W4q33F
555f1e396000-555f1e3b8000 rw-p 00000000 00:00 0 [heap]
7ff4f04be000-7ff4f06bf000 rw-s 00000000 08:02 11796543 /tmp/mmap.test
7ff4f06bf000-7ff4f0854000 r-xp 00000000 08:02 9699336 /lib/x86_64-linux-gnu/libc-2.24.so
7ff4f0854000-7ff4f0a54000 —p 00195000 08:02 9699336 /lib/x86_64-linux-gnu/libc-2.24.so
7ff4f0a54000-7ff4f0a58000 r–p 00195000 08:02 9699336 /lib/x86_64-linux-gnu/libc-2.24.so
7ff4f0a58000-7ff4f0a5a000 rw-p 00199000 08:02 9699336 /lib/x86_64-linux-gnu/libc-2.24.so
7ff4f0a5a000-7ff4f0a5e000 rw-p 00000000 00:00 0
7ff4f0a5e000-7ff4f0a81000 r-xp 00000000 08:02 9699331 /lib/x86_64-linux-gnu/ld-2.24.so
7ff4f0c56000-7ff4f0c58000 rw-p 00000000 00:00 0
7ff4f0c7e000-7ff4f0c81000 rw-p 00000000 00:00 0
7ff4f0c81000-7ff4f0c82000 r–p 00023000 08:02 9699331 /lib/x86_64-linux-gnu/ld-2.24.so
7ff4f0c82000-7ff4f0c83000 rw-p 00024000 08:02 9699331 /lib/x86_64-linux-gnu/ld-2.24.so
7ff4f0c83000-7ff4f0c84000 rw-p 00000000 00:00 0
7ffd5f9f2000-7ffd5fa13000 rw-p 00000000 00:00 0 [stack]
7ffd5fadc000-7ffd5fade000 r–p 00000000 00:00 0 [vvar]
7ffd5fade000-7ffd5fae0000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]