欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 养生 > Linux proc文件系统 内存影射

Linux proc文件系统 内存影射

2025/5/15 21:44:35 来源:https://blog.csdn.net/JK01WYX/article/details/147962537  浏览:    关键词:Linux proc文件系统 内存影射

文章目录

      • 常见的内存分配函数
      • /proc/pid/ 目录解析
    • 用户进程的内存空间分配算法
      • mmap 分配大内存可能不在堆中
          • 换为 malloc 现象相同

常见的内存分配函数

  • malloc / calloc / realloc(来自 C 标准库)
void *malloc(size_t size):分配 size 字节的内存。
void *calloc(size_t nmemb, size_t size):分配并初始化为0的内存,大小为 nmemb * size。
void *realloc(void *ptr, size_t size):重新分配一块内存。
释放函数:
void free(void *ptr):释放由 malloc/calloc/realloc 分配的内存。
  • mmap / munmap(Linux 系统调用级别)
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset):用于分配匿名内存或映射文件。
int munmap(void *addr, size_t length):释放 mmap 分配的内存。
常用于共享内存、匿名内存区域的分配,灵活性更高。// 使用 mmap 分配匿名内存
size_t size = 4096; // 分配 1 页(通常 4KB)大小的内存
void *addr = mmap(NULL, size, PROT_READ | PROT_WRITE,MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);if (addr == MAP_FAILED) {perror("mmap failed");return 1;
}

/proc/pid/ 目录解析

在这里插入图片描述

  • /proc/<pid>/maps : 内存映射区域概览 【程序地址空间】
    该文件列出进程的每个虚拟内存区域的信息,包括地址、权限、偏移、设备、inode 以及映射的文件(如有)。
    <起始地址>-<结束地址> <权限> <偏移> <设备号> <inode> <路径>
    在这里插入图片描述
    如图,是从上到下为低地址向高地址的程序地址空间。
    在这里插入图片描述

  • 2./proc/<pid>/status —— 进程状态摘要(含内存使用情况)
    提供当前进程的状态、资源使用、权限、线程数等,常用于查看内存大小的总体信息。

VmPeak:   132456 kB  使用过的最大虚拟内存
VmSize:   130000 kB  当前分配的虚拟内存
VmRSS:     20480 kB  常驻内存集(实际占用物理内存)
VmData:    90000 kB  数据段使用内存
VmStk:       136 kB  栈区大小
VmExe:      1024 kB  代码段大小
VmLib:     16384 kB  进程加载的 共享库(Shared Library) 占用的虚拟内存大小
  • 3./proc/<pid>/smaps —— maps 的详细版(精细统计每段内存)
    该文件扩展了 maps 的内容,为每个内存段提供详细内存使用信息,如共享、私有的内存、页的大小等。
7f0c5f000000-7f0c5f021000 rw-p 00000000 00:00 0 
Size:                132 kB  区域大小
Rss:                  20 kB  实际驻留物理内存
Pss:                  10 kB  平均共享内存
Shared_Clean:          0 kB  被多个进程共享的页面
Shared_Dirty:          0 kB
Private_Clean:         0 kB   私有页面
Private_Dirty:        20 kB
Referenced:           20 kB   被访问过的内存
Anonymous:            20 kB   匿名映射(如 malloc 分配的内存)
...

用户进程的内存空间分配算法

  1. 连续分配算法
    • 定义:为进程分配一个连续的内存区域,进程的所有数据和代码都存放在该连续空间中。

    • 典型算法:
      单一连续分配:整个内存仅分配给一个进程(早期单任务系统)。
      固定分区分配:内存划分为若干固定大小的分区,每个分区装入一个进程。
      动态分区分配:根据进程需求动态划分内存,如首次适应、最佳适应算法。【连续分配算法】

      • 首次适应算法(First Fit):从空闲分区链的起始位置开始扫描,找到第一个大小足够满足请求的空闲分区,将其分割后分配给进程。
      • 最佳适应算法(Best Fit):遍历整个空闲分区链,找到大小最接近请求且不小于请求的空闲分区进行分配。(实际上碎片化问题更严重)
    • 特点:实现简单,但内存碎片问题严重,空间利用率低。

  2. 离散分配算法
    • 定义:将进程拆分为多个部分,分配到不连续的内存块中,通过地址映射机制(如页表、段表)实现逻辑地址到物理地址的转换。
    • 典型算法:
      分页存储管理:进程划分为固定大小的页(Page),内存划分为页框(Frame),页与页框一一对应。
      分段存储管理:进程划分为逻辑上独立的段(Segment),如代码段、数据段,各段分配独立的内存区域。
      段页式存储管理:结合分段和分页,先分段再分页。
    • 特点:有效解决内存碎片问题,支持虚拟内存,是现代操作系统的主流方案。

