吉游网提供最新游戏下载和手游攻略!

Linux内存初始化过程详解

发布时间:2024-10-21浏览:76

大家好,今天来为大家分享Linux内存初始化过程详解的一些知识点,和的问题解析,大家要是都明白,那么可以忽略,如果不太清楚的话可以看看本篇文章,相信很大概率可以解决您的问题,接下来我们就一起来看看吧!

这篇文章我们先来看下linux在启动过程中的初始化。

创建启动页表:

在汇编代码阶段的head.S文件中,负责创建映射关系的函数是create_page_tables。create_page_tables函数负责identity mapping和kernel image mapping。

  • identity map:是指把idmap_text区域的物理地址映射到相等的虚拟地址上,这种映射完成后,其虚拟地址等于物理地址。idmap_text区域都是一些打开MMU相关的代码。
  • kernel image map:将kernel运行需要的地址(kernel txt、rodata、data、bss等等)进行映射。
arch/arm64/kernel/head.S:ENTRY(stext) bl preserve_boot_args bl el2_setup // Drop to EL1, w0=cpu_boot_mode adrp x23, __PHYS_OFFSET and x23, x23, MIN_KIMG_ALIGN - 1 // KASLR offset, defaults to 0 bl set_cpu_boot_mode_flag bl __create_page_tables /* * The following calls CPU setup code, see arch/arm64/mm/proc.S for * details. * On return, the CPU will be ready for the MMU to be turned on and * the TCR will have been set. */ bl __cpu_setup // initialise processor b __primary_switchENDPROC(stext)

__create_page_tables主要执行的就是identity map和kernel image map:

__create_page_tables:...... create_pgd_entry x0, x3, x5, x6 mov x5, x3 // __pa(__idmap_text_start) adr_l x6, __idmap_text_end // __pa(__idmap_text_end) create_block_map x0, x7, x3, x5, x6 /* * Map the kernel image (starting with PHYS_OFFSET). */ adrp x0, swapper_pg_dir mov_q x5, KIMAGE_VADDR + TEXT_OFFSET // compile time __va(_text) add x5, x5, x23 // add KASLR displacement create_pgd_entry x0, x5, x3, x6 adrp x6, _end // runtime __pa(_end) adrp x3, _text // runtime __pa(_text) sub x6, x6, x3 // _end - _text add x6, x6, x5 // runtime __va(_end) create_block_map x0, x7, x3, x5, x6 ......

其中调用create_pgd_entry进行PGD及所有中间level(PUD, PMD)页表的创建,调用create_block_map进行PTE页表的映射。关于四级页表的关系如下图所示,这里就不进一步解释了。

汇编结束后的内存映射关系如下图所示:

当执行完上面的map之后,MMU就已经打开了并且开始进入C代码运行阶段,那么下一步就要对dtb进行映射了。

fixmap区之dtb map:

在执行setup_arch中,会最先进行early_fixmap_init(),这个函数就是用来map dtb的,但是它只会建立dtb对应的这段物理地址中间level的页表entry,而最后一个level的页表映射则通过setup_machine_fdt函数里的fixmap_remap_fdt来创建。

void *__init fixmap_remap_fdt(phys_addr_t dt_phys){ void *dt_virt; int size; dt_virt = __fixmap_remap_fdt(dt_phys, &size, PAGE_KERNEL_RO); if (!dt_virt) return NULL; memblock_reserve(dt_phys, size); return dt_virt; }

fixmap_remap_fdt主要是为fdt建立地址映射,在该函数的最后,顺便就调用memblock_reserve保留了该段内存。

可以看出dtb的映射采用的是fixmap,所谓fixmap就是固定映射,它需要我们明确的知道想要映射的物理地址,并把这段地址映射到想要映射的虚拟地址上。当然这里固定映射还有些片面,因为在fixmap机制实现上,也有支持动态分配虚拟地址的功能,这个功能主要用于临时fixmap映射(这个临时映射就是用来执行early ioremap使用的。),而dtb的映射属于永久映射。

fixmap区之early ioremap:

对于一些硬件需要在内存管理系统起来之前就要工作的,我们就可以使用这种机制来映射内存给这些硬件driver使用。各个模块在使用完early ioremap的地址后,需要尽快把这段映射的虚拟地址释放掉,这样才能反复被其他模块继续申请使用。

early_ioremap_init会调用early_ioremap_setup:

可见它的实现是依赖fixmap的,所以它必须要在early_fixmap_init之后才能运行。

注意:如果想要在伙伴系统初始化之前进行设备寄存器的访问,那么可以考虑early IO remap机制。

至此我们已经知道dtb和early ioremap都是在fixmap区的,如下图:

系统内存的布局:

完成dtb的map之后,内核可以访问这一段的内存了,通过解析dtb中的内容,内核可以勾勒出整个内存布局的情况,为后续内存管理初始化奠定基础。这一步主要在setup_machine_fdt中完成。这里就不看代码了,其调用流程是:setup_machine_fdt->early_init_dt_scan->early_init_dt_scan_nodes

