当前位置: 首页 > news >正文

操作系统基础:05 系统调用实现

一、系统调用概述

  • 上节课讲解了系统调用的概念,系统调用是操作系统给上层应用提供的接口,表现为一些函数,如open、read、write 等。上层应用程序通过调用这些函数进入操作系统,使用操作系统功能,就像插座一样,看似简单易用,但本讲要探究其背后的实现机制。

二、系统调用的直观想法及问题

  • 以whoami系统调用为例
    在这里插入图片描述

    用户程序调用whoami,目的是取出操作系统中(系统引导时载入)的字符串“lizhijun”并打印。直观想法是,应用程序和操作系统都在内存中,为何不能直接访问内核内存,直接调用printf打印内核中的字符串呢?

  • 不可行原因:如果允许随意调用内核数据、随意跳转(jmp),会带来严重安全问题。比如可能泄露root密码,导致非法获取用户权限;还可能查看他人word内容,侵犯用户隐私。所以,应用程序不能直接访问内核内存。

三、内核态与用户态及内存分段

  • 硬件设计实现隔离
    在这里插入图片描述

    硬件设计区分了内核态和用户态 ,通过处理器保护环实现。用CS的最低两位表示当前程序执行状态,0是内核态,3是用户态。内核态可访问任何数据,用户态不能访问内核数据,指令跳转也受此限制,实现了内核程序和用户程序的隔离。

  • 内存分段及特权级检查:内存对应分为内核段和用户段,通过段寄存器中的CPL(当前特权级)和DPL(目标特权级)等信息来检查访问是否合法。DPL用来表示目标内存段的特权级,操作系统初始化时将内核段的DPL设为0 。CPL表示当前的特权级,数字越大特权级越低,3表示用户态。每次访问时,要求DPL≥CPL且DPL≥RPL(请求特权级 ),若不满足特权级要求则无法访问。

四、进入内核的方法——中断

  • 中断指令int:对于Intel x86架构,硬件提供的主动进入内核的方法是中断指令int 。
    在这里插入图片描述

    int指令会使CS中的CPL改成0,从而进入内核,这是用户程序调用内核代码的唯一方式。

  • 系统调用核心要点

    • 用户程序中包含一段含int指令的代码,通常由库函数展开生成。
    • 操作系统编写中断处理程序,获取想调用程序的编号。
    • 操作系统根据编号执行相应代码。

五、系统调用实现流程

  • 以printf调用为例
    在这里插入图片描述

    应用程序调用printf,经C函数库处理,先由库函数printf转换为库函数write,最终展开成包含int 0x80指令的代码。

    在Linux系统中,以write系统调用为例
    在这里插入图片描述

    使用_syscall3宏展开代码,_NR_write是其系统调用号(值为4 )。在展开的汇编代码中,系统调用号放在eax中,同时eax也存放返回值,ebx、ecx、edx存放3个参数,通过int 0x80指令进入内核。

六、int 0x80中断处理

  • 中断处理设置:系统通过set_system_gate函数设置0x80的中断处理
    在这里插入图片描述

    将中断处理函数入口地址等信息设置到中断描述符表(idt)中,其中DPL设为3,使得用户态代码(CPL = 3 )能通过int 0x80中断进入内核。执行int 0x80指令时,会根据idt表找到对应的中断处理程序system_call 。

七、中断处理程序system_call

  • 处理流程:在system_call中断处理程序中,
    在这里插入图片描述
    首先会检查系统调用号是否合法,然后保存相关寄存器,设置内核数据段,通过系统调用号在_sys_call_table函数表中查找对应的处理函数。比如对于write系统调用,系统调用号为4,就会找到sys_write函数执行相应操作。执行完毕后恢复寄存器,返回用户态。

    _sys_call_table是一个全局函数数组,
    在这里插入图片描述
    存放着各个系统调用对应的处理函数指针。

八、总结

在这里插入图片描述

  • 系统调用从用户态应用程序发起,借助库函数将系统调用展开为含int 0x80指令的代码,通过中断进入内核态,在内核中根据系统调用号执行相应处理函数,完成后返回用户态。这一机制既为应用程序提供了访问内核功能的途径,又保障了系统的安全稳定,理解其原理对深入掌握操作系统及开发应用程序意义重大。

相关文章:

  • playwright 教程高级篇:掌握网页自动化与验证码处理等关键技术详解
  • [数据结构]排序 --2
  • 【C++】C++的引用
  • 在 Ubuntu 下通过 Docker 部署 Caddy 服务器
  • C++双链表介绍及实现
  • 从输入URL到页面渲染:浏览器请求的完整旅程解析
  • LLM学习笔记3——使用Docker(vLLM+OpenWebUI)实现本地部署DeepSeek-R1-32B模型
  • 基于HASM模型的高精度建模matlab仿真
  • Go 跨域中间件实现指南:优雅解决 CORS 问题
  • 十五、C++速通秘籍—异常处理
  • 基于Python的经济循环模型构建与可视化案例
  • Matlab添加标题title与标签lable
  • 上层 Makefile 控制下层 Makefile 的方法
  • 解释型语言和编译型语言的区别
  • 安全岗の夺命连环问:(第壹篇)从XSS到0day的灵魂拷问
  • 舵机、震动传感器、超声波使用代码
  • Qt 5.14.2 入门(四)菜单栏和工具栏的创建
  • 六、继承(三)
  • 如何用finallshell连接虚拟机
  • 前端下载文件时浏览器右上角没有保存弹窗及显示进度,下载完之后才会显示保存弹窗的问题定位及解决方案
  • 事关政府信息公开,最高法发布最新司法解释
  • 鸿蒙电脑正式发布,余承东:国产软件起步晚,基础弱,探索面向未来的电脑体验
  • 多所院校高规格召开考研动员会,有学院考研报名率达84%
  • “十五五”时期长三角需创新机制,形成高水平一体化合作路径
  • 上海发文加强直播经济技能人才培养:三年新培养持证直播技能人才5万名
  • 全总联合六部门印发工作指引,共保劳动者合法权益