在堆对齐的内存上的mprotect神秘地工作

时间:2016-02-06 09:13:32

标签: c linux malloc mmap

所以我试图检查是否可以使用mprotect正确更改mmapped分配内存的访问权限,这就是我写的:

#include <stdio.h>
#include <sys/mman.h>
#include <malloc.h>
#include <unistd.h>

void main()
{
        int pagesize;
        pagesize = getpagesize();
        void *p;
        p = malloc(pagesize);
        getchar();
        int q = posix_memalign(&p, pagesize, pagesize);
        getchar();
        int a = mprotect(p, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC);
        getchar();
        free(p);
}

现在在每个函数之后我使用getchar来使用cat /proc/<pid>/maps文件分析我的内存段,这就是我得到的: (仅显示有关堆的信息,因为这是我唯一关注的问题) 在posix_memalign

之后
01776000-01798000 rw-p 00000000 00:00 0                                  [heap]

mprotect功能后:

01776000-01778000 rw-p 00000000 00:00 0                                  [heap]
01778000-01779000 rwxp 00000000 00:00 0                                  [heap]
01779000-01798000 rw-p 00000000 00:00 0                                  [heap]

因此,如果你注意到在我使用mprotect之后分配给三个部分之前分配的堆,并且只有堆的第二部分获得我在函数中给出的访问权限。 为什么会发生这种划分?为什么只有分割堆的第二个区域才能获得权限? 注意:我搜索了联机帮助页,但对此没有发现任何内容。

1 个答案:

答案 0 :(得分:3)

您在地址0x1000分配了p个字节,在您的示例中为0x1778000。当您使用这些参数调用mprotect时,它确实可以正常工作并标记为01778000-01779000 rwxp

因此,您的问题可能更贴切地表达为什么posix_memalign(3)似乎分配的空间超出您的要求?

让我们看看man posix_memalign

  

POSIX要求从posix_memalign()获得的内存可以使用free(3)释放。

free(3)如何知道要释放多少字节?它需要将它存储在您分配的页面之外的某个位置。 malloc(3)或朋友的后续调用如何知道在哪里可以找到释放的块?这些也需要存储在某个地方。

堆分配器存储用于管理堆上堆的数据结构也就不足为奇了。

如果您想要更低级别的方式来分配页面,请使用mmap(2)

p = mmap(0, getpagesize(), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);

此内存由您管理,当您调用munmap(2)时,通过直接通知内核来删除映射。在用户空间中没有进行回收或管理。