原型
将内存地址的结束位置设置为addr指定的值,前提是值合理,系统有足够的内存,并且进程的内存使用数量没有超过最大值3G。
函数原型1 2 3 4 5 6 7 8
|
int brk(void *addr);
|
函数详情
每个进程可访问的虚拟内存空间为3G,但在程序编译时,不可能也没必要为程序分配这么大的空间,只分配并不大的数据段空间,程序中动态分配的空间就是从这一块分配的。如果这块空间不够,malloc函数族(realloc,calloc等)就调用sbrk函数将数据段的下界移动,sbrk函数在内核的管理下将虚拟地址空间映射到内存,供malloc函数使用。(参见linux内核情景分析)
sbrk不是系统调用,是C库函数。系统调用通常提供一种最小功能,而库函数通常提供比较复杂的功能。sbrk/brk是从堆中分配空间,本质是移动一个位置,向后移就是分配空间,向前移就是释放空间,sbrk用相对的整数值确定位置,如果这个整数是正数,会从当前位置向后移若干字节,如果为负数就向前若干字节。在任何情况下,返回值永远是移动之前的位置
使用参考
main.c1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| #include <stdio.h> #include <unistd.h>
int main() { void* p = sbrk(0);
int* p1 = p; printf("ps addr sbrk(0): %p\n", p1);
brk(p1+4); void* s = sbrk(0); printf("ps addr on brk(p1+4): %p and size modify %d \n", s, s-p);
p1[0] = 10; p1[1] = 20; p1[2] = 30; p1[3] = 40; p1[4] = 50;
int* p2 = sbrk(4*4); s = sbrk(0); printf("ps addr on sbrk(4): %p and size modify %d \n", s, s-p); printf("*sbrk(4)=%d\n", *p2);
p1[5] = 60; p1[6] = 70; p1[7] = 80; p1[8] = 90;
int* p3 = sbrk(4*3); s = sbrk(0); printf("ps addr on sbrk(3): %p and size modify %d \n", s, s-p); printf("*sbrk(3)=%d\n", *p3);
p1[9] = 100; p1[10] = 110; p1[11] = 120;
int* p4 = sbrk(4*2); s = sbrk(0); printf("ps addr on sbrk(2): %p and size modify %d \n", s, s-p); printf("*sbrk(2)=%d\n", *p4);
brk(p1+1024); s = sbrk(0); printf("ps addr on (p1+1024): %p and size modify %d \n", s, s-p);
brk(p1+512); s = sbrk(0); printf("ps addr on (p1+512): %p and size modify %d \n", s, s-p);
brk(p1); s = sbrk(0); printf("ps addr on brk(p1): %p and size modify %d \n", s, s-p);
return 0; }
|