当前位置: 首页 > news >正文

中移(苏州)软件技术有限公司面试问题与解答(2)—— Linux内核内存初始化的完整流程1

接前一篇文章:中移(苏州)软件技术有限公司面试问题与解答(1)—— 可信计算国密标准

本文参考以下文章:

启动期间的内存管理之初始化过程概述----Linux内存管理(九)

Linux初始化

特此致谢!

本文对于中移(苏州)软件技术有限公司面试问题中的“(8)Linux内核内存初始化的完整流程。”进行解答与解析。

实际上早有此心,把Linux内核尤其是进程管理、内存管理和文件系统的代码都筛一遍。但是一直由于种种原因没有花大力气真正干。正好借着这个机会,开始做这个事情。先从面试中问到的内存管理开始。

1. Linux系统启动过程中的内存初始化概述

在Linux系统初始化过程中,必须建立内存管理的数据结构以及很多事务。因为Linux内核在内存管理完全初始化之前就需要使用内存。在系统启动期间,使用了额外的简化的内存管理模块。随后在初始化完成后,将旧的模块丢弃掉。

可以把Linux内核的内存管理分三个阶段:

阶段起点终点过程描述
第一阶段系统启动bootmem或者memblock初始化完成前此阶段只能使用memblock_reserve函数分配内存,早期内核中使用init_bootmem_done=1标识此阶段结束
第二阶段bootmem或者memblock初始化完成buddy初始化完成前引导内存分配器bootmem或者memblock接受内存的管理工作,早期内核中使用mem_init_done=1标记此阶段的结束
第三阶段buddy初始化完成系统停止运行可以用cache和buddy分配内存

2. start_kernel函数中的内存管理相关内容

首先我们来看看start_kernel()是如何初始化系统的。start_kerne函数在init/main.c中,代码如下(笔者使用的内核源码版本为6.7,在这个时间点上是比较新的版本):

asmlinkage __visible __init __no_sanitize_address __noreturn __no_stack_protector
void start_kernel(void)
{char *command_line;char *after_dashes;set_task_stack_end_magic(&init_task);smp_setup_processor_id();debug_objects_early_init();init_vmlinux_build_id();cgroup_init_early();local_irq_disable();early_boot_irqs_disabled = true;/** Interrupts are still disabled. Do necessary setups, then* enable them.*/boot_cpu_init();page_address_init();pr_notice("%s", linux_banner);early_security_init();setup_arch(&command_line);setup_boot_config();setup_command_line(command_line);setup_nr_cpu_ids();setup_per_cpu_areas();smp_prepare_boot_cpu();	/* arch-specific boot-cpu hooks */boot_cpu_hotplug_init();pr_notice("Kernel command line: %s\n", saved_command_line);/* parameters may set static keys */jump_label_init();parse_early_param();after_dashes = parse_args("Booting kernel",static_command_line, __start___param,__stop___param - __start___param,-1, -1, NULL, &unknown_bootoption);print_unknown_bootoptions();if (!IS_ERR_OR_NULL(after_dashes))parse_args("Setting init args", after_dashes, NULL, 0, -1, -1,NULL, set_init_arg);if (extra_init_args)parse_args("Setting extra init args", extra_init_args,NULL, 0, -1, -1, NULL, set_init_arg);/* Architectural and non-timekeeping rng init, before allocator init */random_init_early(command_line);/** These use large bootmem allocations and must precede* initalization of page allocator*/setup_log_buf(0);vfs_caches_init_early();sort_main_extable();trap_init();mm_core_init();poking_init();ftrace_init();/* trace_printk can be enabled here */early_trace_init();/** Set up the scheduler prior starting any interrupts (such as the* timer interrupt). Full topology setup happens at smp_init()* time - but meanwhile we still have a functioning scheduler.*/sched_init();if (WARN(!irqs_disabled(),"Interrupts were enabled *very* early, fixing it\n"))local_irq_disable();radix_tree_init();maple_tree_init();/** Set up housekeeping before setting up workqueues to allow the unbound* workqueue to take non-housekeeping into account.*/housekeeping_init();/** Allow workqueue creation and work item queueing/cancelling* early.  Work item execution depends on kthreads and starts after* workqueue_init().*/workqueue_init_early();rcu_init();/* Trace events are available after this */trace_init();if (initcall_debug)initcall_debug_enable();context_tracking_init();/* init some links before init_ISA_irqs() */early_irq_init();init_IRQ();tick_init();rcu_init_nohz();init_timers();srcu_init();hrtimers_init();softirq_init();timekeeping_init();time_init();/* This must be after timekeeping is initialized */random_init();/* These make use of the fully initialized rng */kfence_init();boot_init_stack_canary();perf_event_init();profile_init();call_function_init();WARN(!irqs_disabled(), "Interrupts were enabled early\n");early_boot_irqs_disabled = false;local_irq_enable();kmem_cache_init_late();/** HACK ALERT! This is early. We're enabling the console before* we've done PCI setups etc, and console_init() must be aware of* this. But we do want output early, in case something goes wrong.*/console_init();if (panic_later)panic("Too many boot %s vars at `%s'", panic_later,panic_param);lockdep_init();/** Need to run this when irqs are enabled, because it wants* to self-test [hard/soft]-irqs on/off lock inversion bugs* too:*/locking_selftest();#ifdef CONFIG_BLK_DEV_INITRDif (initrd_start && !initrd_below_start_ok &&page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) {pr_crit("initrd overwritten (0x%08lx < 0x%08lx) - disabling it.\n",page_to_pfn(virt_to_page((void *)initrd_start)),min_low_pfn);initrd_start = 0;}
#endifsetup_per_cpu_pageset();numa_policy_init();acpi_early_init();if (late_time_init)late_time_init();sched_clock_init();calibrate_delay();arch_cpu_finalize_init();pid_idr_init();anon_vma_init();
#ifdef CONFIG_X86if (efi_enabled(EFI_RUNTIME_SERVICES))efi_enter_virtual_mode();
#endifthread_stack_cache_init();cred_init();fork_init();proc_caches_init();uts_ns_init();key_init();security_init();dbg_late_init();net_ns_init();vfs_caches_init();pagecache_init();signals_init();seq_file_init();proc_root_init();nsfs_init();cpuset_init();cgroup_init();taskstats_init_early();delayacct_init();acpi_subsystem_init();arch_post_acpi_subsys_init();kcsan_init();/* Do the rest non-__init'ed, we're now alive */arch_call_rest_init();/** Avoid stack canaries in callers of boot_init_stack_canary for gcc-10* and older.*/
#if !__has_attribute(__no_stack_protector__)prevent_tail_call_optimization();
#endif
}

