Linux 系统调用(一)

1、系统调用基本概念

系统调用:内核中所有已实现和可用系统调用的集合。Linux中四种类型的接口:

  • 应用编程接口(API)
  • 应用二进制接口(ABI)
  • 内核内部的 API
  • 内核内部的ABI

LSB标准:为了促进Linux不同发行版本间的兼容性,LSB开发了一系列标准,使得各种软件可以很好的在兼容 LSB 标准的系统上运行。
Linux API :是 Linux 内核和用户空间的 API,使用户程序能够通过这个借口访问系统资源和内核提供的服务。Linux API 由两部分组成:Linux 内核的系统调用接口和 GNU C 库(glibc)中的例程。内核 API 主要是标记为 “EXPORT_SYMBOL” 的函数。
GNU C 库:Linux 内核系统调用接口的封装,其中包括 POSIX 兼容应用函数调用和 Linux 专用的函数调用。
POSIX:表示可移植操作系统接口(Portable Operating System Interface of UNIX,缩写为 POSIX ),POSIX标准定义了操作系统应该为应用程序提供的接口标准,是IEEE为要在各种UNIX操作系统上运行的软件而定义的一系列API标准的总称,其正式称呼为IEEE 1003。
Linux ABI:一系列约定的集合,它和具体的 CPU 架构和 OS 相关,只要 OS 遵守相同的 ABI 规范,那么不同的应用就可以实现向前兼容。ABI 包含以下内容:

  • 一个特定的处理器集合
  • 函数调用惯例
  • 系统调用方式
  • 可执行文件的格式(ELF 、PE等)

系统调用号:用来唯一的标识每个系统调用。
系统调用表:把系统调用号和相应的服务例程关联起来。
在这里插入图片描述

从用户态跟踪一个系统调用到内核

  1. 从用户程序中调用fork;
  2. 在libc库中把fork对应的系统调用号2放入寄存器eax;
  3. 通过int 0x80陷入内核;
  4. 在中断描述表IDT中查到系统调用的入口0x80;
  5. 进入Linux内核的entry_32(64).S文件,从系统调用表sys_call_table中找到sys_fork的入口地址;
  6. 执行fork.c中的do_fork代码;
  7. 通过iret或者sysiret返回。
    在这里插入图片描述

跟踪 cp 所调用的系统调用可以使用如下命令:

strace cp

在这里插入图片描述

2、系统调用机制

在用户空间和内核空间之间,有一个叫做Syscall(系统调用, system call)的中间层,是连接用户态和内核态的桥梁。这样即提高了内核的安全型,也便于移植,只需实现同一套接口即可。Linux系统,用户空间通过向内核空间发出Syscall,产生软中断,从而让程序陷入内核态,执行相应的操作。

安全性与稳定性:内核驻留在受保护的地址空间,用户空间程序无法直接执行内核代码,也无法访问内核数据,通过系统调用机制可以增强系统的安全性和稳定性。

性能:Linux上下文切换时间很短,系统调用处理过程非常精简,性能上往往比很多其他操作系统执行要好。

为了让读者清晰明了的理解系统调用的过程,下面以 read 系统调用为例来说明:

当 read() 调用发生时,库函数在保存 read 系统调用号以及参数后,陷入 0x80 中断,执行 0x80 中断处理程序,0x80 中断处理程序接管执行后,先检察其系统调用号,然后根据系统调用号查找系统调用表,并从系统调用表中得到处理 read 系统调用的内核函数 sys_read ,最后传递参数并运行 sys_read 函数。

read 系统调用在内核中所要经历的层次模型
对于磁盘的一次读请求,首先经过虚拟文件系统层(vfs layer),其次是具体的文件系统层(例如 ext2),接下来是 cache 层(page cache 层)、通用块层(generic block layer)、IO 调度层(I/O scheduler layer)、块设备驱动层(block device driver layer),最后是物理块设备层(block device layer)。
在这里插入图片描述
各层的作用

模型所在层 作用
虚拟文件系统层 屏蔽下层具体文件系统操作的差异,为上层的操作提供一个统一的接口。正是因为有了这个层次,所以可以把设备抽象成文件,使得操作设备就像操作文件一样简单。
具体的文件系统层 不同的文件系统(例如 ext2 和 NTFS)具体的操作过程也不同,每种文件系统定义了自己的操作集合。
cache 层 为了提高 linux 操作系统对磁盘访问的性能。 Cache 层在内存中缓存了磁盘上的部分数据。当发生数据请求时,如果在 cache 中存在该数据且是最新的,则直接将数据传递给用户程序,免除了对底层磁盘的操作,提高了性能。
通用块层 接收上层发出的磁盘请求,并最终发出 IO 请求。该层隐藏了底层硬件块设备的特性,为块设备提供了一个通用的抽象视图。
IO 调度层 接收通用块层发出的 IO 请求,缓存请求并试图合并相邻的请求(如果这两个请求的数据在磁盘上是相邻的),并根据设置好的调度算法,回调驱动层提供的请求处理函数,以处理具体的 IO 请求。
块设备驱动层 驱动层中的驱动程序对应具体的物理块设备。它从上层中取出 IO 请求,并根据该 IO 请求中指定的信息,通过向具体块设备的设备控制器发送命令的方式,来操纵设备传输数据。
物理块设备层 设备层中都是具体的物理设备。定义了操作具体设备的规范。

相关的内核数据结构

数据结构 作用
dentry 联系了文件名和文件的 inode 节点
inode 文件 inode 节点,保存文件标识、权限和内容等信息
file 保存文件的相关信息和各种操作文件的函数指针集合
file_operations 操作文件的函数接口集合
address_space 描述文件的 page cache 结构以及相关信息,并包含有操作 page cache 的函数指针集合
address_space_operations 操作 page cache 的函数接口集合
bio IO 请求的描述

数据结构之间的关系
dentry 对象可以找到 inode 对象, inode 对象中可以找到 address_space 对象, address_space 对象可以找到 address_space_operations 对象。
File 对象可以根据当前进程描述符中提供的信息获得,进而可以找到 dentry 对象、 address_space 对象和 file_operations 对象。
在这里插入图片描述


更多有趣的文章,请访问博主目录页

智慧人生,与你相伴
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_34258344/article/details/104537181