初步实现中断处理

本文详细介绍了Linux内核如何处理中断,包括在栈中处理错误码、宏汇编实现中断处理、中断门描述符表的定义以及8259A中断控制器的初始化。同时,展示了中断处理函数的数组结构和通用中断处理函数的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.kernel.S

①有些中断处理,会在栈中留下自己的错误码,就很像Linux的errno,所以当中断处理函数退栈的时候,会造成两种不同的处理方式,这里为了简便,直接将两种一起处理,有错误码的我们执行一条空指令,没有错误码的我们手工压入一个0
②我们在这里采用了宏汇编,来对所有的中断函数进行处理,就是当中断发生的时候,调用宏汇编的函数,在宏汇编的函数中,它压入自己的中断号,然后在IDT中查找自己的中断处理函数,进行处理

[bits 32]
%define ERROR_CODE nop		 
; 若在相关的异常中cpu已经自动压入了错误码,为保持栈中格式统一,这里不做操作.
%define ZERO push 0		 
; 若在相关的异常中cpu没有压入错误码,为了统一栈中格式,就手工压入一个0

extern put_str			 ;声明外部函数
extern g_IDT_Table
section .data
intr_str db "interrupt occur!", 0xa, 0
global g_IntrEntryTable
g_IntrEntryTable:

%macro VECTOR 2
section .text
intr%1entry:		 ; 每个中断处理程序都要压入中断向量号,所以一个中断类型一个中断处理程序,自己知道自己的中断向量号是多少
   %2

   ;保存上下文环境
	PUSH DS
	PUSH ES
	PUSH FS
	PUSH GS
	PUSHAD

   ; 如果是从片上进入的中断,除了往从片上发送EOI外,还要往主片上发送EOI 
   mov al,0x20                   ; 中断结束命令EOI
   out 0xa0,al                   ; 向从片发送
   out 0x20,al                   ; 向主片发送

   PUSH %1 						 ;压入中断向量号
   CALL [g_IDT_Table+ %1*4]		 ;调用中断处理函数
	
   JMP intr_exit


section .data
   dd    intr%1entry	 ; 存储各个中断入口程序的地址,形成intr_entry_table数组
%endmacro

section .text
global intr_exit
intr_exit:
	ADD ESP, 4					 ;跳过中断号
	POPAD
	POP GS
	POP FS
	POP ES
	POP DS
	ADD ESP, 4					 ;跳过错误码
	IRETD



VECTOR 0x00,ZERO
VECTOR 0x01,ZERO
VECTOR 0x02,ZERO
VECTOR 0x03,ZERO 
VECTOR 0x04,ZERO
VECTOR 0x05,ZERO
VECTOR 0x06,ZERO
VECTOR 0x07,ZERO 
VECTOR 0x08,ERROR_CODE
VECTOR 0x09,ZERO
VECTOR 0x0a,ERROR_CODE
VECTOR 0x0b,ERROR_CODE 
VECTOR 0x0c,ZERO
VECTOR 0x0d,ERROR_CODE
VECTOR 0x0e,ERROR_CODE
VECTOR 0x0f,ZERO 
VECTOR 0x10,ZERO
VECTOR 0x11,ERROR_CODE
VECTOR 0x12,ZERO
VECTOR 0x13,ZERO 
VECTOR 0x14,ZERO
VECTOR 0x15,ZERO
VECTOR 0x16,ZERO
VECTOR 0x17,ZERO 
VECTOR 0x18,ERROR_CODE
VECTOR 0x19,ZERO
VECTOR 0x1a,ERROR_CODE
VECTOR 0x1b,ERROR_CODE 
VECTOR 0x1c,ZERO
VECTOR 0x1d,ERROR_CODE
VECTOR 0x1e,ERROR_CODE
VECTOR 0x1f,ZERO 
VECTOR 0x20,ZERO

2.Interrupt.c

①定义了中断描述符表
②定义了异常发生时,显示在屏幕上的错误信息
③定义了中断处理函数的数组
④声明了中断处理函数的入口,定义在kernel.S中
⑤对PIC进行了设定
⑥加载中段描述符表寄存器

#include "Interrupt.h"
#include "stdint.h"
#include "Global.h"
#include "print.h"
#include "io.h"


#define PIC_M_CTRL 0x20	       
// 这里用的可编程中断控制器是8259A,主片的控制端口是0x20
#define PIC_M_DATA 0x21	       // 主片的数据端口是0x21
#define PIC_S_CTRL 0xa0	       // 从片的控制端口是0xa0
#define PIC_S_DATA 0xa1	       // 从片的数据端口是0xa1
#define IDT_DESC_COUNT 0x21		//目前支持的中断总数

