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

时间:2014-10-10 10:19:44

标签: operating-system programming-languages system-calls

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

其他语言如何实现?

2 个答案:

答案 0 :(得分:5)

您的初始前提是错误的:在Linux上,当您在C代码中呼叫open(2)时,您进行系统调用,而是调用{{}提供的函数{3}}(或者你的程序正在使用的C标准库的任何实现 - 还有其他的,例如glibcμLibc等),并且该函数的实现实际上使得系统调用 - 正确地进行必要的设置以符合目标架构的dietlibc约定。

你可以在C中直接创建一个系统调用 ,但它与调用open()会有很大的不同。一些指针是ABIthis

回顾一下:this(指明open(2)和朋友应该如何表现和行为的那个)只指定一个相当高级的接口(就C编程语言而言)但具体的内核实现这个标准有自己的系统调用和约定如何调用它们(在同一内核的H / W架构之间有所不同),它是C“标准库”“知道”如何调用一个具体的内核通过适当的设置确保调用POSIX API的C程序最终使用适当的系统调用。换句话说,在Linux上运行的典型C应用程序中,您不会直接处理系统调用 - 您只会有一个印象。

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

  • 依赖于目标平台的libc并依靠它来调解它们与内核之间的关系。
  • 直接实现调用目标内核的必要系统调用。

我所知道的大多数语言/运行时采用第一种方式(Python,Java仅举几例),而其中一些采用其他路由 - 例如the POSIX standard的参考实现,{{ 3}}

更新2014-10-13 回答@tan评论中提出的问题:

  

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

基本上,该方法类似于系统调用的方法:对于C硬件架构和C编译器的每个组合,再次调用C也是标准化的。有关详细信息和更多信息,请参阅Go

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

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

    也就是说,您的软件唯一必须关注的是正确安排其数据由C端操纵。一个例子是确保传递给C端的内存块在C端完成之前不会被垃圾收集。

    Go编程语言的Free Pascal就是这种方法的一个例子。

  • 调用软件使用一个库(通常用C语言编写,以利用C编译器可以为它做的事情),它能够加载C动态库并正确调用其执行所有必需数据设置的函数。有关详细信息,请参阅this discussion

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

我很难将Java的JNI和.NET的P/Invoke分类为这两个类别。可能是他们坐在中间的某个地方。

答案 1 :(得分:2)

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

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

使用某些语言,您可以以类似于C / C ++的方式将本机DLL直接加载到应用程序中。在使用ctypes的Python的情况下也是如此。

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

希望稍微澄清一下:)如果你想要任何其他特定于语言的详细信息,请告诉我。