Linux 0.11源码阅读笔记-中断过程

Linux 0.11源码阅读笔记-中断过程

是什么中断

中断发生时,计算机会停止当前运行的程序,转而执行中断处理程序,然后再返回原被中断的程序继续运行。中断包括硬件中断和软件中断, 硬中断是由外设自动产生的, 软中断是程序通过int指令主动调用。中断产生时,会有一个中断号,根据 中断号可在 中断向量表中选择对应的中断处理程序执行。

中断在linux当中非常重要,是用户态代码与和心态代码相互切换运行的桥梁。 进程调度依赖于时钟中断进入内核, 系统调用也是依赖 int 80软中断进入内核执行。

中断处理过程

以int 80中断为例。 system_call过程代码是 int 80中断处理程序, 是所有系统调用的入口。位于 linux-0.11/kernel/system_call.s文件中。

sytem_call 执行过程

  1. 保存运行环境:保存被中断程序的运行环境,包括指令地址(PC)、段等寄存器的值。
  2. 执行系统调用:根据系统调用号,查找 系统调用函数地址表,并执行系统调用函数
  3. 执行调度程序:判断进程时间片是否处于不可运行状态(时间片用完或者处于阻塞状态),若不可运行,则执行调度程序。
  4. 进行信号处理:若被中断程序为用户态进程,会先判断信号是否产生,并执行相应的信号处理程序。
  5. 恢复运行环境:恢复被中断程序的运行环境。

system_call代码及注释

### int 0x80 - linux系统调用入口点(调用中断int 0x80,eax 中是调用号)
system_call:
    cmpl $nr_system_calls-1,%eax    # 调用号如果超出范围的话就在eax中置-1并退出
    ja bad_sys_call

保存原段寄存器值
    push %ds
    push %es
    push %fs

edx、ecx、ebx作为系统调用的参数
    pushl %edx
    pushl %ecx      # push %ebx,%ecx,%edx as parameters
    pushl %ebx      # to the system call

设置内核段
    movl $0x10,%edx # set up ds,es to kernel space
    mov %dx,%ds
    mov %dx,%es
fs指向用户程序的数据段。
    movl $0x17,%edx     # fs points to local data space
    mov %dx,%fs

调用系统调用号对应的系统调用函数<details><summary>*<font color='gray'>[En]</font>*</summary>*<font color='gray'>Call the system call function corresponding to the system call number</font>*</details>
    call sys_call_table(,%eax,4)    # 间接调用指定功能C函数
    pushl %eax                      # 把系统调用返回值入栈

如果进程时间片(counter)用完或者状态(state)非就绪,则执行调度程序
    movl current,%eax       # 取当前任务(进程)数据结构地址→eax
    cmpl $0,state(%eax)     # state
    jne reschedule
    cmpl $0,counter(%eax)   # counter
    je reschedule

中断处理程序的后半部分返回到被中断的程序以继续执行。<details><summary>*<font color='gray'>[En]</font>*</summary>*<font color='gray'>The second half of the interrupt handler returns to the interrupted program to continue execution.</font>*</details>
ret_from_sys_call:
若被中断程序为0号进程,直接返回。
    movl current,%eax       # task[0] cannot have signals
    cmpl task,%eax
    je 3f                   # 向前(forward)跳转到标号3处退出中断处理

如果被中断的程序运行在内核状态(例如,其他可以被中断的程序),则直接返回<details><summary>*<font color='gray'>[En]</font>*</summary>*<font color='gray'>If the interrupted program runs in kernel state (for example, other programs that can be interrupted), return directly</font>*</details>
    cmpw $0x0f,CS(%esp)     # was old code segment supervisor ?
    jne 3f
    cmpw $0x17,OLDSS(%esp)  # was stack segment = 0x17 ?
    jne 3f