现代操作系统(如 Linux、Windows)对用户进程的内存管理采用基于分页的虚拟内存机制,属于离散分配算法的范畴,但实现细节更为复杂。

mmap 分配大内存可能不在堆中

小内存分配(通常小于 128KB)
通过 堆(Heap) 分配,使用 brk 系统调用扩展进程的堆空间,内存区域在 /proc/pid/maps 中标记为 [heap]。

大内存分配(通常大于等于 128KB)
通过 匿名映射(Anonymous Mapping) 分配,使用 mmap 系统调用在虚拟地址空间中创建独立的内存区域,这类区域在 /proc/pid/maps 中标记为 rw-p 00000000 00:00 0(无文件关联的匿名映射),不属于传统堆或共享区。

编写程序,连续申请分配六个128MB空间(记为1~6号),然后释放第2、3、5号的128MB空间。然后再分配1024MB,再分配64M内存,观察 /proc/pid/maps, 【解释说明用户进程空间分配属于课本中的离散还是连续分配算法?首次适应还是最佳适应算法?用户空间存在碎片问题吗?】

代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>#define ALLOC_MB(x) ((x) * 1024 * 1024)void *alloc_region(size_t size) {void *ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);if (ptr == MAP_FAILED) {perror("mmap");exit(1);}return ptr;
}void print_hint(const char *msg) {printf("\n==== %s ====\n", msg);printf("pid = %d,请查看 /proc/%d/maps\n", getpid(), getpid());printf("按 Enter 继续...\n");getchar();
}int main() {void *blocks[6];// 分配六块 128MB 匿名内存for (int i = 0; i < 6; i++) {blocks[i] = alloc_region(ALLOC_MB(128));memset(blocks[i], 0, 1);  // 确保内存实际分配}print_hint("已分配 6 块 128MB");// 释放第 2、3、5 块munmap(blocks[1], ALLOC_MB(128));munmap(blocks[2], ALLOC_MB(128));munmap(blocks[4], ALLOC_MB(128));print_hint("已释放第 2、3、5 块");// 分配 1024MBvoid *big = alloc_region(ALLOC_MB(1024));memset(big, 0, 1);print_hint("已分配 1024MB");// 再分配 64MBvoid *extra = alloc_region(ALLOC_MB(64));memset(extra, 0, 1);print_hint("已分配额外的 64MB");sleep(60);return 0;
}
  • 分配 6 个 128MB 内存块:
    在这里插入图片描述
    [heap]下一行的 7fc8c95d8000-7fc8f95d8000 即为分配的6个128MB内存块
    0x7fc8f95d8000 - 0x7fc8c95d8000 = 0x30000000 = 768MB
    mmap 分配的大块内存,不在 [heap] 上!

  • 释放第 2、3、5 号内存块:
    在这里插入图片描述
    [heap]下这三段:
    7fc8c95d8000-7fc8d15d8000 rw-p …
    7fc8d95d8000-7fc8e15d8000 rw-p …
    7fc8f15d8000-7fc8f95d8000 rw-p …
    刚好是 128*3 = 384 MB. 地址连续但 有缺口,说明确实释放了中间段

  • 分配一个 1024MB 内存块:
    在这里插入图片描述
    7fc8c95d8000-7fc8d15d8000 变为 7fc8895d8000-7fc8d15d8000 这是分配了1024MB内存
    0x7fc8d15d8000 - 0x7fc8895d8000 = 0x48000000 = 1207959552 bytes = 1152 MB

  • 额外分配一个 64MB 内存块:
    在这里插入图片描述
    7fc8f15d80000-7fc8f95d80000 变为了7fc8ed5d8000-7fc8f95d8000
    = 0x7fc8f95d8000 - 0x7fc8ed5d8000
    = 0x080000000 (十六进制)
    = 128MB + 64MB = 192MB malloc 的 64MB 被放入了这块扩展后的区域中。

换为 malloc 现象相同
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>#define ALLOC_MB(x) ((x) * 1024 * 1024)void *alloc_region(size_t size) {void *ptr = malloc(size);if (ptr == NULL) {perror("malloc");exit(1);}return ptr;
}void free_region(void *ptr, size_t size) {free(ptr);
}void print_hint(const char *msg) {printf("\n==== %s ====\n", msg);printf("pid = %d,请查看 /proc/%d/maps\n", getpid(), getpid());printf("按 Enter 继续...\n");getchar();
}int main() {void *blocks[6];getchar();// 分配六块 128MB 内存for (int i = 0; i < 6; i++) {blocks[i] = alloc_region(ALLOC_MB(128));memset(blocks[i], 0, 1);  // 确保内存实际分配}print_hint("已分配 6 块 128MB");// 释放第 2、3、5 块free_region(blocks[1], ALLOC_MB(128));free_region(blocks[2], ALLOC_MB(128));free_region(blocks[4], ALLOC_MB(128));print_hint("已释放第 2、3、5 块");// 分配 1024MBvoid *big = alloc_region(ALLOC_MB(1024));memset(big, 0, 1);print_hint("已分配 1024MB");// 再分配 64MBvoid *extra = alloc_region(ALLOC_MB(64));memset(extra, 0, 1);print_hint("已分配额外的 64MB");sleep(60);return 0;
}    

