前两天使用/dev/mem来修改寄存器时遇到了一个问题. 当时的情况是这样的:
我有8K的寄存器空间需要访问, 但是当时我将mmap的空间大小写小了, 只写了1K, 相当于只映射了4K的空间. 但是当我操作到4K-8K的空间的时候, 读写看起来都没有问题, 读回来的数据和写入的数据是一致的. 但是实际寄存器上好像没有感受到一样(没有写入寄存器应有的现象), 刚开始一致怀疑是fpga的bitfile有问题. 后来无意发现了mmap指定的size不对, 改好了就可以了.
那么这里有一个问题, 为什么访问4K-8K的空间没有发生segment fault呢?
我做了一个实验, 下面有两个程序:
program 0 - have mmap:
1 2 3 4 5 6 7 8 9 10 11 12
| #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <sys/mman.h>
int main(int argc, char **argv) { int fd = open("a.txt", O_RDWR | O_DSYNC); void *ptr = mmap(0, 1000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); printf("0x%016lx\n", (unsigned long)ptr); pause(); }
|
program 1 - don’t have mmap:
1 2 3 4 5 6 7
| #include <stdio.h> #include <unistd.h>
int main(int argc, char **argv) { pause(); }
|
先将程序运行起来, 然后通过/proc/[pid]/maps查看他们的线性地址分布情况:
对于program 0:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| 00400000-00401000 r-xp 00000000 fd:02 1051271 /home/gngshn/b 00600000-00601000 r--p 00000000 fd:02 1051271 /home/gngshn/b 00601000-00602000 rw-p 00001000 fd:02 1051271 /home/gngshn/b 02293000-022b4000 rw-p 00000000 00:00 0 [heap] 7f17bd677000-7f17bd834000 r-xp 00000000 fd:00 924939 /usr/lib64/libc-2.24.so 7f17bd834000-7f17bda33000 ---p 001bd000 fd:00 924939 /usr/lib64/libc-2.24.so 7f17bda33000-7f17bda37000 r--p 001bc000 fd:00 924939 /usr/lib64/libc-2.24.so 7f17bda37000-7f17bda39000 rw-p 001c0000 fd:00 924939 /usr/lib64/libc-2.24.so 7f17bda39000-7f17bda3d000 rw-p 00000000 00:00 0 7f17bda3d000-7f17bda62000 r-xp 00000000 fd:00 924461 /usr/lib64/ld-2.24.so 7f17bdc3f000-7f17bdc41000 rw-p 00000000 00:00 0 7f17bdc5f000-7f17bdc60000 rw-s 00000000 fd:02 1066614 /home/gngshn/a.txt 7f17bdc60000-7f17bdc62000 rw-p 00000000 00:00 0 7f17bdc62000-7f17bdc63000 r--p 00025000 fd:00 924461 /usr/lib64/ld-2.24.so 7f17bdc63000-7f17bdc64000 rw-p 00026000 fd:00 924461 /usr/lib64/ld-2.24.so 7f17bdc64000-7f17bdc65000 rw-p 00000000 00:00 0 7fff75117000-7fff75138000 rw-p 00000000 00:00 0 [stack] 7fff75151000-7fff75153000 r--p 00000000 00:00 0 [vvar] 7fff75153000-7fff75155000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
|
对于program 1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 00400000-00401000 r-xp 00000000 fd:02 1051230 /home/gngshn/a 00600000-00601000 r--p 00000000 fd:02 1051230 /home/gngshn/a 00601000-00602000 rw-p 00001000 fd:02 1051230 /home/gngshn/a 7fb99a57a000-7fb99a737000 r-xp 00000000 fd:00 924939 /usr/lib64/libc-2.24.so 7fb99a737000-7fb99a936000 ---p 001bd000 fd:00 924939 /usr/lib64/libc-2.24.so 7fb99a936000-7fb99a93a000 r--p 001bc000 fd:00 924939 /usr/lib64/libc-2.24.so 7fb99a93a000-7fb99a93c000 rw-p 001c0000 fd:00 924939 /usr/lib64/libc-2.24.so 7fb99a93c000-7fb99a940000 rw-p 00000000 00:00 0 7fb99a940000-7fb99a965000 r-xp 00000000 fd:00 924461 /usr/lib64/ld-2.24.so 7fb99ab42000-7fb99ab44000 rw-p 00000000 00:00 0 7fb99ab63000-7fb99ab65000 rw-p 00000000 00:00 0 7fb99ab65000-7fb99ab66000 r--p 00025000 fd:00 924461 /usr/lib64/ld-2.24.so 7fb99ab66000-7fb99ab67000 rw-p 00026000 fd:00 924461 /usr/lib64/ld-2.24.so 7fb99ab67000-7fb99ab68000 rw-p 00000000 00:00 0 7ffdbcd07000-7ffdbcd28000 rw-p 00000000 00:00 0 [stack] 7ffdbcd31000-7ffdbcd33000 r--p 00000000 00:00 0 [vvar] 7ffdbcd33000-7ffdbcd35000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
|
可以看到program 0比program 1多了两段地址空间
- heap空间
- a.txt的mmap空间
heap空间是引入标准io时, 内部使用引入的; a.txt的mmap空间是程序里面调用mmap产生的.
这里可以看见mmap访问后面的地址没有出错的原因了, 在mmap后面刚好有一段mmap空间7f17bdc60000-7f17bdc62000 rw-p 00000000 00:00 0
, size为8K, 权限为读写, 这段空间是匿名映射空间, 当时我的读写都操作到这里了.
因此在使用mmap操作的时候, 一定要注意操作内存不要过界, 程序很可能不会因为你的操作过界而发生segment fault, 但是却会和你期望的相差甚远.