內存頁:
Linux是以頁為單位來管理物理內存的,一頁大小一般等於4096字節。頁容量越大,系統中可能存在的內存碎片就越多。
mmap將一個磁盤上的文件或者對象映射進內存。文件被映射到多個頁上,如果文件的大小不是所有頁的大小之和,最后一個頁不被使用的空間將會清零。
當使用mmap映射文件到進程后,就可以直接操作這段虛擬地址進行文件的讀寫等操作,不必再調用read,write等系統調用。
采用共享內存通信的一個顯而易見的好處是效率高,因為進程可以直接讀寫內存,而不需要任何數據的拷貝。比如像管道和消息隊列,需要在內核和用戶空間進行四次的數據拷貝。
mmap的系統操作有兩個:
#include <sys/mman.h> void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset); int munmap(void *start, size_t length);
第一個函數mmap,將文件描述符fd中的內容放到內存start --- ( start+ length) 的空間中。
port: 期望的內存保護方式,比如內存可讀/可寫/可執行,但是不能與文件的打開模式沖突。就是只能是文件權限的子集。
flag: 指定映射對象的類型
fd: 被映射的文件描述符。
第二個函數munmap,解除一個映射關系。
這兩個函數的說明文檔在:
http://man7.org/linux/man-pages/man2/mmap.2.html
例子
比如這個例子是php的apc使用了mmap:
#strace -p `cat /var/run/httpd.pid` open("/var/www/html/apc_load.php", O_RDONLY) = 13 ... mmap2(NULL, 31457280, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, 1232, 0) = 0xb5ce7000 ... nanosleep({3600, 0},
mmap2() 系統調用執行的操作幾乎與mmap(2) 一樣,唯一的區別在於最后一個參數給出的在文件中的偏移是以4096-字節為單位。
這個mmap就在內存中空出30M的空間做內存映射
php的apc緩存加速
php的apc大致原理是將php的opcode(php的操作碼)使用mmap映射(就是復制)到共享內存中,然后下次用戶再訪問調用php訪問,就可以直接去共享內存中讀取,而不需要再到磁盤上讀取了。
當然當php文件更新的時候,opcode也會自動失效(有檢測機制)。
參考文章:
http://blog.chinaunix.net/uid-26669729-id-3077015.html