如果中断的程序是用户进程,则首先处理该进程的信号。<details><summary>*<font color='gray'>[En]</font>*</summary>*<font color='gray'>If the interrupted program is a user process, the signal of the process is processed first.</font>*</details>
通过信号位图,判断产生的信号,然后调用do_signal执行对应的信号处理程序
    movl signal(%eax),%ebx  # 取信号位图→ebx,每1位代表1种信号,共32个信号
    movl blocked(%eax),%ecx # 取阻塞(屏蔽)信号位图→ecx
    notl %ecx               # 每位取反
    andl %ebx,%ecx          # 获得许可信号位图
    bsfl %ecx,%ecx          # 从低位(位0)开始扫描位图,看是否有1的位,若有,则ecx保留该位的偏移值
    je 3f                   # 如果没有信号则向前跳转退出
    btrl %ecx,%ebx          # 复位该信号(ebx含有原signal位图)
    movl %ebx,signal(%eax)  # 重新保存signal位图信息→current->signal.
    incl %ecx               # 将信号调整为从1开始的数(1-32)
    pushl %ecx              # 信号值入栈作为调用do_signal的参数之一
    call do_signal          # 调用C函数信号处理程序(kernel/signal.c)
    popl %eax               # 弹出入栈的信号值

返回被中断程序
3:  popl %eax               # eax中含有上面入栈系统调用的返回值
    popl %ebx
    popl %ecx
    popl %edx
    pop %fs
    pop %es
    pop %ds
    iret                    # 特权级中断返回指令

用户栈与内核栈之间的切换

特权级发生变化时,会涉及到内核栈和用户栈的切换。linux具有两个特权级,内核态(0)和用户态(3)。int指令可以从用户态转入内核态,iret指令可以从内核态返回用户态。

Linux 0.11源码阅读笔记-中断过程

用户栈到内核栈

中断引起CPU特权级从3级到0级的变化,此时CPU会进行用户栈到内核栈的切换操作。

  1. 获取内核栈内存地址信息。CPU从当前任务状态段TSS(PCB)中取得新栈的段选择符和偏移值,内核栈指针从TSS的ss0(选择符)和esp0字段中获得。
  2. 将用户栈地址信息保存在内核栈中。将用户态栈指针和代码地址信息ss、esp、cs、eip压入内核栈中。
  3. 将ss、esp、cs、eip指向内核栈和代码地址。

内核栈到用户栈

iret指令引起CPU特权级从0级到3级的变化,此时CPU会进行内核栈到用户栈的切换操作。

iret指令将先前压入内核栈的用户进程栈和代码地址信息cs、esp、ss、esp信息从栈里弹出,加载到相应的寄存器中,重新执行用户进程。

进程调度的实现机制

每个用户进程有自己的内核栈,进程调度时,将栈寄存器指向需要运行的进程的内核栈,执行iret指令即可继续运行该进程。

内核栈的切换

进程调度通过内核栈之间的切换来实现进程间的切换操作。为什么每个进程都需要一个内核堆栈?进程需要保存运行状态信息(各种寄存器信息),等待调度器选择并运行。

[En]

Process scheduling realizes the switching operation between processes through the switching between kernel stacks. Why does every process need a kernel stack? The process needs to save the running status information (various register information) and wait for the scheduler to select and run.

Linux 0.11源码阅读笔记-中断过程

进程切换

进程切换的实质在于进程状态(上下文)的切换,即将CPU的当前进程状态替换成新进程的状态。被替换进程的进程状态会保存在其对应的tss数据结构中,等待恢复运行。任务寄存器TR会保存当前任务的TSS指针,TSS数据结构总保存进程的运行状态。

具体过程为:

  1. 当前进程通过中断进入内核,用户态ss、esp、cs、ip寄存器信息保存在内核栈中,切换到内核态运行,使用内核堆栈
  2. schedule调度程序时,将当前进程内核态运行信息保存在当前任务的tss数据结构中,然后切换到新进程的内核运行状态,在内核中运行新的进程。
  3. 新运行的进程通过iret指令从内核态转到用户态运行,用户态的运行状态信息在其内核栈中。

Linux 0.11源码阅读笔记-中断过程

参考

  • Linux 内核完全注释 内核版本0.11 – 赵炯

PS:错漏指出,请大佬指正,在评论区可交流学习。

