前言:爲什麼要使用mmap內存映射?
我們知道,CPU從 I/O設備 讀寫的速度非常慢,而從 內存 讀寫的速度非常快,如果對一個文件需要進行多次讀寫,那麼每一次都調用 I/O
讀寫操作時很不划算的,於是我們便將這個文件 映射 到內存中,這樣CPU就可以直接快速讀寫。
mmap內存映射是一種空間換時間
的思想。
mmap內存映射
void* mmap(void* addr, size_t len, int proc, int flags, int fd, off_t offset)
參數說明:
-
addr
映射內存的地址,一般設置爲NULL,表示系統自動選擇內存映射的地址;也可以自己定義內存映射的地址 -
len
需要映射的文件的大小 -
proc
對映射區域的保護措施
PROT_READ 可讀
PROT_WRITE 可寫
PROT_EXEC 可執行
PROT_NONE 不能進行存取 -
flags
在內存中修改了文件之後是否將修改複製回源文件
MAP_SHARED 映射內存修改後會複製回源文件, 也就是 共享內存 技術
MAP_PRIVATE 映射內存修改後不會回到源文件, 類似於 寫時複製(copy on write) 技術 -
fd
文件句柄(文件描述符) -
offset
文件偏移, 注意必須是分頁大小的整數倍 -
返回值
成功則返回內存映射的起始地址,需要進行(char*)轉換,並讓一個char指針指向內存
失敗則返回-1,也需要進行(char)強制轉換
案例1:共享內存設計
修改file文件中第一個字母爲 ‘m’, 再查看源文件file
int test1()
{
const char *filename = "file";
int ret;
int fd = open(filename, O_RDWR);
ERROR_CHECK(fd, -1, "open");
char *file;
struct stat statinfo;
ret = stat(filename, &statinfo);
ERROR_CHECK(ret, -1, "stat");
file = (char *)mmap(NULL, statinfo.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
ERROR_CHECK((void *)file, (void *)-1, "mmap");
cout << file << endl;
file[0] = 'm';
cout << file << endl;
ret = munmap(file, statinfo.st_size);
ERROR_CHECK(ret, -1, "munmap");
close(fd);
return 0;
}
案例2:父子進程的進程間通信
int test2()
{
int fd = open("file2", O_RDWR | O_CREAT, 0755);
char *buff = (char*)mmap(NULL, 10, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
ERROR_CHECK(buff, (char*)-1, "mmap");
if (fork() == 0)
{
sprintf(buff, "%s", "child message");
exit(0);
}
sleep(1);
cout << "message from child: " << buff << endl;
exit(0);
}