03 - 系统调用

---- 整理自 王利涛老师 课程
实验环境:宅学部落 www.zhaixue.cc

文章目录

  • 1. 系统调用基本概念
    • 1.1 一个系统调用的例子
    • 1.2 什么是系统调用?软件复用的角度
  • 2. 软中断:系统调用的入口
    • 2.1 权限管理
    • 2.2 系统调用号
    • 2.4 man 2 syscall
    • 2.5 实验:arm 系统调用
    • 2.6 实验:x86 系统调用
  • 3. 系统调用接口的封装
    • 3.1 glibc
      • 3.1.1 C 标准库
      • 3.1.2 x86 平台
      • 3.1.3 arm 平台
    • 3.2 syscall
      • 3.2.1 x86_64 下
      • 3.2.2 arm 下
  • 4. 系统调用流程分析
  • 5. 添加一个系统调用
  • 6. 系统调用的开销
    • 6.1 主要开销
    • 6.2 解决之道
    • 6.2.1 快速系统调用
      • 6.2.2 虚拟系统调用:vsyscall
      • 6.2.3 虚拟动态共享对象:VDSO
        • 6.2.3.1 VDSO:virtual dynamic shared object
        • 6.2.3.2 VVAR:VDSO data page
        • 6.2.3.3 实验:反汇编 VDSO 动态库
  • 7. 文件的读写流程

1. 系统调用基本概念

1.1 一个系统调用的例子

在这里插入图片描述

1.2 什么是系统调用?软件复用的角度

main.c – add() – add.c add.h add.o ⇒ ar ⇒ libmath.so / libmath.a
main.c – sub() – sub.c sub.h sub.o ⇒ ar ⇒ libmath.so / libmath.a

  • glibc – 默认链接
  • OS:硬件资源的封装,任务创建、调度,读写磁盘等
    如 ucos:OSInit() – OSTaskCreate() – 创建一个任务
    如 Linux:手机、电脑,底层的硬件、OS、上层 App
    权限管理:内核态、用户态
    系统调用:App – 陷入内核态 – 访问硬件设备

2. 软中断:系统调用的入口

2.1 权限管理

  • 程序的用户态、内核态
  • 操作系统 + CPU 软中断:swi / svc
  • CPU 的运行级别:普通权限 & 特权
    • ARM32:
      • 普通模式:User
      • 特权模式:FIQ、IRQ、SVC、ABT、UND
    • ARM64:EL0、EL1、EL2、EL3
    • X86:ring0 ~ ring3

2.2 系统调用号

  • 系统调用接口:read、write
  • 内核中的实现:sys_read、sys_write
  • 系统调用号:
    • 32 位 ARM:3、4
    • 64 位 ARM:0、1
    • 32 位 X86:3、4
    • 64 位 X86:0、1

2.4 man 2 syscall

man 2 syscall

在这里插入图片描述
在这里插入图片描述

2.5 实验:arm 系统调用

.text
.global _start_start:mov r0, #1             /* stdout*/add r1, pc, #16        /* address of the string*/mov r2, #12            /* string length*/mov r7, #4             /*syscall for 'write'*/swi #0                 /* software interrupt*/_exit:mov r7, #1             /* syscall for 'exit'*/swi #0                 /* software interrupt*/_string:
.asciz "Hello world\n"          @ our string, NULL terminated

在这里插入图片描述

在这里插入图片描述

2.6 实验:x86 系统调用

  • x86_32
.text
_start:mov $4, %eax /* syscall write */mov $1, %ebx /* fd */mov $str, %ecxmov $13, %edxint $0x80mov $1, %eaxmov $0, %ebxint $0x80.data
str:.string "Hello world!\n"

在这里插入图片描述

  • x86_64
.text
_start:mov $1, %rax /* syscall write */mov $1, %rdi /* fd */mov $str, %rsimov $13, %rdxsyscallmov $60, %raxmov $0, %rdisyscall.data
str:.string "Hello world!\n"

在这里插入图片描述

3. 系统调用接口的封装

3.1 glibc

3.1.1 C 标准库

  • 包含一系列系统调用接口的封装
    read、write、fork、open …

3.1.2 x86 平台

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.1.3 arm 平台

在这里插入图片描述
在这里插入图片描述

3.2 syscall

  • 在 C 标准库中没有封装的系统调用
  • syscall 是一个库函数
  • syscall 封装了系统调用的汇编接口
    • 系统调用前保存 CPU 寄存器
    • 从系统调用返回后,恢复寄存器

3.2.1 x86_64 下

