【linux】磁盘映射mmap及共享内存
目录一、mmap存储映射1、mmap概述2、mmap的API及步骤1建立文件和内存的映射2拓展文件大小3释放映射区域只能解除本进程的映射3、案例二、共享内存1、共享内存的概述2、API及步骤1获得一个唯一共享存储标识符2建立进程的虚拟内存 和 物理内存的映射3解除共享映射区4共享内存控制3、案例一、mmap存储映射1、mmap概述存储映射I/O (Memory-mapped I/O) 使一个磁盘文件与存储空间中的一个缓冲区相映射。 是当从缓冲区中取数据就相当于读文件中的相应字节。于此类似将数据存入缓冲区则相应的字节就自动写入文件。2、mmap的API及步骤1建立文件和内存的映射#includesys/mman.hvoid *mmap(void *addr, size_t length, int prot, int flagsint fd, off_t offset);addr 地址填NULLlength 长度 要申请的映射区的长度prot 权限PROT_READ 可读PROT_WRITE 可写flags 标志位MAP_SHARED 共享的 -- 对映射区的修改会影响源文件MAP_PRIVATE 私有的fd 文件描述符 需要打开一个文件offset 指定一个偏移位置 从该位置开始映射返回值成功 返回映射区的首地址失败 返回 MAP_FAILED ((void *) -1)2拓展文件大小#includeunistd.h#includesys/types.hint truncate(const char *path, off_t length);path 要拓展的文件length 要拓展的长度3释放映射区域只能解除本进程的映射int munmap(void *addr, size_t length);addr 映射区的首地址length 映射区的长度返回值成功 返回0失败 返回 -13、案例write.c#include stdio.h #include sys/types.h #include sys/stat.h #include fcntl.h #include sys/mman.h #include unistd.h #include string.h int main(int argc, char const *argv[]) { //通过open事先打开文件 int fd open(tmp, O_RDWR | O_CREAT, 0666); if (fd 0) { perror(open); return 0; } //拓展文件大小 truncate(tmp, 16); //建立映射 char *buf (char *)mmap(NULL, 16, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); //使用区域 strcpy(buf, hello mmap); //断开映射 munmap(buf, 16); return 0; }read.c#include stdio.h #include sys/types.h #include sys/stat.h #include fcntl.h #include sys/mman.h #include unistd.h int main(int argc, char const *argv[]) { //通过open事先打开文件 int fd open(tmp, O_RDWR | O_CREAT, 0666); if (fd 0) { perror(open); return 0; } //拓展文件大小 truncate(tmp, 16); //建立映射 char *buf (char *)mmap(NULL, 16, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); //使用区域 printf(%s\n, buf); //断开映射 munmap(buf, 16); return 0; }二、共享内存1、共享内存的概述共享内存允许两个或者多个进程共享给定的存储区域。共享内存的特点1、共享内存是进程间共享数据的一种最快的方法。 一个进程向共享的内存区域写入 了数据共享这个内存区域的所有进程就可以立刻看到其中的内容。2、使用共享内存要注意的是多个进程之间对一个给定存储区访问的互斥。 若一个进 程正在向共享内存区写数据则在它做完这一步操作前别的进程不应当去读、写这些数 据。共享存储区的最小字节数1共享存储区的最大字节数32M共享存储区的最大个数4096每个进程最多能映射的共享存储区的个数40962、API及步骤1获得一个唯一共享存储标识符#includesys/ipc.h#includesys/shm.hint shmget(key_t key, size_t size,int shmflg);功能:创建或打开一块共享内存区参数:keyIPC键值size该共享存储段的长度(字节)shmflg标识函数的行为及共享内存的权限。参数:shmflgIPC_CREAT如果不存在就创建IPC_EXCL如果已经存在则返回失败位或权限位共享内存位或权限位后可以设置共享内存的访问权限格式和 open函数的mode_t一样但可执行权限未使用。返回值:成功返回共享内存标识符。失败返回1使用shell命令操作共享内存: 查看共享内存 ipcs -m 删除共享内存 ipcrm -m shmid2建立进程的虚拟内存 和 物理内存的映射#includesys/types.h#includesys/shm.hvoid *shmat(int shmid, const void *shmaddr,int shmflg);功能 将一个共享内存段映射到调用进程的数据段中。参数shmid共享内存标识符。shmaddr共享内存映射地址(若为NULL则由系统自动指定)推荐使用NULL。shmflg共享内存段的访问权限和映射条件0共享内存具有可读可写权限。SHM_RDONLY只读。SHM_RNDshmaddr非空时才有效没有指定SHM_RND则此段连接到shmaddr所指定的地址上(shmaddr必需 页对齐)。指定了SHM_RND则此段连接到shmaddr- shmaddr%SHMLBA 所表示的 地址上。返回值成功返回共享内存段映射地址失败返回 -1注意: shmat函数使用的时候第二个和第三个参数一般设为NULL和0即系统自动指定共 享内存地址并且共享内存可读可写3解除共享映射区#includesys/types.h#include sys/shm.hint shmdt(const void *shmaddr);功能 将共享内存和当前进程分离(仅仅是断开联系并不删除共享内存)。参数 shmaddr共享内存映射地址。返回值 成功返回 0失败返回 -1。4共享内存控制#includesys/ipc.h#includesys/shm.hint shmctl(int shmid, int cmd, struct shmid_ds *buf);功能共享内存空间的控制。参数shmid共享内存标识符。cmd函数功能的控制。IPC_RMID删除。IPC_SET设置shmid_ds参数。IPC_STAT保存shmid_ds参数。SHM_LOCK锁定共享内存段(超级用户)。SHM_UNLOCK解锁共享内存段。bufshmid_ds数据类型的地址用来存放或修改共享内存的属性。返回值 成功返回 0失败返回 -13、案例write.c#include stdio.h #include sys/types.h //ftok #include sys/ipc.h //ftok #include sys/shm.h //shmget #include string.h int main(int argc, char const *argv[]) { //获取唯一的key key_t key ftok(/, 2022); //获取共享内存的标示分配物理内存 int shm_id shmget(key, 32, IPC_CREAT | 0666); //将虚拟内存 和 物理内存 建立映射 char *buf (char *)shmat(shm_id, NULL, 0); //操作虚拟内存 strcpy(buf, hello shm); //释放映射 shmdt(buf); return 0; }read.c#include stdio.h #include sys/types.h //ftok #include sys/ipc.h //ftok #include sys/shm.h //shmget #include string.h int main(int argc, char const *argv[]) { //获取唯一的key key_t key ftok(/, 2022); //获取共享内存的标示分配物理内存 int shm_id shmget(key, 32, IPC_CREAT | 0666); //将虚拟内存 和 物理内存 建立映射 char *buf (char *)shmat(shm_id, NULL, 0); //操作虚拟内存 printf(%s\n, buf); //释放映射 shmdt(buf); return 0; }