mmap()函数 (转载+整理)

内存映射区

存储映射I/O (Memory-mapped I/O) 使一个磁盘文件与存储空间中的一个缓冲区相映射。从缓冲区中取数据,就相当于读文件中的相应字节;将数据写入缓冲区,则会将数据写入文件。这样,就可在不使用read和write函数的情况下,使用地址(指针)完成I/O操作。
使用存储映射这种方法,首先应通知内核,将一个指定文件映射到存储区域中。这个映射工作可以通过mmap函数来实现。
在这里插入图片描述
内存映射 mmap的理解

mmap()函数

函数作用

建立存储映射区

函数原型

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
返回值
成功:返回创建的映射区首地址
失败:MAP_FAILED宏
函数参数

  • addr:指定映射的起始位置,通常设置成NULL,由系统指定
  • length:映射到内存的文件长度
  • prot:映射区的保护方式,最常用:
    读:PROT_READ
    写:PROT_WRITE
    读写:PROT_READ | PROT_WRITE
  • flags:映射区的特性,可以是
    MAP_SHARED:写入映射区的数据会写回文件,且允许其他映射该文件的进程共享
    MAP_PRIVATE:对映射区的会产生一个映射区的复制(copy-on-write),对此区域所做的修改不会写回原文件。
  • fd:由open()返回的文件描述符,代表要映射的文件
  • offset:以文件开始处的偏移量,必须是4k的整数倍,通常为0,表示从文件头开始映射。
    [注]mmap使用细节
    1.mmap映射区域大小必须是物理页大小(page_size)的整倍数(32位系统中通常是4k字节)。原因是,内存的最小粒度是页,而进程虚拟地址空间和内存的映射也是以页为单位。为了匹配内存的操作,mmap从磁盘到虚拟地址空间的映射也必须是页。
    2. 内核可以跟踪被内存映射的底层对象(文件)的大小,进程可以合法的访问在当前文件大小以内又在内存映射区以内的那些字节。也就是说,如果文件的大小一直在扩张,只要在映射区域范围内的数据,进程都可以合法得到,这和映射建立时文件的大小无关。具体情形参见“情形三”。
    3. 映射建立之后,即使文件关闭,映射依然存在。因为映射的是磁盘的地址,不是文件本身,和文件句柄无关。同时可用于进程间通信的有效地址空间不完全受限于被映射文件的大小,因为是按页映射。

内存映射 mmap的理解

//使用mmap函数完成父子进程间通信
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
int main()
{
	//使用mmap函数建立共享映射区
	//void *mmap(void *addr, size_t length, int prot, int flags,
    //              int fd, off_t offset);
	int fd = open("./test.log", O_RDWR);
	if(fd<0)
	{
		perror("open error");
		return -1;
	}
	int len = lseek(fd, 0, SEEK_END);

	void * addr = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);//
	//void * addr = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
	if(addr==MAP_FAILED)
	{
		perror("mmap error");
		return -1;
	}
	close(fd);

	//创建子进程
	pid_t pid = fork();
	if(pid<0) 
	{
		perror("fork error");
		return -1;
	}
	else if(pid>0)
	{
		memcpy(addr, "hello world", strlen("hello world"));	
		wait(NULL);
	}
	else if(pid==0)
	{
		sleep(1);
		char *p = (char *)addr;
		printf("[%s]", p);
	}

	return 0;
}

在这里插入图片描述
程序运行之后
在这里插入图片描述
在这里插入图片描述

  • 6
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值