今天我们来看看Linux中形形色色的接口
如果将内核比作一座工厂,那么Linux中众多的接口就是通往这个巨大工厂的高速公路。这条路要足够坚固,禁得起各种破坏(Robust)。要能跑得了运货的卡车,还要能升降飞机。(Compatible)。当然了这条路要越宽越好(Performant)。如下图所标,Linux中有四种类型的接口。位于内核和用户之间的API(应用程序接口)和ABI(应用二进制接口)。内核内部的API和ABI。下面我们逐条的来看看这些接口。
内核-用户接口有内核系统调用和GNU C Library (glibc)的包装例程(wrap subroutines)构成。Linux API开发的目标是给POSIX标准提供一个相对兼容的,程序健壮性强的,高性能的实现,同时又实现一些Linux特有的标准。
1.1 Linux内核的系统调用接口
系统调用接口包含了内核中所有已经实现的和可使用的系统调用。
1.2 C标准库标准库是对系统调用的封装,用于给用户提供一个简单易用的用户态接口。其中最为熟知的就是GNU C Library(glibc),还有为嵌入式和移动设备使用的uClibc。
1.3对POSIX的补充
还有一些接口是Linux特有的,比如:
Cgroup子系统,该子系统包含cgroup系统调用和libcgroup。
Futex,epoll,dnotify,inotify,Fanotify等系统调用。
ABI是一系列约定的集合,例如GNU/Linux,FreeBSD约定函数调用的头六个整型参数放在寄存器RDI, RSI, RDX, RCX, R8和R9上;同时XMM0到XMM7用来放置浮点变元。对于系统调用,R10用来替代RCX。其他额外的参数推入栈,返回值保存在RAX中。[1] 可以说调用惯例(calling convention)就是ABI。因此,ABI是和具体CPU架构和OS相关的。
具体而言,ABI包含以下内容:[3]
1. 一个特定的处理器指令集
2. 函数调用惯例
3. 系统调用方式
4. 可执行文件的格式(ELF,PE)
那么,究竟我们为什么要纠结于ABI这个概念呢?答案是为了兼容,只要OS遵守相同的ABI规范,那么不同的应用就可以实现向前兼容,再也不用担心版本升级后,旧版本的应用不能运行了。
内核API主要是内核中标记为 “EXPORT_SYMBOL”的函数。这些函数主要是为了内核模块的编写而提供的。收到内核版本迭代的影响,内核API并不稳定。2.x版本内核的模块可能在3.x版本上就无法使用。
内核的abi和linux abi的定义类似,再次不再赘述。
在某些情况下,内核过于底层,开发者需要更高一层的抽象。于是出现了类似Mesa 3D的为图形驱动开发而生的API。
[1]
https://en.wikipedia.org/wiki/Linux_kernel_interfaces
所有图的来源
[2]
https://abi-laboratory.pro/index.php?view=abi-view
[3] https://en.wikipedia.org/wiki/Application_binary_interface
abi的wiki
[4] https://zh.wikipedia.org/wiki/X86%E8%B0%83%E7%94%A8%E7%BA%A6%E5%AE%9A
x86调用惯例的中文wiki
[5]
http://laoar.net/blogs/316/
讨论什么是ABI
[6] https://elixir.bootlin.com/linux/latest/source/kernel/sched/wait.c
内核API
[7]
https://stackoverflow.com/questions/2171177/what-is-an-application-binary-interface-abi
讨论什么是ABI
查看"Linux阅码场"精华技术文章请移步:
Linux阅码场原创精华文章汇总
扫描二维码关注"Linux阅码场"