Linux内核的一些知识。

1、中断处理函数里面为什么不能够进行sleep,信号量操作

中断处理函数里面不能够进行sleep有比较多的原因,有以下几个方面:

  • 临界区肯定是不能进行sleep的,这样子会导致系统瘫痪。
  • 中断上下文没有相应的task_struct,因为 linux进程内核调度是以task_struct为单位的,所以如果进行sleep的话将无法进行恢复。但这个不是主要原因,因为 solaris的中断上下文有相应的调度描述符IST。(所以这里来料了,之前有同事说tcp三次握手完成的时候,这个连接属于哪个pid,在Linux上表现为空,此时不知道谁持有这个连接,可能是因为 没有上下文,但如果在solaris这样的环境可能就属于中断调试 IST的了)
  • 为了简单可控,如果允许中断处理函数中进行sleep的话,可能当前调度优先级比较低的话,那么它很难被恢复过来,另外,栈空间溢出也是个问题,因为目前中断栈只有4k。
  • 内核设计原因:内核设计的诸多因素使得这个无法实现,比如目前的中断线是每个CPU一个,a  sleep ->schedule b -> b sleep -> a(i don't know where my stack is)

 

tasklet应用于异常后半部分的处理,优先级比前半部分要低,它在一些检查点被触发调用,通常tasklet也在中断上下文中被处理,所以和中断处理程序一样,不能sleep也不能去调度,不能使用信号量。

a.若在中断中schedule tasklet, 中断结束后立即运行;
b.若CPU忙,在不在此次中断后立即运行;
c.不在中断中shedule tasklet;
d.有软或硬中断在运行;
e.从系统调用中返回;(仅当process闲时)
f.从异常中返回;
g.调度程序调度。(ksoftirqd运行时,此时CPU闲)

 

tasklet一般通过wake_up函数来唤醒等待队列里面的进程,每个驱动都可以自定义一个等待队列DECLARE_WAITQUEUE,进程一般在写设备的时候调用 wait_event_xxx的方式陷入等待。

 

硬中断触发时,CPU会将中断判断,此时CPU处于临界区。CPU退出临界区后可以开中断

 

我们可以使用vmstat 来查看压力情况下的内存情况,cpu在系统/用户态的耗时,进程/任务切换的次数等,vmstat 是个好工具。

但用vmstat的时候,发现 中断次数比进程/任务切换的次数还要多,于是怀疑软件中断是不是不计入中断计数的。于是去查阅linux/arch/arm/kernel下的熟悉的entry-armv.s,发现软件中断的向量跟irq的不一样,处理函数也不一样,do_IRQ是会进行计数的,而arm_syscall不会进行计数,因此vmstat上面显示的进程/任务切换的次数比中断次数还要多。

从内核态到用户态时,需要切换页表目录,寄器,以及权限寄存器CPSR。

多核心的CPU中,每个核心应该都要有自己的TLB,这样子MMU在进行翻译的时候才不会混淆,当然,多核心cpu在进行进程切换的时候情况可能更加复杂一点,还涉及到cache相关的问题,比如cache是以VA(虚拟地址)还是PA(物理地址)作为索引的。目前CPU核心看到的地址都是虚拟地址,而Cache,MMU,DMA等设备看到的都是物理地址。

 

posted on 2017-08-03 00:42  mosmith  阅读(283)  评论(0编辑  收藏  举报