可以看到,start_kernel函数代码很长,有200行。在此只截取出其中与内存管理初始化相关的部分,如下所示:

asmlinkage __visible __init __no_sanitize_address __noreturn __no_stack_protector
void start_kernel(void)
{……setup_arch(&command_line);……setup_per_cpu_areas();……mm_core_init();……kmem_cache_init_late();……setup_per_cpu_pageset();numa_policy_init();……anon_vma_init();……pagecache_init();……/* Do the rest non-__init'ed, we're now alive */arch_call_rest_init();
}
函数功能备注

page_address_init

初始化内核用于查找物理页面地址的数据结构
setup_arch是一个特定于体系结构的设置函数,其中的一项任务是负责初始化自举分配器
setup_per_cpu_areas给每个CPU分配内存,并拷贝.data.percpu段的数据
build_all_zonelists建立并初始化结点和内存域的数据结构已移至mm_core_init函数中
mm_core_init建立了内核的内存分配器。其中通过mem_init函数停用bootmem分配器并迁移到实际的内存管理器(比如伙伴系统),
然后调用kmem_cache_init函数初始化内核内部用于小块内存区的分配器
kmem_cache_init_late在kmem_cache_init函数之后,完善分配器的缓存机制,当前3个可用的内核内存分配器slab、slob、slub都会定义此函数

kmemleak_init

提供了一种可选的内核泄漏检测,其方法类似于跟踪内存收集器。当独立的对象没有被释放时,其报告记录在/sys/kernel/debug/kmemleak中,kmemcheck()能够帮助定位大多数内存错误的上下文已移至mm_core_init函数中
setup_per_cpu_pageset初始化CPU高速缓存行,为pagesets的第一个数组元素分配内存,换句话说,其实就是第一个系统处理器分配
numa_policy_init初始化NUMA策略
anon_vma_init匿名虚拟内存域初始化,创建anon_vma的slab缓存
pagecache_init页高速缓存的初始化
arch_call_rest_init用于在系统引导时调用平台特定的初始化函数