typedef struct INT_GATE_DESC_T			//中断门描述符的结构体定义
{
	uint16_t FunOffsetLowWord;	
	uint16_t Selector;
	uint8_t  dCount;
	uint8_t  Attribute;
	uint16_t FunOffsetHighWord;
}INT_GATE_DESC_T;



//用来保存异常的名字
char * IntrName[IDT_DESC_COUNT];

//定义中断处理程序数组
Int_Handler g_IDT_Table[IDT_DESC_COUNT];

//初始化一个中断描述符的结构体
static void MakeIdtDesc(INT_GATE_DESC_T *pGateDesc, const uint8_t attr, const Int_Handler pIntrFun);

//中断门描述符的数组
static INT_GATE_DESC_T g_IDT[IDT_DESC_COUNT];

//此数组定义在kernel.S文件
extern Int_Handler g_IntrEntryTable[IDT_DESC_COUNT];


//通用的中断处理函数 一般在异常出现时的处理
static void GeneralIntrHandler(uint8_t vec_num)
{
	//IRQ7 IRQ15 会产生伪中断 无需处理
	if(0x27 == vec_num || 0x2f == vec_num)
		return ;

	put_str("INT VECTOR : 0x");
	put_int(vec_num);
	put_char('\n');
}


static void InitException(void)
{
	int i;
	for(i = 0; i < IDT_DESC_COUNT; i++)
	{
		g_IDT_Table[i] = GeneralIntrHandler;
		IntrName[i] = "UNKNOWN";
	}

	IntrName[0] = "#DE Divide Error";
	IntrName[1] = "#DB Debug Exception";
	IntrName[2] = "NMI Interrupt";
	IntrName[3] = "#BP Breakpoint Exception";
	IntrName[4] = "#OF Overflow Exception";
	IntrName[5] = "#BR BOUND Range Exceeded Exception";
	IntrName[6] = "#UD Invalid Opcode Exception";
	IntrName[7] = "#NM Device Not Available Exception";
	IntrName[8] = "#DF Double Fault Exception";
	IntrName[9] = "Coprocessor Segment Overrun";
	IntrName[10] = "#TS Invalid TSS Exception";
	IntrName[11] = "#NP Segment Not Present";
	IntrName[12] = "#SS Stack Fault Exception";
	IntrName[13] = "#GP General Protection Exception";
	IntrName[14] = "#PF Page-Fault Exception";
	   // intr_name[15] 第15项是intel保留项,未使用
	IntrName[16] = "#MF x87 FPU Floating-Point Error";
	IntrName[17] = "#AC Alignment Check Exception";
	IntrName[18] = "#MC Machine-Check Exception";
	IntrName[19] = "#XF SIMD Floating-Point Exception";

}


/* 初始化可编程中断控制器8259A */
static void InitPic(void) 
{

   /* 初始化主片 */
   outb (PIC_M_CTRL, 0x11);   // ICW1: 边沿触发,级联8259, 需要ICW4.
   outb (PIC_M_DATA, 0x20);   
// ICW2: 起始中断向量号为0x20,也就是IR[0-7] 为 0x20 ~ 0x27.
   outb (PIC_M_DATA, 0x04);   // ICW3: IR2接从片. 
   outb (PIC_M_DATA, 0x01);   // ICW4: 8086模式, 正常EOI

   /* 初始化从片 */
   outb (PIC_S_CTRL, 0x11);	// ICW1: 边沿触发,级联8259, 需要ICW4.
   outb (PIC_S_DATA, 0x28);	
// ICW2: 起始中断向量号为0x28,也就是IR[8-15] 为 0x28 ~ 0x2F.
   outb (PIC_S_DATA, 0x02);	// ICW3: 设置从片连接到主片的IR2引脚
   outb (PIC_S_DATA, 0x01);	// ICW4: 8086模式, 正常EOI

   /* 打开主片上IR0,也就是目前只接受时钟产生的中断 */
   outb (PIC_M_DATA, 0xfe);
   outb (PIC_S_DATA, 0xff);

   put_str("  INIT PIC  DONE\n");
}


static void MakeIdtDesc(INT_GATE_DESC_T *pGateDesc, const uint8_t attr, const Int_Handler pIntrFun)
{
	pGateDesc->FunOffsetHighWord = ((uint32_t)pIntrFun & 0xFFFF0000)>>16;
	pGateDesc->Attribute = attr;
	pGateDesc->dCount = 0;
	pGateDesc->Selector = SELECTOR_K_CODE;
	pGateDesc->FunOffsetLowWord = (uint32_t)pIntrFun & 0x0000FFFF;
}

