Linux内存管理部分系统调用与示例分析 您所在的位置:网站首页 malloc返回的地址对齐 Linux内存管理部分系统调用与示例分析

Linux内存管理部分系统调用与示例分析

2023-05-06 17:09| 来源: 网络整理| 查看: 265

写在前面

总结Linux系统调用的内存分配与虚拟内存管理部分, 包括堆内存和栈内存的操作, 分配, 释放等.

参考: Linux/Unix系统编程手册第六/七章.

基本系统调用: brk/sbrk C库函数: malloc/realloc/calloc/alloca/free 虚拟内存管理 简介

首先来看进程的内存布局, 如下图:

截屏2023-02-04 00.37.08.jpg

但是实际上, 这个布局并不是真实存在物理内存中的, 而是位于虚拟内存中.

利用访问局部性以追求高效地使用CPU和RAM(物理内存, 随机访问存储器)资源.

所谓访问局部性, 可以表现为以下两种情况:

时间局部性: 程序倾向于在不久的将来再次访问最近刚访问过的内存地址(例如循环) 空间局部性: 程序倾向于访问最近访问过的内存地址附近的内存(由于指令的顺序执行) 基本规划 将每个程序使用的内存切割成小型的/固定大小的页(page, 内存页)单元, 相应地, 将RAM划分成一系列与虚拟内存页尺寸相同的页帧. 虚拟内存的优点 进程与进程之间/进程与内核之间相互隔离, 所以一个进程不能读取或修改另一进程或内核的内存(通过页表建立纽带, 物理内存间隔离); 适当情况下, 两个或者更多的进程能够共享内存(不同进程的页表可以指向同一RAM物理内存分页) 便于实现内存保护机制, 通过对页表条目进行标记来实现. 程序员/编译器/链接器等无需在意程序在物理内存(RAM)中的布局 程序加载运行速度提高. 物理内存中可同时容纳的进程数量增多了, CPU利用率也相应提高. brk与sbrk 简介

brk一词来源于program break, 指的是堆的当前内存边界. 来看下图:

截屏2023-02-04 00.37.08.jpg

图中程序中断箭头所指位置, 就是堆内存的边界, 最初, 程序中断位置位于未初始化数据段的末尾之后, 与&end位置相同(图中bss段)

在程序中断位置抬升之后, 程序就可以方位新分配区域内的任何内存地址, 此时物理内存页尚未分配.

内核会在进程首次试图访问这些虚拟内存地址时自动分配新的物理内存页.

基本调用格式 #include int brk(void *end_data_segment); // return 0 on success, or -1 on error void *sbrk(intptr_t increment); // return previous program break on success, or (void *) -1 on error

对于brk系统调用, 虽然传入的是指定的数据段结束位置, 但是实际上是四舍五入之后到下一个内存页边界处的结果, 因为内存分配是按照内存页为单位分配的.

brk可能会引起段错误, 因为当访问的位置低于其初始值(图中&end位置), 会产生未定义行为

sbrk是由brk封装得到的系统调用(在Linux下), 通过增量形式进行内存分配, 当参数increment为0时, 返回当前program break(程序中断)的地址, 不做任何改变. 用于 :

跟踪堆的大小 监视内存分配函数包的行为 malloc与free 简介

使用C标准库函数malloc/free来分配内存, 具有以下几种优点:

属于C标准库的一部分 多线程程序常用 接口简单, 允许分配小块内存 允许随意释放内存块, 维护于一张空闲内存列表中, 在后续的内存分配调用时循环使用 函数声明 #include void *malloc(size_t size); void free(void *ptr); malloc(0): 返回NULL或者一块小的内存(可以由free释放). 若无法分配内存, 则malloc返回NULL, 并设置errno. free释放ptr指向的内存块. 为free传入空指针相当于空语句. 不能对同一块内存free两次. 在使用malloc分配了堆内存之后, 虽然程序结束之后会由系统回收对应的内存, 但是还是最好调用free释放对应的内存.

一般情况下, free不会降低program break的位置, 而是将这块内存添加到空闲内存列表中, 供后续的malloc函数循环使用. 其原因有:

被释放的内存块通常位于堆的中间, 非堆顶, 所以降低program break是不可能的 最大限度减少了程序必须执行的sbrk的调用次数(即使是系统调用也会有开销) 大多数情况下降低program break的位置不会对那些分配大量内存的程序有多少帮助, 因为它们通常倾向于持有已分配内存或是反复释放和重新分配内存, 而非释放所有内存后再持续运行一段时间. 内存分配与释放示例 #include #include #include #include #include const int MAX_ALLOCS = 1000000; const int NUM = 1000; const int BLOCK_SIZE = 10240; const int FREE_STEP = 1; const int FREE_MIN = 500; const int FREE_MAX = NUM; int main(int argc, char *argv[]) { char *ptr[MAX_ALLOCS]; int j; if (NUM > MAX_ALLOCS) fprintf(stderr, "num-allocs > %d\n", MAX_ALLOCS); if (FREE_MAX > NUM) fprintf(stderr, "free-max > num-allocs\n"), exit(1); printf("Initial program break: %10p\n", sbrk(0)); printf("Allocating %d*%d bytes\n", NUM, BLOCK_SIZE); for (j = 0; j


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有