Linux操作系统原理与应用06:系统调用

2023-05-16

目录

1. Linux中的各种接口

1.1 LSB标准

1.2 Linux API

1.2.1 概述

1.2.2 Linux内核系统调用接口

1.2.3 C标准库

1.3 Linux ABI

1.4 内核API

1.5 系统调用与各种接口的关系

1.5.1 系统调用与API的关系

1.5.2 系统调用与系统命令的关系

1.5.3 系统调用与内核函数的关系

2. 中断、异常和系统调用的比较

2.1 源头不同

2.2 服务响应方式不同

2.3 处理机制不同

3. 系统调用的基本概念

3.1 系统调用号

3.2 系统调用表

3.3 系统调用封装例程和服务例程

4. 系统调用处理流程

4.1 设置异常处理函数

4.2 触发软中断进入内核态

4.3 调用系统调用服务例程

4.4 系统调用返回

5. 添加新的系统调用

5.1 添加系统调用号

5.1 添加系统调用表项

5.3 实现系统调用服务例程

5.4 重新编译内核

5.5 编写用户态程序


1. Linux中的各种接口

1.1 LSB标准

① LSB即Linux Standards Base,是Linux标准化领域中事实上的标准

② 由于Linux的发行版众多,为了促进Linux不同发行版之间的兼容性,LSB开发了一系列标准,使各种软件可以在兼容LSB标准的系统上运行

1.2 Linux API

1.2.1 概述

Linux API是Linux内核与用户空间的API,也就是让用户空间的程序能够通过这个接口访问系统资源和内核提供的服务

Linux API由两部分组成:Linux内核系统调用接口和GNU C库(glibc库)中的例程

1.2.2 Linux内核系统调用接口

系统调用接口是内核中所有已实现的可用系统调用的集合

1.2.3 C标准库

GNU C库是Linux内核系统调用接口的封装,其中包括POSIX兼容的应用函数调用和Linux专用的应用函数调用

目前最新的Linux内核5.0版本中系统调用大约有380个,GNU C库大约有2000个函数

说明:POSIX标准

POSIX表示可移植操作系统接口(Portable Operating System Interface of UNIX),POISX标准是针对API而不是针对系统调用的,他定义了操作系统应该为应用程序提供的接口标准,并不涉及对应的函数如何实现

1.3 Linux ABI

ABI是一些列约定的集合,可以说调用惯例(calling convention)就是ABI。ABI是和具体的CPU架构和OS相关的,具体而言,ABI包括以下内容,

① 一个特定的处理器指令集

② 函数调用惯例

③ 系统调用方式

④ 可执行文件的格式(e.g. ELF、PE)

说明:什么是函数调用惯例和系统调用方式

Linux提供了一个syscall函数,用来根据系统调用号直接调用系统调用,在该函数的man手册中说明了不同体系结构触发软中断的命令以及系统调用的传参方式,其实这就是所谓的ABI

1.4 内核API

① 内核API主要是内核中标记为EXPORT_SYMBOL的函数,这些函数主要是为了内核模块的编写而提供的

② 收到内核版本更迭的影响,内核API并不稳定,3.x版本内核的模块可能在4.x版本上就无法使用

1.5 系统调用与各种接口的关系

1.5.1 系统调用与API的关系

由于API是对系统调用的封装,所以API和系统调用之间可能存在如下几种关系,

① API和系统调用形式一致

e.g. read函数和read系统调用

② 几个不同的API内部使用了同一个系统调用

e.g. malloc / calloc和free函数的实现都调用了brk系统调用

③ 一个API内部使用了多个系统调用

e.g. malloc函数的实现根据要分配内存的大小,可能使用brk系统调用,也可能使用mmap系统调用

④ API内部不使用系统调用

e.g. string.h中声明的各种字符串处理函数

1.5.2 系统调用与系统命令的关系

系统命令相对API接口更高一层,每个系统命令都是一个可执行程序,使用strace命令可以查看系统命令使用的系统调用

