【Xilinx】MPSOC启动流程(七)- Linux启动流程

此系列博客,仅对Xilinx平台PS端(ARM部分)开发做介绍,不对PL(FPGA)做过多介绍。

目录

一. 内核入口

1.1 链接脚本vmlinux.lds.S

​​​​​​​1.2 入口stext

​​​​​​​二. start_kernel函数

​​​​​​​三. rest_init

​​​​​​​四. init进程

​​​​​​​4.1 kernel_init_freeable


一. 内核入口​​​​​​​

此系列分析的Linux内核版本为5.x, 且为64位

1.1 链接脚本vmlinux.lds.S

链接脚本:告诉链接器如何把输入文件内的各个段(section)放到输出文件中,并控制输出文件中的各个段在此程序运行时的地址空间布局。一个程序由多个段组成,那么这些段是如何在文件中存放的(这些段的存放内容和存放段的地址),以及是如何加载到内存的相应位置进行执行。

       说明入口为stext, 定义在head.S中

​​​​​​​1.2 入口stext

Linux内核的入口点从stext中开始,在head.S中定义

  1. bl preserve_boot_args: 保存uboot传过来的参数,X0为设备树地址,将其保存在x21寄存中,存储x21,x1,x2,x3到X0地址,依次增加
  2. __create_page_tables:创建页表
  3. __cpu_setup:初始化CPU,为开启MMU做准备
  4. __primary_switch:开启MMU,跳转到__primary_switched,
  5. __primary_switch:跳转到start_kernel

​​​​​​​二. start_kernel函数

调用众多的子函数来完成 Linux 启动之前的一些初始化工作

 

                     674行:调用init_IRQ初始化GIC控制器的驱动

最终调用arch_call_rest_init:调用rest_init,在rest_init中创建kernel_init进程(也就是1号进程) 和 kthreadd进程(也就是2号进程),并执行(1号进程和2号进程)对应的处理函数

​​​​​​​三. rest_init

创建kernel_init进程(PID=1,也就是Linux内核init进程) 和 kthreadd进程(pid=2,负责所有内核进程的调度和管理)

cpu_startup_entry:进入idle进程,PID为0

​​​​​​​四. init进程

  1. ramdisk_execute_command 是一个全局的 char 指针变量,此变量值为“/init”,也就是根目录下的init程序,ramdisk_execute_command 也可以通过 uboot 传递,在 bootargs 中使用“rdinit=xxx”即可,xxx 为具体的 init 程序名字
  2. 存在ramdisk_execute_command,调用run_list_process执行init进程
  3. 如果 ramdisk_execute_command 为空的话就看 execute_command 是否为空,反正不管如何一定要在根文件系统中找到一个可运行的 init 程序。execute_command 的值是通过uboot 传递,在 bootargs 中使用“init=xxxx”就可以了,比如“init=/linuxrc”表示根文件系统中的 linuxrc 就是要执行的用户空间 init 程序
  4. 如果 ramdisk_execute_command 和 execute_command 都为空,那么就依次查找“/sbin/init”、“/etc/init”、“/bin/init”和“/bin/sh”,这四个相当于备用 init 程序,如果这四个也不存在,那么 Linux 启动失败

​​​​​​​4.1 kernel_init_freeable

  1. wait_for_completion:等待kpthread准备就绪
  2. sam_init, sched_init_smp: SMP调度相关初始化
  3. do_basic_setup: 初始化驱动设备模型等

              初始化驱动模型:driver_init,

              顺序调用所有编译进内核的驱动模块:

  

4.打开控制台/dev/console用于打印和命令输入,console 通过uboot 的 bootargs 环境变量设置,“console=ttymxc0,115200”表示将/dev/ttymxc0 设置为 console

​​​​​​

调用函数 prepare_namespace 来挂载根文件系统。根文件系统也是由命令行参数指定的,就是 uboot 的 bootargs 环境变量。比如“root=/dev/mmcblk1p2 rootwait rw

猜你喜欢

转载自blog.csdn.net/qq_37755518/article/details/130249015