Linux驱动开发 内核的启动过程_内核启动流程

**__lookup_processor_type:**读取出硬件的CPU ID号,进行合法性检验,合法则继续启动,不合法则停止启动,转向__error_p启动失败。

__lookup_machine_type:本函数校验的是机器码

**__vet_atags:**用来校验uboot通过tag给内核传的参数(上篇uboot如何启动内核有介绍tag传参)

**__create_page_tables:**建立页表,linux内核本身被连接在虚拟地址处,因此kernel希望尽快建立页表并且启动MMU进入虚拟地址工作状态。

__switch_data

__switch_data部分是个函数指针数组,下一步执行__mmap_switched函数,复制数据段、清除bss段,保存起来cpu id号、机器码、tag传参的首地址,b start_kernel跳转到C语言运行阶段。

3.内核启动C语言阶段

内核启动文件main.c

(1)一些初始化代码

smp_setup_processor_id:smp就是对称多处理器,是建立smp。
lockdep_init:锁定依赖,是一个内核调试模块,处理内核自旋锁死锁问题相关的。
boot_init_stack_canary:用来防止栈溢出。
cgroup_init_early:control group,内核提供的一种来处理进程组的技术。
local_irq_disable:屏蔽当前CPU上的所有中断。
early_boot_irqs_off:通过该标记可以让我们知道是否在early bootup code。
early_init_irq_lock_class:设置所有IRQ描述符的锁是统一的锁还是各有各的小锁。
lock_kernel:获得大内核锁,该锁可以用来锁定整个内核。
tick_init:初始化tick控制功能,注册clockevents的框架。
boot_cpu_init:设置第一个CPU核为活跃CPU核。若系统为单CPU核系统,则设置仅有的CPU为活跃CPU核。
page_address_init:函数初始化高端内存页表池的链表。

(2)打印内核版本信息

kernel/init/main.c中的572行,printk函数是内核中用来从console打印信息的,类似于应用层编程中的printf。

为了解决打印信息过多,无效信息会淹没有效信息这个问题,**linux内核的解决方案是给每一个printk添加一个打印级别,**级别定义0-7。

(3)setup_arch函数

实际上这个函数是用来确定我们当前内核的机器(arch、machine)的,之前说过的机器码就是给这个硬件平台一个固定的编码,以表征这个平台,当前使用的平台:CPU:S5PV210开发板:X210。

**setup_arch函数->setup_processor函数:**用来查找CPU信息,通过read_cpuid_id函数,对硬件进行查找,从而确定CPI的ID。

setup_arch函数->setup_machine函数:传参是机器码编号

该函数的工作原理:内核在建立的时候就把各种CPU架构的信息组织成一个一个的machine_desc结构体实例,然后都给一个段属性.arch.info.init,链接的时候会保证这些描述符会被连接在一起。__lookup_machine_type就去那个那些描述符所在处依次挨个遍历各个描述符,比对看机器码哪个相同。

**setup_arch函数进行了基本的cmdline处理:**cmdline就是指的uboot给kernel传参时传递的命令行启动参数,也就是uboot的bootargs。

内核中维护了一个默认的cmdline,uboot还可以通过tag给kernel再传递一个cmdline。如果uboot给内核传cmdline成功则内核会优先使用uboot传递的这一个;如果uboot没有给内核传cmdline或者传参失败,则内核会使用自己默认的这个cmdline

4.rest_init

(1)rest_init中调用kernel_thread函数启动了2个内核线程,分别是:kernel_init和kthreadd
(2)调用schedule函数开启了内核的调度系统,从此linux系统开始转起来了。
(3)rest_init最终调用cpu_idle函数结束了整个内核的启动。也就是说linux内核最终结束了一个函数cpu_idle。这个函数里面肯定是死循环。
(4)简单来说,linux内核最终的状态是:有事干的时候去执行有意义的工作(执行各个进程任务),实在没活干的时候就去死循环(实际上死循环也可以看成是一个任务)。
(5)之前已经启动了内核调度系统,调度系统会负责考评系统中所有的进程,这些进程里面只有有哪个需要被运行,调度系统就会终止cpu_idle死循环进程(空闲进程)转而去执行有意义的干活的进程。这样操作系统就转起来了。

init进程原理:

(1)init进程刚开始运行的时候是内核态,然后他自己运行了一个用户态下面的程序后把自己强行转成了用户态。

(2)内核态下重点就是挂载根文件系统并试图找到用户态下的那个init程序。init进程要把自己转成用户态就必须运行一个用户态的应用程序(这个应用程序名字一般也叫init),挂载根文件系统,因为所有的应用程序都在文件系统中,然后才可以找到这个应用程序。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数嵌入式工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!

img

img

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以+V:Vip1104z获取!!! (备注:嵌入式)

img

最后

资料整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~

你的支持,我的动力;祝各位前程似锦,offer不断,步步高升!!!

44156ee24.jpg" alt=“img” style=“zoom: 67%;” />

最后

资料整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~

你的支持,我的动力;祝各位前程似锦,offer不断,步步高升!!!

更多资料点击此处获qu!!

  • 7
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值