LWN: glibc里的系统调用封装函数
System-call wrappers for glibc
By Jonathan Corbet
LPC
glibc,又名GNU C Library,过去长久以来大家对它的印象都是不愿意为Linux新加的系统调用增加wrapper(封装函数)。因此,其实有很多系统调用多年来一直都没有得到glibc的支持。不过情况在转变。2019 Linux Plumbers Conference会议的Toolchain microconference上,Maciej Rozycki介绍了一下glibc关于system-call wrapper的最新观点,不过也又一次提醒大家,要加一个新的系统调用,会有非常多的工作要做。
Rozycki和Dmitry Levin共同主持了这个环节,不过他并不是负责这部分工作的人,只是代真正的负责人Florian Weimer来做这个介绍,因为Weimer没能赶来参加这个会议。
背景信息:user space运行的应用程序并不是直接调用进入kernel的,而是调用一个wrapper函数,由wrapper函数来决定调用哪个系统调用。通常wrapper函数只是把参数排列好,做些准备,然后就trap进kernel mode。某些情况下,wrapper提供的接口可能跟kernel提供的差异非常大。
其实也并不是一定要提供一个专门的wrapper函数的,application总是可以通过直接调用syscall()来调用任何系统调用的。不过,Rozycki认为还是尽量需要让application避免使用syscall(),例如syscall()不会检查传入参数的类型。system-call number(系统调用编号)在每个体系架构上都不一样,并且不同体系架构的ABI可能也是有区别的。这些导致很难用syscall()调用来实现可移植性强的代码。此外,POSIX线程和线程取消功能也会导致一些问题。所以最好是能把application会用到的系统调用都封装到C库函数里去。
所以glibc项目的做法现在有了改变,此前它不愿意接受新的系统调用wrapper,现在愿意接受了。不过没法一下子把所有syscall都加进来,每个新加的syscall都会需要清理掉一些障碍,例如在glibc manual里写清楚文档,并且完成copyright-assignment文档,毕竟glibc是Free Software Foundation的项目。这里引起了大家的热烈讨论,关于syscall wrapper的copyright需求,是否在承认ABI的copyright?会场讨论下来居然没有结论。Rozycki提到最后一点障碍,就是缺少reviewer,这是其他自由软件项目的共同问题。
glibc项目采取的策略是尽量避免模拟系统调用。如果某个系统调用不可用,那么glibc就会返回ENOSYS结束。因为模拟出来的系统调用,很容易出现各种意外错误,所以只会用在一些不重要的场景下。glibc也要求wrapper的名字要跟体系架构无关,否则的话就会是维护者的噩梦了。可能的话,glibc开发者还希望能把某个syscall在所有体系结构的支持都在同一个release版本里面实现出来,否则会需要人为维护支持状态,很麻烦的。
glibc开发者也从以前的经验得出一个教训(kernel开发者也有同感):multiplexing system call的支持非常麻烦。这会导致参数类型的检测变得非常困难,尤其是要支持可变参数数量(有些函数做不同操作的时候接受不通参数)的话。出于这个原因,大家可以看到futex()或者bpf()这种系统调用很可能会被glibc实现成很多个独立wrapper,每种行为都有一个特制的wrapper。
还有一些ABI相关的规则。比如ssize_t或者size_t应该备用在所有buffer size的场合,无论kernel里面用的是什么类型。这样能够让这个参数的用途更明晰。flag不应该用long类型,因为32位架构系统上如何处理高32位是一个没有定论的行为。错误值应该利用errno来返回出来,除了POSIX线程调用是例外。glibc开发者还希望每个新加的系统调用能有一个单独的kernel UAPI头文件来放置相关的类型和常量,这样在include时就能只包含相关信息,而不会引入太多无关的声明。
Rozycki总结时提出,希望大家能更好的跟各个C函数库项目配合。例如,所有跟ABI改动相关的patch,都应该抄送C函数库相关开发者。不过我倒是发现有时候C函数库开发者对kernel社区提出的要求跟这个很不一样,今后应该如何避免呢?听众中有个建议是应该有更多glibc开发者加入linux-api mailing list,还有个建议是所有改动都加上Florian :)
结束之前,Christian Brauner总结指出,此前要给glibc加入新改动是很麻烦的,不过最近几年已经有了不少变化。哪怕是不起眼的gettid()系统调用,在经过了长期激烈的争论之后,也已经合入了,很多人都表示很惊奇。glibc社区现在跟kernel社区互动更加频繁,希望这个变化能一直保持下去,并且kernel社区也能投桃报李。
[Your editor thanks the Linux Foundation, LWN's travel sponsor, for supporting his travel to this event.]
全文完
LWN文章遵循CC BY-SA 4.0许可协议。
热烈欢迎转载以及基于现有协议修改再创作~
长按下面二维码关注:Linux News搬运工,希望每周的深度文章以及开源社区的各种新近言论,能够让大家满意~