POSIX共享内存(内存映射)

来源:互联网 发布:淘宝宝贝描述文字 编辑:程序博客网 时间:2024/06/06 17:24

本质:

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

直接访问内存,不用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);}


原创粉丝点击