借用linux那个男人,看下
BRK(2) Linux Programmer's Manual
BRK(2)
此部分补充一个知识点:后面的括号
1:Linux系统(shell)指2:系统函数3:标准C函数7:系统编程帮助
所以此部分是linux系统函数
NAME
brk, sbrk -change data segment size
SYNOPSIS
头文件
#include<unistd.h>
原形
intbrk(void *addr);
void*sbrk(intptr_t increment);
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 ofthe uninitialized data segment).
Increasing the program break has theeffect of allocating memory to the
process; decreasing the breakdeallocates memory.
brk() sets the end of the data segmentto the value specified by addr,
when that value is reasonable, the system has enough memory,and the
process does not exceed its maximum datasize
sbrk() increments the program's dataspace by increment bytes. Calling
sbrk() with an increment of 0 can be used to find the current location
of the program break.
RETURNVALUE
On success, brk() returns zero. On error, -1 is returned, and errno is
set to ENOMEM. (But see Linux Notes below.)
On success, sbrk() returns the previous program break. (If the break
was increased,then this value is a pointer to the start of the newly
allocatedmemory). On error, (void *) -1 isreturned, and errno is set
to ENOMEM.
先说下整个运行原理
1. 内核维护一个指针,假设是p,那么第一次调用sbrk(>0的size)或得到一个没有被占用的虚拟内存,大小一般是4K的倍数,返回页开始地址的,并且把p=p size
第二次调用以及后续调用sbrk(>0的size),返回p,并且把p size
写个程序一目了然
#include<stdio.h>
#include <unistd.h>
int main()
{
int*p1 = sbrk(4);
int*p2 = sbrk(4);
int*p3 = sbrk(4);
printf("pid%d\n",getpid());
printf("p1:%p\n",p1);
printf("p2:%p\n",p2);
printf("p3:%p\n",p3);
while(1);
}
运行效果
此时我们可以看下他的maps文件
发现他确实是映射了4K的空间
2. 内核维护一个指针,假设是p,那么sbrk(0)或得到一个没有被占用的虚拟内存地址,但是此时不分配空间,但是此时只是初始化p,所以你如果对此时得到的内存地址赋值,那么就会出现段错误
程序验证
#include<stdio.h>
#include<unistd.h>
int main()
{
int *p = sbrk(0);
printf("%p\n",p);
*p = 111;
}
此时出现段错误
3. brk一般配合着sbrk做申请内存和释放内存使用,用sbrk得到地址后,使用brk做偏移,当然要做合理的范围之内
如程序
#include<stdio.h>
#include<unistd.h>
int main()
{
int *p = sbrk(0);
brk(p 1);/* 3 使用brk分配空间 */
*p = 1;
printf("%d\n",*p);
brk(p); /*4 使用brk释放空间 */
*p = 2;
printf("%d\n",*p);
return 0;
}
运行效果
发现8888能打印,原因是我们用brk(p 1)申请了4个byte的空间,但是后续brk(p)又释放掉了,所以访问会出现段错误
所以总结下brk和sbrk的用法
一般brk和sbrk的通用用法是:
1. 使用sbrk分配空间
Sbrk(>0的size)映射一个4K的page,并且分配一个空间
2.使用sbrk得到没有映射的虚拟地址.
3.使用brk分配空间
4.使用brk释放空间
#include<stdio.h>
#include<unistd.h>
int isPrimer(int a)
{
int i=2;
for(;i<a;i )
{
if(a%i==0)
{
return 1;
}
}
return 0;
}
int main()
{
int i = 2;
int b;
int *p = sbrk(0);
int *r = p;
for(;i<100;i )
{
b = isPrimer(i);
if(b == 0)
{
brk(r 1);
*r = i;
r = sbrk(0);
}
}
i=0;
r=p;
while(r!=sbrk(0))
{
printf("%d\n",*r);
r ;
}
brk(p);
}