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, %ecx
	mov $13, %edx
	int $0x80

	mov $1, %eax
	mov $0, %ebx
	int $0x80

.data
str:
	.string "Hello world!\n"

在这里插入图片描述

  • x86_64
.text
_start:
	mov $1, %rax /* syscall write */
	mov $1, %rdi /* fd */
	mov $str, %rsi
	mov $13, %rdx
	syscall

	mov $60, %rax
	mov $0, %rdi
	syscall

.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. 文件的读写流程

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

全自动网页生成系统网站源码重构版

源码优点: 所有模板经过精心审核与修改&#xff0c;完美兼容小屏手机大屏手机&#xff0c;以及各种平板端、电脑端和360浏览器、谷歌浏览器、火狐浏览器等等各大浏览器显示。 免费制作 为用户使用方便考虑&#xff0c;全自动网页制作系统无需繁琐的注册与登入&#xff0c;直…

MongoDB 设置账号密码_mongodb设置用户名和密码

MongoDB 设置账号密码_mongodb设置用户名和密码 1、安装 安装可以看我这篇文章:https://blog.csdn.net/u014641168/article/details/123937775 2、说明 由于默认安装的MongoDB是没有设置用户密码的,极其危险,所以需要设置一下用户密码 3、创建用户 用Navicat15连接Mon…

Web组件的使用

文章目录 1 概述2 加载网页加载在线网页加载本地网页 3 网页缩放文本缩放 4 Web组件事件Web组件处理JS confirm事件 5 Web和JavaScript交互启用JavaScriptWeb组件调用JS方法JS调用Web组件方法 6 处理页面导航7 调试网络应用8 参考链接 1 概述 相信大家都遇到过这样的场景&…

Serverless 开拓无服务器时代:云计算的新趋势(下)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

SouthernBiotech抗荧光淬灭封片剂

荧光淬灭又称荧光熄灭或萃灭&#xff0c;是指导致特定物质的荧光强度和寿命减少的所有现象。引起荧光淬灭的物质称为荧光淬灭剂。SouthernBiotech专门开发的Fluoromount-G系列荧光封片剂是以甘油为基础&#xff0c;加入抗荧光淬灭剂&#xff0c;可明显降低荧光淬灭现象&#xf…

提升测试多样性,揭秘Pytest插件pytest-randomly

大家可能知道在Pytest测试生态中&#xff0c;插件扮演着不可或缺的角色&#xff0c;为开发者提供了丰富的功能和工具。其中&#xff0c;pytest-randomly 插件以其能够引入随机性的特性而备受欢迎。本文将深入探讨 pytest-randomly 插件的应用&#xff0c;以及如何通过引入随机性…

MySQL:索引失效场景总结

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

Ubuntu 22.0.4 忘记重置 MySQL 密码

Ubuntu 22.0.4 忘记重置 MySQL 密码 一、问题描述二、解决办法 一、问题描述 Ubuntu 22.0.4 忘记了 MySQL的密码&#xff0c;需要重新设置密码 环境描述&#xff1a; 系统&#xff1a;Ubuntu 22.0.4 MySQL&#xff1a;8.0.35 &#xff08;通过 apt install mysql-sever 安装的…

HarmonyOS 容器组件(Column Row Flex)

