searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

内核硬中断处理简要分析

2023-09-11 09:34:11
9
0

中断简介

在响应一个特定中断的时候,内核会执行一个函数,称为中断处理程序(interrupt handler)或中断服务例程(interrupt service routine,ISR)。
中断上半部和下半部:
  • 上半部(top half):运行中断处理程序,需要运行快,处理重要的事务。如网卡处理不及时处理导致接收缓存溢出,其次在处理上半部的时候是关闭当前中断线,导致中断丢失;
  • 下半部(bottom half):能够被允许稍后完成的工作会推迟到下半部(bottomhalf)去。此后在合适的时机,下半部会被开中断执行。

中断服务

  1. 中断注册
中断注册需要各个设备的驱动调用request_irq()[<linux/interrupt.h>],如果flag为设置为共享,则需要驱动程序通过dev字段来进行判别,中断处理程序是不允许睡眠的。
 
request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev)
{
                   return request_threaded_irq(irq, handler, NULL, flags, name, dev);
}
 
  1. 中断执行
中断的执行首先会通过汇编语言将当前进程的相关的段寄存器和通用寄存器保存在栈中(arch\x86\entry\entry_64.S),并将当前中断相关信息压入栈,然后调用do_IRQ()[\arch\x86\kernel\irq.c]进而执行中断服务。
在硬件层面会将当前CPU的中断线,如果有中断到来,当前CPU则会进行丢弃,所以不会发生同种中断嵌套,但是中断服务程序是可以并发进行处理。中断期间是不允许进行调度,因为调度器的基本单位是进程,一旦调度出去,将无法再进行调度回来。
do_irq首先会通过preempt_count_add关闭当前进程的抢占,调用函数服务历程,退出中断,通过preempt_count_sub来开启抢占,同时检测如果不在中断上下文且有软中断需要处理,则会调用软中断。
do_IRQ()执行完毕处理完所有中断服务程序后,会执行ret_from_intr()(汇编),检查是否需要重新调度(need_resched 标志):
  • 返回用户空间:发生在内核正在返回用户空间(中断打断的是用户进程),schedule() 将被调用(就像利用定时中断执行调度,见时钟中断);
  • 返回内核空间:在支持内核抢占的内核上,发生在内核正在返回内核空间(中断打断的是内核),在preempt_count为 0 时,schedule() 会被调用;
0条评论
0 / 1000
一颗苹果
4文章数
1粉丝数
一颗苹果
4 文章 | 1 粉丝
一颗苹果
4文章数
1粉丝数
一颗苹果
4 文章 | 1 粉丝
原创

内核硬中断处理简要分析

2023-09-11 09:34:11
9
0

中断简介

在响应一个特定中断的时候,内核会执行一个函数,称为中断处理程序(interrupt handler)或中断服务例程(interrupt service routine,ISR)。
中断上半部和下半部:
  • 上半部(top half):运行中断处理程序,需要运行快,处理重要的事务。如网卡处理不及时处理导致接收缓存溢出,其次在处理上半部的时候是关闭当前中断线,导致中断丢失;
  • 下半部(bottom half):能够被允许稍后完成的工作会推迟到下半部(bottomhalf)去。此后在合适的时机,下半部会被开中断执行。

中断服务

  1. 中断注册
中断注册需要各个设备的驱动调用request_irq()[<linux/interrupt.h>],如果flag为设置为共享,则需要驱动程序通过dev字段来进行判别,中断处理程序是不允许睡眠的。
 
request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev)
{
                   return request_threaded_irq(irq, handler, NULL, flags, name, dev);
}
 
  1. 中断执行
中断的执行首先会通过汇编语言将当前进程的相关的段寄存器和通用寄存器保存在栈中(arch\x86\entry\entry_64.S),并将当前中断相关信息压入栈,然后调用do_IRQ()[\arch\x86\kernel\irq.c]进而执行中断服务。
在硬件层面会将当前CPU的中断线,如果有中断到来,当前CPU则会进行丢弃,所以不会发生同种中断嵌套,但是中断服务程序是可以并发进行处理。中断期间是不允许进行调度,因为调度器的基本单位是进程,一旦调度出去,将无法再进行调度回来。
do_irq首先会通过preempt_count_add关闭当前进程的抢占,调用函数服务历程,退出中断,通过preempt_count_sub来开启抢占,同时检测如果不在中断上下文且有软中断需要处理,则会调用软中断。
do_IRQ()执行完毕处理完所有中断服务程序后,会执行ret_from_intr()(汇编),检查是否需要重新调度(need_resched 标志):
  • 返回用户空间:发生在内核正在返回用户空间(中断打断的是用户进程),schedule() 将被调用(就像利用定时中断执行调度,见时钟中断);
  • 返回内核空间:在支持内核抢占的内核上,发生在内核正在返回内核空间(中断打断的是内核),在preempt_count为 0 时,schedule() 会被调用;
文章来自个人专栏
CTyunos
4 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
3