Linux系统移植全流程解析

发布时间:2026/8/20 15:37:45
Linux系统移植全流程解析 系统移植系统操作系统一个程序一堆代码管理对应资源和任务包含Linuxwindowuinxfreertos Linux操作系统移植将源代码Linux操作系统源码从一种环境开发环境下放到另一种环境产品环境下运行也可以称为移植。一.启动流程pc机1启动BIOS英文Basic Input Output System的缩略词直译过来后中文名称就是基本输入输出系统。是一组固化到计算机内主板上一个ROM芯片上的程序它保存着计算机最重要的基本输入输出的程序、开机后自检程序和系统自启动程序它可从CMOS中读写系统设置的具体信息。其主要功能是为计算机提供最底层的、最直接的硬件设置和控制。1、初始化时钟初始化内存基本硬件的初始化2、判断启动方式usb/硬盘/光驱2引导程序固化在硬盘存储数据最前面的部分识别对应的操作系统加载对应操作系统3操作系统windows,linux,Mac OS没有图形界面程序4文件系统NTFS,FAT(16/32),window文件系统格式 日志文件系统5应用程序桌面应用程序启动的流程首先pc机启动先启动的BIOS系统时钟和内存、选择对应的启动方式usb、硬盘、光驱。对应启动盘的最开始的程序就是引导程序内存中引导程序是首先识别有多少系统内存中如果只有一个系统直接加载系统当有多个操作系系统时会让你选择系统启动系统起来之后挂载文件系统启动我们程序。操作系统是个非图形化界面的程序桌面是对应的应用程序。嵌入式设备启动流程1厂家固化在IROM代码1.基本硬件初始化它需要的时钟和设备2.判断对应的启动方式eMMC(Flash的一个变种)/USB/SD卡3.把Bootloader第一个阶段的代码加载IRAM芯片内部运行内存缺点芯片贵2在IRAM里面去运行对应的bootloader第一阶段的代码SPLSecondary Program Loader二级程序加载器第二阶段程序的加载1.初始化整个系统时钟2.初始化内存3.把完整的bootloader搬移到内存中Bootloader分两个阶段运行的原因芯片内部存储空间有限如果内存空间做大成本提高。不在IROM中初始化内存的原因因为芯片厂家不知道开发板采用什么样的内存没有办法进行初始化。3在内存运行bootloader第二个阶段的代码1.初始化一下硬件设备根据开发板去定义网卡串口usb2.加载对应操作系统内存4运行操作系统没有图形界面的5挂载文件系统EXT(2,3,4)6启动应用程序BootloaderBIOS引导程序。二.U-boot和Linux 内核之间的参数传递Linux内核是被U-Boot被动加载到内存中运行的没有初始化过内存等硬件对当前硬件环境一无所知如果U-Boot不传递参数内核无法正常运行。u_boot和Linux之间在传递参数的时候是按照双方约定的格式传递格式包含1.struct parm__struct结构体2.tag列表3.设备树参数传递的规则寄存器r0规定为0不传递有效信息r1开发板的IDr2其他参数在内存中开始地址r1的参数是让Linux内核自己去判断它是否支持当前的开发板r2是其他参数在内存中的开始地址单个寄存器只有4个字节无法存放大量参数因此大量参数存放在内存中将内存起始地址记录在r2。r2存放的信息(1内存的信息内存的开始地址和内存的大小(2)命令行参数:bootargs的内容高诉Linux内核启动后挂载文件系统的方式例如NFS方式(3其他信息bootcmdu-boot启动完成读秒后自动执行从参数命令把文件从 TFTP 服务器加载到内存RAM临时的然后从内存启动bootcmdtftp 41000000 uImage;tftp 42000000 exynos4412-fs4412.dtb;tftp 43000000 ramdisk.img;bootm 41000000 43000000 42000000uImage是 U-Boot 引导加载程序专用的、经过特殊格式封装的 Linux 内核镜像文件。exynos4412-fs4412.dtb设备树文件。ramdisk.img自己的系统映象文件。bootargssetenv bootargs root/dev/nfs nfsroot192.168.2.5:/home/hqyj/fs4412/rootfs,prototcp,nfsvers3,consolettySAC2,115200 init/linuxrcip192.168.2.29root/dev/nfs指定根文件系统rootfs不是从本地块设备如 emmc/SD 卡挂载而是使用NFS 网络文件系统。内核会因此启用 NFS 根文件系统支持。nfsroot192.168.2.5:/home/hqyj/fs4412/rootfs192.168.2.5linux的IP地址/home/hdyj/fs4412/rootfs主机上存放根文件系统的位置prototcpNFS 使用TCP 协议nfsvers3使用NFS 版本 3no_lock禁用 NFS 文件锁lockd。避免在无锁服务时出现警告或延迟常用于简单开发环境。rw根文件系统以读写read-write方式挂载允许在开发过程中修改文件。consolettySAC2,115200内核控制台输出到串口 2ttySAC2波特率115200。这是开发板与主机间调试信息的输出通道init/linuxrc内核启动后执行的第一个用户态程序是/linuxrc通常是 BusyBox 提供的初始化脚本或软链接到/sbin/init。ip192.168.2.29给开发板自身指定静态 IP 地址192.168.2.29用于 NFS 挂载及网络通信。三.Kconfig Makefile .config menuconfig之间的关系menuconfig是Linux内核提供的菜单选项用于表示Linux内核有哪些功能类比餐馆的菜单汇总了当前内核所有支持的功能选项供用户选择。.config是Linux当前内核选择了哪些功能的记录类比点菜的凭证记录了用户最终选定的内核功能。Makefile给Linux内核提供对应的功能实现类比餐馆所有厨师会做的菜只有Makefile中支持的功能才能出现在menuconfig的菜单选项里。Kconfig用于配置对应的宏将用户选择的功能配置项通过宏的形式确定下来比如配置为Y代表将对应功能直接编译进内核。M代表编译进模块。n表示不编译。配置项核心逻辑内核菜单的选项来源是KconfigKconfig的内容是一级一级包含的从最内层的硬件相关配置如DM9000开始先被物理网卡相关配置包含再被网络相关配置包含继续向上被更上层的功能配置包含最终汇总成menuconfig的完整菜单。将功能编译进内核依靠make流程中定义的宏配置部分功能没有默认宏配置需要手动配置宏将宏设置为Y代表将该功能直接编译进内核。四.U-boot启动过程分析ARM核的设置1.设置CPU为SVC模式2.设置异常向量表3.关闭Cache和MMU(内存管理单元:A.内存访问权限设置 B.物理地址和虚地址的映射)SOC芯片的设置4.处理唤醒的条件5.判断是否在内存中运行6.如果不在内存中运行,则初始化系统时钟和内存控制器第一阶段如果在内存中运行则不需要初始化系统时钟和内存控制器(第二阶段)7.初始化uart8.设置了sp9.调用board_init_f第一阶段代码:board_init_f 功能将u_boot从存储器搬移到内存跳到内存中运行第二阶段代码:board_init_f(1)执行了初始化序列表 (板子相关的初始化操作)(2)为u_boot重定向预留内存10.对u_boot重定向 (从低端内存搬移到高端内存)11.清bss段12.board_init_r[1]外围硬件初始化emmc 、网卡[2]让串口作为标准输入输出设备[3]main_loop探测自动启动是否被打断如果没有被打断,则执行bootcmd指定的命令如果被打断了则进入u_boot交互界面五.Linux 启动过程分析1内核启动首先读取CPU内部ID芯片厂商生产芯片时会为其生成唯一ID类似身份证内核读取该ID后与内部保存的ID匹配确认当前运行的CPU是内核支持的款型匹配失败会打印错误信息该阶段代码为汇编实现还未进入C语言阶段。2接着获取bootloader传递的板子ID每块开发板也有独立ID与CPU内部ID相互独立开发板ID需要向Linux内核官方申请3MMU使能与页表映射阶段1.两个ID验证完成后内核打开MMUMMU的功能是完成物理地址和虚拟地址的映射这是操作系统中地址为虚拟地址的原因。2.初期采用一级页表映射物理地址和虚拟地址一一对应例如物理地址4000万对应虚拟地址4000万此时仅使能MMU还未完全接管整个内存后续会重新建立页表映射。4C语言运行条件准备阶段1.执行清空BSS段、设置SP指针两步操作是C语言程序可以正常运行的必要条件清空BSS段后未初始化的全局变量和static修饰的未初始化静态变量默认值为0若未做该操作这类变量值为随机值。2.该阶段还会保存板子ID、CPU ID及其他相关参数。3start_kernel阶段C语言运行阶段1.完成C语言运行条件准备后进入start_kernel函数正式切换到C语言执行内核代码此时终端开始输出大量打印信息。2.该阶段具体操作为打印Linux内核版本、处理bootnode传递给Linux内核的参数、初始化控制台默认控制台为窗口用于输入输出、获取内存信息、重新建立页表完成物理内存和虚拟内存的完整映射后续可使用虚拟地址支持多个虚拟地址映射到同一物理内存32位机器的每个进程可拥有4G独立虚拟地址空间实际占用物理内存远小于该数值依赖物理地址和虚拟地址的映射实现。3.之后依次初始化异常处理、加载所有驱动模块、挂载根文件系统、执行根文件系统中的init程序启动init进程完成整个内核启动流程。六.Busybox init启动过程分析1. 启动 init 进程Linux 内核完成根文件系统挂载后执行init进程进程 ID 为 1。在 Busybox 中这个init就是/sbin/init由 Busybox 提供。2.读取并解析 /etc/inittabinittab文件格式id编号权限等级动作进程id编号和权限等级一般忽略动作sysinit表示进程在系统启动后最先执行只执行一次init 进程等待它结束才继续执行其他动作wait表示进程在执行 sysinit 后执行只执行一次init 进程等待它结束才继续执行其他动作once表示进程在执行 wait 后执行只执行一次init 进程不等待它结束respawn表示进程在启动 once 后执行init 进程一旦发现该进程死掉就会重新启动它askfirst表示进程在启动完 respawn 后执行与 respawn 类似不过 init 进程会先输出提示Please press Enter to activate this console等用户输入回车后才启动子进程restart如果 BusyBox 中配置了CONFIG_FEATURE_USE_INITTAB并且 init 进程收到SIGHUP 信号时先重新读取/解析/etc/inittab文件再执行该进程shutdown表示进程在系统收到重启、关闭系统命令时运行ctrlaltdel表示进程在按下CtrlAltDel组合键时运行3. 执行 /etc/init.d/rcS 脚本这是由 init 进程第一个调用的脚本作为系统启动时的初始化脚本。4. 挂载 /etc/fstab 文件指定的设备device:要挂载的设备mount-point:挂载点type:文件系统类型options:挂载参数dump程序根据这个字段来决定这个文件系统是否需要备份。fsck orderfsck程序根据这个字段来决定是否对磁盘做检查proc — Linux内核的资源进程资源 → /proc 这个目录tmpfs — 临时存储的空间 → /tmp 这个目录sysfs — Linux子系统GPIO、PWM、I2C → /sys 这个目录tmpfs — Linux的设备挂载 → /dev 目录5. 运行 shell 程序当init按照inittab配置启动到askfirst或respawn的 shell 进程时用户会看到一个命令行提示符。此时 shell 已经运行但环境变量尚未完全设置好因此接下来需要执行/etc/profile来初始化环境。6. 执行 /etc/profile 脚本

相关新闻