linux syscall和int 80的区别

前言

syscallint 80是中断指令,Linux通过对这两个指令的封装为开发者们提供的一种用户态切换至内核态的方法,因为在处理器中用户态没有权限向更高的权限空间切换的,以x86为例,它只允许高权限向低权限切换或同等权限切换,不允许低权限向高权限切换。但是处理器保留了一个机制,就是当产生中断时(无论是任何中断)都会让处理器切换权限并跳转至中断处理函数里,而中断处理函数又由内核注册所以就完成了用户态到内核态的切换

Tips
本文以X86架构为例

中断与普通函数的区别

中断与普通的函数调用是有区别的,一般最大的区别是返回值上面,一般普通函数调用是存在返回值的,相比之下函数调用的开销一般比中断函数要大,普通函数在调用时遵循的是函数调用约定(Calling Convention),这些约定定义了哪些寄存器需要由调用者(Caller)处理,哪些寄存器需要由被调用者(Callee)处理,例如调用者需要使用参数寄存器来传递参数然后通过call发起调用,而被调用者需要接收这些参数并执行代码体同时还需要使用返回寄存器来存储返回值和跳转回之前的代码段并进行现场恢复,这些约定都是由ISO或处理器厂商定义的。
一般的情况下函数调用使用的寄存器是通用寄存器,并且函数调用不涉及到切换堆栈,只涉及到堆栈增长
函数调用通常使用下面这些寄存器:
通用寄存器:EAX, EBX, ECX, EDX, ESI, EDI, EBP, ESP等。
浮点寄存器:ST0-ST7(在使用浮点运算时)。
SIMD寄存器:XMM0-XMM7(在使用SSE指令集时)。
而中断是为了快速响应而涉及的,它没有参数没有返回值,也不会有堆栈切换,它切换到内核态之后由内核态做堆栈现场保护堆栈切换,在返回时也由内核来恢复堆栈
同时它们的调用也不一样,函数调用使用的是call指令,中断是int,并且中断通常是由硬件自动触发的,返回的指令也有所不同,函数调用是RET,中断是IRET
并且RET指令是不会清理堆栈的也不会恢复堆栈寄存器,而IRET指令执行之后CPU自动清理堆栈恢复堆栈寄存器(ESP/SS)

int 80

0x80属于处理器的一个中断号,它是IDT表的第0x80号中断,int是处理器中触发中断的一个指令,当产生中断时CPU会以0x80为索引到IDT表中取到中断函数入口地址并进行跳转,在跳转时CPU会进行权限切换,在x86里内核态的权限为ring 0,用户态为最低级别的ring 3,为方便内核处理中断CPU会在产生中断时先将当前上下文进行保存,然后切换到中断函数里去执行,由于x86架构权限设计的限制,所以想要切换到内核态只能由中断来进入,所以Linux依靠这一点为用户态提供了调用内核功能的能力,因为用户态是不能访问实际物理设备的所以只能通过内核来访问,例如我们平时所使用的readwrite内部其实都是使用了int 80来调用内核态帮我们完成工作。
以下是printf调用write输出到屏幕的汇编代码,write内部会调用sys_write:

sys_write(unsigned int fd, const char * buf, size_t count)
[section .data]
strHello db “Hello, world!,0Ah
STRLEN equ $ - strHello
[section .text]
global _start
_start:
mov edx,STRLEN			;将count保存到eda寄存器
mov ecx,strHello		;将buf保存到ecx寄存器
mov ebx,1				;将fd参数保存到ebx寄存器,这里fd=1,对应的是stdout
mov eax,4				;调用sys_write, 系统调用号为4
int 0x80				;产生中断

当执行int 0x80之后就会进入到IDT索引为0x80的中断函数里,这个中断函数会读取eax寄存器里的值然后去调用sys_call_table数组里存放的函数,可以在linux/kernel/system_call.s代码里找到调用过程:

