建立覆盆子PI Linux系统的艰难方式

2021-04-14 03:24:49

目标:下面的说明将解释如何从划伤中构建Raspberry PI 3B的Linux环境,专注于极端最小主义。我将在源代码中构建大多数组件,并使用BusyBox作为目标上唯一的用户应用程序。为了学习,重点是极简主义。像网络引导,次要引导加载程序,压缩文件系统等的优化..不会被覆盖。

引导加载程序:在加载操作系统之前运行的平台特定程序。它负责将OS内核的硬件初始化和加载到内存中。

BusyBox:单个Linux应用程序,用于模拟许多常见系统实用程序,例如CP,LS,MV等。通常用于嵌入式系统。

默认内核配置:当开发人员从源代码​​编译时,将应用于Linux内核的一组默认选项。

设备树Blob:用于描述机器设备布局的二进制格式。 Linux内核(及其设备驱动程序)使用此信息来支持特定于平台的硬件。

设备树覆盖:修改设备树BLOB的设备树的片段。它们通常用于对设备树BLOB进行小的更改或添加。

主机:在嵌入式系统中,主机是用于软件开发的计算机,这不是软件开发活动的最终产品。

内核模块:可以在运行时从内核加载和卸载的代码。它们为内核(通常用于硬件管理)添加功能,而无需重新启动系统或修改内核本身。

Linux内核:负责管理系统硬件和资源以及为用户佩纳应用程序提供服务。在系统启动时由引导加载程序加载。

Linux kernel命令行:在加载时传递给Linux内核的一组选项。它通常包含有关如何加载根文件系统的信息。

根文件系统:一系列包含基本应用程序(如init和shell)以及系统配置的一系列目录。

目标机器:嵌入式设备是嵌入式系统开发的最终产品。另请参阅:主机。

USB TTL电缆:允许您访问Raspberry PI系统外壳的电缆,而无需安装键盘和监视器。本教程是必需的硬件。它们非常便宜。

引导分区最终将包含专有的固件Blob,设备树Blob,Linux内核和两个配置文件。

根文件系统将包含内核模块和用户空间程序(例如LS,Cat等)。

我建议使用gparted进行分区。这是一个简短的截图,解释了如何在gparted中执行此操作:

我们的目标是建立一个整个Linux系统。在您加载内核之前,必须初始化硬件。硬件初始化是在Linux内核加载到内存之前运行的“引导加载程序” - 特定于平台的代码的责任。每个平台都会以不同的方式处理引导加载过程。在Raspberry PI 3B中,我们必须下载三个文件并将它们放在SD卡的引导分区(FAT16)中。这些文件不是开源,所以我们无法自己编译。

所有文件都在Raspberry PI固件存储库中提供。我不会深入讨论引导加载程序的主题。您可以在官方文档中阅读更多有关引导配置的更多信息。

在继续之前,将以下文件添加到SD卡的FAT16(启动)分区:

此时,您应该使用具有ext4分区和Fat16引导分区的SD卡。引导分区应包含上一节中列出的三个专有斑点。

安装了启动加载程序,我们已准备好从源代码中编译Linux内核。编译Linux内核需要GCC,C语言编译器。它还需要二进制实用程序(“binutils”)来处理汇编语言文件。

