arm-linux内存管理学习笔记(3)-页表前戏

2024-01-06 21:38

本文主要是介绍arm-linux内存管理学习笔记(3)-页表前戏,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

start_kernel之前的汇编代码建立了内核临时页表,完成了内核区域的静态线性映射,保证内核可以在舒适的虚拟地址空间(运行地址和链接地址一致)运行。进入start_kernel之后就要准备建立完整的页表映射,这部分工作是在paging_init中完成。
不过在建立完整页表映射之前还需要进行一些准备工作,本文来分析下。
为了简化整个代码流程,便于分析,我的设备内核配置为不使用高端内存,不配置CONFIG_HIGHMEM。bootargs中传给内核的mem=256.
内核版本号:3.4.55
paging_init是在start_kernel的setup_arch中调用,这里按照先后顺序对setup_arch跟页表相关的各个函数功能做个介绍,重点函数paging_init进行详细分析。
setup_processor:调用lookup_processor_type,跟head.S中__lookup_processor_type一样,获取存储在.proc.info.init段中与cpu id一致的proc_info_list结构体,该结构体中存储着处理器的一些特性。打印出cpu的一些相关信息(如版本号 cache属性等)。

setup_machine_tags:对uboot传递来的tags进行解析,获取mem cmdline等信息,具体过程可以参考我分析kernel传参的博文,链接:http://blog.csdn.net/skyflying2012/article/details/35787971

parse_early_param:对boot_command_line进行早期的解析,具体解析原理可以参考我分析kernel参数解析的博文,链接:http://blog.csdn.net/skyflying2012/article/details/41142801
与页表相关的是对mem的解析,相应的解析函数如下。

{static int usermem __initdata = 0;unsigned long size;phys_addr_t start;char *endp;/** If the user specifies memory size, we* blow away any automatically generated* size.*/if (usermem == 0) {usermem = 1;meminfo.nr_banks = 0;}start = PHYS_OFFSET;size  = memparse(p, &endp);if (*endp == '@')start = memparse(endp + 1, NULL);arm_add_memory(start, size);return 0;
}
early_param("mem", early_mem);

我的设备内存起始物理地址是0x80000000,即PHYS_OFFSET = 0x80000000,cmdline中mem=256m,
early_mem最终调用arm_add_memory将0x80000000起始的256MB内存添加到meminfo的membank数组中。meminfo中记录着系统有多少块连续内存,用membank数组记录,这里我们仅使用1个membank表示0x80000000起始的256MB内存空间。

sanity_check_meminfo:对meminfo中所有的membank进行范围检查,不能覆盖最小的vmalloc区域,将lowmem_limit设置为最高membank的顶端,我的设备只有一个membank,因此lowmem_limit为0x90000000,这是内存物理地址。最后将high_memory设置为lowmem_limit的虚拟地址,lowmem是线性映射到0xc0000000,因此high_memory=0xd0000000。
static void * __initdata vmalloc_min = (void *)(VMALLOC_END - (240 << 20) - VMALLOC_OFFSET);
我的设备VMALLOC_END=0xfc000000,这是vmalloc区域的上限,VMALLOC_OFFSET=0x800000,是vmalloc区域与lowmem之间8MB的隔离带。这样计算vmalloc_min是0xec800000,这是一个最小(240MB)的vmalloc区域.

arm_memblock_init:全局结构体memblock用来记录内存中可用和保留的区域,memblock.memory代表可用区域,memblock.reserved代表保留区域。arm_memblock_init中首先将meminfo中记录的membank添加到可用区域中。将kernel的代码段 数据段以及ramdisk区域都添加到保留区域,再将一级页目录的16KB区域添加到保留区域。
最后如果在板级结构体machine_desc定义了reserve函数,则会调用该函数完成板级相关的一些内存区域的保留。
为了方便调试,可以在cmdline中加入memblock=debug,会将memblock中可用和保留的区域全部打印出来。
我的设备是将0x80000000起始的256MB区域添加到可用区域memblock.memory中。
以上完成了对meminfo memblock的初始化,需要注意,其中存储的都是物理地址。

