为了账号安全,请及时绑定邮箱和手机立即绑定

什么是应用程序二进制接口(ABI)?

/ 猿问

什么是应用程序二进制接口(ABI)?

拉风的咖菲猫 2019-07-25 14:41:51

什么是应用程序二进制接口(ABI)?

我从未明白ABI是什么。请不要指向维基百科的文章。如果我能理解它,我就不会在这里张贴这么长的帖子。

这是我对不同界面的看法:

电视遥控器是用户和电视之间的接口。它是一个现有实体,但本身无用(不提供任何功能)。遥控器上每个按钮的所有功能都在电视机中实现。

接口:它是间“现有实体”层 functionalityconsumer的该功能。接口本身不起作用。它只是调用后面的功能。

现在取决于用户是谁,有不同类型的接口。

命令行界面(CLI)命令是现有实体,消费者是用户和功能所在。

functionality: 我的软件功能解决了我们描述这个界面的一些目的。

existing entities: 命令

consumer: 用户

图形用户界面(GUI)窗口,按钮等是现有实体,消费者再次是用户和功能所在。

functionality: 我的软件功能解决了我们描述这个界面的一些问题。

existing entities: 窗口,按钮等..

consumer: 用户

应用程序编程接口(API)函数(或更正确的)接口(在基于接口的编程中)是现有实体,这里的消费者是另一个程序而不是用户,并且该层后面的功能也是如此。

functionality: 我的软件功能解决了我们描述这个界面的一些问题。

existing entities: 函数,接口(函数数组)。

consumer: 另一个程序/应用程序

应用程序二进制接口(ABI)这是我的问题开始的地方。

functionality: ???

existing entities: ???

consumer: ???

  • 我用不同的语言编写了软件并提供了不同类型的接口(CLI,GUI和API),但我不确定我是否提供过任何ABI。

维基百科说:

ABI涵盖了诸如此类的详细信息

  • 数据类型,大小和对齐方式;

  • 调用约定,它控制函数参数的传递方式并返回检索的值;

  • 系统调用号码以及应用程序应如何向操作系统进行系统调用;

其他ABI标准化细节,如

  • C ++名称错误,

  • 异常传播,和

  • 在同一平台上调用编译器之间的约定,但不需要跨平台兼容性。

  • 谁需要这些细节?请不要说操作系统。我知道汇编编程。我知道链接和加载是如何工作的。我确切地知道里面发生了什么。

  • 为什么C ++名称输入?我以为我们正在谈二进制。语言为什么会进来?

无论如何,我已经下载了[PDF] System V Application Binary Interface Edition 4.1(1997-03-18),看看它究竟包含了什么。好吧,大部分都没有任何意义。

  • 为什么它包含两章(第4和第5章)来描述ELF文件格式?实际上,这些是该规范中仅有的两个重要章节。其余章节是“处理器特定的”。无论如何,我认为这是一个完全不同的话题。请不要说ELF文件格式规范 ABI。根据定义,它不符合接口的条件。

  • 我知道,因为我们谈论的水平很低,所以必须非常具体。但我不确定它是如何“指令集架构(ISA)”具体的?

  • 我在哪里可以找到Microsoft Windows的ABI?

所以,这些是困扰我的主要问题。


查看完整描述

3 回答

?
www说

理解“ABI”的一种简单方法是将其与“API”进行比较。

您已经熟悉API的概念。如果您想使用某些库或操作系统的功能,您将使用API。API由数据类型/结构,常量,函数等组成,您可以在代码中使用它们来访问该外部组件的功能。

ABI非常相似。可以将其视为API的编译版本(或作为机器语言级别的API)。编写源代码时,可以通过API访问库。编译代码后,您的应用程序将通过ABI访问库中的二进制数据。ABI定义了编译的应用程序将用于访问外部库的结构和方法(就像API一样),仅在较低级别上。

对于使用外部库的应用程序,ABI很重要。如果构建程序以使用特定库并且稍后更新该库,则您不希望必须重新编译该应用程序(并且从最终用户的角度来看,您可能没有源代码)。如果更新的库使用相同的ABI,那么您的程序将不需要更改。即使内部工作可能已经改变,库的接口(这是您的所有程序真正关心的)也是相同的。具有相同ABI的库的两个版本有时被称为“二进制兼容”,因为它们具有相同的低级接口(您应该能够用新版本替换旧版本并且没有任何重大问题)。

