实现嵌入式应用程序的过程很好理解:
代码(用 C/C++/汇编或其他语言)编写并放置在许多文件(模块)中。
每个模块都经过编译/组装以创建可重定位的目标文件。该文件包含目标处理器的机器指令,但地址信息尚未提交。
所有模块都使用链接器(有时称为链接器/定位器)集成在一起。此过程解析所有内存引用并生成一个绝对目标文件:最终系统内存的图像。
这种观点有些简单化,因为还有许多其他细微差别:
增量链接可用于将一个或多个可重定位对象连接在一起以形成单个可重定位对象。
可以调整链接/定位过程,以便代码存储在一个地方,但地址解析为在另一个地址执行,已被引导加载程序复制到那里。
可以将可重定位的目标文件链接在一起是产生目标模块库的一种特殊方式。
“图书馆”一词在各种情况下被使用和滥用。它的含义在这里定义明确。可以将库文件连同可重定位的目标文件一起提供给链接器。它的功能是解析可重定位目标文件未提供的符号(通常是函数名)。例如,如果您在一个模块中的代码调用了函数MyFun()并且在另一个模块中有此函数的定义,那么一切都很好。如果链接器没有找到这个函数,就会产生错误。但是,如果包含一个库(或多个库),则链接器将首先查找那里以解析符号。如果库包含MyFun()函数,则提取代码并在最终的绝对文件中使用。
图书馆的意义可能并不明显。你可以用一种简单的方式将所有的可重定位文件链接在一起——为什么还要麻烦图书馆呢?这个想法是该库包含大量函数,但链接器仅提取当前应用程序所需的函数。未使用的永远不会从库中提取,因此它们不会耗尽(即浪费)目标内存。
库的主要目的是作为大量可重用代码的存储库。在大型开发团队的项目中,这可能是一种很好的工作方式,在这种情况下共享代码非常有益,“重新发明轮子”是不可取的,但很常见。应仔细规划和记录项目库。设计函数时必须考虑重用:不使用全局数据、干净、定义良好的接口、可重入性等。
开发工具供应商通常会提供针对 C/C++ 标准化的库。它们包含两种类型的功能。显而易见的是开发人员在需要时调用的显式函数——比如printf()。其他库函数是隐式的;它们由编译器生成的代码调用,并提供常用的功能,方便共享。
软件 IP 供应商也可能以库的形式提供他们的产品。实时操作系统 (RTOS) 通常以这种方式分布。这使得 RTOS 可以直接扩展;应用程序中仅包含所需的 RTOS 功能。
库分布的一个问题是它们的“粒度”;可以提取多小的代码?一些库是由大块构建的。这意味着库中的模块可能包含属于特定 RTOS 设施的所有服务功能。因此,例如,使用一个 RTOS 调用对信号量进行操作将导致所有与信号量相关的服务调用函数都包含在应用程序中。一个非常细粒度的库可以与较小的单元一起使用。因此,使用单个服务调用将导致仅包含其代码而不是相关函数的代码。有一个权衡。一个非常细粒度的库会延长链接时间,但目标内存不会浪费在未使用的服务调用函数上。
所有嵌入式软件开发人员都应该了解库的工作方式及其提供的好处。代码的可重用性是高效、高效的代码开发和确保可维护性的关键。
审核编辑:郭婷
全部0条评论
快来发表一下你的评论吧 !