蜗窝科技

中断和软中断不能阻塞原因?

蜗窝讨论区存档 · Linux kernel技术问答 · 楼主 Taochao · 2017-01-22 · 5 帖

本文是原「蜗窝讨论区」的历史存档(2017-01-22),来自版块「Linux kernel技术问答」,共 5 帖。讨论区已停止服务,此处仅供查阅。

Taochao · 2017-01-22 09:36

刚入门驱动不久,一直被告诉中断、软中断环境不能调用阻塞函数。 对于我的理解是阻塞会切出去,中断借用的当前线程环境,什么时候能切回来不确定。

最近在网络速率优化的时候,注意到驱动注册的发送接口,大部分情况会由net core中的软中断触发调用,而我们的发送接口不可避免的会调用一些可能阻塞的接口,这样岂不是会有问题?

linuxer · 2017-01-23 11:41

调度器是每一个OS的必备组件,在编码阶段之前,我们往往要制定下我们的设计概念。对于Linux 调度器,它的目标就是调度线程,而一个线程就是调度实体(暂不考虑group sched)。中断上下文是不是调度实体呢?当然不是,它没有专属的task struct,内核无从调度。这是调度器设计者的决定,这样的决定让调度器设计起来简洁而美丽。

基于上面的设计概念,中断上下文(hard irq和softirq context)并不参与调度(暂不考虑中断线程化),它们是异步事件的处理机制,目标就是尽快完成处理,返回现场。因此,所有中断上下文的优先级都是高于进程上下文的,也就是说,对于用户进程(无论内核态还是用户态)或者内核线程,除非disable了CPU的本地中断,否则一旦中断发生,它们是没有任何能力阻挡中断上下文抢占当前进程上下文的执行的。

因此,Linux kernel的设计者制定了规则: 1、中断上下文不是调度实体 2、中断上下文的优先级高于进程上下文 而在中断上下文中调度毫无疑问会打破规则,因此不能在硬中断、软中断环境中调用阻塞函数。

linuxer · 2017-01-23 12:06

当然,我们可以追问为何制定这样的规则?让中断上下文参与调度会引入什么样子的复杂性呢?我们可以想象一个场景:进程A通过系统调用陷入内核,进入spin lock保护的临界区,这时候,中断来了,并且你想要在中断上下文中调用调度器接口,切换到其他进程,怎么处理?spin lock保护的临界区本来设计的时候就要求一定要短,现在居然准备切换到其他进程,你让spin lock情何以堪呐。这样的例子很多,这里就不列举了。

linuxer · 2017-01-23 12:14

我看网上很多的文章都说在中断上下文调用睡眠函数会导致“找不到回来的路”,其实对于linux kernel而言,这是看运气的事情,也就是说要看被中断的上下文的情况,如果中断发生在进程的用户态时候,调用schedule函数还是有机会返回的,进程的内核栈上依次保存了“进程被中断的上下文”和“中断执行路径的上下文”,这些信息足够让进程找到”回家的路“

Taochao · 2017-01-24 21:18

多谢linuxer的解答了,我这边最近在调网络速度,驱动的发送函数被网络层调用,还被modem的线程走fastnet调用,modem的线程优先级高,发包的时候会导致我们缓冲满,丢弃了一部分,也浪费了一部分cpu,最初做实验在发送接口发送满的时候阻塞等待,这样效果还可以,速度上去了,但是发送函数就有阻塞的情况了,之前看过网络那边似乎会从softirq调用的情况,真实测试的时候也会出现这种情况,所以很纳闷这种网络核心层这种设计,不知道是不是我理解错了,驱动的发送函数不可避免有阻塞接口,因为经常有队列操作。。。

linuxer 写道: 我看网上很多的文章都说在中断上下文调用睡眠函数会导致“找不到回来的路”,其实对于linux kernel而言,这是看运气的事情,也就是说要看被中断的上下文的情况,如果中断发生在进程的用户态时候,调用schedule函数还是有机会返回的,进程的内核栈上依次保存了“进程被中断的上下文”和“中断执行路径的上下文”,这些信息足够让进程找到”回家的路“