很多事情看起來很簡單,但是動起手來,發現會有很多問題我們剛開始沒有考慮到的。我們知道LINUX下的一種程序間通信叫共享記憶體,也就是使用mmap來實作。
首先介紹一下mmap這個函數
http://linux.die.net/man/2/mmap
這個函數可以分為兩種使用方式,一種是将檔案映射,另一種就是記憶體映射。差別再于是否設定了MAP_ANONYMOUS,如果設定了這個flag,那麼就意味着是記憶體映射,否則為檔案映射。
1,檔案映射,将這種方式認為是一種讀寫檔案的方式。可以将檔案通過mmap映射,然後就可以直接按照指針來讀取内容,速度快一些,也友善一些。寫檔案就有點奇怪了,首先應該保證檔案大小滿足我們将要寫進去的資料,否則将會發生BUS error。是以用這種方式應該是先建立一個檔案,然後擴大這個檔案的大小?還有一些網上的分析說,寫完成後munmap不一定保證将資料完整寫回磁盤。暗礁比較多,剛開始我用這種方式往裡面寫内容,按照設想,應該可以自動擴大檔案大小,但是卻得到錯誤。
2,記憶體映射,記憶體映射被認為是一種程序間通信的方式,但也确實不太好用吧?必須找一個合适的位址,然後大家一起來映射這個位址,如果映射失敗了,那麼就讀寫不一樣的記憶體位址了,在讀寫的時候還得加上一個檔案鎖之類的?
我應該給自己新的程式設計方式叫做 小心程式設計,多思考,多判斷。
以下是一段爛代碼,測試用途。
#include <fcntl.h>
#include <sys/mman.h>
#include <stdio.h>
static int gshmem_fd = -1;
void *shmem_alloc(size_t size)
{
void *addr;
/*gshmem_fd = open("/tmp/shmem", O_RDWR);
if(gshmem_fd < 0)
{
printf("Open failed.\n");
return NULL;
}*/
addr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, gshmem_fd, 0);
printf("mmap success, addr=%p.\n", addr);
return addr;
}
void shmem_free(void *addr, size_t size)
{
munmap(addr, size);
close(gshmem_fd);
gshmem_fd = -1;
}
int main()
{
char *addr = NULL;
void *temp = NULL;
int size = 1024;
int i = 0;
temp = shmem_alloc(size);
if(MAP_FAILED == temp)
{
printf("shmem_alloc failed.\n");
return -1;
}
addr = (char *)temp;
for(; i < size - 1; i++)
{
*addr = 'a';
addr ++;
}
*addr = '\0';
printf("output:%s.\n", (char *)temp);
shmem_free(temp, size);
return 0;
}