函数
#include<sys/mman.h>
/* 申请内存并映射 */
void mmap(void *addr, size_t len, int prot,int flags, int fildes, off_t off)
/* 同步数据 */
int msync(void *addr, size_t len, int flags);
/* 解除映射,并释放内存 */
int munmap(void *addr, size_t len);
/* 参数:
fd:为即将映射到进程空间的文件描述字,一般由open()返回,同时,fd可以指定为-1,此时须指定flags参数中的MAP_ANON,表明进行的是匿名映射(不涉及具体的文件名,避免了文件的创建及打开,很显然只能用于具有亲缘关系的进程间进行通信)。
len:是映射到调用进程地址空间的字节数,它从被映射文件开头offset个字节开始算起。
prot:指定空想内存的访问权限。可取如下几个值的或:PROT_READ(可读)、PROT_WRITE(可写)、PROT_EXEC(可执行)、PROT_NONE(不可访问)。
flag:由以下几个常值指定:MAP_SHARED、MAP_PRIVATE、MAP_FIXED,其中,MAP_SHARED,MAP_PRIVATE必选其一,而MAP_FIXED则不推荐使用。
offset:一般设为0,表示从文件头开始映射。
addr:指定文件应被映射到进程空间的起始地址,一般被指定一个空指针,此时选择起始地址的任务留给内核来完成。
*/
/* 返回值:
成功:文件映射到进程空间的地址,进程可直接操作起始地址为该值的有效地址。
失败:(void*)-1
*/
匿名映射实现父子进程通信
#include <stdio.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
/* 定义共享内存块的数据结构 */
struct data
{
int num;
char str[64];
};
int main()
{
/* 匿名映射,创建一块内存共父子进程通信 */
struct data* exam = mmap(NULL,sizeof(struct data),PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1,0);
pid_t pid = fork();
if(pid < 0)
{
perror("fork");
exit(-1);
}
else if(pid == 0)
{
for(int i = 0; i<5; i++)
{ /* 子进程循环写五次 */
exam->num = i;
strcpy(exam->str,"Hello world!");
sleep(1);
}
}
else
{ /* 父进程循环读取五次 */
for(int i = 0; i < 5; i++)
{
printf("%d:%s\n",exam->num,exam->str);
sleep(1);
}
}
}
╭─lingyun@manjaro ~/Document/codes
╰─➤ gcc forblog.c
╭─lingyun@manjaro ~/Document/codes
╰─➤ ./a.out
0:Hello world!
0:Hello world!
1:Hello world!
2:Hello world!
4:Hello world!
╭─lingyun@manjaro ~/Document/codes
共享内存映射实现两个进程之间的通信
/* 写进程: forblog.c */
#include <stdio.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
struct data
{
int num;
char str[64];
};
int main()
{
int fd = open("./hello", O_RDWR | O_CREAT,0777);
if(fd < 0)
{
perror("open");
exit(-1);
}
/* 扩展文件大小,否则会出现总线错误 */
lseek(fd,sizeof(struct data),SEEK_SET);
write(fd,"\0",1);
/* 创建一块内存供进程通信 */
struct data* exam = mmap(NULL,sizeof(struct data),PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if(exam == (void*)-1)
{
perror("mmap");
exit(-1);
}
for(int i = 0; i<5; i++)
{ /* 循环写五次 */
exam->num = i;
strcpy(exam->str,"Hello world!");
sleep(1);
}
munmap(exam,sizeof(struct data));
close(fd);
return 0;
}
/* 读进程: forblog2.c */
#include <stdio.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
struct data
{
int num;
char str[64];
};
int main()
{
int fd = open("./hello", O_RDWR | O_CREAT,0777);
if(fd < 0)
{
perror("open");
exit(-1);
}
/* 创建一块内存供进程通信 */
struct data* exam = mmap(NULL,sizeof(struct data),PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
if(exam == (void*)-1)
{
perror("mmap");
exit(-1);
}
for(int i = 0; i<5; i++)
{ /* 循环读五次 */
printf("%d:%s\n",exam->num,exam->str);
sleep(1);
}
munmap(exam,sizeof(struct data));
close(fd);
return 0;
}
╭─lingyun@manjaro ~
╰─➤ gcc forblog.c -o write
╭─lingyun@manjaro ~/Document/codes
╰─➤ ./write
╭─lingyun@manjaro ~
╰─➤ gcc forblog2.c -o read
╭─lingyun@manjaro ~/Document/codes
╰─➤ ./read
1:Hello world!
2:Hello world!
3:Hello world!
4:Hello world!
4:Hello world!
╭─lingyun@manjaro ~/Document/codes