Linux 系统调用

2018/7/8 posted in  Kernel

内核提供了用户进程和内核进行交互的一组接口,这些接口在应用程序和内核之间扮演了使者的角色,应用程序发出各种请求,而内核负责满足这些请求,而这些接口,即是 系统调用

作用

系统调用主要起到保护系统稳定可靠运行的作用,避免应用程序肆意妄为。

除此,系统调用还起到了为用户空间进程与硬件设备之间添加一个中间层的作用,该层的主要作用三个:

  1. 为用户空间提供一种硬件的抽象接口,使用户进程不用区分硬件类型
  2. 使得内核可以基于权限、用户累心和其他一些规则对需要进行的访问进行判断
  3. 为用户空间和系统的其余部分提供公共接口

工作原理

一般情况下,应用程序通过在用户空间实现的应用编程接口(API)而不是直接通过系统调用来编程。在 Unix 中,最流行的应用编程接口是基于 POSIX 标准的,所以 Liunx的系统调用像绝大多数 Unix 一样,作为 C 库的一部分提供:

关于 Unix 的接口设计中有一句格言:“提供机制而不是策略”。换句话说,Unix 的系统调用抽象出了用于完成某种确定的目的的函数,至于这些函数怎么用完全不需要被内核关心。

要访问系统调用(在 Linux 被称为 syscall),通常通过 C 库中定义的函数调用来进行。通常系统调用可以定义零个到多个参数,也会返回一个 long 来标记执行情况或者遇到的错误,而具体的错误信息会写在 error 全局变量中,通过 perror 库函数便可以打印出可读的错误信息。

在 Linux 中每个系统调用都被赋予一个系统调用号(存储在 sys_call_table 中),这样通过独一无二的编号就可以关联系统调用使用户进程不需要提及系统调用的名称。

Linux 系统的系统调用比其他操作系统执行要快的多,首先是因为 Linux 很短的上下文切换时间,其次就是 Linux 的系统调用本身就被设计的非常简洁。

用户空间进程通过系统调用来 “执行” 内核代码,其通知内核的机制是通过软中断实现的: 通过引发一个异常来促使系统切换到内核态去执行异常处理程序 (用户空间引发异常陷入内核)。

在使用系统调用时,除了调用号以外,一般还需要一些外部的参数输入,所以在陷入内核的时候,需要把这些参数从用户空间传入到内核,而最简单的方法就是像传递系统调用号一样,把这些参数也存放在寄存器中。