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

news2024/11/25 20:51:43

一、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同时访问的变量,可能会引发一些通信方面的问题,采用上述概念刚好绕过了这些问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/973626.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于java SpringBoot和Vue uniapp的影楼摄影预约小程序

摘要 今天信息技术的发展很快,其足迹在我们的生活中随处可见。它影响着我们的衣食住行等各种需求。影响也在逐渐增加,逐渐渗透到各行各业,在这种背景下,经过实地考察后,为了让婚纱照管理更加高效方便,我决定…

Java的输入与输出

在Java中,输入和输出是通过标准的输入流(System.in)和标准的输出流(System.out)进行处理的。我们可以通过util.Scanner这个类实现输入和输出,以下是一些常用的输入输出函数的介绍 输出: System.…

NFTScan 浏览器正式版上线 2 周年!

NFTScan 成立于 2021 年 4 月份,总部位于香港。在 2021 年的 7 月份,NFTScan 团队对外发布了 NFTScan 浏览器公测版,并在同年的 9 月 4 号,对外发布了 NFTScan 浏览器正式版,同步启用了全球品牌域名:NFTSCA…

深入理解线段树

大家好,我是 方圆。线段树(Segment Tree) 是常用的维护 区间信息 的数据结构,它可以在 O(logn) 的时间复杂度下实现单点修改、区间修改、区间查询(区间求和、区间最大值或区间最小值)等操作,常用…

SCS【33】单细胞转录之全自动超快速的细胞类型鉴定 (ScType)

‍ ‍ 单细胞生信分析教程 桓峰基因公众号推出单细胞生信分析教程并配有视频在线教程,目前整理出来的相关教程目录如下: Topic 6. 克隆进化之 Canopy Topic 7. 克隆进化之 Cardelino Topic 8. 克隆进化之 RobustClone SCS【1】今天开启单细胞之旅&#x…

Windows中多线程的基础知识——1互斥对象

目录 1 多线程的基本概念1.1 进程一、程序和进程的概念二、进程组成三、进程地址空间 1.2 线程一、线程组成二、线程运行三、线程创建函数 1.3 多进程与多线程并发一、多进程并发二、多线程并发 2 线程同步2.1 一个经典的线程同步问题2.2 利用互斥对象实现线程同步一、创建互斥…

【英文文章总结】数据管理指南系列:渐进式数据库设计

原文连接:系列https://martinfowler.com/data/https://martinfowler.com/data/ Evolutionary Database Design (martinfowler.com) 架构的进化。如何允许更改架构并轻松迁移现有数据? 如何应对项目的变动 迭代开发:很长一段时间人们把数据…

《人生苦短——我学Python》条件判断->双向选择(if--else)

今天我们来学习双向选择判断。顾名思义,双向就是两种选择选其一,即if----else。如果If的条件不成立,则执行else下的语句,否则执行if下面的语句。显然,它们是互斥的!下面就让我们来详细看看吧! 文…

FastViT实战:使用FastViT实现图像分类任务(一)

文章目录 摘要安装包安装timm安装 grad-cam安装mmcv 数据增强Cutout和MixupEMA项目结构计算mean和std生成数据集补充一个知识点:torch.jit两种保存方式 摘要 论文翻译:https://wanghao.blog.csdn.net/article/details/132407722?spm1001.2014.3001.550…

国内 11 家通过备案的 AI 大模型产品

国内 11 家通过《生成式人工智能服务管理暂行办法》备案的 AI 大模型产品将陆续上线。 一、北京5家 1、百度的 “文心一言”https://yiyan.baidu.com 2、抖音的 “云雀”,基于云雀大模型开发的 AI 机器人 “豆包” 开始小范围邀请测试。用户可通过手机号、抖音或…

数据结构:栈的实现

1. 栈(Stack) 1.1 栈的概念 栈(Stack)是只允许在一端进行插入或删除操作的线性表.首先栈是一种线性表,但限定这种线性表只能在某一端进行插入和删除操作.进行数据插入和删除操作的一端叫栈顶,另一端称为栈底.栈中的元素遵循后进先出LIFO(Last In First Out)的原则 压栈:栈的插…

【论文投稿】图形学论文投稿去向

如果您想投稿关于网格几何处理的论文,以下是一些知名的学术会议和期刊,您可以考虑将您的研究成果提交到这些地方: 学术会议: SIGGRAPH:SIGGRAPH会议是计算机图形学领域最重要的会议之一,接收与图形学和交互…

力扣:86. 分隔链表(Python3)

题目: 给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。 你应当 保留 两个分区中每个节点的初始相对位置。 来源:力扣(LeetCode)…

2023-9-4 快速幂

题目链接&#xff1a;快速幂 #include <iostream> #include <algorithm>using namespace std;typedef long long LL;LL qmi(int a, int k, int p) {LL res 1;while(k){if(k & 1) res (LL) res * a % p;k >> 1;a (LL) a * a % p;}return res; }int mai…

羊城杯2023 部分wp

目录 D0nt pl4y g4m3!!!(php7.4.21源码泄露&pop链构造) Serpent(pickle反序列化&python提权) ArkNights(环境变量泄露) Ez_misc(win10sinpping_tools恢复) D0nt pl4y g4m3!!!(php7.4.21源码泄露&pop链构造) 访问/p0p.php 跳转到了游戏界面 应该是存在302跳转…

如何高效的解析Json?

Json介绍 Json是一种数据格式&#xff0c;广泛应用在需要数据交互的场景Json由键值对组成每一个键值对的key是字符串类型每一个键值对的value是值类型(boo1值数字值字符串值)Array类型object类型Json灵活性他可以不断嵌套&#xff0c;数组的每个元素还可以是数组或者键值对键值…

Kubernetes v1.25.0集群搭建实战案例(新版本含Docker容器运行时)

k8s 1.24之后弃用了docker容器运行时&#xff0c;安装方式上有所不同&#xff0c;网上找到的大多数都是1.24之前的版本。所以把自己搭建的完整过程记录下来供大家参考。 一、前言 k8s的部署方式有多种kubeadm、kind、minikube、Kubespray、kops等本文介绍官方推荐的kubeadm的…

Python入门学习12

一、Python包 什么是Python包 从物理上看&#xff0c;包就是一个文件夹&#xff0c;在该文件夹下包含了一个 __init__.py 文件&#xff0c;该文件夹可用于包含多个模块文件。从逻辑上看&#xff0c;包的本质依然是模块 包的作用: 当我们的模块文件越来越多时,包可以帮助我们管…

arco-design-vue的tree组件实现右击事件

arco-design-vue的tree组件实现右击事件 业务中需要使用到tree组件&#xff0c;并且还要对tree实现自定义鼠标右击事件。在arco-design-vue的文档中&#xff0c;可以明确的看到&#xff0c;tree组件并没有右击事件的相关回调&#xff0c;那要如何实现呢&#xff1f;&#xff1f…

10 和为K的子数组

和为K的子数组 题解1 前缀和&#xff08;哈希表&#xff09;题解2 暴力枚举(没过) 给你一个整数数组 nums 和一个整数 k &#xff0c;请你统计并返回 该数组中和为 k 的 连续子数组的个数 。 示例 1&#xff1a; 输入&#xff1a;nums [1,1,1], k 2 输出&#xff1a;2示例…