movl $0x10,%edx       			# set up ds, es to kernel space
mov %dx,%ds
mov %dx,%es
movl $0x17,%edx       			# fs points to local data space
mov %dx,%fs
call _sys_call_table(,%eax,4)   # %eax contains the index (NR_write)
pushl %eax

这里linux设计的非常精明,_sys_call_table里的元素是按系统调用顺序来排列的,这样就可以把eax作为偏移来调用,4是偏移量,作为乘数,在32位操作系统里地址是以4字节偏移的,下面是sys_call_table的定义。

fn_ptr sys_call_table[] = {sys_setup, sys_exit, sys_fork, sys_read, sys_write,sys_open, sys_close, sys_waitpid, sys_creat, sys_link,sys_unlink, sys_execve, sys_chdir, sys_time, sys_mknod,sys_chmod, sys_chown, sys_break, sys_stat, sys_lseek,sys_getpid, sys_mount, sys_umount, sys_setuid, sys_getuid,sys_stime, sys_ptrace, sys_alarm, sys_fstat, sys_pause,sys_utime, sys_stty, sys_gtty, sys_access, sys_nice,sys_ftime, sys_sync, sys_kill, sys_rename, sys_mkdir,sys_rmdir, sys_dup, sys_pipe, sys_times, sys_prof,sys_brk, sys_setgid, sys_getgid, sys_signal, sys_geteuid,sys_getegid, sys_acct, sys_phys, sys_lock, sys_ioctl,sys_fcntl, sys_mpx, sys_setpgid, sys_ulimit, sys_uname,sys_umask, sys_chroot, sys_ustat, sys_dup2, sys_getppid,sys_getpgrp, sys_setsid, sys_sigaction, sys_sgetmask, sys_ssetmask,sys_setreuid, sys_setregid
};

syscall

既然已经知道了int 80的意义,那么syscall与它一样,都是产生中断的方式,它是处理器为提升系统调用效率而开发的新的指令,目前linux已经使用syscall来替代int 80了,syscall的系统调用地址由IA32_LSTAR寄存器记录,这个寄存器里会存放系统调用的入口函数地址,当执行syscall指令时CPU会去读取IA32_LSTAR寄存器里的地址并跳转,一个完整的syscall由三个寄存器组成:IA32_LSTARIA32_STARIA32_FMASK, 它们的作用分别如下:
IA32_LSTAR: 配置内核态代码段选择子。
**IA32_STAR: ** 配置用户态代码段选择子。
**IA32_FMASK: ** 指定系统调用过程中需要屏蔽的标志位。
IA32_LSTARIA32_STAR分别对应高32位低32位,可以把它俩看成一个寄存器IA32_STAR存储的是返回用户态时的地址,当执行syscall时会跳转IA32_LSTAR的地址,当处理完成时需要调用sysret来返回用户态,则跳转的就是IA32_STAR的地址IA32_FMASK用来控制在执行系统调用时需要屏蔽的特权标志位,确保系统调用执行时的状态是安全的,例如屏蔽中断(IF)陷阱中断(TF)方向标志位(DF),屏蔽这些标志位以保证系统能够正确稳定的执行系统调用。

Tips
中断: 计算机系统中的机制,用于处理异步事件或外部信号。它允许计算机在处理当前任务时,立即响应高优先级的事件,从而提高系统的响应性和效率,中断分为硬件中断和软件中断,硬件中断是由硬件产生中断信号给CPU由CPU转入IDT表中处理,软件中断是由软件调用CPU特定指令来产生中断让CPU进入中断函数进行处理
陷阱中断: 跟踪标志位主要作用是控制处理器进入单步操作方式。‌ 当陷阱标志位被设置为1时,‌处理器会以单步执行的方式运行指令,‌即处理器在每条指令执行结束后,‌都会产生一个编号为1的内部中断,‌这种内部中断被称为单步中断
方向标志位: 用于控制字符串操作指令的处理方向。这个标志位用于决定在执行字符串操作指令(如 MOVS, CMPS, SCAS, LODS, STOS)时,处理的数据是向内存地址增加还是减少