接下来调用paging_init,其中与页表建立相关的函数如下。在arch/arm/mm/mmu.c中

这篇关于arm-linux内存管理学习笔记(3)-页表前戏的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/577699

相关文章

ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法

《ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法》本文介绍了Elasticsearch的基本概念,包括文档和字段、索引和映射,还详细描述了如何通过Docker... 目录1、ElasticSearch概念2、ElasticSearch、Kibana和IK分词器部署

Linux流媒体服务器部署流程

《Linux流媒体服务器部署流程》文章详细介绍了流媒体服务器的部署步骤,包括更新系统、安装依赖组件、编译安装Nginx和RTMP模块、配置Nginx和FFmpeg,以及测试流媒体服务器的搭建... 目录流媒体服务器部署部署安装1.更新系统2.安装依赖组件3.解压4.编译安装(添加RTMP和openssl模块

linux下多个硬盘划分到同一挂载点问题

《linux下多个硬盘划分到同一挂载点问题》在Linux系统中,将多个硬盘划分到同一挂载点需要通过逻辑卷管理(LVM)来实现,首先,需要将物理存储设备(如硬盘分区)创建为物理卷,然后,将这些物理卷组成... 目录linux下多个硬盘划分到同一挂载点需要明确的几个概念硬盘插上默认的是非lvm总结Linux下多

golang内存对齐的项目实践

《golang内存对齐的项目实践》本文主要介绍了golang内存对齐的项目实践,内存对齐不仅有助于提高内存访问效率,还确保了与硬件接口的兼容性,是Go语言编程中不可忽视的重要优化手段,下面就来介绍一下... 目录一、结构体中的字段顺序与内存对齐二、内存对齐的原理与规则三、调整结构体字段顺序优化内存对齐四、内

SpringBoot中使用 ThreadLocal 进行多线程上下文管理及注意事项小结

《SpringBoot中使用ThreadLocal进行多线程上下文管理及注意事项小结》本文详细介绍了ThreadLocal的原理、使用场景和示例代码,并在SpringBoot中使用ThreadLo... 目录前言技术积累1.什么是 ThreadLocal2. ThreadLocal 的原理2.1 线程隔离2

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

linux进程D状态的解决思路分享

《linux进程D状态的解决思路分享》在Linux系统中,进程在内核模式下等待I/O完成时会进入不间断睡眠状态(D状态),这种状态下,进程无法通过普通方式被杀死,本文通过实验模拟了这种状态,并分析了如... 目录1. 问题描述2. 问题分析3. 实验模拟3.1 使用losetup创建一个卷作为pv的磁盘3.

Linux环境变量&&进程地址空间详解

《Linux环境变量&&进程地址空间详解》本文介绍了Linux环境变量、命令行参数、进程地址空间以及Linux内核进程调度队列的相关知识,环境变量是系统运行环境的参数,命令行参数用于传递给程序的参数,... 目录一、初步认识环境变量1.1常见的环境变量1.2环境变量的基本概念二、命令行参数2.1通过命令编程

Linux之进程状态&&进程优先级详解

《Linux之进程状态&&进程优先级详解》文章介绍了操作系统中进程的状态,包括运行状态、阻塞状态和挂起状态,并详细解释了Linux下进程的具体状态及其管理,此外,文章还讨论了进程的优先级、查看和修改进... 目录一、操作系统的进程状态1.1运行状态1.2阻塞状态1.3挂起二、linux下具体的状态三、进程的

Linux编译器--gcc/g++使用方式

《Linux编译器--gcc/g++使用方式》文章主要介绍了C/C++程序的编译过程,包括预编译、编译、汇编和链接四个阶段,并详细解释了每个阶段的作用和具体操作,同时,还介绍了调试和发布版本的概念... 目录一、预编译指令1.1预处理功能1.2指令1.3问题扩展二、编译(生成汇编)三、汇编(生成二进制机器语