//初始化中断描述符表
static void InitIdtDesc(void)
{
	int i;
	for(i = 0; i < IDT_DESC_COUNT; i++)
	{
		MakeIdtDesc(&g_IDT[i], IDT_DESC_ATTR_DPL0, g_IntrEntryTable[i]);
	}
	put_str("IDT DESC INIT DONE\n");
}

//完成有关中断的所有初始化工作
void InitIdt(void)
{
	put_str("IDT ININT START\n");
	InitIdtDesc();//初始化中断描述符表
	InitException();//异常名初始化 并注册通用的中断处理函数
	InitPic();//初始化8259A
	

	//IDTR寄存器低16位是IDT界限 高32位是IDT的线性基地址
	uint64_t IdtOperand = ((sizeof(g_IDT)-1) | ((uint64_t) ((uint32_t)g_IDT << 16)));
	
	asm volatile("LIDT %0":: "m" (IdtOperand));

	put_str("IDT INIT DONE\n");
}

### RT-DETRv3 网络结构分析 RT-DETRv3 是一种基于 Transformer 的实时端到端目标检测算法,其核心在于通过引入分层密集正监督方法以及一系列创新性的训练策略,解决了传统 DETR 模型收敛慢和解码器训练不足的问题。以下是 RT-DETRv3 的主要网络结构特点: #### 1. **基于 CNN 的辅助分支** 为了增强编码器的特征表示能力,RT-DETRv3 引入了一个基于卷积神经网络 (CNN) 的辅助分支[^3]。这一分支提供了密集的监督信号,能够与原始解码器协同工作,从而提升整体性能。 ```python class AuxiliaryBranch(nn.Module): def __init__(self, in_channels, out_channels): super(AuxiliaryBranch, self).__init__() self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1) self.bn = nn.BatchNorm2d(out_channels) def forward(self, x): return F.relu(self.bn(self.conv(x))) ``` 此部分的设计灵感来源于传统的 CNN 架构,例如 YOLO 系列中的 CSPNet 和 PAN 结构[^2],这些技术被用来优化特征提取效率并减少计算开销。 --- #### 2. **自注意力扰动学习策略** 为解决解码器训练不足的问题,RT-DETRv3 提出了一种名为 *self-att 扰动* 的新学习策略。这种策略通过对多个查询组中阳性样本的标签分配进行多样化处理,有效增加了阳例的数量,进而提高了模型的学习能力和泛化性能。 具体实现方式是在训练过程中动态调整注意力权重分布,确保更多的高质量查询可以与真实标注 (Ground Truth) 进行匹配。 --- #### 3. **共享权重解编码器分支** 除了上述改进外,RT-DETRv3 还引入了一个共享权重的解编码器分支,专门用于提供密集的正向监督信号。这一设计不仅简化了模型架构,还显著降低了参数量和推理时间,使其更适合实时应用需求。 ```python class SharedDecoderEncoder(nn.Module): def __init__(self, d_model, nhead, num_layers): super(SharedDecoderEncoder, self).__init__() decoder_layer = nn.TransformerDecoderLayer(d_model=d_model, nhead=nhead) self.decoder = nn.TransformerDecoder(decoder_layer, num_layers=num_layers) def forward(self, tgt, memory): return self.decoder(tgt=tgt, memory=memory) ``` 通过这种方式,RT-DETRv3 实现了高效的目标检测流程,在保持高精度的同时大幅缩短了推理延迟。 --- #### 4. **与其他模型的关系** 值得一提的是,RT-DETRv3 并未完全抛弃经典的 CNN 技术,而是将其与 Transformer 结合起来形成混合架构[^4]。例如,它采用了 YOLO 系列中的 RepNCSP 模块替代冗余的多尺度自注意力层,从而减少了不必要的计算负担。 此外,RT-DETRv3 还借鉴了 DETR 的一对一匹配策略,并在此基础上进行了优化,进一步提升了小目标检测的能力。 --- ### 总结 综上所述,RT-DETRv3 的网络结构主要包括以下几个关键组件:基于 CNN 的辅助分支、自注意力扰动学习策略、共享权重解编码器分支以及混合编码器设计。这些技术创新共同推动了实时目标检测领域的发展,使其在复杂场景下的表现更加出色。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值