匿名内存映射
在 Linux 中,如果使用malloc()
分配一块很大的内存 (大于128KB),这时malloc()
不会直接从 heap 上分配内存,而是会调用mmap()
创建匿名的内存映射,那么使用mmap()
分配内存有何优缺点呢?
- 使用
mmap()
分配内存时,不会产生内存碎片。因为当这块内存不需要时,可以直接调用munmap()
释放它,这样内存就会直接返回给操作系统。 - 在 Linux 中,一个页面的大小是 4KB,所以
mmap()
分配的内存会按照 4KB 的大小对齐。通常来说,分配小块内存并不会用到mmap()
,因为mmap()
分配的内存是 4KB 的整数倍,如果不能充分利用,就会造成内存的浪费。 - 和在 heap 上分配内存相比,使用
mmap()
分配内存时将带来比较大的开销,所以mmap()
不适合频繁地调用,通常只有当分配的内存比较大时,才会使用到mmap()
。
使用mmap()
分配内存有两种形式,一种是私有的内存映射,另一种是共享的内存映射。如果创建的是私有的内存映射,那么在fork()
之后,尽管子进程也可以访问这块内存,但是 copy-on-write 会保证父进程和子进程对这块内存的修改不会被彼此看见:
从程序的输出可以看到,子进程对内存的修改不会被父进程看到:
但如果mmap()
创建的是共享的内存映射,那么在fork()
之后,父进程和子进程对这块内存的修改,对彼此来说都是可见的,因此共享的内存映射可以用来作为进程间通信的一种方式。我们可以试着修改上面的程序,改用共享的内存映射:
这时运行程序,可以看到子进程修改了内存,对父进程来说是可见的: