Kernel,Rootfs,Uboot,INIT进程,内核空间一次讲清楚!!!

[复制链接]
作者: zhaoyuac09 | 时间: 2023-5-15 23:57:22 | 其他|
0 59

1947

主题

1947

帖子

5841

积分

研究生

Rank: 9Rank: 9Rank: 9

积分
5841
发表于 2023-5-15 23:57:22| 显示全部楼层 |阅读模式
linux启动过程
      
  • Linux操作系统启动之前,系统硬件需要进行初始化,包括CPU、内存、总线、外设等。当电源被打开后,CPU开始执行复位向量(Reset Vector)中的指令,这个复位向量通常是一个硬件固件中的地址,指向一个固定的内存地址,然后CPU开始从这个地址读取执行指令。通常情况下,CPU在执行复位向量之前需要进行硬件初始化,例如初始化时钟、内存控制器等。当硬件初始化完成后,引导加载程序开始启动。引导加载程序通常是位于系统的非易失性存储器(例如闪存、ROM等)中的一段代码,负责从存储设备(如硬盘、NFS、SD卡等)中读取内核映像文件,将其加载到内存中,并跳转到内核的起始位置开始执行。引导加载程序可以是硬件固件(如BIOS或UEFI),也可以是引导加载器(如GRUB或U-Boot)。内核启动后,它首先会初始化硬件设备,包括CPU、内存、总线、外设等。接下来,内核会初始化文件系统,包括读取根文件系统、安装模块、挂载文件系统等。然后,内核会创建进程并执行用户空间程序,例如init进程,它是所有进程的父进程。此时,用户空间程序开始运行,内核变成了用户空间程序的服务提供者,为用户程序提供系统调用等服务。用户空间程序是指在Linux操作系统中运行的所有应用程序和进程,例如Shell、应用程序、服务进程等。用户空间程序的启动一般由init进程控制。init进程是所有进程的父进程,它负责启动和管理所有其他进程。当内核启动完成后,init进程会通过读取配置文件(如/etc/inittab和/etc/init.d/rc.sysinit)来启动用户空间程序。init进程会根据配置文件中的信息,启动一系列用户空间程序和服务,例如网络服务、系统日志服务、文件共享服务等。
在用户空间程序启动后,系统进入了正常工作状态,用户可以通过Shell或其他应用程序来执行各种任务,例如编辑文本、浏览网页、管理文件等。
以全志H6举例
      
  • 硬件初始化  
  • 全志H6芯片启动前,需要进行硬件初始化,包括CPU、DDR、EMMC、NAND Flash、SPI Flash、MAC等硬件设备的初始化。这些硬件设备的初始化一般由BootROM和BootROM中的相关代码完成。  
  • BootROM是嵌入式系统中的一段代码,它是芯片内置的只读存储器(ROM)中的一段程序,一般由芯片厂商提供。在全志H6芯片中,BootROM是固化在芯片内部的,它是芯片上电后第一时间运行的程序,负责芯片的初始化和引导加载程序的启动。  
  • BootROM和Bootloader的关系  
  • BootROM是芯片内置的引导程序,负责初始化芯片并启动引导加载程序,而Bootloader是启动流程的下一步,负责从存储设备中读取内核和文件系统等映像文件,并将它们加载到内存中。  
  • 在嵌入式系统的启动过程中,U-Boot通常是在芯片上电后第二个运行的程序,它负责初始化硬件、读取内核映像文件和文件系统等映像文件,并将它们加载到内存中。最终,U-Boot将系统的控制权转移给内核,由内核进一步初始化和运行系统。引导加载程序启动  
  • 全志H6芯片启动后,会首先执行BootROM中的代码,读取存储设备(如SD卡或EMMC)中的引导加载程序(如U-Boot),将其加载到DDR内存中。U-Boot是一个开源的引导加载器,它可以在启动时读取SD卡、EMMC、NAND Flash等存储设备中的文件,并将内核和文件系统等映像文件加载到内存中。内核启动  
  • U-Boot将内核映像文件(如zImage)加载到内存中后,会调用内核的起始位置开始执行。内核启动后,会完成硬件设备的初始化,包括DDR、NAND Flash、SPI Flash、MAC等硬件设备的初始化,并初始化虚拟内存、进程管理等系统基础设施。然后,内核会挂载文件系统,包括读取根文件系统、安装模块、挂载文件系统等。初始化和运行内核  
  • 当内核初始化完成后,它会创建第一个用户空间进程(如),并执行用户空间程序。init进程是所有进程的父进程,它负责启动和管理所有其他进程。当内核启动完成后,init进程会根据配置文件(如/etc/inittab和/etc/init.d/rc.sysinit)启动用户空间程序。用户空间程序的启动包括启动一系列系统服务,如网络服务、系统日志服务、文件共享服务等。此时,用户空间程序开始运行,内核变成了用户空间程序的服务提供者,为用户程序提供系统调用等服务。用户空间程序的启动  
  • 当用户空间程序启动后,系统进入了正常工作状态。在全志H6芯片上,用户可以通过终端(如串口、SSH)或其他应用程序(如浏览器、音视频播放器)来执行各种任务,例如编辑文本、浏览网页、播放音视频等。
