进程地址空间 - 堆管理

堆是进程中用于动态分配变量和数据的内存区域。堆的管理对用户来说是不可见的,因为程序员只会使用标准库提供的辅助函数malloc等来分配任意长度的内存区。在kernel和malloc之间的经典接口是brk系统调用。堆是可以通过brk系统调用收缩和扩展的。新近的malloc调用使用了brk和匿名映射的组合方法,该方法提供了更好的性能。

堆是一块连续的内存区,扩展时是自下向上进行的,堆的地址范围在mm_struct中的start_brk和brk定义,start_brk定义了堆的起始地址,brk定义了堆的结束地址,start_brk是不会变化的,堆扩展或者收缩时会修改brk的值。

brk系统调用只有一个参数,用来指定brk的新的结束地址,新结束地址可以大于mm->brk(老的brk结束地址),也可以小于mm->brk。

236 asmlinkage unsigned long sys_brk(unsigned long brk)
 237 {
 238         unsigned long rlim, retval;
 239         unsigned long newbrk, oldbrk;
 240         struct mm_struct *mm = current->mm;
 241 
 242         down_write(&mm->mmap_sem);
 243 
 244         if (brk < mm->end_code)
 245                 goto out;
 246 
 247         /*
 248          * Check against rlimit here. If this check is done later after the test
 249          * of oldbrk with newbrk then it can escape the test and let the data
 250          * segment grow beyond its set limit the in case where the limit is
 251          * not page aligned -Ram Gupta
 252          */
 253         rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
 254         if (rlim < RLIM_INFINITY && brk - mm->start_data > rlim)
 255                 goto out;
 256 
 257         newbrk = PAGE_ALIGN(brk);
 258         oldbrk = PAGE_ALIGN(mm->brk);
 259         if (oldbrk == newbrk)
 260                 goto set_brk;
 261 
 262         /* Always allow shrinking brk. */
 263         if (brk <= mm->brk) {
 264                 if (!do_munmap(mm, newbrk, oldbrk-newbrk))
 265                         goto set_brk;
 266                 goto out;
 267         }
 268 
 269         /* Check against existing mmap mappings. */
 270         if (find_vma_intersection(mm, oldbrk, newbrk+PAGE_SIZE))
 271                 goto out;
 272 
 273         /* Ok, looks good - let it rip. */
 274         if (do_brk(oldbrk, newbrk-oldbrk) != oldbrk)
 275                 goto out;
 276 set_brk:
 277         mm->brk = brk;
 278 out:
 279         retval = mm->brk;
 280         up_write(&mm->mmap_sem);
 281         return retval;
 282 }

244 mm->end_code是代码区的结束地址,堆紧邻代码区,所以brk必然要大于mm->end_code

253~255 看起来data和heap区是紧挨着的,二者之和不能大于系统限制,RLIMIT_DATA是堆大小限制。

263~267 如果是收缩heap,那么调用do_unmap收缩堆

269~272如果是扩展heap,那么要先检查堆是否和进程中存在的内存映射区重叠,如果二者重叠,那么就无法扩展堆了

273~275 do_brk做堆的实际扩展工作。


系统调用brk实际上是基于匿名映射的实现,因此大部分用于管理内存映射的函数,都可以用于brk。



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值