3. 内存初始化过程概述

在操作系统初始化的初期,操作系统只是获取到了内存的基本信息,内存管理的数据结构都没有建立。而这些数据结构创建的过程本身就是一个内存分配的过程。那么问题就来了:内存管理数据结构需要分配到相应的内存,才能完成做后续工作;但是它所做的工作本身就是为了内存能够分配。此时还没有一个内存管理器去负责分配和回收内存,而又不可能将所有的内存信息都静态地创建并初始化,那么怎么分配内存管理器所需要的内存呢?这就是一个典型的“鸡生蛋、蛋生鸡”的问题。不过甭管是先有鸡还是先有蛋,总归要先有二者之一,才能有后续的循环。

类比于鸡和蛋问题,我们先要实现一个满足要求的但是可能效率不高的笨家伙(内存管理器),用它来负责系统初始化初期的内存管理,最重要地,用它来初始化我们内存的数据结构,直到我们真正的内存管理器被初始化完成并能投入使用。之后就可以将旧的内存管理器丢掉。

因此在系统启动过程期间,内核使用了一个额外的简化形式的内存管理模块早期的引导内存分配器(boot memory allocator–bootmem分配器)或者memblock,用于在启动阶段早期分配内存。而在系统初始化完成后,该分配器被内核抛弃,然后初始化了一套新的更加完善的内存分配器。

系统启动

       |    ----  第一阶段

bootmem或者memblock初始化完成

       |    ----  第二阶段

伙伴系统以及slab cache初始化完成

       |    ----  第三阶段

系统终止运行

从下一回开始对start_kernel()中的内存管理相关函数进行详细解析。

相关文章:

中移(苏州)软件技术有限公司面试问题与解答(2)—— Linux内核内存初始化的完整流程1

接前一篇文章&#xff1a;中移&#xff08;苏州&#xff09;软件技术有限公司面试问题与解答&#xff08;1&#xff09;—— 可信计算国密标准 本文参考以下文章&#xff1a; 启动期间的内存管理之初始化过程概述----Linux内存管理(九) Linux初始化 特此致谢&#xff01; 本…...

蓝桥杯、编程考级、NOC、全国青少年信息素养大赛—scratch列表考点

1、小小情报员&#xff08;202309scratch四级24题&#xff09; 1.准备工作 &#xff08;1&#xff09;选择背景 Colorful City&#xff1b; &#xff08;2&#xff09;保留角色小猫&#xff0c;选择角色Ballerina。 2.功能实现 &#xff08;1&#xff09;角色小猫初始位置…...

1.23 力扣图论

841. 钥匙和房间 有 n 个房间&#xff0c;房间按从 0 到 n - 1 编号。最初&#xff0c;除 0 号房间外的其余所有房间都被锁住。你的目标是进入所有的房间。然而&#xff0c;你不能在没有获得钥匙的时候进入锁住的房间。 当你进入一个房间&#xff0c;你可能会在里面找到一套不…...

Vue学习笔记9--vuex(专门在Vue中实现集中式状态(数据)管理的一个Vue插件)

一、vuex是什么&#xff1f; 概念&#xff1a;专门在Vue中实现集中式状态&#xff08;数据&#xff09;管理的一个Vue插件&#xff0c;对vue应用中多个组件的共享状态进行集中式的管理&#xff08;读/写&#xff09;&#xff0c;也是一种组件间通信的方式&#xff0c;且适用于…...

Operation

contents 服务器一、相关概念1.1 云服务器与实例1.2 关于域名解析延时与80端口1.3 关于备案1.4 关于SSL证书1.5 关于SSL证书的签发1.6 关于SSL证书的部署1.7 关于LNMP和LAMP1.8 关于bt面板 二、单服务器单一级域名多网站2.1 创建多个二级域名2.2 解析二级域名绑定到服务器上2.3…...

Kong关键概念 - 服务(Services)

服务&#xff08;Services&#xff09; 在Kong Gateway中&#xff0c;服务是代表外部上游&#xff08;upstream&#xff09;API或微服务的实体。例如&#xff0c;数据转换微服务、计费API等。 服务的主要属性是其URL。您可以使用一个字符串来指定URL&#xff0c;或者通过分别…...

IDEA更改页面不重启

