Linux内核分析第五章读书笔记
发布日期:2025-04-08 11:37:26 浏览次数:9 分类:精选文章

本文共 1268 字,大约阅读时间需要 4 分钟。

系统调用

与内核通信

在操作系统中,内核为用户进程与内核交互提供了一组接口,这些接口在应用程序与内核之间起到重要的中介作用,确保系统的稳定性和安全性,防止应用程序随意访问内核空间。

系统调用

系统调用是用户空间进程与硬件设备之间的中间层,它的主要作用包括:

  • 提供硬件的抽象接口
  • 保障系统的稳定性和安全性
  • 作为内核的唯一合法入口(除异常和陷入外)
  • API与C库

    在UNIX系统中,应用程序通过API(应用编程接口)进行编程。在Linux系统中,系统调用作为C库的一部分,提供了基于POSIX标准的API。程序员通过API与内核进行交互,系统调用的设计理念强调“提供机制而非策略”,即明确功能的实现方式,但不涉及具体的策略。

    系统调用的实现

    系统调用通过C库中的函数调用实现,返回值类型为long。成功返回值为0,错误返回值为负数,错误信息通过errno变量和perror函数向用户空间传递。

    系统调用号

    系统调用号是唯一的,系统调用号一旦确定,不能更改或删除。内核维护了系统调用表sys_call_table,其中每个体系结构都有自己的定义。x86-64体系结构的系统调用号定义在arch/i386/kernel/syscall_64.c文件中。

    系统调用的性能

    Linux系统调用的性能优异,主要原因在于:

  • 切换上下文时间短
  • 系统调用处理程序简洁高效
  • 系统调用的处理程序

    内核通过触发异常切换到内核态执行系统调用处理程序system_call,中断号为128(在x86中使用int$0x80指令)。x86体系结构还引入了sysenter指令,进一步提升性能。

    系统调用参数传递

    系统调用处理程序接受前五个参数分别通过ebx、ecx、edx、esi、edi寄存器传递,参数指针存放在eax寄存器中。返回值存放在eax寄存器。

    系统调用的实现步骤

  • 准备接口:确保接口简洁、参数少且通用。
  • 参数验证:检查指针有效性和权限,使用copy_to_user、copy_from_user和capable函数进行验证。
  • 最终步骤:将系统调用添加到sys_call_table,并定义相应的系统调用号。
  • 系统调用上下文

    内核在执行系统调用时处于进程上下文,current指针指向当前进程。系统调用的处理程序可以休眠或被抢占,确保系统调用的可重入性。

    系统调用的注册

  • 在entry.s文件中添加系统调用表项。
  • 定义系统调用号并注册到<asm/unistd.h>文件中。
  • 将系统调用编译进内核映像,存放至相关文件(如kernel/sys.c)。
  • 系统调用的使用

    用户程序通过包含标准头文件并使用_syscalln宏调用系统调用的实现。例如,open系统调用通过NR_open宏定义接口。

    系统调用的替代方案

    如果不使用系统调用,可以选择以下方式:

  • 实现设备节点并使用read和write接口。
  • 使用ioctl接口实现特定操作。
  • 将新功能添加到已有文件中,避免新增系统调用。
  • 通过这种方式,Linux保持了系统调用的简洁性和稳定性,避免了功能过于分散的问题。

    上一篇:Linux内核创建一个新进程的过程
    下一篇:Linux内核信息相关命令:dmesg

    发表评论

    最新留言

    做的很好,不错不错
    [***.243.131.199]2025年04月21日 17时17分03秒