今天 我们来说容器组件中的 Column Row Flex Column 我们应该比较熟了 之前用了很多了 是一个列容器 老规矩 先来一个组件骨架 Entry Component struct Index {build() {Column({space: 30}) {}.width(100%).height(100%)} }我们在中的 Column 元素中加入代码 Column() {Co…

python统计分析——箱线图(df.boxplot)

资料来源&#xff1a;用python学统计学&#xff0c;帮助文档 使用pd.dataframe.boxplot()函数绘制箱线图 import numpy as np import pandas as pd from matplotlib import pyplot as pltdfpd.DataFrame({type:[A,A,A,A,A,A,A,A,A,A,B,B,B,B,B,B,B,B,B,B],value:[2,3,3,4,4,4…

JDBC多表联查

JDBC多表联查 在单一表进行查询时&#xff0c;只需要对表中的单个字段进行解析即可&#xff1b;例如下面代码&#xff1a; Overridepublic List<ClassBean> selectAllDao() {List list new ArrayList();try {String sql "select * from class";rs select(s…

buuctf[极客大挑战 2019]BabySQL--联合注入、双写过滤

目录 1、测试万能密码&#xff1a; 2、判断字段个数 3、尝试联合注入 4、尝试双写过滤 5、继续尝试列数 6、查询数据库和版本信息 7、查询表名 8、没有找到和ctf相关的内容&#xff0c;查找其他的数据库 9、查看ctf数据库中的表 10、查询Flag表中的字段名 11、查询表…

移远通信推出两款Wi-Fi 7模组新品,赋能无线连接巅峰体验

​1月9日&#xff0c;在2024年国际消费电子产品展览会 (CES) 期间&#xff0c;全球领先的物联网整体解决方案供应商移远通信宣布&#xff0c;正式推出支持Wi-Fi 7技术的通信模组FGE576Q和FGE573Q &#xff0c;这两款模组将以前沿的Wi-Fi性能突破无线连接边界&#xff0c;为下一…

RabbitMQ(六)消息的持久化

目录 一、简介1.1 定义1.2 消息丢失的场景 二、交换机的持久化方式一&#xff1a;直接 new方式二&#xff1a;channel.exchangeDeclare()方式三&#xff1a;ExchangeBuilder【推荐】 三、队列的持久化方式一&#xff1a;直接 new方式二&#xff1a;channel.queueDeclare()方式三…

牛客网-JAVA(错题集)-1

1 Java的抽象类和接口不可以进行实例化 2 知识点&#xff1a; 1、不论如何 finally里面的代码是一定会执行的 2、finally里面的代码块比return早执行 3、多个return是按顺序执行的&#xff0c;只执行一次 public abstract class Test {public static void main(String[] ar…

深度解析-Java语言的未来

深度解析-Java语言的未来&#xff0c;文末有我耗时一个月&#xff0c;问遍了身边的大佬&#xff0c;零基础自学Java的路线&#xff0c;适用程序员入门&进阶&#xff0c;Java学习路线&#xff0c;2024新版最新版。 文章目录 Q1 - 能否自我介绍下&#xff1f; Q2 - Java语…

diffusers scheduler add_noise前向加噪可视化

参考: http://www.bryh.cn/a/604194.html 1、diffusers Pipeline使用 import torch from diffusers import PixArtAlphaPipelinepipe = PixArtAlphaPipeline.from_pretrained("PixArt-alpha/PixArt-XL-2-1024-MS", torch_dtype=torch.float16) pipe = pipe.to(cud…

嵌入式-Stm32-江科大基于寄存器点亮LED灯

文章目录 前言&#xff1a;一&#xff1a;搭建基于寄存器控制LED的工程二&#xff1a;用江科大的STM32板子实现基于寄存器点亮LED灯三&#xff1a;用非江科大stm32板子实现基于寄存器点亮LED灯道友&#xff1a;一星陨落&#xff0c;黯淡不了星空灿烂&#xff1b;一花凋零&#…

认识Linux指令之 “find grep” 命令

01.find指令&#xff1a; -name Linux下find命令在目录结构中搜索文件&#xff0c;并执行指定的操作。 Linux下find命令提供了相当多的查找条件&#xff0c;功能很强大。由于find具有强大的功能&#xff0c;所以它的选项也很多&#xff0c;其中大部分选项都值得我们花时间来…

Set和Map

一、Set的介绍 1.1、Set相关文档介绍 cplusplus.com/reference/set/set/?kwset 1. set是按照一定次序存储元素的容器 2. 在set中&#xff0c;元素的value也标识它(value就是key&#xff0c;类型为T)&#xff0c;并且每个value必须是唯一的。 set中的元素不能在容器中修改…