Linux内核源码分析 (B.x)内核内存布局和堆管理

Linux内核源码分析 (B.x)内核内存布局和堆管理

一、Linux内核内存布局

  • 64位Linux一般使用48位来表示虚拟地址空间,45位表示物理地址。通过命令:cat/proc/cpuinfo。查看Linux内核位数和proc文件系统输出系统软硬件信息如下:

    lh@LH_LINUX:~$ cat /proc/cpuinfo
    vendor_id	: GenuineIntel	// CPU制造商
    cpu family	: 6 			// CPU产品代号
    model		: 165			// CPU属于其系列当中的哪一个代号
    model name	: Intel(R) Core(TM) i7-10875H CPU @ 2.30GHz // CPU属于的名称、编号、主频
    stepping	: 2				// CPU属于制作更新版本
    cpu MHz		: 2303.999		//CPU实际使用主频
    cache size	: 16384 KB		//CPU二级缓存
    physical id	: 0				//单个CPU的标号
    siblings	: 2				//单个CPU逻辑物理核数
    core id		: 0				//当前物理核在其所处的CPU中编号
    cpu cores	: 2				//逻辑核所在CPU的物理核数
    apicid		: 0				//用来区分不同逻辑核的编号
    bogomips : 4607.99 			//系统内核启动时测算的CPU速度
    clflush size : 64			//每次刷新缓存的大小单位
    cache_alignment : 64 		//缓存地址空间对齐单位
    address sizes : 45 bits physical. 48 bits virtual // 可以访问的地址空间位数
    
  • 通过cat/proc/meminfo输出系统架构内存分布情况,具体如下

    lh@LH_LINUX:~$ cat /proc/meminfo
    MemTotal: 12165668 kB 		//所有可用内存空间的大小
    MemFree: 10151616 kB 		//系统还没有使用内存
    MemAvailable: 10570548 kB	//真正系统可用内存
    Buffers: 52596 kB 			//专用用来给块设备做缓存的内存
    Cached: 575008 kB 			//分配给文件缓冲区的内存
    SwapCached: 0 kB 			//被高速缓冲缓存使用的交换空间大小
    Active: 1158808 kB 			//使用高速缓冲存储器页面文件大小
    Inactive: 345196 kB 		//没有经常使用的高速缓存存储器大小
    Active(anon): 870720 kB 	//活跃的匿名内存
    Inactive(anon)12504 kB 	//不活跃的匿名内存
    Active(file): 288088 kB 	//活跃的文件使用内存
    Inactive(file): 332692 kB 	//不活跃的文件使用内存
    Unevictable: 16kB			//不能被释放的内存页
    Mlocked: 16 kB 			//系统调用mlock允许程序在物理内存上锁住部分或全部地址空间
    SwapTotal: 2097148 kB 		//交换空间总内存大小
    SwapFree: 2097148 kB 		//交换空间空闲的内存大小
    Dirty: 24 kB 				//等待被写回到磁盘
    Writeback: 0 kB 			//正在被写加的大小
    AnonPages: 876420 kB 		//未映射页的内存/映射到用户空间的非文件页表大小
    Kipped: 255420 kB 			//映射文件内存
    Shmem: 13896 kB 			//已经被分配的共享内存
    KReclaimabie: 70884 kB 		//可回收的slab内存
    Slab: 151976 kB				//内存数据结构缓存大小
    CommitLimit: 8179980 kB 	//系统实际可以分配内存
    Committed_AS: 4649264 kB 	//系统当前已经分配的内存
    VmallocTotal: 34359738367 kB//预留虚拟内存的总量
    VmallocUsed: 27836 kB 		//已经被使用的虚拟内存
    VmallocChunk: 0 kB 			//可分配的最大逻辑地址连续的虚拟内存
    
  • Linux内核动态内存分配通过系统接口实现

    • alloc_pages/_get_free_page:以页为单位分配
    • vmalloc:以字节为单位分配虚拟地址连续的内存块
    • kmalloc:以字节为单位分配物理地址连续的内存块,它是以slab为中心
  • 我们也可以通过vmalloc分配的内存将它统计输出,具体如下:
    在这里插入图片描述

  • ARM64架构采用48位物理寻址方式,最大可寻找256TB的物理地址空间。对于目前应用完全足够,不需要扩展到64位。虚拟地址也同样最大支持48位寻址。Linux内核在大多数体系结构上将地址空间划为:用户空间和内核空间。

    • 用户空间(User space) : 0x0000_0000_0000_00000x0000_FFFF_FFFF_FFFF
    • 内核空间(Kernel space) : 0xFFFF_0000_0000_00000xFFFF_FFFF_FFFF_FFFF
      在这里插入图片描述
      • KASAN (影子区):它是一个动态检测内存错误的工具,原理利用额外的内存标记可用内存的状态(将1/8内存作为影子区);
      • modules:内核模块使用的虚拟地址空间;
      • vmallocvmalloc函数使用的虚拟地址空间
      • .text:代码段
      • .init:模块初始化数据
      • .data:数据段
      • bss:静态内存分配段
      • fixed:固定映射区域
      • PCI I/OPCI设备的I/O地址空间
      • vmemmap:内存的物理地址如果不连续的话,就会存在内存空洞(稀疏内存)vmemmap就用来存放稀疏内存的page结构体的数据的虚拟地址空间
      • memory:线性映射区域
    • 我们可以打印出ARM64体系结构的Linux内存布局(Linux内核初始化完成后,整体布局稳定。通过Vexpress平台输出即可,因为我们暂时没有环境,所以先通过源码分析打印流程。
      start_kernel() ==> mm_init() ==>mem_init() ==> printk(...)

二、堆管理

  • 堆是进程中主要用于动态分配变量和数据的内存区域,堆的管理对应程序员不是直接可见的。malloc和内核之间的经典接口是brk系统调用,负责拓展/收缩堆。堆是一个连续的内存区域,在拓展时自下至上增长。其中mm_struct结构,包含堆在虚拟地址空间中的起始和当前结束地址(start_brkbrk)。

    struct mm_struct{
    	...
    	unsigned long start_brk,brk,start_stack;
    	...
    }
    
  • brk系统调用指定堆在虚拟地址空间中新的结束地址(如果堆将要收缩,当然可以小于当前值)。brk系统调用动态分配,具体Linux内核源码分析如下

    SYSCALL_DEFINE1(brk, unsigned long, brk){
    	...
    }
    
  • Linux系统当中有两个方法可以创建堆:

    • brk()是系统调用,实际是设置进程数据段的结束地址,将数据段的结束地址向高地址移动。
    • mmap()向操作系统申请一段虚拟地址空间(使用映射到某个文件)。当不用此空间来映射到某个文件时,这块空间称为匿名空间可以用来作为堆空间。
  • per-cpu计数器,引入它用来加速SMP系统上计数器工作,Linux具体内核源码如下:

    #ifdef CONFIG_SMP
    
    struct percpu_counter {
    	spinlock_t lock;
    	s64 count;
    #ifdef CONFIG_HOTPLUG_CPU
    	struct list_head list;	/* All percpu_counters are on a list */
    #endif
    	s32 *counters;
    };
    
    • 采用per-cpu变量有下列好处:所需数据很可能存在于处理器的缓存中,因此可以更快速地访问。如果在多处理器系统中使用可能被所有CPU同时访问的变量,可能会引发一些通信方面的问题,采用上述概念刚好绕过了这些问题。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Elec Liu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值