Linux-内存共享映射
进程间通信-内存共享映射
进程间通信-内存共享映射
一、简述
-
mmap()
系统调用使得进程之间通过映射同一个普通文件实现共享内存
。普通文件被映射到进程地址空间
后,进程可以向访问普通内存一样对文件进行访问,不必再调用read(),write()等操作。 -
mmap()
的作用是映射文件描述符fd指定文件的[off,off + len]
区域至调用进程的[addr, addr + len]
的内存区域, 如下图所示:
二、mmap 函数
功能:
mmap() 可以把磁盘文件的一部分直接映射到内存,这样文件中的位置直接就有对应的内存
地址,对文件的读写可以直接用指针来做而不需要read/write函数。
头文件:
#include <sys/mman.h>
函数原型:
void* mmap ( void * addr , size_t len , int prot ,
int flags , int fd , off_t offset )
参数说明:
-
addr
:指定文件应被映射到进程空间的起始地址,一般被指定一个空指针,此时选择起始地址的任务留给内核来完成。 -
len
:是映射到调用进程地址空间的字节数,它从被映射文件开头offset个字节开始算起。 -
prot
:指定空想内存的访问权限。可取如下几个值的或:PROT_READ(可读)、PROT_WRITE(可写)、PROT_EXEC(可执行)、PROT_NONE(不可访问)。 -
flag
:由以下几个常值指定:MAP_SHARED、MAP_PRIVATE、MAP_FIXED,其中,MAP_SHARED,MAP_PRIVATE必选其一,而MAP_FIXED则不推荐使用。-
MAP_SHARED:多个进程对同一个文件的映射是共享的,一个进程对映射的内存做了修
改,另一个进程也会看到这种变化。
-
MAP_PRIVATE:多个进程对同一个文件的映射不是共享的,一个进程对映射的内存做了修
改,另一个进程并不会看到这种变化,也不会真的写到文件中去。
-
MAP_SHARED:多个进程对同一个文件的映射是共享的,一个进程对映射的内存做了修
-
fd
:为即将映射到进程空间的文件描述字,一般由open()返回,同时,fd可以指定为-1,此时须指定flags参数中的MAP_ANON,表明进行的是匿名映射(不涉及具体的文件名,避免了文件的创建及打开,很显然只能用于具有亲缘关系的进程间进行通信)。 -
offset
:表示偏移量,一般设为0,表示从文件头开始映射。
返回值:
函数的返回值为最后文件映射到进程空间的地址,进程可直接操作起始地址为该值的有效地址。
三、应用示例
mmap_w.c
/* process_mmap_w.c*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#define MAPLEN 0x1000
struct STU {
int id;
char name[20];
char sex;
};
void sys_err(char *str, int exitno) {
perror(str);
exit(exitno);
}
int main(int argc, char *argv[]) {
struct STU *mm;
int fd, i = 0;
if (argc < 2) {
printf("./a.out filename\n");
exit(1);
}
fd = open(argv[1], O_RDWR | O_CREAT, 0777);
if (fd < 0)
sys_err("open", 1);
if (lseek(fd, MAPLEN-1, SEEK_SET) < 0)
sys_err("lseek", 3);
if (write(fd, "\0", 1) < 0)
sys_err("write", 4);
mm = mmap(NULL, MAPLEN, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if (mm == MAP_FAILED)
sys_err("mmap", 2);
close(fd);
while (1) {
mm->id = i;
sprintf(mm->name, "zhang-%d", i);
if (i % 2 == 0)
mm->sex = 'm';
else
mm->sex = 'w';
i++;
sleep(1);
}
munmap(mm, MAPLEN);
return 0;
}
mmap_r.c
/* process_mmap_r.c*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#define MAPLEN 0x1000
struct STU {
int id;
char name[20];
char sex;
};
void sys_err(char *str, int exitno) {
perror(str);
exit(exitno);
}
int main(int argc, char *argv[]) {
struct STU *mm;
int fd, i = 0;
if (argc < 2) {
printf("./a.out filename\n");
exit(1);
}
fd = open(argv[1], O_RDWR);
if (fd < 0)
sys_err("open", 1);
mm = mmap(NULL, MAPLEN, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if (mm == MAP_FAILED)
sys_err("mmap", 2);
close(fd);
unlink(argv[1]);
while (1) {
printf("%d\n", mm->id);
printf("%s\n", mm->name);
printf("%c\n", mm->sex);
sleep(1);
}
munmap(mm, MAPLEN);
return 0;
}
运行结果:
进程1:写
进程2:读
参考来源:
https://blog.****.net/windgs_yf/article/details/81146887