天天看點

LINUX共享記憶體mmap

很多事情看起來很簡單,但是動起手來,發現會有很多問題我們剛開始沒有考慮到的。我們知道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;
}
           

繼續閱讀