中断、信号、系统调用

2023-11-15

1、中断的分类

中断程序的方法可以分为硬件中断和软件中断。

硬件中断是硬件自动触发的,包括中断和异常。比如:中断 通过中断控制器给CPU的INTR引脚发送信号,如按下键盘,会给CPU一个0x21中断号;;异常 CPU执行某条指令发生异常,会自己触动一个中断号,比如执行到一个无效指令,CPU会给自己0x06的中断号。

软件中断是 由软件程序主动触发的, INT 指令。比如系统调用,实际上执行的是INT 0x80指令,CPU给收到0x80的中断号。

但也有的人这么分:

硬中断包括中断、异常、INT指令。整个中断机制都是由硬件实现的逻辑。软中断是由软件实现的,是硬中断的后半部分。

2、步骤

1、系统调用

系统调用是操作系统内核提供的一系列具备预定功能的函数接口供应用程序调用。系统调用把应用程序的请求传给内核,内核调用相应的函数完成所需的处理,再将处理结果返回给应用程序。

应用程序运行在用户态,其诸多操作都受到限制。而系统调用运行在内核 态,那么运行在用户态的应用程序如何运行内核态的代码?操作系统一般是通过中断来完成用户态到内核态的切换。

32 位系统调用

- 用户态

- 将请求参数保存到寄存器

- 将系统调用名称转为系统调用号保存到寄存器 eax 中

- 通过软中断 ENTER_KERNEL 进入内核态  int 0x80 指令

- 内核态

- 将用户态的寄存器保存到 pt_regs 中

- 在系统调用函数表 sys_call_table 中根据调用号找到对应的函数

- 执行函数实现, 将返回值写入 pt_regs 的 ax 位置

- 通过 INTERRUPT_RETURN 根据 pt_regs 恢复用户态进程

 

2、外部设备硬件中断

CPU 收到一个中断号 n 后,会去中断向量表中寻找第n个中断描述符,从中断描述符中找到中断处理程序的地址,然后跳过去执行。

其中涉及到的问题:

  • 如何给 CPU 一个中断号?

外部设备通过 INTR 引脚,或者 CPU 执行指令的过程中自己触发,或者由软件通过 INT n 指令强行触发。

  • CPU 收到中断号后如何寻找到中断程序的入口地址?

通过 IDTR 寄存器找到中断描述符表,通过中断描述符表和中断号定位到中断描述符,取出中断描述符表中存储的程序入口地址。

  • 中断描述符表是谁写的?

操作系统代码写上去的。

  • 找到程序入口地址之后,CPU 做了什么?

简单说,实际上做的事情就是压栈,并跳转到入口地址处执行代码。而压栈的目的,就是保护现场(原来的程序地址、原来的程序堆栈、原来的标志位)和传递信息(错误码) 

每个中断号都对应了一个中断处理程序。中断号是有限的,所以不会用一个中断来对应一个系统调用。对于每个系统调用都有一个系统调用号,在触发中断之前,会将系统调用号放入到一个固定的寄存器,中断处理程序会读取该寄存器的值,然后决定执行哪个系统调用的代码。

硬中断的微观层面,就是 CPU 在每一个指令周期的最后,都会留一个 CPU 周期去查看是否有中断,如果有,就把中断号取出,去中断向量表中寻找中断处理程序,然后跳过去。

软中断的微观层面,简单说就是有一个单独的守护进程,不断轮询一组标志位,如果哪个标志位有值了,那去这个标志位对应的软中断向量表数组的相应位置,找到软中断处理函数,然后跳过去。

软中断是 Linux 处理一个中断的下半部的主要方式,比如 Linux 某网卡接收了一个数据包,此时会触发一个硬中断,由于处理数据包的过程比较耗时,而硬中断资源又非常宝贵,如果占着硬中断函数不返回,会影响到其他硬中断的相应速度,比如点击鼠标、按下键盘等。

所以一般 Linux 会把中断分成上下两半部分执行,上半部分处理最简单的逻辑,下半部分直接丢给一个软中断异步处理。

3、信号

信号的发送与处理是一个复杂的过程,这里来总结一下。

