【问题标题】:Calling system calls on linux machine [duplicate]在linux机器上调用系统调用[重复]
【发布时间】:2014-12-13 00:49:56
【问题描述】:

通常,系统提供位于普通程序和操作系统之间的库或 API。在类 Unix 系统上,该 API 通常是 C 库 (libc) 实现的一部分,例如提供包装器的 glibc系统调用的函数。 现在 C 程序可以调用这些库函数,因为这些库函数是用 C 编写的并进行系统调用。 像 Cobol 这样的语言或任何其他基于编译器的语言如何在 linux 上进行系统调用?这些语言无法调用系统提供的API。

【问题讨论】:

  • 他们对使用 libc 很满意。其他不太聪明的运行时可能会经历自己的内核版本支持地狱。
  • "这些语言无法调用系统提供的API。"为什么不呢?
  • 他们如何调用 libc 函数?..
  • API 是用 C 写的,我如何调用其他语言的 C 函数?
  • Java Native Interface, Calling Native Functions from Managed Code,在此处插入适合您语言的解决方案

标签: c linux operating-system system


【解决方案1】:

编译语言被翻译(编译)成机器语言。操作系统在执行期间读取机器语言并进行适当的系统调用。

所以,我不会说它是 C 或任何编译语言,它会进行系统调用。操作系统根据你的编译器生成的机器语言执行系统调用。

【讨论】:

  • 没那么简单 - 您必须了解 ABI 才能知道如何 进行这些调用。
  • 编译器必须了解 ABI 才能做到这一点?
  • @saurav1405 是的。编写编译器/解释器和/或运行时库的人必须了解编译器运行所在平台的系统调用 ABI,以及他们希望该语言在特定平台上调用哪些系统调用。
【解决方案2】:

一个例子可能会有所帮助:如果我用 gfortran 编译一个像这样的简单 Fortran 程序:

  PROGRAM HELLO

  WRITE(*,*) "HELLO WORLD"

  END

我得到如下代码(在 x86-64 上):

000000000040079d <MAIN__>:
  40079d:       55                      push   %rbp
  40079e:       48 89 e5                mov    %rsp,%rbp
  4007a1:       48 81 ec e0 01 00 00    sub    $0x1e0,%rsp
  4007a8:       48 c7 85 28 fe ff ff    movq   $0x4008e0,-0x1d8(%rbp)
  4007af:       e0 08 40 00 
  4007b3:       c7 85 30 fe ff ff 03    movl   $0x3,-0x1d0(%rbp)
  4007ba:       00 00 00 
  4007bd:       c7 85 20 fe ff ff 80    movl   $0x80,-0x1e0(%rbp)
  4007c4:       00 00 00 
  4007c7:       c7 85 24 fe ff ff 06    movl   $0x6,-0x1dc(%rbp)
  4007ce:       00 00 00 
  4007d1:       48 8d 85 20 fe ff ff    lea    -0x1e0(%rbp),%rax
  4007d8:       48 89 c7                mov    %rax,%rdi
  4007db:       e8 c0 fe ff ff          callq  4006a0 <_gfortran_st_write@plt>
  4007e0:       48 8d 85 20 fe ff ff    lea    -0x1e0(%rbp),%rax
  4007e7:       ba 0b 00 00 00          mov    $0xb,%edx
  4007ec:       be e7 08 40 00          mov    $0x4008e7,%esi
  4007f1:       48 89 c7                mov    %rax,%rdi
  4007f4:       e8 57 fe ff ff          callq  400650 <_gfortran_transfer_character_write@plt>
  4007f9:       48 8d 85 20 fe ff ff    lea    -0x1e0(%rbp),%rax
  400800:       48 89 c7                mov    %rax,%rdi
  400803:       e8 78 fe ff ff          callq  400680 <_gfortran_st_write_done@plt>
  400808:       c9                      leaveq 
  400809:       c3                      retq   

在那里,您可以看到对 gfortran 库函数的三个调用(例如 gfortran_transfer_character_write)。看起来 gfortran 插入这些以实现 WRITE 语句。库函数为implemented in C,最终将通过C 库包装器调用底层系统调用。

当编译器构造对这些函数的调用时,它必须遵循 C 调用约定并执行与调用语言的数据类型之间的任何转换。除此之外,这里没有魔法。进入运行时库后,您可以调用其他 C 库(如 libc)。

【讨论】:

  • @benj 非常感谢。我了解一种语言如何使用 libc 来调用系统调用,但是如何直接调用系统调用,即不使用 libc ?我需要为此编写汇编代码吗?
猜你喜欢
  • 2011-10-28
  • 2014-12-10
  • 2012-06-30
  • 1970-01-01
  • 2014-10-10
  • 2011-02-17
  • 2012-12-30
  • 1970-01-01
  • 2016-05-12
相关资源
最近更新 更多