brk() and sbrk() change the location of the program break, which defines the end of the process‘s data segment (i.e., the program break is the first location after the end of the uninitialized data segment).
brk() , sbrk() 的声明如下:
如 man 里说的:
brk() 和 sbrk() 改变 "program brek" 的位置,这个位置定义了进程数据段的终止处(也就是说,program break 是在未初始化数据段终止处后的第一个位置)。引用brk() and sbrk() change the location of the program break, which defines the end of the process‘s data segment (i.e., the program break is the first location after the end of the uninitialized data segment).
首先说明一点,一个程序一旦编译好后,text segment ,data segment 和 bss segment 是确定下来的,这也可以通过 objdump 观察到。下面通过一个程序来测试这个 program break 是不是在 bss segment 结束那里:
从上面的输出中,可以发现几点:引用[beyes@localhost C]$ ./sbrk
end of bss section:0x8049938
pmem:0x82ec008
1-gap between heap and bss:2762448
pmem:0x82ec008
2-gap between heap and bss:2762448
[beyes@localhost C]$ ./sbrk
end of bss section:0x8049938
pmem:0x8dbc008
1-gap between heap and bss:14100176
pmem:0x8dbc008
2-gap between heap and bss:14100176
从输出可以看到,虽然堆的头部地址在每次程序加载后都不一样,但是每次加载后,堆的大小默认分配是一致的。但是这不是不能改的,可以使用 sysctl 命令修改一下内核参数:引用[beyes@localhost C]$ ./sbrk
pmem:0x80c9008
heap size on each load: 135160
[beyes@localhost C]$ ./sbrk
pmem:0x9682008
heap size on each load: 135160
[beyes@localhost C]$ ./sbrk
pmem:0x9a7d008
heap size on each load: 135160
[beyes@localhost C]$ ./sbrk
pmem:0x8d92008
heap size on each load: 135160
[beyes@localhost C]$ vi sbrk.c
这么做之后,再运行 3 次这个程序看看:引用#sysctl -w kernel/randomize_va_space=0
从输出看到,每次加载后,堆头部的其实地址都一样了。但我们不需要这么做,每次堆都一样,容易带来缓冲区溢出攻击(以前老的 linux 内核就是特定地址加载的),所以还是需要保持 randomize_va_space 这个内核变量值为 1 。引用[beyes@localhost C]$ ./sbrk
pmem:0x804a008
heap size on each load: 135160
[beyes@localhost C]$ ./sbrk
pmem:0x804a008
heap size on each load: 135160
[beyes@localhost C]$ ./sbrk
pmem:0x804a008
heap size on each load: 135160
引用[beyes@localhost C]$ ./sbrk
pmem:0x804a008
1
2
3
4
5
... ...
61
62
63
64
而 brk() 这个函数的参数是一个地址,假如你已经知道了堆的起始地址,还有堆的大小,那么你就可以据此修改 brk() 中的地址参数已达到调整堆的目的。
原文地址:http://blog.csdn.net/yusiguyuan/article/details/39496263