当我使用brk系统调用时,我分配的内存实际上从哪里开始

时间:2015-10-01 10:22:22

标签: linux memory x86 nasm brk

我试图在NASM / x86程序集中使用sys_brk分配一些内存。 sys_break返回break的新地址,这是数据段的结尾对吗?那么我新分配的内存在哪里?我假设它介于旧的中断值和新的中断值之间。因此,如果我使用sys_brk分配64字节的内存,我可以使用接下来的64个字节,从我在调用sys_brk之前存储的旧中断值开始。我是对的吗?

我将分配内存的汇编代码看起来有点像这样。https://gist.github.com/nikAizuddin/f4132721126257ec4345

另一个问题是;

我应该在Assembly中编写一个函数,它返回指向动态分配的内存的指针,该函数将从C程序中调用。如何从程序的C端释放这块内存?只是调用free()就够了吗?

1 个答案:

答案 0 :(得分:0)

brk(2)手册页(部分:C库/内核ABI差异)描述了如何在Linux的系统调用之上实现glibc包装器,该系统调用在成功时返回新的brk,或者在失败时返回旧的brk。

据我了解,超出当前中断的内存未映射。当前中断下方的地址是数据段的一部分(在数据+ bss +堆的意义上)。关于中断是否必须是页面对齐的文档并不清楚。 (即你可以sbrk(64),还是仅仅sbrk(4096)?)

请参阅:What does brk( ) system call do?该问题的答案为an example of using sbrk to replace malloc for code-golf。所以是的,旧的休息是要返回的地址。显然你可以sbrk增加你想要的任何增量,而不仅仅是页面。

你是编写内存分配器的人。 sbrk只是让您从操作系统中获得更多信息,例如mmap(MAP_ANONYMOUS),但不太灵活。 它无法帮助您跟踪空闲块,因此您可以将它们用于将来的分配,而不是总是从操作系统获得更多。

使用sbrk回馈内存的方法是使用负参数调用sbrk。显然这需要一个后进先出的使用模式,这就是为什么glibc的malloc只使用sbrk进行小分配(可以在释放时放在空闲列表中,为将来的mallocs分发) 。大分配最好立即返回操作系统,而不是保持映射,因此glibc的malloc使用mmap

永远不要在free(3)(或malloc(3)之类的相关功能(或strdup(3))上找到的内存上free(3),您可以在文档中说明munmap increment = 0如果你在程序中断以下的内存页面上调用malloc(3)会发生什么情况。可能它只会起作用,但是如果中断减少到那里你会在数据段中保留可能会导致问题。

后来意识到这不是你问的问题:

获取当前brk的最简单方法是简单地使用$ strace -e brk ls 2>&1 | m brk(0) = 0x650000 brk(0) = 0x650000 brk(0x671000) = 0x671000 调用它。

这就是glibc的end(3)内部所做的事情:

&end

brk手册页提到了#app/models/order.rb class Order < ActiveRecord::Base def not_liked user, from_id joins(:likes).where(status: "pending", id > from_id).not(likes: {user_id: user.id}) end end 。显然,有一些全局变量位于文本,数据和bss段的末尾。但是,@order = Order.not_liked current_user, "5" 只是“程序中断附近”,这就是为什么malloc仍然必须调用sbrk(0)来获得初始中断。