起始:

5635d3a68000-5635d3a69000 r--p 00000000 08:05 655630                     /home/wyx/work/SZU_OS/ex3/memtest2.out
5635d3a69000-5635d3a6a000 r-xp 00001000 08:05 655630                     /home/wyx/work/SZU_OS/ex3/memtest2.out
5635d3a6a000-5635d3a6b000 r--p 00002000 08:05 655630                     /home/wyx/work/SZU_OS/ex3/memtest2.out
5635d3a6b000-5635d3a6c000 r--p 00002000 08:05 655630                     /home/wyx/work/SZU_OS/ex3/memtest2.out
5635d3a6c000-5635d3a6d000 rw-p 00003000 08:05 655630                     /home/wyx/work/SZU_OS/ex3/memtest2.out
5635d3fcf000-5635d3ff0000 rw-p 00000000 00:00 0                          [heap]
7fa337f61000-7fa337f83000 r--p 00000000 08:05 1050757                    /usr/lib/x86_64-linux-gnu/libc-2.31.so
7fa337f83000-7fa3380fb000 r-xp 00022000 08:05 1050757                    /usr/lib/x86_64-linux-gnu/libc-2.31.so
7fa3380fb000-7fa338149000 r--p 0019a000 08:05 1050757                    /usr/lib/x86_64-linux-gnu/libc-2.31.so
7fa338149000-7fa33814d000 r--p 001e7000 08:05 1050757                    /usr/lib/x86_64-linux-gnu/libc-2.31.so
7fa33814d000-7fa33814f000 rw-p 001eb000 08:05 1050757                    /usr/lib/x86_64-linux-gnu/libc-2.31.so
7fa33814f000-7fa338155000 rw-p 00000000 00:00 0 
7fa338168000-7fa338169000 r--p 00000000 08:05 1050743                    /usr/lib/x86_64-linux-gnu/ld-2.31.so
7fa338169000-7fa33818c000 r-xp 00001000 08:05 1050743                    /usr/lib/x86_64-linux-gnu/ld-2.31.so
7fa33818c000-7fa338194000 r--p 00024000 08:05 1050743                    /usr/lib/x86_64-linux-gnu/ld-2.31.so
7fa338195000-7fa338196000 r--p 0002c000 08:05 1050743                    /usr/lib/x86_64-linux-gnu/ld-2.31.so
7fa338196000-7fa338197000 rw-p 0002d000 08:05 1050743                    /usr/lib/x86_64-linux-gnu/ld-2.31.so
7fa338197000-7fa338198000 rw-p 00000000 00:00 0 
7ffe3d307000-7ffe3d328000 rw-p 00000000 00:00 0                          [stack]
7ffe3d3f1000-7ffe3d3f5000 r--p 00000000 00:00 0                          [vvar]
7ffe3d3f5000-7ffe3d3f7000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0                  [vsyscall]

分配 6 块 128MB: 发现也不在堆中