假设我们有一个进程 A,main 函数里面调用系统调用进入内核。按照系统调用的原理,会将用户态栈的信息保存在 pt_regs 里面,也即记住原来用户态是运行到了 line A 的地方。

在内核中执行系统调用读取数据。当发现没有什么数据可读取的时候,只好进入睡眠状态,并且调用 schedule 让出 CPU,这是进程调度第一定律。将进程状态设置为 TASK_INTERRUPTIBLE,可中断的睡眠状态,也即如果有信号来的话,是可以唤醒它的。

其他的进程或者 shell 发送一个信号,有四个函数可以调用 kill、tkill、tgkill、rt_sigqueueinfo。四个发送信号的函数,在内核中最终都是调用 do_send_sig_info。do_send_sig_info 调用 send_signal 给进程 A 发送一个信号,其实就是找到进程 A 的 task_struct,或者加入信号集合,为不可靠信号,或者加入信号链表,为可靠信号。do_send_sig_info 调用 signal_wake_up 唤醒进程 A。进程 A 重新进入运行状态 TASK_RUNNING,根据进程调度第一定律,一定会接着 schedule 运行。进程 A 被唤醒后,检查是否有信号到来,如果没有,重新循环到一开始,尝试再次读取数据,如果还是没有数据,再次进入 TASK_INTERRUPTIBLE,即可中断的睡眠状态。

当发现有信号到来的时候,就返回当前正在执行的系统调用,并返回一个错误表示系统调用被中断了。系统调用返回的时候,会调用 exit_to_usermode_loop。这是一个处理信号的时机。

调用 do_signal 开始处理信号。根据信号,得到信号处理函数 sa_handler,然后修改 pt_regs 中的用户态栈的信息,让 pt_regs 指向 sa_handler。同时修改用户态的栈,插入一个栈帧 sa_restorer,里面保存了原来的指向 line A 的 pt_regs,并且设置让 sa_handler 运行完毕后,跳到 sa_restorer 运行。返回用户态,由于 pt_regs 已经设置为 sa_handler,则返回用户态执行 sa_handler。

sa_handler 执行完毕后,信号处理函数就执行完了,接着根据上面对于用户态栈帧的修改,会跳到 sa_restorer 运行。sa_restorer 会调用系统调用 rt_sigreturn 再次进入内核。在内核中,rt_sigreturn 恢复原来的 pt_regs,重新指向 line A。从 rt_sigreturn 返回用户态,还是调用 exit_to_usermode_loop。这次因为 pt_regs 已经指向 line A 了,于是就到了进程 A 中,接着系统调用之后运行,当然这个系统调用返回的是它被中断了,没有执行完的错误。

 

注意信号处理的时机是系统调用或者中断返回时。信号处理的时机和调度的时机基本一致,都是当需要的时候,设置标签位,然后等下一次从系统调用返回或中断返回的时候进行判断进而处理,当发生用户态死循环的时候,不会调用系统调用,但是不代表不会处理中断(尤其是时间中断,这样一来才能保证当进程执行的cpu时间太长就需要强制让出了cpu),当从中断处理返回的时候,同样是从内核态到用户态,同样会进行判断是不是收到信号进而进行处理。

信号处理函数处理完成之后,系统设计的时候,为啥不直接返回用户态LineA的地方? 这样不是省事了吗?

用户态LINEA的所有用于恢复的东西还在内核数据结构里面,包括寄存器什么的。返回不止要返回到正确的地址,还要有各种寄存器的恢复,那如何进内核呢?只能再执行一个系统调用,然后把用户态的场景恢复,完。

异步通知所基于的信号也类似于中断。

硬中断是硬件中断、异常、INT指令 对CPU的中断;

软中断通常是硬中断服务程序对内核的中断

信号则是由内核(或其它进程)对某个进程的中断。

作为系统调用而言,对于X86,软中断是通过int80实现

对于其它的软中断,则是在硬件中断之后触发的软中断,是中断下半部的一种实现机制,本质是内核线程

系统调用的中断是软件触发的中断,所以称为软中断,而对于中断下半部的软中断,虽然也是软件触发,但是并不经过中断向量表。

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

