前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >结合中断上下文切换和进程上下文切换分析Linux内核的一般执行过程

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

原创
作者头像
抖音hzcya
修改2020-06-15 10:43:48
1.3K0
修改2020-06-15 10:43:48
举报
文章被收录于专栏:用户3103921的专栏

中断上下文的切换

进程上下文的切换

异常处理过程:

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

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链表,依次执行,直到找到对应设备的中断服务例程,然后执行。

7. 跳转到ret_from_intr。

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档