说明:下图列出了一些系统命令与Linux各模块之间的关系

1.5.3 系统调用与内核函数的关系

系统调用进入内核后,会找到各自对应的内核函数,这些内核函数被称为系统调用的服务例程

e.g. 系统调用getpid对应的服务例程为sys_getpid

2. 中断、异常和系统调用的比较

根据中断和异常章节的学习可知,中断、异常和系统调用本质上属于一类,在处理方式上也类似,他们的差异体现在如下方面

2.1 源头不同

① 中断是外设发出的请求

② 异常是应用程序意想不到的行为

③ 系统调用是应用程序请求操作系统提供服务

2.2 服务响应方式不同

① 中断是异步的

② 异常是同步的

③ 系统调用既可以是异步的(e.g. 异步IO),也可以是同步的

2.3 处理机制不同

① 中断服务程序在内核态运行,对用户是透明的

② 异常出现时,或者杀死进程,或者重新执行引起异常的指令

③ 系统调用是用户发出请求后等待操作系统的服务

3. 系统调用的基本概念

3.1 系统调用号

① 定义在各体系结构的unistd.h中,在Linux 2.6.11 + 80386版本中为include/asm-i386/unistd.h

② 用来唯一的表示每个系统调用

③ 作为系统调用表的下标,当用户空间的进程执行一个系统调用时,该系统调用号作为参数传递,用来指明要执行的系统调用服务例程

3.2 系统调用表

① 在Linux 2.6.11 + 80386版本中,系统调用表sys_call_table定义在arch/i386/kernel/entry.S中

② 系统调用表是一个函数指针数组,使用系统调用号索引

说明:系统调用号和系统调用表一旦分配好就不能有改变,否则编译好的应用程序会因为调用到错误的系统调用而导致程序异常

3.3 系统调用封装例程和服务例程

① 系统调用服务例程就是内核态最终处理系统调用请求的函数

② 引入系统调用封装例程是因为用户空间的程序无法直接调用内核代码,因此在需要执行一个系统调用时,是通过软中断引发一个异常进入内核态,封装例程就是对这个过程的封装

4. 系统调用处理流程

4.1 设置异常处理函数

在内核初始化的trap_init函数中,将系统调用异常处理函数设置为system_call

说明:将系统调用的IDT描述符设置为系统门,使得用户态可以穿过该门进入内核态

4.2 触发软中断进入内核态

根据不同的体系结构,使用int $0x80 / syscall / svc指令即可触发系统调用对应的异常,并跳转到system_call函数运行

system_call函数在调用系统调用服务例程之前完成如下工作,

① 将系统调用号压栈(根据ABI,系统调用号通过eax寄存器传递)

② 调用SAVE_ALL将异常处理程序可以用到的所有寄存器保存到相应的栈中

此处注意3点,

a. 由于系统调用一定是从用户态切换到内核态,所以在进入异常处理时,硬件会进行栈的切换,并自动保存相关寄存器,如下图所示(系统调用中没有ERROR CODE)

b. SAVE_ALL中同时将ds和es装入内核数据段的段选择符

c. 根据之前的系统调用ABI说明,SAVE_ALL保存的寄存器中就包含了系统调用参数

③ 调用GET_THREAD_INFO,将当前进程thread_info的地址存放在ebp中

④ 判断系统调用号的合法性,如果合法则查找系统调用表并调用系统调用服务例程

4.3 调用系统调用服务例程

① 系统调用服务例程根据系统调用号在sys_call_table中查表得到

② 所有系统调用服务例程的参数为struct pt_regs类型,该类型对应的就是寄存器在栈上的布局

这里就有一个问题了,我们知道在X86体系结构中,函数参数是优先通过寄存器传递的,那么给系统调用服务例程的参数是如何传递的呢 ? 这里的玄机就在于asmlinkage宏

__attribute__((regparm(n)))用于指定最多可以使用n个寄存器传递参数,超过n的参数将使用栈传递