中断、信号、系统调用 的相关文章

  • 尝试编译 git 但在 linux 中找不到 libcurl

    我想编译支持 http https 的 git 我有 ls usr include curl curlbuild h curl h curlrules h curlver h easy h mprintf h multi h stdchea
  • 对于客户端服务器程序,并行接收多个客户端连接请求的最佳方法是什么?

    该程序是在 Linux 上用 C 语言开发的客户端服务器套接字应用程序 每个客户端都连接到一个远程服务器并将其自身记录为在线 在任何给定时间点很可能有多个客户端在线 所有客户端都尝试连接到服务器以将自己记录为在线 忙碌 空闲等 那么服务器如
  • 在 shell 脚本中将脚本目录更改为用户的 homedir

    在我的 bash 脚本中 我需要将当前目录更改为用户的主目录 如果我想更改为用户的foo主目录 从命令行我可以执行以下操作 cd foo 效果很好 但是当我从script它告诉我 bar sh line 4 cd foo No such f
  • mod_perl 无法看到 /tmp 中的文件

    我有一些 mod perl 代码试图访问 tmp 下的文件 但它抛出 没有这样的文件或目录 错误 我在代码中添加了一个 ls al tmp 来查看 Perl 在目录中看到的内容 它只给了我 和 drwxrwxrwt 2 root root
  • 在Linux中执行jar文件[关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我创建了一个可执行的 Java jar 文件 也就是说 我将 java 程序正确打包到 jar 文件中 包括 META INF MANIFEST 文件
  • 我可以告诉 Linux 不要交换特定进程的内存吗?

    有没有办法告诉 Linux 它不应该将特定进程的内存交换到磁盘 它是一个 Java 应用程序 所以理想情况下我希望有一种方法可以从命令行执行此操作 我知道您可以将全局交换性设置为 0 但这明智吗 您可以通过以下方式执行此操作姆洛克尔 2 h
  • Mongo:无法连接到服务器 127.0.0.1:27017 位于 src/mongo/shell/mongo.js:145

    当我尝试在 ubuntu 中的 shell 中运行 mongo 或打开 rockmongo 时 我看到以下错误 couldn t connect to server 127 0 0 1 27017 at src mongo shell mo
  • 检查上次更改密码的时间[关闭]

    Closed 这个问题是与编程或软件开发无关 help closed questions 目前不接受答案 Locked 这个问题及其答案是locked help locked posts因为这个问题是题外话 但却具有历史意义 目前不接受新的
  • 多线程进程的线程ID可以与另一个正在运行的进程的进程ID相同吗?

    我正在尝试找到一种方法来唯一标识多进程环境中的线程 我有一个服务器 它跟踪连接到它的不同进程 其中一些是多线程的 一些不是 为了识别多线程连接中的线程 我使用线程 ID 作为唯一标识符 在任何给定时间最多有 1 个多线程进程连接 我的问题是
  • Pthread互斥锁由不同线程解锁

    一个天真的问题 我之前读到过 MUTEX 只能由锁定它的线程解锁 但我写了一个程序THREAD1锁定 mutexVar 并进入睡眠状态 然后THREAD2可以直接解锁mutexVar做一些操作并返回 gt 我知道每个人都说我为什么要这样做
  • 如何在 .zip 文件中使用 grep

    有 3 个文件 a csv b csv c csv 压缩为 abh zip 现在可以在 abh zip 上执行 grep 命令 是否有任何通配符 仅对里面的 c csv 文件运行 grep压缩 如果你有zipgrep 据我所知 它是随zip
  • 如何在Linux中获取带有图标的活动应用程序

    我想找到一种方法获取活动应用程序的列表及其名称和图标 实际上 我正在使用此命令来获取所有活动进程 wmctrl lp 示例输出 0x03800002 0 3293 user notebook XdndCollectionWindowImp
  • 仅为我自己禁用和重新启用地址空间布局随机化

    我想在我的系统 Ubuntu Gnu Linux 2 6 32 41 server 上禁用地址空间布局随机化 ASLR 但是 如果我使用 sysctl w kernel randomize va space 0 我认为这一更改将影响系统上的
  • 64位版本的adb和fastboot?

    我在 Debian 7 3 x64 已完全修补 上发现了以下错误 我很确定这是因为adb即使在其 SDK 工具的 64 位发行版中也是 32 位 which adb opt android sdk platform tools adb op
  • 如何从内部找到C++ Linux程序的完整路径?

    我有这个要求 我需要从内部找到 C 程序的完整路径 对于Windows 我有以下解决方案 argv 0 可能包含也可能不包含完整路径 但我需要确定 TCHAR drive MAX DRIVE dir MAX DIR base MAX FNA
  • 检测后台操作

    在C中 检测程序在 后台模式 下调用的方法是什么 我有一个程序想要以交互方式或在后台启动 我怎样才能检测到我不应该从标准输入读取并以 已停止 tty 输入 状态结束 我应该测试 stdin 是否已关闭 我怎样才能做到这一点 编辑 isatt
  • Powershell从Linux客户端连接到Windows远程

    我正在尝试从我的 Linux 工作站远程连接到 Windows 计算机 我在 Arch Linux 工作站上安装了 powershell 目前正在尝试连接到主机 在主机上 Enable PSRemoting 然后允许所有主机Set Item
  • 在 Windows 下对 Unix 下创建的文件使用 fstream::seekg

    我有一个C 跨平台程序 在Linux下用g 编译 在PC下用Visual Studio编译 该程序将行写入文本文件 使用 lt lt 运算符和std endl 但也可以从生成的文本文件中读回数据 使用std getline 为了优化数据访问
  • Linux 从设备本身运行的脚本卸载设备

    我在路径中安装了一个 iso 映像 mnt iso 在这个 iso 中我有一个安装脚本 install sh 我从 iso 运行安装脚本 最后脚本询问用户是否要卸载 iso 本身 如果用户按 y 脚本将执行以下代码 cd umount mn
  • Linux 内核中是否使用了扩展指令集(SSE、MMX)?

    好吧 它们带来 至少应该带来 性能的巨大提升 不是吗 所以 我还没有看到任何 Linux 内核源代码 但很想问 它们是否以某种方式被使用 在这种情况下 对于没有此类指令的系统 必须有一些特殊的 代码上限 SSE 和 MMX 指令集在音频 视

随机推荐

  • iOS 切图使用 分辨率 使用 相关总结

    疑问 就iphone来说分辨率有三种 320 480 640 960 640 1136 那么如果我想做图 如果是320 480 1 是不是所有的图片 比如按钮的 背景图的 尺寸都必须做成小于或等于320 480的分辨率 2 是否可以做一张大
  • Latex各种命令、符号、公式、数学符号、排版等

    本文仅供学习参考使用 一切版权和解释权均归原作者所有 转载地址 http blog csdn net garfielder007 article details 51646604 数学符号详细内容见 http mohu org info s
  • vue的v-for循环中图片加载路径问题

    vue的v for循环中图片加载路径问题 产品要求 要求图片和它的名字一一对应 vue中的img的src可以动态绑定到一个变量上
  • 个数是如何用大数据做行为预测的?

    个数 是 个推 旗下面向 APP 开发者提供数据统计分析的产品 个数 通过可视化埋点技术及大数据分析能力从用户属性 渠道质量 行业对比等维度对 APP 进行全面的统计分析 个数 不仅可以及时统计用户的活跃 新增等 还可以分析卸载用户的成分
  • 【网安神器篇】——searchsploit漏洞利用搜索工具

    作者名 Demo不是emo 主页面链接 主页传送门 创作初心 一切为了她座右铭 不要让时代的悲哀成为你的悲哀专研方向 网络安全 数据结构 每日emo 我最常欺骗的人其实是我自己 通过一些技术手段 掌握到一些软件的版本信息应该如何利用呢 举个
  • oh-my-zsh 为 ls 命令自定义颜色

    ls 命令默认显示的颜色是 白色 表示普通文件 蓝色 表示目录 绿色 表示可执行文件 红色 表示压缩文件 蓝绿色 链接文件 红色闪烁 表示链接的文件有问题 黄色 表示设备文件 灰色 表示其他文件 在 oh my zsh 主题下如何自定义这些
  • CodeGeeX - 免费的AI编程助手

    1 官网 CodeGeeX 官网 2 VSCode安装CodeGeeX CodeGeeX 扩展 3 普通模式 无需付费 无需登录 下载就用 运行结果 4 拆分视图模式 快捷键Ctrl Enter触发拆分视图显示模式 5 生成注释模式 支持J
  • [经典论文分享] Attention, Learn to Solve Routing Problems!

    1 背景 自从有人基于指针网络解决组合优化问题以来 基于ML的组合优化问题求解模型逐渐被关注 基于深度强化学习的组合优化求解带来了较高的模型准确度和泛化性 但是目前基于DRL的CO求解准确度和训练效率一般 简单来说就是模型不是很成熟 针对模
  • 科技云报道:软件供应链安全如此重要,但为什么难以解决?

    科技云报道原创 软件供应链安全如今已经成了一个世界性难题 从2021年底Apache Log4j 核弹级 风险爆发 时至今日影响仍然存在 保障软件供应链安全已成为业界关注焦点 但近2年时间过去了 软件供应链安全问题似乎并没有得以缓解 安全事
  • 发送ARP数据包

    发送ARP数据包 ARP 地址解析协议 即ARP Address Resolution Protocol 是根据IP地址获取物理地址的一个TCP IP协议 主机发 送信息时将包含目标IP地址的ARP请求广播到网络上的所有主机 并接收返回消息
  • 服务器虚拟化技术

    一 服务器虚拟化概述 1 服务器虚拟化简介 在一台物理服务器上运行多个虚拟服务器称为 服务器虚拟化 在服务器虚拟化中 专用虚拟化软件将物理服务器上的处理器存储器之类的资源划分为多个资源 并将其分配给虚拟服务器 由于可以在一台物理服务器上聚合
  • Python爬虫 XPath解析出乱码 解决方法

    请求后加上编码 resp requests get url headers headers resp encoding GBK
  • Springboot操作Elasticsearch——聚合分组与排序

    这两天项目中需要从es中查询数据 根据某个字段进行分组 求其最大 最小 平均值 并按最大值进行排序 springboot的版本号 2 0 6 RELEASE Elasticsearch的版本号 5 6 3 主要代码记录下 BoolQuery
  • 拆解开源项目Blender

    计划把Blender项目拆解出来 如果把Blender项目比作一辆汽车 那拆解的任务就是把它的发动机 轮胎 支架等不同的模块单独出来并能独自运行 不知道以前有没有人这样干过 在其他项目上 这样拆解的好处是可以更好地研究它的工作原理 并将这些
  • AFNetWorking出现code=-1016错误解决办法

    AFNetWorking的JSON解析默认库是使用的AFJSONRequestOperation模式 只支持text json application json text javascript 所以如果出现code 1016错误则说明当前的
  • 告别2021,迎接2022

    2021相对有点忙有点累 一直想记录一下 但是实在是在惰性趋势下 歇息了一个月 才正常提笔微记 最近思绪也比较忙 提笔规划也是有点凌乱 2021年在新单位的第二年 开始结交朋友 受朋友们的影响 开始准备考研 软考 幸运的是 也都坚持下来了
  • adb将Apk内置到系统中(system/priv-app)

    有时候我们在Android 系统内置自己的应用 在测试时 Android Studio 默认的安装方式是将我们开发的应用作为普通应用安装到系统中的 本文提供一种方式 在开发过程中 将apk内置到系统中 而不需要系统源代码 adb 将apk内
  • java新建一个窗口_Java实例:使用JFram创建一个简单的窗口

    一个图形用户界面以一个top level container开始 它为其他的界面组件提供了一个 家 指定应用程序的总体感觉 在本教程中 向你介绍JFrame类 它将用于给一个Java应用程序创建一个简单的top level窗口 打开你的编辑
  • UI操作 解决方案

    1 include
  • 中断、信号、系统调用

    1 中断的分类 中断程序的方法可以分为硬件中断和软件中断 硬件中断是硬件自动触发的 包括中断和异常 比如 中断 通过中断控制器给CPU的INTR引脚发送信号 如按下键盘 会给CPU一个0x21中断号 异常 CPU执行某条指令发生异常 会自己