#include <stdio.h>
#include <unistd.h>int main(void)
{printf("Hello world!\n");write(1, "Hello world!\n", 13);// 系统调用号1  标准输出 字符串内容 字符串长度syscall(1, 1, "Hello syscall!\n", 15);return 0;
}

在这里插入图片描述

3.2.2 arm 下

#include <stdio.h>
#include <unistd.h>int main(void)
{printf("Hello world!\n");write(1, "Hello world!\n", 13);// 系统调用号4  标准输出 字符串内容 字符串长度syscall(4, 1, "Hello syscall!\n", 15);return 0;
}

在这里插入图片描述

4. 系统调用流程分析

  • 示例:kill
  • 接口封装: /usr/arm-linux-gnueabi/lib/libc.a
  • 系统调用号: arch/arm/include/generated/calls-eabi.S
  • 内核实现: kernel/signal.c
  • 中断处理: arch/arm/kernel/entry-common.S
// kernel\linux-5.10.4\arch\arm\include\generated\uapi\asm\unistd-common.h
...
#define __NR_kill (__NR_SYSCALL_BASE + 37) // 系统调用号
...
// kernel\linux-5.10.4\include\linux\syscalls.h
...
asmlinkage long sys_kill(pid_t pid, int sig); // 系统调用函数声明
asmlinkage long sys_tkill(pid_t pid, int sig);
asmlinkage long sys_tgkill(pid_t tgid, pid_t pid, int sig);
...// kernel\linux-5.10.4\kernel\signal.c
...
/***  sys_kill - send a signal to a process*  @pid: the PID of the process*  @sig: signal to be sent*/
SYSCALL_DEFINE2(kill, pid_t, pid, int, sig) // 系统调用函数实现
{struct kernel_siginfo info;prepare_kill_siginfo(sig, &info);return kill_something_info(sig, &info, pid);
}
...
// kernel\linux-5.10.4\arch\arm\include\generated\calls-eabi.S
...
NATIVE(37, sys_kill) // 中断向量表
...// kernel\linux-5.10.4\arch\arm\kernel\entry-common.S
// 中断处理程序

5. 添加一个系统调用

  1. 增加内核对应的实现函数
  2. 在系统调用表中增加一个系统调用号及入口
  3. 编写测试程序:在应用层发起系统调用

在这里插入图片描述
在这里插入图片描述

6. 系统调用的开销

6.1 主要开销

  • 中断
  • 抢占系统、任务调度
  • 同步
  • IO 等待

6.2 解决之道

  • 快速系统调用:fast system call
  • 虚拟系统调用:vsyscall
  • 虚拟动态共享对象:VDSO

6.2.1 快速系统调用

  • x86 处理器
    • 专门为系统调用设计的汇编指令
      Intel:sysenter、sysexit
      AMD:syscall、sysret
    • 简化了系统调用和返回流程
    • 预加载参数、不做权限检查
    • 不再查表,直接从寄存器取值,实现快速跳转:MSR 寄存器
    • 不需要保存地址和返回地址等信息

6.2.2 虚拟系统调用:vsyscall

在这里插入图片描述

proc/<PID>/maps
# 查看进程的虚拟地址空间是如何使用的。
  • 编程实验:获取当前系统时间
  1. 使用系统调用 time 获取当前时间
  2. 使用虚拟系统调用接口获取当前时间
  3. 比较 1 和 2 的结果并分析
    原先:app – time – int 80h / syscall – kernel – sys_time – user space
    现在:app – time – vsyscall – user space (效率更高)
#include <stdio.h>
#include <time.h>typedef time_t (*time_fp)(time_t *);int main(void)
{time_t t1, t2;t1 = time(NULL);time_fp fp = (time_fp)0xffffffffff600400; // 可以下载 glibc-2.22 之前的版本,// 搜索:grep -nr VSYSCALL_ADDR_vtime 查看这里的地址。t2 = fp(NULL);printf("t1 = %ld\n", t1);printf("t2 = %ld\n", t2);return 0;
}

在这里插入图片描述

6.2.3 虚拟动态共享对象:VDSO

  • vsyscall 的局限性
    • 分配的内存有限
    • 只支持 4 个系统调用
    • 在进程中的位置是静态的、固定的,易受攻击
  • VDSO 的改进
    • 提供超过 4 个系统调用
    • 在进程中的地址是随机的。如:time
6.2.3.1 VDSO:virtual dynamic shared object
  • # cat /proc/self/maps (6.2.2 中演示)
  • 源码在内核中实现
    arch/arm/kernel/vdso.c
    关键函数:vdso_mremap、install_vvar
  • 速度最快
  • 开销最小,基本等价于函数调用开销