5635d3a68000-5635d3a69000 r--p 00000000 08:05 655630                     /home/wyx/work/SZU_OS/ex3/memtest2.out
5635d3a69000-5635d3a6a000 r-xp 00001000 08:05 655630                     /home/wyx/work/SZU_OS/ex3/memtest2.out
5635d3a6a000-5635d3a6b000 r--p 00002000 08:05 655630                     /home/wyx/work/SZU_OS/ex3/memtest2.out
5635d3a6b000-5635d3a6c000 r--p 00002000 08:05 655630                     /home/wyx/work/SZU_OS/ex3/memtest2.out
5635d3a6c000-5635d3a6d000 rw-p 00003000 08:05 655630                     /home/wyx/work/SZU_OS/ex3/memtest2.out
5635d3fcf000-5635d3ff0000 rw-p 00000000 00:00 0                          [heap]
7fa307f5b000-7fa337f61000 rw-p 00000000 00:00 0 
7fa337f61000-7fa337f83000 r--p 00000000 08:05 1050757                    /usr/lib/x86_64-linux-gnu/libc-2.31.so
7fa337f83000-7fa3380fb000 r-xp 00022000 08:05 1050757                    /usr/lib/x86_64-linux-gnu/libc-2.31.so
7fa3380fb000-7fa338149000 r--p 0019a000 08:05 1050757                    /usr/lib/x86_64-linux-gnu/libc-2.31.so
7fa338149000-7fa33814d000 r--p 001e7000 08:05 1050757                    /usr/lib/x86_64-linux-gnu/libc-2.31.so
7fa33814d000-7fa33814f000 rw-p 001eb000 08:05 1050757                    /usr/lib/x86_64-linux-gnu/libc-2.31.so
7fa33814f000-7fa338155000 rw-p 00000000 00:00 0 
7fa338168000-7fa338169000 r--p 00000000 08:05 1050743                    /usr/lib/x86_64-linux-gnu/ld-2.31.so
7fa338169000-7fa33818c000 r-xp 00001000 08:05 1050743                    /usr/lib/x86_64-linux-gnu/ld-2.31.so
7fa33818c000-7fa338194000 r--p 00024000 08:05 1050743                    /usr/lib/x86_64-linux-gnu/ld-2.31.so
7fa338195000-7fa338196000 r--p 0002c000 08:05 1050743                    /usr/lib/x86_64-linux-gnu/ld-2.31.so
7fa338196000-7fa338197000 rw-p 0002d000 08:05 1050743                    /usr/lib/x86_64-linux-gnu/ld-2.31.so
7fa338197000-7fa338198000 rw-p 00000000 00:00 0 
7ffe3d307000-7ffe3d328000 rw-p 00000000 00:00 0                          [stack]
7ffe3d3f1000-7ffe3d3f5000 r--p 00000000 00:00 0                          [vvar]
7ffe3d3f5000-7ffe3d3f7000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0                  [vsyscall]

释放第 2、3、5 块后现象相同:

5635d3a68000-5635d3a69000 r--p 00000000 08:05 655630                     /home/wyx/work/SZU_OS/ex3/memtest2.out
5635d3a69000-5635d3a6a000 r-xp 00001000 08:05 655630                     /home/wyx/work/SZU_OS/ex3/memtest2.out
5635d3a6a000-5635d3a6b000 r--p 00002000 08:05 655630                     /home/wyx/work/SZU_OS/ex3/memtest2.out
5635d3a6b000-5635d3a6c000 r--p 00002000 08:05 655630                     /home/wyx/work/SZU_OS/ex3/memtest2.out
5635d3a6c000-5635d3a6d000 rw-p 00003000 08:05 655630                     /home/wyx/work/SZU_OS/ex3/memtest2.out
5635d3fcf000-5635d3ff0000 rw-p 00000000 00:00 0                          [heap]
7fa307f5b000-7fa30ff5c000 rw-p 00000000 00:00 0 
7fa317f5d000-7fa31ff5e000 rw-p 00000000 00:00 0 
7fa32ff60000-7fa337f61000 rw-p 00000000 00:00 0 
7fa337f61000-7fa337f83000 r--p 00000000 08:05 1050757                    /usr/lib/x86_64-linux-gnu/libc-2.31.so
7fa337f83000-7fa3380fb000 r-xp 00022000 08:05 1050757                    /usr/lib/x86_64-linux-gnu/libc-2.31.so
7fa3380fb000-7fa338149000 r--p 0019a000 08:05 1050757                    /usr/lib/x86_64-linux-gnu/libc-2.31.so
7fa338149000-7fa33814d000 r--p 001e7000 08:05 1050757                    /usr/lib/x86_64-linux-gnu/libc-2.31.so
7fa33814d000-7fa33814f000 rw-p 001eb000 08:05 1050757                    /usr/lib/x86_64-linux-gnu/libc-2.31.so
7fa33814f000-7fa338155000 rw-p 00000000 00:00 0 
7fa338168000-7fa338169000 r--p 00000000 08:05 1050743                    /usr/lib/x86_64-linux-gnu/ld-2.31.so
7fa338169000-7fa33818c000 r-xp 00001000 08:05 1050743                    /usr/lib/x86_64-linux-gnu/ld-2.31.so
7fa33818c000-7fa338194000 r--p 00024000 08:05 1050743                    /usr/lib/x86_64-linux-gnu/ld-2.31.so
7fa338195000-7fa338196000 r--p 0002c000 08:05 1050743                    /usr/lib/x86_64-linux-gnu/ld-2.31.so
7fa338196000-7fa338197000 rw-p 0002d000 08:05 1050743                    /usr/lib/x86_64-linux-gnu/ld-2.31.so
7fa338197000-7fa338198000 rw-p 00000000 00:00 0 
7ffe3d307000-7ffe3d328000 rw-p 00000000 00:00 0                          [stack]
7ffe3d3f1000-7ffe3d3f5000 r--p 00000000 00:00 0                          [vvar]
7ffe3d3f5000-7ffe3d3f7000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0                  [vsyscall]

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词