首页
学习
活动
专区
圈层
工具
发布
    • 综合排序
    • 最热优先
    • 最新优先
    时间不限
  • 来自专栏韩曙亮的移动开发专栏

    【Linux 内核 内存管理】内存管理架构 ⑤ ( sbrk 内存分配系统调用代码示例 | 在 procpidmaps 中查看进程堆内存详情 )

    文章目录 一、sbrk 内存分配系统调用代码示例 二、在 /proc/pid/maps 中查看进程堆内存详情 本篇博客调用 sbrk 系统调用函数 , 申请并修改 堆内存 , 并在 /proc/pid/ maps 中查看该进程的 堆内存 ; 一、sbrk 内存分配系统调用代码示例 ---- sbrk 系统调用函数 , 作用是 修改程序 BSS 段大小 ; 函数原型如下 : #include <unistd.h > int brk(void *addr); void *sbrk(intptr_t increment); 函数执行成功 , 返回一个指向 " 堆内存 " 的指针 ; 函数执行失败 , 返回 系统调用申请 堆内存 int *p = sbrk(0); // 记录该堆内存地址 int *p_old = p; // 继续为 申请的堆内存, 申请 1024 字节内存 /a.out pid : 4829 p_old : 0x203e000 p : 0x203e000 p_new : 0x2060000 进程 ID 为 4829 ; sbrk 返回的指针 p

    4.6K20编辑于 2023-03-30
  • 来自专栏山河已无恙

    Linux 内存调优之 BPF 分析用户态小内存分配

    写在前面 博文内容为 使用 BPF 工具跟踪 Linux 用户态小内存分配(brk,sbrk) 理解不足小伙伴帮忙指正 :),生活加油 我看远山,远山悲悯 持续分享技术干货,感兴趣小伙伴可以关注下 ^ 同时还有一个sbrk(2)变体调用。在Linux中,sbrk(2)是以库函数形式实现的,内部仍然使用 brk(2)系统调用。 : 6.00 ┌──[root@liruilongs.github.io]-[/usr/share/bcc/tools] └─$ 这里先准备一个测试脚本,调用 malloc 函数多次分配内存,观察 sbrk (0)); sleep(30); return 0; } sbrk(0) 为当前堆顶指针,每次分配内存,堆顶指针都会增加,这里分配了 12KB,120KB,4KB,观察堆顶指针的变化 上面的Demo 中,我们在 print 中调用 sbrk(0) ,这里是否会触发 brk 内核跟踪点 ,注释掉,然后再次运行,发现 brk 的调用次数还是3次,说明和 print 的 sbrk(0) 没有关系

    34610编辑于 2025-06-29
  • 来自专栏用户9199536的专栏

    C|内存管理|Memory Allocation

    SBRK(break) 从某种意义上来说,heap和stack很接近,也有一个sbrk标识堆顶。 在没有free的情况下,sbrk的行为和rsp很接近,每次申请一块内存,sbrk增大,增大的部分作为分配的内存。然而,由于free由用户控制,释放内存不像栈一样始终在栈顶,这就造成了复杂度。 新分配的内存可能在sbrk附近,也有可能在已经被释放的内存上。因此,我们malloc时会先寻找是否有已经存在的被释放的内存,如果没有,再增加sbrk。 (参见数学归纳) 如果free的内存在sbrk附近(表尾),那么直接收缩堆。 Malloc 遍历寻找可分配的chunk,然后找到size大于需求的,直接修改size+allocation bit即可。

    42720发布于 2021-11-22
  • 来自专栏c++与qt学习

    MIT 6.S081 Lab Five -- Lazy Page Allocation

    Xv6应用程序使用sbrk()系统调用向内核请求堆内存。在我们给出的内核中,sbrk()分配物理内存并将其映射到进程的虚拟地址空间。内核为一个大请求分配和映射内存可能需要很长时间。 为了让sbrk()在这些情况下更快地完成,复杂的内核会延迟分配用户内存。 也就是说,sbrk()不分配物理内存,只是记住分配了哪些用户地址,并在用户页表中将这些地址标记为无效。 () (easy) YOUR JOB 你的首项任务是删除sbrk(n)系统调用中的页面分配代码(位于sysproc.c中的函数sys_sbrk())。 处理sbrk()参数为负的情况。 如果某个进程在高于sbrk()分配的任何虚拟内存地址上出现页错误,则终止该进程。 在fork()中正确处理父到子内存拷贝。 处理sbrk()参数为负数的情况,参考之前sbrk()调用的growproc()程序,如果为负数,就调用uvmdealloc()函数,但需要限制缩减后的内存空间不能小于0 uint64 sys_sbrk

    58841编辑于 2023-10-11
  • 来自专栏蓝天

    brk/sbrk和mmap行为分析

    mallopt // M_TRIM_THRESHOLD: 紧缩内存阈值,对应的环境变量为MALLOC_TRIM_THRESHOLD_ // M_MMAP_THRESHOLD: 使用mmap而非brk/sbrk 分配内存阈值,即超过该值的malloc分配将使用mmap // ,否则使用brk/sbrk分配内存,对应的环境变量为MALLOC_MMAP_THRESHOLD_ // 请注意:如今的glibc mprobe // malloc_stats mallinfo malloc_trim malloc_info // mmap分配的内存在调用munmap后会立即返回给系统,而brk/sbrk 而受M_TRIM_THRESHOLD的影响 // 但brk/sbrk分配的内存是否立即归还给系统,不仅受M_TRIM_THRESHOLD的影响,还要看高地址端(栓)的内存是否已经释放: // 假如依次malloc了str1、str2、str3,即使它们都是brk/sbrk分配的,如果没有释放str3,只释放了str1和str2, // 就算两者加起来超过了M_TRIM_THRESHOLD

    1.8K20发布于 2018-08-10
  • 来自专栏Miigon's Blog

    [mit6.s081] 笔记 Lab5: Lazy Page Allocation | 内存页懒分配

    Xv6 applications ask the kernel for heap memory using the sbrk() system call. In the kernel we’ve given you, sbrk() allocates physical memory and maps it into the process’s virtual 实现一个内存页懒分配机制,在调用 sbrk() 的时候,不立即分配内存,而是只作记录。在访问到这一部分内存的时候才进行实际的物理内存分配。 本次 lab 分为三个部分,但其实都是属于同一个实验的不同步骤,所以本文将三点集合到一起: Eliminate allocation from sbrk() (easy) Lazy allocation (moderate) Lazytests and Usertests (moderate) Lazy allocation & Tests 首先修改 sys_sbrk,使其不再调用 growproc(

    1.1K20编辑于 2022-10-27
  • 来自专栏linjinhe的专栏

    Linux进程内存管理(二)

    jemalloc 实现了 arena,维护一个由多种固定大小的内存块组成的内存池,减少外部碎片;同时减少调用系统调用(brk/sbrk/mmap/munmap)的次数,提高内存分配器的性能。 相关系统调用 接下来,介绍一下内存分配器相关的系统调用: brk/sbrk mmap 在介绍这几个系统调用之前,需要先对进程的内存布局有所认识。 ? brk/sbrk #include <unistd.h> int brk(void *addr); void *sbrk(intptr_t increment); brk() and sbrk() 简单地说,brk() 和 sbrk() 就是修改上图所示的Heap的结束地址。注意,为了防止“溢出攻击”,Heap 的起始地址是随机的。

    3.4K40发布于 2018-06-06
  • 来自专栏我的独立博客

    brk与mmap

    2. brk/sbrk brk是linux上一个系统调用,而sbrk是一个C库函数 2.1 brk函数原型 int brk(void *addr); 参数 参数 解释 addr 要调整到的内存地址 返回值 返回增加的大小 2.2 sbrk函数原型 void *sbrk(intptr_t increment); 参数 参数 解释 increment 增加的内存大小 返回值 返回增加之后的program

    73210编辑于 2024-09-02
  • 来自专栏韩曙亮的移动开发专栏

    【Linux 内核 内存管理】内存管理架构 ④ ( 内存分配系统调用过程 | 用户层 malloc free | 系统调用层 brk mmap | 内核层 kmalloc | 内存管理流程 )

    在 " 用户空间 “ 的 应用程序 中调用 malloc 等函数 , 申请 动态分配 ” 堆内存 " , ② 系统调用 : 用户空间 的 内存管理函数 调用 " 内核与用户层接口 “ 中的 brk sbrk delete 关键字 回收 " 堆内存 " ; C++ STL : STL 中 , 堆内存 是 自动分配 , 自动回收 的 , 不需要用户进行手动操作 ; ② 系统调用接口 内存管理 : 调用 brk sbrk mmap munmap 等系统调用函数 , brk sbrk 函数 既可以分配内存 , 又可以回收内存 , 通过 修改 起始 和 终止 地址即可实现 ; mmap 函数用于分配内存 , munmap

    1.1K10编辑于 2023-03-30
  • 来自专栏陈福荣的专栏

    十问 Linux 虚拟内存管理 ( 一 )

    其中堆顶的位置可通过函数 brk 和 sbrk 进行动态调整。 文件映射区域 :如动态库、共享内存等映射物理空间的内存,一般是 mmap 函数所分配的虚拟地址空间。 另外, %esp 执行栈顶,往低地址方向变化; brk/sbrk 函数控制堆顶往高地址方向变化。 可通过以下代码验证进程的地址空间分布,其中 sbrk(0) 函数用于返回栈顶指针。 ]); printf("Top of stack is 0x%lx\n", &local_var); printf("Top of heap is 0x%lx\n", sbrk 关于 malloc 获得虚存空间的实现,与 glibc 的版本有关,但大体逻辑是: 若分配内存小于 128k ,调用 sbrk() ,将堆顶指针向高地址移动,获得新的虚存空间。 其中 sbrk 就是修改栈顶指针位置,而 mmap 可用于生成文件的映射以及匿名页面的内存,这里指的是匿名页面。

    11.9K23发布于 2016-11-02
  • 来自专栏赤道企鹅的博客

    从uClibc部分源码总结固件利用思路的变化

    回到__malloc_from_heap,假如没有足够大小的freed区域用于取出,则会用mmap或者sbrk的方式向操作系统取得一块新的内存,具体使用mmap还是sbrk取决于编译时使用的宏: #ifdef MALLOC_USE_SBRK //如果用sbrk __malloc_lock_sbrk (); /* Use sbrk we can, as it's faster than mmap, and guarantees contiguous allocation. */ block = sbrk (block_size); if (likely = (void *)-1)) { /* Because sbrk can return results of arbitrary alignment, align MALLOC_USE_SBRK */ /* Otherwise, use mmap. */ #ifdef __ARCH_USE_MMU__ block = mmap ((void

    93310编辑于 2022-08-01
  • 来自专栏秘籍酷

    malloc 背后的系统知识

    ptmalloc 对于申请内存小于 128KB 时,分配是在堆段,使用系统调用 brk() 或者 sbrk()。如果大于 128 KB 的话,分配在映射区,使用系统调用 mmap()。 2. brk, sbrk 在堆段申请的话,使用系统调用 brk 或者 sbrk。 int brk(const void *addr); void *sbrk(intptr_t incr); brk 将 brk 指针放置到指定地址处,成功返回 0,否则返回 -1。 sbrk 将 brk 指针向后移动指定字节,返回依赖于系统实现,或者返回移动前的 brk 位置,或者返回移动后的 brk 位置。下面使用 sbrk 实现一个巨简单的 malloc。 void *malloc(size_t size) { void *p = sbrk(0); void *request = sbrk(size); if (request == (void*)

    1.3K11发布于 2019-08-08
  • 来自专栏鹅厂少年的奇妙之旅

    【春节红包系列】一次"内存泄漏"引发的血案

    是通过brk(sbrk)和mmap这两个系统调用实现的。 结合上文进程虚拟空间图,brk(sbrk)是将数据段(.data)的最高地址指针_edata往高地址推。 这两种实现方式的区别大致如下: brk(sbrk),性能损耗少; mmap相对而言,性能损耗大 mmap不存在内存碎片(是物理页对齐的,整页映射和释放); brk(sbrk)可能存在内存碎片(由于new 和delete的顺序不同,可能存在空洞,又称为碎片) 无论是通过brk(sbrk)还是mmap调用分配的内存都是虚拟空间的内存,只有在第一次访问已分配的虚拟地址空间的时候,发生缺页中断,操作系统负责分配物理内存 如果是brk(sbrk)分配的内存,直接调用brk(sbrk)并传入负数,即可缩小Heap区的大小;如果是mmap分配的内存,调用munmap归还内存。 brk(sbrk)和mmap都是系统调用,如果程序中频繁的进行内存的扩张和收缩,每次都直接调用,当然可以实现内存精确管理的目的,但是随之而来的性能损耗也很显著。

    7.5K142发布于 2018-05-29
  • 来自专栏JAVA烂猪皮

    一次“内存泄露”引发的血案

    是通过brk(sbrk)和mmap这两个系统调用实现的。 结合上文进程虚拟空间图,brk(sbrk)是将数据段(.data)的最高地址指针_edata往高地址推。 这两种实现方式的区别大致如下: 1.brk(sbrk),性能损耗少;mmap相对而言,性能损耗大 2.mmap不存在内存碎片(是物理页对齐的,整页映射和释放);brk(sbrk)可能存在内存碎片(由于new 如果是brk(sbrk)分配的内存,直接调用brk(sbrk)并传入负数,即可缩小Heap区的大小;如果是mmap分配的内存,调用munmap归还内存。 brk(sbrk)和mmap都是系统调用,如果程序中频繁的进行内存的扩张和收缩,每次都直接调用,当然可以实现内存精确管理的目的,但是随之而来的性能损耗也很显著。 所有调用delete释放的内存,并不是立即调用brk(sbrk)归还给操作系统,而是先将这个内存块挂在free-list(bins)里面,然后进行内存归并(可选操作,相邻的可用内存块合并为更大的可用内存块

    3.1K41发布于 2020-09-18
  • 来自专栏全栈程序员必看

    malloc函数实现原理!

    2.2.3 brk与sbrk 由上文知道,要增加一个进程实际的可用堆大小,就需要将break指针向高地址移动。Linux通过brk和sbrk系统调用操作break指针。 两个系统调用的原型如下: C int brk(void *addr);
    void *sbrk(intptr_t increment); 1 2 int brk在执行成功时返回0,否则返回-1并设置errno为ENOMEM;sbrk成功时返回break移动之前所指向的地址,否则返回(void *)-1。 (0);
    if (sbrk(size) == (void *)-1)
    return NULL;
    return p;
    } 这里关键是如何只使用sbrk创建一个struct: C #define BLOCK_SIZE 24 /* 由于存在虚拟的data字段,sizeof不能正确计算meta长度,这里手工设置 */</p

    1.5K30编辑于 2022-09-02
  • 来自专栏c语言与cpp编程

    malloc 背后的虚拟内存 和 malloc实现原理

    2. brk, sbrk 在堆段申请的话,使用系统调用 brk 或者 sbrksbrk 将 brk 指针向后移动指定字节,返回依赖于系统实现,或者返回移动前的 brk 位置,或者返回移动后的 brk 位置。下面使用 sbrk 实现一个巨简单的 malloc。 void *malloc(size_t size) { void *p = sbrk(0); void *request = sbrk(size); if (request sbrk与mmap 在堆区中, start_brk 指向 heap 的开始,而 brk 指向 heap 的顶部。 可以使用系统调用 brk()和 sbrk()来增 加标识 heap 顶部的 brk 值,从而线性的增加分配给用户的 heap 空间。

    1.9K20编辑于 2023-09-06
  • 来自专栏linux驱动个人学习

    一篇文章彻底讲懂malloc的实现(ptmalloc)

    三、brk(sbrk)和mmap函数 首先,linux系统向用户提供申请的内存有brk(sbrk)和mmap函数。下面我们先来了解一下这几个函数。 1、brk() 和 sbrk() #include <unistd.h> int brk( const void *addr ) void* sbrk ( intptr_t incr ); 两者的作用是扩展 当top chunk大小小于用户所请求的大小时,top chunk就通过sbrk(main arena)或mmap(thread arena)系统调用来扩容。 六、sbrk与mmap   在堆区中, start_brk 指向 heap 的开始,而 brk 指向 heap 的顶部。 可以使用系统调用 brk()和 sbrk()来增 加标识 heap 顶部的 brk 值,从而线性的增加分配给用户的 heap 空间。

    4.5K11编辑于 2024-02-23
  • 来自专栏C语言中文社区

    深入理解C语言中的 malloc:malloc() 与 free() 原理图解

    三者概念的解释如下: arena:通过sbrk或mmap系统调用为线程分配的堆区,按线程的类型可以分为2类: main arena:主线程建立的arena; thread arena:子线程建立的arena main arena中的内存申请 main arena中的内存申请的流程如下图所示: 第一次申请 根据申请内存空间大小是否达到mmap这一系统调用的分配阈值,决定是使用sbrk系统调用 还是mmap系统调用申请堆区 举例而言,用户申请1000字节的内存,实际会通过sbrk系统调用产生132KB的连续堆内存区域。 然后将用户申请大小的内存返回。(本例中将返回1000字节的内存。) 中的申请 thread arena中的内存申请的流程如下图所示: 其流程类似于main arena的,区别在于thread arena的堆内存是使用mmap系统调用产生的,而非同主线程一样可能会使用sbrk 若已经初始化过了,主分配区则调用sbrk()增加heap空间,分主分配区则在top chunk中切割出一个chunk,使之满足分配需求,并将内存指针返回给用户。

    1.5K31编辑于 2022-05-31
  • 来自专栏全栈程序员必看

    【c语言】malloc函数详解[通俗易懂]

    Linux维护一个break指针,这个指针执行堆空间的某个地址,从堆开始到break之间的地址空间为映射好的,可以供进程访问,而从break往上,是未映射的地址空间,如果访问这段空间则程序会报错 brk与sbrk Linux通过brk和sbrk系统调用操作break指针。 两个系统调用的原型如下: int brk(void *addr); void *sbrk(inptr_t increment); brk将break指针直接设置为某个地址,而sbrk将break从当前位置移动 这里关键是如何只使用sbrk创建一个struct: #define BLOCK_SIZE 24 t_block extend_heap{ t_block b; b = sbrk(0); if(sbrk(BLOCK_SIZE+s)==(void*)-1) return NULL; b->size = s; b->next

    2K20编辑于 2022-07-01
  • 来自专栏Miigon's Blog

    [mit6.s081] 笔记 Lab2: System calls | 系统调用

    define SYS_fstat 8 #define SYS_chdir 9 #define SYS_dup 10 #define SYS_getpid 11 #define SYS_sbrk ] sys_sbrk, [SYS_sleep] sys_sleep, [SYS_uptime] sys_uptime, [SYS_open] sys_open, [SYS_write fstat"); entry("link"); entry("mkdir"); entry("chdir"); entry("dup"); entry("getpid"); entry("sbrk char*); int mkdir(const char*); int chdir(const char*); int dup(int); int getpid(void); char* sbrk ] "sbrk", [SYS_sleep] "sleep", [SYS_uptime] "uptime", [SYS_open] "open", [SYS_write] "write

    1.3K20编辑于 2022-10-27
领券