对于系统调用,使用regparm(0),也就是所有参数均通过栈传递,内核中所有系统调用的实现都使用了这个修饰符

说明:由于ARM体系结构中定义了ATPCS标准,函数的前4个参数使用r0 ~ r4寄存器传递,所以asmlinkage宏实际上就是extern "C",并未使用regparm修饰

在调用实际的系统调用服务例程之前,会先将sp指针传递给r0

4.4 系统调用返回

当服务例程执行结束时,system_call从eax获得他的返回值,并把这个返回值存放在栈中,让其位于用户态eax寄存器曾存放的位置,然后执行syscall_exit终止系统调用处理程序

当进程恢复到用户态执行时,就可以从eax中找到系统调用的返回值

说明:系统调用机制优化简介

在2.6的早期版本中,系统调用的实现使用的是int 0x80和iret命令,因为需要从用户态切换到内核态执行服务例程,然后再返回用户态,所以开销很大

为了加快系统调用的速度,随后引入了vsyscalls和vDSO机制,这两种机制都是从机制上对系统调用的速度进行了优化,但是使用软中断来进行系统调用需要进行特权级切换这一根本问题并没有解决

目前X86_64体系结构使用syscall / sysret指令实现系统调用,细节就不介绍了,因为我目前也不懂

说明2:定义系统调用服务例程

在后续的Linux内核版本中,提供了一组宏,用于定义系统调用服务例程

其中宏名中的数字表示服务例程的参数个数,下面举例说明

该宏可定义sys_write函数

5. 添加新的系统调用

说明:如上文所述,根据不同的体系结构与内核版本,要修改的文件位置会有所不同,甚至要修改的文件就不同,但是思路是一致的

5.1 添加系统调用号

修改体系结构目录中的unistd.h文件,增加系统调用号

注意同步修改NR_syscalls宏,该宏表示系统调用个数,会用于判断系统调用号的合法性

5.1 添加系统调用表项

修改体系结构目录的entry.S文件,添加系统调用表项

5.3 实现系统调用服务例程

可以新建文件,也可以在原有文件中添加系统调用服务例程。如果新建文件,注意修改Makefile

此处我们选择在kernel/sys.c中新增服务例程,

注意使用asmlinage修饰符

5.4 重新编译内核

由于修改了内核源码,要使其生效,必须重新编译并布署内核

5.5 编写用户态程序

#include <unistd.h>
#include <sys/syscall.h>

#define __NR_mysyscall 289

int main(void)
{
    syscall(__NR_mysyscall);
    
    return 0;
}

此处使用syscall + 系统调用号的方式调用系统调用,并未提供系统封装例程。在Linux 2.6.18版本之前,unistd.h中提供了一组__syscall宏用于定义系统调用封装例程,下面以定义3个参数的封装例程为例加以说明

其中type & name为封装例程的返回值与函数名,之后的type & arg对用于定义函数形参

在封装例程的实现中,就是按照ABI的约定将参数通过寄存器传输,并调用int $0x80触发软中断

