2024-08-15 09:00:00

API和ABI的区别

我是Linux系统编程的新手,在阅读时遇到了API和ABI Linux系统编程。

API的定义:

API定义了接口 一个软件进行通信 与另一个在源级。

ABI的定义:

而API定义了一个源 接口时,ABI定义了 两个之间的低级二进制接口 或者更多的软件 特定的体系结构。它定义了 应用程序如何与 本身,应用程序如何交互 与内核,以及如何一个 应用程序与库交互。

程序如何在源级进行通信?什么是源级别?它是否与源代码有关?或者库的源代码包含在主程序中?

我所知道的唯一区别是API主要由程序员使用,而ABI主要由编译器使用。


当前回答

API:应用程序接口

这是您从应用程序/库中公开的公共类型/变量/函数集。

在C/ c++中,这是在应用程序附带的头文件中公开的内容。

ABI:应用程序二进制接口

这就是编译器构建应用程序的方式。 它定义了一些东西(但不限于):

参数如何传递给函数(寄存器/堆栈)。 谁从堆栈中清除参数(调用方/被调用方)。 返回值的位置。 异常如何传播。

其他回答

我先回答你们的具体问题。

1.什么是源级别?它是否与源代码有关?

Yes, the term source level refers to the level of source code. The term level refers to the semantic level of the computation requirements as they get translated from the application domain level to the source code level and from the source code level to the machine code level (binary codes). The application domain level refers what end-users of the software want and specify as their computation requirements. The source code level refers to what programmers make of the application level requirements and then specify as a program in a certain language.

程序如何在源级进行通信?或者库的源代码包含在主程序中?

语言API专门指一种语言需要(指定)(即接口)用该语言编写可重用模块的所有东西。可重用程序符合这些接口(API)要求,以便在相同语言的其他程序中重用。每次重用都需要符合相同的API需求。所以,“沟通”这个词指的是重用。

Yes, source code (of a reusable module; in the case of C/C++, .h files ) getting included (copied at pre-processing stage) is the common way of reusing in C/C++ and is thus part of C++ API. Even when you just write a simple function foo() in the global space of a C++ program and then call the function as foo(); any number of times is reuse as per the C++language API. Java classes in Java packages are reusable modules in Java. The Java beans specification is also a Java API enabling reusable programs (beans) to be reused by other modules ( could be another bean) with the help of runtimes/containers (conforming to that specification).

关于语言API和ABI之间的区别,以及面向服务的API与语言API的区别,我在SO方面的回答应该会有所帮助。

这是我的外行解释:

API——考虑包含文件。它们提供编程接口。 ABI——想想内核模块。当你在某个内核上运行它时,它必须同意如何在没有包含文件的情况下进行通信,即作为低级二进制接口。

让我举一个具体的例子,说明在Java中ABI和API是如何不同的。

ABI不兼容的更改是如果我将方法a# m()从将字符串作为参数更改为String…论点。这不是ABI兼容的,因为您必须重新编译调用它的代码,但它是API兼容的,因为您可以通过重新编译来解析它,而无需在调用方中更改任何代码。

这里有一个例子。我的Java库有类A

    // Version 1.0.0
    public class A {
        public void m(String string) {
            System.out.println(string);
        }
    }

我有一个类使用这个库

    public class Main {
        public static void main(String[] args) {
            (new A()).m("string");
        }
    }

现在,库作者编译了他们的类A,我编译了我的类Main,一切都运行得很好。想象一个新版本的a出现了

    // Version 2.0.0
    public class A {
        public void m(String... string) {
            System.out.println(string[0]);
        }
    }

如果我只是使用新编译的类A,并将其与之前编译的类Main一起删除,那么在试图调用该方法时就会得到异常

Exception in thread "main" java.lang.NoSuchMethodError: A.m(Ljava/lang/String;)V
        at Main.main(Main.java:5)

如果我重新编译Main,这是固定的,所有工作再次。

ABI指的是目标文件/库和最终二进制文件的布局,从成功链接、加载和执行某些二进制文件的角度出发,而不会因为二进制文件不兼容而出现链接错误或逻辑错误。

The binary format specification (PE, COFF, ELF, .obj, .o, .a, .lib (import library, static library), .NET assembly, .pyc, COM .dll): the headers, the header format, defining where the sections are and where the import / export / exception tables are and the format of those The instruction set used to encode the bytes in the code section, as well as the specific machine instructions The actual signature of the functions and data as defined in the API (as well as how they are represented in the binary (the next 2 points)) The calling convention of the functions in the code section, which may be called by other binaries (particularly relevant to ABI compatibility being the functions that are actually exported) The way data is represented and aligned in the data section with respect to its type (particularly relevant to ABI compatibility being the data that is actually exported) The system call numbers or interrupt vectors hooked in the code The name decoration of exported functions and data Linker directives in object files Preprocessor / compiler / assembler / linker flags and directives used by the API programmer and how they are interpreted to omit, optimise, inline or change the linkage of certain symbols or code in the library or final binary (be that binary a .dll or the executable in the event of static linking)

The bytecode format of .NET C# is an ABI (general), which includes the .NET assembly .dll format. The virtual machine that interprets the bytecode has a specific ABI that is C++ based, where types need to be marshalled between native C++ types that the native code's specific ABI uses and the boxed types of the virtual machine's ABI when calling bytecode from native code and native code from bytecode. Here I am calling an ABI of a specific program a specific ABI, whereas an ABI in general, such as 'MS ABI' or 'C ABI' simply refers to the calling convention and the way structures are organised, but not a specific embodiment of the ABI by a specific binary that introduces a new level of ABI compatibility concerns.

An API refers to the set of type definitions exported by a particular library imported and used in a particular translation unit, from the perspective of the compiler of a translation unit, to successfully resolve and check type references to be able to compile a binary, and that binary will adhere to the standard of the target ABI, such that if the library that actually implements the API is also compiled to a compatible ABI, it will link and work as intended. If the API is updated the application may still compile, but there will now be a binary incompatibility and therefore a new binary needs to be used.

API包括:

函数,变量,类,对象,常量,它们的名称,类型和定义,以正确的语法和语义方式编码 这些函数实际做什么,以及如何在源语言中使用它们 需要包含的源代码文件/为了使用它们而需要链接到的二进制文件,以及它们的ABI兼容性

您的程序(源代码)可以使用提供适当API的模块进行编译。

您的程序(二进制)可以在提供适当ABI的平台上运行。

API限制了类型定义、函数定义、宏,有时还有库应该公开的全局变量。

ABI限制了一个“平台”应该为您的程序运行提供什么。我喜欢从三个层面来考虑:

处理器级——指令集,调用约定 内核级——系统调用约定,特殊的文件路径约定(例如Linux中的/proc和/sys文件),等等。 操作系统级别——对象格式、运行时库等。

考虑一个名为arm-linux-gnueabi-gcc的交叉编译器。“arm”表示处理器架构,“linux”表示内核,“gnu”表示其目标程序使用gnu的libc作为运行时库,不同于arm-linux-androideabi-gcc使用Android的libc实现。