码迷,mamicode.com
首页 > 系统相关 > 详细

结合中断上下文切换和进程上下文切换分析Linux内核的一般执行过程

时间:2020-06-13 17:30:14      阅读:59      评论:0      收藏:0      [点我收藏+]

标签:跳转   init   通过   偏移量   执行   传递   数据类型   save   int   

中断上下文的切换

进程上下文的切换

 

异常处理过程:

 

下面从逻辑上完整走一遍中断处理过程(结合中断上下文的切换,以定时器中断为例,假设从用户态进入中断):

1. 定时器连接在8259A可编程中断控制器(PIC,Programmable Interrupt Controller)的0号IRQ线上,0号IRQ线对应32+0=32号中断向量。中断控制器又与CPU的INTR引脚相连。当定时器产生中断时,中断控制器把对应的中断向量32放到一个I/O端口上,从而允许CPU通过数据总线读到这个向量。然后PIC就向CPU的中断引脚发送一个低电平,即产生一个中断。CPU对这个信号做应答,PIC收到应答后,清INTR引脚。

2. 硬件保存现场:SS、SP、eflags、cs、eip,保存到被中断进程的内核堆栈中(tr寄存器保存当前进程的tss段,而tss段里有最后一次访问内核栈的指针)。

3. 读idtr寄存器指向的中断描述符表(idt)的第30项,得到相应的中段描述符,并用中断描述符里的段选择符(还要根据gdtr寄存器指向的全局描述符表gdt获取段选择符对应的段描述符)和偏移量装载CPU的cs和eip寄存器。这样就进入到了中断处理程序的入口,CPU开始执行中断处理程序入口的代码ENTRY(interrupt)。

4. 而在系统初始化时,通过调用init_IRQ()函数用interrupt数组的每一项来初始化idt表,而interrupt数组的每一项都是一样的内容,都是interrupt。所以无论发生哪一种中断,都会跳转到一段汇编代码ENTRY(interrupt)处,这就是每一个中断处理程序的入口。它首先在内核栈上push中断向量号,然后跳转到common_interrupt处。

技术图片

5. common_interrupt首先使用SAVE_ALL继续保存现场(按照pt_regs数据结构保存),然后无论哪一个中断都会调用do_IRQ函数,这个函数就一个参数即指向pt_regs数据结构的指针,使用%eax寄存器传递。

6. do_IRQ函数使用全局数组irq_desc,irq_desc既是数组名也是数组中每个元素的数据类型。每个中断号对应一个irq_desc,irq_desc里包含irqaction链表,我们将每个设备对应的中断服务例程打包成irqaction,并通过setup_irq函数将其加入相应的irqaction链表中。handle_IRQ_event()函数负责扫描action链表,依次把action都执行一遍。 

技术图片

7. 跳转到ret_from_intr。

所以在外部看来就是:定时器发生中断了,定时器中断服务例程执行。

 

结合中断上下文切换和进程上下文切换分析Linux内核的一般执行过程

标签:跳转   init   通过   偏移量   执行   传递   数据类型   save   int   

原文地址:https://www.cnblogs.com/huangmengyu/p/13030600.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!