BootLoader是什么?和Uboot什么关系?
BootLoader是嵌入式系统中非常重要的组件之一,常见的Boot Loader包括以下几种:
      
  • U-Boot:是一款开源的Boot Loader,广泛应用于嵌入式系统中。它可以支持多种处理器和架构,提供丰富的命令行接口和配置选项,可以实现内核和设备驱动程序的加载、引导和调试等功能。RedBoot:是另一款常用的开源Boot Loader,也是一个基于命令行的工具。它支持多种处理器和架构,提供了丰富的调试和监控功能,可以实现网络引导和文件系统管理等功能。Das U-Boot:是U-Boot的一个变种,由DENX开发和维护,专门为嵌入式Linux系统设计。它支持多种处理器和架构,提供了丰富的命令行接口和配置选项,可以实现网络引导、文件系统管理和设备树配置等功能。GRUB:是一个广泛应用于PC和服务器系统的Boot Loader。它支持多种操作系统和文件系统,提供了丰富的引导选项和图形用户界面,可以实现多系统引导和启动配置等功能。
Bootloader是嵌入式系统启动过程中的一个重要组件,它负责加载内核文件和设备树文件等映像文件,为内核的正常运行提供基础环境。在加载内核文件和设备树文件时,Bootloader通常需要完成以下几个步骤:
      
  • 读取内核文件和设备树文件。内核文件是一个镜像文件,包含了操作系统内核的代码和数据,而设备树文件是一个描述硬件设备和系统配置信息的文本文件,通常存储在与内核文件相同的存储设备中。Bootloader需要读取这些文件并将它们加载到内存中,以便后续的操作可以访问和使用它们。解压内核文件。内核文件通常是经过压缩的,需要在加载到内存后进行解压。Bootloader需要根据内核文件的压缩格式进行解压操作,以便内核可以被正确加载和运行。加载设备树文件。设备树文件是一个文本文件,需要经过解析和编译后才能使用。Bootloader需要将设备树文件编译成二进制格式,并将其加载到内存中,以便内核可以访问和使用设备树中描述的硬件设备和系统配置信息。设置内核启动参数。内核启动参数是内核在启动时使用的一组参数,用于指定系统的各种配置和选项。Bootloader需要设置内核启动参数,并将它们传递给内核,以便内核可以按照这些参数进行初始化和配置。转移控制权给内核。最后,Bootloader需要将控制权转移给内核,使得内核可以接管系统的控制权并进行初始化和运行。Bootloader会将内核的入口地址传递给内核,并跳转到内核的入口地址开始执行内核代码。
