3022|0

258

帖子

0

TA的资源

纯净的硅(初级)

楼主
 

《奔跑吧Linux内核2:调试与案例分析》2-中断管理 [复制链接]

本帖最后由 qiao--- 于 2024-4-7 21:43 编辑

本书的第二章是将Linux内核中断管理的部分,中断是Linux内核很重要的一部分,它能够让操作系统做出实时响应和异常处理,相比普通的轮询机制它还能很大程度上节约操作系统的资源。本书对于初入Linux的我而言,理解起来难度还是有点大,如果有哪里写的不好,请大家见谅。本文会重点介绍中断是如何调用系统API接口注册的。

 

1.中断控制器检测中断的流程

了解中断流程前,我们先来了解一下中断的状态和中断控制器。

(1)中断的状态

对于每一个中断来说,它支持的状态有不活跃状态、等待状态、活跃状态以及活跃并等待状态。不活跃(inactive)状态是指中断处于无效状态。等待(pending)状态是指中断处于有效状态,但是等待CPU响应该中断。活跃(active)状态指CPU已经响应中断。活跃并等待(active and pending)状态指CPU正在响应中断,但是该中断源又发送中断过来。

(2)中断控制器

中断控制器是计算机系统中的一个硬件组件,简称GIC,用于管理和协调各种中断信号的处理。它负责接收来自外部设备或内部系统的中断请求信号,并将这些中断请求信号传递给处理器,以触发相应的中断处理程序。

  (3)中断流程

  • 当GIC检测到一个中断发生时,会将该中断标记为 pending状态。
  • 对于处于pending状态的中断,仲裁单元会确定目标CPU,将中断请求发送到这个CPU.
  • 对于每个CPU,仲裁单元会从众多处于pending状态的中断中选择一个优先级最高的中断,发送到目标CPU的CPU接口模块上。
  • CPU接口模块会决定这个中断是否可以发送给CPU。如果该中断的优先级满足要求,GIC会发送一个中断请求信号给该CPU。
  • 当一个 CPU进入中断异常后,会读取GICC_IAR来响应该中断(一般由Linux内核的中断处理程序来读寄存器)。寄存器会返回硬件中断号(hardware interrupt ID),对于SGI来说,返回源CPU的ID (source processor ID)。当GIC感知到软件读取了该寄存器后,又分为如下情况。

    如果该中断处于 pending状态,那么状态将变成activee
    如果该中断又重新产生,那么pending将状态变成active and pending 状态。

    如果该中断处于active 状态,将变成active and pending状态。

  • 当处理器完成中断服务,必须发送一个完成信号结束中断(End Of Interrupt,EOI)给GIC。

2.中断是如何调用系统API接口注册的

当一个外设中断发生后,内核会执行一个函数来响应该中断,这个函数通常称为中断处理程序(intenupt handler)或中断服务例程。中断处理程序是内核用于响应中断的,并且运行在中断上下文中(和进程上下文不同)。中断处理程序最基本的工作是通知硬件设备中断已经被接收,不同的硬件设备的中断处理程序是不同的,有的常常需要做很多的处理工作,这也是Linux内核把中断处理程序分成上半部和下半部的原因。中断处理程序要求快速完成并且退出中断,但是如果中断处理程序需要完成的任务比较繁重,这两个需求就会有冲突,因此上下半部机制就诞生了。

在Linux内核里request_irq()函数是中断注册函数,但是是比较旧的接口函数,在 Linux 2.6.30内核中新增了线程化的中断注册函数request_threaded_irq()。中断线程化是实时Linux 项目开发的一个新特性,目的是降低中断处理对系统实时延迟的影响。下面是函数的原型:

 

其中中断标志位在系统中起着重要的作用,帮助系统管理和处理各种中断事件,下面是常用的中断标志位

 

 

request_threaded irq()函数中实现的主要操作如下:

在第1821~1824行中,完成一个例行的检查,对干那些共享中断的设备来说,这里强制要求传递一个参数dev_id。如果没有额外参数, 中断处理程序无法识别究竟是哪个外设产生的中断,通常根据dev_id查询设备寄存器来确定是哪个共享外设的中断。

在第1826行中,通过IRQ号获取irq_desc。

在第1830~1832行中,irq_settings_can_request()函数判断是否设置了_IRQ_NOREQUEST标志位,它是系统预留的,外设不可以使用这些中断描述符。另外,设置_IRQ_PER_CPU_DEVID标志位的中断描述符预留给IRQF_PERCPU 类型的中断,因此应该使用request percpu_irqO)函数注册中断。

在第1834~1838行中,主处理程序和 thread_fn 不能同时为NULL。当主处理程序为NULIL时使用默认的处理程序,irq_default_ primary_handler()函数直接返回IRQ_WAKE_THREAD,表示要唤醒中断线程。

在第1840行中,分配一个 irqaction数据结构,填充相应的成员。

在第1850行中,调用_setup_irq()函数继续注册中断。

在第1883行中,返回retval。

 

3.ARM64底层中断处理

当外设有事情需要报告SoC时,它会通过和SoC连接的中断引脚发送中断信号。根据中断信号类型,发送不同的波形,如上升沿触发、高电平触发等。SoC内部的中断控制器会感知到中断信号,中断控制器里的仲裁单元(distributor)会在众多CPU内核中选择一个,并把该中断分发给CPU内核。GIC和CPU内核之间通过nIRQ信号线来通知 CPU。

ARM64的处理器支持多个异常等级(exception level),其中ELO是用户模式,EL1是内核模式,也称为特权模式。EL2是虚拟化监管模式,EL3则是安全世界的模式。在 ARMv8架构下,异常分为异步异常和同步异常,其中 Linux内核中的异常属于同步异常,而IRQ和FIQ都属于异步异常。

当一个中断发生时,CPU内核感知到异常发生,硬件会自动做如下一些事情。

  • 处理器的状态保存在对应的异常等级的SPSR_ ELx中。
  • 返回地址保存在对应的异常等级的ELR_ ELx中。
  • PSTATE 寄存器里的DAIF 域都设置为1,相当于把调试异常、系统错误(SEror)、IRQ以及FIQ都关闭了。PSTATE寄存器是ARM v8里新增的寄存器。
  • 如果是同步异常,那么究竟什么原因导致的呢?具体要看ESR_ELx。
  • 设置栈指针,指向对应异常等级里的栈。
  • 迁移处理器等级到对应的异常等级,然后跳转到异常向量表里执行。

 

总结:本期测评就先到这里,这本书中对于一些接口函数和工作流程都讲的十分细致。也许是我基础太差的原因,又获取是我没阅读第一卷原因,我在初次阅读时倍感乏力,所以建议读者需要反复阅读琢磨才能领会其中的真理,有条件的朋友可以同书本系列的第一卷一起阅读效果更佳。

查看本帖全部内容,请登录或者注册
点赞 关注

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条
艾睿电子& Silicon Labs 有奖直播 | 全新蓝牙信道探测:从技术创新到实际应用
直播时间:3月12日(周三)上午10:00
直播奖励:多功能榨汁机、蓝牙音箱、手机支架

查看 »

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表