跟着简叔学的,可以B站搜索 简说linux
1.上下文
1.1中断的种类如上下文判断方式
中断可分为软件中断和硬件中断。或者BH ,这个BH是什么东西去查了查,说是软中断的实现方式,已经被弃用了。
之前讲过内核中的进程描述方式struct task_struct 中有一个thread_info,他之中保留着不同架构的对于进程的描述信息。其中有一个属性是下面这个。 32bit的变量
红色部分描述当前硬中断嵌套的深度,0的话就是不是中断,不允许中断嵌套执行的话就只有0,1两种。
绿色部分第8位是软中断,1的话就是软中断的处理上下文,9~15大于0也表示软中断。蓝色部分表示当前进程是否可以被抢占如果是0就是可以被抢占反之就是不能被抢占。
include/linux/preempt.h
通过这些函数来确定出狱生么上下问之中,可以看到都是在用上面说的preemtycount做位运算。通过current->threadinfo得到threadinfo 然后就能得到preemtycount ,这样就能直到当前处于什么上下文
1.2 调用上面函数的案例
arm中 handle_irq是处理中断的总入口,arch/arm/kernel/irq.c
/kernel/irq/irqdesc.c。
1 |
|
上面 中断陷入中断退出之间就是中断上下文。
1 | /* |
2.中断上下文进入时机
2.1硬件中断进入时机
当外设产生中断,会给cpu发送中断信号,cpu收到中断信号之后会调用(以arm为例,arch/arm/kernel/irq.c)
然后又回到上部分的代码
1 | /* |
可以看到__irq_enter()
有一个操作是对preempt_count
的操作,相当于把 preempt_count
代表硬中断的位置为真,从此开始就进入了硬件中断的上下文。之前那些判断上下文的函数返回值就会显示是硬件中断。与irq_enter相反的操作irq_exit也是将硬件中断的位置为0;
2.2软件中断进入时机
可以看到软中断这块有两个范围,一个是比特8,一个是比特9~15。当我们调用 BHdisable这种函数,9-15就会被置1,还有就是正常处理软中断 比特8会置为1.
在/kernel/softirq.c中,
1 | asmlinkage __visible void __softirq_entry __do_softirq(void) |
轮询所有软中断,如果某个软中断有需要处理的数据,就会调用相应的软中断的handle。处理软中断前后会调用_local_bh_disable_ip(_RET_IP_, SOFTIRQ_OFFSET);
和__local_bh_enable(SOFTIRQ_OFFSET);
这两个函数的作用是会操作preemty_cnt,点进去查看会发现他操作的位是,比特8.可以说这两个函数可以对应硬中断的__irq_enter()
与 __irq_exit()
。所以,在这两条函数中间,调用那些处理软函数中,是在软中断上下文环境中,这个环境中是不允许休眠和调度的。