POSIX共享内存(内存映射)

本质:

两个进程访问同一个逻辑内存;

直接访问内存,不用read()/write(),非常方便。

匿名映射文件:

设备	          作用	                      举例
/dev/zero	永远输出0的设备文件	dd if=/dev/zero of=磁盘分区 count=1024 bs=1024
/dev/null	丢弃一切写入其中数据	cat test > /dev/null
/dev/fd	       记录用户打开的文件描述符	ls /dev/fd/

头文件:

sys/mman.h

链接库:

rt

查看:

man shm_overview

ls  /dev/shm/

创建:

int shm_open(const char* name,int oflag,mode_t  mode);

name:

posix IPC名字。

oflag:

标志:

标志	     作用
O_CREAT	   没有该对象则创建
O_EXCL	  如果O_CREAT指定,但name不存在,就返回错误
O_RDONLY	只读
O_RDWR	        读写
O_WRONLY	只写
O_TRUNC	    若存在则截断

mode:

权限。

权限	作用
S_IWUSR	用户/属主写
S_IRUSR	用户/属主读
S_IWGRP	组成员写
S_IRGRP	组成员读
S_IWOTH	其他用户写
S_IROTH	其他用户读
返回值:

-1-------出错

其他----共享内存描述符


删除:

int shm_unlink(const char* name);

name:

posix IPC名字。

返回值:

-1——出错

0——-成功

修改文件大小:

创建新文件时大小为0,无法映射(存入数据)。

int  ftruncater(int fd,off_t length);

fd:

文件描述符。

length:

文件大小。

如果原文件大小比参数length大,超过部分删除。

返回值:

0——成功

-1——失败


建立内存映射:

void* mmap(void* start,size_t length,int prot,int flags,int fd,off_t offset);

start:

映射区的开始地址,一般为NULL(从可移植考虑)。

如果写NULL,就是让系统决定映射区的起始地址。

length:

映射区的长度(以字节为单位;不足一页内存按一页内存处理)。
port:

内存保护标志。

不能与文件的打开模式冲突(打开为读->prot为读;打开为读写->prot为写或读写)。

PROT_EXEC——页内容可被执行

PROT_READ——页内容可被读写

PROT_WRITE——页可被写

PROT_NONE——页不可访问

flags:

映射对象类型。

MAP_SHARED——变动共享

MAP_PRIVATE——变动私有

MAP_ANON———匿名内存映射(与MAP_SHARED一起用)

fd:

文件描述符(不能为套接字和终端的fd)。

-1————匿名内存映射。

offset:

被映射对象内容的起点(偏移量)。

返回值:

MAP_FAILED——失败

非MAP_FAILED——共享内存地址

删除内存映射:

int munmap(void* start,size_t length);

start:

映射内存起始地址。

length:

内存大小。

返回值:

0——成功

-1——失败

注意:

关闭mmap中的文件描述符不能删除内存映射。

同步(类似fflush):

int msync(void* addr,size_t len,int flags);

addr:

映射内存起始地址。

len:

内存大小。

flags:

同步参数:

MS_ASYNC——异步;调用会立即返回。不等到更新的完成。

MS_SYNC——同步;调用会等到更新完成之后返回。

MS_INVALIDATE——通知使用该共享区域进程,数据以改变;在共享内容更改后,使得文件的其他映射失效。

返回值:

0——成功

-1——失败

代码:

创建+修改文件大小:

#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>

int main(int argc,char* argv[]){
	int fd = shm_open(argv[1],O_CREAT|O_RDWR,0644);
	ftruncate(fd,atoi(argv[2]));
	void* buf = NULL;
	if(( buf =  mmap(NULL,BUFSIZ,PROT_WRITE,MAP_SHARED,fd,0)) == MAP_FAILED){
		perror("mmap error\n");
		return 1;
	}
}

删除:

#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>

int main(int argc,char* argv[]){
	shm_unlink(argv[1]);
}

读:

#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>

int main(int argc,char* argv[]){
	int fd = shm_open(argv[1],O_RDONLY,0);
	void* buf = NULL;
	if(( buf =  mmap(NULL,BUFSIZ,PROT_READ,MAP_SHARED,fd,0)) == MAP_FAILED){
		perror("mmap error\n");
		return 1;
	}
	printf("%s\n",buf);
	munmap(buf,BUFSIZ);
}

写:

#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>

int main(int argc,char* argv[]){
	int fd = shm_open(argv[1],O_RDWR,0);
	void* buf = NULL;
	if(( buf =  mmap(NULL,BUFSIZ,PROT_WRITE,MAP_SHARED,fd,0)) == MAP_FAILED){
		perror("mmap error\n");
		return 1;
	}
	strcpy(buf,argv[2]);
	munmap(buf,BUFSIZ);
}

亲缘进程间的匿名映射:

#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>

int main(int argc,char* argv[]){
	void* buf = NULL;
	if(( buf =  mmap(NULL,BUFSIZ,PROT_WRITE|PROT_READ,MAP_SHARED|MAP_ANON,-1,0)) == MAP_FAILED){
		perror("mmap error\n");
		return 1;
	}
	if(fork()){
		strcpy(buf,argv[1]);	
	}else{
		printf("%s\n",buf);
	}
	munmap(buf,BUFSIZ);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值