linux内核4.1启动流程,正点原子linux内核启动流程学习笔记

1、Linux 内核入口 stext

在linux内核启动之前要求如下:

①、关闭 MMU。

②、关闭 D-cache。(数据缓存)

③、 I-Cache 无所谓。(指令缓存)

④、 r0=0。

⑤、 r1=machine nr(也就是机器 ID)。

⑥、 r2=atags 或者设备树(dtb)首地址

1.1 为什么需要关闭MMU和D-cache

1.1.1 cache的作用

cache 是高速缓冲存储器

cache是位于主存(即是内存)与CPU内部的寄存器之间的一个存储设施,用来加快cpu与内存之间

数据与指令的传输速率,从而加快处理的速度。

1.1.2 为什么要关闭D-Cache 而I-Cache无所谓

在设备上电之初,内存的初始化速度比cpu初始化慢,在内存没有准备好的情况下,就对内存进行数据读取,那么会造成数据读取异常.

至于为什么I-Cache无所谓.不知道

Volatile:

本质:是告诉编译器不要对我的代码进行优化,作用是让编写者感觉变量的变化情况。因为在优化时,会将常用的代码取出来放到Caches中,它没有从实际的物理地址去取,它直接从CPU的缓存中去取,但常用的代码就是为了检测一些常用变量的变化,如果正在取数据的时候发生跳变,那么就检测不到变量的变化了,所以在这种情况下要用Volatile关键字告诉编译器不要做优化,让cpu每次都从实际的物理地址中去取指令。其实这也是为什么要关闭数据缓存的原因,如果汇编指令读取的时候缓存中的数据,而实际物理地址的数据发生了变化,将导致cpu读取不到真实的最新的值。然而在C语言中是不会关闭Caches的,如果编写者要检测外界物理数据的变化,或变化太快,从Caches中取数据会有误差,就加一个关键字Volatile。

1.2.1 MMU

mmu可以实现虚拟内存和内存保护等功能,完成对内存的操作和管理。

1、没有对MMU进行初始化,且用不到mmu为了避免影响启动时的初始化,先关闭MMU

2 linux内核启动步骤

2.1

safe_svcmode_maskall 确保CPU处于SVC模式,并且关闭所有中断

读取处理器ID

__lookup_processor_type 检查当前系统是否支持此CPU,支持则获取procinfo信息

struct proc_info_list {

unsigned int cpu_val;

unsigned int cpu_mask;

unsigned long __cpu_mm_mmu_flags; /* used by head.S /

unsigned long __cpu_io_mmu_flags; / used by head.S /

unsigned long __cpu_flush; / used by head.S */

const char *arch_name;

const char *elf_name;

unsigned int elf_hwcap;

const char *cpu_name;

struct processor *proc;

struct cpu_tlb_fns *tlb;

struct cpu_user_fns *user;

struct cpu_cache_fns *cache;

};

Linux 内核将每种处理器都抽象为一个 proc_info_list 结构体,每种处理器都对应一个

procinfo。

