RK3588s-OrangePi开发板学习分享--Linux 系统构建基础知识储备(二--其一)
一.编译环境和工具平台搭建
二.Linux 系统构建基础知识储备
本小节主要是对三,四小节做一个铺垫性工作。侧重对linux系统编译所需要的通用组件和基础概念进行阐述,各位读者如果想要更深入了解可以参考此纲要去阅读相关书籍和源码资料。
文归正传,首先我们回到计算机体系组成原理中来。一台PC,能够运行起来的必要要素是什么?
- 中央处理器 – CPU
- 内存条 – RAM
- 硬盘 – ROM
- 电源,外设,主板…(此项忽略)
CPU是用来处理程序指令的,RAM提供了代码运行的临时空间,掉电丢失数据。ROM就是存储,想要存储的掉电不丢失的内容就会放在ROM中。
建立上述计算机体系硬件概念之后,我们回到操作系统。操作系统的本质是什么?
操作系统是用来管理板级设备,并为上层应用提供稳定运行软件环境的载体,是PC的大管家。花里胡哨一大堆,大白话操作系统本质就是可稳定运行的软件代码。既然是代码,那么在未启动的时候是不是要将代码(二进制)下载到ROM中,当机器上电的时候通过某种机制加载到RAM中,然后CPU不断的取指令运行。
下载到ROM中的代码我们称之为镜像文件,完整的镜像文件分为四大块
- u-boot镜像
- kernel镜像
- rootfs镜
- dtb
系统上电之后,其实就是将u-boot这四大块镜像中的东西按照某种规则搬运到ram中,最终实现一个稳定的操作系统环境。接下来对几大组件进行简要说明。
2-1. u-boot
u-boot又称为引导加载程序,它的使命就是引导kernel成功加载并匹配到正确的dtb,当kernel主导整套系统的运行时,uboot便自己消亡在这一次ram启动的历史长河中。生的伟大,G的伟大。
u-boot使用的一般步骤:
- 获取相应开源的u-boot源码
- 进行相应的u-boot功能裁剪配置
- 使用目标平台的交叉编译器编译u-boot源码生成u-boot镜像。
- 将u-boot镜像烧录到目标平台指定的ROM区域,当机器运行时u-boot镜像被加载到自己指定的ram区域中,然后开始自己的代码职责。
既然u-boot最终是要消亡的,那为何不直接启动kernel镜像呢?
笔者思考了这个问题,给出了一些自己的理解,其他的用处欢迎各位大佬探讨:
- 现在很多产品都需要OTA功能,如果直接启动Kernel镜像类似这样的功能便不好处理。
- 刚开始调试出现的kernel崩溃问题,看不了调试信息,可以通过u-boot去尝试分析获取关键数据。
- 某些历史遗留的兼容问题和墨守成规的行业通识。
…
2-2. kernel
linux内核代码,内核代码一般包含两部分:
- linux内核的各种机制
- linux驱动代码
现在通常是将第二部分单独编译成模块ko,不编译进内核镜像中,这样就很好的保证了内核机制模块和驱动模块的解耦性,但是因为驱动是后加载运行的,所以在速度上可能会有一定的损失。
编译kernel镜像流程与编译Uboot流程是一样的。都是获取源码然后裁剪配置再交叉编译生成对应的镜像。
2-3. rootfs
根文件系统是kernel运行OK之后挂载的第一个文件系统。如/usr /bin…目录就是kernel
根文件系统的作用,笔者有下列的一些归纳理解:
- linux系统下一切皆文件。根文件系统提供了其他文件系统的根路径。
- 根文件系统在挂载运行之后会调用一系列初始化脚本,完成一系列初始化工作,比如可以利用这些初始化脚本实现驱动ko模块的自动加载。
- 实现常用的一些命令的裁剪移植,比如ls,pwd…
rootfs如何构建:
- 下载busybox,yacot,buildroot等工具。
- 进行功能配置
- 交叉编译
- 通过nfs挂载测试
- nfs挂载测试测试OK的根文件系统打包成指定文件系统的格式(如.ex4)然后烧录到rom中。
2-4. dtb
dtb是设备树二进制文件,即烧录进rom中编译好的设备树描述代码。
dtb的作用?
旧版本的linux没有设备树的概念,2.x版本之后引入的设备树的概念。目的就是将内核中描述各种驱动设备的信息独立出来,避免内核代码无休止的臃肿和增大。
dtb如何得到?
首先要清楚以下三个概念:
- dts – 设备树源码文件
- dtc – 设备树编译工具
- dtb – 设备树二进制文件
即dts经过dtc编译得到dtb.
2-5. shell脚本
Linux自带的脚本语言,主要是可以将在shell解释器中运行的命令行通过脚本的方式编写进文件然后运行文件等同于运行shell解释器中的命令行集合。像orangepi官方编译就采用shell脚本构建了一整套的自动化编译框架。
2-6. Makefile
在学习C语言的时候,编译器IDE会自动的将.c .h文件编译成.o文件,然后通过链接器将.o文件链接,最终链接形成二进制文件。
但是在linu 编译sdk的时候,只有命令行控制的交叉编译指令。那么如何组织各.c .s .h以及各种编译中使用的工具链的依赖关系?
makefile就是基于依赖的一套代码构建规则描述性语言。
2-7. 交叉编译工具链
c代码经过编译器形成.o文件,.o又要经过汇编器形成汇编代码,汇编代码又要经过链接器形成最终能二进制文件。每个芯片平台都有自己的特性,比如大小端,是32位还是64位系统,是arm还是x86…针对不同平台就需要对应的编交叉译工具链来提供编译器,汇编器,链接器,调试器等工具。
2-8.Kconfig
图形化配置uboot,kernel,rootfs…的一种界面描述性语言。在裁剪移植源码时make xxxmenuconfig时会调用。