总之,Bootloader在加载内核文件和设备树文件时需要完成多个步骤,包括读取文件、解压文件、编译设备树文件、设置内核启动参数和转移控制权等,以确保内核和系统可以正常启动并运行。
rootfs
在Linux启动时,内核首先被加载到内存中并执行,接着内核需要加载root文件系统(rootfs),以便用户空间进程可以启动并运行。rootfs是文件系统的根,包含了所有的文件和目录,也是其他文件系统的挂载点。rootfs是一个内存文件系统,不依赖于硬盘上的文件系统。它是一个最小化的文件系统,只包含运行Linux所必需的文件和目录,例如/bin、/dev、/etc、/proc、/sys、/tmp和/var等目录。
加载rootfs是Linux启动过程中的一个重要步骤。Linux内核在启动时需要先加载rootfs,以便能够访问文件系统中的内容,例如可执行程序、配置文件等。
为什么kernel(内核)需要加载rootfs,用户空间进程才可以运行?
内核是操作系统的核心部分,负责管理计算机的硬件和软件资源,为用户空间进程提供支持和服务。但是内核本身并不包含用户空间进程,用户空间进程需要通过文件系统来获取执行文件和相关资源。因此,内核需要加载rootfs(根文件系统)才能让用户空间进程运行。
根文件系统是Linux系统的根目录,它包含了所有系统文件和目录,是用户空间进程的运行环境。当计算机启动时,内核首先加载自身,并初始化硬件设备,然后会尝试挂载根文件系统,使得用户空间进程可以访问其中的文件和资源。
init进程
在Linux系统中,init进程是系统中的第一个用户级进程,它的PID通常为1。init进程的主要作用是负责系统的初始化和启动,它会在系统启动时自动启动,并按照指定的顺序依次启动其他进程和服务,包括加载文件系统、启动守护进程、挂载磁盘分区等。
init进程的启动过程通常可以分为以下几个步骤:
      
  • 内核初始化。当Linux系统启动时,内核会被加载到内存中,并进行一系列初始化工作,包括初始化CPU、内存管理、设备驱动等。在内核初始化完成后,它会启动init进程作为系统的第一个用户级进程。加载init程序。在内核初始化完成后,init进程会被加载到内存中,并开始执行。init进程的代码通常存储在/sbin/init文件中,它会在启动时被执行。执行初始化脚本。在init进程启动后,它会按照预设的顺序执行初始化脚本,以完成系统的基本配置和启动服务。这些初始化脚本通常存储在/etc/init.d/目录下,它们会在系统启动时被自动执行。启动守护进程。在初始化脚本执行完毕后,init进程会启动一些守护进程,包括syslogd、klogd、crond等。这些守护进程会在后台运行,负责系统的日志记录、定时任务等功能。挂载文件系统。在守护进程启动后,init进程会加载并挂载根文件系统。根文件系统是Linux系统的根目录,所有其他文件系统都必须挂载到根文件系统之下。在挂载文件系统之前,init进程会检查文件系统的完整性,并进行修复和恢复。启动用户登录。最后,init进程会启动一个getty进程,以提供用户登录界面。getty进程会等待用户登录,当用户登录成功后,它会将用户的终端连接到一个shell进程中,从而完成用户登录过程。
