非C语言如何与操作系统交互?

tan*_*tan 2 operating-system programming-languages system-calls

在linux上,例如,我们可以使用OS提供的api(打开/关闭/读/写)直接进行系统调用,也可以使用C语言中的libc提供的功能(fopen等)。

用其他语言如何实现?

kos*_*tix 6

您最初的前提是错误的:在Linux上,当您open(2)在C代码中调用(例如)时,您不是在进行系统调用,而是在调用glibc(或您的程序恰巧使用的C标准库的任何实现所提供的功能,还有其他诸如μLibcDietlibc等),该功能的实现实际上使syscall正确地进行了必要的设置,以符合目标体系结构的ABI约定。

您可以直接在C语言中进行syscall ,但是它看起来与仅调用它有很大不同open()。一些指针是thisthis

回顾一下:POSIX标准(指定了open(2)朋友的外观和行为方式)仅指定了一个相当高级的接口(就C编程语言而言),但是实现此标准的具体内核具有其自己的系统调用集。以及有关如何调用它们的约定(在同一内核的H / W体系结构之间有所不同),这是C标准库,它“知道”如何调用具体的内核,从而确保调用POSIX API的C程序最终使用通过适当的设置进行适当的系统调用。换句话说,在Linux上运行的典型C应用程序中,您并没有直接处理syscalls,而是给您留下了深刻的印象。

其他语言/运行时基本上有两种选择:

  • 依赖于目标平台,libc并依靠它在目标平台和内核之间进行中介。
  • 直接实现对目标内核的必要系统调用。

我知道的大多数语言/运行时都采用第一种路线(Python,Java等),而其中一些采用另一种路线-例如,GoFree Pascal的参考实现。

更新2014-10-13回答来自@tan的评论的问题:

因此,如果采用第一个路由(libc),那么如何从python / java调用libc函数?

基本上,该方法类似于syscall的方法:再次,对于C的调用是针对硬件体系结构和C编译器的每种组合进行某种标准化的。有关更多信息和更多指针,请参见此讨论

请注意,实际上,大多数能够与C代码连接的软件都使用以下两种方法之一:

  • 它本身是用C编写的,因此实现对外部C代码中的动态或静态链接的调用是由编译调用软件的编译器处理的。

    也就是说,您的软件唯一需要关注的是正确安排其数据由C端进行操作。一个示例是确保传递给C端的内存块在C端完成处理之前不会被垃圾回收。

    Go编程语言的cgo子系统就是这种方法的一个例子。

  • 调用软件使用一个库(通常用C编写,以利用C编译器可以完成的工作),该库能够加载C动态库并正确调用其执行所有必需数据设置的功能。请参阅以获取更多信息。

    Python的ctypes模块正是实现了这种方法。

对我来说,将Java JNI和.NET P/Invoke分为两类比较困难。可能是他们坐在中间的某个地方。


Jus*_*tin 2

在其他语言中,这通常(总是?)通过本地函数调用的包装器来实现。事实上,它看起来是这样的。LanguageX -> 包装器 -> 本机代码(C/C++)

有时,这个包装器采用整个框架的形式,例如Java 的JNI。这也适用于 Groovy 脚本。

使用某些语言,您可以以类似于 C/C++ 的方式将本机 DLL 直接加载到应用程序中。对于使用ctypes的 Python 来说确实如此。

其他时候,根本不需要本机调用,并且可以使用您选择的语言直接生成相同的结果。跨平台 GUI 工具包是一个可以完全替代本机操作系统调用的小例子。例如 GTK 或 QT

希望这能让事情变得更清楚:) 如果您需要任何其他特定于语言的详细信息,请告诉我。