syscall与int 80的区别在哪里?

最大的区别就是效率上,以x86为例,intel推出syscall就是为了替代int 80中断效率的,int 80是通用中断,它产生中断的流程与硬件中断一致,在进行中断切换时会进行现场保护其次会去查找IDTIDT是存放在内存当中的,CPU首先需要去IDTR里将IDT地址读取出来,然后在根据索引到IDT表里找到对应入口地址然后在进行跳转,同时还需要保存所有寄存器的值如 EAX, EBX, ECX, EDX, ESI, EDI, EBP 等,而syscall是特殊设计,它只保存必要的恢复寄存器,例如EIP,返回地址是存储在IA32_STAR里的,它所需要的操作极少,同时在切换堆栈时也会进行堆栈保存,但是它是从MSR寄存器中获取内核堆栈,而通用中断则是从TSS中获取,TSS存在于内存当中,TSS的基地址存放在TR寄存器中,产生中断时需要先从TR寄存器获取到TSS任务状态段然后去里面查找内核的堆栈在进行切换。
至于堆栈的保护这些一般是由操作系统来使用汇编代码保存,CPU的设计时只会规定寄存器的使用,但它不是一定的,是灵活的,操作系统可以自由决定使用什么寄存器或内存来保存那些想要保存的数据信息。

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

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

相关文章

Python 爬虫入门(一):从零开始学爬虫 「详细介绍」

Python 爬虫入门(一):从零开始学爬虫 「详细介绍」 前言1.爬虫概念1.1 什么是爬虫?1.2 爬虫的工作原理 2. HTTP 简述2.1 什么是 HTTP?2.2 HTTP 请求2.3 HTTP 响应2.4 常见的 HTTP 方法 3. 网页的组成3.1 HTML3.2 CSS3.…

《梦醒蝶飞:释放Excel函数与公式的力量》23.2 项目评估与反馈

第23章:学生项目展示 23.2 项目评估与反馈 在学生项目展示中,项目评估与反馈是至关重要的一环。通过评估和反馈,可以识别项目中的优点和不足,帮助学生不断改进和提升。以下是项目评估与反馈的详细步骤和示例。 项目评估的关键要…

数据分析:微生物数据的荟萃分析框架

介绍 Meta-analysis of fecal metagenomes reveals global microbial signatures that are specific for colorectal cancer提供了一种荟萃分析的框架,它主要基于常用的Wilcoxon rank-sum test和Blocked Wilcoxon rank-sum test 方法计算显著性,再使用分…

Kafka核心知识点整理,值得收藏!

消息队列应用场景 提高系统性能:通过异步处理减少响应时间。削峰/限流:应对高并发场景。降低系统耦合性:解耦生产者和消费者。 消息队列对比 Kafka:高吞吐量,适合日志收集和传输,适合大型公司。RocketMQ…

SpringBoot启动命令过长

Error running DromaraApplication: Command line is too long. Shorten command line for DromaraApplication or also for Spring Boot default configuration?

线上环境服务器CPU飙升排查

前因 收到线上服务器CPU使用率100%的告警信息。 环境 jdk1.8CentOS Linux ;CentOS Linux 排查 查看服务器CPU使用率 果然cpu已经达到了100%了 命令 top 使用arthas工具 使用方式 arthas 执行命令java -jar arthas-boot.jar 然后执行命令 thread 看到有两个…

【linux】Shell脚本三剑客之awk命令的详细用法攻略

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全…

【基础教程】Tutorial on Pytorch 结合官方基础文档和个人经验

参考与前言 此教程首次书写于2021年12月份 至 2022年4月份间不断补充;阅读本文时可以对着代码运行查看 官方网址:https://pytorch.org/tutorials/ 【基本从这里翻译而来 更简洁版碎碎念】https://pytorch.org/tutorials/beginner/blitz/cifar10_tutori…

