Chinaunix
标题:
分配线性地址区间问题
[打印本页]
作者:
embeddedlwp
时间:
2011-09-04 17:15
标题:
分配线性地址区间问题
本帖最后由 embeddedlwp 于 2011-09-04 17:16 编辑
linux 2.6.11的内存管理部分,do_mmap_pgoff中有这么一段
munmap_back:
vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent);
if (vma && vma->vm_start < addr + len) {
if (do_munmap(mm, addr, len))
return -ENOMEM;
goto munmap_back;
}
复制代码
在ULK3 P371上的解释是find_vma_prepare()函数也检查是否还存在与新区间重叠的线性区。这种情况发生在函数返回一个非空的地址,这个地址指向一个线性区,而该区的起始地址位置位于新区间结束地址之前的时候。在这种情况下,do_mmap_pgoff()调用do_munmap()删除新的区间,然后重复整个步骤。
这里如果重复整个步骤,也就是重新执行find_vma_prepare,之前调用do_munmap释放了那个由get_unmmaped_area找到的空闲的地址空间,那个find_vma_prepare也没有分配地址空间的功能,那么程序怎么往下执行了啊?我感觉get_unmmaped_area找到的空闲地址空间一定是不与别的区间重叠的(否则返回NULL),这样这段code就不会执行了。
作者:
amarant
时间:
2011-09-05 08:15
沒看懂你說什麼。。
線性區不會有重複的
vma && vma->vm_start < addr + len
這個條件是檢測是不是傳入的地址與已存在的線性區重疊
如果是的話,先取消之前的映射再繼續
作者:
embeddedlwp
时间:
2011-09-05 09:33
回复
2#
amarant
呵呵,关键是如何继续,这里调用的do_munmap()已经把get_unmmaped_area()获得的线性地址区间取消掉了。没了线性区间怎么往下执行呢,求解惑!
作者:
amarant
时间:
2011-09-05 10:03
回复
3#
embeddedlwp
這個函數的作用就是為了分配線性區,如果所請求的線性區已經被映射了就先unmap,這樣才能實現函數的功能。。
作者:
embeddedlwp
时间:
2011-09-05 10:16
回复
4#
amarant
如果调用do_munmap()了,goto munmap_back;但是之后do_mmap()的操作中没有调用get_unmapped_area(),也就是这次释放这个线性区就不存在了,他也没有去获得新的线性区,函数也不会实现他的功能。
作者:
amarant
时间:
2011-09-05 10:41
记不清楚了,你自己好好看看吧
作者:
embeddedlwp
时间:
2011-09-05 10:43
回复
6#
amarant
奥呵呵,多谢了,刚才在linuxform看到04年有人提过这个问题,也是最后没人解决。
作者:
allen303allen
时间:
2011-09-05 17:16
感觉楼主有几个认识上的误区:
1. get_unmmaped_area()是不会创建一个线性区间的。
它只返回一个地址addr,确保从addr开始,长度为len的区间是没有被映射的(多数情况下)。真正分配线性区间的操作是后面的kmem_cache_zalloc分配一个vma结构,然后设置vma的start和end及其他字段,并加入到vma链表和红黑树中。这样一个线性区间才创建完毕。
2. 所贴这段代码的作用。
这段代码的目的是检查以确保addr开始,长度为len的区间内没有其他的映射区间,如果有,就要把那些区间释放,直到通过find_vma_prepare找不到vma或者找到的vma不在addr开始,长度为len的范围内。
find_vma_prepare肯定没有分配地址空间的功能,它只是找到第一个结束地址大于addr的vma。
所以只要确认了上面说的问题,就可以跳过这段代码往下执行了(往下去分配线性区间了)。
3. get_unmmaped_area()返回的addr并不一定是ok的。
也就是说该函数返回的addr,并不一定从它开始,长度为len的区间内一定没有其他的映射,arch_get_unmapped_area()函数中的开始就有个判断,如果flags中标记了MAP_FIXED,就直接返回传入的addr,根本不去找别的了。
所以只要用户指定了MAP_FIXED标记,除了对该地址做页对齐,就直接在对齐后的地址的基础上做映射了,这就是楼主所贴代码存在的目的,在这种情况下,把该区间内其他的映射区间都删除(这个是有风险的,所以除非你很确信自己在做什么,否则不要随便用MAP_FIXED标记),来给一会要映射的区间让路。
作者:
embeddedlwp
时间:
2011-09-07 17:40
本帖最后由 embeddedlwp 于 2011-09-07 17:59 编辑
回复
8#
allen303allen
高手!醍醐灌顶!
作者:
wukui1008
时间:
2011-12-05 11:02
找到这个贴不容易啊,
这个问题也困惑我一天了
我开始也是这么觉得
get_unmmaped_area找到的空闲地址空间一定是不与别的区间重叠的
接下来的步骤却又说要删除重叠区间
把我可搞晕了
作者:
gnsusn
时间:
2019-01-12 00:04
还有个问题,
linux 4.14.76 内核中,查找是否覆盖已有的vma区域,
/* Clear old maps */
while (find_vma_links(mm, addr, addr + len, &prev, &rb_link,
&rb_parent)) {
if (do_munmap(mm, addr, len, uf))
return -ENOMEM;
}
如果有覆盖已有的vma区域,则释放掉覆盖的区域(do_munmap),
为什么没有判断覆盖的区域是否在使用,直接就释放了呢?
作者:
gnsusn
时间:
2019-01-12 00:04
本帖最后由 gnsusn 于 2019-01-12 00:08 编辑
期待大家的答案
欢迎光临 Chinaunix (http://bbs.chinaunix.net/)
Powered by Discuz! X3.2