mmap源码分析--基于3.10.0-693.11.1

本文详细分析了Linux内核中mmap的实现过程,从mmap的原型到内核内部的mmap_pgoff、vm_mmap_pgoff、do_mmap_pgoff等函数,探讨了文件映射和匿名映射的机制。通过对get_unmapped_area和mmap_region的讲解,揭示了mmap如何在进程地址空间创建或扩展VMA,并讨论了内存映射在读写文件时的内存管理和cow策略。
摘要由CSDN通过智能技术生成

mmap是个既简单又好用的东西,对于读写文件,它减少了一次内存拷贝,对于内存申请,它可以方便的申请到大块内存,用于自己管理。今天就来说说mmap的实现。
mmap的原型是这样的:

void *mmap(void *addr, size_t length, int prot, int flags,
                  int fd, off_t offset);

它在内核里的样子是这样的:

SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,
		unsigned long, prot, unsigned long, flags,
		unsigned long, fd, unsigned long, off)
{
   
	long error;
	error = -EINVAL;
	if (off & ~PAGE_MASK)	//判断offset是否对齐到页大小,不是则返回-EINVAL退出
		goto out;

	error = sys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
out:
	return error;
}

这里调用了mmap_pgoff,不看代码都不知道有这个系统调用呢

SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
		unsigned long, prot, unsigned long, flags,
		unsigned long, fd, unsigned long, pgoff)
{
   
	struct file *file = NULL;
	unsigned long retval = -EBADF;

	if (!(flags & MAP_ANONYMOUS)) {
    //文件映射
		audit_mmap_fd(fd, flags);
		if (unlikely(flags & MAP_HUGETLB))
			return -EINVAL;
		file = fget(fd);	//获取file结构体
		if (!file)
			goto out;
		if (is_file_hugepages(file))
			len = ALIGN(len, huge_page_size(hstate_file(file)));//如果是hugetlbfs的文件,需要调整下len
	} else if (flags & MAP_HUGETLB) {
    //匿名映射大页内存
		struct user_struct *user = NULL;
		struct hstate *hs = hstate_sizelog((flags >> MAP_HUGE_SHIFT) &
						   SHM_HUGE_MASK);

		if (!hs)
			return -EINVAL;

		len = ALIGN(len, huge_page_size(hs)); //如果是hugetlbfs的文件,需要调整下len
		/*
		 * VM_NORESERVE is used because the reservations will be
		 * taken when vm_ops->mmap() is called
		 * A dummy user value is used because we are not locking
		 * memory so no accounting is necessary
		 */
		 //如果是大页映射,则从hugetlbfs中创建一个名为anon_hugepage的file结构体来
		file = hugetlb_file_setup(HUGETLB_ANON_FILE, len,
				VM_NORESERVE,
				&user, HUGETLB_ANONHUGE_INODE,
				(flags >> MAP_HUGE_SHIFT) & MAP_HUGE_MASK);
		if (IS_ERR(file))
			return PTR_ERR(file);
	}

	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); //这一行,目前还不懂它的用意在哪里,但并不影响我们分析 mmap代码,要是后面弄懂了呢:)

	//文件映射、匿名映射都会调到这里来
	retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff);
	if (file)
		fput(file);
out:
	return retval;
}

mmap_pgoff里主要是做了些准备,然后调用vm_mmap_pgoff进行映射,这个函数的用途是对进程的虚拟地址空间进行映射, 它的定义位于mm/util.c说明它个通用的工具函数。

unsigned long vm_mmap_pgoff(struct file *file, unsigned long addr,
	unsigned long len, unsigned long prot,
	unsigned long flag, unsigned long pgoff)
{
   
	unsigned long ret;
	struct mm_struct *mm = current
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值