System V共享內存

共享內存:是最快的IPC形式,一旦這樣的內存映射到共享它的進程的地址空間,這些進程間的數據傳遞不再涉及到內核,不用通過執行進入內核的系統調用來傳遞彼此的數據。

mmap函數:

功能:將文件或者設備空間映射到共享內存區。

void*mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset);
參數
addr:要映射的起始地址,通常指定爲NULL,讓內核自動選擇
len:映射到進程地址空間的字節數
prot:映射區保護方式
flags:標誌
fd:文件描述符
offset:從文件頭開始的偏移量
返回值:成功返回映射到的內存區的起始地址;失敗返回-1

munmap函數:

功能:取消mmap函數建立的映射

int munmap(void *addr, size_t len);
參數
addr:映射的內存起始地址
len:映射到進程地址空間的字節數
返回值:成功返回0;失敗返回-1

msync函數:

功能:對映射的共享內存執行同步操作(立刻寫回文件)

int msync(void *addr, size_t len, int flags);
參數
addr:內存起始地址
len:長度
flags:選項
返回值:成功返回0;失敗返回-1

 

使用示例

write:

#include<unistd.h>//read/write

#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

#define ERR_EXIT(m)  \
	do\
	{\
		perror(m);\
		exit(EXIT_FAILURE);\
	}while (0)


typedef struct stu
{
	char name[4];
	int age;
}STU;

int main(int argc,char *argv[])
{
	if(argc != 2)
	{
		fprintf(stderr,"Usage:%s_<file>\n",argv[0]);
		exit(EXIT_FAILURE);
	}

	int fd;
	fd = open(argv[1],O_CREAT | O_RDWR | O_TRUNC, 0666);
	if(fd == -1)
		ERR_EXIT("open");

	lseek(fd,sizeof(STU)*5-1,SEEK_SET);
	write(fd,"",1);
	//以上創建了文件,接下來進行文件映射

	STU *p;
	//但應注意:映射不能改變文件大小,但可以通過映射傳遞大於文件大小的內容
	p = (STU*)mmap(NULL,sizeof(STU)*10,PROT_READ | PROT_WRITE,MAP_SHARED,fd,0);

	if(p == NULL)
		ERR_EXIT("mmap");
	//映射成功,寫入操作
	char ch = 'a';
	int i;
	for(i = 0;i<10;i++)
	{//對文件的訪問就是對內存的訪問
		memcpy((p+i)->name,&ch,1);
		(p+i)->age = 20+i;
		ch++;
	}

	printf("initialize over\n");
	
	sleep(10);
	
	munmap(p,sizeof(STU)*10);
	printf("exit...\n");
	return 0;
}

read:

#include<unistd.h>//read/write

#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

#define ERR_EXIT(m)  \
	do\
	{\
		perror(m);\
		exit(EXIT_FAILURE);\
	}while (0)


typedef struct stu
{
	char name[4];
	int age;
}STU;

int main(int argc,char *argv[])
{
	if(argc != 2)
	{
		fprintf(stderr,"Usage:%s_<file>\n",argv[0]);
		exit(EXIT_FAILURE);
	}

	int fd;
	fd = open(argv[1],O_RDWR);
	if(fd == -1)
		ERR_EXIT("open");

	STU *p;
	p = (STU*)mmap(NULL,sizeof(STU)*10,PROT_READ | PROT_WRITE,MAP_SHARED,fd,0);

	if(p == NULL)
		ERR_EXIT("mmap");
	//映射成功,讀取操作

	int i;
	for(i = 0;i<10;i++)
	{//對文件的訪問就是對內存的訪問
		printf("name = %s,age = %d\n",(p+i)->name,(p+i)->age);
	}

	munmap(p,sizeof(STU)*10);
	printf("exit...\n");
	return 0;
}

共享內存映射注意點:

  • 映射不能改變文件的大小;
  • 可用於進程間通信的有效地址空間不完全受限於被映射文件的大小;(映射的時候是根據頁面大小來的)
  • 文件一旦被映射後,所有對映射區域的訪問實際上是對內存區域的訪問。映射區域內容寫回文件時,所寫內容不能超過文件的大小。

共享內存進一步使用:

linux網絡編程之System V 共享內存 和 系列函數

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章