int brk(void *end_data_segment);
void *sbrk(intptr_t increment);
以 0 为增量调用 sbrk() 可用于查找程序中断的当前位置。
什么是程序中断?它从哪里开始,0x00?
int brk(void *end_data_segment);
void *sbrk(intptr_t increment);
以 0 为增量调用 sbrk() 可用于查找程序中断的当前位置。
什么是程序中断?它从哪里开始,0x00?
过度简化:
一个进程有几个内存段:
(当然,现在它要复杂得多。有一个rodata段,一个未初始化的数据段,通过mmap分配的映射,一个vdso,......)
程序在类 Unix 操作系统中请求更多内存的一种传统方式是增加数据段的大小,并使用内存分配器(即malloc()
实现)来管理结果空间。这是通过brk()
系统调用完成的,它改变了数据段“中断”/结束的点。
程序中断是进程数据段的结束。又名...
程序中断是未初始化数据段结束后的第一个位置
至于它从哪里开始,它取决于系统,但可能不是 0x00。
您是说 sbrk() 是一个过时的系统调用,我们应该使用 malloc(),但是根据她的文档,当分配的内存少于 128 KiB(32 页)时,malloc() 会使用它。所以我们不应该直接使用 sbrk(),而是 malloc() 使用它,如果分配大于 128 KiB,那么 malloc() 使用 mmap() 将私有页面分配给用户空间。最后,了解 sbrk() 是一个好主意,至少对于了解“程序中断”概念而言。
如今,sbrk(2) (and brk
) 几乎是过时的系统调用(您几乎可以忘记它们并忽略break 的旧概念;专注于理解mmap(2))。请注意,sbrk(2) man
页面在其NOTES中说:
避免使用
brk()
andsbrk()
:malloc(3)内存分配包是一种可移植且舒适的内存分配方式。
(强调我的)
malloc(3)的大多数实现(尤其是musl-libc中的那个)宁愿使用mmap(2)来从内核请求内存 - 并增加它们的虚拟地址空间(看看那个 虚拟地址空间维基页面,它有一个很好的图片)。一些malloc
-ssbrk
用于小分配,mmap
用于大分配。
使用strace(1)找出某个给定进程或命令完成的系统调用(在syscalls(2)中列出)。顺便说一句,您会发现bash
并且ls
(可能还有许多其他程序)不会对sbrk
.
使用proc(5)探索某个进程的虚拟地址空间。尝试cat /proc/$$/maps
并阅读一下cat /proc/self/maps
以cat /proc/$$/smaps
了解输出。
并且sbrk
不是很友好的线程。
(我的回答集中在 Linux 上)