首页 > 其他 > 详细

brk/sbrk工作原理

时间:2014-03-09 00:16:54      阅读:587      评论:0      收藏:0      [点我收藏+]

malloc是c中常用的内存操作函数,malloc动态的申请一块指定大小的内存,方便存放数据

c++中的new实际上除了malloc分配内存之外还会调用构造函数初始化数据

而brk/sbrk则是实现malloc的底层函数,其中brk是系统调用。操作起来更为灵活,但很多人往往不容易理解。


#include <unistd.h>

int brk(void *addr);

void *sbrk(intptr_t increment);


返回值:
    brk()成功返回0,出错返回-1,并且errno被设置为ENOMEM
    sbrk()成功返回上一个程序结束点,出错返回-1,并且errno被设置为 ENOMEM


在文档中查看brk()/sbrk()的描述,粗略翻译如下:

DESCRIPTION
       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).
       Increasing the program break has the effect of allocating memory to the
       process; decreasing the break deallocates memory.

       brk() sets the end of the data segment to the value specified by  addr,
       when  that  value  is reasonable, the system has enough memory, and the
       process does not exceed its maximum data size (see setrlimit(2)).

       sbrk() increments the program‘s data space by increment bytes.  Calling
       sbrk()  with an increment of 0 can be used to find the current location
       of the program break.

       brk()和sbrk()改变程序间断点的位置。程序间断点就是程序数据段的结尾。(程序间断点是为初始化数据段的起始位置).通过增加程序间断点进程可以更有效的申请内存

       当addr参数合理、系统有足够的内存并且不超过最大值时brk()函数将数据段结尾设置为addr,即间断点设置为addr
       sbrk()将程序数据空间增加increment字节。当increment为0时则返回程序间断点的当前位置。       


什么是程序间断点呢?
可以这样理解,进程在内存中被分为代码区,数据区,栈区和堆区。程序间断点指向堆区的起始位置。同时他也是数据段的结尾。
linux进程内存分布,地址从低到高依次是代码段,数据段,堆,栈,堆栈之间是mmap映射的共享内存空间以及共享库,再上是命令行参数,环境变量等,其中栈是从高地址向低地址分配,堆是从低地址向高地址分配。程序间断点就是当前进程映射虚拟地址的终止位置,通过移动这个位置来维护进程的映射的内存.而brk/sbrk的作用就是维护这个位置.


通过文档的描述可以总结出:
brk改变绝对位置
sbrk相对改变位置 >0则增加位置 <0则收缩位置

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

main()
{
	void *p;
	void *old;                       //存放原始间断点位置
	int  r;

	old = p = sbrk(0);               //sbrk(0)返回当前的程序间断点
	if (p == (void*)-1)
		printf("sbrk error\n"), exit(-1);
	printf("当前程序间断点位置:%p\n", p);
	p = sbrk(1);                     //位置+1,但返回的是之前的位置而不是+1后的位置
	printf("%p\n", p);
	p = sbrk(1);                     //位置实际+2,但返回的是位置+1的值
	printf("%p\n", p);

	r = brk(old);                    //将程序间断点设置为原始位置
	if (r == -1)
		printf("brk error\n"), exit(-1);
	printf("原始位置:%p\n", sbrk(0));//输出原始位置与第一次调用sbrk(0)的位置相同
}


输出结果:

bubuko.com,布布扣



应用brk/sbrk小案例,求1-1000的素数.

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int judge(int num)
{
	int i;
	for(i=2; i<num; i++) {
		if(num%i == 0)
			return 0;	
	}
	return 1;
}

main()
{
    int  *p;
	void *old;
	int  i;

	old = sbrk(0);
	if (old == -1)
		printf("sbrk error\n"), exit(-1);
	p = (int*)old;
	
	for(i=1; i<=1000; i++) {
		if(judge(i) == 1) {
			p = sbrk(4);  //int类型所以又移4个字节
			if (p == -1)
				printf("brk error\n"), exit(-1);
			*p = i;
		}	
	}
	
	p = (int*)old;
	while(p != sbrk(0)) {
		printf("%d ", *p);
		p ++;
	}
										
	if (brk(old) == -1)    //输出完毕,收回空间
		printf("brk error\n"), exit(-1);
}


brk/sbrk工作原理,布布扣,bubuko.com

brk/sbrk工作原理

原文:http://blog.csdn.net/aspnet_lyc/article/details/20801957

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!