ABI与API定义及区别
一.概述
1.定义
ABI(Application Binary Interface,应用二进制接口)和 API(Application Programming Interface,应用程序接口)是软件工程中两个核心概念,本质区别在于作用层级与交互对象。
二.关键区别详解
1.作用层级不同
2.变更影响对比
(1)API 变更示例:
// v1.0 API
void process_data(int input);
// v2.0 API (变更参数类型)
void process_data(float input); // 重新编译即可适配
→ 只需修改调用方代码并重新编译。
(2)ABI 变更示例:
修改结构体字段顺序(影响内存布局):
// v1.0 ABI
struct Point { int x; int y; }; // 内存: [x][y]
// v2.0 ABI (字段顺序变化)
struct Point { int y; int x; }; // 内存: [y][x]
→ 旧版二进制库调用新版结构体将内存解释错误,必须重新编译所有依赖模块。
三.技术要素对比
1.API 包含的要素
函数/方法名称(如 open())
参数类型与顺序(如 int open(const char *path, int flags))
返回值类型(如 ssize_t read(int fd, void *buf, size_t count))
错误处理约定(如返回 -1 表示错误)
2.ABI 包含的要素
(1)调用约定(Calling Convention)
参数传递顺序(寄存器 vs 栈)
返回值存储位置(如 x86: eax;ARM: r0)
栈清理责任方(调用者清理 vs 被调用者清理)
assembly:
; x86_64 System V ABI 示例 (Linux)
; 参数顺序: rdi, rsi, rdx, rcx, r8, r9 → 栈
mov rdi, 123 ; 第一个参数
call function ; 调用函数
(2)数据表示规范
数据类型大小(如 long 在 Linux x86_64 = 8字节)
结构体/联合体的内存对齐(如 struct { char c; int i; } 对齐到4字节)
字节序(大端/小端)
(3)系统调用机制
系统调用号(如 x86: sys_open 对应 0x05)
陷入内核的方式(如 int 0x80 / syscall)
(4)异常处理
栈回溯格式(DWARF调试信息)
信号处理帧(Signal Frame)结构
四.实际场景示例
1.场景1:Linux 动态库兼容性
API 兼容:
libcurl.so.4 → libcurl.so.5 的函数签名不变,仅内部优化 → 无需重编译应用程序。
ABI 破坏:
libpython3.8.so → libpython3.9.so 修改了 PyObject 结构布局 → Python 3.8 编译的C扩展无法加载到3.9环境。
2.场景2:跨平台开发
API 一致:
使用POSIX API(如 pthread_create)可在Linux/macOS源码级兼容。
ABI 差异:
相同源码在Linux(System V ABI)和Windows(Microsoft ABI)编译后二进制不兼容:
五.总结
1.核心区别与关联
2.关键结论:
API 是开发者之间的契约 → 解决“如何正确调用功能”
ABI 是机器之间的契约 → 解决“如何正确执行指令”
稳定性要求:API 可迭代演进,ABI 必须严格保持兼容,否则引发“DLL Hell”等问题。