共享内存
共享内存可以通过mmap()映射普通文件
使一个磁盘文件与内存中的一个缓冲区相映射,进程可以像访问普通内存一样对文件进行访问,不必再调用read,write。
#include <sys/mman.h>
void *mmap(void *addr,size_t length,int prot,int flags,int fd,off_t offset);
注意事项:
创建映射区的过程中,隐含着一次对映射文件的读操作,将文件内容读取到映射区。
当MAP_SHARED时,要求:映射区的权限应<=文件打开的权限(出于对映射区的保护),如果不满足报非法参数(Invalid argument)错误。当MAP_PRIVATE时候,mmap中的权限是对内存的限制,只需要文件有读权限即可,操作只在内存有效,不会写到物理磁盘,且不能在进程间共享。
映射区的释放与文件无关,只要映射建立成功,文件可以立即关闭。
用于映射的文件大小必须>0,当映射文件大小为0时,指定非0大小创建映射区,访问映射地址会报总线错误,指定0大小创建映射区,报非法参数错误(Invalid argument)
文件偏移量必须为0或者4K的整数倍(不是会报非法参数Invalid argument错误)
映射区大小可以大于文件大小,但只能访问文件page的内存地址,否则报总线错误,超出映射的内存大小报段错误
mmap()映射的种类:
基于文件的映射
匿名映射:适用于具有亲缘关系的进程之间
释放内存映射
int munmap(void *addr,size_t length);
测试代码
写内存cpp
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stddef.h>
#include <string.h>
#include <sys/mman.h>
int main(){
void *addr;
int fd;
fd=open("test",O_RDWR);
int len=lseek(fd,0,SEEK_END);
addr=mmap(NULL,2048,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
if(addr==MAP_FAILED){
perror("mmap");
return 0;
}
close(fd);
int i=0;
while(i<2048){
memcpy((addr+i),"a",1);
i++;
sleep(1);
}
munmap(addr,2048);
return 0;
}
读内存cpp
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stddef.h>
#include <string.h>
#include <sys/mman.h>
int main(){
void *addr;
int fd;
fd=open("test",O_RDWR);
int len=lseek(fd,0,SEEK_END);
addr=mmap(NULL,2048,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
if(addr==MAP_FAILED){
perror("mmap");
return 0;
}
close(fd);
int i=0;
while(1){
printf("read=%s\n",(char*)addr);
sleep(1);
}
munmap(addr,2048);
return 0;
}
测试结果
system V共享内存
文件生成key值--ftok
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *path,int proj_id);
成功时返回合法的key值,失败时返回EOF。
path 存在且可访问的文件的路径。
proj_id 用于生成key的数值,1-255。
共享内存创建--shmget
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(key_t key,int size,int shmflg);
成功时返回合法的key值,失败时返回EOF。
key 和共享内存关联的key,IPC_PRIVATE或者ftok生成。
shmflg 共享内存标志位 IPC_CREATE|0666
共享内存映射--shmat
void *shmat(int shmid,const void *shmaddr,int shmflg);
成功时返回映射后的地址,失败时返回(void*)-1。
shmid 要映射的共享内存的id
shmaddr 映射后的地址,NULL表示系统自动映射
shmflg 标志位 0表示可读写;SHM_RDONLY表示只读
共享内存撤销映射--shmdt
int shmdt(void* shmaddr);
成功时返回0,失败时返回EOF
不使用共享内存时应撤销映射
进程结束时自动撤销
共享内存控制--shmctl
int shmctl(int shmid,int cmd,struct shmid_ds *buf);
成功时返回0,失败时返回EOF
shmid 要操作的共享内存的id
cmd 要执行的操作 IPC_STAT IPC_SET IPC _RMID(删除共享内存)
buf 保存或设置共享内存属性的地址