非 c 语言如何与操作系统交互? [英] How do non c languages interact with operating system?

查看:19
本文介绍了非 c 语言如何与操作系统交互?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在linux上(例如),我们可以直接使用OS提供的api(open/close/read/write)进行系统调用,也可以在C语言中使用libc提供的函数(fopen等).

On linux (for example), we can directly make system calls using the api provided by OS (open/close/read/write) or we can use functions provided by libc (fopen etc) in C.

在其他语言中是如何实现的?

How is it achieved in other languages?

推荐答案

你最初的前提是错误的:在 Linux 上,当你调用时,比如说,open(2) 在您的 C 代码中,您不是进行系统调用,而是调用glibc (或任何 C 标准的实现)提供的函数你的程序恰好使用的库——还有其他的,例如 μLibc, dietlibc 等),并且该函数的实现实际上使系统调用——正确地进行必要的设置以符合目标架构的 ABI 约定.

Your initial premises are wrong: on Linux, when you call, say, open(2) in your C code, you're not making the syscall but rather calling the function provided by glibc (or whatever implementation of the C standard library your program happens to be using—there are others, such as μLibc, dietlibc etc), and the implementation of that function actually makes the syscall—properly doing the necessary setup to conform to the target architecture's ABI conventions.

您可以在 C 中直接进行系统调用,但它看起来与仅调用 open() 大不相同;一些指针是 this这个.

You can make a syscall directly in C but it will look much different from just calling open(); some pointers are this and this.

回顾一下:POSIX 标准(指定如何open(2) 和朋友应该看起来和行为)确实只指定了一个相当高级的接口(就 C 编程语言而言)但是实现这个标准的具体内核有自己的系统调用集和关于如何调用它们的约定(在同一内核的硬件架构之间有所不同),它是 C 标准库,它知道"如何调用一个具体的内核,它确保调用 POSIX API 的 C 程序最终使用适当的系统调用和正确的设置.换句话说,在 Linux 上运行的典型 C 应用程序中,您并没有直接处理系统调用——您只是有一种印象.

To recap: the POSIX standard (that one specifying how open(2) and friends should looks like and behave) does only specify a rather high-level interface (in terms of the C programming language) but concrete kernels implementing this standard have their own sets of system calls and conventions on how to call them (which differ between H/W architectures for the same kernel), and it's the C standard library which "knows" how to call out to a concrete kernel which makes sure C programs calling POSIX API end up using appropriate system calls with proper set up. In other words, in a typical C application running on Linux you're not dealing with syscalls directly—you just have an impression you do.

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

Other languages/runtimes basically have two alternatives:

  • 依赖目标平台的libc,并依赖它在它们和内核之间进行调解.
  • 直接实现调用目标内核必要的系统调用.
  • Depend on the target platform's libc and rely on it to mediate between them and the kernel.
  • Directly implement calling the necessary syscalls of the target kernel.

我知道的大多数语言/运行时都采用第一条路线(Python、Java 等等),而其中一些采用另一条路线——例如,GoFree Pascal.

Most of languages/runtimes I'm aware of take the first route (Python, Java to name a few) while some of them take the other route—for instance, the reference implementation of Go, Free Pascal.

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

Update 2014-10-13 answering the question from @tan's comment:

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

So, if the first route (libc) is taken, how are libc functions invoked from python/java?

基本上,该方法类似于系统调用的方法:再次调用 C 语言对于硬件架构和 C 编译器的每种组合都是标准化的.请参阅此讨论了解更多信息和进一步的指示.

Basically, the approach is similar to that of the syscalls: calling into C is, again, sort-of standardized for each combination of hardware architecture and the C compiler. See this discussion for more info and further pointers.

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

Note that in reality, most software which is able to interface with C code uses one of these two approaches:

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

  • It is itself written in C, and hence implementing calling out to dynamically or statically linked in external C code is handled by the compiler which compiled the calling software.

也就是说,您的软件唯一需要关心的是正确地安排它的数据由 C 端操作.一个例子是确保传递给 C 端的内存块在 C 端完成之前不会被垃圾回收.

That is, the only thing your software must be concerned of is properly arranging for its data to be manipulated by the C side. One example is making sure a block of memory passed to the C side won't get garbage-collected until the C side is done with it.

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

The cgo subsystem of the Go programming language is one example of this approach.

调用软件使用一个库(通常用 C 编写以利用 C 编译器可以为它做的事情),它能够加载 C 动态库并正确调用它们的函数来执行所有必需的数据设置.请参阅 this 了解更多信息.

The calling software uses a library (typically written in C to leverage what the C compiler can do for it) which is able to load C dynamic libraries and properly call out to their functions performing all the required data setup. See this for more info.

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

Python's ctypes module implements exactly this approach.

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

It's harder for me to classify Java's JNI and .NET's P/Invoke into these two categories. May be they sit somewhere in the middle.

这篇关于非 c 语言如何与操作系统交互?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