1、sys_brk
系统调用sys_brk的函数原型:
/*
* sys_brk()是一个操作系统调用,用于更改进程的堆空间大小。
* sys_brk()函数接收一个无符号长整型参数brk,表示要求的新的程序数据段(堆)结束地址。
* 如果brk的值大于当前的程序数据段结束地址,则增加堆的大小;如果brk的值小于当前的程序数据段结束地址,则缩小堆的大小。
* 函数返回值为long类型,表示数据段结束地址。如果分配失败,则返回-1。
*/
asmlinkage long sys_brk(unsigned long brk);
以下是sys_brk()函数的一个示例代码:
// /*================================================================
// * Copyright (C) 2023 baichao All rights reserved.
// *
// * 文件名称:sys_brk_demo.c
// * 创 建 者:baichao
// * 创建日期:2023年08月01日
// * 描 述:
// *
// ================================================================*/
#include <unistd.h>
#include <stdio.h>
#include <sys/syscall.h> // 增加此头文件
int main()
{
void *cur_brk;
// 获取当前程序数据段结束地址
long ret = syscall(__NR_brk, 0);
cur_brk = (void *)ret;
printf("start, curr data sec end pos: %p\n", cur_brk);
// 增加堆的大小
long delta = 1024;
ret = syscall(__NR_brk, cur_brk + delta); // 堆增长delta
cur_brk = (void *)ret;
printf("add, curr data sec end pos: %p\n", cur_brk);
// 减小堆的大小
delta = -512;
ret = syscall(__NR_brk, cur_brk + delta); // 堆缩小delta
cur_brk = (void *)ret;
printf("sub, curr data sec end pos: %p\n", cur_brk);
// 获取当前程序数据段结束地址
ret = syscall(__NR_brk, 0);
cur_brk = (void *)ret;
printf("end, curr data sec end pos: %p\n", cur_brk);
return 0;
}
执行结果如下:
需要注意的是,在使用sys_brk()函数时必须特别小心,因为它可以轻松地破坏程序的内存布局。通常情况下,建议使用malloc()等库函数来进行内存分配,以避免出现问题。
linux c有一个对于sys_brk的系统调用的封装函数sbrk:
// __delta如果为正,当前程序数据段结束地址在现有的地址上增加delta,即堆增长|delta|
// __delta如果为负,当前程序数据段结束地址在现有的地址上减少delta;即堆减小|delta|
// 返回值:返回增加前的堆的尾地址。
void *sbrk (intptr_t __delta) __THROW;
sbrk 函数用于扩展或缩小进程的堆大小,即为程序动态分配内存提供支持。它可以接受一个整数参数 increment,表示需要增加或减少的字节数。如果 increment 为正数,则将堆大小增加相应的字节数;如果为负数,则将堆大小减小相应的字节数。
示例代码如下:
/*================================================================
* Copyright (C) 2023 baichao All rights reserved.
*
* 文件名称:sbrk.c
* 创 建 者:baichao
* 创建日期:2023年08月01日
* 描 述:
*
================================================================*/
#include <unistd.h>
#include <stdio.h>
int main() {
void *cur_brk;
// 获取当前程序数据段结束地址
cur_brk = sbrk(0);
printf("start, curr data sec end pos: %p\n", cur_brk);
// 增加堆的大小
long delta = 100*1024*1024;
cur_brk = sbrk(delta); // 堆增长delta, 此时的返回值cur_brk是增加前的地址
printf("add1, curr data sec end pos: %p\n", cur_brk);
cur_brk = sbrk(0);
printf("add2, curr data sec end pos: %p\n", cur_brk);
// 减小堆的大小
delta = 50*1024*1024;
cur_brk = sbrk(delta); // 堆缩小delta,同理,此时的返回值cur_brk是减小前的地址
printf("sub1, curr data sec end pos: %p\n", cur_brk);
cur_brk = sbrk(0);
printf("sub2, curr data sec end pos: %p\n", cur_brk);
return 0;
}
运行结果如下: