Linux 的部署设备范围比 Linus Torvalds 在宿舍里开发它时预想的要广泛得多。它支持的芯片架构种类令人震惊,并已导致 Linux 应用于各种大小的设备;从 大型 IBM 大型机到 微型设备(尺寸不大于其连接端口),以及介于两者之间的所有设备。它用于大型企业数据中心、互联网基础设施设备和个人开发系统。它还为消费电子产品、移动电话和许多物联网设备提供动力。
在为桌面和企业级设备构建 Linux 软件时,开发人员通常在其构建机器上使用桌面发行版(例如 Ubuntu),以便拥有尽可能接近软件部署环境的环境。 VirtualBox 和 Docker 等工具甚至可以更好地对齐开发、测试和生产环境。
什么是嵌入式系统?
维基百科将 嵌入式系统 定义为:“在更大的机械或电气系统中具有专用功能的计算机系统,通常具有实时计算约束。”
我发现可以简单地说,嵌入式系统是大多数人不会认为是计算机的计算机。它的主要作用是充当某种设备,并且不被认为是通用计算平台。
嵌入式系统编程中的开发环境通常与测试和生产环境非常不同。它们可能使用不同的芯片架构、软件堆栈,甚至操作系统。嵌入式开发人员与桌面和 Web 开发人员的开发工作流程非常不同。通常,构建输出将包含目标设备的整个软件映像,包括内核、设备驱动程序、库和应用软件(有时还包括引导加载程序)。
在本文中,我将对四种常用的嵌入式 Linux 系统构建选项进行调查。我将介绍使用每种工具的感受,并提供足够的信息来帮助读者决定为他们的设计使用哪种工具。我不会教您如何使用它们中的任何一个;一旦您缩小了选择范围,就会有大量的深入在线学习资源。没有哪个选项适合所有用例,我希望提供足够的细节来指导您的决策。
Yocto
Yocto 项目被 定义 为“一个开源协作项目,它提供模板、工具和方法来帮助您为嵌入式产品创建自定义的基于 Linux 的系统,而无需考虑硬件架构。” 它是一个配方、配置值和依赖项的集合,用于创建针对您的特定需求量身定制的自定义 Linux 运行时映像。
完全公开:我在嵌入式 Linux 方面的大部分工作都集中在 Yocto 项目上,我对该系统的知识和偏见可能会很明显。
Yocto 使用 Openembedded 作为其构建系统。从技术上讲,这两个项目是独立的;然而,在实践中,用户不需要理解这种区别,并且项目名称经常互换使用。
Yocto 项目构建的输出大致由三个组件组成
- 目标运行时二进制文件: 这些文件包括引导加载程序、内核、内核模块、根文件系统映像以及将 Linux 部署到目标平台所需的任何其他辅助文件。
- 软件包源: 这是可在您的目标上安装的软件包的集合。您可以根据您的需要选择软件包格式(例如,deb、rpm、ipk)。其中一些可能已预装在目标运行时二进制文件中,但是,可以构建软件包以安装到已部署的系统中。
- 目标 SDK: 这些是表示安装在您的目标上的软件的库和头文件的集合。应用程序开发人员在构建其代码时使用它们,以确保它们与适当的库链接。
优点
Yocto 项目在行业中得到广泛使用,并得到许多有影响力的公司的支持。此外,它还拥有庞大而活跃的开发者 社区 和 生态系统 为其做出贡献。开源爱好者和企业赞助商的结合有助于推动 Yocto 项目。
有很多选择可以获得 Yocto 的支持。如果您希望自己动手,可以使用书籍和其他培训材料。如果您想聘请专家,可以找到许多具有 Yocto 经验的工程师。许多商业组织提供基于 Yocto 的统包产品或基于服务的实施和定制,以满足您的设计需求。
Yocto 项目通过 层 易于扩展,这些层可以独立发布以添加额外的功能,以针对项目版本中不可用的目标平台,或存储特定于您的系统的自定义项。可以将层添加到您的配置中,以添加标准版本中未专门包含的独特功能;例如,“meta-browser”层包含 Web 浏览器的配方,可以轻松地为您的系统构建这些配方。由于层是独立维护的,因此层的发布计划(根据层的开发速度调整)可能与标准 Yocto 版本的发布计划不同。
Yocto 可以说是本文讨论的所有选项中设备支持最广泛的选项。由于许多半导体和电路板制造商的支持,Yocto 很可能支持您选择的任何目标平台。直接 Yocto 版本 仅支持少数电路板(以允许进行适当的测试和发布周期),但是,标准的工作模式是使用外部电路板支持层。
最后,Yocto 非常灵活且可自定义。针对您的特定应用程序的自定义项可以存储在层中,以进行封装和隔离。特定于功能层的自定义项通常存储为层本身的一部分,这允许将相同的设置同时应用于多个系统配置。 Yocto 还提供了明确定义的层优先级和覆盖功能。这允许您定义应用层和搜索元数据的顺序。它还使您能够覆盖优先级较高的层中的设置;例如,对现有配方的许多自定义项将被添加到您的私有层中,并且顺序由优先级精确控制。
缺点
Yocto 项目的最大缺点是学习曲线。学习该系统并真正理解它需要大量的时间和精力。根据您的需求,这对于与您的应用程序无关的技术和能力来说可能是一笔过大的投资。在这种情况下,与商业供应商之一合作可能是一个不错的选择。
Yocto 项目构建的开发构建时间和资源相当高。需要构建的软件包数量很多,包括工具链、内核和所有目标运行时组件。 Yocto 开发人员的开发工作站往往是大型系统。不建议使用紧凑型笔记本电脑。这可以通过使用许多提供商提供的基于云的构建服务器来缓解。此外,Yocto 具有内置的缓存机制,当它确定构建特定软件包的参数没有更改时,它允许重用先前构建的组件。
建议
将 Yocto 项目用于您的下一个嵌入式 Linux 设计是一个强有力的选择。在本文介绍的选项中,它是最广泛适用的,而无需考虑您的目标用例。广泛的行业支持、活跃的社区和广泛的平台支持使其成为大多数设计师的不错选择。
Buildroot
Buildroot 项目被定义为“一种简单、高效且易于使用的工具,可通过交叉编译生成嵌入式 Linux 系统”。它与 Yocto 项目具有许多相同的目标,但它侧重于简单性和极简主义。一般来说,Buildroot 将禁用所有软件包的所有可选编译时设置(少数例外情况除外),从而生成尽可能小的系统。系统设计人员有责任启用适用于给定设备的设置。
Buildroot 从源代码构建所有组件,但不支持目标软件包管理。因此,它有时被称为固件生成器,因为映像在很大程度上在构建时是固定的。应用程序可以更新目标文件系统,但没有机制将新软件包安装到正在运行的系统中。
Buildroot 输出大致由三个组件组成
- 根文件系统映像以及将 Linux 部署到目标平台所需的任何其他辅助文件
- 适用于目标硬件的内核、引导加载程序和内核模块
- 用于构建所有目标二进制文件的工具链。
优点
Buildroot 对简单性的关注意味着,一般来说,它比 Yocto 更容易学习。核心构建系统是用 Make 编写的,并且足够短,可以让开发人员理解整个系统,同时又足够可扩展以满足嵌入式 Linux 开发人员的需求。 Buildroot 核心通常只处理常见的用例,但它可以通过脚本扩展。
Buildroot 系统使用普通的 Makefile 和 Kconfig 语言进行配置。 Kconfig 由 Linux 内核社区开发,并在开源项目中得到广泛使用,这使许多开发人员都很熟悉它。
由于禁用所有可选构建时设置的设计目标,Buildroot 通常会使用开箱即用的配置生成尽可能小的映像。一般来说,构建时间和构建主机资源也将小于 Yocto 项目的构建时间和构建主机资源。
缺点
对简单性和最少启用构建选项的关注意味着您可能需要进行大量自定义才能为您的应用程序配置 Buildroot 构建。此外,所有配置选项都存储在一个文件中,这意味着如果您有多个硬件平台,则需要为每个平台进行每个自定义更改。
对系统配置文件的任何更改都需要完全重建所有软件包。与 Yocto 相比,最小的映像大小和构建时间在某种程度上缓解了这种情况,但这可能会在您调整配置时导致长时间的构建。
默认情况下未启用中间软件包状态缓存,并且不如 Yocto 实现彻底。这意味着,虽然第一次构建可能比同等的 Yocto 构建要短,但后续构建可能需要重建许多组件。
建议
对于大多数应用程序,将 Buildroot 用于您的下一个嵌入式 Linux 设计是一个不错的选择。如果您的设计需要多种硬件类型或其他差异,您可能需要重新考虑,因为同步多个配置的复杂性,但是,对于由单个设置组成的系统,Buildroot 可能会为您很好地工作。
OpenWRT/LEDE
OpenWRT 项目的启动是为了开发用于消费级路由器的自定义固件。您在当地零售商处购买的许多低成本路由器都能够运行 Linux 系统,但可能不是开箱即用。这些路由器的制造商可能不会频繁提供更新来解决新的威胁,即使他们这样做,安装更新映像的机制也很困难且容易出错。 OpenWRT 项目为许多已被制造商遗弃的设备生成更新的固件映像,并为这些设备赋予新的生命。
OpenWRT 项目的主要交付成果是大量商业设备的二进制映像。有可通过网络访问的软件包存储库,允许设备最终用户向其系统添加新软件。 OpenWRT 构建系统是一个通用构建系统,它允许开发人员创建自定义版本以满足他们自己的需求并添加新软件包,但其主要重点是目标二进制文件。
优点
如果您正在寻找商业设备的替代固件,则应将 OpenWRT 列入您的选项列表。它维护良好,并且可以保护您免受制造商固件无法解决的问题的影响。您还可以添加额外的功能,使您的设备更有用。
如果您的嵌入式设计以网络为中心,则 OpenWRT 是一个不错的选择。网络应用程序是 OpenWRT 的主要用例,您可能会在其中找到许多此类软件包。
缺点
OpenWRT 对您的设计施加了重要的策略决策(相对于 Yocto 和 Buildroot)。如果这些决策不符合您的设计目标,您可能需要进行非平凡的修改。
在已部署的设备群中允许基于软件包的更新很难管理。根据定义,这会导致与您的 QA 团队测试的软件负载不同的软件负载。此外,很难保证大多数软件包管理器的原子安装,并且不合时宜的断电可能会使您的设备处于不可预测的状态。
建议
OpenWRT 是业余爱好者项目或重用商业硬件的不错选择。它也是网络应用程序的不错选择。如果您需要对默认设置进行大量自定义,您可能更喜欢 Buildroot 或 Yocto。
桌面发行版
设计嵌入式 Linux 系统的一种常用方法是从桌面发行版(例如 Debian 或 Red Hat)开始,并删除不需要的组件,直到安装的映像适合您的目标设备的 footprint。这是流行的 Raspbian 发行版用于 Raspberry Pi 平台的做法。
优点
这种方法的主要优点是熟悉性。通常,嵌入式 Linux 开发人员也是桌面 Linux 用户,并且精通他们选择的发行版。在目标上使用类似的环境可能允许开发人员更快地开始工作。根据选择的发行版,可以使用标准软件包工具(例如 apt 和 yum)安装许多其他工具。
可以将显示器和键盘连接到您的目标设备,并在那里直接完成所有开发工作。对于嵌入式领域的新手开发人员来说,这可能是一个更熟悉的环境,并且无需配置和使用棘手的交叉开发设置。
大多数桌面发行版可用的软件包数量通常大于先前讨论的特定于嵌入式的构建器可用的软件包数量。由于更大的用户群和更广泛的用例,您可能能够找到您的应用程序所需的所有运行时软件包,这些软件包已经构建好并可以使用。
缺点
将目标用作您的主要开发环境可能会很慢。运行编译器工具是一项资源密集型操作,并且取决于您构建的代码量,可能会影响您的性能。
在某些例外情况下,桌面发行版并非旨在适应低资源系统,并且可能难以充分修剪您的目标映像。同样,桌面环境中期望的工作流程对于大多数嵌入式设计来说并不理想。以这种方式获得可重现的环境很困难。手动添加和删除软件包容易出错。可以使用特定于发行版的工具(例如基于 Debian 的系统的 debootstrap)编写脚本来实现此目的。为了进一步提高 可重现性,您可以使用配置管理工具,例如 CFEngine(完全公开,它是由我的雇主 Mender.io 制作的)。但是,您仍然受发行版提供商的支配,他们将更新软件包以满足他们的需求,而不是您的需求。
建议
对于您计划推向市场的产品,请注意这种方法。对于业余爱好者应用程序来说,这是一个很好的模型;但是,对于需要支持的产品,这种方法可能会带来麻烦。虽然您可能会更快地入门,但从长远来看,这可能会花费您时间和精力。
其他注意事项
此讨论侧重于构建系统的功能,但通常存在可能影响您决策的非功能性要求。如果您已经选择了您的片上系统 (SoC) 或电路板,您的选择很可能将由供应商决定。如果您的供应商为给定的系统提供电路板支持包 (BSP),则使用它通常会节省大量时间,但请研究 BSP 的质量,以避免在以后的开发周期中出现问题。
如果您的预算允许,您可能需要考虑为您的目标操作系统使用商业供应商。有些公司将为此处讨论的许多选项提供经过验证和支持的配置,并且除非您具有嵌入式 Linux 构建系统的专业知识,否则这是一个不错的选择,并且可以让您专注于您的核心竞争力。
作为替代方案,您可以考虑为您的开发人员提供商业培训。这可能比商业操作系统提供商便宜,并且可以让您更加自给自足。这是快速克服您选择的构建系统基础知识的学习曲线的快捷方法。
最后,您可能已经有一些开发人员具有一个或多个系统的经验。如果您有喜欢某个系统的工程师,那么在您做出决定时肯定值得考虑这一点。
总结
构建嵌入式 Linux 系统有很多选择,每种选择都有优点和缺点。优先考虑设计的这一部分至关重要,因为在流程后期切换系统成本极高。除了这些选项之外,新的系统也一直在开发中。希望本次讨论将为审查新系统(以及此处提到的系统)提供一些背景信息,并帮助您为您的下一个项目做出可靠的决策。
1 条评论