首页 > 编程知识 正文

linux内存映射的几种方法,linux内存映射和内存分配

时间:2023-05-06 20:27:50 阅读:186206 作者:2929

试图理解堆栈在Linux上是如何工作的。 我阅读了AMD64 ABI关于堆栈和进程初始化的部分,但不知道堆栈应该如何映射。 这是相关的引用。 (3.4.1) :

堆栈状态

thissectiondescribesthemachinestatethatexec (ba _ OS ) creates for

新流程。

itisunspecifiedwhetherthedataandstacksegmentsareinitially

mappedwithexecutepermissionsornot.applicationswhichneedto

executecodeonthestackordatasegmentsshouldtakeproper

precautions,e.g .by calling mprotect (

因此,可以从上面的引文推测堆栈是映射的.使用PROT_EXEC创建映射时,未指定. exec也创建映射。

问题是“主线程”堆栈是否正在使用MAP_GROWSDOWN | MAP_STACK映射,甚至可能通过sbrk。

请看pmap -x pid堆栈中显示为[stack] as的内容

00007 ffc 04 c 780001321212 rw---- [ stack ]

地图的创建位置

映射(空,4096,

PROT_READ | PROT_WRITE,

map _ anonymous|map _ private|map _ stack,

- 1,0;

只需创建匿名映射,如pmap -x pid所示

00007fb6e42fa000 4 0 0 rw--- [ anon ]

解决方法:

icandeducefromthequotesabovethatthestackismapped

顾名思义就是分配内存。 这意味着存在从这些虚拟地址到物理页的逻辑映射。 我们知道这是因为您可以在_start中使用推送或调用指令,而无需从用户空间进行系统调用并分配堆栈。

实际上,x86-64系统v ABI指定argc,argv和envp在进程启动时位于堆栈中。

thequestioniswhetherthe“mainthread”‘sstackusesmap _ grows down|map _ stackmappingormaybeevenviasbrk?

ELF二进制加载器在主线程堆栈中设置_GROWSDOWN标志,但不设置MAP_STACK标志。 这是内核中的代码,不通过普通的mmap系统调用接口。

由于使用(mmap _ grows down )的内容不在用户空间中,因此主线程堆栈通常是内核中具有VM_GROWSDOWN标志的唯一映射。

用于堆栈的虚拟内存ise(VMA )标志的内部名称称为VM_GROWSDOWN。 如果您感兴趣,请使用VM_GROWSDOWN、VM_READ、VM_WRITE、VM_MAYREAD、VM_READ gcc -z execstack进行编译等请注意,在支持增长的堆栈的体系结构中,如果使用CONFIG_STACK_GROWSUP定义编译内核,则使用VM_GROWSUP

/proc/…/maps和pmap不使用VM_GROWSDOWN由于依赖于地址比较,因此可能无法准确确定主线程堆栈占用的虚拟地址空间的确切范围(请参见example )。 另一方面,/proc/…/maps将查找VM_GROWSDOWN

所有这些工具/文件都忽略MAP_STACK标志。 实际上,整个Linux内核都忽略了这个标志。 (这可能是程序加载器没有设置它的原因。 ) )用户空间只传递它,对于将来的验证,内核必须开始特别处理线程的堆栈分配。

sbrk在这里没有意义; 堆栈不与“break”相邻。 另外,brk堆无论如何都会向着堆栈向上延伸。 Linux使堆栈非常接近虚拟地址空间的顶部。 因此,当然不能将sbrk分配给主堆栈。 (内核)相当于sbrk。

不,我没有使用MAP_GROWSDOWN。 另外,由于通常不能安全使用,所以也没有使用辅助线程堆栈。

将MAP_GROWSDOWN称为“用于堆栈”的mmap(2)手册页是一个奇怪的过时和误导。 How to mmap the stack for the clone )请参见system call on linux?

作为Ulrich Drepper explained in 2008,使用MAP_GROWSDOWN的代码通常会被破坏,建议从Linux mmap和glibc头中删除该标志. (这显然没有发生,但是pthreads从那时起就没有使用它,如果有的话.)

MAP_GROWSDOWN为内核中的映射设置VM_GROWSDOWN标志.主线程也使用该标志来启用增长机制,因此线程堆栈可能能够以与主堆栈相同的方式增长:如果堆栈指针低于页面错误位置,则任意远(直到ulimit -s?) . (Linux不需要“堆栈探测器”来触摸大型多页堆栈阵列或alloca的每个页面.)

(线程堆栈在前面完全分配;只有物理页面的正常延迟分配才能支持虚拟分配,避免浪费线程堆栈的空间.)

MAP_GROWSDOWN映射也可以增长mmap手册页描述的方式:访问最低映射页面下方的“保护页面”也会触发增长,即使它低于红色区域的底部.

但主线程的堆栈具有mmap(MAP_GROWSDOWN)无法获得的魔力.它将增长空间保留为ulimit -s,以防止随机选择mmap地址,从而创建阻止增长的障碍.这种魔法仅适用于内核程序加载器,它在execve()期间映射主线程的堆栈,从而使mmap(NULL,…)随机阻止未来的堆栈增长.

mmap(MAP_FIXED)仍然可以为主堆栈创建一个包版广告,但是如果你使用MAP_FIXED,则100%负责不破坏任何内容. (Unlimited stack cannot grow 务实的摩托 the initial 132KiB if MAP_FIXED involved?). MAP_FIXED将替换现有的映射和​​保留,但其他任何东西都会将主线程的堆栈增长空间视为保留; (我认为这是真的;值得尝试使用MAP_FIXED_NOREPLACE或仅使用非NULL提示地址)

看到

pthread_create不会将MAP_GROWSDOWN用于线程堆栈,其他任何人都不应该使用它.一般不要使用.默认情况下,Linux pthreads为线程堆栈分配完整大小.这会花费虚拟地址空间,但(直到它实际触及)不是物理页面.

Why is MAP_GROWSDOWN mapping does not grow?评论中的不一致结果(有些人发现它有效,有些人在触摸返回值和下面的页面时发现它仍然是段错误)听起来像https://bugs.centos.org/view.php?id=4767 – MAP_GROWSDOWN甚至可能在标准主堆栈VM_GROWSDOWN映射的方式之外是错误的用过的.

标签:c-3,linux,linux-kernel,stack,mmap

来源: https://codeday.me/bug/20191002/1844137.html

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。