中断概述+实现通过中断来查看网卡每次产生中断的时间间隔

一、中断理论部分学习笔记:

1.中断图示:

在这里插入图片描述

上图列举了实现中断所需的中断控制器、EFLAGS寄存器、INTR以及NMI引脚,接下来一一解释一下每个部件的作用:

部件作用
中断控制器通过引脚接收外部设备发来的中断并且通过INTR引脚传递给CPU
IMR(中断屏蔽寄存器)IMR在中断控制器中,共8位,每一位对应一个中断信号,若该位为0,信号为不可屏蔽
EFLAGS寄存器该寄存器中有一个IF位,若该位是一,则INTR传来的中断不会被屏蔽
NMI引脚中断控制器以及EFLAGS寄存器都对其不起作用,只有系统出现了严重的错误,才会通过NMI引脚传达,比如:内存电路校验错误,UPS电源发来的停电通知。CPU必须马上处理这些中断。

2.为每个中断进行编号:

在这里插入图片描述
其中0x1A——0xFF为自定义中断。

3.中断向量表:

在这里插入图片描述
​ 实模式下,中断号由一个字节编码,故共有256个中断。地址需要两个16位寄存器来表示,故中断向量表中的每个表项(中断程序的入口地址)需要4字节来存储。

​ BIOS程序提供了基本输入输出的代码,其地址BIOS也是知道的,故BIOS会向中断向量表中填入自己代码的入口地址。并且其他硬件也会有BIOS程序,他们会把BIOS代码映射到内存中,接下来主板BIOS会将这些代码映射到中断向量表中。而剩余的中断号并没有定义入口地址,故BIOS写入一个统一的地址——iret(interrupt return)。

4.中断号产生的方式:

产生方式举例
自动生成运算时,碰到除数为0,则自动生成0x00号中断
硬件产生通过INTR和NMI来产生中断号
软件产生若需要打断点,则在程序中通过指令int 0x03来产生中断

5.中断请求队列:

问题回答
产生的原因由于硬件的限制,很多设备必须共享中断线。
如何注册使用request_irq()函数将相应的中断服务程序挂入中断请求队列中。
中断线共享的数据结构课本P138

6.中断执行的整个过程:

在这里插入图片描述

7、中断的下半部分处理机制:

​ 上半部是处理硬件发出的请求,它必须在一个新的中断产生之前终止,这一部分做的工作比较少。而下半部分是运行时是允许中断请求的,而上半部分运行时是关中断的。下半部分(就是一些内核函数)留着稍后处理。

​ 下半部分的执行机制目前也叫软中断机制。这中机制有两种实现方式,分别为小任务机制和工作队列机制。

  1. 中断的小任务机制

    中断是计算机系统中的一种重要机制,用于处理外部事件,例如硬件设备的状态变化、定时器的触发、网络数据包的到达等。 中断的小任务机制是一种用于处理中断事件的高效方法,其主要思想是在中断处理程序中尽量减少执行的代码量,以便尽快恢复到正常程序执行。这种机制通常包括以下关键步骤:

    • 中断响应:当发生中断事件时,CPU会立即暂停正在执行的任务,跳转到中断处理程序的入口点。

    • 中断处理程序:中断处理程序是专门设计的短小代码片段,用于快速响应中断并采取必要的措施,例如读取传感器数据、处理网络数据包、更新定时器等。这些处理程序通常执行得非常快速,以便尽早恢复正常操作。

    • 中断服务例程(ISR):中断处理程序可能会调用一个或多个中断服务例程,这些例程执行特定的任务,并且也应该尽量短小和高效。

    • 中断返回:一旦中断处理程序和相关的例程完成,CPU会执行中断返回指令,将控制权还给原来的任务,从中断事件中恢复正常运行。

    中断的小任务机制的优点是响应速度快,适用于需要快速处理外部事件的应用场景。

  2. 工作队列机制

    工作队列机制是一种用于异步处理任务的方法,通常在内核级别或操作系统中使用。这种机制的目的是将耗时的任务从主程序流中分离出来,以提高系统的响应性和效率。以下是工作队列机制的关键要点:

    • 工作队列:工作队列是一个任务队列,用于存储需要异步执行的任务。这些任务可以是任何需要后台处理的工作,如文件系统操作、设备驱动程序操作、数据处理等。

    • 工作者线程:工作队列通常与一组工作者线程相关联。这些线程负责从工作队列中获取任务并执行它们。工作者线程可以是内核线程或用户级线程,取决于操作系统的实现。

    • 任务调度:当有新任务添加到工作队列时,系统会安排工作者线程来处理这些任务。这允许主程序流继续执行而不受阻塞,因为工作队列中的任务会在后台执行。

    • 完成通知:一旦任务完成,工作者线程通常会发送通知或信号,以便主程序或其他组件知道任务已完成。

      ​ 工作队列机制的优点是它可以提高系统的并发性和响应性,允许将耗时的任务异步执行,而不会阻塞主程序。这对于需要处理多任务和多线程的系统非常有用。

    ​ 总结起来,中断的小任务机制侧重于快速响应外部事件,而工作队列机制侧重于异步处理长时间运行的任务,以提高系统的效率和响应性。选择哪种机制取决于应用的需求和性能要求。

