您的位置:首页 > 运维架构 > Linux

brk与sbrk

2016-10-26 23:10 239 查看
linux系统中的brk 和sbrk 

#include<unistd.h>

int brk(void *addr);
void *sbrk(intptr_t increment);

根据Linux man手册中的描述,brk和sbrk函数用于改变program break的位置,program break 定义了程序数据段的结束。举例来说就是未初始化数据段结尾后的第一个地址,增加program break的值就是在给进程分配内存,反之,则是回收内存。当addr的值是一个合理的值(系统有足够的内存,进程没有超出它的最大数据段大小)时,brk()设置addr 指向的位置为数据段的结尾。sbrk()会根据increment的值调整进程的数据空间,可令increment的值为0来获取当前进程program
break的program break的值。

在Linux的系统调用中brk执行成功返回新的program break, 否则返回当前的program break。而在glibc中对brk进行了封装,使其执行成功返回0, 失败返回-1,并置errno 为ENOMEM。为了增加程序的可移植性,推荐使用malloc和free函数去申请或者释放内存。

上述内容的意思可简要概括为两句话:

系统调用brk可根据参数直接指定进程内存空间中堆段的结束位置
库函数可根据参数调整进程内存空间中堆段的结束位置,当参数为0时,返回堆空间当前的结束位置

对上述结论进行验证:

#include<stdio.h>

int global; // a undefine variable store in bss segment

int main(void){
int i = 9;
int bss_heap_gap;

int *heapvar, *heapvar2, *heapvar3;

heapvar = (int*) malloc(sizeof(int));
if(heapvar == NULL){
perror("malloc");
exit(-1);
}

heapvar2 = (int*) malloc(sizeof(int));
if(heapvar2 == NULL){
perror("malloc");
exit(-1);
}
printf("address of first allocation is %x\n", (long)heapvar);
printf("address of second allocation is %x\n", (long)heapvar2);

printf("Current location of program break is %x\n", sbrk(0));
printf("size of heap is %x\n", (long)sbrk(0) - (long)heapvar);

sbrk(0x20);
printf("sbrk(0x20);\n");
printf("size of heap is %x\n", (long)sbrk(0) - (long)heapvar);

brk((long)sbrk(0) - 0x30);
printf("brk((long)sbrk(0) - 0x30);\n");
printf("size of heap is %x\n", (long)sbrk(0) - (long)heapvar);

heapvar3 = (int*) malloc(sizeof(int));
if(heapvar3 == NULL){
perror("malloc");
exit(-1);
}
printf("address of allocation after brk((long)sbrk(0) - 0x30) is %x\n", (long)heapvar3);

free(heapvar);
free(heapvar2);
free(heapvar3);

return 0;
}

上述例子,已第一次动态申请内存时得到的内存空间起始位置作为堆段的起始地址,在sbrk和brk函数的执行之后观察堆空间的大小变化。
上述例子的一次输出结果如下所示:

address of first allocation is 804b008
address of second allocation is 804b018
Current location of program break is 806c000
size of heap is 20ff8
sbrk(0x20);
size of heap is 21018
brk((long)sbrk(0) - 0x30);
size of heap is 20fe8
address of allocation after brk((long)sbrk(0) - 0x30) is 804b028

补充:有些材料中介绍brk函数是用来修改堆中申请空间的起始值,这个结论是不正确的,详见例子中的变量heapvar3, 其值并不是brk设置的(long)sbrk(0) - 0x30 = 0x806bff0, 而是 0x804b028.

由heapvar2、和heapvar3可以看出堆空间的增长方向是由低地址向高地址增长。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  brk sbrk linux