1,建立共享映射区,将磁盘文件映射到内核区,并返回映射地址
include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<string.h>
#include<sys/mman.h>
int main()
{
pid_t pid;
pid = open("test.c", O_CREAT | O_RDWR, 0644);//打开文件
if(pid == -1)
{
perror("open fail");
exit(1);
}
ftruncate(pid, 4);//文件大小为4
char* p = NULL;
p = mmap(NULL, 4, PROT_READ | PROT_WRITE, MAP_SHARED, pid, 0);//将文件映射到内核
if(p == MAP_FAILED)//p为映射区首地址
{
perror("MAP failed");
exit(1);
}
strcpy(p,"abc");//共享映射区写入数据
munmap(p, 4);//
close(pid);
return 0;
}
父子进程通过mmap共享映射区进行通信
include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<string.h>
#include<sys/mman.h>
#include<sys/wait.h>
int var = 10;
int main()
{
pid_t pid;
pid = open("temp", O_CREAT | O_RDWR, 0644);
if(pid == -1)
{
perror("open fail");
exit(1);
}
ftruncate(pid, 4);
unlink("temp");//删除临时文件目录项,使之具备被释放条件
int* p;
p = mmap(NULL, 4, PROT_READ | PROT_WRITE, MAP_SHARED, pid, 0);
if(p == MAP_FAILED)
{
perror("MAP failed");
exit(1);
}
close(pid);//映射区建立完毕,可以提前关闭文件
pid_t q;
q = fork();
if(q == -1)
{
perror("create fail");
exit(1);
}
else if(q == 0)
{
*p = 2000;
var = 1000;
printf("*p = %d, var = %d\n", *p, var);
}
else
{
sleep(1);
printf("*p = %d, var = %d\n", *p, var);
wait(NULL);
munmap(p, 4);//释放映射区
}
return 0;
}
2,匿名映射区
使用映射区来完成文件读写操作十分方便,但是每次创建映射区都要依赖一个文件才能实现,比较麻烦。可以直接用匿名映射区来代替。
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<string.h>
#include<sys/mman.h>
#include<sys/wait.h>
int var = 10;
int main()
{
int* p;
p = mmap(NULL, 4, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);//创建匿名映射区
if(p == MAP_FAILED)
{
perror("MAP failed");
exit(1);
}
pid_t q;
q = fork();
if(q == -1)
{
perror("create fail");
exit(1);
}
else if(q == 0)
{
*p = 2000;
var = 1000;
printf("child, *p = %d, var = %d\n", *p, var);
}
else
{
sleep(1);
printf("parent, *p = %d, var = %d\n", *p, var);
wait(NULL);
munmap(p, 4);
}
return 0;
}
3,无血缘关系的进程间利用mmap进行通信
mmap_w.c
不断更改写入
#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<sys/mman.h>
#include<unistd.h>
#include<string.h>
struct stu
{
int id;
char name[20];
char sex;
};
void sys_err(char* err)
{
perror(err);
exit(-1);
}
int main(int argc, char* argv[])
{
if(argc < 2)
{
printf("./mmap_w file_share");
exit(1);
}
int fd = open(argv[1], O_CREAT | O_TRUNC | O_RDWR, 0644);
if(fd == -1)
sys_err("open file fail");
struct stu student = {18, "xiaoming", 'm'};
ftruncate(fd, sizeof(student));
struct stu* mm;
mm = mmap(NULL, sizeof(student), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if(mm == MAP_FAILED)
sys_err("mmap fail");
close(fd);
while(1)
{
memcpy(mm, &student, sizeof(student));
student.id++;
sleep(5);
}
munmap(mm, sizeof(student));
return 0;
}
不断读出 mmap_r.c
include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>
#include<sys/mman.h>
#include<unistd.h>
#include<string.h>
struct stu
{
int id;
char name[20];
char sex;
};
void sys_err(char* err)
{
perror(err);
exit(-1);
}
int main(int argc, char* argv[])
{
if(argc < 2)
{
printf("./mmap_w file_share\n");
exit(2);
}
int fd = open(argv[1], O_RDONLY);
if(fd == -1)
sys_err("open file fail");
struct stu student;
struct stu* mm;
mm = mmap(NULL, sizeof(student), PROT_READ, MAP_SHARED, fd, 0);
if(mm == MAP_FAILED)
sys_err("mmap fail");
close(fd);
while(1)
{
printf("id = %d, name = %s, sex = %c\n", mm->id, mm->name, mm->sex);
sleep(2);
}
munmmap(mm, sizeof(student));
return 0;
}