这里特别说明下红框中的"0",他表示输入部分仍使用和输出部分相同的寄存器,次数就是用eax传输系统调用号(系统调用号由__NR_##name构成)

说明:增加有套路,定义需谨慎

增加一个系统调用并不难,他有一套比较规范的方法,难点是在实际应用中如何增加合适的系统调用。在绝大多数情况下,我们不会新增系统调用

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux操作系统原理与应用06:系统调用 的相关文章

  • Jetson TX2入门之开箱刷机跑demo

    Jetson TX2 开箱配置 43 刷机 43 跑demo xff08 常见坑总结 xff09 简介 JetSon系列是Nvidia公司推出的面向无人智能化领域的嵌入式平台 xff0c 这块嵌入式板子的出现使得我们可以在边缘设备上处理复杂
  • 集成显卡安装pytorch

    Inter集成显卡安装pytorch 安装pytorch 计算机右键 管理 gt 设备显示器 gt 显示适配器 xff0c 查看显卡 我的电脑只有Inter的集成显卡 xff0c 没有独显 刚开始接触 xff0c 对GPU不懂 xff0c
  • ROS可视化动态查看所有topic的频率/带宽/消息类型/数值

    在程序运行或者回放数据包时 xff0c 希望实时查看到所有的正在向外发送的topic名字 类型 带宽 频率 数值等 除了rostopic list以外还可使用rqt辅助包 打开rqt rqt 选择Plugins插件 Topics信息 top
  • PID与MPC控制方法

    记录udacity 无人驾驶工程师课程中控制部分 MPC代码和实践链接https github com udacity CarND MPC Quizzes 本文按照对udacity课程的理解和翻译而来 1 PID P xff1a Propo
  • C++STL容器及其优缺点介绍

    STL容器介绍及选择方式 容器类型容器优缺点一 序列容器vectordequelistforward list xff08 C 43 43 11 xff09 queuepriority queue stackarray 二 关联容器setm
  • word中插入noteExpress和页码出现乱码解决方法

    在word中出现页码变成PAGE MERGEFORMAT xff0c noteExpress插入的代码也变成了乱码 打开出问题的word文档 xff0c 按照如下设置 xff1a 文件 选项 高级 显示文档内容 不勾选显示域代码而非阈值 修
  • FreeRTOS内核实现04:空闲任务与阻塞延时

    目录 1 引入原因 2 实现空闲任务 2 1 定义空闲任务组件 2 2 创建空闲任务 3 实现阻塞延时 3 1 vTaskDelay函数实现 3 2 修改vTaskSwitchContext函数 3 3 SysTick初始化函数实现 3 4
  • NoteExpress对参考文献格式修改

    文章目录 NoteExpress格式修改1 将带DOI的模板另存为 Revised GBT 7714 20152 编辑自定义的nes文件3 保存选择使用 NoteExpress参考文献格式修改规则GTB 7714 2015下载 NoteEx
  • ubuntu Nvidia显卡驱动安装后 屏幕不能外接显示(扩展显示)的问题

    文章目录 结论安装历程问题详细描述解决方法 结论 配置文件 etc X11 xorg conf未正确配置 xff0c 安装历程 安装显卡驱动后 xff0c 依旧无法正常扩展屏幕显示 xff0c 仔细一看发现在nvidia smi时出现No
  • ubuntu 16.04无法locate boot-repair的解决方法

    ubuntu16 04 07加windows10后无法启动ubunu的问题解决boot repair的安装方法同样适用于ubuntu18 04 ubuntu20 01等系统不能启动的问题 对boot repair修复的原理进行分析 文章目录
  • 论文降低word大小——图像免费压缩方法

    在期刊和毕业论文提交盲审过程中 xff0c 时常对word和pdf的大小进行限制 xff0c 但是在多图的论文中 xff0c 将大小限制在20MB以内较为困难 梳理以下两种方法 xff1a 1 visio图片大小压缩 visio图片插入到w
  • C/C++获取路径下所有文件及其子目录的文件名

    一 功能描述 需要提取某个文件夹下所有文件名字 xff0c 当包含子目录时 xff0c 将子目录及其路径获取到 二 实现方式 使用C语言的opendir函数 DIR span class token operator span dp spa
  • C/C++删除目录文件夹下所有文件(递归)

    一 问题 想要删除目录文件夹 xff0c 类似于rm r的操作 方式1 xff1a 可以使用system直接执行rm r的指令 xff0c system 34 rm r 34 方式2 xff1a 通过C语言内置的函数remove和rmdir
  • Git GUI 的使用

    权限校验 首先 xff0c 服务器需要身份识别 一段RSA加密字符串 启动GUI xff0c 菜单 帮助 Step1 创建密钥 Generate SSH KEY Step2 添加密钥 去你的代码托管服务器 xff0c 你的账号设置中 xff
  • 推荐系统遇上深度学习(九)--评价指标AUC原理及实践

    欢迎关注天善智能 xff0c 我们是专注于商业智能BI xff0c 人工智能AI xff0c 大数据分析与挖掘领域的垂直社区 xff0c 学习 xff0c 问答 求职一站式搞定 xff01 对商业智能BI 大数据分析挖掘 机器学习 xff0
  • VR版“半条命”大火,VR游戏迎来消费级市场的春天?

    彼之砒霜 xff0c 汝之蜜糖 2020年的艰难开局 xff0c 在让众多行业陷入困顿之际 xff0c 却让游戏业迎来了一场流量的盛宴 除了日进斗金的王者 吃鸡 xff0c 还有火爆朋友圈的动森 xff0c 一款3A级VR游戏 Half L
  • 读懂海尔智家大脑:深度体验的本质是深度生活

    了解科技行业的读者 xff0c 应该都对 大脑 这个名词不陌生 黑灯工厂 里指挥生产的 工业大脑 xff0c 繁忙机场里运筹帷幄的 航空大脑 xff0c 还有智慧城市建设的灵魂 城市大脑 如果家也有一颗总揽全局的大脑 xff0c 生活会发生
  • FreeRTOS内核实现05:支持多优先级

    目录 1 支持多优先级的方法 1 1 任务优先级 1 2 基于优先级的就绪列表 1 3 实现基于优先级的调度 2 查找最高优先级就绪任务的方法 2 1 通用方法 2 2 体系结构优化方法 3 修改代码支持多优先级 3 1 创建任务相关 3
  • 无人机和激光雷达,会是一对好cp吗?

    占据一辆无人驾驶汽车成本40 的激光雷达 xff0c 以精准和无死角的空间探测能力 xff0c 成为是无人驾驶领域不可或缺的存在 但和汽车相比 xff0c 似乎激光雷达在无人机上更有用武之地 xff1a 成像精度要求不高 行动自由范围大 成
  • Html文件读取与爬取(个人笔记篇)

    Html文件读取与爬取 xff08 个人笔记篇 xff09 文章目录 Html文件读取与爬取 xff08 个人笔记篇 xff09 html文件读取解析html数据存储爬取到的数据完整代码展示 html文件读取 1 通过open xff1a

随机推荐

  • ubuntu 安装包报:下列软件包有未满足的依赖关系:

    root 64 ubuntu usr src linux 5 0 1 apt install zlib1g dev 正在读取软件包列表 完成 正在分析软件包的依赖关系树 正在读取状态信息 完成 有一些软件包无法被安装 如果您用的是 unst
  • SLAM学习笔记(三) 后端优化与回环检测

    后端优化是对相机位姿和点位置的再度优化 xff08 相较于前端优化规模更大 xff09 xff0c 回环检测是对地图进行的一种修正 xff08 当机器人回到原来位置时 xff0c 地图也实现一个闭环 xff09 后端优化与回环检测 后端优化
  • 基于STM32 HAL库的自定义USB HID设备通信

    最近有个项目需要用到STM32的高速通信 xff0c 准备调试一下STM32的USB功能 xff0c 但是发现F103C8T6只有全速USB xff0c 因此作为HID设备一帧只能发送64字节 xff0c 最小间隔是1ms xff0c 显然
  • PX4-Autopilot安装

    Ubuntu 18 04 43 ROS Melodic 1 PX4源码下载 1 先mkdir一个文件夹 xff0c 在该文件夹下进行源码下载 xff08 因为在github下载很慢 xff0c 所以后续到PX4 Autopilot目录下再单
  • MAVROS(1)offboard模式(手动和roslaunch启动)

    官方教程 xff1a https docs px4 io master en ros mavros offboard html 1 编写功能包 参考 xff1a https blog csdn net weixin 44917390 art
  • VINS-Fusion安装

    1 安装Ceres Solver 官方教程 xff1a http ceres solver org installation html 参考教程 xff1a https blog csdn net qq 27251141 article d
  • APM-MAVROS连接

    1 运行mavros roslaunch mavros apm launch fcu url 61 34 dev ttyUSB0 921600 34 2 读取topic之前先运行以下命令 xff0c 修改飞控广播频率 rosservice
  • PX4 Avoidance(3DVFH*)

    Github地址 xff1a https github com PX4 PX4 Avoidance readme PX4用户指南 xff1a computer vision obstacle avoidance PX4 Avoidance下
  • FreeRTOS源码分析与应用开发04:消息队列

    目录 1 队列结构 2 创建队列 2 1 动态创建队列 2 1 1 xQueueCreate函数 2 1 2 xQueueGenericCreate函数 2 1 3 xQueueGenericReset函数 2 2 静态创建队列 2 2 1
  • APM-SITL Gazebo MAVROS 仿真

    1 配置APM SITL环境 1 下载安装Ardupilot 参考链接 xff1a 官方教程 注意 xff1a 文件install prereqs ubuntu sh路径在 ardupilot Tools environment insta
  • Ego-planner-swarm安装及报错解决

    项目地址 xff1a https github com ZJU FAST Lab ego planner swarmhttps github com ZJU FAST Lab ego planner swarm https github c
  • 单片机和嵌入式系统的区别

    单片机和嵌入式系统的区别 嵌入式和单片机并不是一对相对的概念 xff0c 嵌入式系统包括硬件和软件部分 xff0c 而单片机是单片微型计算机 Single Chip Microcomputer 的简称 xff0c 即微控制单元 Microc
  • 程序员的5个级别,你属于哪一个等级?

    码农和程序员虽说是调侃 xff0c 但是实质上还真的是不一样 还别说 xff0c 程序员还是有分等级的 比如有技术专家 xff0c 初级专员等 程序员的级别不同 xff0c 薪水也是有着天壤之别 免费领取Python学习资料可以加小编的微信
  • FutureTask的使用示例

    今天看书 xff0c 有关于 FutureTask 的介绍 xff0c 感觉还蛮有意思的 xff0c 可以用它来做一些比较花时间的事情 下面打个通俗的比方来说明一下它的用处 xff1a 比如 xff0c 早上一大早的去公交站台等公交 xff
  • 用脚本创建快捷方式

    64 echo off set shortCutPath 61 C Documents and Settings administrator 桌面 set shortCutName 61 报表 set StartPath 61 起始位置 s
  • activemq配置wss协议

    wss是加密协议 xff0c 必须配置https证书 span class token operator lt span sslContext span class token operator gt span span class tok
  • MATLAB 初学者 课堂笔记

    1 预定义变量 xff1a pi i j inf xff1a 无穷大 eps a xff1a a 与大于 a 的最小的浮点数之间的距离 xff0c 距离越小表示精度越高 默认a 61 1 2 矩阵运算 xff1a 左除 C 61 A B 6
  • 备赛笔记:Opencv学习:颜色识别

    OpenCV颜色识别一般要以下步骤 xff1a 1 颜色空间转换 xff0c 将BGR转换为HSV xff0c 用色调区分颜色 2 按照阈值滤出所识别的颜色 3 消除噪点 xff0c 平滑边界 3 提取连续域 xff0c 提取要识别的颜色
  • 树莓派buster安装ROS完整记录

    我敢说这一教程全网找不到相同的 我今天在安装ROS时查了各方教程 xff1a 官方Wiki xff0c Google xff0c CSDN都各查了不下10篇 xff0c 终于综合各教程内容花了大半天下好了 使用硬件及软件 xff1a 树莓派
  • Linux操作系统原理与应用06:系统调用

    目录 1 Linux中的各种接口 1 1 LSB标准 1 2 Linux API 1 2 1 概述 1 2 2 Linux内核系统调用接口 1 2 3 C标准库 1 3 Linux ABI 1 4 内核API 1 5 系统调用与各种接口的关