有时,ABI的变化是不可避免的。发生这种情况时,任何使用该库的程序都将无法运行,除非重新编译它们以使用新版本的库。如果ABI发生变化但API没有变化,则新旧库版本有时称为“源兼容”。这意味着虽然为一个库版本编译的程序不能与另一个库版本一起工作,但为一个编写的源代码在重新编译时将适用于另一个。

出于这个原因,图书馆编写者倾向于试图保持他们的ABI稳定(以尽量减少中断)。保持ABI稳定意味着不改变函数接口(返回类型和数量,类型和参数的顺序),数据类型或数据结构的定义,定义的常量等。可以添加新函数和数据类型,但现有函数和数据类型必须保持不变相同。如果将16位数据结构字段扩展为32位字段,则使用该数据结构的已编译代码将无法正确访问该字段(或任何后续字段)。访问数据结构成员在编译期间转换为内存地址和偏移量,如果数据结构发生变化,那么这些偏移量将不会指向代码期望它们指向的内容,并且结果最多也是不可预测的。

除非您希望人们使用汇编与您的代码进行交互,否则ABI不一定是您明确提供的内容。它也不是特定于语言的,因为(例如)C应用程序和Pascal应用程序在编译后将使用相同的ABI。

编辑:关于您在SysV ABI文档中关于ELF文件格式章节的问题:包含此信息的原因是因为ELF格式定义了操作系统和应用程序之间的接口。当您告诉操作系统运行程序时,它希望程序以某种方式格式化(例如)期望二进制文件的第一部分是包含特定内存偏移量的某些信息的ELF头。这是应用程序将有关其自身的重要信息传达给操作系统的方式。如果以非ELF二进制格式(例如a.out或PE)构建程序,那么期望ELF格式的应用程序的操作系统将无法解释二进制文件或运行应用程序。

IIRC,Windows目前使用可移植可执行(或PE)格式。该维基百科页面的“外部链接”部分中有链接,其中包含有关PE格式的更多信息。

另外,关于你关于C ++名称修改的注释:ABI可以为C ++编译器定义一种“标准化”方式,以便为了兼容性而进行名称修改。也就是说,如果我创建一个库并且您开发了一个使用该库的程序,那么您应该能够使用与我不同的编译器,而不必担心由于不同的名称修改方案而导致的二进制文件不兼容。如果您要定义新的二进制文件格式或编写编译器或链接器,那么这只是有用的。


查看完整回答
反对 回复 2019-07-25
?
慕圣8478803

如果您知道程序集以及操作系统级别的工作方式,那么您就符合某个ABI。ABI管理诸如如何传递参数,放置返回值的位置。对于许多平台,只有一个ABI可供选择,在这些情况下,ABI只是“如何工作”。

但是,ABI也管理如何在C ++中布置类/对象。如果您希望能够跨模块边界传递对象引用,或者如果要混合使用不同编译器编译的代码,则这是必需的。

此外,如果您有一个可以执行32位二进制文件的64位操作系统,则32位和64位代码将具有不同的ABI。

通常,链接到同一可执行文件的任何代码都必须符合相同的ABI。如果要使用不同的ABI在代码之间进行通信,则必须使用某种形式的RPC或序列化协议。

我认为你很难将不同类型的接口挤入一组固定的特性中。例如,界面不一定必须拆分为消费者和生产者。接口只是两个实体交互的约定。

ABI可以(部分)与ISA无关。某些方面(例如调用约定)依赖于ISA,而其他方面(例如C ++类布局)则不依赖于ISA。

定义良好的ABI对于编写编译器的人来说非常重要。如果没有明确定义的ABI,就不可能生成可互操作的代码。

编辑:一些说明澄清:

  • ABI中的“二进制”不排除使用字符串或文本。如果要链接导出C ++类的DLL,则必须对其中的方法和类型签名进行编码。这就是C ++名称变形的地方。

  • 你从未提供过ABI的原因是绝大多数程序员都不会这样做。ABI由设计平台(即操作系统)的人提供,很少有程序员有权设计广泛使用的ABI。



查看完整回答
反对 回复 2019-07-25

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信