二、实践部分:

1.向内核中插入一个自定义中断:

#include <linux/interrupt.h>
#include<linux/irq.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
static int irq=13;  //13号中断
 
// 自定义中断处理函数
static irqreturn_t myhandler(int irq, void *dev_id)
{
    printk("the irq is :%d\n", irq);  //irq是对应中断的中断号
    printk("in the interrupt handler function\n");
    return IRQ_HANDLED;
}

static int __init request_irq_init(void)
{
    
    int result=0;
    printk("into request_irq_init\n");
    /*调用函数request_irq( )申请中断,irq指中断编号,irq_handler是中断处理函数,IRQF_DISABLED
      是中断类型,“A_New_Device”指中断设备名,NULL指设备,设备为NULL说明设备不真实存在,NULL这个位置
      与共享设备有关,用于标识中断服务程序*/
    result=request_irq(irq, myhandler, IRQF_NO_SUSPEND, "A_New_Device", NULL);
    printk("the result of the request_irq is: %d\n", result);    //显示申请结果
    printk("out request_irq_init\n");
    return 0;
}
 
static void __exit request_irq_exit(void)
{
    free_irq(irq, NULL); //释放申请的中断
    printk("Goodbye request_irq\n");
    return;
}
 
module_init(request_irq_init);
module_exit(request_irq_exit);
obj-m := interval.o 
CURRENT_PATH:=$(shell pwd)
LINUX_KERNEL:=$(shell uname -r)
LINUX_KERNEL_PATH:=/usr/src/linux-headers-$(LINUX_KERNEL)

all:
	make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) modules
clean:
	make -C $(LINUX_KERNEL_PATH) M=$(CURRENT_PATH) clean

结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.查看网卡每次产生中断的时间间隔:

#include<linux/module.h>
#include<linux/init.h>
#include<linux/interrupt.h>
#include<linux/kernel.h>

static int irq;         //申请的中断号
static char *interface; //设备名称,本实验中使用ens33(网卡)
static int count = 0;   //统计的总次数

//传递参数
module_param(interface,charp,0644);
module_param(irq,int,0644); 

//中断服务程序
static irqreturn_t intr_handler(int irq,void *dev_id){
    static long interval = 0;   //记录时间间隔
    if(count == 0)
        interval = jiffies;     //特殊处理第一次记录
    interval = jiffies - interval;   //时间差
    printk("The interval between two interrupts is %ld\n",interval);
    interval = jiffies;
    count++;    //总共统计的次数
    return IRQ_NONE;
}

//模块初始化函数
static int __init intr_init(void){
	//interface表示与中断相关的设备名,&irq提供唯一的标志信息
    if(request_irq(irq,&intr_handler,IRQF_SHARED,interface,&irq)){
        printk(KERN_ERR"Fails to register IRQ %d\n",irq);
        return -EIO;
    }
    printk("%s Request on IRQ %d succeeded\n",interface,irq); //表示申请成功
    return 0;
}
static void __exit intr_exit(void){
    printk("The %d interrupts happened on irq %d",count,irq);
    free_irq(irq,&irq);  //删除自定义的中断
    printk("Freeing IRQ %d\n",irq);
    return;
}
module_init(intr_init);
module_exit(intr_exit);

MODULE_LICENSE("GPL");

在这里插入图片描述

解释一下参数:interface=ens33表示我们绑定的设备是网卡,irq=19表示申请该中断服务程序到19号中断中,即当网卡每次收发数据包时,都会触发19号中断,而19号中断线是共享中断线,并且共享中断线的数据结构irqaction中有属性dev_id会唯一地标识某个设备。因此,当中断发生时就会在19号中断的中断请求队列中执行dev_id为ens33的中断服务程序。
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值