vue3+element-plus 实现动态菜单和动态路由的渲染

在 Vue.js 中,使用 Vue Router 管理路由数据,并将其用于渲染 el-menu(Element UI 的菜单组件)通常涉及以下几个步骤: 定义路由元数据: 在你的路由配置中,为每个路由项添加 meta 字段&#xff0c…

无人机10公里WiFi图传摄像模组,飞睿智能超清远距离无线监控,智能安防新潮流

在这个科技日新月异的时代,我们对影像的捕捉和传播有了更高的要求。从传统的有线传输到无线WiFi图传,每一次技术的飞跃都为我们带来了全新的视觉体验。今天,我们要探讨的,正是一款具有划时代意义的科技产品——飞睿智能10公里WiFi…

自学网络安全,从小白到大神的破茧之路!

在当今数字化高速发展的时代,网络安全已经成为了至关重要的领域。无论是个人的隐私保护,还是企业、国家的关键信息资产维护,都离不开网络安全的有力保障。出于对这一领域的浓厚兴趣以及对未来职业发展的清晰规划,我毅然决然地踏上…

0722_驱动1 字符设备驱动框架

一、字符设备驱动框架 字符设备驱动按照字节流进行访问,并且只能顺序访问 设备号一共有32位,主设备号(高12位)次设备号(低20位) 二、注册/注销字符设备驱动API接口 2.1、注册字符设备驱动(入口) #include &…

树莓派智能家居中枢

一个先进的枢纽,使智能家居系统更智能、更可定制、更易于控制 Homey Pro由树莓派 Compute Module 4 供电,Homey Pro 为用户提供了一个单一界面,用于控制和监控来自不同品牌的所有智能家居设备。它完全在本地网络上运行,而不是依赖云端,从而实现了最低的延迟、最高的…

深入理解CSS中的变量(应用篇)

在现代Web开发中,换肤功能已经成为提升用户体验的重要手段之一。通过使用CSS变量和JavaScript,我们可以轻松实现动态换肤功能。本文将介绍如何动态生成和应用CSS变量来实现换肤效果。 1. 定义基础CSS变量 首先,我们在CSS中定义一些基础的CSS变量。这些变量将用于存储不同主…

测试面试宝典(三十三)—— 接口测试有没有测试出什么问题?

在之前的接口测试工作中,确实发现了一些问题。比如,在对某关键业务接口进行测试时,发现当输入的参数值超出正常范围时,接口没有按照预期返回错误提示,而是出现了系统崩溃的情况。 还有一次,在测试一个数据…

关于任务栏设置闪退的一种解决方法

昨天我用了下360安全卫士,就发现我的任务栏变成了小任务栏模式。我想把它关掉,于是想要打开任务栏设置,然后就发现任务栏设置闪退。 我去晚上找了许多方法,像是卸载360,用指令修补破损文件,重启电脑等等&am…

【PostgreSQL教程】PostgreSQL 删除表格

博主介绍:✌全网粉丝20W+,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物联网、机器学习等设计与开发。 感兴趣的可…

docker发布镜像到自己远程私有仓库

1、登录docker hub创建自己的仓库地址:https://hub.docker.com/repository/create 输入仓库名称 2.构建镜像 略过。。。。请自己查找别的资料,此篇文章只讲述镜像推送到远程 3.推送 假设你已经构建了一个镜像 web/online-editor:latest,现…

推荐系统三十六式学习笔记:工程篇.常见架构25|Netflix个性化推荐架构

目录 架构的重要性经典架构1.数据流2.在线层3.离线层4.近线层 简化架构总结 你是否曾经觉得算法就是推荐系统的全部,即便不是全部,至少也是嫡长子,然而实际上,工程实现才是推荐系统的骨架。如果没有好的软件实现,算法不…