mmap函数参数讲解

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

mmap函数参数讲解1.mmap-创建内存映射
作⽤:将磁盘⽂件的数据映射到内存,⽤户通过内存就能修改磁盘⽂件
函数原型:
void *mmap{
void *addr; //映射区⾸地址,传NULL
size_t length; //映射区的⼤⼩
//会⾃动调为4k的整数倍
//不能为0
//⼀般⽂件多⼤,length就指定多⼤
int prot; //映射区权限
//PROT_READ 映射区⽐必须要有读权限
//PROT_WRITE
//PROT_READ | PROT_WRITE
int flags; //标志位参数
//MAP_SHARED 修改了内存数据会同步到磁盘
//MAP_PRIVATE 修改了内存数据不会同步到磁盘
int fd; //要映射的⽂件对应的fd
off_t offset; //映射⽂件的偏移量,从⽂件的哪⾥开始操作
//映射的时候⽂件指针的偏移量
//必须是4k的整数倍
//⼀般设置为0
}
返回值:
映射区的⾸地址-调⽤成功
调⽤失败:MAP_FALED
2.munmap-释放内存映射区
函数原型:int munmap(void *addr,size_t length);
addr-mmap的返回值
length-mmap的第⼆个参数
3.注意事项
问:如果对mmap的返回值(ptr)做++操作(ptr++), munmap是否能够成功?
答:不能
问:如果open时O_RDONLY, mmap时prot参数指定PROT_READ | PROT_WRITE会怎样? 答mmap调⽤失败
open⽂件指定权限应该⼤于等于mmap第三个参数prot指定的权限
问:如果⽂件偏移量为1000会怎样?
答:必须是4096的整数倍
问:mmap什么情况下会调⽤失败?
第⼆个参数length = 0
第三个参数必须指定PROT_READ
fd对应的打开权限必须⼤于等于port权限
偏移量:必须是4096的整数倍
问:可以open的时候O_CREAT⼀个新⽂件来创建映射区吗?
答:可以,需要做⽂件拓展
lseek
truncate(path,length)
问:mmap后关闭⽂件描述符,对mmap映射有没有影响?
答:没有
问:对ptr越界操作会怎样?
答:段错误
4.mmap使⽤
(1)基本代码
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <sys/mman.h>
#include <fcntl.h>
int main(int argc, const char* argv[])
{
//打开⼀个⽂件
int fd=open("english.txt",O_RDWR);
int len=lseek(fd,0,SEEK_END);
//创建内存映射区
void *ptr=mmap(NULL,len,PROT_READ | PROT_WRITE,MAP_SHARED,fd,0); if(ptr==MAP_FAILED)
{
perror("mmap error");
exit(1);
}
printf("%s",(char*)ptr);
//释放内存映射区
munmap(ptr,len);
close(fd);
return 0;
}
运⾏结果:
wangkai@wangkai-HP-242-G1-Notebook-PC:~/0110/6Day$ ./mmap sadaskdkasj
sdasdasd
asdasdsadasds
dasdas
(2)使⽤mmap进⾏有⾎缘关系的进程间通信
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <fcntl.h>
/*
利⽤mmap进⾏⽗⼦间通信,效率⽐⽂件I/O⾼,
数据不是从磁盘上读,⽽是从内存上读写
不阻塞,所以读之前⼀定要写好
*/
int main(int argc, const char* argv[])
{
//打开⼀个⽂件
int fd=open("english.txt",O_RDWR);
int len=lseek(fd,0,SEEK_END);
//创建内存映射区
void *ptr=mmap(NULL,len,PROT_READ | PROT_WRITE,MAP_SHARED,fd,0); if(ptr==MAP_FAILED)
{
perror("mmap error");
exit(1);
}
close(fd);
//创建⼦进程
pid_t pid=fork();
if(pid==-1)
{
perror("fork error");
exit(1);
}
if(pid>0)
{
//写数据
strcpy((char*)ptr,"我是你爸爸");
//回收⼦进程
wait(NULL);
}
else if(pid==0)
{
//读数据
printf("%s\n",(char*)ptr);
}
printf("%s",(char*)ptr);
//释放内存映射区
munmap(ptr,len);
return 0;
}
(3)创建匿名映射区
int len=4096;
//创建匿名内存映射区,不指定⽂件
void *ptr=mmap(NULL,len,PROT_READ | PROT_WRITE,MAP_SHARED | MAP_ANON,-1,0);效果和(2)⼀样。

(4)没有⾎缘关系的进程间通信
写代码
//mmap_w_ipc.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
int fd = open("temp", O_RDWR | O_CREAT, 0664);
void* ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if(ptr == MAP_FAILED)
{
perror("mmap");
exit(1);
}
while(1)
{
char*p = (char*)ptr;
p += 1024;
strcpy(p, "hello parent, i am your 朋友\n");
sleep(2);
}
// 释放
int ret = munmap(ptr, 8192);
if(ret == -1)
{
perror("munmap");
exit(1);
}
return 0;
}
读代码
//mmap_r_ipc.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
int fd = open("temp", O_RDWR | O_CREAT, 0664);
ftruncate(fd, 4096);
int len = lseek(fd, 0, SEEK_END);
void* ptr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if(ptr == MAP_FAILED)
{
perror("mmap");
exit(1);
}
while(1)
{
sleep(1);
printf("%s\n", (char*)ptr+1024);
}
// 释放
int ret = munmap(ptr, len);
if(ret == -1)
{
perror("munmap");
exit(1);
}
return 0;
}
⼩结
1. 进程间通信
a. 有⾎缘关系的
⽗⼦进程共享内存映射区
b. 没有⾎缘关系的进程间通信
i. 如何通信?
不能使⽤匿名映射的⽅式
只能借助磁盘⽂件创建映射区 - hello
不阻塞
ii. a(a.c) b(b.c)
a.c
int fd = open("hello");
void* ptr = mmap(,,,,,fd, 0);
对映射区进⾏读写操作
b.c
int fd1 = open("hello");
void* ptr1 = mmap(,,,,fd1, 0);
对映射区做读写操作
2. mmap 实现内存映射
a. 必须有⼀个⽂件
b. ⽂件数据什么时候有⽤:
i. 单纯⽂件映射
ii. 进程间通信:
1) ⽂件数据是没有⽤的
3. 如果创建匿名映射区
mmap的时候:
第⼆个参数:指定映射区⼤⼩
第四个参数:需要添加MAP_ANON宏 第五个参数:-1
4. ⽗⼦进程永远共享的东西?
⽂件描述符
内存映射区。

相关文档
最新文档