__vet_atag 验证atags或则设备树(dtb是否有效

__create_page_tables 创建页表

__mmap_switched 的地址保存到 r13 寄存器中

start_kernel

/*

* Need to run as early as possible, to initialize the

* lockdep hash:

*/

lockdep_init();/* lockdep 是死锁检测模块,此函数会初始化 ,两个hash表。此函数要求尽可能的早执行*/

set_task_stack_end_magic(&init_task); /* 设置任务栈结束,用于栈溢出检测*/

smp_setup_processor_id();/* 跟 SMP 有关(多核处理器),设置处理器 ID */

debug_objects_early_init();/* 做一些和 debug 有关的初始化 */

/*

* Set up the the initial canary ASAP:

*/

boot_init_stack_canary();/* 栈溢出检测初始化 */

cgroup_init_early();/* cgroup 初始化, cgroup 用于控制 Linux 系统资源*/

local_irq_disable();/* 关闭当前 CPU 中断 */

early_boot_irqs_disabled = true;

/*

* Interrupts are still disabled. Do necessary setups, then

* enable them

*/

boot_cpu_init();/* 跟 CPU 有关的初始化 */

page_address_init();/* 页地址相关的初始化 */

pr_notice("%s", linux_banner); /* 打印 Linux 版本号、编译时间等信息 */

setup_arch(&command_line);/* 架构相关的初始化,此函数会解析传递进来的

* ATAGS 或者设备树(DTB)文件。会根据设备树里面

* 的 model 和 compatible 这两个属性值来查找

* Linux 是否支持这个单板。此函数也会获取设备树

* 中 chosen 节点下的 bootargs 属性值来得到命令

* 行参数,也就是 uboot 中的 bootargs 环境变量的

* 值,获取到的命令行参数会保存到

*command_line 中。

*/

mm_init_cpumask(&init_mm);

setup_command_line(command_line);

setup_nr_cpu_ids();/* 如果只是 SMP(多核 CPU)的话,此函数用于获取

* CPU 核心数量, CPU 数量保存在变量

* nr_cpu_ids 中。

*/

setup_per_cpu_areas(); /* 在 SMP 系统中有用,设置每个 CPU 的 per-cpu 数据 */

smp_prepare_boot_cpu();/* arch-specific boot-cpu hooks */

build_all_zonelists(NULL, NULL); /* 建立系统内存页区(zone)链表 */

page_alloc_init();/* 处理用于热插拔 CPU 的页 */

/* 打印命令行信息 */

pr_notice("Kernel command line: %s\n", boot_command_line);

parse_early_param();/* 解析命令行中的 console 参数 */

after_dashes = parse_args("Booting kernel",

static_command_line, __start___param,

__stop___param - __start___param,

-1, -1, &unknown_bootoption);

if (!IS_ERR_OR_NULL(after_dashes))

parse_args("Setting init args", after_dashes, NULL, 0, -1, -1,

set_init_arg);

jump_label_init();

/*

* These use large bootmem allocations and must precede

* kmem_cache_init()

*/

setup_log_buf(0);/* 设置 log 使用的缓冲区*/

pidhash_init();/* 构建 PID 哈希表, Linux 中每个进程都有一个 ID,

* 这个 ID 叫做 PID。通过构建哈希表可以快速搜索进程

* 信息结构体。

*/

vfs_caches_init_early();/* 预先初始化 vfs(虚拟文件系统)的目录项和

* 索引节点缓存

*/

sort_main_extable();/* 定义内核异常列表 */

trap_init();/* 完成对系统保留中断向量的初始化 */

mm_init();/* 内存管理初始化 */

sched_init();/* 初始化调度器,主要是初始化一些结构体 */

preempt_disable();/* 关闭优先级抢占 */

if (WARN(!irqs_disabled(),/* 检查中断是否关闭,如果没有的话就关闭中断 */

"Interrupts were enabled *very* early, fixing it\n"))

local_irq_disable();

idr_init_cache();/* IDR 初始化, IDR 是 Linux 内核的整数管理机

* 制,也就是将一个整数 ID 与一个指针关联起来。

*/

rcu_init();/* 初始化 RCU, RCU 全称为 Read Copy Update(读-拷贝修改) */

/* trace_printk() and trace points may be used after this */

trace_init();/* 跟踪调试相关初始化 */

context_tracking_init();

radix_tree_init();/* 基数树相关数据结构初始化 */

/* init some links before init_ISA_irqs() */

early_irq_init();/* 初始中断相关初始化,主要是注册 irq_desc 结构体变

* 量,因为 Linux 内核使用 irq_desc 来描述一个中断。

*/

init_IRQ();/* 中断初始化 */

tick_init();/* tick 初始化 */

rcu_init_nohz();

init_timers();/* 初始化定时器 */

hrtimers_init();/* 初始化高精度定时器 */

softirq_init();/* 软中断初始化 */

timekeeping_init();

time_init();/* 初始化系统时间 */

sched_clock_postinit();

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();/* slab 初始化, slab 是 Linux 内存分配器 */

/*

* 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();/* 初始化控制台,之前 printk 打印的信息都存放

* 缓冲区中,并没有打印出来。只有调用此函数

* 初始化控制台以后才能在控制台上打印信息。

*/

if (panic_later)

panic("Too many boot %s vars at `%s'", panic_later,

panic_param);

lockdep_info(); /* 如果定义了宏 CONFIG_LOCKDEP,那么此函数打印一些信息。 */

/*

* 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_INITRD

if (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;

}

#endif

page_ext_init();

debug_objects_mem_init();

kmemleak_init();/* kmemleak 初始化, kmemleak 用于检查内存泄漏 */

setup_per_cpu_pageset();

numa_policy_init();

if (late_time_init)

late_time_init();

sched_clock_init();

calibrate_delay(); /* 测定 BogoMIPS 值,可以通过 BogoMIPS 来判断 CPU 的性能

* BogoMIPS 设置越大,说明 CPU 性能越好。

*/

pidmap_init();/* PID 位图初始化 */

anon_vma_init();/* 生成 anon_vma slab 缓存 */

acpi_early_init();

#ifdef CONFIG_X86

if (efi_enabled(EFI_RUNTIME_SERVICES))

efi_enter_virtual_mode();

#endif

#ifdef CONFIG_X86_ESPFIX64

/* Should be run before the first non-init thread is created */

init_espfix_bsp();

#endif

thread_info_cache_init();

cred_init();/* 为对象的每个用于赋予资格(凭证) */

fork_init();/* 初始化一些结构体以使用 fork 函数 */

proc_caches_init();/* 给各种资源管理结构分配缓存 */

buffer_init();/* 初始化缓冲缓存 */

key_init();/* 初始化密钥 */

security_init();/* 安全相关初始化 */

dbg_late_init();

vfs_caches_init(totalram_pages);/* 为 VFS 创建缓存 */

signals_init();/* 初始化信号 */

/* rootfs populating might need page-writeback */

page_writeback_init();/* 页回写初始化 */

proc_root_init();/* 注册并挂载 proc 文件系统 */

nsfs_init();

cpuset_init();/* 初始化 cpuset, cpuset 是将 CPU 和内存资源以逻辑性

* 和层次性集成的一种机制,是 cgroup 使用的子系统之一

*/

cgroup_init();/* 初始化 cgroup */

taskstats_init_early();/* 进程状态初始化 */

delayacct_init();/* 检查写缓冲一致性 */

check_bugs();

acpi_subsystem_init();

sfi_init_late();

if (efi_enabled(EFI_RUNTIME_SERVICES)) {

efi_late_init();

efi_free_boot_services();

}

ftrace_init();

/* Do the rest non-__init'ed, we're now alive */

rest_init();/* rest_init 函数 */

rest_init();

static noinline void __init_refok rest_init(void)

{

int pid;

rcu_scheduler_starting();/* 启动 RCU 锁调度器 */

smpboot_thread_init();

/*

* We need to spawn init first so that it obtains pid 1, however

* the init task will end up wanting to create kthreads, which, if

* we schedule it before we create kthreadd, will OOPS.

*/

kernel_thread(kernel_init, NULL, CLONE_FS); /* 创建init 进程 PID =1 */

numa_default_policy();

pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);/* 创建 kthreadd 内核进程,此内核进程的 PID 为 2*/

rcu_read_lock();

kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);

rcu_read_unlock();

complete(&kthreadd_done);

/*

* The boot idle thread must execute schedule()

* at least once to get things moving:

*/

init_idle_bootup_task(current);

schedule_preempt_disabled();

/* Call into cpu_idle with preempt disabled */

cpu_startup_entry(CPUHP_ONLINE); /* 来进入 idle 进程 PID = 0*/

}

_enable_mmu 函 数 使 能 MMU

标签:__,初始化,init,CPU,early,正点,内核,linux,cpu

来源: https://blog.csdn.net/weixin_43471255/article/details/115643838

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值