首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么` `write()`是通过`call`指令而不是中断来执行的?

write()是通过call指令而不是中断来执行的原因如下:

  1. write()函数是一个系统调用,用于将数据写入文件或设备。系统调用是用户程序与操作系统之间的接口,用于访问操作系统提供的服务和资源。在执行系统调用时,用户程序需要切换到内核态,这需要一些特殊的处理。
  2. 中断是一种由硬件或软件触发的事件,用于打断正在执行的程序,转而执行相应的中断处理程序。中断通常用于处理硬件设备的输入/输出操作,例如键盘输入、磁盘读写等。中断处理程序通常是事先定义好的,用于处理特定的中断事件。
  3. 在执行系统调用时,用户程序需要切换到内核态,这是因为系统调用需要访问操作系统的内部资源和功能。为了实现这种切换,操作系统提供了特殊的指令,例如call指令。
  4. call指令用于在程序中调用一个子程序或函数,并将控制权转移到该子程序中执行。当用户程序调用write()函数时,通过call指令将控制权转移到操作系统内核中的相应系统调用处理程序。这样可以确保在执行系统调用时,用户程序能够正确地切换到内核态,并且操作系统能够提供相应的服务。

总结起来,write()是通过call指令而不是中断来执行的,是因为系统调用需要用户程序切换到内核态,并且操作系统提供了特殊的指令来实现这种切换。中断通常用于处理硬件设备的输入/输出操作,而系统调用是用户程序与操作系统之间的接口,用于访问操作系统提供的服务和资源。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

详解linux系统调用原理

库函数 与 系统调用处理函数 之间,由于涉及用户态与内核态切换,要复杂一些。 Linux 通过中断 实现从 用户态 到 内核态 切换。...用户态 与 内核态 独立执行流,因此在切换时,需要准备 执行栈 并保存 寄存器 。 内核实现了很多不同系统调用(提供不同功能), 系统调用处理函数 只有一个。...因此,用户进程必须传递一个参数用于区分,这便是 系统调用号 ( system call number )。 在 Linux 中, 系统调用号 一般通过 eax 寄存器 传递。...总结起来, 执行态切换 过程如下: 应用程序 在 用户态 准备好调用参数,执行 int 指令触发 软中断中断号为 0x80 ; CPU 被软中断打断后,执行对应 中断处理函数 ,这时便已进入 内核态...并从 内核栈 中恢复 寄存器 ; 系统调用处理函数 执行 ret 指令切换回 用户态 ; 编程实践 下面,通过一个简单程序,看看应用程序如何在 用户态 准备参数并通过 int 指令触发 软中断

4.2K43

操作系统接口和调用--02

即用户怎么用操作系统?.. ---- 会学习从会问问题开始… 操作系统接口并不是直接暴露给用户使用,用户通过应用软件间接调用到操作系统接口。 ---- 命令行怎么回事?...因此就有了IEEE制定统一操作系统相关接口。 例如上面讲到printf函数,底层就是通过调用操作系统提供write接口完成对屏幕输出操作。...---- 硬件提供了“主动进入内核方法” 硬件提供了中断功能,让程序可以调用操作系统相关接口,当调用int指令进行中断时候,会将CS中CPL设置为0,然后去调用内核区中系统接口。...当中断程序执行结束后,会将CPL重新设置为3,回到用户态 如果还不清楚,也可以看看下面这篇文章分析: 系统调用:用户级函数如何通过INT 80中断进入操作系统内核 ---- 中断处理程序: system_call...) 执行system_call内核函数,通过传入系统调用号,去函数表中定位到对应函数,然后执行函数 ----

41420
  • 从一个简单汇编程序学习linux下系统调用机制

    (system call),其类似C语言中函数,可在程序中直接调用,也即 write(1,msg,len)和 exit(0)。...系统中断-操控内核关键 1、什么系统中断?...任何CPU在检测到从外部发来或内部产生中断信息时候,都需要立即处理所接受到信息,CPU在不再接着向下执行刚才指令,转而去处理中断信息过程就叫中断中断有内中断和外中断之分。...内中断又有以下几种情况: 除法错误 单步执行 执行into指令 执行int指令 2、 int0x80是什么? 在CPU设计之初,中断信息中包含有标识中断类型码。...中断类型码作用是用来定位中断处理程序执行int指令, intnn为中断类型码,其功能为引发中断过程。 int0x80,即中断号为0x80,其上层应用程序与内核进行交互通信唯一接口。

    86420

    Go 语言汇编入门

    为什么要学 Go 语言汇编 首先是要破除迷信,同一个问题网上答案众说纷纭,比如到底传值还是传引用争论不休,不如静下心看一下汇编踏实。...学习 Go 语言汇编不是为了以后用汇编做开发,只是可以用通过阅读汇编深刻理解 Go 语言背后实现细节,真正精通这门语言,在使用过程中可以更加安心。...接下来指令 .globl _start,这里并没有拼错,不是 global,_start 一个标签。接下来真正汇编指令部分了。...接下来指令 int $0x80,前面介绍过,这是一条中断触发指令,把执行流程交给内核继续处理,应用程序不用关心内核如何处理,内核处理完会把执行流程还给应用程序,同时根据执行成功与否设置全局变量 errno...接下来指令实际上执行 exit(0) 退出程序,指令和逻辑与之前一样,不再赘述。 下面编译和执行上面的汇编代码。

    95920

    什么系统调用?

    当谈到系统调用(system call)时,我们首先映入脑海差不多就是软中断、内核态、用户态。开宗明义第一章,我想让大家先要重新认识一下『系统调用』这个词。...中断本身一个硬件概念,就是打断CPU,让其执行一下其他任务,比如键盘中断、打印机中断、定时器中断等。软中断本就是从软件层面模拟了这一中断操作。...网上很多资料大多会提到使用128号软中断指令(int 0x80)来使进程从用户态陷入内核态,执行完毕后调用iret指令重回用户态。但其实这是比较传统、比较老做法。...后来随着 ( 和 )升级, 内核一般会使用快速系统调用( ) 指令代替int 0x80,使用sysexit/sysret代替iret。...在运行软中断指令时候,会用一个寄存器存储具体系统调用号,比如在Linux上read和write系统调用号分别为0和1。 单内核与微内核上系统调用有什么不同呢?

    1.6K30

    MIT 6.S081 (BOOK-RISCV-REV1)教材第四章内容 --Trap -- 中

    通过getCmd函数汇编源码,可以看到调用write函数对应汇编指令,这段汇编指令主要作了参数准备,最后跳转到write函数地址执行write汇编代码如下所示: 通过上图可知write汇编程序入口地址...ecall并不会为我们做这里任何一件事。 当然,我们可以通过修改硬件让ecall为我们完成这些工作,不是交给软件完成。并且,我们也将会看到,在软件中完成这些工作并不是特别简单。...另一个问题为什么这些寄存器保存在trapframe,不是用户代码栈中?...所以内核需要自己管理这些寄存器保存,这就是为什么内核将这些内容保存在属于内核内存trapframe中,不是用户内存。...我们之前在系统调用过程中打开了中断,这里关闭中断是因为我们将要更新STVEC寄存器指向用户空间trap处理代码,之前在内核中时候,我们指向内核空间trap处理代码。

    37340

    进入Linux内核前准备

    我们把为什么给ds赋值说清楚了,那ds为什么0x07c0呢?之前我们不是说Bios将数据复制到内存中0x7c00吗,这里为为什么刚好差了16倍呢?...这个中断发起后,CPU会通过这个中断号,去寻找对应中断处理程序入口地址,并跳转过去执行,逻辑上就想到那个与执行了一个函数,0x13号中断BIOS提前写好一个读取磁盘相关功能函数。...继续看head.s,两个call语句设置了中断描述符表IDT和全局描述符表GDT,然后后面又是重新执行了一遍前面的代码,为什么要重新设置段寄存器值呢?...idt里面存储中断描述符,每个中断号对应一个中断描述符,中断描述符里面存储着主要是中断程序地址,这样CPU就可以根据中断号寻找到对应中断程序并且执行。...因此上面几句执行完后,会把esp寄存器(栈顶元素)值赋值给eip寄存器,cs:eipCPU执行下一条指令地址,此时栈顶刚好我们压入栈main.c里面main函数内存地址,这样我们就使用压栈指令和返回指令

    5.6K20

    操作系统进程实现---中---05

    然后,通过系统调用号,去system_call_table定位到某个具体内核函数地址,然后执行 这里具体定位到sys_fork函数 在执行sys_fork时候,可能会引起切换,例如: 如果产生了阻塞或者时间片到期了...,即PCB切换,因为用户态状态在产生中断时候,就已经保存到了内核栈中 然后再通过counter判断时间片是否到期,如果到期了,也需要进行切换 当reschedule函数执行结束后,会去执行ret_from_sys_call...---- 这里先来看一下中断返回,即执行完_schedule函数后,执行ret_from_sys_call 恢复现场,将保存相关寄存器状态从栈中弹出 此时esp指向栈,已经不是原内核级线程对应栈了...当段间指令jmp所含指针选择符指示一个可用任务状态段TSS描述符时,将造成任务切换。那么CPU怎么识别描述符TSS描述符不是其他描述符呢?...,其使用就是父进程用户栈空间,下面ss和esp参数,就是函数从栈中获取实参值 最后还有一点需要说明,因为这里使用tss完成内核级线程切换,不是内核栈方式,因此不需要将eip压入两个栈中

    88460

    16汇编第十讲完结Call变为函数以及指令最后讲解

    整体这样,这里为什么要一开始把bp和sp相等,有原因,我们不妨这样想,如果我们申请局部变量空间 时候,是不是参数偏移也要改动,这样每次都要自己计算偏移,相当麻烦,所以只能这样, 我们以后找参数就...返回 ,retf下面详细讲 在这里主要是掌握bp所在位置即可,就能明白为什么这样写了,不信的话自己写个程序,看下反汇编,大体就是这个套路,这里讲解为什么这样做,不是和市面的汇编视频一样,你看到...4到栈底才可以 二丶中断指令 1.什么中断指令 中断,有一种改变程序执行顺序方法 中断具有很多中断类型 中断指令有3条   1.INT i8(i8代表一个八位立即数)   2.IRET  IRET...比如显示一个字符串 mov ah,09h int 21h 其中参数09,int 21h代表执行,还有很多 介绍下指令   INT I8:  中断调用指令: 产生I8号中断,就是调用int代表我要调用了...,其中指令是什么使我们给,一个八位立即数比如 09   IRET:  中断返回指令,理解为返回,可以进行下一条指令执行   INTO:  不常用,不讲解. 3.21h中断,到底个啥玩意 我们每次都调用

    926100

    ROP基本原理和实战教学,看这一篇就够了!

    通过上一篇文章栈溢出漏洞原理详解与利用,我们可以发现栈溢出控制点ret处,那么ROP核心思想就是利用以ret结尾指令序列把栈中应该返回EIP地址更改成我们需要值,从而控制程序执行流程。...时,程序会尝试在数据页面上执行指令,此时CPU就会抛出异常,不是执行恶意指令。...sys_write(unsigned int fd, const char __user *buf, size_t count); 可以发现前三个mov指令把该函数需要参数放进相应寄存器中,然后把sys_write...,&system_call),设置中断向量号0x80中断描述符,也就是说实现了系统调用 (处理过程system_call)和 int 0x80中断对应,进而通过中断号用EAX实现不同子系统调用...、通过ret指令使得EIP指向pop eax;地址 3、执行pop eax;栈顶值0xb成功出栈,栈顶指针下移 4、通过ret指令使得EIP指向pop ebx;地址 .....

    2.8K30

    Linux系统调用原理

    由于某些指令(如设置时钟、关闭/打开中断和I/O操作等)只能运行在内核态,所以操作系统必须提供一种能够进入内核态方式,系统调用 就是这样一种机制。...系统调用 Linux 内核提供一段代码(函数),其实现了一些特定功能,用户可以通过 int 0x80 中断(x86 CPU)或者 syscall 指令(x64 CPU)调用 系统调用。...二、进入系统调用 本文主要介绍 x86 CPU 进入系统调用方式 Linux 提供了 int 0x80 中断让用户程序进入 系统调用,我们来看看 Linux 对 int 0x80 中断处理初始化过程...因为 用户态 和 内核态 使用栈不同,调用 系统调用 在用户态调用进入 系统调用 后会变成内核态,所以参数就不能通过传递。... Linux 进入中断处理程序时,会把这些寄存器值保存到内核栈中,这样 系统调用 就能通过内核栈获取到参数。

    4.2K30

    xv6(6) 系统调用

    $xv6$ 系统调用是用 INT n 指令实现,INT n 作用就是触发一个 $n$ 号中断中断过程应该很熟悉了吧,不熟悉可以看看前文中断代码部分。...指令触发中断。...上面只是说一般大致情况,如果看过前文中断机制应该知道,$xv6$ 对所有中断(包括系统调用)处理执行共同中断入口程序,主要就是保护现场压栈寄存器,然后根据向量号不同执行不同中断处理程序。...问题很多,咱们一个一个解决,首先从 IDT, GDT 中获取到中断入口程序地址之后,执行中断入口程序压栈寄存器保存上下文,这个上下文中包括了向量号。...$c$ 语言中这个过程可能看起来不是那么真切,如果用汇编来写,或者查看编译之后程序,会有下面的大致过程: push size push buf push fd call writecall

    33010

    操作系统篇-进程管理和中断

    进程和线程区别 进程就是一个程序运行起来状态,线程一个进程中不同执行路径。 进程OS分配资源基本单位,线程执行调度基本单位。...纤程线程中线程,对应图最上面蓝色框,在用户空间,不需要向操作系统申请。 纤程处于线程内部,非常轻量级,可以在线程中快速切换。JVM自己管理,自己实现调度,自己切换,与操作系统无关。...(下半场) 软中断(80中断中断向量表特殊符号 系统调用:int 0x80 (INT用于x86处理器汇编指令) 或者 sysenter原语(现在cpu在硬件级别直接支持,汇编码) 通过ax...寄存器填入调用号(比如1代表exit函数,2代表fork函数) 参数通过bx cx dx si di传入内核 返回值通过ax返回 系统调用实现hello world代码: ;以下例子主要调用了内核空间...注:eax 32位,ax16位 java中例子 java读网络 – jvm read() – c库read() - > 内核空间 -> system_call() (系统调用处理程序)-> sys_read

    1.2K00

    深入探索 perf CPU Profiling 实现原理

    CPU cycles (周期) CPU 执行指令时间单位,时钟频率表示 CPU 每秒执行 CPU 周期数。每个 CPU 指令执行可能需要一个或多个 CPU 周期。...Brendan Gregg 在大量例子中都使用了 99 Hertz 这个采样频率,至于为什么这样设置,他在文章 perf Examples 中给出了解释,大意:选择 99 Hertz 不是100...我们知道,PC 寄存器存放下一条指令地址,这时 PC 寄存器中函数调用指令call)后紧跟着那条指令地址。...返回地址函数调用指令call)后下一条指令,即 Calc 调用完 Sum 后紧跟着下一条指令,把这个指令地址恢复到 PC 寄存器中,实际上将控制权返回给了 Calc ,让 Calc 剩余部分接着执行...在 x86 架构中,每个中断或异常都通过一个 0 到 255 范围内数字识别,这个数字一个 8 位无符号数,被称为“向量(vector)”。

    2.5K84

    为什么 Linux 系统调用会消耗较多资源

    多数编程语言函数调用只需要分配新栈空间、向寄存器写入参数并执行 CALL 汇编指令跳转到目标地址执行函数,在函数返回时通过栈或者寄存器返回参数[^3]。...图 4 - 硬件中断和软件中断 根据事件发出者不同,我们可以将中断分成硬件和软件中断两种,硬件中断由处理器外部设备触发电子信号;软件中断由处理器在执行特定指令时触发,某些特殊指令也可以故意触发软件中断...在 32 位 x86 系统上,我们可以使用 INT 指令触发软件中断,早期 Linux 会使用 INT 0x80 触发软件中断、注册特定中断处理器 entry_INT80_32 来处理系统调用...等架构上仍然会使用中断执行系统调用[^12] 汇编指令 因为使用软件中断实现系统调用在 Pentium 4 处理器上表现非常差[^13]。...与 INT 0x80 通过触发软件中断实现系统调用不同,SYSENTER 和 SYSCALL 专门为系统调用设计汇编指令,它们不需要在中断描述表(Interrupt Descriptor Table

    1.9K40

    Linux系统调用过程

    应用程序和文件系统接口系统调用。 ?...我们经常看到比如fork、open、write 等等函数实际上并不是真正系统调用函数,他们都只是c库,在这些函数里将执行一个软中断 swi 指令,产生一个软中断,使CPU 陷入内核态,接着在内核中进行一系列判断...,判断出哪个系统调用,再转到真正系统调用函数,完成相应功能。...但是因为用户程序运行在用户空间,系统调用运行在内核空间,因此用户程序不能直接调用系统调用函数,我们经常看到比如fork、open、write 等等函数实际上并不是真正系统调用函数,他们都只是c库,...在这些函数里将执行一个软中断 swi 指令,产生一个软中断,使CPU 陷入内核态,接着在内核中进行一系列判断,判断出哪个系统调用,再转到真正系统调用函数,完成相应功能。

    4.8K70

    程序编译、链接、装载与运行

    装载 在上一节我们已经通过链接得到了可执行文件,在可执行文件中包含了很多段(section),但是一旦这些段被加载到内存中之后,我们就不在乎他到底是什么类型数据,只在乎这份数据在内存中读写权限。...由于现代操作系统均采用分页方式管理内存,所以操作系统只需要读取可执行文件文件头,之后建立起可执行文件到虚拟内存注5映射关系,不需要真正将程序载入内存。...运行 开始执行 操作系统jmp到进程第一条指令不是main方法,而是别的代码。...x86下使用中断(interrupt)发送信息给CPU,一旦CPU收到了中断信息,就会停止执行当前任务转而根据中断编号去执行中断处理函数。...= 2 对应 fork,等等 参数设置完毕之后,用户程序执行 int 0x80 指令,CPU收到中断信息 CPU将控制权限交给操作系统内核,进程栈从用户栈切换到内核栈注8 中断向量表中 0x80 号中断中断处理函数开始执行

    1.3K10

    逆向工程——汇编基础

    调用子程序指令CALL,对应返回指令RET,另外还有ENTER和LEAVE,她们可以帮助进行堆栈维护。 CALL指令参数被调用子程序地址。使用宏汇编时候,这通常是一个标号。...CPU向DMA控制器发出指令,要求外设和内存直接交换数据,通过CPU。...子程序一个不错主意,不过,CALL指令需要指定地址,让外设强迫CPU执行一条CALL指令也违背了CPU作为核心控制单元设计初衷。考虑到这些,这x86系统中引入了中断向量概念。...操作系统随时可能升级,这样,通过CALL调用操作系统服务(如果说每个程序都包含对于文件系统、进程表这些应该由操作系统管理数据直接操作的话,不仅会造成程序臃肿,而且不利于系统安全)就显得不太合适了...CPU将保存当前程序状态字,清除Trap和Interrupt两个标志,将即将执行指令地上压入堆栈,并调用中断服务(根据中断向量表)。 编写中断服务程序不是一件容易事情。

    1.2K10
    领券