• 中断子系统7_中断出口处理


    //	中断公共入口
    1.1 common_interrupt:   //所有可屏蔽中断函数的公共入口  
        SAVE_ALL    //寄存器入栈  
        movl %esp,%eax  //  eax保存栈顶指针  
        call do_IRQ //中断处理函数  
        jmp ret_from_intr	//从中断返回
    
    
    //	从中断返回
    //	函数主要任务:
    //		1.确定中断发生前的运行模式
    //			1.1 恢复内核执行路径
    //				1.1.1 检查是否内核抢占,执行内核抢占
    //				1.1.2 恢复硬件上下文 
    //				1.1.3.iret
    //			1.2 恢复用户执行路径
    //				1.2.1 处理信号
    //				1.2.2 恢复硬件上下文
    //				1.2.3 iret
    2.1 ret_from_intr:
    	GET_THREAD_INFO(%ebp)	//当前进程threadinfo的指针存入寄存器EBX中
    	movl EFLAGS(%esp), %eax		
    	movb CS(%esp), %al 		
    	testl $(VM_MASK | 3), %eax 	//cs,eflags确定中断发生前的运行模式:1.VM86,用户空间,2.内核空间
    	jz resume_kernel		
    ENTRY(resume_userspace)		//恢复用户空间
     	cli		//关本cpu中断,防止中断退出时被打断
    	movl TI_flags(%ebp), %ecx	//threadinfo->flags
    	andl $_TIF_WORK_MASK, %ecx	//处理挂起的信号
    	jne work_pending
    	jmp restore_all	//恢复硬件上下文
    
    ENTRY(resume_kernel)	//恢复内核空间
    	cli	//关本cpu中断,防止中断退出时被打断
    	cmpl $0,TI_preempt_count(%ebp)	//内核抢占计数器
    	jnz restore_all 				//内核抢占计数!=0,不可以发生内核抢占,恢复之前的内核执行路径
    need_resched:						//否则,检查当前进程是否设置need_resched标志
    	movl TI_flags(%ebp), %ecx		
    	testb $_TIF_NEED_RESCHED, %cl 	//没有设置TIF_NEED_RESCHED标志
    	jz restore_all 					//恢复程序执行
    	testl $IF_MASK,EFLAGS(%esp)     
    	jz restore_all
    	call preempt_schedule_irq	//内核抢占
    	jmp need_resched 			//重调度
    
    //	恢复中断发生前程序状态
    //		注:iret中断服务程序的最后一条指令。IRET指令将推入堆栈的段地址和偏移地址弹出,
    //			使程序返回到原来发生中断的地方。其作用是从中断中恢复中断前的状态,具体作用有如下三点:
    //			1.恢复IP(instruction pointer):(IP)←((SP)+1:(SP)),(SP)←(SP)+2
    //			2.恢复CS(code segment):(CS)←((SP))+1:(SP)),(SP)←(SP)+2
    //			3.恢复中断前的PSW(program status word),即恢复中断前的标志寄存器的状态。
    //			(FR)←((SP)+1:(SP)),(SP)←(SP)+2
    2.2 #define RESTORE_ALL	
    	RESTORE_REGS	
    	addl $4, %esp;	
    1:	iret;		
    
    //ret_from_intr 流程:

                                                   

    //	内核抢占入口
    //	函数主要任务:
    //		1.设置preempt_active,表示当前进程正在发生内核抢占
    //			1.1 防止递归调用preempt_schedule_irq
    //		2.开中断
    //		3.调度
    //		4.进程再次恢复执行,关中断,清除preempt_active,表示内核抢占完成
    //		5.检查是否再次需要内核抢占
    2.3 asmlinkage void __sched preempt_schedule_irq(void)
    {
    	struct thread_info *ti = current_thread_info();
    
    need_resched:
    	//设置preempt_active,表示正在发生内核抢占
    	add_preempt_count(PREEMPT_ACTIVE);
    	//在进入preempt_schedule_irq之前中断被关闭,此处开中断
    	local_irq_enable();
    	//调度
    	schedule();
    	//此进程恢复执行,关闭中断
    	local_irq_disable();
    	//清除preempt_active,表示内核抢占完成
    	sub_preempt_count(PREEMPT_ACTIVE);
    	//检查是否需要内核抢占
    	barrier();
    	if (unlikely(test_thread_flag(TIF_NEED_RESCHED)))
    		goto need_resched;
    }
    
    
    //	处理挂起的信号
    //	函数主要任务:
    //		1.检查是否需要重调度
    //			1.1 调度
    //			1.2 恢复执行后,检查信号是否已经被处理
    //				1.2.1 如果已经被处理,恢复进程路径
    //				1.2.2 重复路径1
    //		2.执行信号处理函数
    //		3.恢复硬件上下文
    2.4 work_pending:
    	testb $_TIF_NEED_RESCHED, %cl 	//检查是否需要重调度
    	jz work_notifysig 				//	先执行进程调度
    work_resched:
    	call schedule
    	cli				//关中断
    	movl TI_flags(%ebp), %ecx
    	andl $_TIF_WORK_MASK, %ecx	//恢复进程执行后,检查信号是否已经被处理
    	jz restore_all 					//如果信号已经被处理,则直接恢复进程硬件上下文
    	testb $_TIF_NEED_RESCHED, %cl 	//检查是否需进程调度
    	jnz work_resched
    
    work_notifysig:	//处理挂起的信号			
    	testl $VM_MASK, EFLAGS(%esp)
    	movl %esp, %eax 	//检查是否在vm86模式
    	jne work_notifysig_v86		
    	xorl %edx, %edx
    	call do_notify_resume	//执行信号处理函数
    	jmp restore_all
    //中断嵌套

                                                             

    // 参考 深入理解linux内核
    //  关于x86平台下中断嵌套的讨论
    //      http://blog.focus-linux.net/?p=50















  • 相关阅读:
    webapi支持session
    webapi返回数据同时支持xml与json
    webapi权限控制
    Asp.net 将js文件打包进dll 方法
    All Media to FLV asp.net在线视频自动转换并截图调试成功!
    未能从程序集“System.ServiceModel
    [javascript]浮动广告
    [python]multi thread tcp connect port scanner
    [vc]让你Y的用YY
    [python]扫描网站后台脚本
  • 原文地址:https://www.cnblogs.com/fuhaots2009/p/3429210.html
Copyright © 2020-2023  润新知