任何人都可以向我解释编程语言中的系统调用吗?

时间:2013-07-26 07:04:54

标签: operating-system

我几天前开始研究操作系统概念,我已经遇到了一些问题。 主要是我对系统调用非常好奇。 我了解到每个操作系统都提供了自己的API (例如Windows for Windows API,Linux for libc等)

我开始感到困惑的是包装函数。 例如,Linux有一个fork()包装函数。 这是否意味着此函数内的算法执行系统调用例程 基于OS的系统调用表? 我不知道它是用C语写的意思 这是否意味着它使用的是C标准库?还是只是C编译器? 另外,即使C编译器如何编译它的标准库 有不同种类的编译器,如GCC Windows C编译器等? 我很好奇的是,C标准库函数还调用系统调用对吗? 但它可能必须调用不同的系统调用才能在不同的操作系统中获得相同的输出吗? 这是否意味着,即使它是相同的标准C函数,系统调用 内部实现的内容因OS而异吗?

我真的想要一个好的系统调用概念plz :)

3 个答案:

答案 0 :(得分:3)

系统调用是底层操作系统公开的功能。对于语言来说,通常有明确定义的方式来发出系统调用。例如,Intel x86处理器使用了syscall指令,但您也可以使用其他方法,例如发出中断指令。

进行系统调用时,会发生从用户空间到内核空间的转换,该空间以更高的特权级别运行。将系统调用的参数复制到内核空间并进行验证,以确保它们不会损害内核。但是,参数很可能也是在用户空间中验证的。在某些情况下,用户空间函数将是内核函数的薄包装器,有时它们将在顶部提供额外的功能。

C和Unix有着严格的遗产,这就是为什么许多系统调用名称与它们的C版本相同(例如fork,execXXX)。但是,这只是一种惯例,并非在所有情况下都是如此。在Windows上,系统调用的名称与Linux对应的名称完全不同。但是,平台上的底层C运行时实现会隐藏这一点,并进行正确的系统调用以实现我的C函数所提供的功能。

通常,像Ruby这样的高级语言不会直接发出系统调用。相反,他们使用的是用较低级语言(例如C或C ++)编写的库,它们将Ruby调用转换为对底层系统函数的调用。

答案 1 :(得分:0)

我只对Linux内核有所了解,所以我将以Linux内核为例回答我的问题。要了解系统调用,您必须了解内核空间和用户空间的概念。系统调用是用户空间应用程序与内核通信的接口。因此系统调用的实现是内核的一部分。

首先,Linux内核主要使用C编写,部分使用汇编语言编写。但Linux内核从不使用任何C标准库函数。所以在Linux中,用C标准库函数实现系统调用是不可能的。

其次,Linux提供了数百个系统调用。其中一些是用C编写的,但其中一些必须用汇编语言实现。不仅用C编写的程序可以进行系统调用,大多数其他语言如Ruby,Golang也可以这样做。恕我直言,说系统调用用C语言编写是不对的。

第三,不同的操作系统提供不同的系统调用。即使是相同的操作系统也可以在不同的体系结构中运行,例如x86,arm等。不同的体系结构意味着不同的指令集。因此,即使是相同的OS也可以以不同的方式实现相同的系统调用。所以我认为你对此的理解是正确的。

答案 2 :(得分:0)

系统调用和包装函数是两个不同的概念。

  1. 系统调用: 这些是内核空间中的常规函数​​。用户程序无法直接访问它们,即由您和我这样的人编写的函数。系统调用只能由内核代码访问。这些功能将与设备或主存储器交互,以向用户程序提供所请求的服务。

  2. 包装功能: 如果要在用户代码中使用系统调用,则无法以用户空间中的函数方式直接调用它。您的处理器需要执行陷阱机器指令(中断)以切换到内核模式。切换到内核模式以执行系统函数后,传递给该函数的参数中应该没有错误。系统调用不会检查其参数是否正确,因此如果参数有任何问题,可能会导致内核错误。如果您的用户空间程序出现故障,内核将会终止您的进程,但是当内核出现故障时,整个内核都会出现故障,这是不可接受的。 包装函数确保所有参数都有效。如果一切正常,他们还会设置陷阱到内核的基础。

  3. 现在回答你的问题:

    1. 包装函数不执行系统调用函数,它们只检查参数的正确性,并通过传递适当的系统调用号将陷阱设置为内核模式。您的内核包含按编号的系统调用表,并执行所请求的函数。一旦包装函数调用了陷阱,它的工作就结束了。

    2. 包装函数是常规用户级程序,用C语言编写,部分用汇编语言编写。是的,包装函数可以调用标准库函数。

    3. 标准库函数是用C89,C99版本和旧版本的C编写的。这并不重要,因为较新版本的C向后兼容旧版本。所以,是的,库函数编译就像普通用户代码一样,没有任何版本的C编译器出现问题。

    4. 大多数标准库函数在多个操作系统和编译器中都是相同的,但是,也有一些差异。 fork()包装器函数在Visual Studio中不起作用,因为Windows有不同的方法。

    5. 编辑:fork()不是系统调用,它只是一个内部陷阱到内核的库函数