内核映像文件
内核映像文件(kernel image file)是Linux系统中内核的二进制文件,它包含了内核的所有代码和数据。在Linux系统启动时,内核映像文件被加载到内存中,并开始执行,以完成系统的初始化和启动。
内核映像文件通常存储在文件系统中的/boot目录下,其文件名一般为vmlinuz或bzImage,其中vmlinuz是经过gzip压缩的内核映像文件,而bzImage是经过bzip2压缩的内核映像文件。这些压缩方式可以减小内核映像文件的大小,从而更容易传输和存储。
在Linux系统启动时,内核映像文件被加载到内存中,并进行一系列初始化工作,包括初始化CPU、内存管理、设备驱动等。内核会读取设备树文件,对硬件进行初始化,并加载并挂载根文件系统。在初始化完成后,内核会启动init进程作为系统的第一个用户级进程,init进程会依次启动其他进程和服务,以完成系统的启动和配置。
内核映像文件的生成通常需要进行编译和链接,其中编译过程需要使用交叉编译器,以将代码编译成适合嵌入式系统的二进制格式。在编译完成后,可以使用一些工具将内核映像文件打包成镜像文件,例如uImage和zImage等,以便于传输和存储。
内核空间和用户态
内核空间和用户态是计算机操作系统中的两个重要概念,它们主要用来区分不同程序的运行环境和访问权限。
      
  • 内核空间和用户态是两个不同的虚拟地址空间,操作系统内核运行在内核空间,应用程序运行在用户态。内核空间可以直接访问硬件资源和操作系统的所有功能,而用户态程序需要通过系统调用接口来请求内核的帮助。内核空间和用户态之间的切换是通过系统调用、中断、异常等方式实现的。当应用程序需要访问内核资源时,会触发相应的中断或异常,使CPU从用户态切换到内核态。内核空间和用户态之间的切换需要进行一定的上下文切换,包括保存和恢复CPU的状态、切换虚拟地址空间、切换堆栈等操作,因此会带来一定的性能开销。内核空间和用户态的划分是为了保护系统的稳定和安全,内核空间具有更高的访问权限和更大的系统资源,但同时也带来了更高的风险和更大的责任。而用户态程序则更加灵活和易于开发和维护,但其访问权限和系统资源受到一定限制。
举个例子
在Linux系统中,用户态程序可以通过系统调用接口请求内核的帮助来访问硬件资源或进行系统操作。例如,一个用户态程序想要读取文件,就可以调用系统调用接口open()和read()来请求内核打开文件并读取数据。在调用系统调用接口时,程序会触发一次从用户态到内核态的上下文切换,使得程序可以访问内核空间中的相关资源和功能。当系统调用结束后,程序再次切换回用户态,继续执行程序的逻辑。这样,用户态程序就可以通过系统调用接口来访问内核资源,而内核则可以保护系统的稳定和安全,防止用户态程序对系统造成损害。
内核模式和用户模式
在计算机系统中,CPU(中央处理器)通常具有两种不同的运行模式,也称为特权级别或权限模式,分别是内核模式(也称为特权模式或系统模式)和用户模式(也称为非特权模式或用户态)。
内核模式是CPU的一种运行模式,通常是操作系统内核的运行模式。在内核模式下,CPU可以访问和控制所有硬件资源和内存空间,包括处理器、内存、设备等等。内核模式具有更高的权限和特权,可以进行更加底层的操作,例如访问硬件设备、修改内存分页表等等。
用户模式是CPU的另一种运行模式,通常是用户空间程序的运行模式。在用户模式下,CPU只能访问自己的内存空间和一部分受操作系统授权的硬件资源,无法直接访问操作系统内核和系统资源。用户模式下的程序不能直接执行特权指令,只能通过系统调用等特殊机制来向内核发出请求,从而访问操作系统内核和系统资源。
在实际应用中,操作系统内核通常运行在内核模式下,而用户空间程序则运行在用户模式下。当用户空间程序需要访问操作系统内核和系统资源时,需要通过系统调用等特殊机制来向内核发出请求,从而进入内核模式执行特权操作。这种内核态和用户态的切换,可以保证操作系统的安全性和稳定性。
具体来说,当CPU执行代码时,会根据代码中指令的特权级别来判断当前指令所处的特权级别。如果指令的特权级别等于或高于当前的特权级别,那么CPU会执行这个指令,并且在执行过程中会保持当前的特权级别不变;否则,CPU会抛出异常或者中断,让操作系统处理。

来源:
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回列表 返回顶部