brk和sbrk非常类似库函数的malloc,虽然参数不同,但均用于程序员手动分配内存空间,也就是对堆进行操作。
void *sbrk(intptr_t increment);
sbrk接收一个整数参数 increment(后面简称inc),当 inc>0时表示由当前位置后移,分配了inc个字节的内存空间;相反,当inc<0时表示前移,释放inc个字节的内存空间。当inc=0时表示返回到当前的位置sbrk(0),因为它接收的是一个增量。我们习惯的定义一个指针指向sbrk(0)的位置从而获取系统给我们的一个虚拟内存,有了这个虚拟内存后,后面我们使用sbrk进行内存分配时,系统就会将这个虚拟内存进行映射。
int brk(void *addr);
brk和sbrk的功能大同小异,要不然怎么说是亲兄弟呢。只不过,brk表示内存中绝对的位置,直接使用addr的值修改该指针的位置,相比sbrk理解起来还是比较直观的。
既然是哥俩那肯定得一起上阵,sbrk和brk都属于POSIX标准中的内存映射函数,都可以进行单独映射和取消映射,大多数情况下配合使用,即用sbrk分配,用brk释放。
下面举例简单说明一下它俩大概的配合用法:(打印前1000个素数,存储到堆内存)
注:不是1000以内的素数,而是从2开始前1000个素数
#include <stdio.h>
#include <unistd.h>
#include <stdbool.h>
// 判断一个数是否为素数的函数
bool is_prime(int num)
{
if (num <= 1) return false; // 小于等于1的数不是素数
for (int i = 2; i * i <= num; i++)
{ // 只需检查到num的平方根
if (num % i == 0) return false; // 如果能被整除,则不是素数
}
return true; // 否则是素数
}
int main(int argc,const char* argv[])
{
int count = 0; // 用于计数已找到的素数
int num = 2; // 从2开始检查每个数是否为素数
int* primes = sbrk(0); // 获取当前指针的位置,堆的开始位置
int* start = primes; // 保存素数数组的起始位置
// 循环直到找到1000个素数
while (count < 1000)
{
if (is_prime(num))
{
// 为新找到的素数分配内存
primes = sbrk(sizeof(int));//映射内存,调整到一个int大小的位置
if (primes == (void*) -1)
{ // 如果内存分配失败
perror("sbrk"); // 打印错误信息
return 1; // 退出程序
}
*primes = num; // 在分配的内存中存储素数
count++; // 素数计数加一
primes++; // 移动指针到下一个整数位置,为下一个素数做准备
}
num++; // 检查下一个数
}
// 打印前1000个素数
for (int i = 0; i < 1000; i++)
{
printf("%d ", *(start + i)); // 从起始位置开始,逐个打印素数
}
printf("\n");
//取消映射
brk(start);
return 0;
}
看完这个案例大概就能悟到brk和sbrk的用法
over