了解对系统调用的更高级别调用

时间:2017-04-07 03:16:23

标签: operating-system system-calls

我正在阅读高尔文在操作系统上的这本书。在第2章末尾有一节,作者写了关于"添加系统调用"到了内核。

他描述了如何使用asmlinkage我们可以创建一个包含函数的文件,并使其符合系统调用的条件。但在接下来的部分中,关于如何调用系统调用,他写了以下内容:

" 不幸的是,这些是使用C语言语句无法执行的低级操作,而是需要汇编指令。幸运的是,Linux提供了用于实例化包含适当汇编指令的包装函数的宏。例如,以下C程序使用_syscallO()宏来调用新定义的系统调用:

基本上,我想了解syscall()函数通常如何工作。现在,我对Macros的理解是一个文本替换系统。 (如果我错了,请纠正我) 宏如何调用汇编语言指令? 这样编译时的syscallO()是否被转换为执行陷阱的指令的地址(操作码)?(但这不符合我所拥有的宏的概念或定义) 包含在内部的包装函数究竟是什么,它们也是用汇编语言编写的?

假设,我想创建一个自己的函数来执行系统调用,那么我需要做些什么。我需要编译它来生成用于执行陷阱指令的机器代码吗?

1 个答案:

答案 0 :(得分:0)

男人,你必须支付156美元,然后你实际上必须阅读它。您可能会以低于30美元的价格获得VMS内部和数据结构书。

那就是说,让我试着将那些胡言乱语翻译成英文。

系统调用不使用其他函数使用的相同类型的链接(即传递参数和调用函数的方法)。

执行系统服务时,不是执行某种类型的调用指令,而是触发异常(在英特尔中奇怪地称为 中断 )。

CPU期望操作系统创建DISPATCH TABLE并将其位置和大小存储在特殊的硬件寄存器中。 dispatch表是指向异常和中断的处理程序的指针数组。

异常和中断有数字,当发生异常或中断号#1时,CPU在内核模式下调度表中调用2d异常处理程序(不是#0,但是#1)。

  

内部包含的包装函数究竟是什么?它们也是用汇编语言编写的?

操作系统通常将一个(但有时更多)的例外用于系统服务。你需要在汇编语言中做一些这样的事情来调用系统服务:

INT $80 ; Explicitly trigger exception 80h 

因为您必须执行特定指令,所以必须使用汇编语言。也许你的C编译器可以在线调用汇编语言来调用系统服务。但即使可能,每次你想打电话给系统服务时,都必须要做皇家PITA。

另外,我还没有在这里填写所有细节(只是对系统服务的实际调用)。通常,当您使用C(或其他)调用函数时,参数将被推送到程序堆栈中。因为当你进入内核模式时堆栈通常会改变,所以系统调用的参数需要存储在寄存器中。

PLUS您需要确定要执行的系统服务。通常,系统服务有数字。系统服务的编号被加载到第一个寄存器中(例如,R0或AX)。

需要调用系统服务时的完整过程是:

  1. 保存要覆盖的堆栈。
  2. 将要传递给系统服务的参数加载到硬件寄存器中。
  3. 将系统服务的编号加载到最低的寄存器中。
  4. 触发异常以进入内核模式。
  5. 从寄存器
  6. 卸载系统服务返回的参数
  7. 可能会进行一些错误检查
  8. 恢复之前保存的寄存器。
  9. 每次调用系统服务时,操作系统都会提供高级语言的包装函数,而不是这样做。您可以像调用函数一样调用包装器。包装器(使用汇编语言)为您执行上述步骤。

    因为这些包装器几乎相同(通常唯一的区别是不同数量的参数的结果),所以可以使用宏创建包装器。一些汇编程序具有强大的宏功能,允许单个宏定义所有包装器,即使使用不同数量的参数。

    Linux提供了多个创建包装器的_syscall C宏。每个参数都有一个。请注意,这些宏仅适用于操作系统开发人员。包装器出现后,每个人都可以使用它。

      

    宏如何调用汇编语言指令?

    这些_syscall宏必须在行汇编代码中生成。

    最后,请注意这些包装器不定义实际的系统服务。必须在调度表和系统服务异常处理程序中设置它。