brk与sbrk

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函数去申请或者释放内存。


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

  1. 系统调用brk可根据参数直接指定进程内存空间中堆段的结束位置
  2. 库函数可根据参数调整进程内存空间中堆段的结束位置,当参数为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可以看出堆空间的增长方向是由低地址向高地址增长。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值