IDEA更改页面不重启 idea若依 修改包名 idea 1、修改IDEA设置 File -> Settings -> Build Execution Deployment -> Build Project automatically 勾选2、勾选Running Ctrl Shift Alt / 然后选择 Registry&#xff0c;勾上 Compiler.autoMake.allow.when.app.runn…...

golang学习-channel管道

1、定义 管道是golang语言提供的goroutine间的通讯方式&#xff0c;channel可以让一个goroutine发送特定的值给另一个goroutine的通讯机制。 管道是引用类型。 golang语言中channel是一种特殊的类型。像一个队列一样&#xff0c;先进先出。 var 变量 chan 元素类型 var ch1 …...

oracle 12 查询数据库锁

在Oracle 12c中&#xff0c;查询数据库锁信息可以通过以下视图进行&#xff1a; v$locked_object&#xff1a;这个视图显示了当前被锁定的对象&#xff08;如表、行等&#xff09;的信息。 SELECT l.session_id sid, s.serial#, l.locked_mode,o.object_name,s.osuser,s.userna…...

【LeetCode-135】分发糖果(贪心)

LeetCode135.分发糖果 题目描述 老师想给孩子们分发糖果&#xff0c;有 N 个孩子站成了一条直线&#xff0c;老师会根据每个孩子的表现&#xff0c;预先给他们评分。 你需要按照以下要求&#xff0c;帮助老师给这些孩子分发糖果&#xff1a; 每个孩子至少分配到 1 个糖果。…...

5G_射频测试_发射机测量(四)

6.2 Base station output power 用于测量载波发射功率的大小&#xff0c;功率越大小区半径越大但是杂散也会越大 载波功率&#xff08;用频谱仪测&#xff09;天线口功率&#xff08;用功率计测&#xff09;载波功率是以RBW为单位的filter测量的积分功率不同带宽的多载波测试时…...

MySQL经典50题

目录 一、数据表介绍 二、练习题 1. 查询" 01 "课程比" 02 "课程成绩高的学生的信息及课程分数 2. 查询同时存在" 01 "课程和" 02 "课程的情况 3. 查询存在" 01 "课程但可能不存在" 02 "课程的情况…...

常用的Qt开源库分享