6.2.3.2 VVAR:VDSO data page
  • struct vdso_data
6.2.3.3 实验:反汇编 VDSO 动态库
  1. 将 VDSO 指令从内存中 dump 出来
  2. 反汇编为汇编代码
  3. 分析汇编代码

在这里插入图片描述

可以关闭随机地址功能:echo 0 > /proc/sys/kernel/randomize_va_space

在这里插入图片描述

可以通过:cat /proc/self/smaps 查看 vdso 大小。(输出内容较多,截取 vdso 大小的部分如下)

在这里插入图片描述

  1. 将 VDSO 指令从内存中 dump 出来

在这里插入图片描述

  1. 反汇编查看:objdump -T 显示文件的动态符号表入口,仅仅对动态目标文件有意义,比如某些共享库

在这里插入图片描述

起始地址:0x7ffff7fcd000
偏移:0x9e0

  1. 分析
#include <stdio.h>
#include <time.h>typedef time_t (*time_fp)(time_t *);int main(void)
{time_t t1, t2;t1 = time(NULL);time_fp fp = (time_fp)(0x7ffff7fcd000 + 0x9e0); // 见上述2,起始地址 + 偏移t2 = fp(NULL);printf("t1 = %ld\n", t1);printf("t2 = %ld\n", t2);return 0;
}

在这里插入图片描述

7. 文件的读写流程

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/612233.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

优化 ParamValidator,让编辑器Pycharm智能提示校验方法

目录 一、前置说明1、总体目录2、相关回顾3、本节目标 二、操作步骤1、项目目录2、代码实现3、测试代码4、日志输出 三、后置说明1、要点小结2、下节准备 一、前置说明 1、总体目录 《 pyparamvalidate 参数校验器&#xff0c;从编码到发布全过程》 2、相关回顾 基于 Valid…

基于JavaWeb+BS架构+SpringBoot+Vue基于web的多媒体素材管理系统的设计和实现

基于JavaWebBS架构SpringBootVue基于web的多媒体素材管理系统的设计和实现 文末获取源码Lun文目录前言主要技术系统设计功能截图订阅经典源码专栏Java项目精品实战案例《500套》 源码获取 文末获取源码 Lun文目录 1 绪 论 1 1.1选题背景与意义 1 1.1 研究背景 1 1.2 研究意义…

网络安全工具:通过监控分析日志数据保护企业网络

由于混合工作模式的兴起以及业务运营向云环境的迁移&#xff0c;企业网络变得更加分散和复杂&#xff0c;仅安装外围安全解决方案只会创建一个基本的防御层&#xff0c;系统、服务器和其他网络实体会生成记录所有网络活动的日志。集中式日志管理系统可以帮助管理员自动监控网络…

手机直连卫星及NTN简介

一、手机直连卫星的发展现状 近日&#xff0c;华为推出了支持北斗卫星短报文的Mate 50旗舰机、P60系列&#xff0c;苹果也跟Globalstar&#xff08;全球星&#xff09;合作推出了支持卫星求救的iPhone14&#xff0c;最亮眼的还是华为的。这几款产品揭开了卫星通信探索消费领域…

Spring MVC 参数传递和JSON数据处理

