unsigned long
get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
unsigned long pgoff, unsigned long flags)
在当前进程的用户空间中获得一个未映射的起始地址.
其在do_mmap中有使用这个函数。
其源码分析如下:
unsigned long
get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
unsigned long pgoff, unsigned long flags)
{
unsigned long (*get_area)(struct file *, unsigned long,
unsigned long, unsigned long, unsigned long);
#针对特定平台的检查,目前arm64中arch_mmap_check 是一个空函数
unsigned long error = arch_mmap_check(addr, len, flags);
if (error)
return error;
#申请虚拟空间的地址不能超过最大值。这里可以知道虚拟空间size 的最大值就是TASK_SIZE
/* Careful about overflows.. */
if (len > TASK_SIZE)
return -ENOMEM;
#指向当前进程的unmap 空间的分配函数
get_area = current->mm->get_unmapped_area;
#file 不为空的话,则unmap 空间的分配函数执行file中指定的函数
if (file) {
if (file->f_op->get_unmapped_area)
get_area = file->f_op->get_unmapped_area;
} else if (flags & MAP_SHARED) {
#如果file为空,说明可能申请的是匿名空间,这里检查如果是共享内存的话,则分配函数执行共享内存的分配函数
/*
* mmap_region() will call shmem_zero_setup() to create a file,
* so use shmem's get_unmapped_area in case it can be huge.
* do_mmap_pgoff() will clear pgoff, so match alignment.
*/
pgoff = 0;
get_area = shmem_get_unmapped_area;
}
#使用前面已经指定的分配函数来在未映射的虚拟空间中映射的空间中申请.
addr = get_area(file, addr, len, pgoff, flags);
if (IS_ERR_VALUE(addr))
return addr;
#addr +len 不能大于TASK_SIZE
if (addr > TASK_SIZE - len)
return -ENOMEM;
#检查分配到的地址是否已经被映射,如果已经被映射则返回error,毕竟我们这里要分配的是进程未映射的空间。
if (offset_in_page(addr))
return -EINVAL;
#secure检查
error = security_mmap_addr(addr);
return error ? error : addr;
}
内存管理API之get_unmapped_area
最新推荐文章于 2023-03-01 23:56:18 发布