概述
mmap函数
1.创建映射区
void *mmap(void *adrr,size_t length,int prot,int flags,int fp,off_t offset);
addr:建立映射区的首地址,直接传NULL
length:映射区的大小
prot:映射区权限PROT_READ,PROT_WRITE,PROT_READ|PROT_WRITE
flags:标志位参数,MAP_SHARED将映射区所做的操作反映到物流设备(磁盘)上(父子进程可以共享映射区)
MAP_PRIVATE不反映(父子进程不共享映射区,各自独占)。
offset:映射文件的偏移(4k的整数倍)为0时表示起始位置。
成功:返回映射区的首地址,失败:返回MAP_FAILED
- 新建立的文件不能创建映射区,也就是说,不能创建大小为0的映射区
- 可以在堆区开辟大小为0的空间(void *malloc(unsigned int size));
- 映射区的权限要 <= 打开文件的权限
- 映射区创建的过程中隐含一次对文件的读操作
- 父子进程共享mmap建立的映射区,和打开的文件
- 当mmap中的flags参数设置成MAP_PRIVATE时,父子进程各自独占映射区,不共享。
2.关闭映射区
int munmap(void *addr,size_t length);
```c
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/mman.h>
#include<string.h>
int main()
{
int fp = open("test",O_RDWR | O_CREAT,0644);
if(fp == -1)
{
perror("open error:");
exit(1);
}
int file_len = truncate("test",1024);
if(file_len == -1)
{
perror("truncate error");
exit(1);
}
char *mp = NULL;
mp = mmap(NULL,1024,PROT_READ | PROT_WRITE,MAP_SHARED,fp,0);
if(mp == MAP_FAILED)
{
perror("mmap error:");
exit(1);
}
else
{
strcpy(mp,"6666666666666666666n");
int nump = munmap(mp,1024);
if(nump == -1)
{
perror("munmap error:");
exit(1);
}
close(fp);
}
return 0;
}
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/mman.h>
#include<sys/wait.h>
int variety = 666;
int main()
{
int fp = open("test",O_RDWR | O_CREAT | O_TRUNC,0644);
if(fp == -1)
{
perror("open error:");
exit(1);
}
ftruncate(fp,512);
int len = lseek(fp,0,SEEK_END);
printf("the length of test is:%dn",len);
int *mp;
mp = mmap(NULL,len,PROT_READ | PROT_WRITE,MAP_SHARED,fp,0);
if(mp == MAP_FAILED)
{
perror("mmap error:");
exit(1);
}
close(fp);
int ul = unlink("test");
if(ul == 0)
{
printf("file is deleted successfuln");
}
pid_t pid = fork();
if(pid == 0)
{
printf("I am childn");
*mp = 999;
variety = 888;
printf("*mp = %d,variety = %dn",*mp,variety);
}
else
{
sleep(1);
printf("I am fathern");
printf("*mp = %d,variety = %dn",*mp,variety);
wait(NULL);
}
int numap = munmap(mp,len);
if(numap == -1)
{
perror("numap error:");
exit(1);
}
return 0;
}
匿名映射:
- 无需依赖一个文件即可建立映射区
- 在参数flags中加入:MAP_ANONYMOUS(ANON)
```cpp
int*p=mmap(NULL,4,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,O);
- 需注意的是,MAP_ANONYMOUS和MAP_ANON这两个宏是Linux操作系统特有的宏。在类Unix系统中如无宏定义,可使用如下两步来完成匿名映射区的建立。
int fd=open("/dev/zero",O_RDWR);
p=mmap(NULL,size,PROT_READ|PROT_WRITE,MMAP_SHARED,fd,0);
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/mman.h>
#include<sys/wait.h>
int variety = 666;
int main()
{
int *mp;
mp = mmap(NULL,128,PROT_READ | PROT_WRITE,MAP_SHARED | MAP_ANON,-1,0);
if(mp == MAP_FAILED)
{
perror("mmap error:");
exit(1);
}
pid_t pid = fork();
if(pid == 0)
{
printf("I am childn");
*mp = 999;
variety = 888;
printf("*mp = %d,variety = %dn",*mp,variety);
}
else
{
sleep(1);
printf("I am fathern");
printf("*mp = %d,variety = %dn",*mp,variety);
wait(NULL);
}
int numap = munmap(mp,128);
if(numap == -1)
{
perror("numap error:");
exit(1);
}
return 0;
}
总结:使用mmap时务必注意以下事项:
1.创建映射区的过程中,隐含着一次对映射文件的读操作。
2.当MAP_SHARED时,要求:映射区的权限应<=文件打开的权限(出于对映射区的保护)。而MAP_PRIVATE则无所谓,因为mmapf的权限是对内存的限制。
3.映射区的释放与文件关闭无关。只要映射建立成功,文件可以立即关闭。
4.特别注意,当映射文件大小为0时,不能创建映射区。所以:用于映射的文件必须要有实际大小!mmap.使用时常常会出现总线错误,通常是由于共享文件存储空间大小引起的。
5.munmap.传入的地址一定是mmap的返回地址。坚决杜绝指针++/- -操作。
6.offset文件偏移量必须为4K的整数倍
7.mmap创建映射区出错概率非常高,一定要检查返回值,确保映射区建立成功再进行后续操作。
8.因为创建mmap函数比较容易出错,所以创建完成后一定要通过判断返回值来确定是否创建成功
将结构体写入文件中
#include<sys/mman.h>
#include<sys/wait.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
struct stu{
int num;
char name[16];
int class;
};
int main(int argc,char *argv[])
{
struct stu student = {1,"zjl",11};
if (argc<2)
{
printf("argument is lessn");
exit(1);
}
int fp = open(argv[1],O_RDWR | O_CREAT | O_TRUNC,0644);
int len = sizeof(student);
printf("student len is:%dn",len);
ftruncate(fp,128);
int length = lseek(fp,0,SEEK_END);
printf("the len of fp is:%dn",length);
int *mp = mmap(NULL,len,PROT_WRITE | PROT_READ,MAP_SHARED,fp,0);
if(mp == MAP_FAILED)
{
perror("mmap error:");
exit(1);
}
close(fp);
while(1)
{
printf("enter while len is:%dn",len);
printf("student.name = %sn",student.name);
memcpy(mp,&student,64);
student.num++;
sleep(1);
}
int numap = munmap(mp,128);
if(numap == -1)
{
perror("numap error:");
exit(1);
}
return 0;
}
2个不相关进程间的通信
先写入shared_file文件中
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/mman.h>
#include<sys/wait.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
struct stu{
int num;
char name[16];
int class;
};
int main(int argc,char *argv[])
{
struct stu student = {1,"zjl",11};
int fp = open("sharerd_file",O_RDWR | O_CREAT | O_TRUNC,0644);
int len = sizeof(student);
printf("student len is:%dn",len);
ftruncate(fp,128);
int *mp = mmap(NULL,len,PROT_WRITE | PROT_READ,MAP_SHARED,fp,0);
if(mp == MAP_FAILED)
{
perror("mmap error:");
exit(1);
}
close(fp);
printf("start to write!!!n");
int n = 0;
while(1)
{
n += 1;
printf("[%d]writen",n);
memcpy(mp,&student,64);
student.num++;
student.class++;
sleep(1);
}
int numap = munmap(mp,128);
if(numap == -1)
{
perror("numap error:");
exit(1);
}
return 0;
}
再从文件中读出
#include<unistd.h>
#include<fcntl.h>
#include<sys/mman.h>
#include<sys/wait.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
struct stu{
int num;
char name[16];
int class;
};
int main(int argc,char *argv[])
{
struct stu student;
int fp = open("sharerd_file",O_RDONLY);
struct stu *mp = mmap(NULL,sizeof(student),PROT_READ,MAP_SHARED,fp,0);
if(mp == MAP_FAILED)
{
perror("mmap error:");
exit(1);
}
close(fp);
printf("开始接受!!!n");
while(1)
{
sleep(1);
printf("num = %d,name = %s,class = %dn",mp->num,mp->name,mp->class);
}
return 0;
}
最后
以上就是等待马里奥为你收集整理的mmap函数mmap函数匿名映射:的全部内容,希望文章能够帮你解决mmap函数mmap函数匿名映射:所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复