Original: https://www.cnblogs.com/lazyfiish/p/16071685.html
Author: LazyFish
Title: Linux 0.11源码阅读笔记-中断过程

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/523938/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Samba:文件共享

    samba:现主要用于Linux与Windows之间的文件共享。 samba的特点: 用于Linux与Windows之间进行文件共享和打印机共享 不仅用于Windows之间的文件共…

    Linux 2023年6月13日
    0109
  • Linux系统中断处理框架(3)【转】

    //init/main.casmlinkage void __init start_kernel(void){…… trap_init(); //空函数…… ear…

    Linux 2023年6月8日
    099
  • 部署无人值守安装系统

    主机名 操作系统 ip地址 无人值守系统 CentOS Linux release 7.9.2009 (Core) 192.168.71.128 客户端 未安装系统 –…

    Linux 2023年6月13日
    0123
  • 数据链路层 交换机的工作原理

    以太网 以太网是一种将几台电脑连接起来,能够进行通讯的技术,也就是组建所谓的”局域网”。所以以太网可以说是一种局域网技术但局域网技术并非只有以太网一种,还有…

    Linux 2023年6月6日
    0115
  • QT:设置子窗口显示在父窗口的位置(绝对坐标)

    故事背景:最近需要在父窗体修改按钮上弹出二次确认框,之前要么使用 QDesktopWidget,要么使用QCursor,来设置弹窗位置,但是这两种方式不是很理想,就是想弹到相对父窗…

    Linux 2023年6月13日
    0104
  • Golang 实现 Redis(11): RDB 文件格式

    RDB 文件使用二进制方式存储 Redis 内存中的数据,具有体积小、加载快的优点。本文主要介绍 RDB 文件的结构和编码方式,并借此探讨二进制编解码和文件处理方式,希望对您有所帮…

    Linux 2023年5月28日
    094
  • [转帖]shell中if语句的使用

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    Linux 2023年5月28日
    0103
  • java反射机制

    1..获取Class实例的方式 1 @Test 2 public void test3() throws ClassNotFoundException { 3 //方式一:调用运行…

    Linux 2023年6月6日
    0117
  • SharePoint 2007 Full Text Searching PowerShell and CS file content with SharePoint Search

    Ensure your site or shared folder in one Content Source. Add file types. The second step i…

    Linux 2023年5月28日
    073
  • 常见网络安全设备

    一、防火墙定位:访问控制类产品,网络出现后的第一类安全产品。功能:隔离内网、外网以及DMZ区(业务系统对外发布区,Web应用服务器,邮件服务器等)并控制用户访问。部署方式:通常部署…

    Linux 2023年6月14日
    086
  • 【Hash篇】哈希计算神器-HashMyFiles

    可直接拖放、复制粘贴、添加文件或文件夹的方式来批量计算Hash,操作简便、体积小、免费。这篇来介绍他的汉化和其它一些功能设置—【suy】 目录 1、绿色便携 2、批量算…

    Linux 2023年6月13日
    0101
  • mac redis安装与使用,连接远程服务器 redis

    brew install redis@6.2 #后面@接版本号可指定版本,也可以不指定版本 brew services start redis redis-cli redis-cl…

    Linux 2023年5月28日
    093
  • ansible用authorized_key模块批量推送密钥到受控主机实现免密登录

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    Linux 2023年6月7日
    091
  • locate-updatedb命令检索不全

    执行updatedb 命令,用于立刻更新locate 命令所必需的数据库文件,但有些文件可能会在检索过程中被过滤掉。 有时候明明存在的文件,用find 命令都能搜得出来,但用loc…

    Linux 2023年6月13日
    088
  • redis好书推荐

    redis好书推荐原创amy_xing01 最后发布于2018-07-16 18:29:54 阅读数 10427 收藏展开Redis从入门到深入学习,推荐几本好书: 《Redis入…

    Linux 2023年5月28日
    092
  • sql server 增删改(查太多了)

    delete(删除) 使用 delete语句删除表中数据。 delete from 表名 [where where_definition] 如果不使用where子句,将删除表中所有…

    Linux 2023年6月7日
    083
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球