1. Qwt (https://qwt.sf.net): Qwt是一个基于Qt的数据可视化库&#xff0c;提供了绘制曲线、图表、仪表盘等功能。 2. QJson (https://qjson.sourceforge.net): QJson是一个用于JSON数据解析和生成的库&#xff0c;使Qt应用程序能够方便地处理JSON格式的数据。 3. QCustomP…...

Unity开发授权系统

Unity开发授权系统 引子 因为有些客户尾款到账不及时&#xff0c;因此研究了一套授权系统&#xff0c;当授权到期后&#xff0c;系统就提示软件授权已到期&#xff0c;不能继续使用云云&#xff0c;这样方便尾款的收回。 大体需求就是 时间相关性&#xff0c;可以自由设置授…...

一周时间,开发了一款封面图生成工具

介绍 这是一款封面图的制作工具&#xff0c;根据简单的配置即可生成一张好看的封面图&#xff0c;目前已有七款主题可以选择。做这个工具的初衷来自平时写文章&#xff0c;都为封面图发愁&#xff0c;去图片 网站上搜索很难找到满意的&#xff0c;而且当你要的图如果要搭配上文…...

【.NET Core】深入理解异步编程模型(APM)

【.NET Core】深入理解异步编程模型&#xff08;APM&#xff09; 文章目录 【.NET Core】深入理解异步编程模型&#xff08;APM&#xff09;一、APM概述二、IAsyncResult接口2.1 BeginInvoke2.2 EndInvoke2.3 IAsyncResult属性2.4 IAsyncResult异步演示 三、通过结束异步操作来…...

pyqtgraph绘图类

pyqtgraph绘图类 pyqtgraph绘图有四种方法: 方法描述pyqtgraph.plot()创建一个新的QWindow用来绘制数据PlotWidget.plot()在已存在的QWidget上绘制数据PlotItem.plot()在已存在的QWidget上绘制数据GraphicsLayout.addPlot()在网格布局中添加一个绘图 上面四个方法都接收同样…...

C#6-10新增的内容

目录 异常筛选器 属性语法 表达式主体定义 Null 条件运算符 ?. 和 ?[] 使用 $ 的字符串内插 nameof 表达式 元组类型 模糊匹配 本地函数 Expression-bodied 成员 Reference 变量 ?、??和??= .. 模式匹配功能(C# 9) Record init c#8.NET Framework 4.8…...

【立创EDA-PCB设计基础】3.网络表概念解读+板框绘制

前言&#xff1a;本文对网络表概念解读板框绘制&#xff08;确定PCB板子轮廓&#xff09; 网络表概念解读 在本专栏的上一篇文章【嘉立创EDA-PCB设计指南】2&#xff0c;将设计的原理图转为了PCB&#xff0c;在PCB界面下出现了所有的封装&#xff0c;以及所有的飞线属性&…...

在Python环境中运行R语言的配环境实用教程

前情提要 在做一些生物信息与医学统计的工作&#xff0c;本来偷懒希望只靠python完成的&#xff0c;结果还是需要用R语言&#xff0c;倒腾了一会儿&#xff0c;调成功了&#xff0c;就记录一下这个过程。 我的环境&#xff1a; win10, pycharm, R-4.3.2 首先&#xff0c;我们…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

UE5 学习系列(三)创建和移动物体

这篇博客是该系列的第三篇&#xff0c;是在之前两篇博客的基础上展开&#xff0c;主要介绍如何在操作界面中创建和拖动物体&#xff0c;这篇博客跟随的视频链接如下&#xff1a; B 站视频&#xff1a;s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

【JVM】Java虚拟机(二)——垃圾回收

目录 一、如何判断对象可以回收 &#xff08;一&#xff09;引用计数法 &#xff08;二&#xff09;可达性分析算法 二、垃圾回收算法 &#xff08;一&#xff09;标记清除 &#xff08;二&#xff09;标记整理 &#xff08;三&#xff09;复制 &#xff08;四&#xff…...

Linux系统部署KES

1、安装准备 1.版本说明V008R006C009B0014 V008&#xff1a;是version产品的大版本。 R006&#xff1a;是release产品特性版本。 C009&#xff1a;是通用版 B0014&#xff1a;是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存&#xff1a;1GB 以上 硬盘&#xf…...

前端高频面试题2:浏览器/计算机网络

本专栏相关链接 前端高频面试题1&#xff1a;HTML/CSS 前端高频面试题2&#xff1a;浏览器/计算机网络 前端高频面试题3&#xff1a;JavaScript 1.什么是强缓存、协商缓存&#xff1f; 强缓存&#xff1a; 当浏览器请求资源时&#xff0c;首先检查本地缓存是否命中。如果命…...

2025年低延迟业务DDoS防护全攻略:高可用架构与实战方案

一、延迟敏感行业面临的DDoS攻击新挑战 2025年&#xff0c;金融交易、实时竞技游戏、工业物联网等低延迟业务成为DDoS攻击的首要目标。攻击呈现三大特征&#xff1a; AI驱动的自适应攻击&#xff1a;攻击流量模拟真实用户行为&#xff0c;差异率低至0.5%&#xff0c;传统规则引…...

P10909 [蓝桥杯 2024 国 B] 立定跳远

# P10909 [蓝桥杯 2024 国 B] 立定跳远 ## 题目描述 在运动会上&#xff0c;小明从数轴的原点开始向正方向立定跳远。项目设置了 $n$ 个检查点 $a_1, a_2, \cdots , a_n$ 且 $a_i \ge a_{i−1} > 0$。小明必须先后跳跃到每个检查点上且只能跳跃到检查点上。同时&#xff0…...

Web APIS Day01

1.声明变量const优先 那为什么一开始前面就不能用const呢&#xff0c;接下来看几个例子&#xff1a; 下面这张为什么可以用const呢&#xff1f;因为复杂数据的引用地址没变&#xff0c;数组还是数组&#xff0c;只是添加了个元素&#xff0c;本质没变&#xff0c;所以可以用con…...

2025年全国I卷数学压轴题解答

第19题第3问: b b b 使得存在 t t t, 对于任意的 x x x, 5 cos ⁡ x − cos ⁡ ( 5 x t ) < b 5\cos x-\cos(5xt)<b 5cosx−cos(5xt)<b, 求 b b b 的最小值. 解: b b b 的最小值 b m i n min ⁡ t max ⁡ x g ( x , t ) b_{min}\min_{t} \max_{x} g(x,t) bmi…...