就像注释中所示内核根据dtb的不同node勾勒出choosen node,root node,memory node相应内存区域。

除了这3个node,还有一个reserved-memory node,它是在上面讲到dtb map的时候fixmap_remap_fdt函数做的。下面我们看下这4个node的具体实现。

  • choosen node

该节点有一个bootargs属性,该属性定义了内核的启动参数,比如mem= xx,此外,还处理initrd相关的property,并保存在initrd_start和initrd_end这两个全局变量中。

  • root node

与内存无关,暂时不详述,以后有机会讲到device tree系列再详述。

  • memory node

通过memblock_add加入到memblock.memory对应的memblock_type链表中进行管理。

接下来到arm64_memblock_init函数:

用户评论

逃避

这篇文章介绍的Linux内核内存初始化非常详细!从物理内存到虚拟内存,各个阶段都解释得很清晰,我以前对这个过程没懂 lắm,现在终于弄明白了!

    有5位网友表示赞同!

我怕疼别碰我伤口

说实话,我对这些低级细节不太感兴趣,不过这篇博文写得真好,让我感觉阅读起来一点都不枯燥。如果能加入一些例子和具体应用场景,就更好了!

    有5位网友表示赞同!

西瓜贩子

之前一直用Windows系统,最近才接触Linux,发现这个内存初始化流程真的很有趣。希望后续的文章能讲解一些其他Linux内核的细节,比如调度算法之类的!

    有16位网友表示赞同!

伪心

对于新手来说,这篇关于Linux内存初始化的文章非常有帮助! 详细地解释了每个步骤,还包括了相应的图示,很容易理解。强烈推荐给所有想了解Linux底层的同学。

    有12位网友表示赞同!

半梦半醒半疯癫

这篇文章虽然讲解得很细致,但还是觉得有点过于抽象。如果能用一些实际的代码案例来进行说明,就更生动易懂了!

    有20位网友表示赞同!

采姑娘的小蘑菇

终于找到了能够解释Linux内存初始化的文章!之前查阅了很多资料都没有找到很好的解答。这篇博文终于解开了我的疑惑,感谢作者!

    有11位网友表示赞同!

抚笙

内存管理是Linux系统稳定运行的关键环节,这篇博文的讲解很有价值。 虽然内容比较专业,但我还是花了时间认真阅读,从中学到了很多知识。

    有13位网友表示赞同!

早不爱了

这篇文章确实写得不错,尤其是对Linux内核的架构和工作原理的解释很到位。 但希望作者能加入一些更具体的例子, 帮助读者更加深刻地理解内存初始化过程。

    有14位网友表示赞同!

不浪漫罪名

对于已经熟悉Linux系统的人来说,这篇博文可能有点基础,但对于新手来说无疑是一份宝贵的资源!强烈推荐给所有想深入学习Linux内核的同学。

    有8位网友表示赞同!

孤独症

感觉这篇文章过于注重理论层面了,而缺少一些实际应用场景的介绍。 如果能结合一些具体的案例来讲解内存初始化的流程和作用,效果会更好。

    有10位网友表示赞同!

青瓷清茶倾城歌

这篇博文虽然很详细,但我觉得还是有点过于罗嗦了。 希望能更加简洁地表达概念,突出重点内容。

    有15位网友表示赞同!

_心抽搐到严重畸形っ°

我一直对Linux内存管理机制很有兴趣,这篇博文的讲解让我更深入地了解到了这个重要的系统级功能。感谢作者的分享!

    有11位网友表示赞同!

盲从于你

这篇文章介绍的Linux内存初始化过程令人印象深刻! 从内核加载到虚拟内存分配,每个步骤都说得清清楚楚。我终于明白了为什么有时候我的电脑运行会比较慢!

    有15位网友表示赞同!

喜欢梅西

我觉得这篇文章写的很有条理,逻辑清晰易懂。 但有些地方用的专业词汇太多,对于初学者来说可能理解起来比较难度。

    有11位网友表示赞同!

迁心

这篇博文让我对Linux系统内部运作有了更深入的了解,真是太棒了!希望作者能继续分享更多关于内核细节的文章!

    有15位网友表示赞同!

浮殇年华

虽然我是一个程序员,但我还是从这篇博文中学到了很多新的知识。 例如之前从未想过内存初始化的步骤会这么多,这让我对硬件和软件之间的关系有了更深入的理解。

    有16位网友表示赞同!

北染陌人

文章写的非常详细,涵盖了linux内存初始化过程的所有关键点。 但是我个人觉得,图解可以丰富一些的内容,使信息更直观易懂

    有15位网友表示赞同!

↘▂_倥絔

感谢作者分享这篇关于 Linux 内存初始化的文章,它帮助我更好地理解了Linux系统的工作原理!希望以后能看到更多这样高质量的博客文章。

    有12位网友表示赞同!

热点资讯