参数传递 ModelAndView传递 编写controller Controller RequestMapping("/account") public class AccountController { ​//也可以不创建ModelAndView&#xff0c;直接在参数中指定RequestMapping(value "/findAccount9")public ModelAndView findAccou…

美国证券交易委员会 X 账户被黑,引发比特币市场震荡

Bleeping Computer 网站消息&#xff0c;威胁攻击者成功“占领”了美国证券交易委员会的 X 账户&#xff0c;并发布一条关于批准比特币 ETF 在证券交易所上市的虚假公告。 帖子原文&#xff1a;今天&#xff0c;美国证券交易委员会批准比特币 ETF 在注册的国家证券交易所上市&a…

MySQL:索引失效场景总结

1 执行计划查索引 通过执行计划命令可以查看查询语句使用了什么索引。 EXPLAIN SELECT * FROM ods_finebi_area WHERE areaName = 福建 执行查询计划后,key列的值就是被使用的索引的名称,若key列没有值表示查询未使用索引。 2 在什么列上创建索引 (1)列经常被用于where…

Map与JSONObject区别

相同点&#xff1a; 都可以存key-value&#xff1b;key是唯一的,如果key重复了会覆盖前面的 不同点&#xff1a; &#xff08;1&#xff09;JSONObject 不可以存空&#xff0c;Map可以存空。 &#xff08;2&#xff09;Map由jdk提供&#xff0c;JsonObject需要第三方jar包提供。…

XUbuntu22.04之快速复制绝对路径(二百零五)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

Windows启动MongoDB服务报错(错误 1053:服务没有及时响应启动或控制请求)

问题描述&#xff1a;修改MongoDB服务bin目录下的mongod.cfg&#xff0c;然后在任务管理器找到MongoDB服务-->右键-->点击【开始】&#xff0c;启动失败无提示&#xff1a; 右键点击任务管理器的MongoDB服务-->点击【打开服务】&#xff0c;跳转到服务页面-->找到M…

一级倒立摆控制 - 非线性 MPC 控制及 MATLAB 实现

系列文章目录 前言 本示例使用非线性模型预测控制器对象和块实现对小车上倒立摆的摆动和平衡控制。 本示例需要 Optimization Toolbox™ 软件为非线性 MPC 提供默认的非线性编程求解器&#xff0c;以计算每个控制间隔的最优控制动作。 一、摆锤/小车装配 本例中的被控对象是…

ChatGPT本地部署,学习记录

一、GPT4ALL模型 官网地址&#xff1a; Github&#xff1a;https://github.com/nomic-ai/gpt4all GPT4ALL项目部署简易&#xff0c;但是在运行体验上一般&#xff0c;并且是只调用CPU来进行运算。 看官方文档介绍在嵌入式上有比较大的优势&#xff0c;但是目前个人对嵌入式…

ffmpeg写YUV420文件碰到阶梯型横线或者条纹状画面的原因和解决办法

版权声明&#xff1a;本文为CSDN博主「文三~」的原创文章&#xff0c;遵循CC 4.0 BY-SA版权协议&#xff0c;转载请附上原文出处链接及本声明。 原文链接&#xff1a;https://blog.csdn.net/asdasfdgdhh/article/details/112831581 留作备份 阶梯型横线&#xff1a; 条纹状画面…

CloudCompare——拟合空间球

目录 1.拟合球2.软件操作3.算法源码4.相关代码 本文由CSDN点云侠原创&#xff0c;CloudCompare——拟合空间球&#xff0c;爬虫自重。如果你不是在点云侠的博客中看到该文章&#xff0c;那么此处便是不要脸的爬虫与GPT生成的文章。 1.拟合球 源码里用到了四点定球&#xff0c;…

[笔记]学习做微信小程序

学习视频&#xff1a;前端微信小程序开发教程 本篇文章 只对关键内容笔记&#xff0c;用于自用。 这里写目录标题 注册、下载、安装我的小程序ID&#xff1a;wxe1fbd6939d8797d8我的小游戏ID&#xff1a;wx8b2c3e47ac9127b7开发者工具外观代理设置 创建第一个小程序主界面5个组…

QT开发 2024最新版本优雅的使用vscode开发QT

▬▬▬▬▬▶VS开发QT◀▬▬▬▬▬ &#x1f384;先看效果 &#x1f384;编辑环境变量 如图添加环境变量&#xff01;&#xff01;&#xff01; 东西全在QT的安装目录&#xff01;&#xff01;&#xff01; 找到的按照我的教程再装一次&#xff01;&#xff01;&#xff01; 点…

postman 之 接口请求

一、前言 1. 安装 2. 主界面 3. 请求区域 Body下主要包含以下4中格式 form-data&#xff1a;混合表单&#xff0c;支持上传文件x-www-form-urlencoded&#xff1a;文本表单raw&#xff1a;原始格式&#xff0c;支持JSON/XML格式&#xff08;后面可选择&#xff09;binary&am…

Camunda Event Based Gateway

一&#xff1a;bpmn 二&#xff1a;java 如果没有收到信号&#xff0c;超过等待时间&#xff0c;流程进入总经理审批&#xff0c;如果在等待时间内收到信号&#xff0c;流程进入副总经理审批。 示例1&#xff1a;发送信号事件&#xff0c;流程进入副总经理审批。 repository…

yolo 分割label格式标注信息图片显示可视化查看

参考: https://github.com/ultralytics/ultralytics/issues/3137 https://blog.csdn.net/weixin_42357472/article/details/135218349?spm=1001.2014.3001.5501 需要把坐标信息在图片上显示 代码 1)只画出了坐标边缘 import cv2 import numpy as np from random impor…

AlexNet论文精读

1:该论文解决了什么问题&#xff1f; 图像分类问题 2&#xff1a;该论文的创新点&#xff1f; 使用了大的深的卷积神经网络进行图像分类&#xff1b;采用了两块GPU进行分布式训练&#xff1b;采用了Relu进行训练加速&#xff1b;采用局部归一化提高模型泛化能力&#xff1b;…