您的主机可能已经安装了GCC和Binutils,但存在问题 - 主机上的编译器发出x86二进制文件。覆盆子PI使用完全不同的ARM指令集。要生成二进制,RPI可以执行,我们需要一个发出ARM指令的编译器,而不是x86。无疑可以毫无疑问地安装Raspberry Pi OS(https://www.raspberypi.org/software/)并在目标设备上执行内核编译。然而,这将是一个长期的过程。为了比较,我有一个第10个Gen Core I7笔记本电脑,带有8个物理核心,8 GB的RAM和固态驱动器。编译Linux内核在此机器上花了大约20分钟,这仍然是相当大的时间。覆盆子PI上的编译将需要更长时间。

编译raspberry pi linux内核的更好方法是通过“交叉编译器”的“交叉编译”。交叉编译器是一个在一个指令集上运行的编译器,但在完全不同的指令集中输出源代码而不是目标。在我们的情况下,我们需要一个在x86机器上运行的编译器,但它发出了RPI可以理解的ARM指令。

#安装`arm-linux-gnueabihf- *`编译器,链接器等。sudo apt安装bc bison crossbuild-asers-armhf flex git libc6-dev libncurses5-dev libssl-dev

运行上面的命令后,我们的机器将有一组新的工具:

你看到了模式吗?在下一步中,我们将设置一个Cross_compile环境变量,以便应用程序将通过ARM-Linux-GNUEABIHF-GCC而不是本机GCC编译。通常,交叉编译器将提供所有本机编译器和Binutils的可执行文件,例如GCC和LD。但是,它会这样做,其中包含指示目标架构的前缀。在我们的情况下,前缀是ARM-Linux-Gnueabihf-。

如果要构建自定义工具链,或从源构建工具链,请查看Crosstool-NG。它是一种更先进的方式来生成交叉编译器。

现在我们有一个工作的工具链,我们需要查找最新的Linux内核源并编译它。

在继续之前,我们需要设置一些环境变量。您必须在执行所有步骤时导出这些变量。

#==== Bash用户:#将架构设置为ARM:导出arch = ARM#我们想要使用ARM v7:导出kernel = kernel7#设置跨编译器前缀(在上一节中解释):导出cross_compile =手臂 - linux-gnueabihf-#====鱼类用户:#set -x kernel kernel7#set -x arch arm#set -x cross_compile arm-linux-gnueabihf-

Raspberry PI Foundation管理其自己的内核版本。我们将使用git克隆源代码:

然后,我们必须根据目标设备(使用BCM2709芯片组的RPI3B)应用构建系统的默认配置:

有些用户将想修改默认内核配置。您可以通过make menuconfig完成此操作,但在我们的用例中不需要。

我们已准备好编译内核,但我们需要确定我们在我们这样做之前的CPU内核。我们需要此信息以启用并行编译,这可以大大降低编译时间。执行以下步骤:

请注意,我在下面的例子中使用了-J12。您的机器可能需要不同的-J值!

#编译实际内核,模块,DTBS#使用SSDMake -J12 Zimage模块DTBS〜20分钟

我们需要将这些类型的文件移动到先前以特定方式创建的FAT16引导分区。

首先,找到前面创建的引导分区(FAT16)的位置。在我的机器上,路径是/媒体/ rick / rpi_boot。您的设备将不同。它将生活在与BootCode.bin,fixup.dat,我们之前下载的start.elf文件中的相同位置。

#使用我们之前编译的Linux内核。 kernel = zimage#使能UART,因此我们可以使用TTL电缆。 Enable_uart = 1#为我们的设备使用相应的DTB。 device_tree = bcm2710-rpi-3-b.dtb#禁用蓝牙通过设备树覆盖。 #TIT'您可以阅读的复杂解释:https://youtu.be/68jbiuf27ay?T=431#如果跳过此步骤,您的串行连接将不会正确地工作。 dtoverlay =禁用 - bt

raspberry pi将从cmdline.txt获取内核命令行。与config.txt一样,它生活在引导分区(FAT16)中:

既然Linux内核是构建的并且配置了引导加载程序,我们需要将我们的焦点转移到构建根文件系统。根文件系统是Linux期望查找可执行文件,内核模块,系统文件和许多其他系统的位置。布局由Linux文件系统层次结构标准指定

我们将在主机上的目录中创建一个根文件系统。稍后,我们将将最终目录结构复制到我们在教程开头进行的EXT4分区。

使用PWD来确定此目录的绝对路径。让这些信息方便;我们将需要几步。

我们将放在根文件系统上的第一件事是内核模块,它在上一步中与Linux内核一起编译。

CD返回到Linux源代码的目录,但将绝对路径保留到root_fs目录方面。

我们需要将Install ModPath环境变量设置为root_fs的绝对路径:

在此步骤之后,您将在root_fs /目录中找到一个众多的* .ko文件。

模块现在安装在根文件系统中。但是,模块不足以运行Linux系统。我们需要在Linux系统上找到的所有常用工具,如LS,CD,CP和朋友。

我们将静态交叉编译BusyBox而不是单独编译每个工具。 Busybox Touts本身就像“嵌入式Linux的瑞士军刀”。它是一个单个可执行文件,用于多个函数,具体取决于如何加载可执行文件。例如,我们可以从busybox到/ bin / echo创建一个符号链接。当我们执行/ bin / echo时,busybox将注意符号链接名称并按照echo命令的预期运行。 BusyBox实现了CD和LS等所有基本Linux命令行实用程序。它还附带了像轻量级HTTP服务器和文本编辑器等附加的附加功能。

一旦我们在我们的主机上有源,我们需要在Menuconfig in in in menuconfig中调整一些设置: #-J值将不同。 #通常,我使用1.5倍物理CPU CoreS.Make -J12Make安装 BusyBox现在安装在....../root_F。 您应该在root文件系统目录($ install_mod_path)的bin /,sbin /和usr /目录中看到许多符号链接。 BusyBox不够引导Linux系统。 我们仍然需要添加: #创建登录挂载的目录:mkdir procmkdir sysmkdir devmkdir etc#create config目录:mkdir etc / init.d#创建一个空的`rcs`file.touch etch etc / init.d / rcs 请勿使用监视器 - 需要USB TTL电缆! 如果您不拥有这样的电缆,您可以在亚马逊上购买几美元。 它将改变你的生活作为覆盆子PI爱好者,相信我。 打开电源后,您应该看到一些内核消息滚动,最终滚动shell提示。

#......缩短了澄清...... [4.536592] USB 1-1.1:使用DWC_OTG的新型高速USB设备编号3 [4.666906] USB 1-1.1:找到新的USB设备,IDvendor = 0424,IDProduct = EC00,BCDDevice = 2.00 [4.680733] USB 1-1.1:新USB设备字符串:MFR = 0,产品= 0,SerialNumber = 0 [4.693829] SMSC95xx V1.0.6 [4.791032] SMSC95xx 1-1.1:1.0 eth0:寄存器' smsc95xx' smsc95xx& #39; 在USB-3F980000.USB-1.1,SMSC95xx USB 2.0以太网,B8:27:EB:54:61:EFPLEASE按ENTER激活此控制台./#Echo"您好,Linux世界。"你好, Linux世界。 我们现在有一个工作的Linux根分区和引导分区。 将root_fs /目录复制到SD卡并尝试引导设备。 本文中提供的Linux系统并不是很有用,但希望它可以更好地了解Linux发行版和嵌入式Linux系统的建立方式。 随着反馈的reddit或lobste.rs,请随时与我联系。