大家都知道malloc是c中常用的内存操作函数,malloc动态的申请一块指定大小的内存,方便存放数据。而brk/sbrk则是实现malloc的底层函数,其中brk是系统调用。brk和sbrk主要的工作是实现虚拟内存到内存的映射。很多人对这两个函数不是很熟悉,本文主要介绍这两个函数的用法。
首先介绍一下内存分配的过程。每个进程可访问的虚拟内存空间为3G,但在程序编译时,不可能也没必要为程序分配这么大的空间,只分配并不大的数据段空间,程序中动态分配的空间就是从这一块分配的。如果这块空间不够,malloc函数族(realloc,calloc等)就调用sbrk函数将数据段的下界移动,sbrk函数在内核的管理下将虚拟地址空间映射到内存,供malloc函数使用。
sbrk不是系统调用,是C库函数。系统调用通常提供一种小功能,而库函数通常提供比较复杂的功能。sbrk/brk是从堆中分配空间,本质是移动一个位置,向后移就是分配空间,向前移就是释放空间,sbrk用相对的整数值确定位置,如果这个整数是正数,会从当前位置向后移若干字节,如果为负数就向前若干字节。在任何情况下,返回值永远是移动之前的位置。
代码演示如下:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main() {
void *p, *old;
int r;
old = p = sbrk(0);
if (p == (void *)-1) {
printf("sbrk error\n");
return -1;
}
printf("cur pos:%p\n", p);
p = sbrk(1);
printf("%p\n", p);
p = sbrk(1);
printf("%p\n", p);
r = brk(old);
if (r == -1) {
printf("sbrk error\n");
return -1;
}
printf("original pos :%p\n", sbrk(0));
return 0;
}
程序执行结果如下:
cur pos:0x947c000
0x947c000
0x947c001
original pos :0x947c000
从程序的执行结果,可以看出,sbrk移动内存的单位是字节,且返回移动之前的值。
下面例子是利用brk和sbrk函数实现了打印1~100之间所有素数的功能,代码如下:
#include
#include
#include
int judge(int num) {
int i;
for (i = 2; i < num; i++) {
if (num % i == 0) {
return 0;
}
}
return 1;
}
int main() {
int *p;
void *old;
int i;
old = sbrk(0);
if(old == (void *)-1) {
printf("sbrk error\n");
return -1;
}
p = (int *)old;
for (i = 1; i <= 100; i++) {
if (judge(i) == 1) {
p = sbrk(sizeof(int));
if (p == (int *)-1) {
printf("sbrk error\n");
return -1;
}
*p = i;
}
}
p = (int *)old;
while (p != sbrk(0)) {
printf("%d ", *p);
p++;
}
if (brk(old) == -1) {
printf("brk error\n");
return -1;
}
puts("");
return 0;
}
程序执行结果如下:
1 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
Copyright © 2004-2024 华清远见教育科技集团 版权所有
京ICP备16055225号-5,京公海网安备11010802025203号